Merge remote-tracking branches 'origin/sub_desktop_1', 'origin/sub_laptop_2', 'origin/sub_laptop_4' and 'origin/sub_laptop_7' into main_laptop_1
This commit is contained in:
@@ -107,6 +107,19 @@
|
||||
background: color-mix(in srgb, var(--color-lavender-wash) 14%, var(--color-canvas));
|
||||
}
|
||||
|
||||
/* 구조물 조합 일위대가 합계 칸(101-1) — 초록 모두 반영 · 노랑 일부 빠짐 · 붉음 기준 단가 안 나옴(설계값·계산 칸보다 진함) */
|
||||
.ui-sheet__table td.is-sum-ok {
|
||||
background: color-mix(in srgb, var(--color-success) 26%, var(--color-canvas));
|
||||
}
|
||||
|
||||
.ui-sheet__table td.is-sum-short {
|
||||
background: color-mix(in srgb, var(--color-warning) 34%, var(--color-canvas));
|
||||
}
|
||||
|
||||
.ui-sheet__table td.is-sum-error {
|
||||
background: color-mix(in srgb, var(--color-danger) 28%, var(--color-canvas));
|
||||
}
|
||||
|
||||
.ui-sheet--project .ui-sheet__table tbody td.is-locked {
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
@@ -141,6 +154,43 @@
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
/* 구조물 조합 — 고른 열의 머리 칸 + 합계 칸을 한 상자로(머리 아래 · 합계 위 변 없음 = 중간선 없음) */
|
||||
.ui-sheet--combo .ui-sheet__table:has(tr.ui-sheet__meta td.is-selected) th.is-head-picked {
|
||||
border-bottom-width: 0;
|
||||
outline: 0;
|
||||
box-shadow:
|
||||
inset 2px 0 0 var(--color-focus-ring),
|
||||
inset -2px 0 0 var(--color-focus-ring),
|
||||
inset 0 2px 0 var(--color-focus-ring);
|
||||
}
|
||||
|
||||
.ui-sheet--combo .ui-sheet__table tr.ui-sheet__meta td.is-selected {
|
||||
outline: 0;
|
||||
box-shadow:
|
||||
inset 2px 0 0 var(--color-focus-ring),
|
||||
inset -2px 0 0 var(--color-focus-ring),
|
||||
inset 0 -2px 0 var(--color-focus-ring);
|
||||
}
|
||||
|
||||
/* 틀고정 칸의 오른쪽 선 그림자(:87-91)와 합침 */
|
||||
.ui-sheet--combo
|
||||
.ui-sheet__table:has(tr.ui-sheet__meta td.is-selected)
|
||||
th.is-head-picked.is-frozen {
|
||||
box-shadow:
|
||||
inset 2px 0 0 var(--color-focus-ring),
|
||||
inset -2px 0 0 var(--color-focus-ring),
|
||||
inset 0 2px 0 var(--color-focus-ring),
|
||||
1px 0 0 var(--color-border);
|
||||
}
|
||||
|
||||
.ui-sheet--combo .ui-sheet__table tr.ui-sheet__meta td.is-selected.is-frozen {
|
||||
box-shadow:
|
||||
inset 2px 0 0 var(--color-focus-ring),
|
||||
inset -2px 0 0 var(--color-focus-ring),
|
||||
inset 0 -2px 0 var(--color-focus-ring),
|
||||
1px 0 0 var(--color-border);
|
||||
}
|
||||
|
||||
.ui-sheet__table tr.is-fixed td {
|
||||
border-bottom: 2px solid var(--color-border);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
addLevel,
|
||||
deleteColumn,
|
||||
isBlankPick,
|
||||
KEY_SUM,
|
||||
KEY_UNIT,
|
||||
navRows,
|
||||
PICK_ROWS,
|
||||
@@ -61,6 +62,8 @@ export interface SheetOptions {
|
||||
areaLabel?: (colId: string) => string;
|
||||
/** 구조물 조합 표(`combo`) 「일위대가 합계」 줄 칸 글 — 주면 읽기 전용 줄이 생김(86-3). */
|
||||
laborSumLabel?: (colId: string) => string;
|
||||
/** 합계 칸 색 상태 · 툴팁 까닭(101-1) — `state` = ok · short · error · 없으면 색 없음. */
|
||||
laborSumState?: (colId: string) => { state: string; why: string } | undefined;
|
||||
/** 칸을 고름 — 누르기 · 방향키 · Tab. */
|
||||
onSelect?: (sel: SheetSelection) => void;
|
||||
/** 조회 후 선택 — master 일위대가 · 도면 · 면적산출 칸을 두 번 누르기 · Enter · F2 로 부름.
|
||||
@@ -93,6 +96,7 @@ export function createSheet(host: HTMLElement, input: SheetDoc, opts: SheetOptio
|
||||
drawingLabel: opts.drawingLabel,
|
||||
areaLabel: opts.areaLabel,
|
||||
laborSumLabel: opts.laborSumLabel,
|
||||
laborSumState: opts.laborSumState,
|
||||
pick: !!opts.onPick,
|
||||
headLocked: !!opts.lockHead,
|
||||
combo: !!opts.combo,
|
||||
@@ -186,7 +190,10 @@ export function createSheet(host: HTMLElement, input: SheetDoc, opts: SheetOptio
|
||||
state.result = recalcSheet(state.doc);
|
||||
const { scrollLeft, scrollTop } = scroll;
|
||||
scroll.replaceChildren(renderSheet(state));
|
||||
if (opts.combo && state.sel) deepestHead(state.sel.c)?.classList.add("is-head-picked");
|
||||
if (opts.combo && state.sel) {
|
||||
deepestHead(state.sel.c)?.classList.add("is-head-picked");
|
||||
markSum(state.sel.c);
|
||||
}
|
||||
scroll.scrollLeft = scrollLeft;
|
||||
scroll.scrollTop = scrollTop;
|
||||
syncToolbar();
|
||||
@@ -212,6 +219,10 @@ export function createSheet(host: HTMLElement, input: SheetDoc, opts: SheetOptio
|
||||
}
|
||||
return best;
|
||||
};
|
||||
/** 구조물 조합 — 머리를 고르면 그 열 합계 칸도 늘 같이 고름 표시(101-2) */
|
||||
const markSum = (colId: string): void => {
|
||||
for (const cell of cellsAt(KEY_SUM, colId)) cell.classList.add("is-selected");
|
||||
};
|
||||
const select = (r: string, c: string, reveal = false): void => {
|
||||
for (const cell of scroll.querySelectorAll(".is-selected, .is-head-picked"))
|
||||
cell.classList.remove("is-selected", "is-head-picked");
|
||||
@@ -220,6 +231,7 @@ export function createSheet(host: HTMLElement, input: SheetDoc, opts: SheetOptio
|
||||
head?.classList.add("is-head-picked");
|
||||
const cells = cellsAt(r, c);
|
||||
for (const cell of cells) cell.classList.add("is-selected");
|
||||
if (opts.combo) markSum(c);
|
||||
if (reveal) (cells[0] ?? head)?.scrollIntoView({ block: "nearest", inline: "nearest" });
|
||||
syncToolbar();
|
||||
opts.onSelect?.(selectionOf(state.doc, r, c));
|
||||
|
||||
@@ -46,6 +46,8 @@ export interface RenderState {
|
||||
areaLabel?: (colId: string) => string;
|
||||
/** 구조물 조합 표 「일위대가 합계」 줄 칸 글 — 주면 combo 표에 읽기 전용 줄이 생김(86-3). */
|
||||
laborSumLabel?: (colId: string) => string;
|
||||
/** 합계 칸 색 상태 · 툴팁 까닭(101-1) */
|
||||
laborSumState?: (colId: string) => { state: string; why: string } | undefined;
|
||||
/** 조회 후 선택 줄(`PICK_ROWS`)을 고름으로 받나 — 칸 겉모양만. */
|
||||
pick?: boolean;
|
||||
/** 머리 · 층 이름을 못 고침(`lockHead`) — 칸 겉모양만. */
|
||||
@@ -194,6 +196,14 @@ export function renderSheet(state: RenderState): HTMLElement {
|
||||
const text = blank ? "" : refText(state, key, col.id); // 마스터 줄 = 모두 번호 글
|
||||
const td = bodyCell(key, col, j, text);
|
||||
td.classList.remove("is-num");
|
||||
if (key === KEY_SUM) {
|
||||
td.classList.remove("is-calc", "is-bound", "is-hand"); // 합계 칸은 열 꼴 색 없음 — 상태 색만
|
||||
const sum = blank ? undefined : state.laborSumState?.(col.id);
|
||||
if (sum) {
|
||||
td.classList.add(`is-sum-${sum.state}`);
|
||||
td.title = sum.why;
|
||||
}
|
||||
}
|
||||
if (state.pick && PICK_ROWS.includes(key) && !blank) td.classList.add("is-pick");
|
||||
tr.append(td);
|
||||
});
|
||||
|
||||
@@ -242,16 +242,16 @@ export const ui_locales_b2 = {
|
||||
B06_Cross_Width_Inc: ["표시 반폭 1m 늘리기", "Widen view width by 1m"],
|
||||
B06_Cross_Width_Reset: ["전역 반폭으로 초기화", "Reset to global width"],
|
||||
B06_Cross_Revet_Select: [
|
||||
"기슭막이 선택 — 화살표로 자리 조절",
|
||||
"흙막이 선택 — 화살표로 자리 조절",
|
||||
"Select revetment — nudge with arrows",
|
||||
],
|
||||
B06_Cross_Revet_Label: ["기슭막이", "Revetment"],
|
||||
B06_Cross_Revet_Label: ["흙막이", "Revetment"],
|
||||
B06_Cross_Revet_Close: ["조정창 닫기", "Close adjuster"],
|
||||
B06_Cross_Revet_Left: ["왼쪽으로 — 관 길이 1m 단위", "Move left — 1m of pipe length"],
|
||||
B06_Cross_Revet_Right: ["오른쪽으로 — 관 길이 1m 단위", "Move right — 1m of pipe length"],
|
||||
B06_Cross_Revet_Reset: ["기슭막이 자동 자리로 초기화", "Reset revetment to solved position"],
|
||||
B06_Cross_Revet_Inlet: ["기슭막이(유입)", "Revetment (inlet)"],
|
||||
B06_Cross_Revet_Outlet: ["기슭막이(유출)", "Revetment (outlet)"],
|
||||
B06_Cross_Revet_Reset: ["흙막이 자동 자리로 초기화", "Reset revetment to solved position"],
|
||||
B06_Cross_Revet_Inlet: ["흙막이(유입)", "Revetment (inlet)"],
|
||||
B06_Cross_Revet_Outlet: ["흙막이(유출)", "Revetment (outlet)"],
|
||||
/* 배관과 무관한 독립 기슭막이(구조물 정본 D군) — 2026-08-28. */
|
||||
B06_Cross_Revet_Own: ["기슭막이(독립)", "Revetment (standalone)"],
|
||||
/* 세월교 · BOX암거 유입 · 유출 흙막이 조정창(79b). */
|
||||
@@ -259,7 +259,7 @@ export const ui_locales_b2 = {
|
||||
B06_Cross_Guard_Outlet: ["흙막이(유출)", "Retaining wall (outlet)"],
|
||||
B06_Cross_Struct_Label: ["구조물 형식", "Structure type"],
|
||||
// 조정창 제목은 "기슭막이(…)" 한 형식으로 통일한다(2026-08-29 사용자). {n} = 단 번호.
|
||||
B06_Cross_Revet_Extra: ["기슭막이(추가 {n})", "Revetment (extra {n})"],
|
||||
B06_Cross_Revet_Extra: ["흙막이(추가 {n})", "Revetment (extra {n})"],
|
||||
B06_Cross_Revet_Up: ["사면 위로(대각) 1m", "Up along fill slope 1m"],
|
||||
B06_Cross_Revet_Down: ["사면 아래로(대각) 1m", "Down along fill slope 1m"],
|
||||
B06_Cross_Revet_Limit_Up: [
|
||||
@@ -283,7 +283,7 @@ export const ui_locales_b2 = {
|
||||
B06_Cross_Mat_Dry: ["메쌓기", "Dry masonry"],
|
||||
B06_Cross_Mat_Wet: ["찰쌓기", "Wet masonry"],
|
||||
B06_Cross_Mat_Concrete: ["콘크리트", "Concrete"],
|
||||
B06_Cross_Extra_Count: ["추가 기슭막이(단)", "Extra revetments"],
|
||||
B06_Cross_Extra_Count: ["추가 흙막이(단)", "Extra revetments"],
|
||||
B06_Cross_Extra_Add: ["한 단 추가", "Add one tier"],
|
||||
B06_Cross_Extra_Equalize: [
|
||||
"다단 등간격 배치 — 사면 구간을 같게",
|
||||
@@ -291,17 +291,17 @@ export const ui_locales_b2 = {
|
||||
],
|
||||
B06_Cross_Extra_Remove: ["한 단 삭제", "Remove one tier"],
|
||||
B06_Cross_Struct_Auto: ["자동(규칙)", "Auto (by rule)"],
|
||||
B06_Cross_Struct_Revet: ["기슭막이+배관", "Revetment + pipe"],
|
||||
B06_Cross_Struct_Revet: ["흙막이+배관", "Revetment + pipe"],
|
||||
B06_Cross_Struct_I: ["집수정 I형", "Catch basin — I"],
|
||||
B06_Cross_Struct_L: ["집수정 ㄴ형", "Catch basin — L"],
|
||||
B06_Cross_Struct_U: ["집수정 ㄷ형", "Catch basin — U"],
|
||||
B06_Cross_Struct_InletBasin: ["유입 집수정", "Inlet catch basin"],
|
||||
B06_Cross_Revet_Limit_Inward: [
|
||||
"기슭막이 안쪽 한계 — 노견(도로) 안쪽으로는 들어갈 수 없습니다.",
|
||||
"흙막이 안쪽 한계 — 노견(도로) 안쪽으로는 들어갈 수 없습니다.",
|
||||
"Revetment inner limit — cannot move inside the road shoulder.",
|
||||
],
|
||||
B06_Cross_Revet_Limit_Outward: [
|
||||
"기슭막이 바깥 한계 — 조정 범위를 벗어나 더 밀 수 없습니다.",
|
||||
"흙막이 바깥 한계 — 조정 범위를 벗어나 더 밀 수 없습니다.",
|
||||
"Revetment outer limit — cannot push beyond the adjustment range.",
|
||||
],
|
||||
B06_Profile_View_Longitudinal: ["종단면도", "Longitudinal profile"],
|
||||
@@ -345,7 +345,7 @@ export const ui_locales_b2 = {
|
||||
/* 성토사면 경사길이 — 구조물이 사면을 끊기 전 **본래** 길이(2026-09-03 사용자 지시). */
|
||||
B06_Cross_FillSlope: ["성토사면", "Fill slope"],
|
||||
B06_Cross_FillSlope_Tip: [
|
||||
"노견 끝(그 측에 측구가 있으면 측구 바깥)부터 성토 사면이 원지반과 만나는 곳까지의 경사길이입니다. 기슭막이·집수정이 사면을 끊기 전 본래 길이이며, 양측 성토면 좌·우를 함께 적습니다. 5m를 넘으면 옹벽·석축 등이 필요합니다(성토_비탈면 §2). 「≥」는 사면이 계산 반폭 안에서 원지반과 만나지 못해 거기까지만 잰 하한값입니다.",
|
||||
"노견 끝(그 측에 측구가 있으면 측구 바깥)부터 성토 사면이 원지반과 만나는 곳까지의 경사길이입니다. 흙막이·집수정이 사면을 끊기 전 본래 길이이며, 양측 성토면 좌·우를 함께 적습니다. 5m를 넘으면 옹벽·석축 등이 필요합니다(성토_비탈면 §2). 「≥」는 사면이 계산 반폭 안에서 원지반과 만나지 못해 거기까지만 잰 하한값입니다.",
|
||||
"Slant length of the fill slope, from the shoulder edge (outside the ditch if that side has one) to where it meets existing ground. It is the original slope before any revetment or catch basin cuts it short, and both sides are shown when the section is filled on both. Over 5 m a retaining structure is required. A leading ≥ marks a lower bound: the slope never meets ground within the computed half-width, so only that much could be measured.",
|
||||
],
|
||||
B06_MassHaul_CutNatural: ["절토(자연)", "Cut (natural)"],
|
||||
|
||||
Reference in New Issue
Block a user