|
|
|
@@ -0,0 +1,100 @@
|
|
|
|
|
const EstReport = (() => {
|
|
|
|
|
function preview(all = false) {
|
|
|
|
|
const { state, esc } = EstApp;
|
|
|
|
|
const number = (value) =>
|
|
|
|
|
new Intl.NumberFormat("ko-KR", { maximumFractionDigits: 12 }).format(Number(value) || 0);
|
|
|
|
|
const root = document.createElement("div");
|
|
|
|
|
if (state.project.tables[state.view]) {
|
|
|
|
|
const rows = all
|
|
|
|
|
? state.project.tables[state.view].map((row, index) => ({ row, index }))
|
|
|
|
|
: EstApp.visibleRows();
|
|
|
|
|
const common = ["Code", "Name", "Size", "Unite"];
|
|
|
|
|
const columns = {
|
|
|
|
|
EstMainDat: [...common, "GN", "TU", "TC", "NC", "GC", "JC", "SC"],
|
|
|
|
|
HeadMainDat: [...common, "GN", "NU", "GU", "JU", "SU", "TU", "NC", "GC", "JC", "SC", "TC"],
|
|
|
|
|
CostMainDat: ["LineData"],
|
|
|
|
|
MachMainDat: [...common, "GN", "TU", "NC", "GC", "JC", "TC"],
|
|
|
|
|
Wonga: ["Gubun", "Name", "Youl", "VSusic", "Cost"],
|
|
|
|
|
};
|
|
|
|
|
root.innerHTML = EstViews.grid(
|
|
|
|
|
state.view,
|
|
|
|
|
rows,
|
|
|
|
|
columns[state.view] ||
|
|
|
|
|
EstModel.columns(state.view).filter(
|
|
|
|
|
(key) =>
|
|
|
|
|
![
|
|
|
|
|
"ValueIndex",
|
|
|
|
|
"SelectField",
|
|
|
|
|
"Ratio",
|
|
|
|
|
"NachalRatio",
|
|
|
|
|
"Diget",
|
|
|
|
|
"DigetIndex",
|
|
|
|
|
].includes(key),
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
} else root.innerHTML = EstApp.byId("work-content").innerHTML;
|
|
|
|
|
root
|
|
|
|
|
.querySelectorAll("button,.row-number,.business-tools,select#quantity-sheet")
|
|
|
|
|
.forEach((node) => node.remove());
|
|
|
|
|
root.querySelectorAll("input,textarea,select").forEach((node) => {
|
|
|
|
|
const value =
|
|
|
|
|
node.tagName === "SELECT"
|
|
|
|
|
? node.selectedOptions[0]?.textContent || ""
|
|
|
|
|
: node.type === "number" && node.value !== ""
|
|
|
|
|
? number(node.value)
|
|
|
|
|
: EstText.clean(EstText.encode(node.value));
|
|
|
|
|
if (node.tagName === "TEXTAREA") node.parentElement.classList.add("col-LineData");
|
|
|
|
|
if (node.type === "number") node.parentElement.classList.add("numeric");
|
|
|
|
|
node.replaceWith(document.createTextNode(value));
|
|
|
|
|
});
|
|
|
|
|
root
|
|
|
|
|
.querySelectorAll("[contenteditable]")
|
|
|
|
|
.forEach((node) => node.removeAttribute("contenteditable"));
|
|
|
|
|
const title = EstApp.titles[state.view] || state.view;
|
|
|
|
|
const detail =
|
|
|
|
|
state.view === "quantity"
|
|
|
|
|
? state.project.quantitySheets?.find((sheet) => sheet.Code === state.quantitySheet)?.Name
|
|
|
|
|
: state.view === "progress"
|
|
|
|
|
? state.project.progress.find((round) => round.id === state.roundId)?.name
|
|
|
|
|
: state.group
|
|
|
|
|
? EstNative.groups(state.project.tables[state.view] || []).get(state.group)?.rows[0]
|
|
|
|
|
?.Name
|
|
|
|
|
: "";
|
|
|
|
|
const totals = state.project.calculation;
|
|
|
|
|
const errors = totals?.errors || [];
|
|
|
|
|
const source = `<!doctype html><html lang="ko"><head><meta charset="UTF-8"><title>${esc(state.project.name)} · ${esc(title)}</title>
|
|
|
|
|
<style>@page{size:A3 landscape;margin:12mm}*{box-sizing:border-box}body{font:9pt "Malgun Gothic",sans-serif;color:#111;margin:0}
|
|
|
|
|
h1{font-size:17pt;margin:0 0 4mm}h2{font-size:12pt;margin:0 0 3mm}.summary{margin:2mm 0 4mm}
|
|
|
|
|
table{width:100%;border-collapse:collapse;font-size:8pt}thead{display:table-header-group}tr{break-inside:avoid}
|
|
|
|
|
th,td{border:1px solid #777;padding:1.5mm;vertical-align:top;overflow-wrap:anywhere}th{background:#eee}
|
|
|
|
|
.heading,.level{font-weight:bold;background:#f4f4f4}.selected{background:transparent}
|
|
|
|
|
.numeric{text-align:right;font-variant-numeric:tabular-nums}
|
|
|
|
|
.col-LineData{font-family:"굴림체",Consolas,monospace;white-space:pre-wrap;min-width:130mm}
|
|
|
|
|
.error-row{outline:1px solid #a00}.errors{color:#900;white-space:pre-wrap}.muted{color:#555}
|
|
|
|
|
</style></head><body><h1>${esc(state.project.name)}</h1><h2>${esc(title)}</h2>
|
|
|
|
|
${detail ? `<h2>${esc(detail)}</h2>` : ""}${totals ? `<div class="summary">순공사비 ${number(totals.direct?.TC)}원 · 도급액 ${number(totals.total)}원</div>` : ""}
|
|
|
|
|
${root.innerHTML}${errors.length ? `<p class="errors">계산 오류 ${errors.length}건: ${esc(errors.join(" / "))}</p>` : ""}</body></html>`;
|
|
|
|
|
EstApp.byId("print-frame").srcdoc = source;
|
|
|
|
|
}
|
|
|
|
|
function open() {
|
|
|
|
|
const table = EstApp.state.project.tables[EstApp.state.view];
|
|
|
|
|
EstApp.showDialog(
|
|
|
|
|
"인쇄 미리보기",
|
|
|
|
|
`<div class="business-tools">
|
|
|
|
|
${table ? '<label>출력 범위 <select id="print-scope"><option value="current">현재 호표·검색 결과 전체 행</option><option value="all">현재 자료의 모든 호표·행</option></select></label>' : ""}
|
|
|
|
|
<button data-action="print-document">인쇄 / PDF 저장</button></div>
|
|
|
|
|
<iframe id="print-frame" title="인쇄할 문서" style="width:100%;height:65vh;border:1px solid #aaa"></iframe>`,
|
|
|
|
|
);
|
|
|
|
|
EstApp.byId("print-scope")?.addEventListener("change", (event) =>
|
|
|
|
|
preview(event.target.value === "all"),
|
|
|
|
|
);
|
|
|
|
|
preview();
|
|
|
|
|
}
|
|
|
|
|
function print() {
|
|
|
|
|
const frame = EstApp.byId("print-frame");
|
|
|
|
|
if (!frame?.contentDocument?.body) throw Error("인쇄 미리보기가 준비되지 않았습니다.");
|
|
|
|
|
frame.contentWindow.focus();
|
|
|
|
|
frame.contentWindow.print();
|
|
|
|
|
}
|
|
|
|
|
return { open, preview, print };
|
|
|
|
|
})();
|