Files
flowable_management/base-fast/Word模板配置说明.md
2026-01-31 15:51:23 +08:00

9.9 KiB
Raw Blame History

Word合同模板配置说明

📋 问题原因

Word模板中的动态列表数据渲染失败主要原因是

  1. 没有配置 LoopRowTableRenderPolicy 循环行渲染策略
  2. 数据格式不匹配直接传JSONArray而不是List
  3. 模板语法使用不正确

解决方案

1. Word模板正确语法

在Word模板的表格中需要使用以下格式

┌─────────┬──────────┬──────────┬──────┬──────┬──────────┬──────────┬──────┐
│  序号   │ 产品名称  │   型号   │ 数量 │ 单位 │ 单价(元) │ 总价(元) │ 备注 │
├─────────┼──────────┼──────────┼──────┼──────┼──────────┼──────────┼──────┤
│{{#rows}}│          │          │      │      │          │          │      │
├─────────┼──────────┼──────────┼──────┼──────┼──────────┼──────────┼──────┤
│{{seq}}  │{{materialName}}│{{materialSpec}}│{{qty}}│{{unitName}}│{{salePrice}}│{{amount}}│{{remark}}│
├─────────┼──────────┼──────────┼──────┼──────┼──────────┼──────────┼──────┤
│{{/rows}}│          │          │      │      │          │          │      │
└─────────┴──────────┴──────────┴──────┴──────┴──────────┴──────────┴──────┘

重要说明

  • {{#rows}} 必须单独占一行(表格的一行)
  • 数据行包含所有字段:{{seq}}, {{materialName}}
  • {{/rows}} 必须单独占一行(表格的一行)
  • 这三行构成一个完整的循环结构

2. 模板文件位置

将模板文件放在以下位置之一:

方式1放在resources目录推荐

src/main/resources/templates/contract_template.docx

方式2使用绝对路径

/Users/mima0000/Desktop/合同.docx

3. 后端代码关键点

3.1 配置循环行策略

LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
Configure config = Configure.builder()
        .bind("rows", policy) // 绑定rows标签
        .build();

3.2 数据格式转换

// 错误方式 ❌
dataMap.put("rows", JSONArray.parseArray(materialJson));

// 正确方式 ✅
List<Map<String, Object>> rowsList = new ArrayList<>();
for (int i = 0; i < materialArray.size(); i++) {
    JSONObject item = materialArray.getJSONObject(i);
    Map<String, Object> rowData = new HashMap<>();
    rowData.put("seq", i + 1);
    rowData.put("materialName", item.getString("materialName"));
    // ... 其他字段
    rowsList.add(rowData);
}
dataMap.put("rows", rowsList);

3.3 使用配置渲染

XWPFTemplate template = XWPFTemplate.compile(templateStream, config)
        .render(dataMap);

🎯 完整的Word模板示例

模板结构

服务合同

需方:{{clientName}}                    合同编号:{{contractCode}}
供方:上海诺力智能科技有限公司          签订时间:{{effectiveDate}}

一、产品明细单

┌─────────┬──────────┬──────────┬──────┬──────┬──────────┬──────────┬──────┐
│  序号   │ 产品名称  │   型号   │ 数量 │ 单位 │ 单价(元) │ 总价(元) │ 备注 │
├─────────┼──────────┼──────────┼──────┼──────┼──────────┼──────────┼──────┤
│{{#rows}}│          │          │      │      │          │          │      │
├─────────┼──────────┼──────────┼──────┼──────┼──────────┼──────────┼──────┤
│{{seq}}  │{{materialName}}│{{materialSpec}}│{{qty}}│{{unitName}}│{{salePrice}}│{{amount}}│{{remark}}│
├─────────┼──────────┼──────────┼──────┼──────┼──────────┼──────────┼──────┤
│{{/rows}}│          │          │      │      │          │          │      │
├─────────┴──────────┴──────────┴──────┴──────┴──────────┼──────────┼──────┤
│                                              共计:      │{{totalPrice}}│      │
└──────────────────────────────────────────────┴──────────┴──────┘

二、质量要求:{{qc}}
三、交货时间、地点:货期:{{delivery}},交货地:{{place}}
四、运输方式:{{transport}}
五、包装标准:{{packaging}}
六、结算方式:{{pay}},付款方式:{{payment}}
七、违约责任:{{breach}}
八、解决合同纠纷的方式:{{solve_dispute}}
九、其它约定事项:{{supplement}}

┌──────────────────────────────┬──────────────────────────────┐
│           需方:              │           供方:              │
├──────────────────────────────┼──────────────────────────────┤
│单位名称:{{clientName}}       │单位名称:上海诺力智能科技有限公司│
│地址:{{clientAdd}}            │地址:上海青浦区徐泾镇...      │
│委托代理人:{{juridicalPerson}}│委托代理人:                   │
│电话:{{clientTel}}            │电话:                         │
│传真:{{clientFax}}            │传真:                         │
│开户银行:{{clientBank}}       │开户银行:招商银行虹桥支行     │
│帐号:{{clientCard}}           │帐号12191702501091          │
└──────────────────────────────┴──────────────────────────────┘

📝 字段说明

基本信息字段

字段名 说明 示例
clientName 客户名称 XX公司
contractCode 合同编号 HT20250101
effectiveDate 生效日期 2025年01月01日
totalPrice 总价 100000.00

列表字段rows

字段名 说明 示例
seq 序号 1, 2, 3...
materialName 产品名称 叉车
materialSpec 型号 CPD15
qty 数量 10
unitName 单位
salePrice 单价 50000.00
amount 总价 500000.00
remark 备注 含税

合同条款字段

字段名 说明
qc 质量要求
delivery 交货时间
place 交货地点
transport 运输方式
packaging 包装标准
pay 结算方式
payment 付款方式
breach 违约责任
solve_dispute 解决纠纷方式
supplement 其它约定

客户信息字段

字段名 说明
clientAdd 客户地址
juridicalPerson 法人代表
clientTel 客户电话
clientFax 客户传真
clientBank 客户开户行
clientCard 客户账号

🔧 常见问题

1. 列表数据不显示

原因:没有配置 LoopRowTableRenderPolicy 解决:在代码中添加配置

Configure config = Configure.builder()
        .bind("rows", policy)
        .build();

2. 列表只显示一行

原因:模板中 {{#rows}}{{/rows}} 没有单独占一行 解决:确保循环标签单独占表格的一行

3. 数据格式错误

原因直接传JSONArray而不是List 解决转换为List<Map<String, Object>>格式

4. 中文乱码

原因:文件名编码问题 解决使用URLEncoder编码文件名

String fileName = java.net.URLEncoder.encode("合同.docx", "UTF-8");

🎉 测试步骤

  1. 准备模板文件

    • 按照上述格式创建Word模板
    • 保存为 contract_template.docx
    • 放到 src/main/resources/templates/ 目录
  2. 测试导出

    • 访问:GET /flow/contract/export?contractId=1
    • 检查下载的Word文档
    • 验证列表数据是否正确显示
  3. 验证数据

    • 打开导出的Word文档
    • 检查产品明细表是否有多行数据
    • 检查所有字段是否正确填充

💡 最佳实践

  1. 模板管理

    • 将模板文件放在resources目录
    • 使用版本控制管理模板
    • 为不同类型合同创建不同模板
  2. 错误处理

    • 添加try-catch捕获异常
    • 记录详细的错误日志
    • 返回友好的错误提示
  3. 性能优化

    • 缓存模板对象
    • 使用流式处理大文件
    • 异步处理导出任务

📚 参考资料


更新时间: 2026-01-30
版本: v1.0