From 18e6d10ebb3144f950c316bf492c5361bdf09116 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Sat, 17 Oct 2026 14:54:54 +0900 Subject: [PATCH] =?UTF-8?q?feat(B06=20=ED=9A=A1=EB=8B=A8):=20=EC=B9=B4?= =?UTF-8?q?=EB=93=9C=20=EC=A2=8C=EC=83=81=20=EB=A9=B4=EC=A0=81=ED=91=9C=20?= =?UTF-8?q?=EC=A7=80=EC=9B=80=20=E2=80=94=20=EA=B0=92=EC=9D=80=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=EB=AA=A8=EB=8B=AC=20=ED=91=9C=20=C2=B7=20=EC=A1=B0?= =?UTF-8?q?=EC=A0=95=EC=B0=BD=20=EC=9C=84=EC=97=90=EC=84=9C=20=EC=8B=9C?= =?UTF-8?q?=EC=9E=91=20(379-2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 카드 면적 readout(buildAreaReadout · setChipActive) · 그 CSS · 안 쓰게 된 로케일 키 지움 - 구조물 조정창 top = spacing-8(표 높이 띄움 걷음) · 면적 강조 밴드 · 모달 표 그대로 - 시험 test_173 고쳐 씀(표 걷음 · 조정창 자리 · 글자 변수 남김) Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_014utrjfoW831Vc5wJUd13kL --- B06_Section/B06_Section_UI_Cross_Areas.ts | 174 +----------------- B06_Section/B06_Section_UI_Cross_Design.ts | 1 - B06_Section/B06_Section_UI_Cross_View.ts | 17 +- B06_Section/B06_Section_UI_Section_View.ts | 2 +- .../B06_Section_UI_Style_Cross_Areas.css | 106 +---------- .../B06_Section_UI_Style_Cross_Controls.css | 8 +- resources/tester/test_173_areas_detail.py | 31 ++-- ui_template/ui_template_locale_b2.ts | 14 -- 8 files changed, 26 insertions(+), 327 deletions(-) diff --git a/B06_Section/B06_Section_UI_Cross_Areas.ts b/B06_Section/B06_Section_UI_Cross_Areas.ts index 6bdaaee94..6985913bd 100644 --- a/B06_Section/B06_Section_UI_Cross_Areas.ts +++ b/B06_Section/B06_Section_UI_Cross_Areas.ts @@ -1,6 +1,6 @@ /* ============================================================================= * B06_Section_UI_Cross_Areas.ts - * 횡단 절·성토 면적 readout과 면적 영역 하이라이트 밴드. + * 횡단 절·성토 면적 영역 하이라이트 밴드(카드 좌상 면적표는 걷음 · 값은 상세 모달 표 · 379-2). * * 절토는 암반 경계선(지면선 평행 복사)을 기준으로 위=토사, 아래=암반으로 갈린다. 경계선 * 위치가 곧 유토곡선 EA/RR/BR 비율을 만들므로, 사용자가 경계선을 올리내리면 여기 표시되는 @@ -16,7 +16,7 @@ * ========================================================================== */ import type { CrossDesign, SectionSample } from "./B06_Section_Api_Fetch"; -import { L, svgElement } from "./B06_Section_UI_Section_Common"; +import { svgElement } from "./B06_Section_UI_Section_Common"; /** * 강조 대상 = 면적표의 칸. `cut_total`은 토사·암반 두 밴드를 함께 켠다. @@ -135,7 +135,7 @@ function bandPolygons( /** * 그 측점 절토의 암종. 분리 필드가 없는 **구 데이터**는 지반유형을 그대로 쓴다 — - * 표(`cutBreakdown`)는 그 규칙으로 RR/BR에 값을 넣는데 여기서만 null로 보면 + * 면적표(상세 모달)는 그 규칙으로 RR/BR에 값을 넣는데 여기서만 null로 보면 * 암반 밴드가 아예 안 만들어져 **표에는 값이 있는데 그림이 안 켜진다**(2026-08-02 사용자 지적). */ function rockKindOf(design: CrossDesign): CrossDesign["cut_rock_kind"] { @@ -246,171 +246,3 @@ export function appendCrossAreaBands( } }; } - -/** 절토 단면적을 도면 표기(EA 토사 / RR 리핑암 / BR 발파암)로 갈라 낸다. */ -function cutBreakdown(design: CrossDesign): { - ea: number; - rr: number; - br: number; - total: number; -} { - const total = design.cut_area_m2; - // 구 데이터(분리 필드 없음)는 절토 전량을 측점 지반유형으로 돌린다 — 유토곡선 폴백과 같은 규칙. - if (design.cut_soil_area_m2 === undefined || design.cut_rock_area_m2 === undefined) { - const ground = design.ground_type; - return { - ea: ground === "soil" ? total : 0, - rr: ground === "ripping_rock" ? total : 0, - br: ground === "blasting_rock" ? total : 0, - total, - }; - } - const rock = design.cut_rock_area_m2; - const kind = rockKindOf(design); - return { - ea: design.cut_soil_area_m2, - rr: kind === "ripping_rock" ? rock : 0, - br: kind === "blasting_rock" ? rock : 0, - total, - }; -} - -/** 표 한 칸. `key`가 없으면 강조 대상이 아닌 칸(성토의 EA/RR/BR 자리)이다. */ -interface AreaCell { - key: CrossAreaKey | null; - value: number | null; - variant: string; -} - -function appendCell( - row: HTMLTableRowElement, - cell: AreaCell, - onSelect: ((key: CrossAreaKey) => void) | undefined, - cells: Map, -): void { - const td = document.createElement("td"); - td.className = `b06-design__area b06-design__area--${cell.variant}`; - const text = cell.value === null ? "—" : cell.value.toFixed(2); - // 값이 0이어도 칸은 남긴다 — 측점마다 항목 수가 달라지면 카드끼리 비교가 안 된다. - if (!cell.key || !onSelect || cell.value === null) { - td.textContent = text; - row.append(td); - return; - } - const button = document.createElement("button"); - button.type = "button"; - button.textContent = text; - button.title = L("B06_Design_Area_Highlight"); - button.setAttribute("aria-pressed", "false"); - button.addEventListener("click", (event) => { - // 카드까지 올라가면 측점 선택이 다시 걸려 카드가 통째로 다시 그려진다 — 강조가 즉시 사라진다. - event.stopPropagation(); - onSelect(cell.key as CrossAreaKey); - }); - cells.set(cell.key, [...(cells.get(cell.key) ?? []), button]); - td.append(button); - row.append(td); -} - -/** - * 절·성토 면적값 오버레이(E-4) — 그래프 중상단에 표(절토/성토 × EA·RR·BR·계)로 표시한다. - * 항목 이름은 도면 표기를 그대로 쓴다(EA 토사 / RR 리핑암 / BR 발파암). - * `onSelect`가 오면 값 칸이 강조 토글 버튼이 된다(선택된 카드에서만 넘어온다). - */ -export function buildAreaReadout( - design: CrossDesign | undefined, - onSelect?: (key: CrossAreaKey) => void, -): { root: HTMLElement; setActive: AreaHighlightSetter } { - if (!design) { - const unset = document.createElement("div"); - unset.className = "b06-cross-card__areas b06-design__area--unset"; - unset.textContent = L("B06_Design_Unset"); - return { root: unset, setActive: () => undefined }; - } - - const table = document.createElement("table"); - table.className = "b06-cross-card__areas"; - const head = document.createElement("tr"); - // 좌상단(행제목 × 열제목 교차) 칸은 단위 자리다 — 값 칸마다 단위를 붙이지 않는다. - for (const [text, tip] of [ - [L("B06_Design_Area_Unit"), ""], - [L("B06_Design_Area_EA"), L("B06_Design_Ground_Soil")], - [L("B06_Design_Area_RR"), L("B06_Design_Ground_Ripping")], - [L("B06_Design_Area_BR"), L("B06_Design_Ground_Blasting")], - [L("B06_Design_Area_Total"), ""], - ]) { - const th = document.createElement("th"); - th.textContent = text; - if (tip) th.title = tip; - head.append(th); - } - const thead = document.createElement("thead"); - thead.append(head); - - const cells = new Map(); - const cut = cutBreakdown(design); - const tbody = document.createElement("tbody"); - const rows: Array<{ label: string; variant: string; cells: AreaCell[] }> = [ - { - label: L("B06_Design_Cut_Area"), - variant: "cut_total", - // 값이 0이어도 누를 수 있다(2026-08-02 사용자 지시) — 그림에 없는 면적이면 강조만 켜지고 - // 밴드는 그대로다. 칸마다 눌리는 자리가 달라지면 어느 칸이 눌리는지 매번 확인해야 한다. - cells: [ - { key: "cut_soil", value: cut.ea, variant: "cut_soil" }, - { key: "cut_rr", value: cut.rr, variant: "cut_rr" }, - { key: "cut_br", value: cut.br, variant: "cut_br" }, - { key: "cut_total", value: cut.total, variant: "cut_total" }, - ], - }, - { - // 성토는 완성 단면(다짐 상태)이라 지반유형으로 갈리지 않는다 — 계 한 칸만 쓴다. - label: L("B06_Design_Fill_Area"), - variant: "fill", - cells: [ - { key: null, value: null, variant: "fill" }, - { key: null, value: null, variant: "fill" }, - { key: null, value: null, variant: "fill" }, - { key: "fill", value: design.fill_area_m2, variant: "fill" }, - ], - }, - ]; - // 사토장이 선 측점만 한 줄 더 — **성토와 합치지 않는다**(확정 ㉠). 없는 측점에 빈 줄을 - // 세우면 어느 측점에 사토장이 있는지 표에서 안 보인다. - const spoilArea = Number(design.spoil_fill_area_m2 ?? 0); - if (spoilArea > 0) { - rows.push({ - label: L("B06_Design_SpoilFill_Area"), - variant: "spoil-fill", - cells: [ - { key: null, value: null, variant: "spoil-fill" }, - { key: null, value: null, variant: "spoil-fill" }, - { key: null, value: null, variant: "spoil-fill" }, - { key: null, value: spoilArea, variant: "spoil-fill" }, - ], - }); - } - for (const row of rows) { - const tr = document.createElement("tr"); - const th = document.createElement("th"); - th.className = `b06-design__area b06-design__area--${row.variant}`; - th.textContent = row.label; - tr.append(th); - for (const cell of row.cells) appendCell(tr, cell, onSelect, cells); - tbody.append(tr); - } - table.append(thead, tbody); - - return { - root: table, - setActive: (key) => { - for (const [cellKey, elements] of cells) { - const active = cellKey === key; - for (const element of elements) { - element.classList.toggle("is-active", active); - element.setAttribute("aria-pressed", String(active)); - } - } - }, - }; -} diff --git a/B06_Section/B06_Section_UI_Cross_Design.ts b/B06_Section/B06_Section_UI_Cross_Design.ts index 5b43ca31a..1a521fa4e 100644 --- a/B06_Section/B06_Section_UI_Cross_Design.ts +++ b/B06_Section/B06_Section_UI_Cross_Design.ts @@ -443,7 +443,6 @@ export function buildDesignControls( scheduleReflow(card); // 암 경계선 제어는 그래프 X축 제목 행으로 이동(E-7, Cross_View에서 배치). - // 절·성토 면적 readout은 그래프 중상단 오버레이로 이동(E-4, Cross_View에서 배치). return { bar, groundSegment }; } diff --git a/B06_Section/B06_Section_UI_Cross_View.ts b/B06_Section/B06_Section_UI_Cross_View.ts index c4acae6b0..de5501110 100644 --- a/B06_Section/B06_Section_UI_Cross_View.ts +++ b/B06_Section/B06_Section_UI_Cross_View.ts @@ -13,7 +13,6 @@ import type { CrossSection } from "./B06_Section_Api_Fetch"; import { appendCrossAreaBands, type AreaHighlightSetter, - buildAreaReadout, type CrossAreaKey, } from "./B06_Section_UI_Cross_Areas"; import { @@ -192,7 +191,6 @@ export function createCrossSectionCard( let isSelected = selected; let activeArea: CrossAreaKey | null = selected ? (initialAreaKey ?? null) : null; let setBandActive: AreaHighlightSetter = () => undefined; - let setChipActive: AreaHighlightSetter = () => undefined; let activeRevet: RevetPick | null = revetOffset?.selectedFor(section) ?? null; /** 이 카드에서 **강조**할 벽. 연동으로 이어진 옆 측점이 고른 벽도 켠다 — * 조정창(`activeRevet`)은 고른 카드 하나에만 뜬다(2026-08-30 사용자). */ @@ -226,7 +224,6 @@ export function createCrossSectionCard( if (activeArea === null) return; activeArea = null; setBandActive(null); - setChipActive(null); onAreaSelect?.(section.station_id, null); }, selectCard: () => onSelect(section.station_id), @@ -245,7 +242,6 @@ export function createCrossSectionCard( if (activeRevet !== null && activeArea !== null) { activeArea = null; setBandActive(null); - setChipActive(null); } if (activeRevet !== null) { dropLine(); // 고름 하나만(137-3) @@ -262,7 +258,6 @@ export function createCrossSectionCard( card.classList.toggle("b06-cross-card--selected", nextSelected); activeArea = nextSelected ? (areaKey ?? null) : null; setBandActive(activeArea); - setChipActive(activeArea); // 면적이 켜졌거나 카드가 선택에서 빠지면 구조물 선택은 풀린다(같은 레벨). if ((activeArea !== null || !nextSelected) && activeRevet !== null) { // 전역 선택이 **아직 이 카드 것일 때만** 비운다 — 옆 카드에서 방금 고른 벽까지 @@ -306,7 +301,6 @@ export function createCrossSectionCard( dropLine(); } setBandActive(activeArea); - setChipActive(activeArea); onAreaSelect?.(section.station_id, activeArea); }; /** 보라 선 고름 — 다른 고름(벽 · 본체 · 면적)을 풀고 카드도 고름(137-3). 다시 누르면 풂. */ @@ -319,7 +313,6 @@ export function createCrossSectionCard( if (activeArea !== null) { activeArea = null; setBandActive(null); - setChipActive(null); onAreaSelect?.(section.station_id, null); } if (!isSelected) { @@ -649,9 +642,6 @@ export function createCrossSectionCard( contentBounds, ); scaleCenter(cardZoomStates.get(section.station_id)?.scale ?? 1); - // 절·성토 면적값은 그래프 중상단 오버레이로 표시(E-4). 값 칸은 항상 강조 토글이다. - const readout = buildAreaReadout(section.design, toggleArea); - setChipActive = readout.setActive; // 배수관 · 흙막이 조정창 두 벌(카드 안 · 좌측 사본) — `_Cross_View_Panels`(137-1). const panel = buildCardPanels({ section, @@ -684,12 +674,9 @@ export function createCrossSectionCard( fit: () => stationWidth.request(section.chainage_m, crossHalfWidth ?? maxOffset), }; const zoomBar = buildZoomControls(zoomPan, widthActions); - chartWrap.append(svg, readout.root, zoomBar, panel.root); + chartWrap.append(svg, zoomBar, panel.root); for (const panel of bodies.panels) chartWrap.append(panel.root); - if (activeArea) { - setBandActive(activeArea); - setChipActive(activeArea); - } + if (activeArea) setBandActive(activeArea); card.append(chartWrap); } diff --git a/B06_Section/B06_Section_UI_Section_View.ts b/B06_Section/B06_Section_UI_Section_View.ts index f2bb7aab8..a7934b7ba 100644 --- a/B06_Section/B06_Section_UI_Section_View.ts +++ b/B06_Section/B06_Section_UI_Section_View.ts @@ -455,7 +455,7 @@ export function createSectionView( // CSS auto-fill의 자체 열 수와 JS columnCount가 어긋나면 같은 행 높이 그룹핑이 실제 // 렌더 행과 달라져 카드 내부가 뒤죽박죽된다(N-2-6). 열 수 · 폭을 JS가 명시해 일치시킨다. grid.style.gridTemplateColumns = `repeat(${cols}, ${cachedCardWidth}px)`; - grid.dataset.columns = String(cols); // 4열부터 면적표 「계」만(173-3 · CSS) + grid.dataset.columns = String(cols); // 실제 그린 열 수(CSS) // 맹암거 형상 누름 = 그 구조물 id 고름(288-2 · 노면공 포장 범위 표식과 따로 · 같은 id 고름 창구) grid.addEventListener(SHAPE_PICK_EVENT, (event) => { const id = (event as CustomEvent).detail; diff --git a/B06_Section/B06_Section_UI_Style_Cross_Areas.css b/B06_Section/B06_Section_UI_Style_Cross_Areas.css index 12c8a2a21..256898f46 100644 --- a/B06_Section/B06_Section_UI_Style_Cross_Areas.css +++ b/B06_Section/B06_Section_UI_Style_Cross_Areas.css @@ -1,117 +1,15 @@ /* ============================================================================= * B06_Section_UI_Style_Cross_Areas.css - * 횡단 카드의 **면적 오버레이 계열** 스타일 — 절·성토 면적 표, 면적 강조 밴드, + * 횡단 카드의 **면적 오버레이 계열** 스타일 — 면적 강조 밴드, * 설계선·암 경계선·포장층, 암 경계선 제어 버튼. * * `_UI_Style_Cross.css`가 700줄을 넘겨, 도면 뼈대(섹션·카드·차트·줌/팬)와 * 그 위에 얹는 면적 표기 계열을 갈랐다. 색은 모두 theme.css 토큰만 쓴다. * ========================================================================== */ -/* 절·성토 면적 오버레이(E-4) — 그래프 **좌측 상단**(축선 바로 안쪽), 배경색으로 그래프 - 선과 겹쳐도 가독. 절토/성토 × EA·RR·BR·계 표라서 칩을 늘어놓을 때보다 가로 폭을 덜 먹는다. - 가운데(left:50%)에 두던 것을 좌측으로만 옮겼다 — 세로 자리는 그대로(2026-08-23 사용자 지시). - 58px = CROSS_PAD.left(Y축 눈금 띠 폭) — 표가 플롯 왼쪽 끝에 맞춰 선다. - 글자 = 그림 칸(컨테이너) 폭 비례(173-3 · 3열 ≈ 0.72rem) · 표 높이 변수도 같은 식 — - 조정창 · 보라 치수가 표 아래에서 시작(`_Cross_Controls`). */ +/* 그림 칸 글자 = 칸(컨테이너) 폭 비례(173-3). 카드 좌상 면적표는 걷음 — 값은 상세 모달 표(379-2). */ .b06-cross-card__chart-wrap { --b06-areas-font: clamp(0.6rem, 0.55rem + 0.7cqw, 0.9rem); - --b06-areas-height: calc(var(--b06-areas-font) * 5); -} - -.b06-cross-card__areas { - position: absolute; - top: var(--spacing-8); - left: 58px; - transform: none; - padding: 2px 6px; - border-radius: var(--radius-inputs); - background: color-mix(in srgb, var(--color-surface) 88%, transparent); - font-size: var(--b06-areas-font); - font-family: var(--font-mono); - white-space: nowrap; - border-collapse: collapse; - pointer-events: none; -} - -.b06-cross-card__areas th, -.b06-cross-card__areas td { - padding: 0 0.45em; - text-align: center; - font-weight: var(--font-weight-regular); -} - -/* 4열부터 「계」만(173-3) — EA · RR · BR 칸(머리 · 본문 2~4째)을 접음 · 열 수 = 그리드 data-columns */ -.b06-section__grid:is([data-columns="4"], [data-columns="5"], [data-columns="6"]) - .b06-cross-card__areas - :is(th, td):nth-child(n + 2):nth-child(-n + 4) { - display: none; -} - -/* 열 제목은 가운데 맞춤 — 값은 우측 정렬이라 자릿수가 흔들려도 머리글은 열 중앙에 선다. */ -.b06-cross-card__areas thead th { - text-align: center; - color: var(--color-text-muted); -} - -/* 행 이름(절토/성토)은 왼쪽 정렬 — 숫자 열과 구분된다. */ -.b06-cross-card__areas tbody th { - text-align: left; -} - -/* 면적 표기 색은 **테마 토큰만** 쓴다. 고정 RGB를 박으면 다크 테마에서 글자가 배경에 - 묻힌다(발파암에 쓰던 검정이 그랬다). 차트 팔레트는 밝기가 두 테마 모두에 맞춰져 있다. */ -.b06-design__area--cut, -.b06-design__area--cut_total { - color: var(--color-danger); -} - -/* 절토 내역 — 토사(EA), 리핑암(RR), 발파암(BR)을 색으로 갈라 둔다. */ -.b06-design__area--cut_soil { - color: var(--color-chart-2); -} - -/* RR은 `--color-slate`를 쓰면 안 된다 — 그 토큰이 곧 `--color-text-secondary`라 - 라이트 테마에서 회색 글자가 "비활성"으로 읽히고, 28% 밴드는 흰 배경에 묻힌다. - `--color-warning`도 못 쓴다(암 경계선 점선이 이미 그 색이라 밴드가 제 경계선과 섞인다). */ -.b06-design__area--cut_rr { - color: var(--color-success); -} - -.b06-design__area--cut_br { - color: var(--color-chart-3); -} - -.b06-design__area--fill { - color: var(--color-chart-0); -} - -/* 사토장 — 성토와 **다른 색**으로 둔다. 같은 색이면 표에서 한 덩어리로 읽힌다. */ -.b06-design__area--spoil-fill { - color: #6d7a20; -} - -.b06-design__area--unset { - color: var(--color-text-muted); -} - -/* 선택된 카드에서만 값 칸이 버튼이 된다 — 부모가 pointer-events: none이라 여기서 되살린다. */ -.b06-cross-card__areas button { - padding: 0 2px; - border: none; - border-radius: var(--radius-inputs); - background: none; - color: inherit; - font-family: inherit; - font-size: inherit; - cursor: pointer; - pointer-events: auto; -} - -/* 켠 칸은 글자색을 유지한 채 같은 색으로 옅게 칠하고 테두리를 둘러 대비를 살린다. */ -.b06-cross-card__areas button.is-active { - background: color-mix(in srgb, currentcolor 18%, transparent); - box-shadow: inset 0 0 0 1px currentcolor; - font-weight: var(--font-weight-medium); } /* 면적 강조 밴드 — 평소엔 클릭 대상으로만 남고, 켜질 때만 채워진다. */ diff --git a/B06_Section/B06_Section_UI_Style_Cross_Controls.css b/B06_Section/B06_Section_UI_Style_Cross_Controls.css index ac2a795b3..25eb1c938 100644 --- a/B06_Section/B06_Section_UI_Style_Cross_Controls.css +++ b/B06_Section/B06_Section_UI_Style_Cross_Controls.css @@ -4,15 +4,13 @@ * 넘칠 만큼 길어지면 창 안에서 스크롤한다. z-index는 카드 안 오버레이 중 최상단. */ .b06-structure-panel { position: absolute; - /* 좌측 상단에는 절·성토 면적표가 이미 서 있다 — 조정창을 같은 자리에 두면 표를 덮어 - 수치가 안 보인다(2026-09-12 사용자). 표 높이(머리글+절토+성토 세 줄)만큼 내려 시작한다. - 아래를 기준으로 붙이지 않는 까닭은 종전 그대로다 — 낮은 횡단도에서 창이 잘린다. */ - top: calc(var(--spacing-8) + var(--b06-areas-height, 3.6rem)); + /* 좌측 상단 면적표를 걷어(379-2) 위에서 바로 시작. 아래 기준이 아닌 까닭 = 낮은 횡단도에서 잘림. */ + top: var(--spacing-8); /* Y축·눈금 라벨 띠(CROSS_PAD.left)를 덮지 않게 그림 영역 안쪽에서 시작한다. */ left: calc(var(--b06-plot-left, 58px) + var(--spacing-8)); z-index: 20; display: flex; - max-height: calc(100% - 2 * var(--spacing-8) - var(--b06-areas-height, 3.6rem)); + max-height: calc(100% - 2 * var(--spacing-8)); flex-direction: column; gap: 2px; padding: var(--spacing-8); diff --git a/resources/tester/test_173_areas_detail.py b/resources/tester/test_173_areas_detail.py index f7a695ac6..8b60b99d1 100644 --- a/resources/tester/test_173_areas_detail.py +++ b/resources/tester/test_173_areas_detail.py @@ -1,6 +1,6 @@ """PLAN 173-3 · 173-4 — B06 횡단 카드 면적표 열 연동 · [상세] 그림 테마 색 · 칸 가득. -짝: `B06_Section/B06_Section_UI_Style_Cross_Areas.css`(글자 = 그림 칸 폭 · 4열부터 「계」만) · +짝: `B06_Section/B06_Section_UI_Style_Cross_Areas.css`(글자 = 그림 칸 폭 · 379-2 카드 면적표 걷음) · `_UI_Section_View.ts`(그리드 data-columns · `detailChart`) · `_UI_Cross_Detail.ts`(칸 크기로 새로 그림) · `_UI_Style_Cross_Detail.css`(테마 토큰) · `_UI_Cross_View_Metrics.ts` `fitPlotBase`(Node 헬퍼 `helper_173_detail_fit.cjs` 가 실제 TS 를 돌림). @@ -10,7 +10,6 @@ from __future__ import annotations import json import os -import re import subprocess import pytest @@ -40,16 +39,14 @@ def fit() -> dict: return json.loads(proc.stdout) -# ── 173-3 면적표 ───────────────────────────────────────────── +# ── 173-3 그림 칸 글자 · 379-2 카드 좌상 면적표 걷음 ───────────────── -def test_면적표_글자_그림_칸_폭_비례_높이_변수_같은_식(): +def test_그림_칸_글자_폭_비례_남김(): css = _read("B06_Section_UI_Style_Cross_Areas.css") wrap = css.split(".b06-cross-card__chart-wrap {", 1)[1].split("}", 1)[0] assert "--b06-areas-font: clamp(0.6rem, 0.55rem + 0.7cqw, 0.9rem);" in wrap - assert "--b06-areas-height: calc(var(--b06-areas-font) * 5);" in wrap - table = css.split(".b06-cross-card__areas {", 1)[1].split("}", 1)[0] - assert "font-size: var(--b06-areas-font);" in table + assert "font-size: var(--b06-areas-font);" in css # 남은 쓰는 곳 assert "font-size: 0.72rem" not in css # 3열 그림 칸 ≈ 400 px → 지금 글자(0.72rem)와 거의 같음 · 1열 · 6열은 끝값 @@ -60,16 +57,18 @@ def test_면적표_글자_그림_칸_폭_비례_높이_변수_같은_식(): assert rem(1232) == 0.9 and rem(192) == pytest.approx(0.634) -def test_면적표_4열부터_계만_접기(): +def test_카드_좌상_면적표_걷음_조정창은_위에서(): + """379-2 — 카드 좌상 면적표 지움 · 조정창 top = spacing-8 · 모달 표는 그대로.""" css = _read("B06_Section_UI_Style_Cross_Areas.css") - rule = re.search( - r'\.b06-section__grid:is\(\[data-columns="4"\], \[data-columns="5"\], \[data-columns="6"\]\)\s+' - r"\.b06-cross-card__areas\s+:is\(th, td\):nth-child\(n \+ 2\):nth-child\(-n \+ 4\) \{\n display: none;", - css, - ) - assert rule, "4~6열 EA · RR · BR 접기 규칙 없음" - src = _read("B06_Section_UI_Section_View.ts") - assert "grid.dataset.columns = String(cols);" in src # 실제 그린 열 수(휴대폰 폭 = 1 · 기기대응) + assert "b06-cross-card__areas" not in css and "--b06-areas-height" not in css + assert "buildAreaReadout" not in _read("B06_Section_UI_Cross_Areas.ts") + view = _read("B06_Section_UI_Cross_View.ts") + assert "buildAreaReadout" not in view and "setChipActive" not in view + controls = _read("B06_Section_UI_Style_Cross_Controls.css") + panel = controls.split(".b06-structure-panel {", 1)[1].split("}", 1)[0] + assert "top: var(--spacing-8);" in panel and "--b06-areas-height" not in controls + table = os.path.join(ROOT, "B07_DesignDetail", "B07_DesignDetail_Engine_Cad_Table.py") + assert os.path.isfile(table) # 모달 표 그대로 # ── 173-4 [상세] 그림 ──────────────────────────────────────── diff --git a/ui_template/ui_template_locale_b2.ts b/ui_template/ui_template_locale_b2.ts index 9240f1b4a..796f13715 100644 --- a/ui_template/ui_template_locale_b2.ts +++ b/ui_template/ui_template_locale_b2.ts @@ -424,23 +424,9 @@ export const ui_locales_b2 = { B06_Design_Ditch_Legend: ["측구위치", "Ditch side"], B06_Design_Ditch_Left: ["좌", "Left"], B06_Design_Ditch_Right: ["우", "Right"], - B06_Design_Cut_Area: ["절토", "Cut"], /* 절토 내역 — 지표면~암반 경계선이 토사, 그 아래가 암반(합=절토). */ B06_Design_Cut_Soil_Area: ["절토(토사)", "Cut (soil)"], B06_Design_Cut_Rock_Area: ["절토(암반)", "Cut (rock)"], - /* 횡단 면적표 열 이름은 유토곡선 도면 표기를 그대로 쓴다(EA 토사 / RR 리핑암 / BR 발파암). */ - B06_Design_Area_EA: ["EA", "EA"], - B06_Design_Area_RR: ["RR", "RR"], - B06_Design_Area_BR: ["BR", "BR"], - B06_Design_Area_Total: ["계", "Total"], - /* 단위는 값 칸마다 붙이지 않고 표 좌상단(행제목 × 열제목 교차) 칸에 한 번만 적는다. */ - B06_Design_Area_Unit: ["㎡", "㎡"], - B06_Design_Area_Highlight: ["누르면 해당 면적을 강조합니다", "Click to highlight this area"], - B06_Design_Fill_Area: ["성토", "Fill"], - // 사토장(유용토운반작업장) — **성토와 갈라 보인다**. 합치면 「쌓기」가 갑자기 커 보여 - // 사람이 오해한다(2026-09-09 네 창 확정 ㉠). - B06_Design_SpoilFill_Area: ["사토장", "Spoil site"], - B06_Design_Unset: ["미지정", "Not set"], B06_Design_DitchType_Legend: ["측구형식", "Ditch type"], B06_Design_DitchType_Standard: ["일반", "Standard"], B06_Design_DitchType_LType: ["L형", "L-type"],