Merge remote-tracking branch 'origin/sub_laptop_2' into sub_laptop_7

This commit is contained in:
2026-11-01 15:08:49 +09:00
4 changed files with 31 additions and 10 deletions
@@ -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"),
];
@@ -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%;
}
@@ -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"],
@@ -211,6 +211,11 @@
white-space: nowrap;
}
/* 표 칸은 칸 그대로 — block 이면 이웃 칸이 한 칸에 위아래로 쌓임(단가 2 행) */
td.m01-logic__money {
display: table-cell;
}
/* 목록 「별칭」 칸(208-1) — 칸 안 글 상자 · 테두리는 올렸을 때만 */
.m01-logic__alias {
width: 160px;