fix(B06): 폼의 높이·길이·전/후가 횡단도를 따라오게 하고 기본값을 조정창과 맞춘다
2026-08-29 사용자 지적 2건: ① 폼에서 높이·길이·기준측점 전/후를 고쳐도 도면이 그대로였다 — 조정창 조작값 (revet_adjust.h·m)이 폼 값보다 우선이라 그림이 옛 값을 유지했다. 폼이 높이· 형태를 정하면 그 벽의 조정값을 비워 폼 값이 이기게 했다. ② 폼 기본값은 예전 조정창이 보여주던 값이 기준이다 — 관 옵션이 비어 있으면 횡단 스펙(culvert 스펙: 형태·높이·길이·전/후·집수정 구간값·관종·관경)에서 채워 폼과 조정창이 같은 원천을 보게 했다. 저장된 옵션이 있으면 그쪽이 이긴다.
This commit is contained in:
@@ -137,6 +137,7 @@ export async function renderB06ProfileCross(root: HTMLElement): Promise<void> {
|
||||
// 하단 고정 dock 도 B05와 같은 구조: [구조물 목록][구분선][액션 버튼 행].
|
||||
const structuresPanel = createB06StructuresPanel({
|
||||
projectId,
|
||||
detail: () => sectionDetail,
|
||||
stationInterval: () => stationInterval ?? 20,
|
||||
focusChainage: focusStationAt,
|
||||
queuePipeOptions: (chainageM, patch) => stationControls.queueCulvertOptions(chainageM, patch),
|
||||
@@ -182,6 +183,20 @@ export async function renderB06ProfileCross(root: HTMLElement): Promise<void> {
|
||||
put(side, "revet_after_m", num(`${prefix}_revet_after_m`));
|
||||
put(side, "structure", patch[`${prefix}_type`]);
|
||||
}
|
||||
// 폼이 높이·형태를 정하면 그 벽의 **조정값**(revet_adjust.h·m)은 비운다 —
|
||||
// 조정값이 남아 있으면 그림이 폼 값을 따라오지 않는다(2026-08-29 사용자 보고).
|
||||
for (const [role, prefix] of [
|
||||
["inlet", "inlet"],
|
||||
["outlet", "outlet"],
|
||||
] as const) {
|
||||
const patchHeight = patch[`${prefix}_revet_height_m`] !== undefined;
|
||||
const patchForm = patch[`${prefix}_revet_form`] !== undefined;
|
||||
if (!patchHeight && !patchForm) continue;
|
||||
stationControls.revetOffset.update(owner.chainage_m, role, {
|
||||
...(patchHeight ? { h: null } : {}),
|
||||
...(patchForm ? { m: null } : {}),
|
||||
});
|
||||
}
|
||||
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"));
|
||||
|
||||
@@ -35,6 +35,9 @@ const PIPE_MOVE_NOTICE =
|
||||
|
||||
export interface B06StructuresPanelDeps {
|
||||
projectId: string | null;
|
||||
/** 횡단 캐시 — 폼 기본값을 조정창과 **같은 원천**(culvert 스펙)에서 읽는다
|
||||
* (2026-08-29 사용자: 예전 조정창이 보여주던 값이 기본값이다). */
|
||||
detail?: () => SectionDetailResponse | null;
|
||||
/** 측점 간격(m) — 측점번호+잔여거리 환산용. */
|
||||
stationInterval: () => number;
|
||||
/** 목록·폼에서 고른 시설의 측점 카드를 선택·스크롤한다. */
|
||||
@@ -82,6 +85,44 @@ function coversChainage(structure: StructureInstance, chainageM: number): boolea
|
||||
return Math.abs(structureAnchorM(structure) - chainageM) < PIPE_MATCH_M;
|
||||
}
|
||||
|
||||
/**
|
||||
* 관 지점 옵션에 **횡단 스펙 값**을 채워 넣는다 — 조정창이 보여주던 값과 폼이
|
||||
* 어긋나지 않게 한다(2026-08-29 사용자). 옵션에 이미 값이 있으면 그대로 두고,
|
||||
* 비어 있을 때만 스펙(서버 계산·저장분)에서 가져온다.
|
||||
*/
|
||||
function withSpecDefaults(
|
||||
options: Record<string, string | number> | undefined,
|
||||
detail: SectionDetailResponse | null,
|
||||
chainageM: number,
|
||||
): Record<string, string | number> | undefined {
|
||||
const owner = detail?.cross_sections.find(
|
||||
(section) => Math.abs(section.chainage_m - chainageM) < PIPE_MATCH_M,
|
||||
);
|
||||
const culvert = owner?.culvert;
|
||||
if (!culvert) return options;
|
||||
const merged: Record<string, string | number> = { ...(options ?? {}) };
|
||||
const put = (key: string, value: string | number | null | undefined): void => {
|
||||
if (merged[key] === undefined && value !== null && value !== undefined) merged[key] = value;
|
||||
};
|
||||
put("pipe_kind", culvert.pipe_kind);
|
||||
put("pipe_diameter_mm", Math.round(culvert.diameter_m * 1000));
|
||||
for (const [side, prefix] of [
|
||||
[culvert.inlet, "inlet"],
|
||||
[culvert.outlet, "outlet"],
|
||||
] as const) {
|
||||
put(`${prefix}_type`, side.structure);
|
||||
put(`${prefix}_revet_form`, side.revet_form);
|
||||
put(`${prefix}_revet_height_m`, side.revet_height_m);
|
||||
put(`${prefix}_revet_length_m`, side.revet_length_m);
|
||||
put(`${prefix}_revet_before_m`, side.revet_before_m);
|
||||
put(`${prefix}_revet_after_m`, side.revet_after_m);
|
||||
}
|
||||
put("inlet_basin_length_m", culvert.inlet.basin_length_m);
|
||||
put("inlet_basin_before_m", culvert.inlet.basin_before_m);
|
||||
put("inlet_basin_after_m", culvert.inlet.basin_after_m);
|
||||
return merged;
|
||||
}
|
||||
|
||||
export function createB06StructuresPanel(deps: B06StructuresPanelDeps): B06StructuresPanel {
|
||||
let structures: StructureInstance[] = [];
|
||||
let pipeFacilities: PipeFacilityItem[] = [];
|
||||
@@ -169,13 +210,15 @@ export function createB06StructuresPanel(deps: B06StructuresPanelDeps): B06Struc
|
||||
// 저장하지 않고 나갔던 조작분이 있으면 그것으로 화면을 세운다(B05와 같은 규칙).
|
||||
structures = readPendingStructures(projectId) ?? stored.structures;
|
||||
section.setStructures(structures);
|
||||
const detail = deps.detail?.() ?? null;
|
||||
pipeFacilities = pipeResponse.pipe_points.map((pipe) => ({
|
||||
chainage_m: pipe.chainage_m,
|
||||
facility: pipe.facility ?? "pipe",
|
||||
start_m: pipe.start_m,
|
||||
end_m: pipe.end_m,
|
||||
source: pipe.source,
|
||||
options: pipe.options,
|
||||
// 폼 기본값 = 조정창이 쓰던 값(횡단 스펙). 저장된 옵션이 있으면 그쪽이 이긴다.
|
||||
options: withSpecDefaults(pipe.options, detail, pipe.chainage_m),
|
||||
design_flow_m3s: null,
|
||||
}));
|
||||
section.setPipeFacilities(pipeFacilities);
|
||||
@@ -187,6 +230,16 @@ export function createB06StructuresPanel(deps: B06StructuresPanelDeps): B06Struc
|
||||
}
|
||||
}
|
||||
|
||||
/** 폼에 올리기 직전에 그 관의 옵션을 최신 스펙으로 보강한다(빈 칸만 채운다). */
|
||||
function refreshSpecDefaults(chainageM: number): void {
|
||||
const hit = pipeFacilities.find(
|
||||
(entry) => Math.abs(entry.chainage_m - chainageM) < PIPE_MATCH_M,
|
||||
);
|
||||
if (!hit) return;
|
||||
hit.options = withSpecDefaults(hit.options, deps.detail?.() ?? null, hit.chainage_m);
|
||||
section.setPipeFacilities(pipeFacilities);
|
||||
}
|
||||
|
||||
return {
|
||||
root: section.root,
|
||||
listRoot: section.listRoot,
|
||||
@@ -198,6 +251,7 @@ export function createB06StructuresPanel(deps: B06StructuresPanelDeps): B06Struc
|
||||
},
|
||||
showPipeAt: (chainageM) => {
|
||||
currentChainageM = chainageM;
|
||||
if (chainageM !== null) refreshSpecDefaults(chainageM);
|
||||
section.selectPipeByChainage(chainageM);
|
||||
},
|
||||
showAtChainage: (chainageM) => {
|
||||
@@ -213,6 +267,7 @@ export function createB06StructuresPanel(deps: B06StructuresPanelDeps): B06Struc
|
||||
);
|
||||
if (pipe) {
|
||||
currentChainageM = pipe.chainage_m;
|
||||
refreshSpecDefaults(pipe.chainage_m);
|
||||
section.selectPipeByChainage(pipe.chainage_m);
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user