祖安之光
3 天以前 4d99171d6e935ba2060ae0af723a8e2db72d22d6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// 引入工具
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;
        }
    });
}