diff --git a/M02_MasterTemplete/M02_MasterTemplete_Drawing.ts b/M02_MasterTemplete/M02_MasterTemplete_Drawing.ts index 7650e1d2a..8aa61bc40 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_Drawing.ts +++ b/M02_MasterTemplete/M02_MasterTemplete_Drawing.ts @@ -77,6 +77,9 @@ function migrateOldRecovery(options: DrawingTemplateOptions, scope: string): voi export interface DrawingTemplateHandle { getDoc: () => Promise; + /** 표 놓기 · 칸 갈기(41장) — `cad_host` 그대로 */ + placeTable: (entity: Record, link: string) => void; + updateTable: (link: string, cells: unknown[][]) => Promise; destroy: () => void; } @@ -277,6 +280,8 @@ export function mountDrawingTemplate( return { getDoc, + placeTable: cad.placeTable, + updateTable: cad.updateTable, destroy: () => { areaModal?.close(); cad.destroy(); diff --git a/ui_template/cad_host/cad_host.ts b/ui_template/cad_host/cad_host.ts index 88c27c69e..db2f74a87 100644 --- a/ui_template/cad_host/cad_host.ts +++ b/ui_template/cad_host/cad_host.ts @@ -28,6 +28,10 @@ const CAD_HOST_SAVE_MESSAGE = "aislo:b08:host-save"; * CAD 안 react-toastify는 모양·자리가 달라 한 화면에 두 종류가 섞여 보였다. */ const CAD_TOAST_MESSAGE = "aislo:b08:toast"; const CAD_TOAST_ACTION_MESSAGE = "aislo:b08:toast-action"; +/** 표(M02 41장) — 짝 = CAD `integration/aislo-table-bridge.ts` */ +const CAD_PLACE_TABLE_MESSAGE = "aislo:b08:place-table"; +const CAD_UPDATE_TABLE_MESSAGE = "aislo:b08:update-table"; +const CAD_TABLE_UPDATED_MESSAGE = "aislo:b08:table-updated"; /** CAD 가 주고받는 도면 JSON — 도형·층 밖의 칸은 페이지마다 다르다. */ export interface CadHostDrawing { @@ -93,6 +97,11 @@ export interface CadHost { ) => void; /** CAD 의 지금 편집본을 받는다. */ requestSave: () => Promise>; + /** 표 놓기(41장) — `entity` = 표 JSON(TableEntity 꼴) · CAD 가 `style.연결 = link` 로 커서에 붙여 놓게 함. + * 도면이 아직 안 열렸으면 열린 뒤 보냄 · 놓기는 사용자가 누를 때 · 저장은 [저장]. */ + placeTable: (entity: Record, link: string) => void; + /** 표 칸 갈기(41장) — `style.연결 === link` 인 표의 칸만(자리 · 크기 그대로) · 돌려받는 수 = 바꾼 표 수(0 = 없음). */ + updateTable: (link: string, cells: unknown[][]) => Promise; /** 메시지 듣기를 멈춘다 — 페이지를 떠날 때. */ destroy: () => void; } @@ -177,6 +186,35 @@ export function createCadHost[] = []; + const postAfterLoad = (message: Record): void => { + if (drawingLoaded) post(message); + else afterLoad.push(message); + }; + const tableWaits = new Map void)[]>(); + + const placeTable: CadHost["placeTable"] = (entity, link) => + postAfterLoad({ type: CAD_PLACE_TABLE_MESSAGE, entity, link }); + + const updateTable: CadHost["updateTable"] = (link, cells) => + new Promise((resolve, reject) => { + const waits = tableWaits.get(link) ?? []; + waits.push(resolve); + tableWaits.set(link, waits); + postAfterLoad({ type: CAD_UPDATE_TABLE_MESSAGE, link, cells }); + window.setTimeout(() => { + const left = tableWaits.get(link) ?? []; + if (!left.includes(resolve)) return; + tableWaits.set( + link, + left.filter((one) => one !== resolve), + ); + reject(new Error("CAD 표 갈기 응답 시간이 초과되었습니다.")); + }, 5000); + }); + const load: CadHost["load"] = ( drawing, meta, @@ -185,6 +223,7 @@ export function createCadHost { pendingLoad = { drawing, meta, frameEdit, frameFields, extra }; + drawingLoaded = false; // 새로 싣는 중 — 표는 열린 뒤에 if (!cadReady) return; post({ type: CAD_LOAD_MESSAGE, drawing, meta, frameEdit, frameFields, ...extra }); pendingLoad = undefined; @@ -215,6 +254,8 @@ export function createCadHost { stopLoadWatchdog(); window.removeEventListener("message", onMessage);