fix(B06): 폼에서 바꾼 관 제원이 횡단도에 바로 반영되게 한다

원인: 좌측 폼의 실시간 반영이 세션 예약(culvertopt)과 목록 캐시까지만 갱신하고,
횡단 캐시(section.culvert 스펙)를 건드리지 않아 카드가 옛 값으로 남았다.

- 폼 옵션 키를 culvert 스펙 자리로 옮기는 applyPipeOptionsToCache 추가
  (관종·관경, 유입·유출 기슭막이 형태·높이·길이·전/후, 집수정 구간값, 구조).
- 연장이 덮는 범위의 카드만 다시 그린다 — 조정창 조작과 같은 흐름.
- 화면 캐시만 고친다. 영구저장은 [저장]·[확정] 그대로.
This commit is contained in:
2026-08-29 16:45:52 +09:00
parent c641fa98b2
commit 936def3755
2 changed files with 61 additions and 0 deletions
+57
View File
@@ -140,7 +140,64 @@ export async function renderB06ProfileCross(root: HTMLElement): Promise<void> {
stationInterval: () => stationInterval ?? 20,
focusChainage: focusStationAt,
queuePipeOptions: (chainageM, patch) => stationControls.queueCulvertOptions(chainageM, patch),
applyPipeOptions: (chainageM, patch) => applyPipeOptionsToCache(chainageM, patch),
});
/**
* 폼에서 바꾼 관 옵션을 **횡단 캐시**(`section.culvert` 스펙)에 얹고, 그 구조물이
* 덮는 측점 카드를 다시 그린다 — 조정창 조작과 같은 흐름이라 도면이 바로 따라온다
* (2026-08-29 사용자 보고: 값만 바뀌고 횡단도가 그대로였다).
* 여기서는 화면 캐시만 고친다 — 영구저장은 [저장]·[확정] 몫이다.
*/
function applyPipeOptionsToCache(
chainageM: number,
patch: Record<string, number | string>,
): void {
const owner = sectionDetail?.cross_sections.find(
(section) => Math.abs(section.chainage_m - chainageM) < 0.51,
);
const culvert = owner?.culvert;
if (!owner || !culvert) return;
const num = (key: string): number | undefined => {
const value = Number(patch[key]);
return Number.isFinite(value) ? value : undefined;
};
const put = <T extends object>(target: T, field: keyof T, value: unknown): void => {
if (value !== undefined) (target as Record<string, unknown>)[field as string] = value;
};
put(culvert, "pipe_kind", patch.pipe_kind);
const diameterMm = num("pipe_diameter_mm");
if (diameterMm !== undefined) culvert.diameter_m = diameterMm / 1000;
// 유입·유출 기슭막이 제원과 집수정 구간값 — 폼 옵션 키를 스펙 자리로 옮긴다.
for (const [side, prefix] of [
[culvert.inlet, "inlet"],
[culvert.outlet, "outlet"],
] as const) {
put(side, "revet_form", patch[`${prefix}_revet_form`]);
put(side, "revet_height_m", num(`${prefix}_revet_height_m`));
put(side, "revet_length_m", num(`${prefix}_revet_length_m`));
put(side, "revet_before_m", num(`${prefix}_revet_before_m`));
put(side, "revet_after_m", num(`${prefix}_revet_after_m`));
put(side, "structure", patch[`${prefix}_type`]);
}
put(culvert.inlet, "basin_length_m", num("inlet_basin_length_m"));
put(culvert.inlet, "basin_before_m", num("inlet_basin_before_m"));
put(culvert.inlet, "basin_after_m", num("inlet_basin_after_m"));
// 연장이 바뀌면 옆 측점 링크도 달라진다 — 그 구조물이 덮는 범위만 다시 그린다.
const reach = Math.max(
culvert.inlet.revet_before_m ?? 0,
culvert.inlet.revet_after_m ?? 0,
culvert.outlet.revet_before_m ?? 0,
culvert.outlet.revet_after_m ?? 0,
num("inlet_revet_length_m") ?? 0,
num("outlet_revet_length_m") ?? 0,
);
for (const other of sectionDetail?.cross_sections ?? []) {
if (Math.abs(other.chainage_m - owner.chainage_m) <= reach + 1e-9) {
sectionView.refreshCard(other.chainage_m);
}
}
}
const dockDivider = document.createElement("hr");
dockDivider.className = "b05-structure__divider";
const actionDock = document.createElement("div");
@@ -40,6 +40,9 @@ export interface B06StructuresPanelDeps {
/** 폼 [수정]으로 바뀐 관 옵션을 캐시에 예약한다 — [저장]·[확정]이 정본에 쓴다
* (2026-08-29: 조정창 구간값과 같은 경로). 없으면 안내만 한다. */
queuePipeOptions?: (chainageM: number, patch: Record<string, number | string>) => void;
/** 바뀐 값을 그 측점 횡단 캐시(culvert 스펙)에 얹고 카드를 다시 그린다 —
* 조정창과 같은 흐름이라 폼 조작도 도면에 바로 보인다(2026-08-29 사용자 보고). */
applyPipeOptions?: (chainageM: number, patch: Record<string, number | string>) => void;
}
export interface B06StructuresPanel {
@@ -112,6 +115,7 @@ export function createB06StructuresPanel(deps: B06StructuresPanelDeps): B06Struc
return;
}
deps.queuePipeOptions(fromChainageM, patch as Record<string, number | string>);
deps.applyPipeOptions?.(fromChainageM, patch as Record<string, number | string>);
// 화면 캐시(목록·폼 재로드용)도 같이 맞춘다 — 저장 전에도 값이 유지된다.
const hit = pipeFacilities.find(
(entry) => Math.abs(entry.chainage_m - fromChainageM) < PIPE_MATCH_M,