feat(M02): 산출근거 전체 편집 화면 — 집계표 카드는 보기 + [산출근거 수정]

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0168FQuoV7vDh5nhnSowW5cp
This commit is contained in:
2026-09-28 00:30:48 +09:00
co-authored by Claude Sonnet 5
parent e31e1b0016
commit 69f9c64c98
2 changed files with 57 additions and 69 deletions
@@ -143,9 +143,9 @@ export function createMain(isAdmin: boolean, onSaved?: () => void): MainHandle {
const made = createStructurePanel({
isAdmin,
confirmLeave,
// 같은 페이지에서 그 구조물 도면을 CAD 편집으로 엶
onEdit: (column, label) => {
void open({ layer: "system", projectId: null, kind: "structure", name: column, label });
// 같은 페이지에서 그 열을 CAD·스프레드시트 전체 편집으로 엶
onEdit: (column, label, kind) => {
void open({ layer: "system", projectId: null, kind, name: column, label });
},
});
extra.replaceChildren(made.root);
@@ -179,6 +179,20 @@ export function createMain(isAdmin: boolean, onSaved?: () => void): MainHandle {
if (struct) sheet = editor as SheetEditorHandle;
return;
}
if (at.kind === "basis") {
// 산출근거 = 구조물집계표 열마다 한 스프레드시트 — 페이지 번들에 안 섞이게 이 화면을 열 때만
// `import()` 로 받음(계약 `spreadsheet_types.ts` 머리)
try {
const { createSpreadsheet } = await import("../A00_Common/spreadsheet/spreadsheet");
editor = createSpreadsheet(host, doc as Parameters<typeof createSpreadsheet>[1], {
readOnly,
onChange: () => (dirty = !readOnly),
});
} catch {
empty(L("M02_NoSpreadsheet"));
}
return;
}
const mountDrawing = await findExport<(h: HTMLElement, d: unknown, o: object) => EditorHandle>(
DRAWING_MODS,
"mountDrawingTemplate",
@@ -226,10 +240,13 @@ export function createMain(isAdmin: boolean, onSaved?: () => void): MainHandle {
)
: got.문서;
if (mine !== seq) return;
// 구조물 도면은 열 id 로 열리니 머리에 도번을 함께 보임
// 구조물 도면 · 산출근거는 열 id 로 열리니 머리에 도번 · 표번을 함께 보임
if (next.kind === "structure") {
const number = (got.문서 as StructureDoc)?.도번;
if (number) title.textContent = `${number} · ${next.label ?? next.name}`;
} else if (next.kind === "basis") {
const number = (got.문서 as { 표번?: string })?.표번;
if (number) title.textContent = `${number} · ${next.label ?? next.name}`;
}
await mount(shown, next);
} catch (error) {
@@ -245,11 +262,14 @@ export function createMain(isAdmin: boolean, onSaved?: () => void): MainHandle {
const at = sel;
try {
const edited = editor ? await editor.getDoc() : loaded;
// 구조물 도면 저장은 `도면` 칸만 갈아 끼움 — 도번 · 산출근거는 읽은 그대로
// 구조물 도면 저장은 `도면` 칸만 갈아 끼움 — 도번 · 산출근거는 읽은 그대로.
// 산출근거는 스프레드시트 문서로 통째 갈아 끼우되 표번은 계약 밖(엔진이 모름)이라 옮겨 붙임.
const doc =
at.kind === "structure" && loaded
? { ...(loaded as StructureDoc), 도면: edited as StructureDoc["도면"] }
: edited;
: at.kind === "basis" && loaded
? { ...(loaded as Record<string, unknown>), ...(edited as Record<string, unknown>) }
: edited;
const info = await saveTemplate(at.layer, at.kind, at.name, at.projectId, version, doc);
version = info.판;
loaded = doc;