From 73954cf4e71efa28ac959b7611e7e882f56802a2 Mon Sep 17 00:00:00 2001 From: = <=> Date: Wed, 15 Jul 2026 11:13:08 +0800 Subject: [PATCH] commit --- .../common/ProposalCommonServiceImpl.java | 70 +++++++++++++++++-- 1 file changed, 65 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/budwk/app/zhgh/democratic/proposal/service/common/ProposalCommonServiceImpl.java b/src/main/java/com/budwk/app/zhgh/democratic/proposal/service/common/ProposalCommonServiceImpl.java index 4e2188d0..b19294ff 100644 --- a/src/main/java/com/budwk/app/zhgh/democratic/proposal/service/common/ProposalCommonServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/democratic/proposal/service/common/ProposalCommonServiceImpl.java @@ -632,8 +632,11 @@ public class ProposalCommonServiceImpl extends BaseServiceImpl imp } // 按任务节点分组 - Map> taskGroups = doneTaskVos.stream().collect(Collectors.groupingBy(ProcessTaskVO::getDisplayName)); + Map> taskGroups = doneTaskVos.stream() + .filter(Objects::nonNull) + .collect(Collectors.groupingBy(ProcessTaskVO::getDisplayName)); docData.putAll(taskGroups); + putProposalExportTaskAliases(id, taskGroups, docData); // 提案附议 List secondInfos = new ArrayList<>(); @@ -704,22 +707,79 @@ public class ProposalCommonServiceImpl extends BaseServiceImpl 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 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> taskGroups, + NutMap docData) { + putTaskAlias(docData, "提案委主任审核", taskGroups.get("校工会预审核")); + putTaskAlias(docData, "提案委主任意见", taskGroups.get("提案委员会立案")); + putTaskAlias(docData, "提案委委员审议", taskGroups.get("委员会确认承办单位")); + + List 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 masterUnitRows = listMap(masterUnitSql); + Set masterUnitNames = masterUnitRows.stream() + .map(row -> row.getString("unitName")) + .filter(StrUtil::isNotBlank) + .collect(Collectors.toSet()); + + List masterReplyTasks = new ArrayList<>(); + List 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 tasks) { + if (Lang.isNotEmpty(tasks)) { + docData.put(templateKey, tasks); + } + } + @Override public void exportProposalFeedBackAsDocx(String id, ByteArrayOutputStream byteArrayOutputStream) { if (id == null || id.isEmpty()) {