fix(b06): 횡단도 구조물 고르기 → 좌측 패널 연결 점검 · 고침(53-1)

- 다른 측점 부재를 누를 때 옛 카드 선택 풀기가 폼 · 선택 칸을 비우던 것 막음(첫 누름부터 잡힘)
- 컨테이너 상자 강조가 폼 다시 그리기에 지워지던 것 · 옛 상자 강조 남던 것 · 유입 · 유출도 보이게 스크롤
- 고른 구조물 기준 측점 고침 = 바로 반영 · 횡단 카드 · 알약 · 선택 칸이 따라감
- 부재키는 같은 것을 다시 적을 때만 지킴 · 풀면 지움(B05 ↔ B06 오갈 때 옛 조정창 안 열림)
- 카드 고름이 일반 측점 · 이음 카드 알약을 지우던 것 → 연 구조물 알약 지킴
- B05 되살리기 = 구조물 id 가 같은 측점 관보다 먼저 · B06 다시 들어올 때 넘김값 다시 적용
- 시험: ui_checks/53-1_횡단_고르기.js(점검 116 · 흠 0) · 선택 시험 새 규칙으로

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W4uKaV4ZBhsJN4GHG7yRj4
This commit is contained in:
2026-10-06 10:20:37 +09:00
co-authored by Claude Opus 5.5
parent 9c20c08327
commit 26c2e8b05f
11 changed files with 728 additions and 20 deletions
@@ -38,8 +38,10 @@ import {
} from "../common_util/common_util_summary_item";
import { readStructurePick } from "../B05_Profile/B05_Profile_UI_Structure_Pick_Session";
import {
coversChainage,
NO_SELECTION,
PIPE_MATCH_M,
readSelection,
resolveSelection,
selectDesign,
type DesignSelection,
@@ -170,6 +172,23 @@ export function createB06StructuresPanel(deps: B06StructuresPanelDeps): B06Struc
pushMarks();
if (deps.projectId) writePendingStructures(deps.projectId, structures);
deps.onStructuresChanged?.();
// 고른 구조물을 다른 측점으로 옮기면 횡단 카드도 따라감(53-1)
const picked = readSelection(deps.projectId);
const moved = picked?.structureId
? structures.find((entry) => entry.structure_id === picked.structureId)
: undefined;
if (moved && picked?.chainageM != null && !coversChainage(moved, picked.chainageM)) {
const id = moved.structure_id ?? null;
preferredId = id;
deps.focusChainage(structureAnchorM(moved));
preferredId = null;
deps.markStructure?.(id); // 카드 고름이 옛 자리로 알약을 풀었으면 다시 세움
selectDesign(
deps.projectId,
{ chainageM: structureAnchorM(moved), structureId: id },
{ from: "b06" },
);
}
},
onSelect: (structure) => {
if (!structure) return;
@@ -552,11 +571,17 @@ export function wireStructureSelection(
const origRevet = stationControls.revetOffset.select;
stationControls.revetOffset.select = (chainageM, key) => {
markWallSelecting();
// 다른 카드 부재를 고르는 중에 옛 카드가 제 선택을 푸는 것 — 폼 · 선택 칸은 새 것 몫(53-1)
const nested = wallSelecting;
// 푸는 것은 고름이 아님 — 표시를 켜면 뒤이은 카드 고름이 선택 칸에 안 적힘(53-1)
if (key) markWallSelecting();
origRevet(chainageM, key);
if (key) remember?.(ownerChainageOf(chainageM), key);
if (key) panel.showAtChainage(ownerChainageOf(chainageM));
else panel.releasePipe();
else if (!nested) {
remember?.(ownerChainageOf(chainageM), ""); // 푼 부재가 B05 ↔ B06 오갈 때 다시 안 열림
panel.releasePipe();
}
if (key) syncInletStructure();
// 폼이 이 시설로 갈아 끼워진 뒤에 이식을 다시 돌린다 — 목적지 칸이 그제야 선다.
refreshAdjustSlots();
@@ -564,22 +589,30 @@ export function wireStructureSelection(
const origFord = stationControls.ford.select;
stationControls.ford.select = (chainageM, role) => {
markWallSelecting();
const nested = wallSelecting;
if (role) markWallSelecting();
origFord(chainageM, role);
if (role) remember?.(chainageM, role);
if (role) panel.showAtChainage(chainageM);
else panel.releasePipe();
else if (!nested) {
remember?.(chainageM, "");
panel.releasePipe();
}
// 폼이 이 시설로 갈아 끼워진 뒤에 이식을 다시 돌린다 — 날개벽 칸이 그제야 선다
// (배관 기슭막이와 같은 순서, 2026-08-30 사용자 지시 1).
refreshAdjustSlots();
};
const origBox = stationControls.box.select;
stationControls.box.select = (chainageM, role) => {
markWallSelecting();
const nested = wallSelecting;
if (role) markWallSelecting();
origBox(chainageM, role);
if (role) remember?.(chainageM, role);
if (role) panel.showAtChainage(chainageM);
else panel.releasePipe();
else if (!nested) {
remember?.(chainageM, "");
panel.releasePipe();
}
// 폼이 이 시설로 갈아 끼워진 뒤에 이식을 다시 돌린다 — 날개벽 칸이 그제야 선다.
refreshAdjustSlots();
};