feat(B06 횡단): 카드 좌상 면적표 지움 — 값은 상세 모달 표 · 조정창 위에서 시작 (379-2)
- 카드 면적 readout(buildAreaReadout · setChipActive) · 그 CSS · 안 쓰게 된 로케일 키 지움 - 구조물 조정창 top = spacing-8(표 높이 띄움 걷음) · 면적 강조 밴드 · 모달 표 그대로 - 시험 test_173 고쳐 씀(표 걷음 · 조정창 자리 · 글자 변수 남김) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014utrjfoW831Vc5wJUd13kL
This commit is contained in:
@@ -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<CrossAreaKey, HTMLElement[]>,
|
||||
): 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<CrossAreaKey, HTMLElement[]>();
|
||||
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));
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -443,7 +443,6 @@ export function buildDesignControls(
|
||||
scheduleReflow(card);
|
||||
|
||||
// 암 경계선 제어는 그래프 X축 제목 행으로 이동(E-7, Cross_View에서 배치).
|
||||
// 절·성토 면적 readout은 그래프 중상단 오버레이로 이동(E-4, Cross_View에서 배치).
|
||||
return { bar, groundSegment };
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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<string>).detail;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/* 면적 강조 밴드 — 평소엔 클릭 대상으로만 남고, 켜질 때만 채워진다. */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 [상세] 그림 ────────────────────────────────────────
|
||||
|
||||
@@ -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"],
|
||||
|
||||
Reference in New Issue
Block a user