feat(B09 설계내역서): [엑셀 내역 불러오기] 창 — 수량 갈래 · 두 번 셈 막음 · 어긋난 줄 목록 (PLAN 707-1)

- 설계내역서 도구 줄 끝 단추 → 파일 고름 → 창 한 번(넘겨받기 · 단가만 · 이름 같은 자동 줄 붙임 · 남는 자동 줄 지움) → [불러오기] = 화면 캐시(저장 안 함 · [저장]해야 남음)
- 어긋난 줄(엑셀 금액 ≠ 우리 금액) = 같은 창 목록 · 없으면 닫고 알림 · DRM = 「읽을 수 없음」
- 단가만 갈래 = 불러온 수량과 10 % 넘게 다른 수량 칸 붉게 · 풍선 = 불러온 수량
- 시험 243-1(표 만드는 길 목록 = 불러오기 창 표 더함 · 보기 전용) · 200-2(도구 줄 배선 = 불러오기 단추 끝) 고침 — 낡은 글자 대조

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-31 15:50:19 +09:00
co-authored by Claude Opus 5.5
parent c0ea73501f
commit 02886d5d4d
6 changed files with 217 additions and 6 deletions
+14 -1
View File
@@ -42,6 +42,7 @@ import { createCheckPanel } from "./B09_Estimation_UI_Check";
import { createLiveCalc, markWaiting, waitingKeys, withoutWaiting } from "./B09_Estimation_UI_Live";
import { tableOptionsOf, tabTableOf } from "./B09_Estimation_UI_Builders";
import { createDock, linkMode } from "./B09_Estimation_UI_Dock";
import { createBillImport } from "./B09_Estimation_UI_Import";
import { closePopups, openRowPopup } from "./B09_Estimation_UI_Popup";
import {
DRAFT,
@@ -285,7 +286,7 @@ export function renderB09Estimation(root: HTMLElement): void {
);
if (range) unpickOnRelease(table.root);
const level = bill ? levelBar(table.root, bill, (i) => table.edit(i)) : null;
if (level) bars.setTools(level.tools);
if (level) bars.setTools(importer ? [...level.tools, importer] : level.tools);
// 203 안내 글 영역 하나 — 설계내역서 레벨 안내 + 탭 안내 이어 붙임
if (level && hint) hint.textContent = `${level.guide.textContent} · ${hint.textContent}`;
const foot = hint ?? level?.guide;
@@ -301,6 +302,18 @@ export function renderB09Estimation(root: HTMLElement): void {
if (at >= 0) requestAnimationFrame(() => table.focusRow(at, false)); // 스크롤만(표시 = 빨강)
};
// 707-1 [엑셀 내역 불러오기] = 설계내역서 도구 줄 끝 · 받은 캐시 → 원가 자료와 함께 다시 셈(저장 안 함)
const importer = projectId
? createBillImport(
projectId,
() => user,
(next, made) => {
writeState("b09-estimation", made, projectId);
apply(next, false);
},
)
: null;
const apply = (next: Row, fromServer: boolean): void => {
payload = next;
const draft = projectId && !fromServer ? readState<Row>("b09-estimation", projectId) : null;