From 4eb81f2b7d17bb7d0a5c228d14ae1e110f5aa088 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Thu, 24 Sep 2026 11:54:47 +0900 Subject: [PATCH] =?UTF-8?q?feat(M01):=20=EC=A1=B0=ED=95=A9=20=EB=AF=B8?= =?UTF-8?q?=EB=A6=AC=20=EB=B3=B4=EA=B8=B0=20=EC=9E=90=EB=8F=99=EA=B0=92=20?= =?UTF-8?q?=EC=B1=84=EC=9A=B0=EA=B8=B0=20=C2=B7=20=EA=B2=AC=EB=B3=B8=20?= =?UTF-8?q?=EB=94=B1=EC=A7=80=20=C2=B7=20=EC=97=B4=EC=9E=90=EB=A7=88?= =?UTF-8?q?=EC=9E=90=20=EA=B3=84=EC=82=B0=20=C2=B7=20=EB=B0=94=EA=BE=B8?= =?UTF-8?q?=EB=A9=B4=20=EB=8B=A4=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01JgUhN55Z3BCYhUJTjwTNfj --- .../M01_MasterData_UI_Combo_Preview.ts | 45 ++++++++++++++++--- 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/M01_MasterData/M01_MasterData_UI_Combo_Preview.ts b/M01_MasterData/M01_MasterData_UI_Combo_Preview.ts index b688c479..4955f7df 100644 --- a/M01_MasterData/M01_MasterData_UI_Combo_Preview.ts +++ b/M01_MasterData/M01_MasterData_UI_Combo_Preview.ts @@ -5,10 +5,11 @@ * ========================================================================== */ import { createInputField, createSelectField, el } from "@ui/ui_template_elements"; -import { fetchLogic, type LogicInput } from "./M01_MasterData_UI_Logic_Api"; +import { fetchAuto, fetchLogic, type LogicInput } from "./M01_MasterData_UI_Logic_Api"; import { previewCombo, type Combo } from "./M01_MasterData_UI_Combo_Api"; import { tc, type ComboTextKey } from "./M01_MasterData_UI_Combo_Text"; import { formatMoney } from "./M01_MasterData_UI_Logic_Money"; +import { tx } from "./M01_MasterData_UI_Logic_Text"; const COSTS = ["노무비", "재료비", "경비"] as const; const LABEL: Record<(typeof COSTS)[number], ComboTextKey> = { @@ -29,6 +30,8 @@ function inputCell( input: LogicInput, key: string, values: Record>, + sample: Set, + onEdit: () => void, ): HTMLElement { const mine = (values[key] ??= {}); const value = mine[input.이름] ?? initial(input); @@ -40,8 +43,20 @@ function inputCell( const control = "select" in field ? field.select : field.input; control.value = value; control.setAttribute("data-input", `${key}|${input.이름}`); - control.addEventListener("input", () => (mine[input.이름] = control.value)); - control.addEventListener("change", () => (mine[input.이름] = control.value)); + const tag = sample.has(`${key}|${input.이름}`) + ? el("span", { className: "m01-logic__tag", text: tx("Calc_Sample") }) + : undefined; + if (tag) field.root.append(tag); + const edit = (): void => { + mine[input.이름] = control.value; + sample.delete(`${key}|${input.이름}`); + tag?.remove(); + }; + control.addEventListener("input", edit); + control.addEventListener("change", () => { + edit(); + onEdit(); // 바꾸면 다시 미리 보기 계산 + }); return field.root; } @@ -55,6 +70,9 @@ export function buildPreview(combo: () => Combo): PreviewHandle { const values: Record> = {}; /** 서버가 받을 꼴 — 원래 숫자·고르기 값으로 되돌림 */ const inputs = new Map(); + /** 견본(자동값)으로 채운 칸 `로직|입력` — 사용자가 고치면 빠짐 · 로직마다 자동값은 한 번만 받음 */ + const sample = new Set(); + const asked = new Set(); const form = el("div", { className: "m01-logic__stack" }); const out = el("div", { className: "m01-master__grid-wrap", @@ -131,7 +149,18 @@ export function buildPreview(combo: () => Combo): PreviewHandle { inputs.clear(); for (const row of combo().담은로직) { try { - const one = await fetchLogic(row.로직); + const [one, auto] = await Promise.all([ + fetchLogic(row.로직), + asked.has(row.로직) ? Promise.resolve({}) : fetchAuto(row.로직), + ]); + asked.add(row.로직); + const mine = (values[row.로직] ??= {}); + for (const i of one.logic.입력) { + const got = (auto as Record)[i.이름]; + if (got === undefined || got === null || (mine[i.이름] ?? "").trim() !== "") continue; + mine[i.이름] = String(got); + sample.add(`${row.로직}|${i.이름}`); + } inputs.set(row.로직, one.logic.입력); blocks.push( el("div", { @@ -141,7 +170,9 @@ export function buildPreview(combo: () => Combo): PreviewHandle { className: "m01lab__cell--wide", text: `${row.로직} ${one.logic.이름}`, }), - ...one.logic.입력.map((i) => inputCell(i, row.로직, values)), + ...one.logic.입력.map((i) => + inputCell(i, row.로직, values, sample, () => void run()), + ), ], }), ); @@ -150,7 +181,9 @@ export function buildPreview(combo: () => Combo): PreviewHandle { } } form.replaceChildren(...blocks); - out.replaceChildren(el("p", { className: "m01-logic__muted", text: tc("Prev_Wait") })); + if (blocks.length) + await run(); // 열자마자 한 번 미리 보기 계산 + else out.replaceChildren(el("p", { className: "m01-logic__muted", text: tc("Prev_Wait") })); }; const root = el("section", {