feat(b09-print): 원가계산 영역 이어 붙임 — 서버 몸(pdfBody · xlsxBody)을 표 파일로 · 원가 18장 → 표 PDF · 엑셀 이음매 시험 (302-1)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QfHKQs7J3hQELKMWQMUJEy
This commit is contained in:
2026-10-13 07:55:19 +09:00
co-authored by Claude Opus 5.5
parent 952ce4142a
commit deab5a348f
4 changed files with 100 additions and 17 deletions
+3 -14
View File
@@ -20,7 +20,7 @@ import type { MountedPage } from "../../A00_Common/router";
import { navigateTo } from "../../A00_Common/router";
import { workflowSteps } from "../../A00_Common/b_page_scaffold";
import { goToWorkflowStage, WORKFLOW_STEP_ROUTES } from "../../A00_Common/b_workflow_nav";
import { inlineImages, sheetGrid, sheetHtml } from "./B09_Draft_Print_Table";
import { inlineImages, pdfBody, xlsxBody } from "./B09_Draft_Print_Table";
import type {
CollectSheets,
DrawingItem,
@@ -72,20 +72,9 @@ function tableArea(projectId: string, title: string, sheets: PrintSheet[]): Area
items: sheets.map(({ id, name }) => ({ id, name })),
pdf: async (ids) => {
const picked = await Promise.all(pick(ids).map(inlineImages));
return post(projectId, "table-pdf", {
title,
sheets: picked.map((s) => ({
name: s.name,
orientation: s.orientation ?? "portrait",
html: sheetHtml(s),
})),
});
return post(projectId, "table-pdf", pdfBody(title, picked));
},
xlsx: (ids) =>
post(projectId, "table-xlsx", {
title,
sheets: pick(ids).map((s) => ({ name: s.name, grid: sheetGrid(s.table) })),
}),
xlsx: (ids) => post(projectId, "table-xlsx", xlsxBody(title, pick(ids))),
};
}
@@ -122,6 +122,21 @@ export function sheetGrid(table: DataTableOptions): SheetGrid {
};
}
/** 서버 몸 — 함수 칸(rowClass · level.of …)은 여기서 펼쳐 글 · 값으로만 보냄 */
export const pdfBody = (title: string, sheets: PrintSheet[]) => ({
title,
sheets: sheets.map((s) => ({
name: s.name,
orientation: s.orientation ?? "portrait",
html: sheetHtml(s),
})),
});
export const xlsxBody = (title: string, sheets: PrintSheet[]) => ({
title,
sheets: sheets.map((s) => ({ name: s.name, grid: sheetGrid(s.table) })),
});
/** 그림 주소 → data: 주소(서버 헤드리스는 바깥 요청을 막음 · 로그인 쿠키로 브라우저가 받아 둠) */
export async function inlineImages(s: PrintSheet): Promise<PrintSheet> {
if (!s.images?.some((im) => !im.src.startsWith("data:"))) return s;