Optimize BpmTaskServiceImpl with improved task retrieval and filtering logic
Co-authored-by: dingjiangying <dingjiangying@meituan.com>
This commit is contained in:
@@ -62,6 +62,7 @@ import org.springframework.transaction.support.TransactionSynchronizationManager
|
|||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
@@ -173,7 +174,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得用户指定 taskId 任务编号的“待办”(未审批、且可审核)的任务
|
* 获得用户指定 taskId 任务编号的"待办"(未审批、且可审核)的任务
|
||||||
*
|
*
|
||||||
* @param userId 用户编号
|
* @param userId 用户编号
|
||||||
* @param taskId 任务编号
|
* @param taskId 任务编号
|
||||||
@@ -194,7 +195,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得用户指定 processInstanceId 流程编号下的首个“待办”(未审批、且可审核)的任务
|
* 获得用户指定 processInstanceId 流程编号下的首个"待办"(未审批、且可审核)的任务
|
||||||
*
|
*
|
||||||
* @param userId 用户编号
|
* @param userId 用户编号
|
||||||
* @param processInstanceId 流程编号
|
* @param processInstanceId 流程编号
|
||||||
@@ -241,7 +242,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||||||
}
|
}
|
||||||
List<HistoricTaskInstance> tasks = taskQuery.listPage(PageUtils.getStart(pageVO), pageVO.getPageSize());
|
List<HistoricTaskInstance> tasks = taskQuery.listPage(PageUtils.getStart(pageVO), pageVO.getPageSize());
|
||||||
|
|
||||||
// 特殊:强制移除自动完成的“发起人”节点
|
// 特殊:强制移除自动完成的"发起人"节点
|
||||||
// 补充说明:由于 taskQuery 无法方面的过滤,所以暂时通过内存过滤
|
// 补充说明:由于 taskQuery 无法方面的过滤,所以暂时通过内存过滤
|
||||||
tasks.removeIf(task -> task.getTaskDefinitionKey().equals(START_USER_NODE_ID));
|
tasks.removeIf(task -> task.getTaskDefinitionKey().equals(START_USER_NODE_ID));
|
||||||
return new PageResult<>(tasks, count);
|
return new PageResult<>(tasks, count);
|
||||||
@@ -297,7 +298,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||||||
public Task validateTask(Long userId, String taskId) {
|
public Task validateTask(Long userId, String taskId) {
|
||||||
Task task = validateTaskExist(taskId);
|
Task task = validateTaskExist(taskId);
|
||||||
// 为什么判断 assignee 非空的情况下?
|
// 为什么判断 assignee 非空的情况下?
|
||||||
// 例如说:在审批人为空时,我们会有“自动审批通过”的策略,此时 userId 为 null,允许通过
|
// 例如说:在审批人为空时,我们会有"自动审批通过"的策略,此时 userId 为 null,允许通过
|
||||||
if (StrUtil.isNotBlank(task.getAssignee())
|
if (StrUtil.isNotBlank(task.getAssignee())
|
||||||
&& ObjectUtil.notEqual(userId, NumberUtils.parseLong(task.getAssignee()))) {
|
&& ObjectUtil.notEqual(userId, NumberUtils.parseLong(task.getAssignee()))) {
|
||||||
throw exception(TASK_OPERATE_FAIL_ASSIGN_NOT_SELF);
|
throw exception(TASK_OPERATE_FAIL_ASSIGN_NOT_SELF);
|
||||||
@@ -404,19 +405,28 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||||||
* @return 所有子任务列表
|
* @return 所有子任务列表
|
||||||
*/
|
*/
|
||||||
private List<Task> getAllChildTaskList(Task parentTask) {
|
private List<Task> getAllChildTaskList(Task parentTask) {
|
||||||
|
// 1. 获取流程实例的所有任务
|
||||||
|
List<Task> allTasks = taskService.createTaskQuery().processInstanceId(parentTask.getProcessInstanceId()).list();
|
||||||
|
if (CollUtil.isEmpty(allTasks)) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 构建父任务到子任务列表的映射关系,用于内存中快速查找
|
||||||
|
Map<String, List<Task>> childrenTaskMap = allTasks.stream()
|
||||||
|
.filter(task -> task.getParentTaskId() != null)
|
||||||
|
.collect(Collectors.groupingBy(Task::getParentTaskId));
|
||||||
|
if (CollUtil.isEmpty(childrenTaskMap)) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 使用栈进行遍历,广度或深度优先搜索所有子孙任务
|
||||||
List<Task> result = new ArrayList<>();
|
List<Task> result = new ArrayList<>();
|
||||||
// 1. 递归获取子级
|
|
||||||
Stack<Task> stack = new Stack<>();
|
Stack<Task> stack = new Stack<>();
|
||||||
stack.push(parentTask);
|
stack.push(parentTask);
|
||||||
// 2. 递归遍历
|
|
||||||
for (int i = 0; i < Short.MAX_VALUE; i++) {
|
while (!stack.isEmpty()) {
|
||||||
if (stack.isEmpty()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// 2.1 获取子任务们
|
|
||||||
Task task = stack.pop();
|
Task task = stack.pop();
|
||||||
List<Task> childTaskList = getTaskListByParentTaskId(task.getId());
|
List<Task> childTaskList = childrenTaskMap.get(task.getId());
|
||||||
// 2.2 如果非空,则添加到 stack 进一步递归
|
|
||||||
if (CollUtil.isNotEmpty(childTaskList)) {
|
if (CollUtil.isNotEmpty(childTaskList)) {
|
||||||
stack.addAll(childTaskList);
|
stack.addAll(childTaskList);
|
||||||
result.addAll(childTaskList);
|
result.addAll(childTaskList);
|
||||||
@@ -659,7 +669,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 审批通过存在“后加签”的任务。
|
* 审批通过存在"后加签"的任务。
|
||||||
* <p>
|
* <p>
|
||||||
* 注意:该任务不能马上完成,需要一个中间状态(APPROVING),并激活剩余所有子任务(PROCESS)为可审批处理
|
* 注意:该任务不能马上完成,需要一个中间状态(APPROVING),并激活剩余所有子任务(PROCESS)为可审批处理
|
||||||
* 如果马上完成,则会触发下一个任务,甚至如果没有下一个任务则流程实例就直接结束了!
|
* 如果马上完成,则会触发下一个任务,甚至如果没有下一个任务则流程实例就直接结束了!
|
||||||
@@ -771,7 +781,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||||||
BpmCommentTypeEnum.REJECT.formatComment(reqVO.getReason()));
|
BpmCommentTypeEnum.REJECT.formatComment(reqVO.getReason()));
|
||||||
// 2.3 如果当前任务时被加签的,则加它的根任务也标记成未通过
|
// 2.3 如果当前任务时被加签的,则加它的根任务也标记成未通过
|
||||||
// 疑问:为什么要标记未通过呢?
|
// 疑问:为什么要标记未通过呢?
|
||||||
// 回答:例如说 A 任务被向前加签除 B 任务时,B 任务被审批不通过,此时 A 会被取消。而 yudao-ui-admin-vue3 不展示“已取消”的任务,导致展示不出审批不通过的细节。
|
// 回答:例如说 A 任务被向前加签除 B 任务时,B 任务被审批不通过,此时 A 会被取消。而 yudao-ui-admin-vue3 不展示"已取消"的任务,导致展示不出审批不通过的细节。
|
||||||
if (task.getParentTaskId() != null) {
|
if (task.getParentTaskId() != null) {
|
||||||
String rootParentId = getTaskRootParentId(task);
|
String rootParentId = getTaskRootParentId(task);
|
||||||
updateTaskStatusAndReason(rootParentId, BpmTaskStatusEnum.REJECT.getStatus(),
|
updateTaskStatusAndReason(rootParentId, BpmTaskStatusEnum.REJECT.getStatus(),
|
||||||
@@ -1044,8 +1054,8 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||||||
/**
|
/**
|
||||||
* 校验任务是否可以加签,主要校验加签类型是否一致:
|
* 校验任务是否可以加签,主要校验加签类型是否一致:
|
||||||
* <p>
|
* <p>
|
||||||
* 1. 如果存在“向前加签”的任务,则不能“向后加签”
|
* 1. 如果存在"向前加签"的任务,则不能"向后加签"
|
||||||
* 2. 如果存在“向后加签”的任务,则不能“向前加签”
|
* 2. 如果存在"向后加签"的任务,则不能"向前加签"
|
||||||
*
|
*
|
||||||
* @param userId 当前用户 ID
|
* @param userId 当前用户 ID
|
||||||
* @param reqVO 请求参数,包含任务 ID 和加签类型
|
* @param reqVO 请求参数,包含任务 ID 和加签类型
|
||||||
@@ -1366,8 +1376,8 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||||||
Boolean skipStartUserNodeFlag = Convert.toBool(runtimeService.getVariable(processInstance.getProcessInstanceId(),
|
Boolean skipStartUserNodeFlag = Convert.toBool(runtimeService.getVariable(processInstance.getProcessInstanceId(),
|
||||||
PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE, String.class));
|
PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE, String.class));
|
||||||
if (userTaskElement.getId().equals(START_USER_NODE_ID)
|
if (userTaskElement.getId().equals(START_USER_NODE_ID)
|
||||||
&& (skipStartUserNodeFlag == null // 目的:一般是“主流程”,发起人节点,自动通过审核
|
&& (skipStartUserNodeFlag == null // 目的:一般是"主流程",发起人节点,自动通过审核
|
||||||
|| Boolean.TRUE.equals(skipStartUserNodeFlag)) // 目的:一般是“子流程”,发起人节点,按配置自动通过审核
|
|| Boolean.TRUE.equals(skipStartUserNodeFlag)) // 目的:一般是"子流程",发起人节点,按配置自动通过审核
|
||||||
&& ObjUtil.notEqual(returnTaskFlag, Boolean.TRUE)) {
|
&& ObjUtil.notEqual(returnTaskFlag, Boolean.TRUE)) {
|
||||||
getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId())
|
getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId())
|
||||||
.setReason(BpmReasonEnum.ASSIGN_START_USER_APPROVE_WHEN_SKIP_START_USER_NODE.getReason()));
|
.setReason(BpmReasonEnum.ASSIGN_START_USER_APPROVE_WHEN_SKIP_START_USER_NODE.getReason()));
|
||||||
|
Reference in New Issue
Block a user