Files
Aislo/A00_Common/line_stack_sourced.ts
T
eomsangdonandClaude Opus 5.5 d11075c7c2 feat(810-3): 원파일 가져온 식 화면 — 옵션 칸 · 추정 칸 · 소계 빈칸 · 카드 확정률 · 화면 셈 거울
- 올림 칸 accept .estx · .stc · 올림 안내 「원파일 · EST/STmate — 호표 N · 같은 공사 엑셀 HP 에 붙음」
- 줄 쌓기 위 옵션 가로 — 가져온 식 값으로 드러난 수 하나 변수(q · K · E · Cm · Q …) = 값 칸 + 꼬리표 「원파일」 · 「엑셀」(`sourceOf` · 공식 묶음 밖) · 규격 칸(원파일) · 품셈 조건 글 = 「추정」 칸(읽기만 · 기초에 안 묶음)
- 합 밖 · 비목 없는 소계 줄 = 종류 「소계」 · 비목 칸 빈칸(편집 · 산출근거 표 칸 모두)
- 원문 카드 — 「원파일 · EST 산근 D… · 행 …」 한 줄 + 원파일 확정(확정 · 표지 · 추정 · 확정률)
- 서버 — 원파일 원본에 원코드 · 규격(EST) · 문서 머리 가져온에 원코드 · 규격 · 확정 · 추정 글줄(금액 · 길 그대로)
- 화면 계산기 큰나머지 끝전 — 나머지 비교 소수 흔들림 반올림(파이썬 Decimal 과 같은 갈래 · 동부청영월 블록 1810 재료비 1 원 어긋남 고침)
- 시험 test_810_3_native_screen(EST 1,849 · STC 371 블록 화면 셈 = 서버 셈 · 옵션 칸 · 추정 칸 수 = 확정 추정 · 소계 · 카드) · 헬퍼 helper_810_3_screen.cjs

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 20:55:48 +09:00

81 lines
3.3 KiB
TypeScript

/* =============================================================================
* line_stack_sourced.ts
* 가져온 식 옵션 가로 칸(PLAN 810-3 · 요구 705 · 703) — 줄 쌓기 위 옵션 가로(`formula_doc_options.ts`) 뒤에 붙음
* 값 칸 = 경쟁사 파일에 값으로 드러난 수(q · K · E · Cm · Q …) · 꼬리표 「원파일」 · 「엑셀」(`sourceOf`) ·
* 고침 = 그 숫자 연결 값(부른 쪽 `set` · 캐시 → [저장])
* 규격 칸 = 원파일 블록 규격(읽기만) · 추정 칸 = 값 없이 이름만 적힌 품셈 조건 글(문서 `가져온.추정` · 읽기만 ·
* M01 기초에 묶지 않음 · 703)
* ========================================================================== */
import { createBadge } from "@ui/ui_template_badge";
import { el } from "@ui/ui_template_elements";
import { createInputField } from "@ui/ui_template_input";
import { varId, type DocVar, type FormulaDoc } from "../common_util/common_util_formula_doc";
import { sourceOf } from "../common_util/common_util_line_stack";
import { lt } from "./line_stack_text";
interface Head {
원파일?: boolean;
규격?: string;
추정?: { 행?: number; 글?: string }[];
}
const cell = (field: HTMLElement, tag: string, tone: "info" | "warning", hint: string) =>
el("div", {
className: "lstk-src",
attrs: { title: hint },
children: [field, createBadge(tag, tone)],
});
export function buildSourced(
doc: FormulaDoc | null,
lock: boolean,
set: (key: string, v: DocVar, value: unknown) => void,
): HTMLElement[] {
const head = (doc as { 가져온?: Head } | null)?.가져온;
if (!doc || !head) return [];
const out: HTMLElement[] = [];
for (const v of doc.변수 ?? []) {
const tag = sourceOf(doc, v);
if (!tag) continue;
const id = varId(v);
const f = createInputField({
label: v.이름 || id,
value: String(v.연결?.값 ?? ""),
compact: true,
size: 28,
unit: v.단위 || undefined,
});
f.input.disabled = lock;
f.input.addEventListener("change", () => {
const n = Number(f.input.value.trim().replace(/,/g, ""));
if (f.input.value.trim() === "" || !Number.isFinite(n))
return void (f.input.value = String(v.연결?.값 ?? "")); // 수만 — 빈 값 · 글 = 그대로
set(id, v, String(n));
});
f.root.dataset.option = id;
const tagText = tag === "원파일" ? lt("Src_Native") : tag === "엑셀" ? lt("Src_Excel") : tag;
out.push(cell(f.root, tagText, "info", lt("Src_Hint")));
}
const ro = (label: string, value: string, mark: string, guess: boolean) => {
const f = createInputField({ label, value, compact: true, size: 28 });
f.input.readOnly = true;
f.input.title = value; // 긴 조건 글 = 칸 위에 올리면 다 보임
if (guess) f.root.dataset.guess = mark;
return guess
? cell(f.root, lt("Guess"), "warning", lt("Guess_Hint"))
: cell(f.root, lt("Src_Native"), "info", lt("Src_Hint"));
};
if (head.규격) out.push(ro(lt("Spec"), head.규격, "", false));
for (const g of head.추정 ?? [])
out.push(
ro(
`${lt("Guess_Label")}${g.행 !== undefined ? ` · ${g.행}행` : ""}`,
String(g.글 ?? "").replace(/^※\s*/, ""),
String(g.행 ?? ""),
true,
),
);
return out;
}