|
@@ -0,0 +1,158 @@
|
|
|
|
+// 导出工具文件 export-utils.js
|
|
|
|
+import { asBlob } from 'html-docx-js-typescript';
|
|
|
|
+import jsPDF from 'jspdf';
|
|
|
|
+import html2canvas from 'html2canvas';
|
|
|
|
+const exportUtils = {
|
|
|
|
+ // 导出Word
|
|
|
|
+ exportWord(htmlContent, fileName = 'document.docx') {
|
|
|
|
+ const content = `
|
|
|
|
+ <!DOCTYPE html>
|
|
|
|
+ <html>
|
|
|
|
+ <head>
|
|
|
|
+ <meta charset="utf-8">
|
|
|
|
+ <title>${fileName.replace('.docx', '')}</title>
|
|
|
|
+ </head>
|
|
|
|
+ <body>${htmlContent}</body>
|
|
|
|
+ </html>
|
|
|
|
+ `;
|
|
|
|
+
|
|
|
|
+ asBlob(content).then((data) => {
|
|
|
|
+ const url = URL.createObjectURL(data);
|
|
|
|
+ const a = document.createElement('a');
|
|
|
|
+ a.href = url;
|
|
|
|
+ a.download = fileName;
|
|
|
|
+ a.click();
|
|
|
|
+ URL.revokeObjectURL(url);
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ async exportPDF(element, fileName = 'document.pdf', options = {}) {
|
|
|
|
+ try {
|
|
|
|
+ // 创建隐藏的iframe
|
|
|
|
+ const iframe = document.createElement('iframe');
|
|
|
|
+ iframe.style.cssText = `
|
|
|
|
+ position: fixed;
|
|
|
|
+ top: -9999px;
|
|
|
|
+ left: -9999px;
|
|
|
|
+ width: 794px; // A4宽度(210mm)减去边距,约794px(96dpi)
|
|
|
|
+ height: 1123px; // A4高度(297mm)约1123px
|
|
|
|
+ border: none;
|
|
|
|
+ visibility: hidden;
|
|
|
|
+ `;
|
|
|
|
+ document.body.appendChild(iframe);
|
|
|
|
+
|
|
|
|
+ // 准备iframe内容
|
|
|
|
+ const content = typeof element === 'string' ? element : element.outerHTML;
|
|
|
|
+ const style =
|
|
|
|
+ options.style ||
|
|
|
|
+ `
|
|
|
|
+ body {
|
|
|
|
+ margin: 0;
|
|
|
|
+ padding: 10mm;
|
|
|
|
+ font-size: 12pt;
|
|
|
|
+ font-family: "SimSun", "宋体", serif;
|
|
|
|
+ }
|
|
|
|
+ p {
|
|
|
|
+ text-indent: 2em;
|
|
|
|
+ margin: 0 0 12pt 0;
|
|
|
|
+ padding: 0;
|
|
|
|
+ line-height: 1.5;
|
|
|
|
+ }
|
|
|
|
+ table {
|
|
|
|
+ width: 100%;
|
|
|
|
+ border-collapse: collapse;
|
|
|
|
+ }
|
|
|
|
+ td, th {
|
|
|
|
+ border: 1px solid #ddd;
|
|
|
|
+ padding: 4px;
|
|
|
|
+ }
|
|
|
|
+ `;
|
|
|
|
+ // 写入iframe内容
|
|
|
|
+ iframe.contentDocument.open();
|
|
|
|
+ iframe.contentDocument.write(`
|
|
|
|
+ <!DOCTYPE html>
|
|
|
|
+ <html>
|
|
|
|
+ <head>
|
|
|
|
+ <meta charset="utf-8">
|
|
|
|
+ <style>${style}</style>
|
|
|
|
+ ${options.customCSS ? `<style>${options.customCSS}</style>` : ''}
|
|
|
|
+ </head>
|
|
|
|
+ <body>${content}</body>
|
|
|
|
+ </html>
|
|
|
|
+ `);
|
|
|
|
+ iframe.contentDocument.close();
|
|
|
|
+
|
|
|
|
+ // 等待iframe内容加载完成
|
|
|
|
+ await new Promise((resolve) => {
|
|
|
|
+ iframe.onload = resolve;
|
|
|
|
+ // 确保即使onload不触发也能继续
|
|
|
|
+ setTimeout(resolve, 500);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ // 默认配置
|
|
|
|
+ const defaultOptions = {
|
|
|
|
+ scale: 2,
|
|
|
|
+ logging: false,
|
|
|
|
+ useCORS: true,
|
|
|
|
+ allowTaint: true,
|
|
|
|
+ backgroundColor: '#ffffff',
|
|
|
|
+ width: 794,
|
|
|
|
+ windowWidth: 794,
|
|
|
|
+ letterRendering: true,
|
|
|
|
+ // 使用iframe的body作为渲染目标
|
|
|
|
+ foreignObjectRendering: true,
|
|
|
|
+ // 确保iframe内容完全加载
|
|
|
|
+ async: true,
|
|
|
|
+ onclone: (clonedDoc) => {
|
|
|
|
+ // 可以在这里对克隆的文档进行最后调整
|
|
|
|
+ if (options.onClone) {
|
|
|
|
+ options.onClone(clonedDoc);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ // 合并配置
|
|
|
|
+ const canvasOptions = { ...defaultOptions, ...options };
|
|
|
|
+
|
|
|
|
+ // 使用iframe的body作为渲染目标
|
|
|
|
+ const canvas = await html2canvas(iframe.contentDocument.body, canvasOptions);
|
|
|
|
+
|
|
|
|
+ // 创建PDF
|
|
|
|
+ const imgData = canvas.toDataURL('image/png');
|
|
|
|
+ const pdf = new jsPDF('p', 'mm', 'a4');
|
|
|
|
+ const imgWidth = 190; // A4宽度减去边距(210-20)
|
|
|
|
+ const imgHeight = (canvas.height * imgWidth) / canvas.width;
|
|
|
|
+
|
|
|
|
+ pdf.addImage(imgData, 'PNG', 10, 10, imgWidth, imgHeight);
|
|
|
|
+
|
|
|
|
+ // 处理多页内容(如果需要)
|
|
|
|
+ let heightLeft = imgHeight - (297 - 20); // 剩余高度
|
|
|
|
+ let position = 10; // 当前位置
|
|
|
|
+ let pageCount = 1;
|
|
|
|
+
|
|
|
|
+ while (heightLeft >= 0 && pageCount < 10) {
|
|
|
|
+ // 限制最多10页
|
|
|
|
+ pdf.addPage();
|
|
|
|
+ position = heightLeft - imgHeight;
|
|
|
|
+ pdf.addImage(imgData, 'PNG', 10, position, imgWidth, imgHeight);
|
|
|
|
+ heightLeft -= 297 - 20;
|
|
|
|
+ pageCount++;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 保存文件
|
|
|
|
+ pdf.save(fileName);
|
|
|
|
+
|
|
|
|
+ // 移除iframe
|
|
|
|
+ document.body.removeChild(iframe);
|
|
|
|
+
|
|
|
|
+ return true;
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error('导出PDF失败:', error);
|
|
|
|
+ // 确保出错时也移除iframe
|
|
|
|
+ const iframes = document.querySelectorAll('iframe[style*="-9999px"]');
|
|
|
|
+ iframes.forEach((iframe) => document.body.removeChild(iframe));
|
|
|
|
+ throw error;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+export default exportUtils;
|