백테스팅 분석결과 레포트 출력
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
/**
|
||||
* 레포트 HTML을 별도 iframe 문서로 열어 인쇄·PDF 저장 (메인 앱 visibility 인쇄 버그 회피)
|
||||
*/
|
||||
|
||||
/** App.css 전체 로드 전에도 PDF 다페이지·하단 잘림 방지 */
|
||||
const CRITICAL_PRINT_CSS = `
|
||||
@media print {
|
||||
html, body {
|
||||
height: auto !important;
|
||||
overflow: visible !important;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
.btd-report-print-doc,
|
||||
.btd-report-print-area,
|
||||
.brd-dashboard,
|
||||
.brd-dashboard--report {
|
||||
overflow: visible !important;
|
||||
max-height: none !important;
|
||||
min-height: 0 !important;
|
||||
height: auto !important;
|
||||
font-family: 'Apple SD Gothic Neo', 'Malgun Gothic', 'Noto Sans KR', sans-serif !important;
|
||||
}
|
||||
.brd-dashboard {
|
||||
break-inside: auto !important;
|
||||
page-break-inside: auto !important;
|
||||
}
|
||||
.brd-row,
|
||||
.brd-row--2col,
|
||||
.brd-row--3col,
|
||||
.brd-card,
|
||||
.brd-card--full {
|
||||
break-inside: auto !important;
|
||||
page-break-inside: auto !important;
|
||||
overflow: visible !important;
|
||||
}
|
||||
.brd-kpi-grid {
|
||||
break-inside: auto !important;
|
||||
page-break-inside: auto !important;
|
||||
}
|
||||
.brd-kpi-card,
|
||||
.brd-dash-header {
|
||||
break-inside: avoid !important;
|
||||
page-break-inside: avoid !important;
|
||||
}
|
||||
.brd-sig-scroll {
|
||||
max-height: none !important;
|
||||
overflow: visible !important;
|
||||
height: auto !important;
|
||||
}
|
||||
.brd-expand-btn {
|
||||
display: none !important;
|
||||
}
|
||||
.btd-report-print-footer {
|
||||
break-inside: avoid !important;
|
||||
page-break-inside: avoid !important;
|
||||
}
|
||||
}
|
||||
@page {
|
||||
size: A4 portrait;
|
||||
margin: 10mm;
|
||||
}
|
||||
`;
|
||||
|
||||
const FONT_LINKS = `
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@400;500;700&display=swap" rel="stylesheet">
|
||||
`;
|
||||
|
||||
function escapeHtml(s: string): string {
|
||||
return s
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"');
|
||||
}
|
||||
|
||||
function collectDocumentStyles(): string {
|
||||
const links = Array.from(document.querySelectorAll<HTMLLinkElement>('link[rel="stylesheet"]'))
|
||||
.filter(l => l.href && !l.href.includes('fonts.googleapis.com'))
|
||||
.map(l => `<link rel="stylesheet" href="${l.href}">`);
|
||||
const inline = Array.from(document.querySelectorAll('style'))
|
||||
.map(s => s.outerHTML);
|
||||
return [...links, ...inline].join('\n');
|
||||
}
|
||||
|
||||
export function printReportDocument(contentHtml: string, documentTitle: string): void {
|
||||
const iframe = document.createElement('iframe');
|
||||
iframe.setAttribute('title', 'print');
|
||||
iframe.style.cssText = 'position:fixed;width:0;height:0;border:0;left:-9999px;top:0;';
|
||||
document.body.appendChild(iframe);
|
||||
|
||||
const win = iframe.contentWindow;
|
||||
const doc = win?.document;
|
||||
if (!doc) {
|
||||
iframe.remove();
|
||||
return;
|
||||
}
|
||||
|
||||
doc.open();
|
||||
doc.write(`<!DOCTYPE html>
|
||||
<html lang="ko">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>${escapeHtml(documentTitle)}</title>
|
||||
${FONT_LINKS}
|
||||
${collectDocumentStyles()}
|
||||
<style>${CRITICAL_PRINT_CSS}</style>
|
||||
</head>
|
||||
<body class="btd-report-print-doc"></body>
|
||||
</html>`);
|
||||
doc.close();
|
||||
|
||||
if (doc.body) {
|
||||
doc.body.insertAdjacentHTML('beforeend', contentHtml);
|
||||
}
|
||||
|
||||
let printed = false;
|
||||
const runPrint = () => {
|
||||
if (printed) return;
|
||||
printed = true;
|
||||
try {
|
||||
win?.focus();
|
||||
win?.print();
|
||||
} finally {
|
||||
window.setTimeout(() => iframe.remove(), 2000);
|
||||
}
|
||||
};
|
||||
|
||||
iframe.addEventListener('load', () => {
|
||||
window.setTimeout(runPrint, 500);
|
||||
}, { once: true });
|
||||
|
||||
window.setTimeout(runPrint, 900);
|
||||
}
|
||||
Reference in New Issue
Block a user