// 引入工具 import PizZip from 'pizzip'; import Docxtemplater from 'docxtemplater'; import JSZipUtils from 'jszip-utils'; import { saveAs } from 'file-saver'; // 加载 .docx 模板文件 function loadFile(url, callback) { JSZipUtils.getBinaryContent(url, callback); } // 下载生成的文档 export function download(file, name) { saveAs(file, name); } // 处理富文本,提取段落和缩进信息 function processRichText(html) { if (!html) return ''; // 将HTML字符串转换为DOM对象 const parser = new DOMParser(); const doc = parser.parseFromString(html, 'text/html'); let result = []; // 处理普通段落 const paragraphs = doc.querySelectorAll('p'); paragraphs.forEach(p => { const style = p.getAttribute('style') || ''; const indentMatch = style.match(/text-indent:\s*(\d+)pt/); const indent = indentMatch ? parseInt(indentMatch[1]) / 24 : 0; const text = p.textContent.trim(); if (text) { const indentStr = indent > 0 ? ' '.repeat(indent) : ''; result.push(indentStr + text); } }); // 处理列表(ul/li) const lists = doc.querySelectorAll('ul'); lists.forEach(ul => { const lis = ul.querySelectorAll('li'); lis.forEach(li => { // 计算缩进层级 let parent = li.parentElement; let indentLevel = 0; while (parent && parent !== ul) { if (parent.tagName === 'UL') indentLevel++; parent = parent.parentElement; } const text = li.textContent.trim(); if (text) { // 使用不同符号表示不同层级 const bullets = ['▪', '•', '▫', '◦']; const bullet = bullets[Math.min(indentLevel, bullets.length - 1)]; const indentStr = ' '.repeat(indentLevel); result.push(indentStr + bullet + ' ' + text); } }); }); return result.join('\n\n'); // 用两个换行符分隔段落 } function convertTreeToHtml(data) { let html = ''; function buildList(items) { let listHtml = ''; return listHtml; } html = buildList(data); return html; } // 生成并下载 Word 文档 export function generateWordDocument(templatePath, data, name) { // 处理富文本字段(如果有) if (data.summaries && typeof data.summaries === 'string') { data.summaries = processRichText(data.summaries); } if (data.policies && typeof data.policies === 'string') { data.policies = processRichText(data.policies); } // 处理树形结构数据(如果有) if (data.deptList && Array.isArray(data.deptList)) { data.departmentsHtml = processRichText(convertTreeToHtml(data.deptList)); } loadFile(templatePath, function (error, content) { if (error) { throw error; } try { // 加载模板文件内容到 PizZip const zip = new PizZip(content); const doc = new Docxtemplater(zip, { paragraphLoop: true, linebreaks: true, }); // 设置模板中的占位符数据 doc.setData(data); // 渲染文档 doc.render(); // 生成最终的文档 Blob const fileWord = doc.getZip().generate({ type: 'blob', mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', }); saveAs(fileWord, name); } catch (error) { console.error('Error rendering document:', error); throw error; } }); }