- 원본 처리 근거대로 인쇄표 차례·고른 서식을 한 문서로 이어 인쇄 - 서식마다 간지(제목 가운데·겹테두리), 공사별 선택 저장 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
108 lines
5.4 KiB
JavaScript
108 lines
5.4 KiB
JavaScript
// 원본 묶음 인쇄(TEstPrint.Print 0x10fef98, TFRMESTPRINT2·TFRMPRINTLISTCHECK·TFRMESTPRINTPRIVATE 간지).
|
|
// 인쇄표 차례대로(공통 설정 행 Index 0 제외) 고른(Checked) 서식마다 간지(PrintGangiShow, 가운데 제목 Name2 · 겹테두리) → 서식 본문.
|
|
// 웹은 한 문서로 이어 인쇄하고 쪽 번호는 브라우저 쪽 번호를 쓴다(원본은 간지가 쪽 번호를 쓰지 않음 — 웹은 간지 쪽에 번호만 숨김).
|
|
// 서식 본문은 인쇄 미리보기와 같은 자료(EstForms.data · EstDocs.html). 화면 전용 서식은 건너뛰고 알린다.
|
|
const EstPrintBatch = (() => {
|
|
const esc = (v) =>
|
|
String(v ?? "").replace(
|
|
/[&<>"]/g,
|
|
(c) => ({ "&": "&", "<": "<", ">": ">", '"': """ })[c],
|
|
);
|
|
|
|
function forms(catalog, project) {
|
|
const saved = project.printBatch?.checked;
|
|
return catalog
|
|
.filter((row) => Number(row.Index) !== 0)
|
|
.map((row) => ({
|
|
Index: row.Index,
|
|
Name: row.Name2 || row.Name || String(row.Index),
|
|
checked: saved ? saved.includes(row.Index) : Number(row.Checked) === 1,
|
|
gangi: project.printBatch?.gangi ?? Number(row.PrintGangiShow) === 1,
|
|
outline: Number(row.PrintGangiOutLineShow ?? 1) === 1,
|
|
}));
|
|
}
|
|
|
|
function body(index, project, state) {
|
|
const output = EstForms.data(index, project, state);
|
|
if (output) return EstForms.grid(output);
|
|
const doc = typeof EstDocs !== "undefined" ? EstDocs.html(Number(index), project) : "";
|
|
return doc || null;
|
|
}
|
|
|
|
function document_(list, project, state, gangi) {
|
|
const skipped = [],
|
|
parts = [];
|
|
for (const form of list.filter((f) => f.checked)) {
|
|
const html = body(form.Index, project, state);
|
|
if (html == null) {
|
|
skipped.push(form.Name);
|
|
continue;
|
|
}
|
|
if (gangi)
|
|
parts.push(
|
|
`<section class="gangi${form.outline ? " outline" : ""}"><div>${esc(form.Name)}</div></section>`,
|
|
);
|
|
parts.push(`<section class="form"><h2>${esc(form.Name)}</h2>${html}</section>`);
|
|
}
|
|
const html = `<!doctype html><html lang="ko"><head><meta charset="utf-8"><title>${esc(project.name)} 설계서</title><style>
|
|
@page{size:A4 landscape;margin:12mm;@bottom-right{content:counter(page)}}@page gangi{@bottom-right{content:none}}
|
|
body{font:9pt "Malgun Gothic",sans-serif;margin:0}table{width:100%;border-collapse:collapse}th,td{border:1px solid #777;padding:1.2mm}
|
|
th{background:#eee}.numeric{text-align:right}.form{break-after:page}.form:last-child{break-after:auto}
|
|
.gangi{page:gangi;break-after:page;height:170mm;display:flex;align-items:center;justify-content:center;font-size:30pt;font-weight:bold}
|
|
.gangi.outline div{border:4px double #222;padding:12mm 30mm}.document-text{white-space:pre-wrap}</style></head><body>${parts.join("")}</body></html>`;
|
|
return { html, skipped, count: parts.length };
|
|
}
|
|
|
|
let catalog = [];
|
|
async function open(state) {
|
|
const defaults = await EstApp.api("/api/print-catalog");
|
|
const original = new Map((state.project.printCatalog || []).map((row) => [row.Index, row]));
|
|
catalog = defaults.map((row) => ({ ...row, ...original.get(row.Index) }));
|
|
render(state);
|
|
}
|
|
function render(state) {
|
|
const list = forms(catalog, state.project);
|
|
EstApp.showDialog(
|
|
"묶음 인쇄(설계서 일체)",
|
|
`<p>인쇄할 서식을 고르세요. 인쇄표 차례대로 이어 인쇄합니다.</p><label><input type="checkbox" name="pb-gangi" ${list[0]?.gangi ? "checked" : ""}>간지 인쇄</label><div style="max-height:260px;overflow:auto;columns:2">${list.map((f) => `<label style="display:block"><input type="checkbox" name="pb-form" value="${esc(f.Index)}" ${f.checked ? "checked" : ""}>${esc(f.Name)}</label>`).join("")}</div><button data-action="print-batch-preview">미리보기</button> <button data-action="print-batch-print">인쇄</button><p id="print-batch-note"></p><iframe id="print-batch-frame" style="width:100%;height:360px;border:1px solid #ccc"></iframe>`,
|
|
);
|
|
}
|
|
function read(state) {
|
|
const checked = [...document.querySelectorAll('#dialog-content [name="pb-form"]:checked')].map(
|
|
(n) => (/^\d+$/.test(n.value) ? Number(n.value) : n.value),
|
|
);
|
|
const gangi = document.querySelector('#dialog-content [name="pb-gangi"]').checked;
|
|
if (!checked.length) throw Error("인쇄할 서식을 하나 이상 고르세요.");
|
|
const next = { checked, gangi };
|
|
if (JSON.stringify(next) !== JSON.stringify(state.project.printBatch))
|
|
EstApp.change((project) => (project.printBatch = next), false);
|
|
return next;
|
|
}
|
|
function build(state) {
|
|
const { gangi } = read(state),
|
|
list = forms(catalog, state.project),
|
|
out = document_(list, state.project, state, gangi),
|
|
frame = EstApp.byId("print-batch-frame");
|
|
frame.srcdoc = out.html;
|
|
EstApp.byId("print-batch-note").textContent =
|
|
`서식·간지 ${out.count}개${out.skipped.length ? ` · 화면 전용이라 뺀 서식: ${out.skipped.join(", ")}` : ""}`;
|
|
return frame;
|
|
}
|
|
|
|
function handle(name, state) {
|
|
if (name === "print-batch")
|
|
open(state).catch((error) => {
|
|
state.notice = error.message;
|
|
EstApp.render();
|
|
});
|
|
else if (name === "print-batch-preview") build(state);
|
|
else if (name === "print-batch-print") {
|
|
const frame = build(state);
|
|
frame.onload = () => frame.contentWindow.print();
|
|
} else return false;
|
|
return true;
|
|
}
|
|
|
|
return { forms, document: document_, handle };
|
|
})();
|