Merge remote-tracking branch 'origin/sub_laptop_5' into main_laptop_1

# Conflicts:
#	B06_Section/B06_Section_UI_Cross_Areas.ts
#	B06_Section/B06_Section_UI_Style_Cross_Areas.css
This commit is contained in:
2026-10-17 15:29:53 +09:00
42 changed files with 354 additions and 1774 deletions
@@ -47,11 +47,7 @@ import { showsAnchor } from "./logic/B05_Profile_UI_Structures_Define";
import { hiddenOptionKeys } from "./B05_Profile_UI_Structures_Define_Form";
import { stationLabel as formatStation } from "../common_util/common_util_station";
import { PIPE_MATCH_M, resolveSelection } from "../A00_Common/design/design_selection";
import {
movedStructure,
snapOldStations,
snapStructureStation,
} from "./B05_Profile_UI_Structures_Snap";
import { movedStructure, snapOldStations, snapStationFor } from "./B05_Profile_UI_Structures_Snap";
/** 공개 타입·표시 상수는 700줄 제한으로 `_Structures_Panel_Types` 로 옮겼다 —
* 옛 임포트 경로가 그대로 동작하도록 여기서 다시 내보낸다(2026-09-04). */
@@ -645,7 +641,7 @@ export function createStructuresSection(
loadForm(structures.find((entry) => entry.structure_id === structureId) ?? null);
},
addAt(chainageM, typeId) {
chainageM = snapStructureStation(chainageM); // 정수 m · 일반 측점 붙기(234-1)
chainageM = snapStationFor(chainageM, placementOf(typeId)); // 정수 m · site = 기존 측점(234-1 · 380-2)
const type = typeMap().get(typeId);
if (!type) return;
// 우클릭 = [추가]까지 끝난 상태(116-1 · 08-18 「즉시 추가 폐지」를 바꿈) — 새로 놓기에서
@@ -23,7 +23,10 @@ import { readStructureSpec, specRenderedKeys } from "./B05_Profile_UI_Structures
import { asRoad } from "./logic/B05_Profile_UI_Structures_Define";
import type { GroupBoxes } from "./B05_Profile_UI_Structures_Groups";
import { specFor } from "../A00_Common/design/logic/design_structure_pipe";
import { snapStructureStation } from "../common_util/common_util_structure_station";
import {
snapExistingStation,
snapStructureStation,
} from "../common_util/common_util_structure_station";
import {
readGroupItems,
readSummaryItem,
@@ -328,6 +331,11 @@ export async function commit(ctx: StructuresCommitContext, live = false): Promis
} else {
anchor = ctx.anchorFields.read(step, true);
if (anchor === null) return stop(ctx.anchorFields.station, "기준 측점");
if (placement === "site") {
// 사토장 · 토취장 = 친 m 에서 가장 가까운 기존 측점 · 새 측점 안 심음(380-2)
anchor = snapExistingStation(anchor);
ctx.anchorFields.write(anchor, step);
}
}
// 필수 옵션(미확정 기본값 없음)이 비어 있으면 추가하지 않는다 — 서버도 거절한다.
// 상세(detail) 옵션은 폼에 없으므로 여기 걸리지 않는다(B06/B07에서 받는다).
+14 -4
View File
@@ -11,18 +11,21 @@
import { showToast } from "@ui/ui_template_elements";
import {
isSnappedStation,
snapExistingStation,
snapStationFor,
snapStructureStation,
} from "../common_util/common_util_structure_station";
import { PIPE_MATCH_M } from "../A00_Common/design/design_selection";
export { snapStructureStation };
export { snapStationFor, snapStructureStation };
import { structureAnchorM, type StructureInstance } from "./B05_Profile_Api_Structures";
import type { FacilityAttributes } from "./B05_Profile_UI_Drainage_Facility";
import type { PipeFacilityItem } from "./B05_Profile_UI_Structures_Panel_Types";
/** 구조물을 그 측점으로 옮긴 모양 — 구간은 기준과의 거리 · 길이를 지키되 시작 · 끝도 맞춤. */
/** 구조물을 그 측점으로 옮긴 모양 — 구간은 기준과의 거리 · 길이를 지키되 시작 · 끝도 맞춤 ·
* site(사토장 · 토취장) = 가장 가까운 기존 측점(380-2). */
export function movedStructure(target: StructureInstance, toChainageM: number): StructureInstance {
const anchor = snapStructureStation(toChainageM);
const anchor = snapStationFor(toChainageM, target.placement);
if (target.placement !== "interval") return { ...target, chainage_m: anchor };
const length = (target.end_m ?? 0) - (target.start_m ?? 0);
const start = snapStructureStation(anchor - (structureAnchorM(target) - (target.start_m ?? 0)));
@@ -47,9 +50,16 @@ export function followSnapped<T extends { chainage_m: number }>(
const offGrid = (value: number | null | undefined): boolean =>
typeof value === "number" && !isSnappedStation(value);
/** 기존 측점(끝 소수 · 옛 소수 구조물 측점 포함)에 선 site 인가 — 맞춤 밖으로 안 셈(380-2). */
const onExisting = (structure: StructureInstance): boolean =>
structure.placement === "site" &&
typeof structure.chainage_m === "number" &&
snapExistingStation(structure.chainage_m) === structure.chainage_m;
/** 기준 · 시작 · 끝 중 하나라도 맞춤 밖(소수)인 구조물인가. */
export const structureOffGrid = (structure: StructureInstance): boolean =>
offGrid(structure.chainage_m) || offGrid(structure.start_m) || offGrid(structure.end_m);
!onExisting(structure) &&
(offGrid(structure.chainage_m) || offGrid(structure.start_m) || offGrid(structure.end_m));
export interface SnapPlan {
/** 목록 자리 · 옮긴 모양. */