- 길 = GET /api/projects/{id}/print/drawings · POST /api/projects/{id}/print/drawings-pdf {ids?} (draft 라우터 · 로그인 · 회사 · 프로젝트 권한 스스로)
- 차례 = B07 도면번호 → 구조물 조합 도면(도번 차례 · 도번마다 한 번 · 더한장)
- B07 = B07 단건 조회 그대로(확정본 · 미확정 조립) · 미확정 횡단 장 구조물 = 화면 TS 를 서버 Node 로(번들 tmp · package.json 안 건드림)
- 쪽 = 도각 양식 실치수(A1 840×594) · 색 = openwebcad 밝은 바탕 규칙 · 글 = 맑은 고딕 심음(subset) · 그림 = data URL 넣음 · 못 넣은 수 = 응답 머리
- 화면 쪽 = fetchDrawingList · fetchDrawingsPdf(약속 꼴) · skippedImagesOf
- requirements = PyMuPDF · ezdxf
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013QyNXY2TUKXCFMwAca2APG
60 lines
2.5 KiB
TypeScript
60 lines
2.5 KiB
TypeScript
/* =============================================================================
|
|
* B09_Draft_Print_Drawings.ts
|
|
* 인쇄 미리보기 도면 영역(PLAN 302-2) — 서버가 만든 목록 · PDF 를 그대로 받음(보는 것 = 받는 것).
|
|
* 차례 = B07 도면번호 → 구조물 조합 도면(도번마다 한 번) · 서버 `B09_Draft_Print_Drawings_Router.py`
|
|
* PDF 머리 X-Aislo-Skipped-Images = 못 넣은 그림 {id: 수} → `skippedImagesOf(blob)`
|
|
* ========================================================================== */
|
|
|
|
import { API_BASE_URL } from "@config/config_frontend";
|
|
import type { DrawingItem, FetchDrawingList, FetchDrawingsPdf } from "./B09_Draft_Print_Types";
|
|
|
|
/** 도면 한 장 — 약속 꼴(id · name = label) + 서버가 주는 칸 */
|
|
export interface PrintDrawingItem extends DrawingItem {
|
|
source: "b07" | "structure";
|
|
kind: string;
|
|
label: string;
|
|
number: string;
|
|
confirmed: boolean;
|
|
paper: string | null;
|
|
/** PDF 를 만들어야 셈 — 목록에서는 null */
|
|
images_skipped: number | null;
|
|
}
|
|
|
|
async function failure(response: Response): Promise<Error> {
|
|
const body = (await response.json().catch(() => null)) as { message?: string } | null;
|
|
return new Error(body?.message ?? `HTTP ${response.status}`);
|
|
}
|
|
|
|
export const fetchDrawingList: FetchDrawingList = async (projectId) => {
|
|
const response = await fetch(`${API_BASE_URL}/projects/${projectId}/print/drawings`, {
|
|
credentials: "include",
|
|
});
|
|
if (!response.ok) throw await failure(response);
|
|
const items = (await response.json()) as Omit<PrintDrawingItem, "name">[];
|
|
return items.map((item): PrintDrawingItem => ({ ...item, name: item.label }));
|
|
};
|
|
|
|
const skipped = new WeakMap<Blob, Record<string, number>>();
|
|
|
|
export const fetchDrawingsPdf: FetchDrawingsPdf = async (projectId, ids) => {
|
|
const response = await fetch(`${API_BASE_URL}/projects/${projectId}/print/drawings-pdf`, {
|
|
method: "POST",
|
|
credentials: "include",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify(ids ? { ids } : {}),
|
|
});
|
|
if (!response.ok) throw await failure(response);
|
|
const blob = await response.blob();
|
|
try {
|
|
skipped.set(blob, JSON.parse(response.headers.get("X-Aislo-Skipped-Images") ?? "{}"));
|
|
} catch {
|
|
/* 머리가 깨졌으면 빠진 그림 없음으로 */
|
|
}
|
|
return blob;
|
|
};
|
|
|
|
/** 그 PDF 에서 못 넣은 그림 {도면 id: 수} — 없으면 빈 꼴 */
|
|
export function skippedImagesOf(blob: Blob): Record<string, number> {
|
|
return skipped.get(blob) ?? {};
|
|
}
|