Merge remote-tracking branch 'origin/dev' into sub_laptop_2
This commit is contained in:
@@ -15,7 +15,7 @@ import {
|
||||
} from "./M01_MasterData_UI_Logic_Api";
|
||||
import { formatNumber } from "./M01_MasterData_UI_Logic_Edit";
|
||||
import { hasPickable, pickPanel, swappedRow } from "./M01_MasterData_UI_Test_Pick";
|
||||
import { plainReason, tt } from "./M01_MasterData_UI_Test_Text";
|
||||
import { guideLines, plainReason, tt } from "./M01_MasterData_UI_Test_Text";
|
||||
|
||||
type Step =
|
||||
{ kind: "job" } | { kind: "ask"; spec: LogicInput } | { kind: "pick" } | { kind: "result" };
|
||||
@@ -81,7 +81,10 @@ function wizard(host: HTMLElement, one: LogicOne): void {
|
||||
frame(
|
||||
`${logic.원문번호} ${logic.이름}`,
|
||||
tt("Job_Note"),
|
||||
[el("p", { text: `${tt("Job_Title")} · ${logic.결과단위}` })],
|
||||
[
|
||||
el("p", { text: `${tt("Job_Title")} · ${logic.결과단위}` }),
|
||||
el("ul", { children: guideLines("A").map((t) => el("li", { text: t })) }),
|
||||
],
|
||||
true,
|
||||
);
|
||||
} else if (step.kind === "ask") drawAsk(step.spec);
|
||||
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
} from "./M01_MasterData_UI_Logic_Api";
|
||||
import { formatNumber } from "./M01_MasterData_UI_Logic_Edit";
|
||||
import { hasPickable, pickPanel, swappedRow, type Swaps } from "./M01_MasterData_UI_Test_Pick";
|
||||
import { plainReason, tt } from "./M01_MasterData_UI_Test_Text";
|
||||
import { guideLines, plainReason, tt } from "./M01_MasterData_UI_Test_Text";
|
||||
|
||||
/* ── 원문 표(소요량·계수) 미리보기 — /elements 로 파일을 찾고 /table 로 통째 읽음 ── */
|
||||
|
||||
@@ -232,7 +232,12 @@ export function render(host: HTMLElement, logicKey: string): void {
|
||||
const swaps: Swaps = new Map();
|
||||
const state: State = {
|
||||
one,
|
||||
values: {},
|
||||
// 고르기 칸은 첫 값으로 시작 — 방식 C 와 같게(바로 계산이 돎)
|
||||
values: Object.fromEntries(
|
||||
(one.logic.입력 ?? [])
|
||||
.filter((spec) => spec.고르기?.length)
|
||||
.map((spec) => [spec.이름, String(spec.고르기?.[0])]),
|
||||
),
|
||||
answer: null,
|
||||
selected: 0,
|
||||
calcSeq: 0,
|
||||
@@ -322,6 +327,10 @@ function paint(host: HTMLElement, state: State): void {
|
||||
main.style.cssText = "flex:1 1 60%;min-width:0;";
|
||||
main.append(
|
||||
el("h3", { text: `${row.원문번호} ${row.이름}` }),
|
||||
el("ul", {
|
||||
className: "m01-logic__muted",
|
||||
children: guideLines("B").map((t) => el("li", { text: t })),
|
||||
}),
|
||||
inputWrap,
|
||||
...(hasPickable(state.one.logic)
|
||||
? [
|
||||
@@ -387,7 +396,35 @@ function buildHoTable(host: HTMLElement, state: State): HTMLElement {
|
||||
}),
|
||||
],
|
||||
}),
|
||||
el("tbody", { children: rows }),
|
||||
el("tbody", {
|
||||
children: [
|
||||
...rows,
|
||||
// 하위 로직이 여러 줄로 풀린 경우 — 호표 줄 수보다 많은 줄도 빠짐없이 보임
|
||||
...(lines ?? []).slice((state.one.logic.호표 ?? []).length).map((calc) =>
|
||||
el("tr", {
|
||||
children: [
|
||||
el("td", { text: calc.이름 }),
|
||||
el("td", { text: "" }),
|
||||
el("td", { text: `${formatNumber(calc.수량)} ${calc.단위}` }),
|
||||
el("td", { className: "m01-logic__money", text: formatNumber(calc.금액) }),
|
||||
],
|
||||
}),
|
||||
),
|
||||
...(state.answer?.ok && state.answer.sums
|
||||
? [
|
||||
el("tr", {
|
||||
attrs: { "data-total": String(state.answer.sums["계"] ?? 0) },
|
||||
children: [
|
||||
el("td", { text: tt("Sum_Total") }),
|
||||
el("td", { text: "" }),
|
||||
el("td", { text: "" }),
|
||||
el("td", { text: formatNumber(state.answer.sums["계"] ?? 0) }),
|
||||
],
|
||||
}),
|
||||
]
|
||||
: []),
|
||||
],
|
||||
}),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ import {
|
||||
type FlowKind,
|
||||
} from "./M01_MasterData_UI_Test_C_Model";
|
||||
import { hasPickable, pickPanel, swappedRow, type Swaps } from "./M01_MasterData_UI_Test_Pick";
|
||||
import { plainReason, tt } from "./M01_MasterData_UI_Test_Text";
|
||||
import { guideLines, plainReason, tt } from "./M01_MasterData_UI_Test_Text";
|
||||
import "./M01_MasterData_UI_Test_C_Style.css";
|
||||
|
||||
const TEXT = {
|
||||
@@ -212,6 +212,10 @@ function mount(host: HTMLElement, one: LogicOne): void {
|
||||
...(one.reasons.length
|
||||
? [el("p", { className: "m01c__bad", text: one.reasons.join(" · ") })]
|
||||
: []),
|
||||
el("ul", {
|
||||
className: "m01c__muted",
|
||||
children: guideLines("C").map((t) => el("li", { text: t })),
|
||||
}),
|
||||
stopped,
|
||||
...(hasPickable(row)
|
||||
? [
|
||||
|
||||
@@ -46,6 +46,26 @@ const TEXT = {
|
||||
"넣은 값에 맞는 표 줄이 없습니다 — 값을 바꿔 보세요",
|
||||
"No table row fits these values — try other values",
|
||||
],
|
||||
Stop_Spec: [
|
||||
"「{name}」 규격이 여럿이라 정하지 못함 — 위 「쓰이는 재료·기계」에서 하나를 골라 주세요",
|
||||
"「{name}」 has several specs — pick one in the materials list above",
|
||||
],
|
||||
Stop_NoPrice: [
|
||||
"「{name}」 단가가 자료에 비어 있어 셈하지 못함 — 자료를 채워야 함",
|
||||
"「{name}」 has no price in the data yet",
|
||||
],
|
||||
Guide_A: [
|
||||
"한 번에 하나씩 묻는 대로 답하면 끝에 결과 표가 나옴|값을 잘못 넣었으면 「이전」으로 돌아가 고침|재료·기계를 바꿔 보는 칸은 뒤쪽 단계에 있음",
|
||||
"Answer one question at a time; the result table comes last|Use Back to fix a value|Swap materials in a later step",
|
||||
],
|
||||
Guide_B: [
|
||||
"위쪽 칸에 값을 넣으면 아래 호표(재료·인력·기계 줄)의 수량과 금액이 바로 바뀜|줄을 누르면 오른쪽에 그 수량이 어디서 왔는지 나옴|맨 아래 「합계」가 최종 금액",
|
||||
"Type values above and the table below updates at once|Click a row to see where its quantity comes from|The last row is the total",
|
||||
],
|
||||
Guide_C: [
|
||||
"왼쪽 「설계 값」을 넣으면 오른쪽으로 수량 → 단가 → 합계 순으로 흐름이 이어짐|상자를 누르면 값과 출처가 펼쳐짐|빨간 글이 뜨면 그 까닭 그대로 값을 채우거나 바꿈",
|
||||
"Enter design values on the left; quantity, price and total follow to the right|Click a box for details|Red text says what is missing",
|
||||
],
|
||||
Enter_Value: ["값을 넣어 주세요", "Enter a value"],
|
||||
Result_Title: ["결과", "Result"],
|
||||
Result_Stopped: ["계산이 멈춤", "Calculation stopped"],
|
||||
@@ -63,9 +83,17 @@ export function plainReason(reason: string): string {
|
||||
const missing = /입력 「([^」]+)」 없음/.exec(reason);
|
||||
if (missing) return tt("Stop_Missing", { name: missing[1] });
|
||||
if (/맞는 줄 0개/.test(reason)) return tt("Stop_NoRow");
|
||||
const spec = /「([^」]+)」 후보 여럿/.exec(reason);
|
||||
if (spec) return tt("Stop_Spec", { name: spec[1] });
|
||||
const noPrice = /「([^」]+)」 값 없음/.exec(reason);
|
||||
if (noPrice) return tt("Stop_NoPrice", { name: noPrice[1] });
|
||||
return reason;
|
||||
}
|
||||
|
||||
/** 방식 첫 화면 「이 방식은 이렇게 씀」 — 줄 목록 */
|
||||
export const guideLines = (id: "A" | "B" | "C"): string[] =>
|
||||
tt(`Guide_${id}` as TestTextKey).split("|");
|
||||
|
||||
export function tt(key: TestTextKey, fill: Record<string, string | number> = {}): string {
|
||||
const entry = TEXT[key];
|
||||
const text: string = entry[currentLanguageIndex as 0 | 1] ?? entry[0];
|
||||
|
||||
Reference in New Issue
Block a user