feat(m02): 일위대가 옵션 줄 = 구분 · 이름 · 별칭 병합 칸 · 나머지 칸 두 줄 병합(113-1)

- 옵션 글 있는 로직만 위 줄 차례 · 수량산출 · 단위 · 금액 넷 · 순서 칸 rowspan 2 · 옵션 줄 colspan 3
- CSS 아래선 · hover · 고름 띠 · 끌기 아래선 맞춤 · 좁은 칸 그대로
- ui_checks 44-6 기대 colspan 3 · 45-7 rowspan 셈 · card_shell 시험 하나

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W4uKaV4ZBhsJN4GHG7yRj4
This commit is contained in:
2026-10-08 18:22:52 +09:00
co-authored by Claude Opus 5.5
parent 5f64633df3
commit 4defeb529b
5 changed files with 59 additions and 26 deletions
@@ -131,7 +131,8 @@
opacity: 0.5;
}
.m02-labrow tr.is-dragunder td {
.m02-labrow tr.is-dragunder td,
.m02-labrow tr:has(+ tr.m02-labrow__optrow.is-dragunder) > td[rowspan] {
box-shadow: inset 0 -2px 0 var(--color-primary);
}
@@ -157,7 +158,7 @@
font-size: var(--text-caption);
}
/* 옵션 값 줄(44-6) — 이름 ~ 합계에 걸친 한 줄 말줄임(max-width 0 = 표 폭을 안 늘림) · 위 줄과 한 덩이 */
/* 옵션 값 줄(44-6 · 113-1) — 구분 ~ 별칭에 걸친 한 줄 말줄임(max-width 0 = 표 폭을 안 늘림) · 위 줄과 한 덩이 */
.m02-labrow .m02-labrow__optrow td {
padding-top: 0;
padding-bottom: var(--spacing-4);
@@ -173,7 +174,7 @@
text-overflow: ellipsis;
}
.m02-labrow__row:has(+ .m02-labrow__optrow) td {
.m02-labrow__row:has(+ .m02-labrow__optrow) td:not([rowspan]) {
border-bottom: 0;
}
@@ -182,18 +183,18 @@
}
.m02-labrow__optrow.is-open:hover,
.m02-labrow__row.is-open:hover + .m02-labrow__optrow {
.m02-labrow__row.is-open:hover + .m02-labrow__optrow,
.m02-labrow__row.is-open:has(+ .m02-labrow__optrow:hover) {
background: var(--color-mist-violet);
}
/* 고른 줄(47-5) — 옵션 값 줄까지 한 덩이 · 왼쪽 띠 */
/* 고른 줄(47-5) — 옵션 값 줄까지 한 덩이 · 왼쪽 띠(차례 칸 = 두 줄 병합 · 113-1) */
.m02-labrow .m02-labrow__row.is-selected,
.m02-labrow .m02-labrow__optrow.is-selected {
background: var(--color-mist-violet);
}
.m02-labrow__row.is-selected > td:first-child,
.m02-labrow__optrow.is-selected > td:first-child {
.m02-labrow__row.is-selected > td:first-child {
box-shadow: inset 3px 0 0 var(--color-primary);
}
@@ -419,7 +420,6 @@
}
/* 옵션 값 줄 — 한 줄 통째 */
.m02-labrow__optrow .m02-labrow__no,
.m02-labrow__sum .m02-labrow__kind,
.m02-labrow__sum .m02-labrow__alias {
display: none;
@@ -432,7 +432,8 @@
/* 끌기 선(102-2) — 칸마다 말고 줄 카드 하나에 */
.m02-labrow tr.is-dragover td,
.m02-labrow tr.is-dragunder td {
.m02-labrow tr.is-dragunder td,
.m02-labrow tr:has(+ tr.m02-labrow__optrow.is-dragunder) > td[rowspan] {
box-shadow: none;
}
@@ -3,7 +3,8 @@
* 일위대가 담은 로직 표 · 자재목록 표(39-3) — 상세 · 보기 갈래(면적산출 오른쪽 패널 · 카드)가 같이 씀.
* 담은 로직 = 차례 · 구분(키 머리에서 읽음 · 50-4) · 로직(키 · 이름 + 「빈 값 n」 붉게) · 별칭(44-6) · 수량산출(「12.5(B6)」) ·
* 결과 단위 · 금액 칸 넷(노무비 · 재료비 · 경비 · 합계 · 칸마다 위 기준 작게 / 아래 반영) ·
* 옵션 값(「지역 서울 · 규격 25mm」)은 줄 아래 이름 ~ 합계에 걸친 한 줄 · 맨 아래 합계 줄(전체 합계 강조).
* 옵션 값(「지역 서울 · 규격 25mm」)은 줄 아래 구분 ~ 별칭에 걸친 한 줄(나머지 칸은 위 줄과 두 줄 병합 · 113-1) ·
* 맨 아래 합계 줄(전체 합계 강조).
* 자재목록 = 코드 · 이름 · 규격 · 수량산출 · 단위 · 가격 다섯(기준 칸 강조) · 기준단가 / 반영 금액(43-3).
* 금액은 calc 답(없으면 「…」).
* 줄 누름 · 줄 단추는 `on` 이 있을 때만(보기 갈래 = 없음) — 순서 칸 2행(51-14 · 위 [위로] [아래로] / 아래 [옵션] 또는 [수정] · [삭제] ·
@@ -37,8 +38,8 @@ const HEAD: Record<(typeof COSTS)[number], Parameters<typeof tc>[0]> = {
계: "Prev_Sum",
};
/** 옵션 값 줄이 걸치는 칸 수 — 구분 · 이름 · 별칭 · 수량산출 · 결과 단위 · 금액 넷 */
const SPAN = 5 + COSTS.length;
/** 옵션 값 줄이 걸치는 칸 수 — 구분 · 이름 · 별칭(113-1 · 나머지 칸은 위 줄에서 rowspan 2) */
const SPAN = 3;
/** 구분(50-4 · 저장 안 함) — 줄 모양(참조 키 머리)에서 읽음 · SP- = 단가승격 · SC- = 일위조합(50-3) */
export const kindOf = (row: Pick<LaborRow, "로직" | "참조">): string => {
@@ -442,18 +443,20 @@ export function logicTable(data: LogicTableData, on?: RowHandlers): HTMLElement
if (on) tr.addEventListener("click", () => on.open(i));
const subs = sel ? subRows(line, wait, tools) : [];
if (!note) return [tr, ...subs];
// 옵션 값 줄(44-6) — 이름 ~ 합계 칸에 걸친 한 줄(말줄임 · 전체 글은 title) · 행 높이 안 커짐
// 옵션 값 줄(44-6 · 113-1) — 구분 · 이름 · 별칭 칸에 걸친 한 줄(말줄임 · 전체 글은 title) · 행 높이 안 커짐 ·
// 차례 · 수량산출 · 단위 · 금액 넷 · 순서 칸은 위 줄에서 두 줄 병합
for (const td of tr.children)
if (!td.matches(".m02-labrow__kind, .m02-labrow__name, .m02-labrow__alias"))
td.setAttribute("rowspan", "2");
const opt = el("tr", {
className: (on ? "m02-labrow__optrow is-open" : "m02-labrow__optrow") + sel,
attrs: { "data-labor-opt": id },
children: [
el("td", { className: "m02-labrow__no", text: "" }),
el("td", {
className: "m02-labrow__opt",
text: note,
attrs: { colspan: String(SPAN), title: note },
}),
...(tools ? [el("td", { text: "" })] : []),
],
});
if (on) opt.addEventListener("click", () => on.open(i));