2025-12-11 18:18:38 +08:00
|
|
|
|
import { saveAs } from 'file-saver';
|
|
|
|
|
|
import html2pdf from 'html2pdf.js';
|
|
|
|
|
|
|
|
|
|
|
|
const isDOM = (obj) => obj instanceof HTMLElement;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 导出 PDF
|
|
|
|
|
|
* @param {HTMLElement} dom 目标 DOM 元素
|
|
|
|
|
|
* @param {string} name 文件名
|
|
|
|
|
|
*/
|
|
|
|
|
|
export const downloadPDF = async (dom, name = '导出文件') => {
|
2025-12-11 18:44:06 +08:00
|
|
|
|
if (!isDOM(dom)) return;
|
2025-12-11 18:18:38 +08:00
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 等待一段时间确保所有图表完全渲染
|
|
|
|
|
|
await new Promise(resolve => setTimeout(resolve, 1500));
|
|
|
|
|
|
|
|
|
|
|
|
// 强制重新渲染所有图表
|
|
|
|
|
|
const resizeEvent = new Event('resize');
|
|
|
|
|
|
window.dispatchEvent(resizeEvent);
|
|
|
|
|
|
|
|
|
|
|
|
// 再次等待图表重绘完成
|
|
|
|
|
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
|
|
|
|
|
|
|
|
|
|
// 获取内容的实际高度
|
|
|
|
|
|
const contentHeight = dom.scrollHeight;
|
|
|
|
|
|
|
|
|
|
|
|
// 计算需要的页面尺寸(单位:毫米)
|
|
|
|
|
|
// 将像素转换为毫米(1px ≈ 0.264583mm)
|
|
|
|
|
|
const a4HeightMm = 297; // A4纸高度
|
|
|
|
|
|
const contentHeightMm = contentHeight * 0.264583;
|
|
|
|
|
|
|
|
|
|
|
|
const opt = {
|
|
|
|
|
|
margin: [10, 10, 20, 10], // [top, right, bottom, left] 格式
|
|
|
|
|
|
filename: name + '.pdf',
|
|
|
|
|
|
image: {
|
|
|
|
|
|
type: 'png',
|
|
|
|
|
|
quality: 1
|
|
|
|
|
|
},
|
|
|
|
|
|
html2canvas: {
|
|
|
|
|
|
scale: 1.5,
|
|
|
|
|
|
useCoRs: true,
|
|
|
|
|
|
allowTaint: true,
|
|
|
|
|
|
foreignObjectRendering: false,
|
|
|
|
|
|
logging: false,
|
|
|
|
|
|
width: dom.scrollWidth,
|
|
|
|
|
|
height: dom.scrollHeight + 100, // 增加额外高度,包含底部内容
|
|
|
|
|
|
scrollX: 0,
|
|
|
|
|
|
scrollY: 0
|
|
|
|
|
|
},
|
|
|
|
|
|
jsPDF: {
|
|
|
|
|
|
unit: 'mm',
|
|
|
|
|
|
format: [210, contentHeightMm + 40], // 自定义页面高度,确保所有内容都在一页
|
|
|
|
|
|
orientation: "portrait"
|
|
|
|
|
|
},
|
|
|
|
|
|
pagebreak: {
|
|
|
|
|
|
mode: "avoid", // 尽量避免在元素中间分页
|
|
|
|
|
|
before: '.analysis-report-box h2', // 在h2标题前避免分页
|
|
|
|
|
|
after: '.analysis-report-box h2', // 在h2标题后避免分页
|
|
|
|
|
|
avoid: '.analysis-report-box p' // 避免在段落中间分页
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
await html2pdf().set(opt).from(dom).save();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('PDF导出失败:', error);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 带样式的下载方法
|
|
|
|
|
|
export function downloadDocWithStyle(textContent) {
|
|
|
|
|
|
if (typeof textContent !== 'string') return;
|
|
|
|
|
|
const wordDocument = `
|
|
|
|
|
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" >
|
|
|
|
|
|
<head>
|
|
|
|
|
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
|
|
|
|
|
<title>富文本导出</title>
|
|
|
|
|
|
<style>
|
|
|
|
|
|
/* 应用两端对齐样式 */
|
|
|
|
|
|
body {
|
|
|
|
|
|
text-align: justify;
|
|
|
|
|
|
text-justify: inter-character; /* 中文文本两端对齐 */
|
|
|
|
|
|
font-family: "Microsoft YaHei", Arial, sans-serif;
|
|
|
|
|
|
}
|
|
|
|
|
|
p {
|
|
|
|
|
|
text-align: justify;
|
|
|
|
|
|
text-justify: inter-character;
|
|
|
|
|
|
}
|
2025-12-11 18:44:06 +08:00
|
|
|
|
.center-subtitle {
|
|
|
|
|
|
display: flex;align-items: center;justify-content: space-between; color: red;margin-top: 30px;padding: 0 30px;font-size: 18px;font-weight: 700;
|
|
|
|
|
|
}
|
2025-12-11 18:18:38 +08:00
|
|
|
|
</style>
|
|
|
|
|
|
</head>
|
|
|
|
|
|
<body>
|
|
|
|
|
|
${textContent}
|
|
|
|
|
|
</body>
|
|
|
|
|
|
</html>
|
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
|
|
const blob = new Blob([wordDocument], {
|
|
|
|
|
|
type: 'application/msword'
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
saveAs(blob, 'styled-document.doc');
|
|
|
|
|
|
};
|