From abd37e8979795364dd0ce382751c84f9220d670a Mon Sep 17 00:00:00 2001 From: umsangdon Date: Tue, 22 Sep 2026 20:54:25 +0900 Subject: [PATCH] =?UTF-8?q?feat(M01):=20=EB=A1=9C=EC=A7=81=20=EC=97=B4?= =?UTF-8?q?=EC=9E=90=EB=A7=88=EC=9E=90=20=ED=85=8D=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=88=98=EC=8B=9D=20=EC=99=BC=EC=AA=BD=20=EC=9D=B4=EB=A6=84=20?= =?UTF-8?q?=EC=8B=9D=20=EC=B1=84=EC=9B=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 로직을 열 때 /text 를 값 없이 한 번 불러 왼쪽 이름 식 칸만 미리 채움 오른쪽 값 식 칸은 [계산] 전까지 안내 글만 표시 · [계산] 뒤엔 지금과 같음 onText 콜백이 redraw 를 안 불러 화면에 안 닿던 것을 찾아 LogicLab.ts 한 줄도 같이 고침(onLines 와 같은 자리) --- M01_MasterData/M01_MasterData_UI_LogicLab.ts | 1 + .../M01_MasterData_UI_LogicLab_Formula.ts | 18 +++++++++++++----- .../M01_MasterData_UI_Logic_Calc.ts | 19 +++++++++++++++++++ 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/M01_MasterData/M01_MasterData_UI_LogicLab.ts b/M01_MasterData/M01_MasterData_UI_LogicLab.ts index 231e38b4..4eb22ae7 100644 --- a/M01_MasterData/M01_MasterData_UI_LogicLab.ts +++ b/M01_MasterData/M01_MasterData_UI_LogicLab.ts @@ -169,6 +169,7 @@ export async function mountM01LogicLab( values: current.values, onText: (text) => { current.text = text; + drawEditor(); // [계산] 전 미리보기 응답도 왼쪽 이름 식 칸에 바로 비치게 — onLines 와 같은 자리 }, onLines: (lines) => { current.lines = lines; diff --git a/M01_MasterData/M01_MasterData_UI_LogicLab_Formula.ts b/M01_MasterData/M01_MasterData_UI_LogicLab_Formula.ts index c021fae0..332cc315 100644 --- a/M01_MasterData/M01_MasterData_UI_LogicLab_Formula.ts +++ b/M01_MasterData/M01_MasterData_UI_LogicLab_Formula.ts @@ -12,8 +12,11 @@ import { tx } from "./M01_MasterData_UI_Logic_Text"; import { tl } from "./M01_MasterData_UI_LogicLab_Text"; import "./M01_MasterData_UI_LogicLab_Formula.css"; +/** 로직 열자마자 값 없이 부른 미리보기 응답은 `계산됨` 을 false 로 표시 — [계산] 을 거친 응답은 안 붙어 true 취급 */ +export type PreviewTextAnswer = TextAnswer & { 계산됨?: boolean }; + export interface FormulaContext { - text: TextAnswer | null; + text: PreviewTextAnswer | null; } const muted = (text: string): HTMLElement => el("p", { className: "m01-logic__muted", text }); @@ -41,6 +44,7 @@ export function buildFormula(host: HTMLElement, ctx: FormulaContext): void { ], }); const rows: HTMLElement[] = []; + const calculated = text.계산됨 !== false; // [계산] 뒤 응답은 표식이 안 붙음 — 미리보기만 false const light = (pair: string, on: boolean): void => rows.forEach((r) => r.dataset.pair === pair && r.classList.toggle("is-on", on)); const blocks = text.groups.flatMap((g) => [ @@ -54,10 +58,14 @@ export function buildFormula(host: HTMLElement, ctx: FormulaContext): void { el("div", { className: "m01lab-fx__cell", text: line.이름글 ?? line.이름 }), el("div", { className: "m01lab-fx__cell", - children: [ - el("div", { text: `${line.이름} : ${line.글}` }), - ...(line.까닭 ? [el("div", { className: "m01-logic__muted", text: line.까닭 })] : []), - ], + children: calculated + ? [ + el("div", { text: `${line.이름} : ${line.글}` }), + ...(line.까닭 + ? [el("div", { className: "m01-logic__muted", text: line.까닭 })] + : []), + ] + : [el("div", { className: "m01-logic__muted", text: tl("Formula_Slot") })], }), ], }); diff --git a/M01_MasterData/M01_MasterData_UI_Logic_Calc.ts b/M01_MasterData/M01_MasterData_UI_Logic_Calc.ts index 471f8675..821c76bd 100644 --- a/M01_MasterData/M01_MasterData_UI_Logic_Calc.ts +++ b/M01_MasterData/M01_MasterData_UI_Logic_Calc.ts @@ -55,6 +55,9 @@ export interface CalcContext { const SUMS = ["노무비", "재료비", "경비", "계"]; +/** 로직을 열 때마다 새로 부르는 미리보기 — 늦게 온 응답이 새 로직을 덮지 않게 순번으로 거름 */ +let previewSeq = 0; + export function buildCalc(host: HTMLElement, ctx: CalcContext): void { // 그릇 폭 280px 고정 칸은 옛 테스트 컨테이너(UI_Test*, 걷힘)의 죽은 CSS 규칙 — // 지금 쓰는 LogicLab 화면은 그 칸에 안 걸려 폭이 이미 넓음(실측 730px) · 따로 안 풂 @@ -100,7 +103,23 @@ export function buildCalc(host: HTMLElement, ctx: CalcContext): void { }); }); const out = el("div", { className: "m01-logic__calc-out" }); + let manualRun = false; // [계산] 이 이미 답했으면 뒤늦게 오는 미리보기로 안 덮음 + if (ctx.onText) { + const mySeq = ++previewSeq; + const draft = ctx.dirty() || ctx.savedKey === null; + const body = { + key: ctx.savedKey ?? ctx.row.키, + inputs: {}, + ...(draft ? { row: ctx.row, file: ctx.file } : {}), + }; + void runText(body).then((answer) => { + if (manualRun || mySeq !== previewSeq) return; // [계산] 을 눌렀거나 다른 로직이 이미 열림 + (answer as TextAnswer & { 계산됨?: boolean }).계산됨 = false; + ctx.onText?.(answer); + }); + } const run = async (): Promise => { + manualRun = true; const inputs: Record = {}; for (const spec of ctx.row.입력 ?? []) { const raw = (ctx.values[spec.이름] ?? "").trim();