From 9bcd8483af1d40990e0418491a704fff48a8c83d Mon Sep 17 00:00:00 2001 From: umsangdon Date: Sun, 1 Nov 2026 14:58:52 +0900 Subject: [PATCH] =?UTF-8?q?feat(710-1):=20M01=20=EB=8B=A8=EA=B0=80?= =?UTF-8?q?=EC=82=B0=EC=B6=9C=20=EC=83=81=EC=84=B8=20=EC=97=B4=20=E2=80=94?= =?UTF-8?q?=20=EC=9D=B4=EB=A6=84=20=C2=B7=20=EC=88=98=EB=9F=89=20=C2=B7=20?= =?UTF-8?q?=EB=8B=A8=EC=9C=84=20=C2=B7=20=EB=A1=9C=EC=A7=81=20=C2=B7=20?= =?UTF-8?q?=EB=8B=A8=EA=B0=80=20=C2=B7=20=EA=B8=88=EC=95=A1=20=C2=B7=20?= =?UTF-8?q?=EB=8B=A8=EA=B0=80=201=20=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 수량 = 계산 답 고른 수량(% 덧줄은 율) · 계산 전 「—」 - 로직 열 = 옛 수량 칸 식 알약(단가 왼쪽) - 단가 2 행 = 표 칸 돈 꼴 block 흠 — td 는 칸 그대로 Co-Authored-By: Claude Opus 5.5 --- .../M01_MasterData_UI_LogicLab_Detail.ts | 20 ++++++++++++++----- .../M01_MasterData_UI_LogicLab_Style.css | 15 +++++++++----- .../M01_MasterData_UI_LogicLab_Text.ts | 1 + .../M01_MasterData_UI_Logic_Style.css | 5 +++++ 4 files changed, 31 insertions(+), 10 deletions(-) diff --git a/M01_MasterData/M01_MasterData_UI_LogicLab_Detail.ts b/M01_MasterData/M01_MasterData_UI_LogicLab_Detail.ts index dda7aab44..023fc34d0 100644 --- a/M01_MasterData/M01_MasterData_UI_LogicLab_Detail.ts +++ b/M01_MasterData/M01_MasterData_UI_LogicLab_Detail.ts @@ -17,7 +17,8 @@ import type { TextLine, TextPiece, } from "./M01_MasterData_UI_Logic_Api"; -import { buildEditor, qtyKind } from "./M01_MasterData_UI_Logic_Edit"; +import { pctView } from "./M01_MasterData_UI_Logic_Api"; +import { buildEditor, formatNumber, qtyKind } from "./M01_MasterData_UI_Logic_Edit"; import { formatMoney, formatPrice } from "./M01_MasterData_UI_Logic_Money"; import { openPicker } from "./M01_MasterData_UI_Logic_Pick"; import { safeReason, tx } from "./M01_MasterData_UI_Logic_Text"; @@ -97,6 +98,8 @@ interface Entry { spec: string; unit: string; qty: string; + /** 고른 수량 값(계산 답 `CalcLine.수량` · % 덧줄은 율) — 계산 전 「—」 */ + qtyValue: string; qtyTag: string; qtyFrag: Fragment[]; /** 한 줄이 비목 몫으로 갈렸을 때 이 묶음의 몫 이름(예 「노무비」) */ @@ -214,6 +217,9 @@ function infoBox(ctx: DetailContext): HTMLElement { ]); } +/** 수량 칸 = 계산 답의 고른 수량(% 덧줄은 율) · 계산 전 「—」 */ +const qtyOf = (line?: CalcLine): string => (line ? formatNumber(pctView(line).qty) : "—"); + /** 계산된 줄은 서버가 준 비목별 몫으로 묶음에 나눠 넣음 — 로직을 부르는 줄도 노무비·재료비·경비로 갈림 */ const spread = (e: Entry, line?: CalcLine): Entry[] => { const parts = Object.entries(line?.비목 ?? {}).filter(([, v]) => v !== 0); @@ -249,6 +255,7 @@ function entries(ctx: DetailContext): Entry[] { spec: item.규격 ?? brief?.규격 ?? "", unit: item.단위 ?? "", qty: item.수량, + qtyValue: qtyOf(line), qtyTag: qtyKind(item.수량) === tx("Ho_QtyTable") ? tl("Tag_Table") : qtyKind(item.수량), qtyFrag: [{ text: item.수량 }], price: price === undefined || price === null ? "" : formatPrice(price), @@ -278,8 +285,9 @@ function entries(ctx: DetailContext): Entry[] { group: OF_COST[extra.비목 ?? ""] ?? "other", name: extra.이름, spec: "", - unit: "", + unit: line ? pctView(line).unit : "", qty: extra.식, + qtyValue: qtyOf(line), qtyTag: tl("Extra"), qtyFrag: [{ text: extra.식 }], price: "", @@ -356,6 +364,7 @@ function lineRow(e: Entry): HTMLElement { ...(e.warn ? [createBadge(`${tx("Calc_UnitWarn")} · ${e.warn}`, "warning")] : []), ], }), + cellOf(e.qtyValue, "m01-logic__money"), cellOf(e.unit), el("td", { className: "m01lab__qty-cell", @@ -375,7 +384,7 @@ function groupTable(group: Group, mine: Entry[], calculated: boolean): HTMLEleme const empty = el("tr", { children: [ el("td", { - attrs: { colspan: "5" }, + attrs: { colspan: "6" }, className: "ui-text ui-text--muted", text: tl("Empty_Group"), }), @@ -385,14 +394,15 @@ function groupTable(group: Group, mine: Entry[], calculated: boolean): HTMLEleme className: "m01lab__subtotal", attrs: { "data-group": group, "data-subtotal": calculated ? String(sub) : "" }, children: [ - el("td", { attrs: { colspan: "4" }, text: `${groupName(group)} ${tl("Subtotal")}` }), + el("td", { attrs: { colspan: "5" }, text: `${groupName(group)} ${tl("Subtotal")}` }), cellOf(calculated ? formatMoney(sub) : "—", "m01-logic__money"), ], }); const headers = [ tl("Col_Name"), - tl("Col_Unit"), tl("Col_Qty"), + tl("Col_Unit"), + tl("Col_Logic"), tl("Col_Price"), tl("Col_Amount"), ]; diff --git a/M01_MasterData/M01_MasterData_UI_LogicLab_Style.css b/M01_MasterData/M01_MasterData_UI_LogicLab_Style.css index 41e4c4ad9..e9779d7e2 100644 --- a/M01_MasterData/M01_MasterData_UI_LogicLab_Style.css +++ b/M01_MasterData/M01_MasterData_UI_LogicLab_Style.css @@ -45,20 +45,25 @@ table-layout: fixed; } +/* 열 = 이름 · 수량 · 단위 · 로직 · 단가 · 금액 */ .m01lab__ho th:nth-child(1) { - width: 26%; + width: 22%; } .m01lab__ho th:nth-child(2) { - width: 8%; + width: 9%; } .m01lab__ho th:nth-child(3) { - width: 40%; + width: 7%; } -.m01lab__ho th:nth-child(4), -.m01lab__ho th:nth-child(5) { +.m01lab__ho th:nth-child(4) { + width: 36%; +} + +.m01lab__ho th:nth-child(5), +.m01lab__ho th:nth-child(6) { width: 13%; } diff --git a/M01_MasterData/M01_MasterData_UI_LogicLab_Text.ts b/M01_MasterData/M01_MasterData_UI_LogicLab_Text.ts index 60c643139..5baa2b5d1 100644 --- a/M01_MasterData/M01_MasterData_UI_LogicLab_Text.ts +++ b/M01_MasterData/M01_MasterData_UI_LogicLab_Text.ts @@ -40,6 +40,7 @@ const TEXT = { Col_Name: ["이름", "Name"], Col_Unit: ["단위", "Unit"], Col_Qty: ["수량", "Quantity"], + Col_Logic: ["로직", "Logic"], Col_Price: ["단가", "Price"], Col_Amount: ["금액", "Amount"], Empty_Group: ["줄 없음", "No lines"], diff --git a/M01_MasterData/M01_MasterData_UI_Logic_Style.css b/M01_MasterData/M01_MasterData_UI_Logic_Style.css index 75bcf7ec2..5d5a9e7ef 100644 --- a/M01_MasterData/M01_MasterData_UI_Logic_Style.css +++ b/M01_MasterData/M01_MasterData_UI_Logic_Style.css @@ -211,6 +211,11 @@ white-space: nowrap; } +/* 표 칸은 칸 그대로 — block 이면 이웃 칸이 한 칸에 위아래로 쌓임(단가 2 행) */ +td.m01-logic__money { + display: table-cell; +} + /* 목록 「별칭」 칸(208-1) — 칸 안 글 상자 · 테두리는 올렸을 때만 */ .m01-logic__alias { width: 160px;