2026-09-05 사용자 지시 건. 넘김 자체는 서 있었고 값이 중간에 지워지거나 대조에서 떨어지고 있었다. - 부재키가 지워지던 길 — 3D 로 고른 뒤 선택 동기화가 **측점만** 다시 적어 부재키를 덮었다. 같은 측점이면 이미 적힌 부재키를 지키게 함(모든 호출자에 함께 적용). - 측점 대조 허용오차 0.01m → 0.05m. 같은 화면의 다른 대조와 같은 값이며, 3D 가 준 누가거리가 소수점 아래에서 조금만 달라도 측점을 못 찾고 조용히 끝나던 원인. - 「진입당 한 번」 빗장을 넘김값 서명 비교로 교체 — 자료가 늦게 와도 다시 서고, 같은 값이면 재렌더에도 스크롤이 안 튄다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
65 lines
3.3 KiB
TypeScript
65 lines
3.3 KiB
TypeScript
/* =============================================================================
|
|
* B06_Section_UI_Page_Structure_Pick.ts
|
|
* B05 3D에서 고른 구조물을 **B06 화면에 얹는다**(2026-09-04 사용자 확정) — 그 측점
|
|
* 카드를 고르고 화면에 드러낸 뒤, 부재키가 있으면 그 시설의 조정창까지 연다.
|
|
*
|
|
* 부재키는 **횡단도가 그 부재를 부르는 이름 그대로**다. 이름이 겹쳐도(배수관 유입 ↔
|
|
* 세월교 유입) 한 측점에는 시설이 하나뿐이라 헷갈리지 않는다 — 그 측점이 세월교면
|
|
* 세월교 조정창, BOX암거면 BOX 조정창, 아니면 기슭막이 조정창으로 보낸다.
|
|
* 본체(`body` — 세월교 월류부 상판·BOX 구체)는 고르는 부재가 아니라 카드까지만 연다.
|
|
*
|
|
* 세월교·BOX는 조정창 하나가 그 측 부재 여럿(벽·바닥·날개벽·에이프런)을 함께 다루므로
|
|
* 부재키가 `측이름:부재`(예 `inlet:wall`) 꼴이다 — **앞칸이 조정창 이름**이다. 3D 강조는
|
|
* 부재 하나만 켜야 해서 뒤칸까지 나눠 두었다(2026-09-04 사용자 확정).
|
|
* ========================================================================== */
|
|
|
|
import type { SectionDetailResponse } from "./B06_Section_Api_Fetch";
|
|
import type { RevetKey } from "./B06_Section_UI_Cross_Culvert";
|
|
import type { StructurePickHandoff } from "../B05_Profile/B05_Profile_UI_Structure_Pick_Session";
|
|
|
|
/** 기슭막이 조정창이 받는 부재키 — 집수정·배관·본체는 여기서 빠진다. */
|
|
const REVET_KEYS = /^(inlet|outlet|own|extra\d+|bextra\d+)$/;
|
|
|
|
interface PickTargets {
|
|
focusStation: (stationId: string) => void;
|
|
refreshCard: (chainageM: number) => void;
|
|
revetSelect: (chainageM: number, key: RevetKey) => void;
|
|
fordSelect: (chainageM: number, role: "inlet" | "outlet") => void;
|
|
boxSelect: (chainageM: number, role: "left" | "right") => void;
|
|
}
|
|
|
|
/**
|
|
* 넘김값을 화면에 적용한다. 값이 없거나 그 측점이 이 노선에 없으면 아무것도 안 한다.
|
|
* 카드가 다 선 뒤에 고른다 — 스크롤이 자리를 잡아야 한다.
|
|
*/
|
|
export function applyStructurePick(
|
|
handoff: StructurePickHandoff | null,
|
|
detail: SectionDetailResponse | null,
|
|
targets: PickTargets,
|
|
): void {
|
|
if (!handoff) return;
|
|
// 허용오차는 같은 화면의 다른 대조와 같은 0.05m 다 — 0.01m 로는 3D 가 준 누가거리가
|
|
// 소수점 아래에서 조금만 달라도 그 측점을 못 찾고 조용히 끝났다(2026-09-05 진단).
|
|
const target = detail?.cross_sections.find(
|
|
(section) => Math.abs(section.chainage_m - handoff.at) < 0.05,
|
|
);
|
|
if (!target) return;
|
|
// 조정창은 앞칸(측 이름)만 본다 — 뒤칸은 3D 강조를 부재 하나로 좁히는 몫이다.
|
|
const key = handoff.key?.split(":")[0];
|
|
requestAnimationFrame(() => {
|
|
targets.focusStation(target.station_id);
|
|
if (!key || key === "body") return;
|
|
if (target.ford) {
|
|
if (key !== "inlet" && key !== "outlet") return;
|
|
targets.fordSelect(target.chainage_m, key);
|
|
} else if (target.box) {
|
|
if (key !== "left" && key !== "right") return;
|
|
targets.boxSelect(target.chainage_m, key);
|
|
} else {
|
|
if (!REVET_KEYS.test(key)) return;
|
|
targets.revetSelect(target.chainage_m, key as RevetKey);
|
|
}
|
|
targets.refreshCard(target.chainage_m);
|
|
});
|
|
}
|