From 8ed3066506e3984e9f3ab4cfcf063e89de53e4e4 Mon Sep 17 00:00:00 2001 From: smallNorthLee <18210040298@163.com> Date: Sun, 16 Mar 2025 21:41:47 +0800 Subject: [PATCH 01/16] =?UTF-8?q?review:=20=E9=87=8D=E6=9E=84=E7=BB=84?= =?UTF-8?q?=E8=A3=85=E4=B8=8B=E4=B8=80=E4=B8=AA=E8=8A=82=E7=82=B9=E5=AE=A1?= =?UTF-8?q?=E6=89=B9=E4=BA=BA=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../task/BpmProcessInstanceServiceImpl.java | 39 +++++++++++++------ 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index 1e0a777d02..0a63cf1b6c 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -267,24 +267,41 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService // 3.1 获取下一个将要执行的节点集合 FlowElement flowElement = bpmnModel.getFlowElement(task.getTaskDefinitionKey()); List nextFlowNodes = BpmnModelUtils.getNextFlowNodes(flowElement, bpmnModel, processVariables); - return convertList(nextFlowNodes, node -> { + + // 2. 收集所有节点的候选用户 ID + Set allCandidateUsers = new HashSet<>(); + for (FlowNode node : nextFlowNodes) { List candidateUserIds = getTaskCandidateUserList(bpmnModel, node.getId(), loginUserId, historicProcessInstance.getProcessDefinitionId(), processVariables); - // 3.2 获取节点的审批人信息 - Map userMap = adminUserApi.getUserMap(candidateUserIds); - // 3.3 获取节点的审批人部门信息 - Map deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); - // 3.4 存在一个节点多人审批的情况,组装审批人信息 + allCandidateUsers.addAll(candidateUserIds); + } + + // 3. 批量查询用户和部门信息 + Map userMap = adminUserApi.getUserMap(new ArrayList<>(allCandidateUsers)); + Map deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); + + // 4. 组装节点信息 + return convertList(nextFlowNodes, node -> { + // 4.1 获取当前节点的候选用户 ID + List candidateUserIds = getTaskCandidateUserList(bpmnModel, node.getId(), + loginUserId, historicProcessInstance.getProcessDefinitionId(), processVariables); + + // 4.2 组装候选用户信息 List candidateUsers = new ArrayList<>(); - userMap.forEach((key, value) -> candidateUsers.add(BpmProcessInstanceConvert.INSTANCE.buildUser(key, userMap, deptMap))); - return new ActivityNode().setNodeType(BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType()) + for (Long userId : candidateUserIds) { + AdminUserRespDTO user = userMap.get(userId); + if (user != null) { + candidateUsers.add(BpmProcessInstanceConvert.INSTANCE.buildUser(userId, userMap, deptMap)); + } + } + + // 4.3 构建节点信息 + return new ActivityNode() + .setNodeType(BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType()) .setId(node.getId()) .setName(node.getName()) .setStatus(BpmTaskStatusEnum.RUNNING.getStatus()) .setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(node)) - // TODO @小北:先把 candidateUserIds 设置完,然后最后拼接 candidateUsers 信息。这样,如果有多个节点,就不用重复查询啦;类似 buildApprovalDetail 思路; - // TODO 先拼接处 List ActivityNode - // TODO 接着,再起一段,处理 adminUserApi.getUserMap(candidateUserIds)、deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)) .setCandidateUsers(candidateUsers); }); } From 7ed96c4c6c5b247a791357ff78ada94e11061aff Mon Sep 17 00:00:00 2001 From: smallNorthLee <18210040298@163.com> Date: Sun, 16 Mar 2025 22:32:42 +0800 Subject: [PATCH 02/16] =?UTF-8?q?review:=20=E9=87=8D=E6=9E=84=E7=BB=84?= =?UTF-8?q?=E8=A3=85=E4=B8=8B=E4=B8=80=E4=B8=AA=E8=8A=82=E7=82=B9=E5=AE=A1?= =?UTF-8?q?=E6=89=B9=E4=BA=BA=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bpm/service/task/BpmProcessInstanceServiceImpl.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index 0a63cf1b6c..05ac86e69a 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -289,9 +289,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService // 4.2 组装候选用户信息 List candidateUsers = new ArrayList<>(); for (Long userId : candidateUserIds) { - AdminUserRespDTO user = userMap.get(userId); - if (user != null) { - candidateUsers.add(BpmProcessInstanceConvert.INSTANCE.buildUser(userId, userMap, deptMap)); + UserSimpleBaseVO user = BpmProcessInstanceConvert.INSTANCE.buildUser(userId, userMap, deptMap); + if (user != null){ + candidateUsers.add(user); } } From 58c667f728d4217a95e2a43b10581fbb6861724e Mon Sep 17 00:00:00 2001 From: Lesan <1960681385@qq.com> Date: Mon, 17 Mar 2025 08:54:34 +0800 Subject: [PATCH 03/16] =?UTF-8?q?feat:=20=E4=BB=BB=E5=8A=A1=E5=89=8D?= =?UTF-8?q?=E5=90=8E=E7=BD=AE=E9=80=9A=E7=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vo/model/BpmModelMetaInfoVO.java | 6 +++ .../BpmProcessDefinitionInfoDO.java | 12 ++++++ .../core/listener/BpmTaskEventListener.java | 7 +++- .../bpm/service/task/BpmTaskService.java | 7 ++++ .../bpm/service/task/BpmTaskServiceImpl.java | 41 +++++++++++++++++++ 5 files changed, 72 insertions(+), 1 deletion(-) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java index cf9ca3e5fd..957b010c87 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java @@ -88,6 +88,12 @@ public class BpmModelMetaInfoVO { @Schema(description = "流程后置通知设置", example = "{}") private HttpRequestSetting processAfterTriggerSetting; + @Schema(description = "任务前置通知设置", example = "{}") + private HttpRequestSetting taskBeforeTriggerSetting; + + @Schema(description = "任务后置通知设置", example = "{}") + private HttpRequestSetting taskAfterTriggerSetting; + @Schema(description = "流程 ID 规则") @Data @Valid diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionInfoDO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionInfoDO.java index 86c83ed611..2f79ec1c9e 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionInfoDO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionInfoDO.java @@ -199,4 +199,16 @@ public class BpmProcessDefinitionInfoDO extends BaseDO { @TableField(typeHandler = JacksonTypeHandler.class) private BpmModelMetaInfoVO.HttpRequestSetting processAfterTriggerSetting; + /** + * 任务前置通知设置 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private BpmModelMetaInfoVO.HttpRequestSetting taskBeforeTriggerSetting; + + /** + * 任务后置通知设置 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private BpmModelMetaInfoVO.HttpRequestSetting taskAfterTriggerSetting; + } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java index 329241f799..e50df0bcf0 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java @@ -47,7 +47,7 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener { public static final Set TASK_EVENTS = ImmutableSet.builder() .add(FlowableEngineEventType.TASK_CREATED) .add(FlowableEngineEventType.TASK_ASSIGNED) -// .add(FlowableEngineEventType.TASK_COMPLETED) // 由于审批通过时,已经记录了 task 的 status 为通过,所以不需要监听了。 + .add(FlowableEngineEventType.TASK_COMPLETED) // 由于审批通过时,已经记录了 task 的 status 为通过,这里仅处理任务后置通知。 .add(FlowableEngineEventType.ACTIVITY_CANCELLED) .add(FlowableEngineEventType.TIMER_FIRED) // 监听审批超时 .build(); @@ -66,6 +66,11 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener { taskService.processTaskAssigned((Task) event.getEntity()); } + @Override + protected void taskCompleted(FlowableEngineEntityEvent event) { + taskService.processTaskCompleted((Task) event.getEntity()); + } + @Override protected void activityCancelled(FlowableActivityCancelledEvent event) { List activityList = taskService.getHistoricActivityListByExecutionId(event.getExecutionId()); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java index e99d974356..0a5c866fda 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java @@ -278,6 +278,13 @@ public interface BpmTaskService { */ void processTaskAssigned(Task task); + /** + * 处理 Task 完成事件,目前是发送任务后置通知 + * + * @param task 任务实体 + */ + void processTaskCompleted(Task task); + /** * 处理 Task 审批超时事件,可能会处理多个当前审批中的任务 * diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index 242ed77475..7becc5fd58 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -12,6 +12,7 @@ import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.framework.common.util.object.PageUtils; import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.BpmModelMetaInfoVO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; @@ -23,6 +24,7 @@ import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskSignTypeEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum; import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum; import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants; +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmHttpRequestUtils; import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils; import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; import cn.iocoder.yudao.module.bpm.service.definition.BpmFormService; @@ -1180,6 +1182,21 @@ public class BpmTaskServiceImpl implements BpmTaskService { log.error("[processTaskCreated][taskId({}) 没有找到流程实例]", task.getId()); return; } + BpmProcessDefinitionInfoDO processDefinitionInfo = bpmProcessDefinitionService. + getProcessDefinitionInfo(processInstance.getProcessDefinitionId()); + if (processDefinitionInfo == null) { + log.error("[processTaskCreated][processDefinitionId({}) 没有找到流程定义]", processInstance.getProcessDefinitionId()); + return; + } + // 任务前置通知 + if (ObjUtil.isNotNull(processDefinitionInfo.getTaskBeforeTriggerSetting())){ + BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getTaskBeforeTriggerSetting(); + BpmHttpRequestUtils.executeBpmHttpRequest(processInstance, + setting.getUrl(), + setting.getHeader(), + setting.getBody(), + true, setting.getResponse()); + } BpmnModel bpmnModel = modelService.getBpmnModelByDefinitionId(processInstance.getProcessDefinitionId()); FlowElement userTaskElement = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey()); Integer approveType = BpmnModelUtils.parseApproveType(userTaskElement); @@ -1391,6 +1408,30 @@ public class BpmTaskServiceImpl implements BpmTaskService { }); } + @Override + public void processTaskCompleted(Task task) { + ProcessInstance processInstance = processInstanceService.getProcessInstance(task.getProcessInstanceId()); + if (processInstance == null) { + log.error("[processTaskCompleted][taskId({}) 没有找到流程实例]", task.getId()); + return; + } + BpmProcessDefinitionInfoDO processDefinitionInfo = bpmProcessDefinitionService. + getProcessDefinitionInfo(processInstance.getProcessDefinitionId()); + if (processDefinitionInfo == null) { + log.error("[processTaskCompleted][processDefinitionId({}) 没有找到流程定义]", processInstance.getProcessDefinitionId()); + return; + } + // 任务前置通知 + if (ObjUtil.isNotNull(processDefinitionInfo.getTaskAfterTriggerSetting())){ + BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getTaskAfterTriggerSetting(); + BpmHttpRequestUtils.executeBpmHttpRequest(processInstance, + setting.getUrl(), + setting.getHeader(), + setting.getBody(), + true, setting.getResponse()); + } + } + @Override @Transactional(rollbackFor = Exception.class) public void processTaskTimeout(String processInstanceId, String taskDefineKey, Integer handlerType) { From 6fbcac3c13f5604605b4390c7f17c947abcafced Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=91=E5=A8=81?= Date: Mon, 17 Mar 2025 15:31:34 +0800 Subject: [PATCH 04/16] =?UTF-8?q?=E3=80=90Simple=E8=AE=BE=E8=AE=A1?= =?UTF-8?q?=E5=99=A8=E3=80=91=E6=B5=81=E7=A8=8B=E6=A8=A1=E5=9E=8B->?= =?UTF-8?q?=E5=9F=BA=E6=9C=AC=E4=BF=A1=E6=81=AF->=E8=B0=81=E5=8F=AF?= =?UTF-8?q?=E4=BB=A5=E5=8F=91=E8=B5=B7=EF=BC=8C=E6=94=AF=E6=8C=81=E6=8C=87?= =?UTF-8?q?=E5=AE=9A=E5=A4=9A=E4=B8=AA=E9=83=A8=E9=97=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 指定部门可以在部门新增成员后无需重新修改相关流程 --- .../admin/base/dept/DeptSimpleBaseVO.java | 13 ++++++++++ .../admin/definition/BpmModelController.java | 12 ++++++++- .../vo/model/BpmModelMetaInfoVO.java | 3 +++ .../definition/vo/model/BpmModelRespVO.java | 4 +++ .../convert/definition/BpmModelConvert.java | 15 ++++++++--- .../BpmProcessDefinitionInfoDO.java | 8 ++++++ .../BpmProcessDefinitionServiceImpl.java | 25 +++++++++++++++---- 7 files changed, 70 insertions(+), 10 deletions(-) create mode 100644 yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/base/dept/DeptSimpleBaseVO.java diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/base/dept/DeptSimpleBaseVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/base/dept/DeptSimpleBaseVO.java new file mode 100644 index 0000000000..f6a9c126b3 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/base/dept/DeptSimpleBaseVO.java @@ -0,0 +1,13 @@ +package cn.iocoder.yudao.module.bpm.controller.admin.base.dept; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "部门精简信息 VO") +@Data +public class DeptSimpleBaseVO { + @Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + @Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + private String name; +} \ No newline at end of file diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java index 5578114f9d..0b3f9c3333 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java @@ -12,6 +12,8 @@ import cn.iocoder.yudao.module.bpm.service.definition.BpmCategoryService; import cn.iocoder.yudao.module.bpm.service.definition.BpmFormService; import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService; import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; +import cn.iocoder.yudao.module.system.api.dept.DeptApi; +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; @@ -53,6 +55,8 @@ public class BpmModelController { @Resource private AdminUserApi adminUserApi; + @Resource + private DeptApi deptApi; @GetMapping("/list") @Operation(summary = "获得模型分页") @@ -85,8 +89,14 @@ public class BpmModelController { return metaInfo != null ? metaInfo.getStartUserIds().stream() : Stream.empty(); }); Map userMap = adminUserApi.getUserMap(userIds); + // 获得 Dept Map + Set deptIds = convertSetByFlatMap(list, model -> { + BpmModelMetaInfoVO metaInfo = BpmModelConvert.INSTANCE.parseMetaInfo(model); + return metaInfo != null && metaInfo.getStartDeptIds() != null ? metaInfo.getStartDeptIds().stream() : Stream.empty(); + }); + Map deptMap = deptApi.getDeptMap(deptIds); return success(BpmModelConvert.INSTANCE.buildModelList(list, - formMap, categoryMap, deploymentMap, processDefinitionMap, userMap)); + formMap, categoryMap, deploymentMap, processDefinitionMap, userMap, deptMap)); } @GetMapping("/get") diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java index cf9ca3e5fd..db54c947e9 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java @@ -59,6 +59,9 @@ public class BpmModelMetaInfoVO { @Schema(description = "可发起用户编号数组", example = "[1,2,3]") private List startUserIds; + @Schema(description = "可发起部门编号数组") + private List startDeptIds; + @Schema(description = "可管理用户编号数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[2,4,6]") @NotEmpty(message = "可管理用户编号数组不能为空") private List managerUserIds; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelRespVO.java index 275368c7c6..6a9150aa27 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelRespVO.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model; +import cn.iocoder.yudao.module.bpm.controller.admin.base.dept.DeptSimpleBaseVO; import cn.iocoder.yudao.module.bpm.controller.admin.base.user.UserSimpleBaseVO; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO; @@ -39,6 +40,9 @@ public class BpmModelRespVO extends BpmModelMetaInfoVO { @Schema(description = "可发起的用户数组") private List startUsers; + @Schema(description = "可发起的部门数组") + private List startDepts; + @Schema(description = "BPMN XML") private String bpmnXml; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java index 19ec8491ee..5f3faa33e6 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java @@ -4,6 +4,7 @@ import cn.hutool.core.util.ArrayUtil; import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.bpm.controller.admin.base.dept.DeptSimpleBaseVO; import cn.iocoder.yudao.module.bpm.controller.admin.base.user.UserSimpleBaseVO; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.BpmModelMetaInfoVO; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.BpmModelRespVO; @@ -13,6 +14,7 @@ import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmPro import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmCategoryDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils; +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import org.flowable.common.engine.impl.db.SuspensionState; import org.flowable.engine.repository.Deployment; @@ -43,7 +45,8 @@ public interface BpmModelConvert { Map categoryMap, Map deploymentMap, Map processDefinitionMap, - Map userMap) { + Map userMap, + Map deptMap) { List result = convertList(list, model -> { BpmModelMetaInfoVO metaInfo = parseMetaInfo(model); BpmFormDO form = metaInfo != null ? formMap.get(metaInfo.getFormId()) : null; @@ -52,7 +55,8 @@ public interface BpmModelConvert { ProcessDefinition processDefinition = model.getDeploymentId() != null ? processDefinitionMap.get(model.getDeploymentId()) : null; List startUsers = metaInfo != null ? convertList(metaInfo.getStartUserIds(), userMap::get) : null; - return buildModel0(model, metaInfo, form, category, deployment, processDefinition, startUsers); + List startDepts = metaInfo != null ? convertList(metaInfo.getStartDeptIds(), deptMap::get) : null; + return buildModel0(model, metaInfo, form, category, deployment, processDefinition, startUsers, startDepts); }); // 排序 result.sort(Comparator.comparing(BpmModelMetaInfoVO::getSort)); @@ -61,7 +65,7 @@ public interface BpmModelConvert { default BpmModelRespVO buildModel(Model model, byte[] bpmnBytes, BpmSimpleModelNodeVO simpleModel) { BpmModelMetaInfoVO metaInfo = parseMetaInfo(model); - BpmModelRespVO modelVO = buildModel0(model, metaInfo, null, null, null, null, null); + BpmModelRespVO modelVO = buildModel0(model, metaInfo, null, null, null, null, null, null); if (ArrayUtil.isNotEmpty(bpmnBytes)) { modelVO.setBpmnXml(BpmnModelUtils.getBpmnXml(bpmnBytes)); } @@ -72,7 +76,8 @@ public interface BpmModelConvert { default BpmModelRespVO buildModel0(Model model, BpmModelMetaInfoVO metaInfo, BpmFormDO form, BpmCategoryDO category, Deployment deployment, ProcessDefinition processDefinition, - List startUsers) { + List startUsers, + List startDepts) { BpmModelRespVO modelRespVO = new BpmModelRespVO().setId(model.getId()).setName(model.getName()) .setKey(model.getKey()).setCategory(model.getCategory()) .setCreateTime(DateUtils.of(model.getCreateTime())); @@ -96,6 +101,8 @@ public interface BpmModelConvert { } // User modelRespVO.setStartUsers(BeanUtils.toBean(startUsers, UserSimpleBaseVO.class)); + // Dept + modelRespVO.setStartDepts(BeanUtils.toBean(startDepts, DeptSimpleBaseVO.class)); return modelRespVO; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionInfoDO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionInfoDO.java index 86c83ed611..786a96c3bc 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionInfoDO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionInfoDO.java @@ -151,6 +151,14 @@ public class BpmProcessDefinitionInfoDO extends BaseDO { @TableField(typeHandler = LongListTypeHandler.class) // 为了可以使用 find_in_set 进行过滤 private List startUserIds; + /** + * 可发起部门编号数组 + * + * 关联 {@link AdminUserRespDTO#getId()} 字段的数组 + */ + @TableField(typeHandler = LongListTypeHandler.class) + private List startDeptIds; + /** * 可管理用户编号数组 * diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java index 14ee084063..86bb93062d 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java @@ -12,6 +12,8 @@ import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitio import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmProcessDefinitionInfoMapper; import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants; import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.flowable.bpmn.model.BpmnModel; @@ -49,6 +51,8 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ @Resource private BpmProcessDefinitionInfoMapper processDefinitionMapper; + @Resource + private AdminUserApi adminUserApi; @Override public ProcessDefinition getProcessDefinition(String id) { @@ -88,12 +92,23 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ if (processDefinition == null) { return false; } - // 为空,则所有人都可以发起 - if (CollUtil.isEmpty(processDefinition.getStartUserIds())) { - return true; + + // 获取用户所在部门 + AdminUserRespDTO user = adminUserApi.getUser(userId); + Long userDeptId = user != null ? user.getDeptId() : null; + + // 校验用户是否在允许发起的用户列表中 + if (!CollUtil.isEmpty(processDefinition.getStartUserIds())) { + return processDefinition.getStartUserIds().contains(userId); } - // 不为空,则需要存在里面 - return processDefinition.getStartUserIds().contains(userId); + + // 校验用户是否在允许发起的部门列表中 + if (!CollUtil.isEmpty(processDefinition.getStartDeptIds()) && userDeptId != null) { + return processDefinition.getStartDeptIds().contains(userDeptId); + } + + // 都为空,则所有人都可以发起 + return true; } @Override From 67e548d54567777c60bfbde9f1213491bb87cdfa Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 17 Mar 2025 21:37:15 +0800 Subject: [PATCH 05/16] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91BPM=EF=BC=9A=E4=BB=BB=E5=8A=A1=E5=89=8D?= =?UTF-8?q?=E7=BD=AE=E3=80=81=E5=90=8E=E7=BD=AE=E9=80=9A=E7=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../task/BpmProcessInstanceServiceImpl.java | 14 ++++---------- .../bpm/service/task/BpmTaskServiceImpl.java | 19 ++++++++----------- .../task/listener/BpmUserTaskListener.java | 5 +---- .../trigger/http/BpmHttpCallbackTrigger.java | 5 +---- .../http/BpmSyncHttpRequestTrigger.java | 5 +---- 5 files changed, 15 insertions(+), 33 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index 05ac86e69a..7fd065e833 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -63,7 +63,6 @@ import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; -import org.springframework.web.client.RestTemplate; import java.util.*; @@ -268,6 +267,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService FlowElement flowElement = bpmnModel.getFlowElement(task.getTaskDefinitionKey()); List nextFlowNodes = BpmnModelUtils.getNextFlowNodes(flowElement, bpmnModel, processVariables); + // TODO @小北:还是可以优化下哈;“4. 组装节点信息” 只拼接出 candidateUserIds;之后,再第二次循环,查询用户和部门信息,进行拼接 // 2. 收集所有节点的候选用户 ID Set allCandidateUsers = new HashSet<>(); for (FlowNode node : nextFlowNodes) { @@ -290,7 +290,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService List candidateUsers = new ArrayList<>(); for (Long userId : candidateUserIds) { UserSimpleBaseVO user = BpmProcessInstanceConvert.INSTANCE.buildUser(userId, userMap, deptMap); - if (user != null){ + if (user != null) { candidateUsers.add(user); } } @@ -932,10 +932,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getProcessAfterTriggerSetting(); BpmHttpRequestUtils.executeBpmHttpRequest(instance, - setting.getUrl(), - setting.getHeader(), - setting.getBody(), - true, setting.getResponse()); + setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse()); } } }); @@ -954,10 +951,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService } BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getProcessBeforeTriggerSetting(); BpmHttpRequestUtils.executeBpmHttpRequest(instance, - setting.getUrl(), - setting.getHeader(), - setting.getBody(), - true, setting.getResponse()); + setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse()); }); } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index 7becc5fd58..08e0cdad1e 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -1176,7 +1176,6 @@ public class BpmTaskServiceImpl implements BpmTaskService { } updateTaskStatus(task.getId(), BpmTaskStatusEnum.RUNNING.getStatus()); - // 2. 处理自动通过的情况,例如说:1)无审批人时,是否自动通过、不通过;2)非【人工审核】时,是否自动通过、不通过 ProcessInstance processInstance = processInstanceService.getProcessInstance(task.getProcessInstanceId()); if (processInstance == null) { log.error("[processTaskCreated][taskId({}) 没有找到流程实例]", task.getId()); @@ -1188,15 +1187,15 @@ public class BpmTaskServiceImpl implements BpmTaskService { log.error("[processTaskCreated][processDefinitionId({}) 没有找到流程定义]", processInstance.getProcessDefinitionId()); return; } - // 任务前置通知 + + // 2. 任务前置通知 if (ObjUtil.isNotNull(processDefinitionInfo.getTaskBeforeTriggerSetting())){ BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getTaskBeforeTriggerSetting(); BpmHttpRequestUtils.executeBpmHttpRequest(processInstance, - setting.getUrl(), - setting.getHeader(), - setting.getBody(), - true, setting.getResponse()); + setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse()); } + + // 3. 处理自动通过的情况,例如说:1)无审批人时,是否自动通过、不通过;2)非【人工审核】时,是否自动通过、不通过 BpmnModel bpmnModel = modelService.getBpmnModelByDefinitionId(processInstance.getProcessDefinitionId()); FlowElement userTaskElement = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey()); Integer approveType = BpmnModelUtils.parseApproveType(userTaskElement); @@ -1421,14 +1420,12 @@ public class BpmTaskServiceImpl implements BpmTaskService { log.error("[processTaskCompleted][processDefinitionId({}) 没有找到流程定义]", processInstance.getProcessDefinitionId()); return; } - // 任务前置通知 + + // 任务后置通知 if (ObjUtil.isNotNull(processDefinitionInfo.getTaskAfterTriggerSetting())){ BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getTaskAfterTriggerSetting(); BpmHttpRequestUtils.executeBpmHttpRequest(processInstance, - setting.getUrl(), - setting.getHeader(), - setting.getBody(), - true, setting.getResponse()); + setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse()); } } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmUserTaskListener.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmUserTaskListener.java index e16fafa2d1..0ddaba4769 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmUserTaskListener.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmUserTaskListener.java @@ -52,10 +52,7 @@ public class BpmUserTaskListener implements TaskListener { listenerHandler.getBody().add(new BpmSimpleModelNodeVO.HttpRequestParam().setKey("taskId") .setType(BpmHttpRequestParamTypeEnum.FIXED_VALUE.getType()).setValue(delegateTask.getId())); BpmHttpRequestUtils.executeBpmHttpRequest(processInstance, - listenerHandler.getPath(), - listenerHandler.getHeader(), - listenerHandler.getBody(), - false, null); + listenerHandler.getPath(), listenerHandler.getHeader(), listenerHandler.getBody(), false, null); // 3. 是否需要后续操作?TODO 芋艿:待定! } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/http/BpmHttpCallbackTrigger.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/http/BpmHttpCallbackTrigger.java index 351b57ddd4..d2cc03e27a 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/http/BpmHttpCallbackTrigger.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/http/BpmHttpCallbackTrigger.java @@ -45,10 +45,7 @@ public class BpmHttpCallbackTrigger extends BpmAbstractHttpRequestTrigger { .setKey("taskDefineKey") // 重要:回调请求 taskDefineKey 需要传给被调用方,用于回调执行 .setType(BpmHttpRequestParamTypeEnum.FIXED_VALUE.getType()).setValue(setting.getCallbackTaskDefineKey())); BpmHttpRequestUtils.executeBpmHttpRequest(processInstance, - setting.getUrl(), - setting.getHeader(), - setting.getBody(), - false, null); + setting.getUrl(), setting.getHeader(), setting.getBody(), false, null); } } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/http/BpmSyncHttpRequestTrigger.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/http/BpmSyncHttpRequestTrigger.java index 2ac04117e4..cecbe6a3c8 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/http/BpmSyncHttpRequestTrigger.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/http/BpmSyncHttpRequestTrigger.java @@ -40,10 +40,7 @@ public class BpmSyncHttpRequestTrigger extends BpmAbstractHttpRequestTrigger { // 2. 发起请求 ProcessInstance processInstance = processInstanceService.getProcessInstance(processInstanceId); BpmHttpRequestUtils.executeBpmHttpRequest(processInstance, - setting.getUrl(), - setting.getHeader(), - setting.getBody(), - true, setting.getResponse()); + setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse()); } } From 41639d5dd7c9b8b272e615435fa7e2707998a478 Mon Sep 17 00:00:00 2001 From: smallNorthLee <18210040298@163.com> Date: Tue, 18 Mar 2025 19:12:39 +0800 Subject: [PATCH 06/16] =?UTF-8?q?review:=20=E9=87=8D=E6=9E=84=E7=BB=84?= =?UTF-8?q?=E8=A3=85=E4=B8=8B=E4=B8=80=E4=B8=AA=E8=8A=82=E7=82=B9=E5=AE=A1?= =?UTF-8?q?=E6=89=B9=E4=BA=BA=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/task/BpmProcessInstanceServiceImpl.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index 7fd065e833..f987620802 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -267,7 +267,6 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService FlowElement flowElement = bpmnModel.getFlowElement(task.getTaskDefinitionKey()); List nextFlowNodes = BpmnModelUtils.getNextFlowNodes(flowElement, bpmnModel, processVariables); - // TODO @小北:还是可以优化下哈;“4. 组装节点信息” 只拼接出 candidateUserIds;之后,再第二次循环,查询用户和部门信息,进行拼接 // 2. 收集所有节点的候选用户 ID Set allCandidateUsers = new HashSet<>(); for (FlowNode node : nextFlowNodes) { @@ -287,13 +286,13 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService loginUserId, historicProcessInstance.getProcessDefinitionId(), processVariables); // 4.2 组装候选用户信息 - List candidateUsers = new ArrayList<>(); - for (Long userId : candidateUserIds) { - UserSimpleBaseVO user = BpmProcessInstanceConvert.INSTANCE.buildUser(userId, userMap, deptMap); + List candidateUsers = convertList(candidateUserIds, userId -> { + AdminUserRespDTO user = userMap.get(userId); if (user != null) { - candidateUsers.add(user); + return BpmProcessInstanceConvert.INSTANCE.buildUser(userId, userMap, deptMap); } - } + return null; + }); // 4.3 构建节点信息 return new ActivityNode() From b6c700af6babf05a9d08f70c34c115e6257bfc9f Mon Sep 17 00:00:00 2001 From: lizhixian <18210040298@163.com> Date: Wed, 19 Mar 2025 17:21:29 +0800 Subject: [PATCH 07/16] =?UTF-8?q?fix=EF=BC=9A=E4=BF=AE=E5=A4=8Dsimple?= =?UTF-8?q?=E8=AE=BE=E8=AE=A1=E5=99=A8=E7=AC=AC=E4=B8=80=E4=B8=AA=E5=8F=91?= =?UTF-8?q?=E8=B5=B7=E4=BA=BA=E8=8A=82=E7=82=B9=EF=BC=8C=E5=AE=A1=E6=89=B9?= =?UTF-8?q?=E6=97=B6=E6=A0=A1=E9=AA=8C=E6=98=AF=E5=90=A6=E5=AD=98=E5=9C=A8?= =?UTF-8?q?=E5=AE=A1=E6=89=B9=E4=BA=BA=E5=AF=BC=E8=87=B4=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/bpm/service/task/BpmTaskServiceImpl.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index 08e0cdad1e..451bc3b996 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -599,6 +599,9 @@ public class BpmTaskServiceImpl implements BpmTaskService { */ private Map validateAndSetNextAssignees(String taskDefinitionKey, Map variables, BpmnModel bpmnModel, Map> nextAssignees, ProcessInstance processInstance) { + if (taskDefinitionKey.equals(START_USER_NODE_ID)) { + return variables; + } // 1. 获取下一个将要执行的节点集合 FlowElement flowElement = bpmnModel.getFlowElement(taskDefinitionKey); List nextFlowNodes = getNextFlowNodes(flowElement, bpmnModel, variables); From f70a50472fefd6f17119ab91a0a8e4a6f551cbab Mon Sep 17 00:00:00 2001 From: lizhixian <18210040298@163.com> Date: Wed, 19 Mar 2025 17:23:12 +0800 Subject: [PATCH 08/16] =?UTF-8?q?fix=EF=BC=9A=E4=BF=AE=E5=A4=8Dsimple?= =?UTF-8?q?=E8=AE=BE=E8=AE=A1=E5=99=A8=E7=AC=AC=E4=B8=80=E4=B8=AA=E5=8F=91?= =?UTF-8?q?=E8=B5=B7=E4=BA=BA=E8=8A=82=E7=82=B9=EF=BC=8C=E5=AE=A1=E6=89=B9?= =?UTF-8?q?=E6=97=B6=E6=A0=A1=E9=AA=8C=E6=98=AF=E5=90=A6=E5=AD=98=E5=9C=A8?= =?UTF-8?q?=E5=AE=A1=E6=89=B9=E4=BA=BA=E5=AF=BC=E8=87=B4=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/bpm/service/task/BpmTaskServiceImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index 451bc3b996..c0098f706e 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -599,6 +599,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { */ private Map validateAndSetNextAssignees(String taskDefinitionKey, Map variables, BpmnModel bpmnModel, Map> nextAssignees, ProcessInstance processInstance) { + // Simple设计器第一个节点默认为发起人节点,不校验是否存在审批人 if (taskDefinitionKey.equals(START_USER_NODE_ID)) { return variables; } From 629bf284959cafbdb8f8e454759faa250b6219bb Mon Sep 17 00:00:00 2001 From: lizhixian <18210040298@163.com> Date: Fri, 21 Mar 2025 14:08:24 +0800 Subject: [PATCH 09/16] =?UTF-8?q?fix=EF=BC=9A=E4=BF=AE=E5=A4=8D=E5=AE=A1?= =?UTF-8?q?=E6=89=B9=E6=8E=A5=E5=8F=A3=EF=BC=8C=E6=A0=A1=E9=AA=8C=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E8=A7=84=E5=88=99=E4=B8=BA=E5=8F=91=E8=B5=B7=E4=BA=BA?= =?UTF-8?q?=E8=87=AA=E9=80=89=E6=97=B6=EF=BC=8C=E5=85=88=E4=BB=8E=E5=8E=86?= =?UTF-8?q?=E5=8F=B2=E5=8F=98=E9=87=8F=E4=B8=AD=E6=9F=A5=E8=AF=A2=E5=AE=A1?= =?UTF-8?q?=E6=89=B9=E4=BA=BA=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bpm/service/task/BpmTaskServiceImpl.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index c0098f706e..9eb25323ee 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -613,16 +613,17 @@ public class BpmTaskServiceImpl implements BpmTaskService { Integer candidateStrategy = parseCandidateStrategy(nextFlowNode); // 2.1 情况一:如果节点中的审批人策略为 发起人自选 if (ObjUtil.equals(candidateStrategy, BpmTaskCandidateStrategyEnum.START_USER_SELECT.getStrategy())) { - // 如果节点存在,但未配置审批人 - List assignees = nextAssignees != null ? nextAssignees.get(nextFlowNode.getId()) : null; - if (CollUtil.isEmpty(assignees)) { - throw exception(PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_CONFIG, nextFlowNode.getName()); - } + // 先从历史中获取审批人,在发起人会把所有的审批人保存到历史中,这里从历史中获取 processVariables = FlowableUtils.getStartUserSelectAssignees(processInstance.getProcessVariables()); // 特殊:如果当前节点已经存在审批人,则不允许覆盖 if (processVariables != null && CollUtil.isNotEmpty(processVariables.get(nextFlowNode.getId()))) { continue; } + // 如果节点存在,但未配置审批人 + List assignees = nextAssignees != null ? nextAssignees.get(nextFlowNode.getId()) : null; + if (CollUtil.isEmpty(assignees)) { + throw exception(PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_CONFIG, nextFlowNode.getName()); + } // 设置 PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES if (processVariables == null) { processVariables = new HashMap<>(); @@ -632,12 +633,13 @@ public class BpmTaskServiceImpl implements BpmTaskService { } // 2.2 情况二:如果节点中的审批人策略为 审批人,在审批时选择下一个节点的审批人,并且该节点的审批人为空 if (ObjUtil.equals(candidateStrategy, BpmTaskCandidateStrategyEnum.APPROVE_USER_SELECT.getStrategy())) { + // 获取审批人自选的历史变量 + processVariables = FlowableUtils.getApproveUserSelectAssignees(processInstance.getProcessVariables()); // 如果节点存在,但未配置审批人 List assignees = nextAssignees != null ? nextAssignees.get(nextFlowNode.getId()) : null; if (CollUtil.isEmpty(assignees)) { throw exception(PROCESS_INSTANCE_APPROVE_USER_SELECT_ASSIGNEES_NOT_CONFIG, nextFlowNode.getName()); } - processVariables = FlowableUtils.getApproveUserSelectAssignees(processInstance.getProcessVariables()); if (processVariables == null) { processVariables = new HashMap<>(); } From 113dfae73255e38b686f0ee846b8d97a83edb7aa Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 22 Mar 2025 23:20:31 +0800 Subject: [PATCH 10/16] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91BPM=EF=BC=9A1297=20fix:=20=E4=BF=AE=E5=A4=8Ds?= =?UTF-8?q?imple=E8=AE=BE=E8=AE=A1=E5=99=A8=E7=AC=AC=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E5=8F=91=E8=B5=B7=E4=BA=BA=E8=8A=82=E7=82=B9=EF=BC=8C=E5=AE=A1?= =?UTF-8?q?=E6=89=B9=E6=97=B6=E6=A0=A1=E9=AA=8C=E6=98=AF=E5=90=A6=E5=AD=98?= =?UTF-8?q?=E5=9C=A8=E5=AE=A1=E6=89=B9=E4=BA=BA=E5=AF=BC=E8=87=B4=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../task/BpmProcessInstanceServiceImpl.java | 57 +++++++------------ .../bpm/service/task/BpmTaskServiceImpl.java | 36 ++++++------ 2 files changed, 39 insertions(+), 54 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index f987620802..aa8f58b45d 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -14,7 +14,6 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.framework.common.util.object.PageUtils; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; -import cn.iocoder.yudao.module.bpm.controller.admin.base.user.UserSimpleBaseVO; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.BpmModelMetaInfoVO; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; @@ -262,47 +261,31 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService processVariables.putAll(reqVO.getProcessVariables()); } - // 3 获取当前任务节点的信息 - // 3.1 获取下一个将要执行的节点集合 + // 3. 获取下一个将要执行的节点集合 FlowElement flowElement = bpmnModel.getFlowElement(task.getTaskDefinitionKey()); List nextFlowNodes = BpmnModelUtils.getNextFlowNodes(flowElement, bpmnModel, processVariables); - - // 2. 收集所有节点的候选用户 ID - Set allCandidateUsers = new HashSet<>(); - for (FlowNode node : nextFlowNodes) { - List candidateUserIds = getTaskCandidateUserList(bpmnModel, node.getId(), - loginUserId, historicProcessInstance.getProcessDefinitionId(), processVariables); - allCandidateUsers.addAll(candidateUserIds); + List nextActivityNodes = convertList(nextFlowNodes, node -> new ActivityNode().setId(node.getId()) + .setName(node.getName()).setNodeType(BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType()) + .setStatus(BpmTaskStatusEnum.RUNNING.getStatus()) + .setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(node)) + .setCandidateUserIds(getTaskCandidateUserList(bpmnModel, node.getId(), + loginUserId, historicProcessInstance.getProcessDefinitionId(), processVariables))); + if (CollUtil.isNotEmpty(nextActivityNodes)) { + return nextActivityNodes; } - // 3. 批量查询用户和部门信息 - Map userMap = adminUserApi.getUserMap(new ArrayList<>(allCandidateUsers)); + // 4. 拼接基础信息 + Map userMap = adminUserApi.getUserMap( + convertSetByFlatMap(nextActivityNodes, ActivityNode::getCandidateUserIds, Collection::stream)); Map deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); - - // 4. 组装节点信息 - return convertList(nextFlowNodes, node -> { - // 4.1 获取当前节点的候选用户 ID - List candidateUserIds = getTaskCandidateUserList(bpmnModel, node.getId(), - loginUserId, historicProcessInstance.getProcessDefinitionId(), processVariables); - - // 4.2 组装候选用户信息 - List candidateUsers = convertList(candidateUserIds, userId -> { - AdminUserRespDTO user = userMap.get(userId); - if (user != null) { - return BpmProcessInstanceConvert.INSTANCE.buildUser(userId, userMap, deptMap); - } - return null; - }); - - // 4.3 构建节点信息 - return new ActivityNode() - .setNodeType(BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType()) - .setId(node.getId()) - .setName(node.getName()) - .setStatus(BpmTaskStatusEnum.RUNNING.getStatus()) - .setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(node)) - .setCandidateUsers(candidateUsers); - }); + nextActivityNodes.forEach(node -> node.setCandidateUsers(convertList(node.getCandidateUserIds(), userId -> { + AdminUserRespDTO user = userMap.get(userId); + if (user != null) { + return BpmProcessInstanceConvert.INSTANCE.buildUser(userId, userMap, deptMap); + } + return null; + }))); + return nextActivityNodes; } @Override diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index 9eb25323ee..2f293dd4fe 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -6,6 +6,7 @@ import cn.hutool.core.lang.Assert; import cn.hutool.core.util.*; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; @@ -599,8 +600,8 @@ public class BpmTaskServiceImpl implements BpmTaskService { */ private Map validateAndSetNextAssignees(String taskDefinitionKey, Map variables, BpmnModel bpmnModel, Map> nextAssignees, ProcessInstance processInstance) { - // Simple设计器第一个节点默认为发起人节点,不校验是否存在审批人 - if (taskDefinitionKey.equals(START_USER_NODE_ID)) { + // simple 设计器第一个节点默认为发起人节点,不校验是否存在审批人 + if (Objects.equals(taskDefinitionKey, START_USER_NODE_ID)) { return variables; } // 1. 获取下一个将要执行的节点集合 @@ -608,15 +609,13 @@ public class BpmTaskServiceImpl implements BpmTaskService { List nextFlowNodes = getNextFlowNodes(flowElement, bpmnModel, variables); // 2. 校验选择的下一个节点的审批人,是否合法 - Map> processVariables; for (FlowNode nextFlowNode : nextFlowNodes) { Integer candidateStrategy = parseCandidateStrategy(nextFlowNode); // 2.1 情况一:如果节点中的审批人策略为 发起人自选 if (ObjUtil.equals(candidateStrategy, BpmTaskCandidateStrategyEnum.START_USER_SELECT.getStrategy())) { - // 先从历史中获取审批人,在发起人会把所有的审批人保存到历史中,这里从历史中获取 - processVariables = FlowableUtils.getStartUserSelectAssignees(processInstance.getProcessVariables()); // 特殊:如果当前节点已经存在审批人,则不允许覆盖 - if (processVariables != null && CollUtil.isNotEmpty(processVariables.get(nextFlowNode.getId()))) { + Map> startUserSelectAssignees = FlowableUtils.getStartUserSelectAssignees(processInstance.getProcessVariables()); + if (startUserSelectAssignees != null && CollUtil.isNotEmpty(startUserSelectAssignees.get(nextFlowNode.getId()))) { continue; } // 如果节点存在,但未配置审批人 @@ -624,28 +623,31 @@ public class BpmTaskServiceImpl implements BpmTaskService { if (CollUtil.isEmpty(assignees)) { throw exception(PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_CONFIG, nextFlowNode.getName()); } + // 设置 PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES - if (processVariables == null) { - processVariables = new HashMap<>(); + if (startUserSelectAssignees == null) { + startUserSelectAssignees = new HashMap<>(); } - processVariables.put(nextFlowNode.getId(), assignees); - variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES, processVariables); + startUserSelectAssignees.put(nextFlowNode.getId(), assignees); + variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES, startUserSelectAssignees); + continue; } + // 2.2 情况二:如果节点中的审批人策略为 审批人,在审批时选择下一个节点的审批人,并且该节点的审批人为空 if (ObjUtil.equals(candidateStrategy, BpmTaskCandidateStrategyEnum.APPROVE_USER_SELECT.getStrategy())) { - // 获取审批人自选的历史变量 - processVariables = FlowableUtils.getApproveUserSelectAssignees(processInstance.getProcessVariables()); // 如果节点存在,但未配置审批人 + Map> approveUserSelectAssignees = FlowableUtils.getApproveUserSelectAssignees(processInstance.getProcessVariables()); List assignees = nextAssignees != null ? nextAssignees.get(nextFlowNode.getId()) : null; if (CollUtil.isEmpty(assignees)) { throw exception(PROCESS_INSTANCE_APPROVE_USER_SELECT_ASSIGNEES_NOT_CONFIG, nextFlowNode.getName()); } - if (processVariables == null) { - processVariables = new HashMap<>(); - } + // 设置 PROCESS_INSTANCE_VARIABLE_APPROVE_USER_SELECT_ASSIGNEES - processVariables.put(nextFlowNode.getId(), assignees); - variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_APPROVE_USER_SELECT_ASSIGNEES, processVariables); + if (approveUserSelectAssignees == null) { + approveUserSelectAssignees = new HashMap<>(); + } + approveUserSelectAssignees.put(nextFlowNode.getId(), assignees); + variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_APPROVE_USER_SELECT_ASSIGNEES, approveUserSelectAssignees); } } return variables; From 4fbe9fa480b25fde992687399206af5da8ffecc8 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 23 Mar 2025 17:28:08 +0800 Subject: [PATCH 11/16] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91BPM=EF=BC=9A=E6=B5=81=E7=A8=8B=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B->=E5=9F=BA=E6=9C=AC=E4=BF=A1=E6=81=AF->=E8=B0=81?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E5=8F=91=E8=B5=B7=EF=BC=8C=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E6=8C=87=E5=AE=9A=E5=A4=9A=E4=B8=AA=E9=83=A8=E9=97=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/base/dept/DeptSimpleBaseVO.java | 4 +++- .../admin/definition/BpmModelController.java | 3 +-- .../definition/vo/model/BpmModelMetaInfoVO.java | 2 +- .../bpm/convert/definition/BpmModelConvert.java | 10 ++++------ .../definition/BpmProcessDefinitionInfoDO.java | 2 +- .../BpmProcessDefinitionServiceImpl.java | 14 +++++++------- 6 files changed, 17 insertions(+), 18 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/base/dept/DeptSimpleBaseVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/base/dept/DeptSimpleBaseVO.java index f6a9c126b3..ba8049a4b6 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/base/dept/DeptSimpleBaseVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/base/dept/DeptSimpleBaseVO.java @@ -6,8 +6,10 @@ import lombok.Data; @Schema(description = "部门精简信息 VO") @Data public class DeptSimpleBaseVO { + @Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Long id; - @Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + @Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "技术部") private String name; + } \ No newline at end of file diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java index 0b3f9c3333..aa4c484fee 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java @@ -83,13 +83,12 @@ public class BpmModelController { List processDefinitions = processDefinitionService.getProcessDefinitionListByDeploymentIds( deploymentMap.keySet()); Map processDefinitionMap = convertMap(processDefinitions, ProcessDefinition::getDeploymentId); - // 获得 User Map + // 获得 User Map、Dept Map Set userIds = convertSetByFlatMap(list, model -> { BpmModelMetaInfoVO metaInfo = BpmModelConvert.INSTANCE.parseMetaInfo(model); return metaInfo != null ? metaInfo.getStartUserIds().stream() : Stream.empty(); }); Map userMap = adminUserApi.getUserMap(userIds); - // 获得 Dept Map Set deptIds = convertSetByFlatMap(list, model -> { BpmModelMetaInfoVO metaInfo = BpmModelConvert.INSTANCE.parseMetaInfo(model); return metaInfo != null && metaInfo.getStartDeptIds() != null ? metaInfo.getStartDeptIds().stream() : Stream.empty(); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java index fbad5bdc6b..d2316f58eb 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java @@ -59,7 +59,7 @@ public class BpmModelMetaInfoVO { @Schema(description = "可发起用户编号数组", example = "[1,2,3]") private List startUserIds; - @Schema(description = "可发起部门编号数组") + @Schema(description = "可发起部门编号数组", example = "[2,4,6]") private List startDeptIds; @Schema(description = "可管理用户编号数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[2,4,6]") diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java index 5f3faa33e6..2101b22b28 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java @@ -76,8 +76,7 @@ public interface BpmModelConvert { default BpmModelRespVO buildModel0(Model model, BpmModelMetaInfoVO metaInfo, BpmFormDO form, BpmCategoryDO category, Deployment deployment, ProcessDefinition processDefinition, - List startUsers, - List startDepts) { + List startUsers, List startDepts) { BpmModelRespVO modelRespVO = new BpmModelRespVO().setId(model.getId()).setName(model.getName()) .setKey(model.getKey()).setCategory(model.getCategory()) .setCreateTime(DateUtils.of(model.getCreateTime())); @@ -99,10 +98,9 @@ public interface BpmModelConvert { modelRespVO.getProcessDefinition().setDeploymentTime(DateUtils.of(deployment.getDeploymentTime())); } } - // User - modelRespVO.setStartUsers(BeanUtils.toBean(startUsers, UserSimpleBaseVO.class)); - // Dept - modelRespVO.setStartDepts(BeanUtils.toBean(startDepts, DeptSimpleBaseVO.class)); + // User、Dept + modelRespVO.setStartUsers(BeanUtils.toBean(startUsers, UserSimpleBaseVO.class)) + .setStartDepts(BeanUtils.toBean(startDepts, DeptSimpleBaseVO.class)); return modelRespVO; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionInfoDO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionInfoDO.java index 9f006e0400..c2799ef67f 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionInfoDO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionInfoDO.java @@ -154,7 +154,7 @@ public class BpmProcessDefinitionInfoDO extends BaseDO { /** * 可发起部门编号数组 * - * 关联 {@link AdminUserRespDTO#getId()} 字段的数组 + * 关联 {@link AdminUserRespDTO#getDeptId()} 字段的数组 */ @TableField(typeHandler = LongListTypeHandler.class) private List startDeptIds; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java index 86bb93062d..836b5181c7 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java @@ -51,6 +51,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ @Resource private BpmProcessDefinitionInfoMapper processDefinitionMapper; + @Resource private AdminUserApi adminUserApi; @@ -93,18 +94,17 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ return false; } - // 获取用户所在部门 - AdminUserRespDTO user = adminUserApi.getUser(userId); - Long userDeptId = user != null ? user.getDeptId() : null; - // 校验用户是否在允许发起的用户列表中 - if (!CollUtil.isEmpty(processDefinition.getStartUserIds())) { + if (CollUtil.isNotEmpty(processDefinition.getStartUserIds())) { return processDefinition.getStartUserIds().contains(userId); } // 校验用户是否在允许发起的部门列表中 - if (!CollUtil.isEmpty(processDefinition.getStartDeptIds()) && userDeptId != null) { - return processDefinition.getStartDeptIds().contains(userDeptId); + if (CollUtil.isNotEmpty(processDefinition.getStartDeptIds())) { + AdminUserRespDTO user = adminUserApi.getUser(userId); + return user != null + && user.getDeptId() != null + && processDefinition.getStartDeptIds().contains(user.getDeptId()); } // 都为空,则所有人都可以发起 From e14716a3078561f90df4d0384b69e2a38c3ff7cf Mon Sep 17 00:00:00 2001 From: Lesan <1960681385@qq.com> Date: Tue, 25 Mar 2025 10:24:34 +0800 Subject: [PATCH 12/16] =?UTF-8?q?fix:=20=E5=AD=98=E5=9C=A8=E5=AD=90?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E6=83=85=E5=86=B5=E4=B8=8B=E7=9A=84=E5=8F=96?= =?UTF-8?q?=E6=B6=88=E9=80=BB=E8=BE=91=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/bpm/enums/ErrorCodeConstants.java | 1 + .../yudao/module/bpm/enums/task/BpmReasonEnum.java | 1 + .../admin/task/BpmProcessInstanceController.java | 1 - .../flowable/core/util/SimpleModelUtils.java | 1 - .../service/task/BpmProcessInstanceServiceImpl.java | 13 +++++++++++++ 5 files changed, 15 insertions(+), 2 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java index 65605142c2..23bdba9933 100644 --- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java @@ -42,6 +42,7 @@ public interface ErrorCodeConstants { ErrorCode PROCESS_INSTANCE_CANCEL_FAIL_NOT_ALLOW = new ErrorCode(1_009_004_005, "流程取消失败,该流程不允许取消"); ErrorCode PROCESS_INSTANCE_HTTP_TRIGGER_CALL_ERROR = new ErrorCode(1_009_004_006, "流程 Http 触发器请求调用失败"); ErrorCode PROCESS_INSTANCE_APPROVE_USER_SELECT_ASSIGNEES_NOT_CONFIG = new ErrorCode(1_009_004_007, "下一个任务({})的审批人未配置"); + ErrorCode CHILD_PROCESS_INSTANCE_CANCEL_FAIL_NOT_ALLOW = new ErrorCode(1_009_004_008, "子流程取消失败,子流程不允许取消"); // ========== 流程任务 1-009-005-000 ========== ErrorCode TASK_OPERATE_FAIL_ASSIGN_NOT_SELF = new ErrorCode(1_009_005_001, "操作失败,原因:该任务的审批人不是你"); diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmReasonEnum.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmReasonEnum.java index b0ade75299..eca18cce6e 100644 --- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmReasonEnum.java +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmReasonEnum.java @@ -18,6 +18,7 @@ public enum BpmReasonEnum { REJECT_TASK("审批不通过任务,原因:{}"), // 场景:用户审批不通过任务。修改文案时,需要注意 isRejectReason 方法 CANCEL_PROCESS_INSTANCE_BY_START_USER("用户主动取消流程,原因:{}"), // 场景:用户主动取消流程 CANCEL_PROCESS_INSTANCE_BY_ADMIN("管理员【{}】取消流程,原因:{}"), // 场景:管理员取消流程 + CANCEL_CHILD_PROCESS_INSTANCE_BY_MAIN_PROCESS("子流程自动取消,原因:子流程已取消"), // ========== 流程任务的独有原因 ========== diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java index 9316261678..8a3777772e 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java @@ -148,7 +148,6 @@ public class BpmProcessInstanceController { processDefinition, processDefinitionInfo, startUser, dept)); } - // TODO @lesan:【子流程】子流程如果取消,主流程应该是通过、还是不通过哈?还是禁用掉子流程的取消? @DeleteMapping("/cancel-by-start-user") @Operation(summary = "用户取消流程实例", description = "取消发起的流程") @PreAuthorize("@ss.hasPermission('bpm:process-instance:cancel')") diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java index 3b5bad52c7..ae7e08536d 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java @@ -813,7 +813,6 @@ public class SimpleModelUtils { callActivity.setCalledElementType("key"); // 1. 是否异步 if (node.getChildProcessSetting().getAsync()) { - // TODO @lesan: 这里目前测试没有跳过执行call activity 后面的节点 callActivity.setAsynchronous(true); } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index aa8f58b45d..efb2cf23b7 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -823,6 +823,10 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService && Boolean.FALSE.equals(processDefinitionInfo.getAllowCancelRunningProcess())) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_ALLOW); } + // 1.4 子流程不允许取消 + if (StrUtil.isNotBlank(instance.getSuperExecutionId())) { + throw exception(CHILD_PROCESS_INSTANCE_CANCEL_FAIL_NOT_ALLOW); + } // 2. 取消流程 updateProcessInstanceCancel(cancelReqVO.getId(), @@ -851,6 +855,15 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService // 2. 结束流程 taskService.moveTaskToEnd(id, reason); + + // 3. 取消所有子流程 + List subProcessInstances = runtimeService.createProcessInstanceQuery() + .superProcessInstanceId(id) + .list(); + subProcessInstances.forEach(processInstance -> { + updateProcessInstanceCancel(processInstance.getProcessInstanceId(), + BpmReasonEnum.CANCEL_CHILD_PROCESS_INSTANCE_BY_MAIN_PROCESS.getReason()); + }); } @Override From b471dc55c38815cc14a83345aeb84ae111a51fce Mon Sep 17 00:00:00 2001 From: Lesan <1960681385@qq.com> Date: Tue, 25 Mar 2025 10:37:38 +0800 Subject: [PATCH 13/16] =?UTF-8?q?fix:=20=E5=AD=98=E5=9C=A8=E5=AD=90?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E6=83=85=E5=86=B5=E4=B8=8B=E7=9A=84=E5=8F=96?= =?UTF-8?q?=E6=B6=88=E9=80=BB=E8=BE=91=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/bpm/enums/task/BpmReasonEnum.java | 2 +- .../bpm/service/task/BpmProcessInstanceServiceImpl.java | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmReasonEnum.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmReasonEnum.java index eca18cce6e..46d1482a5e 100644 --- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmReasonEnum.java +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmReasonEnum.java @@ -18,7 +18,7 @@ public enum BpmReasonEnum { REJECT_TASK("审批不通过任务,原因:{}"), // 场景:用户审批不通过任务。修改文案时,需要注意 isRejectReason 方法 CANCEL_PROCESS_INSTANCE_BY_START_USER("用户主动取消流程,原因:{}"), // 场景:用户主动取消流程 CANCEL_PROCESS_INSTANCE_BY_ADMIN("管理员【{}】取消流程,原因:{}"), // 场景:管理员取消流程 - CANCEL_CHILD_PROCESS_INSTANCE_BY_MAIN_PROCESS("子流程自动取消,原因:子流程已取消"), + CANCEL_CHILD_PROCESS_INSTANCE_BY_MAIN_PROCESS("子流程自动取消,原因:主流程已取消"), // ========== 流程任务的独有原因 ========== diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index efb2cf23b7..709779bf64 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -853,10 +853,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService BpmProcessInstanceStatusEnum.CANCEL.getStatus()); runtimeService.setVariable(id, BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_REASON, reason); - // 2. 结束流程 - taskService.moveTaskToEnd(id, reason); - - // 3. 取消所有子流程 + // 2. 取消所有子流程 List subProcessInstances = runtimeService.createProcessInstanceQuery() .superProcessInstanceId(id) .list(); @@ -864,6 +861,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService updateProcessInstanceCancel(processInstance.getProcessInstanceId(), BpmReasonEnum.CANCEL_CHILD_PROCESS_INSTANCE_BY_MAIN_PROCESS.getReason()); }); + + // 3. 结束流程 + taskService.moveTaskToEnd(id, reason); } @Override From c9a8548920f2507338b35bc77a75430dec7c4de5 Mon Sep 17 00:00:00 2001 From: Lesan <1960681385@qq.com> Date: Tue, 25 Mar 2025 11:07:24 +0800 Subject: [PATCH 14/16] =?UTF-8?q?feat:=20=E6=B5=81=E7=A8=8B=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E7=BA=BF=E9=80=82=E9=85=8D=E5=AD=90=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=E8=8A=82=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vo/instance/BpmApprovalDetailRespVO.java | 3 +++ .../task/BpmProcessInstanceServiceImpl.java | 19 +++++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmApprovalDetailRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmApprovalDetailRespVO.java index 888f59ada2..226878a048 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmApprovalDetailRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmApprovalDetailRespVO.java @@ -72,6 +72,9 @@ public class BpmApprovalDetailRespVO { @Schema(description = "候选人用户列表") private List candidateUsers; // 只包含未生成 ApprovalTaskInfo 的用户列表 + @Schema(description = "流程编号", example = "8761d8e0-0922-11f0-bd37-00ff1db677bf") + private String processInstanceId; + } @Schema(description = "活动节点的任务信息") diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index 709779bf64..d9db8ed94f 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -387,8 +387,6 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService List activities, List tasks) { // 遍历 tasks 列表,只处理已结束的 UserTask // 为什么不通过 activities 呢?因为,加签场景下,它只存在于 tasks,没有 activities,导致如果遍历 activities 的话,它无法成为一个节点 - // TODO @芋艿:子流程只有activity,这里获取不到已结束的子流程; - // TODO @lesan:【子流程】基于 activities 查询出 usertask、callactivity,然后拼接?如果是子流程,就是可以点击过去? List endTasks = filterList(tasks, task -> task.getEndTime() != null); List approvalNodes = convertList(endTasks, task -> { FlowElement flowNode = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey()); @@ -410,7 +408,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService // 遍历 activities,只处理已结束的 StartEvent、EndEvent List endActivities = filterList(activities, activity -> activity.getEndTime() != null - && (StrUtil.equalsAny(activity.getActivityType(), ELEMENT_EVENT_START, ELEMENT_EVENT_END))); + && (StrUtil.equalsAny(activity.getActivityType(), ELEMENT_EVENT_START, ELEMENT_CALL_ACTIVITY, ELEMENT_EVENT_END))); endActivities.forEach(activity -> { // StartEvent:只处理 BPMN 的场景。因为,SIMPLE 情况下,已经有 START_USER_NODE 节点 if (ELEMENT_EVENT_START.equals(activity.getActivityType()) @@ -444,7 +442,18 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService } approvalNodes.add(endNode); } + // CallActivity + if (ELEMENT_CALL_ACTIVITY.equals(activity.getActivityType())) { + ActivityNode callActivity = new ActivityNode().setId(activity.getId()) + .setName(BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getName()) + .setNodeType(BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType()).setStatus(processInstanceStatus) + .setStartTime(DateUtils.of(activity.getStartTime())) + .setEndTime(DateUtils.of(activity.getEndTime())) + .setProcessInstanceId(activity.getProcessInstanceId()); + approvalNodes.add(callActivity); + } }); + approvalNodes.sort(Comparator.comparing(ActivityNode::getStartTime)); return approvalNodes; } @@ -464,7 +473,6 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService HistoricActivityInstance::getActivityId); // 按照 activityId 分组,构建 ApprovalNodeInfo 节点 - // TODO @lesan:【子流程】在子流程进行审批的时候,HistoricActivityInstance 里面可以拿到 runActivities.get(0).getCalledProcessInstanceId()。要不要支持跳转??? Map taskMap = convertMap(tasks, HistoricTaskInstance::getId); return convertList(runningTaskMap.entrySet(), entry -> { String activityId = entry.getKey(); @@ -510,6 +518,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService approvalTaskInfo.getAssignee())); // 委派或者向前加签情况,需要先比较 owner activityNode.setCandidateUserIds(CollUtil.sub(candidateUserIds, index + 1, candidateUserIds.size())); } + if (BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType().equals(activityNode.getNodeType())) { + activityNode.setProcessInstanceId(firstActivity.getProcessInstanceId()); + } return activityNode; }); } From f0c26d5b5ac7fcc44d8a9f807c9ca49a6988219b Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 25 Mar 2025 12:49:34 +0800 Subject: [PATCH 15/16] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91BPM=EF=BC=9A=E5=AD=90=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/bpm/enums/ErrorCodeConstants.java | 2 +- .../task/vo/instance/BpmApprovalDetailRespVO.java | 2 +- .../task/BpmProcessInstanceServiceImpl.java | 15 +++++++-------- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java index 23bdba9933..d5d6fa77c4 100644 --- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java @@ -42,7 +42,7 @@ public interface ErrorCodeConstants { ErrorCode PROCESS_INSTANCE_CANCEL_FAIL_NOT_ALLOW = new ErrorCode(1_009_004_005, "流程取消失败,该流程不允许取消"); ErrorCode PROCESS_INSTANCE_HTTP_TRIGGER_CALL_ERROR = new ErrorCode(1_009_004_006, "流程 Http 触发器请求调用失败"); ErrorCode PROCESS_INSTANCE_APPROVE_USER_SELECT_ASSIGNEES_NOT_CONFIG = new ErrorCode(1_009_004_007, "下一个任务({})的审批人未配置"); - ErrorCode CHILD_PROCESS_INSTANCE_CANCEL_FAIL_NOT_ALLOW = new ErrorCode(1_009_004_008, "子流程取消失败,子流程不允许取消"); + ErrorCode PROCESS_INSTANCE_CANCEL_CHILD_FAIL_NOT_ALLOW = new ErrorCode(1_009_004_008, "子流程取消失败,子流程不允许取消"); // ========== 流程任务 1-009-005-000 ========== ErrorCode TASK_OPERATE_FAIL_ASSIGN_NOT_SELF = new ErrorCode(1_009_005_001, "操作失败,原因:该任务的审批人不是你"); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmApprovalDetailRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmApprovalDetailRespVO.java index 226878a048..38c2bc1013 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmApprovalDetailRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmApprovalDetailRespVO.java @@ -73,7 +73,7 @@ public class BpmApprovalDetailRespVO { private List candidateUsers; // 只包含未生成 ApprovalTaskInfo 的用户列表 @Schema(description = "流程编号", example = "8761d8e0-0922-11f0-bd37-00ff1db677bf") - private String processInstanceId; + private String processInstanceId; // 当且仅当,该节点是子流程节点时,才会有值(CallActivity 的 processInstanceId 字段) } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index d9db8ed94f..a46068040e 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -453,6 +453,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService approvalNodes.add(callActivity); } }); + + // 按照时间排序 approvalNodes.sort(Comparator.comparing(ActivityNode::getStartTime)); return approvalNodes; } @@ -836,7 +838,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService } // 1.4 子流程不允许取消 if (StrUtil.isNotBlank(instance.getSuperExecutionId())) { - throw exception(CHILD_PROCESS_INSTANCE_CANCEL_FAIL_NOT_ALLOW); + throw exception(PROCESS_INSTANCE_CANCEL_CHILD_FAIL_NOT_ALLOW); } // 2. 取消流程 @@ -865,13 +867,10 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService runtimeService.setVariable(id, BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_REASON, reason); // 2. 取消所有子流程 - List subProcessInstances = runtimeService.createProcessInstanceQuery() - .superProcessInstanceId(id) - .list(); - subProcessInstances.forEach(processInstance -> { - updateProcessInstanceCancel(processInstance.getProcessInstanceId(), - BpmReasonEnum.CANCEL_CHILD_PROCESS_INSTANCE_BY_MAIN_PROCESS.getReason()); - }); + List childProcessInstances = runtimeService.createProcessInstanceQuery() + .superProcessInstanceId(id).list(); + childProcessInstances.forEach(processInstance -> updateProcessInstanceCancel( + processInstance.getProcessInstanceId(), BpmReasonEnum.CANCEL_CHILD_PROCESS_INSTANCE_BY_MAIN_PROCESS.getReason())); // 3. 结束流程 taskService.moveTaskToEnd(id, reason); From d7a785d1de97a24d54fd169512359c488c938814 Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Fri, 28 Mar 2025 21:41:40 +0800 Subject: [PATCH 16/16] =?UTF-8?q?=E3=80=90=E9=97=AE=E9=A2=98=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E3=80=91=20=E5=B9=B6=E8=A1=8C=E7=BD=91=E5=85=B3?= =?UTF-8?q?=E4=BF=9D=E5=AD=98=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vo/model/simple/BpmSimpleModelNodeVO.java | 4 ++-- .../flowable/core/util/SimpleModelUtils.java | 14 +++++++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java index f002e6894a..1cbebe06e4 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java @@ -112,7 +112,7 @@ public class BpmSimpleModelNodeVO { /** * 条件节点设置 */ - private ConditionSetting conditionSetting; // 仅用于条件节点 BpmSimpleModelNodeType.CONDITION_NODE + private ConditionSetting conditionSetting; // 仅用于条件节点 BpmSimpleModelNodeTypeEnum.CONDITION_NODE @Schema(description = "路由分支组", example = "[]") private List routerGroups; @@ -241,7 +241,7 @@ public class BpmSimpleModelNodeVO { @Schema(description = "条件设置") @Data @Valid - // 仅用于条件节点 BpmSimpleModelNodeType.CONDITION_NODE + // 仅用于条件节点 BpmSimpleModelNodeTypeEnum.CONDITION_NODE public static class ConditionSetting { @Schema(description = "条件类型", example = "1") diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java index ae7e08536d..bd427e32f2 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java @@ -187,7 +187,7 @@ public class SimpleModelUtils { /** * 构建有附加节点的连线 * - * @param nodeId 当前节点 ID + * @param nodeId 当前节点 ID * @param attachNodeId 附属节点 ID * @param targetNodeId 目标节点 ID */ @@ -662,6 +662,10 @@ public class SimpleModelUtils { * 构造条件表达式 */ public static String buildConditionExpression(BpmSimpleModelNodeVO.ConditionSetting conditionSetting) { + // 并行网关不需要设置条件 + if (conditionSetting == null) { + return null; + } return buildConditionExpression(conditionSetting.getConditionType(), conditionSetting.getConditionExpression(), conditionSetting.getConditionGroups()); } @@ -958,8 +962,8 @@ public class SimpleModelUtils { if (nodeType == BpmSimpleModelNodeTypeEnum.CONDITION_BRANCH_NODE) { // 查找满足条件的 BpmSimpleModelNodeVO 节点 BpmSimpleModelNodeVO matchConditionNode = CollUtil.findOne(currentNode.getConditionNodes(), - conditionNode -> !BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow()) - && evalConditionExpress(variables, conditionNode.getConditionSetting())); + conditionNode -> !BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow()) + && evalConditionExpress(variables, conditionNode.getConditionSetting())); if (matchConditionNode == null) { matchConditionNode = CollUtil.findOne(currentNode.getConditionNodes(), conditionNode -> BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow())); @@ -973,8 +977,8 @@ public class SimpleModelUtils { if (nodeType == BpmSimpleModelNodeTypeEnum.INCLUSIVE_BRANCH_NODE) { // 查找满足条件的 BpmSimpleModelNodeVO 节点 Collection matchConditionNodes = CollUtil.filterNew(currentNode.getConditionNodes(), - conditionNode -> !BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow()) - && evalConditionExpress(variables, conditionNode.getConditionSetting())); + conditionNode -> !BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow()) + && evalConditionExpress(variables, conditionNode.getConditionSetting())); if (CollUtil.isEmpty(matchConditionNodes)) { matchConditionNodes = CollUtil.filterNew(currentNode.getConditionNodes(), conditionNode -> BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow()));