Optimize Export to PDF
This commit is contained in:
@@ -2062,6 +2062,12 @@ body.exporting {{
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
}}
|
}}
|
||||||
|
.exporting *,
|
||||||
|
.exporting *::before,
|
||||||
|
.exporting *::after {{
|
||||||
|
animation: none !important;
|
||||||
|
transition: none !important;
|
||||||
|
}}
|
||||||
.export-progress {{
|
.export-progress {{
|
||||||
width: 220px;
|
width: 220px;
|
||||||
height: 6px;
|
height: 6px;
|
||||||
@@ -2121,6 +2127,10 @@ ul, ol {{
|
|||||||
margin-left: 1.5em;
|
margin-left: 1.5em;
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
}}
|
}}
|
||||||
|
img, canvas, svg {{
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}}
|
||||||
.meta-card {{
|
.meta-card {{
|
||||||
background: rgba(0,0,0,0.02);
|
background: rgba(0,0,0,0.02);
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
@@ -2344,21 +2354,38 @@ pre.code-block {{
|
|||||||
}}
|
}}
|
||||||
.chapter > *,
|
.chapter > *,
|
||||||
.hero-section,
|
.hero-section,
|
||||||
.callout,
|
.callout,
|
||||||
.chart-card,
|
.chart-card,
|
||||||
.kpi-grid,
|
.kpi-grid,
|
||||||
.table-wrap,
|
.table-wrap,
|
||||||
figure,
|
figure,
|
||||||
blockquote {{
|
blockquote {{
|
||||||
break-inside: avoid;
|
break-inside: avoid;
|
||||||
page-break-inside: avoid;
|
page-break-inside: avoid;
|
||||||
}}
|
}}
|
||||||
.chapter h2,
|
.chapter h2,
|
||||||
.chapter h3,
|
.chapter h3,
|
||||||
.chapter h4 {{
|
.chapter h4 {{
|
||||||
break-after: avoid;
|
break-after: avoid;
|
||||||
page-break-after: avoid;
|
page-break-after: avoid;
|
||||||
}}
|
break-inside: avoid;
|
||||||
|
}}
|
||||||
|
.chart-card,
|
||||||
|
.table-wrap {{
|
||||||
|
overflow: visible !important;
|
||||||
|
}}
|
||||||
|
.chart-card canvas {{
|
||||||
|
width: 100% !important;
|
||||||
|
height: auto !important;
|
||||||
|
}}
|
||||||
|
.table-wrap table {{
|
||||||
|
table-layout: fixed;
|
||||||
|
width: 100%;
|
||||||
|
}}
|
||||||
|
.table-wrap table th,
|
||||||
|
.table-wrap table td {{
|
||||||
|
word-break: break-word;
|
||||||
|
}}
|
||||||
}}
|
}}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -2821,6 +2848,7 @@ function exportPdf() {
|
|||||||
exportBtn.disabled = true;
|
exportBtn.disabled = true;
|
||||||
}
|
}
|
||||||
showExportOverlay('正在导出PDF,请稍候...');
|
showExportOverlay('正在导出PDF,请稍候...');
|
||||||
|
document.body.classList.add('exporting');
|
||||||
const pdf = new jspdf.jsPDF('p', 'mm', 'a4');
|
const pdf = new jspdf.jsPDF('p', 'mm', 'a4');
|
||||||
try {
|
try {
|
||||||
if (window.pdfFontData) {
|
if (window.pdfFontData) {
|
||||||
@@ -2832,14 +2860,25 @@ function exportPdf() {
|
|||||||
console.warn('Custom PDF font setup failed, fallback to default', err);
|
console.warn('Custom PDF font setup failed, fallback to default', err);
|
||||||
}
|
}
|
||||||
const pageWidth = pdf.internal.pageSize.getWidth();
|
const pageWidth = pdf.internal.pageSize.getWidth();
|
||||||
const pxWidth = Math.max(target.scrollWidth, document.documentElement.scrollWidth);
|
const pxWidth = Math.max(
|
||||||
|
target.scrollWidth,
|
||||||
|
document.documentElement.scrollWidth,
|
||||||
|
Math.round(pageWidth * 3.78)
|
||||||
|
);
|
||||||
const restoreButton = () => {
|
const restoreButton = () => {
|
||||||
if (exportBtn) {
|
if (exportBtn) {
|
||||||
exportBtn.disabled = false;
|
exportBtn.disabled = false;
|
||||||
}
|
}
|
||||||
|
document.body.classList.remove('exporting');
|
||||||
};
|
};
|
||||||
let renderTask;
|
let renderTask;
|
||||||
try {
|
try {
|
||||||
|
// force charts to rerender at full width before capture
|
||||||
|
chartRegistry.forEach(chart => {
|
||||||
|
if (chart && typeof chart.resize === 'function') {
|
||||||
|
chart.resize();
|
||||||
|
}
|
||||||
|
});
|
||||||
renderTask = pdf.html(target, {
|
renderTask = pdf.html(target, {
|
||||||
x: 8,
|
x: 8,
|
||||||
y: 12,
|
y: 12,
|
||||||
@@ -2847,14 +2886,24 @@ function exportPdf() {
|
|||||||
margin: [12, 12, 20, 12],
|
margin: [12, 12, 20, 12],
|
||||||
autoPaging: 'text',
|
autoPaging: 'text',
|
||||||
windowWidth: pxWidth,
|
windowWidth: pxWidth,
|
||||||
|
html2canvas: {
|
||||||
|
scale: Math.min(1.2, Math.max(0.8, pageWidth / (target.clientWidth || pageWidth))),
|
||||||
|
useCORS: true,
|
||||||
|
scrollX: 0,
|
||||||
|
scrollY: -window.scrollY,
|
||||||
|
logging: false
|
||||||
|
},
|
||||||
pagebreak: {
|
pagebreak: {
|
||||||
mode: ['css', 'legacy'],
|
mode: ['css', 'legacy'],
|
||||||
avoid: ['.chapter > *', '.callout', '.chart-card', '.table-wrap', '.kpi-grid', '.hero-section']
|
avoid: [
|
||||||
},
|
'.chapter > *',
|
||||||
html2canvas: {
|
'.callout',
|
||||||
scale: 0.72,
|
'.chart-card',
|
||||||
useCORS: true,
|
'.table-wrap',
|
||||||
logging: false
|
'.kpi-grid',
|
||||||
|
'.hero-section'
|
||||||
|
],
|
||||||
|
before: '.chapter-divider'
|
||||||
},
|
},
|
||||||
callback: (doc) => doc.save('report.pdf')
|
callback: (doc) => doc.save('report.pdf')
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user