feat(B06): 기준 측점 이동을 B06 구조물 배치에서도 한다

2026-08-29 사용자: 구조물 배치 컨테이너를 B06으로 가져온 이유가 이것이다 —
폼의 기준 측점 숫자를 바꾸면 관이 옮겨져야 한다.

- 관 저장기에 이동 예약(queueMove)을 더했다. 세션 키 b06:culvertmove에 담고,
  [저장]·[확정]의 flush가 옵션 병합과 함께 pipe_points에 반영한다. 세부 배수유역
  재분할은 서버가 관 목록을 다시 받아 처리한다.
- 폼에서 측점을 옮기면 목록·폼 캐시가 즉시 새 자리를 따르고, 옵션은 옮기기 전
  자리로 예약한다(저장 시점 관 목록이 그 자리 기준).
- 이동 안내는 차단 문구에서 '저장 뒤 다시 계산' 알림으로 바꿨다.
This commit is contained in:
2026-08-29 16:53:17 +09:00
parent effd5e59d3
commit 45c6f9aa07
4 changed files with 72 additions and 8 deletions
@@ -30,6 +30,8 @@ import type { StationControls } from "./B06_Section_UI_Page_Station_Controls";
const PIPE_ADD_GUIDE = "계곡 통과 시설의 추가·삭제는 B05(종단) 화면에서 합니다.";
const PIPE_MOVE_GUIDE = "기준 측점 이동은 배수유역을 다시 나눠야 해 B05(종단) 화면에서 합니다.";
const PIPE_MOVE_NOTICE =
"기준 측점을 옮겼습니다 — 세부 배수유역과 횡단도는 [저장]·[확정] 뒤에 다시 계산됩니다.";
export interface B06StructuresPanelDeps {
projectId: string | null;
@@ -43,6 +45,9 @@ export interface B06StructuresPanelDeps {
/** 바뀐 값을 그 측점 횡단 캐시(culvert 스펙)에 얹고 카드를 다시 그린다 —
* 조정창과 같은 흐름이라 폼 조작도 도면에 바로 보인다(2026-08-29 사용자 보고). */
applyPipeOptions?: (chainageM: number, patch: Record<string, number | string>) => void;
/** 기준 측점 이동을 예약한다 — 세부 배수유역 재분할은 [저장]·[확정] 때 서버가
* 관 목록을 다시 받아 처리한다(2026-08-29 사용자: B06에서도 옮길 수 있어야 한다). */
movePipe?: (fromChainageM: number, toChainageM: number) => void;
}
export interface B06StructuresPanel {
@@ -108,14 +113,27 @@ export function createB06StructuresPanel(deps: B06StructuresPanelDeps): B06Struc
// 0.1m로 반올림되므로 0.005m 기준으로 보면 값만 고쳐도 이동으로 잡힌다
// (2026-08-29 사용자 보고: 높이만 바꿨는데 이동 안내가 떴다).
const moved = Math.abs(fromChainageM - toChainageM) > PIPE_MATCH_M;
// 이동이라도 함께 온 제원은 반영한다 — 위치만 못 옮길 뿐 같은 데이터다.
if (moved) showToast(PIPE_MOVE_GUIDE, "error");
if (moved) {
if (deps.movePipe) {
deps.movePipe(fromChainageM, toChainageM);
const hit = pipeFacilities.find(
(entry) => Math.abs(entry.chainage_m - fromChainageM) < PIPE_MATCH_M,
);
if (hit) hit.chainage_m = toChainageM;
currentChainageM = toChainageM;
section.setPipeFacilities(pipeFacilities);
showToast(PIPE_MOVE_NOTICE, "success");
} else {
showToast(PIPE_MOVE_GUIDE, "error");
}
}
const patch = attributes.options;
if (!patch || !Object.keys(patch).length) return;
if (!deps.queuePipeOptions) {
showToast(PIPE_ADD_GUIDE, "error");
return;
}
// 옵션은 **옮기기 전 자리**로 예약한다 — 저장 시점의 관 목록이 그 자리 기준이다.
deps.queuePipeOptions(fromChainageM, patch as Record<string, number | string>);
deps.applyPipeOptions?.(fromChainageM, patch as Record<string, number | string>);
// 화면 캐시(목록·폼 재로드용)도 같이 맞춘다 — 저장 전에도 값이 유지된다.