feat(M01): 로직 열자마자 텍스트 수식 왼쪽 이름 식 채움

로직을 열 때 /text 를 값 없이 한 번 불러 왼쪽 이름 식 칸만 미리 채움
오른쪽 값 식 칸은 [계산] 전까지 안내 글만 표시 · [계산] 뒤엔 지금과 같음
onText 콜백이 redraw 를 안 불러 화면에 안 닿던 것을 찾아 LogicLab.ts 한 줄도 같이 고침(onLines 와 같은 자리)
This commit is contained in:
2026-09-22 20:54:25 +09:00
parent 8187b0a79e
commit abd37e8979
3 changed files with 33 additions and 5 deletions
@@ -169,6 +169,7 @@ export async function mountM01LogicLab(
values: current.values,
onText: (text) => {
current.text = text;
drawEditor(); // [계산] 전 미리보기 응답도 왼쪽 이름 식 칸에 바로 비치게 — onLines 와 같은 자리
},
onLines: (lines) => {
current.lines = lines;
@@ -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") })],
}),
],
});
@@ -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<void> => {
manualRun = true;
const inputs: Record<string, unknown> = {};
for (const spec of ctx.row. ?? []) {
const raw = (ctx.values[spec.] ?? "").trim();