From 0b649fd3e1c7f178bf5c0cbdadc584628a6b7ffc Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 24 Sep 2023 16:08:50 +0800 Subject: [PATCH] =?UTF-8?q?bpm=EF=BC=9A=E7=AE=80=E5=8C=96=E8=8E=B7?= =?UTF-8?q?=E5=BE=97=E5=8F=AF=E5=9B=9E=E9=80=80=E8=8A=82=E7=82=B9=E7=9A=84?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../flowable/core/util/ModelUtils.java | 10 ++-- .../module/bpm/enums/ErrorCodeConstants.java | 7 +-- .../task/vo/task/BpmTaskReturnReqVO.java | 4 +- .../task/vo/task/BpmTaskSimpleRespVO.java | 6 +-- .../bpm/convert/task/BpmTaskConvert.java | 3 +- .../bpm/service/task/BpmTaskService.java | 2 +- .../bpm/service/task/BpmTaskServiceImpl.java | 54 ++++++------------- 7 files changed, 29 insertions(+), 57 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/util/ModelUtils.java b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/util/ModelUtils.java index 84bd0342a..5db69d302 100644 --- a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/util/ModelUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/util/ModelUtils.java @@ -1,13 +1,12 @@ package cn.iocoder.yudao.framework.flowable.core.util; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; -import org.flowable.bpmn.converter.BpmnXMLConverter; import org.flowable.bpmn.model.Process; import org.flowable.bpmn.model.*; -import org.flowable.common.engine.impl.util.io.StringStreamSource; -import java.util.*; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; /** * 流程模型转操作工具类 @@ -56,7 +55,6 @@ public class ModelUtils { return process.getFlowElement(flowElementId); } - /** * 找到 source 节点之前的所有用户任务节点 * 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 48b71ef72..79bd539ac 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 @@ -47,9 +47,10 @@ public interface ErrorCodeConstants { ErrorCode TASK_COMPLETE_FAIL_ASSIGN_NOT_SELF = new ErrorCode(1_009_005_001, "审批任务失败,原因:该任务的审批人不是你"); ErrorCode TASK_NOT_EXISTS = new ErrorCode(1_009_005_002, "流程任务不存在"); ErrorCode TASK_IS_PENDING = new ErrorCode(1_009_005_003, "当前任务处于挂起状态,不能操作"); - ErrorCode TASK_SOURCE_TARGET_ERROR = new ErrorCode(1_009_005_004, "目标节点是在并行网关上或非同一路线上,不可跳转"); - ErrorCode TASK_TARGET_NODE_NOT_EXISTS = new ErrorCode(1_009_005_005, " 目标节点不存在"); - ErrorCode TASK_RETURN_FAIL = new ErrorCode(1_009_005_006, "回退任务失败,选择回退的节点没有需要回滚的任务!请重新选择其他任务节点"); + ErrorCode TASK_TARGET_NODE_NOT_EXISTS = new ErrorCode(1_009_005_004, " 目标节点不存在"); + ErrorCode TASK_RETURN_FAIL_NO_RETURN_TASK = new ErrorCode(1_009_005_005, "回退任务失败,选择回退的节点没有需要回滚的任务!请重新选择其他任务节点"); + ErrorCode TASK_RETURN_FAIL_SOURCE_TARGET_ERROR = new ErrorCode(1_009_005_006, "回退任务失败,目标节点是在并行网关上或非同一路线上,不可跳转"); + // ========== 流程任务分配规则 1-009-006-000 ========== ErrorCode TASK_ASSIGN_RULE_EXISTS = new ErrorCode(1_009_006_000, "流程({}) 的任务({}) 已经存在分配规则"); ErrorCode TASK_ASSIGN_RULE_NOT_EXISTS = new ErrorCode(1_009_006_001, "流程任务分配规则不存在"); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskReturnReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskReturnReqVO.java index e977e4bb1..1a0af7358 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskReturnReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskReturnReqVO.java @@ -14,10 +14,10 @@ public class BpmTaskReturnReqVO { private String id; @Schema(description = "回退到的任务 Key", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotEmpty(message = "回退到的任务Key不能为空") + @NotEmpty(message = "回退到的任务 Key 不能为空") private String targetDefinitionKey; - @Schema(description = "回退意见", example = "") + @Schema(description = "回退意见", example = "我就是想驳回") private String reason; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskSimpleRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskSimpleRespVO.java index 232d830d5..b98a25a22 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskSimpleRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskSimpleRespVO.java @@ -3,10 +3,7 @@ package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -/** - * - */ -@Schema(description = "管理后台 - 流程任务的 可回退的节点 Response VO") +@Schema(description = "管理后台 - 流程任务的精简 Response VO") @Data public class BpmTaskSimpleRespVO { @@ -15,4 +12,5 @@ public class BpmTaskSimpleRespVO { @Schema(description = "任务名词", requiredMode = Schema.RequiredMode.REQUIRED, example = "经理审批") private String name; + } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java index 992570f33..ce693e468 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java @@ -140,8 +140,7 @@ public interface BpmTaskConvert { return reqDTO; } - @Mapping(source = "taskDefinitionKey", target = "id") - default List convertList(List elementList) { + default List convertList(List elementList) { return CollectionUtils.convertList(elementList, element -> new BpmTaskSimpleRespVO() .setName(element.getName()) .setDefinitionKey(element.getId())); 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 1c327ca78..23c4ed3bc 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 @@ -125,7 +125,7 @@ public interface BpmTaskService { /** * 获取当前任务的可回退的流程集合 * - * @param taskId 当前的任务ID + * @param taskId 当前的任务 ID * @return 可以回退的节点列表 */ List getReturnTaskList(String taskId); 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 a7d1496a7..26e9431d7 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 @@ -327,49 +327,25 @@ public class BpmTaskServiceImpl implements BpmTaskService { @Override public List getReturnTaskList(String taskId) { - // 当前任务 task + // 1. 校验当前任务 task 存在 Task task = getTask(taskId); - if (null == task) { + if (task == null) { throw exception(TASK_NOT_EXISTS); } - // 根据流程定义获取流程模型信息 BpmnModel bpmnModel = bpmModelService.getBpmnModelByDefinitionId(task.getProcessDefinitionId()); - // 查询该任务的前置任务节点的key集合 - Set historyTaksDefinitionKeySet = getPreTaskByCurrentTask(task, bpmnModel); - if (CollUtil.isEmpty(historyTaksDefinitionKeySet)) { + FlowElement source = ModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey()); + if (source == null) { + throw exception(TASK_NOT_EXISTS); + } + + // 2.1 查询该任务的前置任务节点的 key 集合 + List previousUserList = ModelUtils.getPreUserTaskList(source, null, null); + if (CollUtil.isEmpty(previousUserList)) { return Collections.emptyList(); } - // 获取当前任务节点元素 - FlowElement source = ModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey()); - List elementList = new ArrayList<>(); - for (String activityId : historyTaksDefinitionKeySet) { - FlowElement target = ModelUtils.getFlowElementById(bpmnModel, activityId); - //非 串行和子流程则加入返回节点 elementList - boolean isSequential = ModelUtils.isSequentialReachable(source, target, new HashSet<>()); - if (isSequential) { - elementList.add(target); - } - } - return BpmTaskConvert.INSTANCE.convertList(elementList); - } - - /** - * 查询当前流程实例符合条件可回退的 taskDefinitionKey 集合 - * - * @param task 当前任务 - * @param bpmnModel 当前流程定义对应的流程模型 - * @return 符合条件的已去重的 taskDefinitionKey集合 - */ - private Set getPreTaskByCurrentTask(Task task, BpmnModel bpmnModel) { - // 获取当前任务节点元素 - FlowElement source = ModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey()); - //拿到当前任务节点的前置节点集合 - List preUserTaskList = ModelUtils.getPreUserTaskList(source, null, null); - //需要保证这些节点都是在该source节点之前的 - if (CollUtil.isNotEmpty(preUserTaskList)) { - return convertSet(preUserTaskList, UserTask::getId); - } - return Collections.emptySet(); + // 2.2 过滤:只有串行可到达的节点,才可以回退。类似非串行、子流程无法退回 + previousUserList.removeIf(userTask -> ModelUtils.isSequentialReachable(source, userTask, null)); + return BpmTaskConvert.INSTANCE.convertList(previousUserList); } @Transactional(rollbackFor = Exception.class) @@ -426,7 +402,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { // 从当前节点向前扫描,判断当前节点与目标节点是否属于串行,若目标节点是在并行网关上或非同一路线上,不可跳转 boolean isSequential = ModelUtils.isSequentialReachable(source, target, new HashSet<>()); if (!isSequential) { - throw exception(TASK_SOURCE_TARGET_ERROR); + throw exception(TASK_RETURN_FAIL_SOURCE_TARGET_ERROR); } return target; } @@ -455,7 +431,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { } })); if (CollUtil.isEmpty(currentTaskIds)) { - throw exception(TASK_RETURN_FAIL); + throw exception(TASK_RETURN_FAIL_NO_RETURN_TASK); } // 设置回退意见 for (String currentTaskId : currentTaskIds) {