mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2025-01-19 03:30:06 +08:00
bpm:简化获得可回退节点的实现
This commit is contained in:
parent
3826846368
commit
0b649fd3e1
@ -1,13 +1,12 @@
|
|||||||
package cn.iocoder.yudao.framework.flowable.core.util;
|
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.Process;
|
||||||
import org.flowable.bpmn.model.*;
|
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);
|
return process.getFlowElement(flowElementId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 找到 source 节点之前的所有用户任务节点
|
* 找到 source 节点之前的所有用户任务节点
|
||||||
*
|
*
|
||||||
|
@ -47,9 +47,10 @@ public interface ErrorCodeConstants {
|
|||||||
ErrorCode TASK_COMPLETE_FAIL_ASSIGN_NOT_SELF = new ErrorCode(1_009_005_001, "审批任务失败,原因:该任务的审批人不是你");
|
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_NOT_EXISTS = new ErrorCode(1_009_005_002, "流程任务不存在");
|
||||||
ErrorCode TASK_IS_PENDING = new ErrorCode(1_009_005_003, "当前任务处于挂起状态,不能操作");
|
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_004, " 目标节点不存在");
|
||||||
ErrorCode TASK_TARGET_NODE_NOT_EXISTS = new ErrorCode(1_009_005_005, " 目标节点不存在");
|
ErrorCode TASK_RETURN_FAIL_NO_RETURN_TASK = new ErrorCode(1_009_005_005, "回退任务失败,选择回退的节点没有需要回滚的任务!请重新选择其他任务节点");
|
||||||
ErrorCode TASK_RETURN_FAIL = new ErrorCode(1_009_005_006, "回退任务失败,选择回退的节点没有需要回滚的任务!请重新选择其他任务节点");
|
ErrorCode TASK_RETURN_FAIL_SOURCE_TARGET_ERROR = new ErrorCode(1_009_005_006, "回退任务失败,目标节点是在并行网关上或非同一路线上,不可跳转");
|
||||||
|
|
||||||
// ========== 流程任务分配规则 1-009-006-000 ==========
|
// ========== 流程任务分配规则 1-009-006-000 ==========
|
||||||
ErrorCode TASK_ASSIGN_RULE_EXISTS = new ErrorCode(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, "流程任务分配规则不存在");
|
ErrorCode TASK_ASSIGN_RULE_NOT_EXISTS = new ErrorCode(1_009_006_001, "流程任务分配规则不存在");
|
||||||
|
@ -14,10 +14,10 @@ public class BpmTaskReturnReqVO {
|
|||||||
private String id;
|
private String id;
|
||||||
|
|
||||||
@Schema(description = "回退到的任务 Key", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
@Schema(description = "回退到的任务 Key", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||||
@NotEmpty(message = "回退到的任务Key不能为空")
|
@NotEmpty(message = "回退到的任务 Key 不能为空")
|
||||||
private String targetDefinitionKey;
|
private String targetDefinitionKey;
|
||||||
|
|
||||||
@Schema(description = "回退意见", example = "")
|
@Schema(description = "回退意见", example = "我就是想驳回")
|
||||||
private String reason;
|
private String reason;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,7 @@ package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task;
|
|||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
/**
|
@Schema(description = "管理后台 - 流程任务的精简 Response VO")
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Schema(description = "管理后台 - 流程任务的 可回退的节点 Response VO")
|
|
||||||
@Data
|
@Data
|
||||||
public class BpmTaskSimpleRespVO {
|
public class BpmTaskSimpleRespVO {
|
||||||
|
|
||||||
@ -15,4 +12,5 @@ public class BpmTaskSimpleRespVO {
|
|||||||
|
|
||||||
@Schema(description = "任务名词", requiredMode = Schema.RequiredMode.REQUIRED, example = "经理审批")
|
@Schema(description = "任务名词", requiredMode = Schema.RequiredMode.REQUIRED, example = "经理审批")
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -140,8 +140,7 @@ public interface BpmTaskConvert {
|
|||||||
return reqDTO;
|
return reqDTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Mapping(source = "taskDefinitionKey", target = "id")
|
default List<BpmTaskSimpleRespVO> convertList(List<? extends FlowElement> elementList) {
|
||||||
default List<BpmTaskSimpleRespVO> convertList(List<FlowElement> elementList) {
|
|
||||||
return CollectionUtils.convertList(elementList, element -> new BpmTaskSimpleRespVO()
|
return CollectionUtils.convertList(elementList, element -> new BpmTaskSimpleRespVO()
|
||||||
.setName(element.getName())
|
.setName(element.getName())
|
||||||
.setDefinitionKey(element.getId()));
|
.setDefinitionKey(element.getId()));
|
||||||
|
@ -125,7 +125,7 @@ public interface BpmTaskService {
|
|||||||
/**
|
/**
|
||||||
* 获取当前任务的可回退的流程集合
|
* 获取当前任务的可回退的流程集合
|
||||||
*
|
*
|
||||||
* @param taskId 当前的任务ID
|
* @param taskId 当前的任务 ID
|
||||||
* @return 可以回退的节点列表
|
* @return 可以回退的节点列表
|
||||||
*/
|
*/
|
||||||
List<BpmTaskSimpleRespVO> getReturnTaskList(String taskId);
|
List<BpmTaskSimpleRespVO> getReturnTaskList(String taskId);
|
||||||
|
@ -327,49 +327,25 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<BpmTaskSimpleRespVO> getReturnTaskList(String taskId) {
|
public List<BpmTaskSimpleRespVO> getReturnTaskList(String taskId) {
|
||||||
// 当前任务 task
|
// 1. 校验当前任务 task 存在
|
||||||
Task task = getTask(taskId);
|
Task task = getTask(taskId);
|
||||||
if (null == task) {
|
if (task == null) {
|
||||||
throw exception(TASK_NOT_EXISTS);
|
throw exception(TASK_NOT_EXISTS);
|
||||||
}
|
}
|
||||||
// 根据流程定义获取流程模型信息
|
|
||||||
BpmnModel bpmnModel = bpmModelService.getBpmnModelByDefinitionId(task.getProcessDefinitionId());
|
BpmnModel bpmnModel = bpmModelService.getBpmnModelByDefinitionId(task.getProcessDefinitionId());
|
||||||
// 查询该任务的前置任务节点的key集合
|
FlowElement source = ModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey());
|
||||||
Set<String> historyTaksDefinitionKeySet = getPreTaskByCurrentTask(task, bpmnModel);
|
if (source == null) {
|
||||||
if (CollUtil.isEmpty(historyTaksDefinitionKeySet)) {
|
throw exception(TASK_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2.1 查询该任务的前置任务节点的 key 集合
|
||||||
|
List<UserTask> previousUserList = ModelUtils.getPreUserTaskList(source, null, null);
|
||||||
|
if (CollUtil.isEmpty(previousUserList)) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
// 获取当前任务节点元素
|
// 2.2 过滤:只有串行可到达的节点,才可以回退。类似非串行、子流程无法退回
|
||||||
FlowElement source = ModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey());
|
previousUserList.removeIf(userTask -> ModelUtils.isSequentialReachable(source, userTask, null));
|
||||||
List<FlowElement> elementList = new ArrayList<>();
|
return BpmTaskConvert.INSTANCE.convertList(previousUserList);
|
||||||
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<String> getPreTaskByCurrentTask(Task task, BpmnModel bpmnModel) {
|
|
||||||
// 获取当前任务节点元素
|
|
||||||
FlowElement source = ModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey());
|
|
||||||
//拿到当前任务节点的前置节点集合
|
|
||||||
List<UserTask> preUserTaskList = ModelUtils.getPreUserTaskList(source, null, null);
|
|
||||||
//需要保证这些节点都是在该source节点之前的
|
|
||||||
if (CollUtil.isNotEmpty(preUserTaskList)) {
|
|
||||||
return convertSet(preUserTaskList, UserTask::getId);
|
|
||||||
}
|
|
||||||
return Collections.emptySet();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
@ -426,7 +402,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||||||
// 从当前节点向前扫描,判断当前节点与目标节点是否属于串行,若目标节点是在并行网关上或非同一路线上,不可跳转
|
// 从当前节点向前扫描,判断当前节点与目标节点是否属于串行,若目标节点是在并行网关上或非同一路线上,不可跳转
|
||||||
boolean isSequential = ModelUtils.isSequentialReachable(source, target, new HashSet<>());
|
boolean isSequential = ModelUtils.isSequentialReachable(source, target, new HashSet<>());
|
||||||
if (!isSequential) {
|
if (!isSequential) {
|
||||||
throw exception(TASK_SOURCE_TARGET_ERROR);
|
throw exception(TASK_RETURN_FAIL_SOURCE_TARGET_ERROR);
|
||||||
}
|
}
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
@ -455,7 +431,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
if (CollUtil.isEmpty(currentTaskIds)) {
|
if (CollUtil.isEmpty(currentTaskIds)) {
|
||||||
throw exception(TASK_RETURN_FAIL);
|
throw exception(TASK_RETURN_FAIL_NO_RETURN_TASK);
|
||||||
}
|
}
|
||||||
// 设置回退意见
|
// 设置回退意见
|
||||||
for (String currentTaskId : currentTaskIds) {
|
for (String currentTaskId : currentTaskIds) {
|
||||||
|
Loading…
Reference in New Issue
Block a user