This commit is contained in:
=
2026-07-15 11:13:08 +08:00
parent 5c46d07f46
commit 73954cf4e7
@@ -632,8 +632,11 @@ public class ProposalCommonServiceImpl extends BaseServiceImpl<ProposalInfo> imp
}
// 按任务节点分组
Map<String, List<ProcessTaskVO>> taskGroups = doneTaskVos.stream().collect(Collectors.groupingBy(ProcessTaskVO::getDisplayName));
Map<String, List<ProcessTaskVO>> taskGroups = doneTaskVos.stream()
.filter(Objects::nonNull)
.collect(Collectors.groupingBy(ProcessTaskVO::getDisplayName));
docData.putAll(taskGroups);
putProposalExportTaskAliases(id, taskGroups, docData);
// 提案附议
List<NutMap> secondInfos = new ArrayList<>();
@@ -704,22 +707,79 @@ public class ProposalCommonServiceImpl extends BaseServiceImpl<ProposalInfo> imp
Configure config = Configure.builder()
.bind("secondedList", policy)
.bind("seconders", policy)
.bind("提案附议", policy)
.bind("提案委委员审议", policy)
.bind("brief", htmlRenderPolicy)
.bind("measures", htmlRenderPolicy)
.bind("taskFormData.tf_opinion", htmlRenderPolicy)
.build();
Map<String, Object> renderDocCellDataMap = MapUtil.of("proposal", docCellDataMap);
renderDocCellDataMap.put("secondedList", secondInfos);
renderDocCellDataMap.put("delegationAuditList", delegationAuditList);
// 数据库模板使用平铺占位符(例如 {{code}}、{{sessionName}}),不能将基础字段嵌套到 proposal 节点。
// 流程节点分组已写入 docData,附议人与代表团审核列表也必须写入同一上下文,才能被模板的循环标签识别。
docData.put("secondedList", secondInfos);
docData.put("delegationAuditList", delegationAuditList);
try {
XWPFTemplate.compile(sysOfficeTemplateUtil.getTemplate("proposal"), config).render(renderDocCellDataMap).writeAndClose(byteArrayOutputStream);
XWPFTemplate.compile(sysOfficeTemplateUtil.getTemplate("proposal"), config).render(docData).writeAndClose(byteArrayOutputStream);
} catch (IOException e) {
log.error("提案导出失败{},提案id:{}", e.getMessage(), id);
}
}
/**
* 将现行工作流节点映射到历史提案表模板使用的区块名称,并按主协办单位拆分办理答复。
* 模板仍使用旧节点名称时,避免已完成的意见和答复因键名不一致而无法渲染。
*
* @param proposalId 提案ID,用于查询主办单位
* @param taskGroups 已完成任务按显示名称分组后的数据
* @param docData Word 模板的平铺渲染数据
*/
private void putProposalExportTaskAliases(String proposalId, Map<String, List<ProcessTaskVO>> taskGroups,
NutMap docData) {
putTaskAlias(docData, "提案委主任审核", taskGroups.get("校工会预审核"));
putTaskAlias(docData, "提案委主任意见", taskGroups.get("提案委员会立案"));
putTaskAlias(docData, "提案委委员审议", taskGroups.get("委员会确认承办单位"));
List<ProcessTaskVO> replyTasks = taskGroups.get("承办单位答复");
if (Lang.isEmpty(replyTasks)) {
return;
}
Sql masterUnitSql = Sqls.create("SELECT unitName FROM proposal_reply_unit WHERE proposalId = @proposalId AND isMaster = 1")
.setParam("proposalId", proposalId);
List<NutMap> masterUnitRows = listMap(masterUnitSql);
Set<String> masterUnitNames = masterUnitRows.stream()
.map(row -> row.getString("unitName"))
.filter(StrUtil::isNotBlank)
.collect(Collectors.toSet());
List<ProcessTaskVO> masterReplyTasks = new ArrayList<>();
List<ProcessTaskVO> slaveReplyTasks = new ArrayList<>();
for (ProcessTaskVO replyTask : replyTasks) {
Dict taskFormData = replyTask.getTaskFormData();
String unitName = taskFormData == null ? null : taskFormData.getStr("unitName");
if (masterUnitNames.contains(unitName)) {
masterReplyTasks.add(replyTask);
} else {
slaveReplyTasks.add(replyTask);
}
}
putTaskAlias(docData, "主办单位答复", masterReplyTasks);
putTaskAlias(docData, "协办单位答复", slaveReplyTasks);
}
/**
* 仅在存在已完成任务时写入模板区块,空任务不触发 Word 条件标签。
*
* @param docData Word 模板的平铺渲染数据
* @param templateKey Word 模板中的条件或循环标签名称
* @param tasks 对应的已完成流程任务
*/
private void putTaskAlias(NutMap docData, String templateKey, List<ProcessTaskVO> tasks) {
if (Lang.isNotEmpty(tasks)) {
docData.put(templateKey, tasks);
}
}
@Override
public void exportProposalFeedBackAsDocx(String id, ByteArrayOutputStream byteArrayOutputStream) {
if (id == null || id.isEmpty()) {