feat(M02): 면적 값 고침이 저장 전 도면 패널 표에 바로 비침 · 이름 · 보내기 취소는 [저장] 때 서버가 기록(112-1·112-2)
- 112-1 면적 표 변환을 공용 파일(spreadsheet_area_table.ts)로 빼 서버 Node 와 브라우저가 한 벌로 씀 · 도면 패널이 칸 고침마다(값 바뀐 표만 · 펼친 동안만) CAD 연결 표 갈기를 보기 전용 갈음(preview)으로 보냄 - 112-2 보낸 범위 이름은 도면 [저장] 요청 안에서 서버가 면적 문서에 둠(놓기만 하고 저장 안 하면 안 생김) · [보내기 취소]는 화면에서만 빼고 면적 [저장] 때 서버가 연결표 줄 · 이름을 뺌 · /name · /unlink 길 삭제 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MgChuAcyBqUkhHMTXomQC7
This commit is contained in:
@@ -5,12 +5,17 @@
|
||||
* 83-3 — 머리 [면적산출로 보내기] = CAD 에 고른 범위 요청(`aislo:b08:export-table-request`) → 받은 표 자료
|
||||
* (`aislo:b08:export-table` · CAD `integration/aislo-table-export.ts`)를 `onTable` 로(새 시트 만들기는 부른 쪽).
|
||||
* CAD 명령 TOAREA 로 보낸 것도 같은 길. 고칠 수 없는 면적(읽기 층)이면 단추 없음.
|
||||
* 112-1 — 면적 칸을 고치면(저장 전) 연결 표 값이 바로 따라 바뀜: 지금 시트의 칸 글을 서버와 같은 코드
|
||||
* (`spreadsheet_area_table.ts`)로 브라우저가 만들어 CAD 연결 표 갈기 메시지(보기 전용 갈음)로 보냄 ·
|
||||
* 패널이 펼쳐진 동안 · 값이 바뀐 표만 · 도면 문서는 안 고침([저장] 때는 서버 refresh_drawing 이 정본).
|
||||
* ========================================================================== */
|
||||
|
||||
import { createButton, el } from "@ui/ui_template_elements";
|
||||
import { readTemplate, type Layer, type StructureDoc } from "./M02_MasterTemplete_Api_Fetch";
|
||||
import { mountStructureSheets } from "./M02_MasterTemplete_Drawing";
|
||||
import type { DrawingTable } from "./M02_MasterTemplete_AreaFromDrawing";
|
||||
import { sameValues, type TableLink } from "./M02_MasterTemplete_AreaToDrawing";
|
||||
import type { Workbook } from "../A00_Common/spreadsheet/spreadsheet_types";
|
||||
|
||||
const TEXT = {
|
||||
loading: "도면 불러오는 중…",
|
||||
@@ -44,12 +49,25 @@ function hideChrome(frame: HTMLIFrameElement): void {
|
||||
export interface AreaDrawingOptions {
|
||||
/** 받은 표 자료 — 없으면(읽기 층) 보내기 단추 없음 */
|
||||
onTable?: (table: DrawingTable) => void;
|
||||
/** 면적 화면에서 [보내기 취소]한 연결(저장 전) — 실시간 값 갈기에서 뺌 */
|
||||
cancelled?: () => ReadonlySet<string>;
|
||||
}
|
||||
|
||||
/** 도면 손잡이 중 실시간 갈기에 쓰는 것(`mountStructureSheets` 의 `updateTable`) */
|
||||
interface LiveHandle {
|
||||
updateTable?: (link: string, cells: unknown[][], preview?: boolean) => Promise<number>;
|
||||
}
|
||||
|
||||
const LIVE_MS = 150; // 칸 고침이 이어지는 동안 모았다가 한 번에
|
||||
|
||||
export interface AreaDrawing {
|
||||
root: HTMLElement;
|
||||
/** 패널이 펼쳐짐 — 처음 한 번만 읽고 그림 */
|
||||
show: () => void;
|
||||
/** 패널이 접힘 — 접힌 동안은 실시간 갈기 건너뜀 */
|
||||
hide: () => void;
|
||||
/** 면적 시트가 바뀜(저장 전) — 지금 책을 주면 연결 표 값을 따라 바꿈 */
|
||||
sync: (book: () => Workbook | null | undefined) => void;
|
||||
destroy: () => void;
|
||||
}
|
||||
|
||||
@@ -64,6 +82,12 @@ export function createAreaDrawing(
|
||||
let frame: HTMLIFrameElement | null = null;
|
||||
let started = false;
|
||||
let dead = false;
|
||||
let open = false;
|
||||
let rows: TableLink[] = [];
|
||||
let bookOf: (() => Workbook | null | undefined) | null = null;
|
||||
let timer: number | undefined;
|
||||
/** 연결별로 마지막에 도면에 비춘 칸 글(없으면 저장된 `값`) */
|
||||
const pushed = new Map<string, Record<string, string>>();
|
||||
const note = (text: string): void =>
|
||||
stage.replaceChildren(el("p", { className: "m02-apanel__note", text }));
|
||||
|
||||
@@ -85,8 +109,38 @@ export function createAreaDrawing(
|
||||
};
|
||||
window.addEventListener("message", onMessage);
|
||||
|
||||
/** 지금 시트 → 연결 표마다 칸 글을 만들어 달라진 것만 도면에 비춤(서버 `areaTable` 과 같은 코드) */
|
||||
async function push(): Promise<void> {
|
||||
const book = bookOf?.();
|
||||
const handle = view as LiveHandle | null;
|
||||
if (dead || !open || !book || !handle?.updateTable || !rows.length) return;
|
||||
const { areaTable } = await import("../A00_Common/spreadsheet/spreadsheet_area_table");
|
||||
for (const row of rows) {
|
||||
if (opts.cancelled?.().has(row.연결)) continue;
|
||||
try {
|
||||
const got = areaTable({
|
||||
book,
|
||||
시트: row.시트,
|
||||
범위: row.범위,
|
||||
이름: row.이름,
|
||||
글자크기: row.글자크기,
|
||||
});
|
||||
if (sameValues(pushed.get(row.연결) ?? row.값, got.값)) continue;
|
||||
pushed.set(row.연결, got.값);
|
||||
await handle.updateTable(row.연결, got.표.shapeData.cells, true).catch(() => 0);
|
||||
} catch {
|
||||
// 이름이 지워짐 · 범위 못 바꿈 — 표는 그대로(저장 때 서버가 판정)
|
||||
}
|
||||
}
|
||||
}
|
||||
const later = (): void => {
|
||||
window.clearTimeout(timer);
|
||||
timer = window.setTimeout(() => void push(), LIVE_MS);
|
||||
};
|
||||
|
||||
const show = (): void => {
|
||||
if (started) return;
|
||||
open = true;
|
||||
if (started) return later(); // 접힌 사이 바뀐 값을 따라잡음
|
||||
started = true;
|
||||
note(TEXT.loading);
|
||||
readTemplate(layer, "structure", column, null)
|
||||
@@ -95,6 +149,7 @@ export function createAreaDrawing(
|
||||
const doc = got.문서 as StructureDoc | null;
|
||||
if (!doc?.도면) return note(TEXT.none);
|
||||
stage.replaceChildren();
|
||||
rows = doc.연결표 ?? [];
|
||||
// 보기 전용 + 고르기(누름 · 끌기) — 미리보기(끌기 = 화면 옮기기)는 고르기가 꺼져 있어 안 씀
|
||||
const sheets = doc as unknown as Parameters<typeof mountStructureSheets>[1];
|
||||
view = mountStructureSheets(stage, sheets, {
|
||||
@@ -111,6 +166,7 @@ export function createAreaDrawing(
|
||||
frame = stage.querySelector("iframe");
|
||||
if (frame) hideChrome(frame);
|
||||
send.disabled = !frame;
|
||||
later();
|
||||
})
|
||||
.catch(() => !dead && note(TEXT.none));
|
||||
};
|
||||
@@ -118,8 +174,11 @@ export function createAreaDrawing(
|
||||
return {
|
||||
root,
|
||||
show,
|
||||
hide: () => (open = false),
|
||||
sync: (book) => ((bookOf = book), later()),
|
||||
destroy: () => {
|
||||
dead = true;
|
||||
window.clearTimeout(timer);
|
||||
window.removeEventListener("message", onMessage);
|
||||
view?.destroy();
|
||||
root.remove();
|
||||
|
||||
Reference in New Issue
Block a user