// 引入工具
|
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 = '<ul style="font-family: 宋体; font-size: 12pt; line-height: 1.5;">';
|
|
items.forEach(item => {
|
listHtml += `<li style="margin-bottom: 6pt;">${item.label}`;
|
|
if (item.children && item.children.length > 0) {
|
listHtml += buildList(item.children);
|
}
|
|
listHtml += '</li>';
|
});
|
|
listHtml += '</ul>';
|
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;
|
}
|
});
|
}
|