Merge remote-tracking branch 'origin/dev' into main_desktop_1

This commit is contained in:
2026-10-06 10:37:36 +09:00
26 changed files with 4349 additions and 84 deletions
@@ -55,7 +55,11 @@ import {
} from "../A00_Common/design/design_structure_box";
import { FORD_SPEC, withLegacyGuards } from "../A00_Common/design/design_structure_ford";
import { fordHeightHint, fordHeightM } from "../A00_Common/design/design_structure_ford_calc";
import { guardHeightHint, pipeLengthM } from "../A00_Common/design/design_structure_pipe_calc";
import {
guardHeightHint,
pipeExtraCount,
pipeLengthM,
} from "../A00_Common/design/design_structure_pipe_calc";
import {
hasLinks,
linkFields,
@@ -215,6 +219,8 @@ export interface FacilityOptionsForm {
paintLinks: () => void;
/** 고른 관 측점 — 관 길이(자동) 계산에 씀. */
setChainage: (chainageM: number | null) => void;
/** 횡단 「추가 기슭막이(단)」이 바뀜 — 배관 흙막이 컨테이너 수를 다시 맞춤(54-1 · B06 이 부름). */
recount: () => void;
/** 현재 필드 값을 시설 옵션으로 읽는다(빈 값 생략). 숨긴 칸은 폼이 받은 옛 값 그대로. */
readOptions: () => Record<string, string | number>;
/** 「구조물 옵션 보이기」에서 끈 레지스트리 옵션 키 — 그 칸을 가린다(값은 옛 값 보존).
@@ -265,8 +271,10 @@ export function createFacilityOptionsForm(
auto: (_c, item) => {
if (item.id !== "length") return "";
const length = pipeLengthM(chainage);
return length === null ? "횡단 설계 뒤 셈" : length.toFixed(2);
return length === null ? "횡단 설계 뒤 셈" : String(Math.round(length));
},
// 흙막이 개수 = 유출 「추가 기슭막이(단)」(54-1)
count: (c) => (c.id === "soil_add" ? pipeExtraCount(chainage) : undefined),
hint: (c, item, state) => {
const soil = c.id !== "inlet" || state.inlet?.[0]?.structure === "기슭막이";
return item.id === "height" && soil ? guardHeightHint(state.pipe?.[0]?.diameter ?? "") : "";
@@ -475,6 +483,9 @@ export function createFacilityOptionsForm(
chainage = chainageM;
if (current === "pipe") pipeForm.refresh();
},
recount() {
if (current === "pipe") pipeForm.recount();
},
onInletStructureChange(handler) {
inletStructureHandler = handler;
},
@@ -494,7 +505,11 @@ export function createFacilityOptionsForm(
// 받은 값만 칸에 — 없으면 「안 정함」(새 시설은 부르는 쪽이 등록부 기본값을 실어 줌 · 46-7).
const groups = Object.fromEntries((definition?.groups ?? []).map((g) => [g.id, g.name]));
const names = definition?.spec_names ?? {};
if (facility === "pipe") pipeForm.write(PIPE_SPEC, options, names, groups);
if (facility === "pipe") {
// 정의 파일의 옛 이름 「흙막이 추가」 — 명세 이름 「흙막이」가 앞섬(54-1)
const { soil_add: _old, ...pipeNames } = names;
pipeForm.write(PIPE_SPEC, options, pipeNames, groups);
}
if (facility === "box_culvert") {
// 본체 규격은 저장 안 함 — 폭 · 높이로 되찾음 · 옛 설치 「있음」 = 날개벽
boxForm.write(BOX_SPEC, boxOptionsIn(options), names, groups);
@@ -26,10 +26,8 @@ export const FORM_OPTION_KEYS: Readonly<Record<string, readonly string[]>> = {
"pipe_diameter_mm",
"inlet_type",
"inlet_structure",
"inlet_basin_length_m",
// 집수정 길이 · 전 · 후는 폼에서 빠짐(54-1) — 옛 값 그대로 둠
"inlet_basin_height_m",
"inlet_basin_before_m",
"inlet_basin_after_m",
...revetKeys("inlet"),
"outlet_type",
...revetKeys("outlet"),
@@ -21,6 +21,7 @@ import { mergeStructureOptions } from "./B05_Profile_UI_Structures_Summary";
import { readStructureSpec, specRenderedKeys } from "./B05_Profile_UI_Structures_Spec";
import { asRoad } from "./B05_Profile_UI_Structures_Define";
import type { GroupBoxes } from "./B05_Profile_UI_Structures_Groups";
import { STRUCTURE_SPECS } from "../A00_Common/design/design_structure_pipe";
import {
readGroupItems,
readSummaryItem,
@@ -110,8 +111,13 @@ export function loadForm(ctx: StructuresCommitContext, target: StructureInstance
ctx.endFields.write(target.end_m ?? null, step);
ctx.memoField.value = target.memo ?? "";
ctx.renderOptionFields(shown.options);
ctx.setSummary(readSummaryItem(target.summary_item));
ctx.groupBoxes.set(readGroupItems(target.group_items));
const links = readGroupItems(target.group_items);
const summary = readSummaryItem(target.summary_item);
// 정의 그룹 종류는 종류 단위 잇기 줄이 없음 — 옛 종류 단위 값은 첫 그룹 컨테이너 잇기로 읽음(54-6)
const first = type && !STRUCTURE_SPECS[type.type_id] ? type.groups?.[0]?.id : undefined;
const moved = !!(first && summary && !links[first]);
ctx.setSummary(moved ? null : summary);
ctx.groupBoxes.set(moved ? { ...links, [first!]: summary! } : links);
ctx.groupBoxes.setShapes(target.options);
// 구간 직접 입력 시절에 저장된 항목 호환 — 길이·전길이 옵션이 없으면 저장된
// 시작~종료·기준점에서 역산해 채워 범위 표시·재저장이 이어지게 한다(2026-08-19).
@@ -242,7 +242,8 @@ export function paintStale(
? staleValues(values, known).filter(([key]) => !own.prefixes.some((p) => key.startsWith(p)))
: [];
box.replaceChildren();
box.hidden = !stale.length;
// 상자는 모든 종류에서 숨김(54-1) — 값은 파일에 그대로
box.hidden = true;
if (!stale.length) return;
const legend = document.createElement("legend");
legend.textContent = "지난 정의 값";
@@ -34,7 +34,7 @@ export function buildSummaryRow(): SummaryRow {
const pick = document.createElement("button");
pick.type = "button";
pick.className = "b05-route__irregular-btn";
pick.textContent = "고르기";
pick.textContent = "선택";
pick.dataset.b05Summary = "pick";
const clear = document.createElement("button");
clear.type = "button";