From a965427ce3063e9b4b8ba35dde093aada02f90d0 Mon Sep 17 00:00:00 2001 From: wsm <8454518+new-twice@user.noreply.gitee.com> Date: Mon, 3 Aug 2026 10:43:49 +0000 Subject: [PATCH] =?UTF-8?q?!101=20feat(fixcontact):=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E9=83=A8=E9=97=A8=E9=A2=86=E5=AF=BC=E4=B8=8E=E7=BB=8F=E5=8A=9E?= =?UTF-8?q?=E4=BA=BA=E5=AE=A1=E6=89=B9=E7=9B=91=E5=90=AC=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(fixcontact): 新增部门领导与经办人审批监听器 * feat(fixcontact): 新增部门并行子流程流程表达式方法与常量 * feat(fixcontact): 反馈列表联表查询反馈人与反馈部门名称 * feat(fixcontact): 部门审批信息落库approve_info并新增保存接口 --- .../constant/FixContactConstant.java | 16 ++ .../FixedContact20260730Controller.java | 17 ++ .../entity/FixedContact20260730.java | 9 +- .../entity/FixedContactFeedback20260730.java | 10 + .../bg/fixcontact/flow/FixContactFlow.java | 183 ++++++++++++++++++ .../FixContactDeptLeaderApproveListener.java | 79 ++++++++ .../FixContactWorkerApproveListener.java | 114 +++++++++++ .../FixedContactFeedback20260730Mapper.java | 9 +- .../service/IFixedContact20260730Service.java | 7 + .../impl/FixedContact20260730ServiceImpl.java | 50 +++++ 10 files changed, 492 insertions(+), 2 deletions(-) create mode 100644 jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/listener/FixContactDeptLeaderApproveListener.java create mode 100644 jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/listener/FixContactWorkerApproveListener.java diff --git a/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/constant/FixContactConstant.java b/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/constant/FixContactConstant.java index 89fb531..834f1cb 100644 --- a/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/constant/FixContactConstant.java +++ b/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/constant/FixContactConstant.java @@ -15,6 +15,8 @@ public final class FixContactConstant { public static final String SLD_ROLE_ID = "2062794430936240130"; /** 部门负责人 */ public static final String DEPT_LEADER_ID = "2044680793306591234"; + /** 部门负责人角色编码 */ + public static final String DEPT_LEADER_ROLE_CODE = "ld"; } /** 角色编码 */ @@ -28,6 +30,14 @@ public final class FixContactConstant { public static final class FlowVarName { /** 业务表单ID */ public static final String BUSINESS_KEY = "businessKey"; + /** 子流程当前部门ID(多实例局部变量) */ + public static final String IMPL_DEPT_ID = "impl_dept_id"; + /** 部门领导(子流程局部变量) */ + public static final String TEM_IMPL_LEADER = "tem_impl_leader"; + /** 部门经办人(子流程局部变量) */ + public static final String TEM_IMPL_WORKER = "tem_impl_worker"; + /** 部门经办人(流程变量,前端写入) */ + public static final String SUB_APPROVE_USER = "sub_approve_user"; } /** 业务状态 */ @@ -37,4 +47,10 @@ public final class FixContactConstant { /** 未办结 */ public static final String UNFINISHED = "0"; } + + /** 业务状态 */ + public static final class fieldKey { + /** 已办结 */ + public static final String IS_END_KEY = "is_end"; + } } diff --git a/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/controller/FixedContact20260730Controller.java b/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/controller/FixedContact20260730Controller.java index 6cb8cef..99a5432 100644 --- a/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/controller/FixedContact20260730Controller.java +++ b/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/controller/FixedContact20260730Controller.java @@ -179,6 +179,23 @@ public class FixedContact20260730Controller extends JeecgController saveSubApprove(@RequestBody Map params) { + String mainId = (String) params.get("mainId"); + String deptId = (String) params.get("deptId"); + Integer isEnd = params.get("isEnd") != null ? Integer.valueOf(params.get("isEnd").toString()) : null; + String implWorker = (String) params.get("implWorker"); + @SuppressWarnings("unchecked") + List implUserNameList = (List) params.get("implUserNameList"); + if (oConvertUtils.isEmpty(mainId) || oConvertUtils.isEmpty(deptId)) { + return Result.error("主表ID和部门ID不能为空"); + } + fixedContact20260730Service.saveSubApprove(mainId, deptId, isEnd, implWorker, implUserNameList); + return Result.OK("保存成功"); + } + @AutoLog(value = "反馈子表-添加") @Operation(summary = "反馈子表-添加") @PostMapping(value = "/addFixedContactFeedback20260730") diff --git a/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/entity/FixedContact20260730.java b/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/entity/FixedContact20260730.java index c5e89c9..91795de 100644 --- a/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/entity/FixedContact20260730.java +++ b/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/entity/FixedContact20260730.java @@ -3,8 +3,10 @@ package org.jeecg.modules.bg.fixcontact.entity; import java.io.Serializable; import java.util.Date; import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; import com.fasterxml.jackson.annotation.JsonFormat; import org.springframework.format.annotation.DateTimeFormat; import org.jeecgframework.poi.excel.annotation.Excel; @@ -14,9 +16,10 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; import org.jeecg.common.aspect.annotation.Dict; +import org.jeecg.modules.bg.xispeak.entity.DeptApproveDetailMap; @Data -@TableName("fixed_contact_20260730") +@TableName(value = "fixed_contact_20260730", autoResultMap = true) @Accessors(chain = true) @EqualsAndHashCode(callSuper = false) @Schema(description = "定点联系单") @@ -132,4 +135,8 @@ public class FixedContact20260730 implements Serializable { @Schema(description = "所办领导ID,多个逗号分隔") private java.lang.String supDeptleaderid; + + @TableField(typeHandler = JacksonTypeHandler.class) + @Schema(description = "部门审批信息Map(按部门ID存是否办结与部门经办人)") + private DeptApproveDetailMap approveInfo; } diff --git a/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/entity/FixedContactFeedback20260730.java b/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/entity/FixedContactFeedback20260730.java index 1e15633..f830aa7 100644 --- a/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/entity/FixedContactFeedback20260730.java +++ b/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/entity/FixedContactFeedback20260730.java @@ -3,6 +3,7 @@ package org.jeecg.modules.bg.fixcontact.entity; import java.io.Serializable; import java.util.Date; import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; @@ -25,6 +26,7 @@ public class FixedContactFeedback20260730 implements Serializable { private java.lang.String id; @Schema(description = "主表ID(外键)") + @TableField("fixed_contact_20260730_id") private java.lang.String fixedContact20260730Id; @Schema(description = "创建人") @@ -73,4 +75,12 @@ public class FixedContactFeedback20260730 implements Serializable { @Schema(description = "反馈部门") private java.lang.String feedbackDept; + + @TableField(exist = false) + @Schema(description = "反馈人姓名") + private java.lang.String feedbackUserName; + + @TableField(exist = false) + @Schema(description = "反馈部门名称") + private java.lang.String feedbackDeptName; } diff --git a/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/flow/FixContactFlow.java b/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/flow/FixContactFlow.java index ff4b1eb..0ac095a 100644 --- a/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/flow/FixContactFlow.java +++ b/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/flow/FixContactFlow.java @@ -13,6 +13,8 @@ import org.jeecg.modules.bg.fixcontact.entity.FixedContact20260730; import org.jeecg.modules.bg.fixcontact.entity.FixedContactFeedback20260730; import org.jeecg.modules.bg.fixcontact.service.IFixedContact20260730Service; import org.jeecg.modules.bg.fixcontact.service.IFixedContactFeedback20260730Service; +import org.jeecg.modules.bg.xispeak.entity.DeptApproveDetail; +import org.jeecg.modules.bg.xispeak.entity.DeptApproveDetailMap; import org.jeecg.modules.extbpm.process.common.expression.FlowNodeExpression; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -126,6 +128,28 @@ public class FixContactFlow { return entity.getCoDept(); } + // ${fixContactFlow.getIsNeedBgLdApprove(execution)} + public String getIsNeedBgLdApprove(DelegateExecution execution) { + FixedContact20260730 entity = this.getFixedContact(execution); + if (entity == null) { + log.error("【定点联系-流程表达式】未获取到定点联系单, processInstanceId: {}", + execution.getProcessInstanceId()); + return null; + } + return entity.getIsNeedAppro(); + } + + // ${fixContactFlow.getBgLd(execution)} + public String getBgLd(DelegateExecution execution) { + FixedContact20260730 entity = this.getFixedContact(execution); + if (entity == null) { + log.error("【定点联系-流程表达式】未获取到定点联系单, processInstanceId: {}", + execution.getProcessInstanceId()); + return null; + } + return entity.getSupDeptleaderid(); + } + // ${fixContactFlow.getContactDept(execution)} public String getContactDept(DelegateExecution execution) { FixedContact20260730 entity = this.getFixedContact(execution); @@ -155,6 +179,25 @@ public class FixContactFlow { return this.getOfficeLeaderList(execution).size(); } + // 流程表达式内用法:${fixContactFlow.getIsEnd(execution, dept_id)} + public String getIsEnd(DelegateExecution execution, String deptId) { + if (StringUtils.isBlank(deptId)) { + log.error("【定点联系-流程表达式】传入部门ID为空,无法读取办结状态, processInstanceId: {}", + execution.getProcessInstanceId()); + return null; + } + FixedContact20260730 entity = this.getFixedContact(execution); + if (entity == null || entity.getApproveInfo() == null || entity.getApproveInfo().isEmpty()) { + log.warn("【定点联系-流程表达式】未获取到部门审批信息, processInstanceId: {}", + execution.getProcessInstanceId()); + return null; + } + DeptApproveDetail detail = entity.getApproveInfo().get(deptId); + Integer isEnd = detail != null ? detail.getIsEnd() : null; + log.info("【定点联系-流程表达式】读取部门办结状态, deptId: {}, isEnd: {}", deptId, isEnd); + return isEnd != null ? isEnd.toString() : null; + } + // ${fixContactFlow.getUsersByDeptAndRole(deptId, roleId)} public List getUsersByDeptAndRole(String deptId, String roleId) { log.info("【定点联系-流程表达式】查询部门角色用户列表, deptId: {}, roleId: {}", deptId, roleId); @@ -201,6 +244,45 @@ public class FixContactFlow { return this.getHostDeptLeaderList(execution).size(); } + // ${fixContactFlow.getCurrentDeptId(execution)} + public String getCurrentDeptId(DelegateExecution execution) { + if (execution == null) { + return null; + } + Object deptVar = execution.getVariableLocal(FixContactConstant.FlowVarName.IMPL_DEPT_ID); + if (deptVar == null) { + deptVar = execution.getVariable(FixContactConstant.FlowVarName.IMPL_DEPT_ID); + } + if (deptVar == null) { + log.warn("【定点联系-流程表达式】未获取到子流程当前部门ID, processInstanceId: {}", + execution.getProcessInstanceId()); + return null; + } + return deptVar.toString().replace("[", "").replace("]", "").trim(); + } + + // ${fixContactFlow.getCurrentDeptLeaderList(execution, deptId)} + public List getCurrentDeptLeaderList(DelegateExecution execution, String deptId) { + if (StringUtils.isBlank(deptId)) { + log.error("【定点联系-流程表达式】传入部门ID为空,无法查询部门领导, processInstanceId: {}", + execution.getProcessInstanceId()); + return Collections.emptyList(); + } + List leaderList = this.getUsersByDeptAndRole(deptId, FixContactConstant.RoleCode.DEPT_LEADER_ROLE_CODE); + if (CollectionUtils.isEmpty(leaderList)) { + log.warn("【定点联系-流程表达式】部门: {} 下未配置角色为 {} 的用户,领导列表为空", + deptId, FixContactConstant.RoleCode.DEPT_LEADER_ROLE_CODE); + return Collections.emptyList(); + } + log.info("【定点联系-流程表达式】查询到部门: {} 的领导列表: {}", deptId, leaderList); + return leaderList; + } + + // ${fixContactFlow.getCurrentDeptLeaderListCount(execution, deptId)} + public int getCurrentDeptLeaderListCount(DelegateExecution execution, String deptId) { + return this.getCurrentDeptLeaderList(execution, deptId).size(); + } + // =================================================================== // 反馈子表相关 // =================================================================== @@ -355,10 +437,111 @@ public class FixContactFlow { return getUsersByDeptAndRole(coDept, "ld"); } + // ${fixContactFlow.getDeptIdList(execution)} + public List getDeptIdList(DelegateExecution execution) { + FixedContact20260730 entity = this.getFixedContact(execution); + if (entity == null) { + log.error("【定点联系-流程表达式】未获取到定点联系单,无法组装部门列表, processInstanceId: {}", + execution.getProcessInstanceId()); + return Collections.emptyList(); + } + List deptList = new ArrayList<>(); + if (StringUtils.isNotBlank(entity.getHostDept())) { + deptList.add(entity.getHostDept()); + } + if (StringUtils.isNotBlank(entity.getCoDept())) { + deptList.add(entity.getCoDept()); + } + log.info("【定点联系-流程表达式】已组装主办+协办部门列表: {}, businessKey: {}", + deptList, entity.getId()); + return deptList; + } + + // ${fixContactFlow.getDeptIdListCount(execution)} + public int getDeptIdListCount(DelegateExecution execution) { + return this.getDeptIdList(execution).size(); + } + + // ${fixContactFlow.getTodoUserList(execution)} + public List getTodoUserList(DelegateExecution execution) { + FixedContact20260730 entity = this.getFixedContact(execution); + if (entity == null) { + log.error("【定点联系-流程表达式】未获取到定点联系单,无法获取待办人, processInstanceId: {}", + execution.getProcessInstanceId()); + return Collections.emptyList(); + } + DeptApproveDetailMap approveInfo = entity.getApproveInfo(); + if (approveInfo == null || approveInfo.isEmpty()) { + log.warn("【定点联系-流程表达式】部门审批信息为空,待办人为空, businessKey: {}", entity.getId()); + return Collections.emptyList(); + } + List deptList = this.getDeptIdList(execution); + // LinkedHashSet 去重并保持插入顺序(主办部门经办人优先) + Set todoUserSet = new LinkedHashSet<>(); + for (String deptId : deptList) { + DeptApproveDetail detail = approveInfo.get(deptId); + if (detail == null) { + continue; + } + // isEnd=0 时取多选经办人 implUserNameList,isEnd=1 时取单选经办人 implWorker + if (detail.getImplUserNameList() != null && !detail.getImplUserNameList().isEmpty()) { + todoUserSet.addAll(detail.getImplUserNameList()); + } else if (StringUtils.isNotBlank(detail.getImplWorker())) { + todoUserSet.add(detail.getImplWorker()); + } + } + List todoUserList = new ArrayList<>(todoUserSet); + log.info("【定点联系-流程表达式】已获取部门领导分配的待办人: {}, businessKey: {}", + todoUserList, entity.getId()); + return todoUserList; + } + + // ${fixContactFlow.getTodoUserListLength(execution)} + public int getTodoUserListLength(DelegateExecution execution) { + return this.getTodoUserList(execution).size(); + } + + // ${fixContactFlow.getCurrentDeptWorkerList(execution, deptId)} + public List getCurrentDeptWorkerList(DelegateExecution execution, String deptId) { + DeptApproveDetail detail = this.getDeptApproveDetail(execution, deptId); + if (detail == null) { + log.warn("【定点联系-流程表达式】部门: {} 审批信息为空,经办人为空, processInstanceId: {}", + deptId, execution.getProcessInstanceId()); + return Collections.emptyList(); + } + // isEnd=0 时取多选经办人 implUserNameList,isEnd=1 时取单选经办人 implWorker + if (detail.getImplUserNameList() != null && !detail.getImplUserNameList().isEmpty()) { + return detail.getImplUserNameList(); + } + if (StringUtils.isNotBlank(detail.getImplWorker())) { + return Collections.singletonList(detail.getImplWorker()); + } + return Collections.emptyList(); + } + + // ${fixContactFlow.getCurrentDeptWorkerListCount(execution, deptId)} + public int getCurrentDeptWorkerListCount(DelegateExecution execution, String deptId) { + return this.getCurrentDeptWorkerList(execution, deptId).size(); + } + // =================================================================== // 通用工具方法 // =================================================================== + private DeptApproveDetail getDeptApproveDetail(DelegateExecution execution, String deptId) { + if (execution == null) { + return null; + } + FixedContact20260730 entity = this.getFixedContact(execution); + if (entity == null || entity.getApproveInfo() == null) { + return null; + } + if (StringUtils.isBlank(deptId)) { + return null; + } + return entity.getApproveInfo().get(deptId); + } + private String getStringFromData(Object jsonData, String codeName, String logLabel) { if (jsonData == null || StringUtils.isBlank(codeName)) { return null; diff --git a/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/listener/FixContactDeptLeaderApproveListener.java b/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/listener/FixContactDeptLeaderApproveListener.java new file mode 100644 index 0000000..a05da36 --- /dev/null +++ b/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/listener/FixContactDeptLeaderApproveListener.java @@ -0,0 +1,79 @@ +package org.jeecg.modules.bg.fixcontact.listener; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang.StringUtils; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.delegate.TaskListener; +import org.flowable.engine.runtime.Execution; +import org.flowable.task.service.delegate.DelegateTask; +import org.jeecg.common.util.SpringContextUtils; +import org.jeecg.modules.bg.fixcontact.constant.FixContactConstant; +import org.springframework.stereotype.Component; + +/** + * 部门领导审批完成监听器:将部门领导(assignee)写入上两级执行实例局部变量, + * 供子流程内后续节点(如经办人会签、网关判断)读取当前部门的领导。 + */ +@Slf4j +@Component("FixContactDeptLeaderApproveListener") +public class FixContactDeptLeaderApproveListener implements TaskListener { + + private static final long serialVersionUID = 1L; + private static final String VARIABLE_NAME = FixContactConstant.FlowVarName.TEM_IMPL_LEADER; + + private static RuntimeService runtimeService; + + static { + runtimeService = SpringContextUtils.getBean(RuntimeService.class); + } + + @Override + public void notify(DelegateTask delegateTask) { + if (delegateTask == null) { + return; + } + String assignee = delegateTask.getAssignee(); + if (StringUtils.isBlank(assignee)) { + log.warn("【定点联系-部门领导审批监听器】任务办理人为空,跳过写入领导变量, taskId: {}", delegateTask.getId()); + return; + } + String currentExecutionId = delegateTask.getExecutionId(); + if (StringUtils.isBlank(currentExecutionId)) { + log.warn("【定点联系-部门领导审批监听器】获取执行实例ID失败,跳过写入领导变量, taskId: {}", delegateTask.getId()); + return; + } + + Execution currentExecution = runtimeService.createExecutionQuery() + .executionId(currentExecutionId) + .singleResult(); + if (currentExecution == null) { + return; + } + + // 向上寻找第一层父级(内层会签容器/子流程) + String parentId = currentExecution.getParentId(); + if (StringUtils.isBlank(parentId)) { + log.warn("【定点联系-部门领导审批监听器】未找到父级执行实例,当前已是顶层, executionId: {}", currentExecutionId); + return; + } + + // 通过第一层父级实体对象向上爬取第二层 ID + Execution parentExecution = runtimeService.createExecutionQuery() + .executionId(parentId) + .singleResult(); + if (parentExecution == null) { + return; + } + String grandParentId = parentExecution.getParentId(); + // 有第二层父级则存入第二层(大会签容器/外层作用域),否则存入第一层 + String targetId = StringUtils.isNotBlank(grandParentId) ? grandParentId : parentId; + try { + runtimeService.setVariableLocal(targetId, VARIABLE_NAME, assignee); + log.info("【定点联系-部门领导审批监听器】已存入上两级局部变量, targetExecutionId: {}, variableName: {}, assignee: {}", + targetId, VARIABLE_NAME, assignee); + } catch (Exception e) { + log.error("【定点联系-部门领导审批监听器】设置嵌套局部变量失败, targetExecutionId: {}, assignee: {}", + targetId, assignee, e); + } + } +} diff --git a/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/listener/FixContactWorkerApproveListener.java b/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/listener/FixContactWorkerApproveListener.java new file mode 100644 index 0000000..95ab59a --- /dev/null +++ b/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/listener/FixContactWorkerApproveListener.java @@ -0,0 +1,114 @@ +package org.jeecg.modules.bg.fixcontact.listener; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang.StringUtils; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.delegate.TaskListener; +import org.flowable.task.service.delegate.DelegateTask; +import org.jeecg.modules.bg.fixcontact.constant.FixContactConstant; +import org.jeecg.modules.bg.fixcontact.entity.FixedContact20260730; +import org.jeecg.modules.bg.fixcontact.service.IFixedContact20260730Service; +import org.jeecg.modules.bg.xispeak.entity.DeptApproveDetail; +import org.jeecg.modules.bg.xispeak.entity.DeptApproveDetailMap; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +/** + * 部门经办人会签任务监听器:经办人办理完成后,将当前经办人写入子流程执行实例局部变量 + * (tem_impl_worker),并记录到业务表单 approveInfo 对应部门的经办人列表,供会签统计与展示使用。 + */ +@Slf4j +@Component("FixContactWorkerApproveListener") +@RequiredArgsConstructor(onConstructor_ = @Autowired) +public class FixContactWorkerApproveListener implements TaskListener { + + private static final long serialVersionUID = 1L; + + private final IFixedContact20260730Service fixedContact20260730Service; + private final RuntimeService runtimeService; + + @Override + @Transactional(rollbackFor = Exception.class) + public void notify(DelegateTask delegateTask) { + if (delegateTask == null) { + return; + } + String currentWorker = delegateTask.getAssignee(); + if (StringUtils.isBlank(currentWorker)) { + log.warn("【定点联系-经办人会签监听器】任务办理人为空,跳过写入经办人变量, taskId: {}", delegateTask.getId()); + return; + } + + // 1. 将当前经办人写入子流程执行实例局部变量 + String executionId = delegateTask.getExecutionId(); + if (StringUtils.isNotBlank(executionId)) { + try { + runtimeService.setVariableLocal(executionId, FixContactConstant.FlowVarName.TEM_IMPL_WORKER, currentWorker); + log.info("【定点联系-经办人会签监听器】已写入经办人局部变量, executionId: {}, variableName: {}, worker: {}", + executionId, FixContactConstant.FlowVarName.TEM_IMPL_WORKER, currentWorker); + } catch (Exception e) { + log.error("【定点联系-经办人会签监听器】写入经办人局部变量失败, executionId: {}, worker: {}", + executionId, currentWorker, e); + } + } else { + log.warn("【定点联系-经办人会签监听器】获取执行实例ID失败,跳过写入经办人变量, taskId: {}", delegateTask.getId()); + } + + // 2. 记录经办人到业务表单 approveInfo 对应部门 + Object rawBusinessKey = delegateTask.getVariable(FixContactConstant.FlowVarName.BUSINESS_KEY); + if (rawBusinessKey == null || StringUtils.isBlank(rawBusinessKey.toString())) { + log.warn("【定点联系-经办人会签监听器】未获取到业务表单ID,跳过记录经办人, taskId: {}", delegateTask.getId()); + return; + } + + Object rawDeptVar = delegateTask.getVariableLocal(FixContactConstant.FlowVarName.IMPL_DEPT_ID); + if (rawDeptVar == null) { + rawDeptVar = delegateTask.getVariable(FixContactConstant.FlowVarName.IMPL_DEPT_ID); + } + if (rawDeptVar == null || StringUtils.isBlank(rawDeptVar.toString())) { + log.warn("【定点联系-经办人会签监听器】未获取到子流程当前部门ID,跳过记录经办人, taskId: {}", delegateTask.getId()); + return; + } + String deptId = rawDeptVar.toString().replace("[", "").replace("]", "").trim(); + + FixedContact20260730 fixedContact = fixedContact20260730Service.getByIdForUpdate(rawBusinessKey.toString()); + if (fixedContact == null) { + log.error("【定点联系-经办人会签监听器】未查询到业务表单记录, businessKey: {}", rawBusinessKey); + return; + } + + DeptApproveDetailMap approveMap = fixedContact.getApproveInfo(); + if (approveMap == null) { + approveMap = new DeptApproveDetailMap(); + } + + DeptApproveDetail detail = approveMap.get(deptId); + if (detail == null) { + detail = new DeptApproveDetail(); + detail.setDeptId(deptId); + detail.setImplUserNameList(new ArrayList<>()); + approveMap.put(deptId, detail); + } + + // 更新该部门经办人列表 + List workerList = detail.getImplUserNameList(); + if (workerList == null) { + workerList = new ArrayList<>(); + detail.setImplUserNameList(workerList); + } + if (!workerList.contains(currentWorker)) { + workerList.add(currentWorker); + fixedContact.setApproveInfo(approveMap); + fixedContact20260730Service.updateById(fixedContact); + log.info("【定点联系-经办人会签监听器】部门: {} 经办人已记录, worker: {}, businessKey: {}", + deptId, currentWorker, fixedContact.getId()); + } else { + log.info("【定点联系-经办人会签监听器】部门: {} 经办人 {} 已在列表中,跳过更新", deptId, currentWorker); + } + } +} diff --git a/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/mapper/FixedContactFeedback20260730Mapper.java b/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/mapper/FixedContactFeedback20260730Mapper.java index 0477f94..de91302 100644 --- a/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/mapper/FixedContactFeedback20260730Mapper.java +++ b/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/mapper/FixedContactFeedback20260730Mapper.java @@ -12,6 +12,13 @@ public interface FixedContactFeedback20260730Mapper extends BaseMapper selectByMainId(@Param("mainId") String mainId); } diff --git a/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/service/IFixedContact20260730Service.java b/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/service/IFixedContact20260730Service.java index 5cbc365..187a4ef 100644 --- a/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/service/IFixedContact20260730Service.java +++ b/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/service/IFixedContact20260730Service.java @@ -16,4 +16,11 @@ public interface IFixedContact20260730Service extends IService idList); + + void saveSubApprove(String mainId, String deptId, Integer isEnd, String implWorker, List implUserNameList); + + /** + * 悲观锁查询(for update),需在事务中使用 + */ + FixedContact20260730 getByIdForUpdate(String id); } diff --git a/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/service/impl/FixedContact20260730ServiceImpl.java b/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/service/impl/FixedContact20260730ServiceImpl.java index 0868142..7d57e29 100644 --- a/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/service/impl/FixedContact20260730ServiceImpl.java +++ b/jeecg-module-supervision/src/main/java/org/jeecg/modules/bg/fixcontact/service/impl/FixedContact20260730ServiceImpl.java @@ -1,19 +1,26 @@ package org.jeecg.modules.bg.fixcontact.service.impl; import java.io.Serializable; +import java.util.ArrayList; import java.util.Collection; import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.jeecg.common.exception.JeecgBootException; import org.jeecg.modules.bg.fixcontact.entity.FixedContact20260730; import org.jeecg.modules.bg.fixcontact.entity.FixedContactFeedback20260730; import org.jeecg.modules.bg.fixcontact.mapper.FixedContact20260730Mapper; import org.jeecg.modules.bg.fixcontact.mapper.FixedContactFeedback20260730Mapper; import org.jeecg.modules.bg.fixcontact.service.IFixedContact20260730Service; +import org.jeecg.modules.bg.xispeak.entity.DeptApproveDetail; +import org.jeecg.modules.bg.xispeak.entity.DeptApproveDetailMap; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @Service +@Slf4j public class FixedContact20260730ServiceImpl extends ServiceImpl implements IFixedContact20260730Service { @Autowired @@ -59,4 +66,47 @@ public class FixedContact20260730ServiceImpl extends ServiceImpl implUserNameList) { + FixedContact20260730 fixedContact = this.getById(mainId); + if (fixedContact == null) { + throw new JeecgBootException("业务表单不存在"); + } + + DeptApproveDetailMap approveMap = fixedContact.getApproveInfo(); + if (approveMap == null) { + approveMap = new DeptApproveDetailMap(); + } + + DeptApproveDetail detail = approveMap.get(deptId); + if (detail == null) { + detail = new DeptApproveDetail(); + detail.setDeptId(deptId); + detail.setImplUserNameList(new ArrayList<>()); + approveMap.put(deptId, detail); + } + + detail.setIsEnd(isEnd); + if (isEnd != null && isEnd == 1) { + detail.setImplWorker(implWorker); + detail.setImplUserNameList(null); + } else { + detail.setImplWorker(null); + detail.setImplUserNameList(implUserNameList != null ? implUserNameList : new ArrayList<>()); + } + + fixedContact.setApproveInfo(approveMap); + this.updateById(fixedContact); + log.info("【定点联系-部门审批保存】部门审批信息保存成功, mainId: {}, deptId: {}, isEnd: {}, implWorker: {}, implUserNameList: {}", + mainId, deptId, isEnd, implWorker, implUserNameList); + } + + @Override + public FixedContact20260730 getByIdForUpdate(String id) { + return this.getOne(new LambdaQueryWrapper() + .eq(FixedContact20260730::getId, id) + .last("for update")); + } }