From dff1e3aff9107bb0fb2d6b132770196e7aaeb91d Mon Sep 17 00:00:00 2001 From: umsangdon Date: Sun, 23 Aug 2026 18:47:36 +0900 Subject: [PATCH] =?UTF-8?q?feat(B06):=20=ED=9A=A1=EB=8B=A8=20=EB=B3=B4?= =?UTF-8?q?=EA=B8=B0=20=EB=B0=98=ED=8F=AD=EC=9D=84=20=EB=B3=84=EB=8F=84=20?= =?UTF-8?q?=EC=BB=A8=ED=85=8C=EC=9D=B4=EB=84=88=EB=A1=9C=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC=20+=20=EC=82=AC=EC=9D=B4=EB=93=9C=20=EC=96=91?= =?UTF-8?q?=EC=8B=9D=20B05=20=EC=A0=95=EB=A0=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 「횡단 보기 설정」 컨테이너 신설: 반폭 입력 + [적용] 버튼 한 줄. 표준 횡단면 설정의 [전체 측점 반영]에 물려 있던 반폭 적용을 떼어냈다 — 보유 샘플(20m) 안이면 전 측점 설계 재계산 없이 즉시 반영된다. - 표준 횡단면 설정 컨테이너는 기본 접힘. - 사이드 컨테이너 양식(여백·글자 크기·색)을 B05 .b05-route__panel-section 값으로 맞춤. 접힘 토글·외곽선은 이미 공용(ui-collapsible / ui-sidebar-section)이었다. 표준단면 「변수 위치 안내」 모식도 스타일은 현행 유지. - 표준패널의 미사용 extraControl 인자 제거. Co-Authored-By: Claude Opus 5 (1M context) --- B06_Section/B06_Section_UI_Page.ts | 59 ++++++++++++-------- B06_Section/B06_Section_UI_Standard_Panel.ts | 7 +-- B06_Section/B06_Section_UI_Style.css | 34 +++++++++-- ui_template/ui_template_locale_b2.ts | 2 +- 4 files changed, 68 insertions(+), 34 deletions(-) diff --git a/B06_Section/B06_Section_UI_Page.ts b/B06_Section/B06_Section_UI_Page.ts index 899df2bc..3cd56be6 100644 --- a/B06_Section/B06_Section_UI_Page.ts +++ b/B06_Section/B06_Section_UI_Page.ts @@ -56,22 +56,35 @@ export async function renderB06ProfileCross(root: HTMLElement): Promise { let stationInterval: number | undefined; // 표준 횡단면 설정 패널 자리. context 로드 후 config 기본값으로 채운다. - const standardGroup = buildGroup(L("B06_Std_Title")); + // 표준 횡단면 설정은 기본 접힘(2026-08-23 사용자 지시) — 자주 여는 칸이 아니다. + const standardGroup = buildGroup(L("B06_Std_Title"), true); const standardPanelSlot = document.createElement("div"); standardGroup.append(standardPanelSlot); let standardPanel: StandardPanelController | null = null; - // 높이 배율 옵션은 폐지 — 항상 1배율(2026-08-06 사용자 지시). 표시 옵션 그룹도 함께 - // 사라지고, 횡단 반폭은 표준 횡단면 설정 컨테이너의 [전체 측점 반영] 위로 옮겼다. - // 반폭 적용도 그 버튼이 담당한다(재계산 버튼 폐지) — 요청 반폭이 보유 샘플 폭(기본 - // 20m, config SECTION_CROSS_HALF_WIDTH_M) 이하면 표시만 바꾸고, 넘으면 B05부터 - // 재생성해 영구저장 후 다시 로드한다. + // 높이 배율 옵션은 폐지 — 항상 1배율(2026-08-06 사용자 지시). + // 횡단 반폭은 **자체 컨테이너 + 자체 [보기 반폭 적용] 버튼**이다(2026-08-23 사용자 지시) + // — 표준 횡단면 설정의 [전체 측점 반영]에 물려 있어 반폭만 바꿔도 전 측점 설계 + // 재계산을 기다려야 했다. 요청 반폭이 보유 샘플 폭(기본 20m, config + // SECTION_CROSS_HALF_WIDTH_M) 이하면 표시만 바꾸므로 즉시 끝나고, 넘을 때만 재생성한다. const crossHalfWidthField = createInputField({ label: L("B05_Route_Field_CrossHalfWidth"), type: "number", }); crossHalfWidthField.input.min = "0.1"; crossHalfWidthField.input.step = "0.1"; + const applyWidthButton = createButton({ + label: L("B06_View_Apply"), + variant: "filled", + onClick: () => void applyCrossHalfWidth(), + }); + applyWidthButton.title = L("B06_View_Apply_Tip"); + const viewGroup = buildGroup(L("B06_View_Title")); + // 반폭 입력 + [적용]은 한 줄(2026-08-23 사용자 지시). + const viewRow = document.createElement("div"); + viewRow.className = "b06-profile__field-row"; + viewRow.append(crossHalfWidthField.root, applyWidthButton); + viewGroup.append(viewRow); /** 횡단면도 **표시** 반폭 기본값(m) — 2026-08-19 사용자 지시로 20 → 12. 계산·보유 * 샘플 폭은 백엔드 기본(SECTION_CROSS_HALF_WIDTH_M = 20m) 그대로라 12는 표시 * 범위만 좁힌다(12 ≤ 20이므로 재계산 없음). 계산 범위와 혼동 금지. */ @@ -105,7 +118,7 @@ export async function renderB06ProfileCross(root: HTMLElement): Promise { const leftForm = document.createElement("div"); leftForm.className = "b06-profile__form"; - leftForm.append(standardGroup, actionRow); + leftForm.append(viewGroup, standardGroup, actionRow); // 그룹 제목 행 클릭 시 접기/펼치기(N-4-1). 액션 버튼 행은 collapsible 아님. attachCollapsible(leftForm); @@ -265,23 +278,30 @@ export async function renderB06ProfileCross(root: HTMLElement): Promise { }, }); - /** 패널 [전체 반영](N-2-1): design 보유 전 측점을 패널 최신값으로 순차 재계산한다. - * handleDesignChange가 standardPanel.getValues()를 실어 보내므로 표준단면 수치만 - * 갱신되고 측점별 버튼 선택값은 보존된다. 순차 await로 동시 API 호출 수를 제한한다. */ - async function applyPanelToAll(): Promise { - if (!sectionDetail || !projectId || currentRouteId === null) return; + /** + * [보기 반폭 적용] — 표시 반폭만 반영한다(2026-08-23 사용자 지시로 분리). + * 보유 샘플(기본 20m) 안이면 재계산 없이 즉시, 넘을 때만 재생성이 돈다. + * 측점 개별 반폭은 전역값으로 초기화한다 — 남아 있으면 전역값이 무시된다. + */ + async function applyCrossHalfWidth(): Promise { + if (!sectionDetail) return; const requested = crossHalfWidth(); if (requested !== undefined && !(await ensureSampledWidth(requested))) return; - // 전체 반영 = 개별 반폭도 전역값으로 초기화(2026-08-06). 저장된 개별값 - // (design.display_half_width_m)이 남아 있으면 전역 반폭이 무시되므로, 세션에 - // 전역값을 명시해 저장값보다 우선하게 한다(확정 시 저장값도 전역으로 덮인다). + if (!sectionDetail) return; stationControls.applyGlobalWidth( requested, sectionDetail.cross_sections.map((section) => section.chainage_m), ); persistDisplayHalfWidth(); renderSectionDetail(); - updateActionState(); + showToast(L("B06_View_Apply_Success"), "success"); + } + + /** 패널 [전체 반영](N-2-1): design 보유 전 측점을 패널 최신값으로 순차 재계산한다. + * handleDesignChange가 standardPanel.getValues()를 실어 보내므로 표준단면 수치만 + * 갱신되고 측점별 버튼 선택값은 보존된다. 순차 await로 동시 API 호출 수를 제한한다. */ + async function applyPanelToAll(): Promise { + if (!sectionDetail || !projectId || currentRouteId === null) return; const targets = sectionDetail.cross_sections.filter((section) => section.design); if (!targets.length) return; showLoadingOverlay(); @@ -607,12 +627,7 @@ export async function renderB06ProfileCross(root: HTMLElement): Promise { // 표준 횡단면 설정 패널 장착(세션값 우선, 없으면 config 기본값). // 횡단 반폭 입력은 [전체 측점 반영] 버튼 위로 들어간다(2026-08-06 사용자 지시). - standardPanel = createStandardPanel( - projectId, - context.standard_cross_section, - applyPanelToAll, - crossHalfWidthField.root, - ); + standardPanel = createStandardPanel(projectId, context.standard_cross_section, applyPanelToAll); standardPanelSlot.append(standardPanel.root); if (context.route_id === null) { diff --git a/B06_Section/B06_Section_UI_Standard_Panel.ts b/B06_Section/B06_Section_UI_Standard_Panel.ts index 604c515b..2055c94c 100644 --- a/B06_Section/B06_Section_UI_Standard_Panel.ts +++ b/B06_Section/B06_Section_UI_Standard_Panel.ts @@ -159,8 +159,6 @@ export function createStandardPanel( projectId: string, defaults: StandardCrossSection, onApplyAll?: () => void | Promise, - /** [전체 측점 반영] 버튼 **위**에 끼울 추가 컨트롤(횡단 반폭 입력, 2026-08-06 사용자 지시). */ - extraControl?: HTMLElement, ): StandardPanelController { // 세션값 우선, 없으면 config 기본값. defaults는 복원 기준으로 보존한다. const sessionValue = readSession(projectId); @@ -264,9 +262,8 @@ export function createStandardPanel( } actions.append(resetButton); - // 추가 컨트롤(횡단 반폭)은 액션 행 바로 위 — [전체 측점 반영]이 반폭 적용까지 담당한다. - if (extraControl) root.append(body, loader, extraControl, actions); - else root.append(body, loader, actions); + // 횡단 반폭은 사이드의 **별도 컨테이너**로 뺐다(2026-08-23) — 여기는 표준단면 설정만. + root.append(body, loader, actions); return { root, diff --git a/B06_Section/B06_Section_UI_Style.css b/B06_Section/B06_Section_UI_Style.css index 95cacc76..23696df7 100644 --- a/B06_Section/B06_Section_UI_Style.css +++ b/B06_Section/B06_Section_UI_Style.css @@ -31,23 +31,45 @@ gap: var(--spacing-16); } +/* 사이드 컨테이너 양식은 B05 경로 패널(.b05-route__panel-section)과 같게 맞춘다 + — 두 화면의 좌측 패널이 같은 폼으로 보여야 한다(2026-08-23 사용자 지시). + 여백·글자 크기·색을 B05 값으로 옮겼고, 표준단면 「변수 위치 안내」 모식도만 + 기존 스타일(.b06-std__diagram*)을 그대로 둔다. */ .b06-profile__group { display: flex; flex-direction: column; - gap: var(--spacing-16); + gap: var(--spacing-8); margin: 0; - padding: var(--spacing-16); + padding: calc(var(--spacing-8) + var(--spacing-4)); /* 테두리는 공통 ui-sidebar-section이 전담 — 로컬 border 선언이 공통 색을 덮던 문제 제거(2026-08-06 사용자 보고). */ border-radius: var(--radius-cards); background-color: var(--color-surface-raised); + color: var(--color-text-body); + font-size: var(--text-caption); } .b06-profile__group-legend { - padding: 0 var(--spacing-8); - font-size: var(--text-caption); - font-weight: var(--font-weight-medium); - color: var(--color-text-secondary); + margin: 0; + padding: 0; + font-size: var(--text-body-sm); + color: var(--color-text); +} + +/* 입력 한 칸 + 버튼을 한 줄로(횡단 보기 설정). 버튼은 입력 아래 선에 맞춘다. */ +.b06-profile__field-row { + display: flex; + align-items: flex-end; + gap: var(--spacing-8); +} + +.b06-profile__field-row > *:first-child { + flex: 1 1 auto; + min-width: 0; +} + +.b06-profile__field-row > .ui-btn { + flex: 0 0 auto; } /* --- 읽기 전용 경로 컨텍스트 --- */ diff --git a/ui_template/ui_template_locale_b2.ts b/ui_template/ui_template_locale_b2.ts index 16748df3..0414aed0 100644 --- a/ui_template/ui_template_locale_b2.ts +++ b/ui_template/ui_template_locale_b2.ts @@ -466,7 +466,7 @@ export const ui_locales_b2 = { /* --- B06 횡단 보기 설정(반폭) --- */ B06_View_Title: ["횡단 보기 설정", "Cross-section view"], - B06_View_Apply: ["보기 반폭 적용", "Apply view width"], + B06_View_Apply: ["적용", "Apply"], B06_View_Apply_Tip: [ "표시 반폭만 바로 반영합니다(측점 설계 재계산 없음). 계산 반폭(20m)을 넘는 값만 재생성이 필요해 시간이 걸립니다.", "Applies the display half-width only (no per-station redesign). Only values beyond the sampled 20 m need regeneration.",