fix(B06·B05): 노면공 고름 세 갈래 · 형상 누름 = 목록 고름 · 카드 하나 = 그 측점(189-1)

- ② 카드 안 노면공 포장층 누름 = 목록 고름과 같은 길(범위 카드 전부 · 포장층 강조) — 카드 고름보다 먼저 가로챔
- ③ 카드 하나 누름 = 연 노면공 · 범위 강조 풂 · 그 카드 하나(165-1 노면공 지킴 · 167-3 재누름 그대로 없앰)
- 카드 고름 세션 = 그 측점(구조물 id 는 목록 · 알약 · 넘김이 고른 것만)
- 종단: 구조물 넘김이면 측점선 · 3D 띠 안 켬
- 새 시험 test_189_1_pave_pick · test_165 · test_188_1 기대값 41번 규칙으로

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01STqEqztUthVFBmEP18wBSz
This commit is contained in:
2026-10-10 13:21:23 +09:00
co-authored by Claude Opus 5.5
parent e744da8af1
commit 9e69bec512
12 changed files with 301 additions and 72 deletions
+17 -11
View File
@@ -68,7 +68,7 @@ import {
} from "./B06_Section_UI_Section_Common";
import type { SectionViewController } from "./B06_Section_UI_Section_View_Types";
import { createFillSlopeNotice } from "./B06_Section_UI_Cross_FillSlope_Notice";
import { highlightPavement } from "./B06_Section_UI_Cross_Design_Surface";
import { highlightPavement, pavementAt } from "./B06_Section_UI_Cross_Design_Surface";
import { createSectionProfile } from "./B06_Section_UI_Section_View_Profile";
import type { DesignPageShared } from "../A00_Common/design/design_shared";
@@ -270,6 +270,8 @@ export function createSectionView(
/** 카드 선택 변경 수신자(좌측 구조물 폼). 페이지가 등록한다. */
let stationSelectListener: ((stationId: string | null) => void) | null = null;
/** 카드 안 노면공 형상 누름 수신자 — 목록 고름과 같은 길(189-1). */
let pavementSelectListener: ((structureId: string) => void) | null = null;
/**
* 선택이 바뀐 흔적만 화면에 반영한다 — **재렌더 금지**.
@@ -288,16 +290,6 @@ export function createSectionView(
/** 같은 측점을 다시 고르면 선택을 푼다(2026-08-02 사용자 지시) — 카드·측점선 어느 쪽이든. */
const selectStation = (stationId: string, scroll: boolean): void => {
// 고른 노면공 범위 안 카드는 다시 눌러도 그대로 — 풂은 빈 자리 · 목록 · 알약(167-3)
const section = currentDetail?.cross_sections.find((entry) => entry.station_id === stationId);
const held =
section && isPavement(spanMarkId)
? inSpan(
section,
spanMarks.find((entry) => entry.structure_id === spanMarkId),
)
: false;
if (selectedStationId === stationId && held) return;
const previous = selectedStationId;
const deselect = selectedStationId === stationId;
selectedStationId = deselect ? null : stationId;
@@ -429,6 +421,17 @@ export function createSectionView(
grid.addEventListener("click", (event) => {
if (!(event.target as HTMLElement).closest(".b06-cross-card")) clearSelection();
});
// 노면공 형상 누름 = 목록 고름(범위 카드 전부 · 형상 강조) — 카드 고름보다 먼저 가로챔(189-1)
grid.addEventListener(
"click",
(event) => {
const pave = pavementAt(event.target, spanMarks);
if (!pave?.structure_id || !isPavement(pave.structure_id)) return;
event.stopPropagation();
pavementSelectListener?.(pave.structure_id);
},
true,
);
// 열 수 = 사용자 값 · 폭 = (칸 폭 − 간격) ÷ 열 수(`_Section_Columns` · 138-3).
cachedCardWidth = crossCardWidth(renderWidth, columnCount, CROSS_GRID_GAP);
// CSS auto-fill의 자체 열 수와 JS columnCount가 어긋나면 같은 행 높이 그룹핑이 실제
@@ -609,6 +612,9 @@ export function createSectionView(
setStationSelectListener(listener) {
stationSelectListener = listener;
},
setPavementSelectListener(listener) {
pavementSelectListener = listener;
},
setStructureEdit(edit) {
structureEdit = edit;
},