浏览代码

Merge remote-tracking branch 'origin/feature/bpm' into feature/bpm

# Conflicts:
#	yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
jason 7 月之前
父节点
当前提交
5011cc4b31

+ 8 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskRespVO.java

@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task;
 
 import cn.iocoder.yudao.module.bpm.controller.admin.base.user.UserSimpleBaseVO;
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
@@ -33,10 +34,17 @@ public class BpmTaskRespVO {
     @Schema(description = "审批理由", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
     private String reason;
 
+    @Schema(description = "任务负责人编号", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "2048")
+    @JsonIgnore // 不返回,只是方便后续读取,赋值给 ownerUser
+    private Long owner;
     /**
      * 负责人的用户信息
      */
     private UserSimpleBaseVO ownerUser;
+
+    @Schema(description = "任务分配人编号", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "2048")
+    @JsonIgnore // 不返回,只是方便后续读取,赋值给 assigneeUser
+    private Long assignee;
     /**
      * 审核的用户信息
      */

+ 26 - 5
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmProcessInstanceConvert.java

@@ -192,7 +192,8 @@ public interface BpmProcessInstanceConvert {
     }
 
     default Set<Long> parseUserIds(HistoricProcessInstance processInstance,
-                                   List<BpmApprovalDetailRespVO.ActivityNode> activityNodes) {
+                                   List<BpmApprovalDetailRespVO.ActivityNode> activityNodes,
+                                   BpmTaskRespVO todoTask) {
         Set<Long> userIds = new HashSet<>();
         if (processInstance != null) {
             userIds.add(NumberUtils.parseLong(processInstance.getStartUserId()));
@@ -202,6 +203,14 @@ public interface BpmProcessInstanceConvert {
             CollUtil.addAll(userIds, convertSet(activityNode.getTasks(), BpmApprovalDetailRespVO.ActivityNodeTask::getOwner));
             CollUtil.addAll(userIds, activityNode.getCandidateUserIds());
         }
+        if (todoTask != null) {
+            CollUtil.addIfAbsent(userIds, todoTask.getAssignee());
+            CollUtil.addIfAbsent(userIds, todoTask.getOwner());
+            if (CollUtil.isNotEmpty(todoTask.getChildren())) {
+                CollUtil.addAll(userIds, convertSet(todoTask.getChildren(), BpmTaskRespVO::getAssignee));
+                CollUtil.addAll(userIds, convertSet(todoTask.getChildren(), BpmTaskRespVO::getOwner));
+            }
+        }
         return userIds;
     }
 
@@ -225,7 +234,7 @@ public interface BpmProcessInstanceConvert {
                                                         Map<String, String> formFieldsPermission,
                                                         Map<Long, AdminUserRespDTO> userMap,
                                                         Map<Long, DeptRespDTO> deptMap) {
-        // 1. 流程实例
+        // 1.1 流程实例
         BpmProcessInstanceRespVO processInstanceResp = null;
         if (processInstance != null) {
             AdminUserRespDTO startUser = userMap.get(NumberUtils.parseLong(processInstance.getStartUserId()));
@@ -233,12 +242,12 @@ public interface BpmProcessInstanceConvert {
             processInstanceResp = buildProcessInstance(processInstance, null, null, startUser, dept);
         }
 
-        // 2. 流程定义
+        // 1.2 流程定义
         List<UserTask> userTaskList = BpmTaskCandidateStartUserSelectStrategy.getStartUserSelectUserTaskList(bpmnModel);
         BpmProcessDefinitionRespVO definitionResp = BpmProcessDefinitionConvert.INSTANCE.buildProcessDefinition(
                 processDefinition, null, processDefinitionInfo, null, null, bpmnModel, userTaskList);
 
-        // 3. 流程节点
+        // 1.3 流程节点
         activityNodes.forEach(approveNode -> {
             if (approveNode.getTasks() != null) {
                 approveNode.getTasks().forEach(task -> {
@@ -249,7 +258,19 @@ public interface BpmProcessInstanceConvert {
             approveNode.setCandidateUsers(convertList(approveNode.getCandidateUserIds(), userId -> buildUser(userId, userMap, deptMap)));
         });
 
-        // 4. 拼接起来
+        // 1.4 待办任务
+        if (todoTask != null) {
+            todoTask.setAssigneeUser(buildUser(todoTask.getAssignee(), userMap, deptMap));
+            todoTask.setOwnerUser(buildUser(todoTask.getOwner(), userMap, deptMap));
+            if (CollUtil.isNotEmpty(todoTask.getChildren())) {
+                todoTask.getChildren().forEach(childTask -> {
+                    childTask.setAssigneeUser(buildUser(childTask.getAssignee(), userMap, deptMap));
+                    childTask.setOwnerUser(buildUser(childTask.getOwner(), userMap, deptMap));
+                });
+            }
+        }
+
+        // 2. 拼接起来
         return new BpmApprovalDetailRespVO().setStatus(processInstanceStatus)
                 .setProcessDefinition(definitionResp)
                 .setProcessInstance(processInstanceResp)

+ 7 - 26
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java

@@ -9,12 +9,10 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.module.bpm.controller.admin.base.user.UserSimpleBaseVO;
 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO;
 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.bpm.framework.flowable.core.util.FlowableUtils;
 import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO;
 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
-import org.flowable.bpmn.model.BpmnModel;
 import org.flowable.engine.history.HistoricProcessInstance;
 import org.flowable.engine.runtime.ProcessInstance;
 import org.flowable.task.api.Task;
@@ -29,7 +27,6 @@ import java.util.Map;
 
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
 import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
-import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils.isAddSignUserTask;
 
 /**
  * Bpm 任务 Convert
@@ -126,29 +123,13 @@ public interface BpmTaskConvert {
         }));
     }
 
-    default List<BpmTaskRespVO> buildTodoTaskListByUserId(Long userId, List<Task> todoTaskList,
-                                                          Map<String, List<Task>> childrenTaskMap,
-                                                          BpmnModel bpmnModel,
-                                                          Map<Long, AdminUserRespDTO> userMap,
-                                                          Map<Long, DeptRespDTO> deptMap) {
-       return convertList(todoTaskList, task -> {
-           // 找到分配给当前用户,或者当前用户加签的任务(为了减签)
-           if (!FlowableUtils.isAssignUserTask(userId, task)
-                   && !FlowableUtils.isAddSignUserTask(userId, task, childrenTaskMap)) {
-               return null;
-           }
-           BpmTaskRespVO taskVO = BeanUtils.toBean(task, BpmTaskRespVO.class);
-           taskVO.setStatus(FlowableUtils.getTaskStatus(task)).setReason(FlowableUtils.getTaskReason(task));
-           taskVO.setButtonsSetting(BpmnModelUtils.parseButtonsSetting(bpmnModel, task.getTaskDefinitionKey()));
-           buildTaskOwner(taskVO, task.getOwner(), userMap, deptMap);
-           buildTaskAssignee(taskVO, task.getAssignee(), userMap, deptMap);
-           // 如果是被加签的任务. 找到它的子任务 (为了减签)
-           // TODO @jason:如果是向后加签,这个判断有问题哈。因为向后加签后,当前任务,assignee 还是没变。可以简单点,直接拿子任务哈。另外,需要考虑子任务的子任务。
-           if (isAddSignUserTask(userId, task, childrenTaskMap)) {
-               buildTaskChildren(taskVO, childrenTaskMap, userMap, deptMap);
-           }
-           return taskVO;
-       });
+    default BpmTaskRespVO buildTodoTask(Task todoTask, List<Task> childrenTasks,
+                                              Map<Integer, BpmTaskRespVO.OperationButtonSetting> buttonsSetting) {
+        return BeanUtils.toBean(todoTask, BpmTaskRespVO.class)
+                .setStatus(FlowableUtils.getTaskStatus(todoTask)).setReason(FlowableUtils.getTaskReason(todoTask))
+                .setButtonsSetting(buttonsSetting)
+                .setChildren(convertList(childrenTasks, childTask -> BeanUtils.toBean(childTask, BpmTaskRespVO.class)
+                        .setStatus(FlowableUtils.getTaskStatus(childTask))));
     }
 
     default BpmMessageSendWhenTaskCreatedReqDTO convert(ProcessInstance processInstance, AdminUserRespDTO startUser,

+ 0 - 40
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/FlowableUtils.java

@@ -1,7 +1,5 @@
 package cn.iocoder.yudao.module.bpm.framework.flowable.core.util;
 
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.NumberUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
 import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
@@ -16,7 +14,6 @@ import org.flowable.engine.history.HistoricProcessInstance;
 import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
 import org.flowable.engine.impl.util.CommandContextUtil;
 import org.flowable.engine.runtime.ProcessInstance;
-import org.flowable.task.api.Task;
 import org.flowable.task.api.TaskInfo;
 
 import java.util.HashMap;
@@ -203,43 +200,6 @@ public class FlowableUtils {
         return taskLocalVariables;
     }
 
-    /**
-     * 判断指定用户,是否是当前任务的分配人
-     *
-     * @param userId 用户编号
-     * @param task   任务
-     * @return 是否
-     */
-    public static boolean isAssignUserTask(Long userId, Task task) {
-        Long assignee = NumberUtil.parseLong(task.getAssignee(), null);
-        return ObjectUtil.equal(userId, assignee);
-    }
-
-    /**
-     * 判断指定用户,是否是当前任务的拥有人
-     *
-     * @param userId 用户编号
-     * @param task   任务
-     * @return 是否
-     */
-    public static boolean isOwnerUserTask(Long userId, Task task) {
-        Long assignee = NumberUtil.parseLong(task.getAssignee(), null);
-        return ObjectUtil.equal(userId, assignee);
-    }
-
-    /**
-     * 判断指定用户,是否是当前任务的加签人
-     *
-     * @param userId 用户 Id
-     * @param task 任务
-     * @param  childrenTaskMap 子任务集合
-     * @return 是否
-     */
-    public static boolean isAddSignUserTask(Long userId, Task task, Map<String, List<Task>> childrenTaskMap) {
-        return (isAssignUserTask(userId, task) || isOwnerUserTask(userId, task))
-                && CollUtil.isNotEmpty(childrenTaskMap.get(task.getId()));
-    }
-
     // ========== Expression 相关的工具方法 ==========
 
     public static Object getExpressionValue(VariableContainer variableContainer, String expressionString) {

文件差异内容过多而无法显示
+ 0 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java


+ 2 - 1
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java

@@ -8,6 +8,7 @@ import jakarta.validation.Valid;
 import org.flowable.bpmn.model.UserTask;
 import org.flowable.engine.history.HistoricActivityInstance;
 import org.flowable.task.api.Task;
+import org.flowable.task.api.TaskInfo;
 import org.flowable.task.api.history.HistoricTaskInstance;
 
 import java.util.Collection;
@@ -138,7 +139,7 @@ public interface BpmTaskService {
      * @param tasks 任务列表
      * @return 子任务列表
      */
-    List<HistoricTaskInstance> getAllChildrenTaskListByParentTaskId(String parentTaskId, List<HistoricTaskInstance> tasks);
+    <T extends TaskInfo> List<T> getAllChildrenTaskListByParentTaskId(String parentTaskId, List<T> tasks);
 
     /**
      * 获取指定任务的子任务列表

+ 63 - 34
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java

@@ -40,10 +40,10 @@ import org.flowable.engine.ManagementService;
 import org.flowable.engine.RuntimeService;
 import org.flowable.engine.TaskService;
 import org.flowable.engine.history.HistoricActivityInstance;
-import org.flowable.engine.history.HistoricProcessInstance;
 import org.flowable.engine.runtime.ProcessInstance;
 import org.flowable.task.api.DelegationState;
 import org.flowable.task.api.Task;
+import org.flowable.task.api.TaskInfo;
 import org.flowable.task.api.TaskQuery;
 import org.flowable.task.api.history.HistoricTaskInstance;
 import org.flowable.task.api.history.HistoricTaskInstanceQuery;
@@ -121,46 +121,39 @@ public class BpmTaskServiceImpl implements BpmTaskService {
         return new PageResult<>(tasks, count);
     }
 
-    // TODO @芋艿:可以进一步简化
     @Override
     public BpmTaskRespVO getFirstTodoTask(Long userId, String processInstanceId) {
         if (processInstanceId == null) {
             return null;
         }
-        // 1.1 查询任务
-        TaskQuery taskQuery = taskService.createTaskQuery()
+        // 1. 查询所有任务
+        List<Task> tasks = taskService.createTaskQuery()
                 .active()
                 .processInstanceId(processInstanceId)
                 .includeTaskLocalVariables()
                 .includeProcessVariables()
-                .orderByTaskCreateTime().asc(); // 按创建时间升序
-        List<Task> todoList = taskQuery.list();
-        if (CollUtil.isEmpty(todoList)) {
+                .orderByTaskCreateTime().asc() // 按创建时间升序
+                .list();
+        if (CollUtil.isEmpty(tasks)) {
             return null;
         }
-        // 1.2 构建子任务 Map,用于减签。key:parentTaskId
-        Map<String, List<Task>> childrenTaskMap = convertMultiMap(
-                filterList(todoList, r -> StrUtil.isNotEmpty(r.getParentTaskId())),
-                Task::getParentTaskId);
 
-        // 2.1 获取用户信息
-        Set<Long> userIds = CollUtil.newHashSet();
-        todoList.forEach(task -> {
-            CollUtil.addIfAbsent(userIds, NumberUtils.parseLong((task.getAssignee())));
-            CollUtil.addIfAbsent(userIds, NumberUtils.parseLong((task.getOwner())));
+        // 2.1 查询我的首个任务
+        Task todoTask = CollUtil.findOne(tasks, task -> {
+            return isAssignUserTask(userId, task) // 当前用户为审批人
+                    || isAddSignUserTask(userId, task); // 当前用户为价钱人(为了减签)
         });
-        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds);
-        Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(
-                convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
-
-        // 2.2 构建用户待办 Task 列表
-        HistoricProcessInstance processInstance = processInstanceService.getHistoricProcessInstance(processInstanceId);
-        BpmnModel bpmnModel = bpmProcessDefinitionService.getProcessDefinitionBpmnModel(processInstance.getProcessDefinitionId());
-        List<BpmTaskRespVO> todoTasks = BpmTaskConvert.INSTANCE.buildTodoTaskListByUserId(userId, todoList, childrenTaskMap,
-                bpmnModel, userMap, deptMap);
-
-        // 2.3 找到首个任务
-        return findFirst(todoTasks, Objects::nonNull);
+        if (todoTask == null) {
+            return null;
+        }
+        // 2.2 查询该任务的子任务
+        List<Task> childrenTasks = getAllChildrenTaskListByParentTaskId(todoTask.getId(), tasks);
+
+        // 3. 转换返回
+        BpmnModel bpmnModel = bpmProcessDefinitionService.getProcessDefinitionBpmnModel(todoTask.getProcessDefinitionId());
+        Map<Integer, BpmTaskRespVO.OperationButtonSetting> buttonsSetting = BpmnModelUtils.parseButtonsSetting(
+                bpmnModel, todoTask.getTaskDefinitionKey());
+        return BpmTaskConvert.INSTANCE.buildTodoTask(todoTask, childrenTasks, buttonsSetting);
     }
 
     @Override
@@ -307,17 +300,17 @@ public class BpmTaskServiceImpl implements BpmTaskService {
     }
 
     @Override
-    public List<HistoricTaskInstance> getAllChildrenTaskListByParentTaskId(String parentTaskId, List<HistoricTaskInstance> tasks) {
+    public <T extends TaskInfo> List<T> getAllChildrenTaskListByParentTaskId(String parentTaskId, List<T> tasks) {
         if (CollUtil.isEmpty(tasks)) {
             return Collections.emptyList();
         }
-        Map<String, List<HistoricTaskInstance>> parentTaskMap = convertMultiMap(
-                filterList(tasks, task -> StrUtil.isNotEmpty(task.getParentTaskId())), HistoricTaskInstance::getParentTaskId);
+        Map<String, List<T>> parentTaskMap = convertMultiMap(
+                filterList(tasks, task -> StrUtil.isNotEmpty(task.getParentTaskId())), TaskInfo::getParentTaskId);
         if (CollUtil.isEmpty(parentTaskMap)) {
             return Collections.emptyList();
         }
 
-        List<HistoricTaskInstance> result = new ArrayList<>();
+        List<T> result = new ArrayList<>();
         // 1. 递归获取子级
         Stack<String> stack = new Stack<>();
         stack.push(parentTaskId);
@@ -328,10 +321,10 @@ public class BpmTaskServiceImpl implements BpmTaskService {
             }
             // 2.1 获取子任务们
             String taskId = stack.pop();
-            List<HistoricTaskInstance> childTaskList = filterList(tasks, task -> StrUtil.equals(task.getParentTaskId(), taskId));
+            List<T> childTaskList = filterList(tasks, task -> StrUtil.equals(task.getParentTaskId(), taskId));
             // 2.2 如果非空,则添加到 stack 进一步递归
             if (CollUtil.isNotEmpty(childTaskList)) {
-                stack.addAll(convertList(childTaskList, HistoricTaskInstance::getId));
+                stack.addAll(convertList(childTaskList, TaskInfo::getId));
                 result.addAll(childTaskList);
             }
         }
@@ -420,6 +413,42 @@ public class BpmTaskServiceImpl implements BpmTaskService {
         return historyService.createHistoricActivityInstanceQuery().executionId(executionId).list();
     }
 
+    /**
+     * 判断指定用户,是否是当前任务的审批人
+     *
+     * @param userId 用户编号
+     * @param task   任务
+     * @return 是否
+     */
+    private boolean isAssignUserTask(Long userId, Task task) {
+        Long assignee = NumberUtil.parseLong(task.getAssignee(), null);
+        return ObjectUtil.equals(userId, assignee);
+    }
+
+    /**
+     * 判断指定用户,是否是当前任务的拥有人
+     *
+     * @param userId 用户编号
+     * @param task   任务
+     * @return 是否
+     */
+    private boolean isOwnerUserTask(Long userId, Task task) {
+        Long assignee = NumberUtil.parseLong(task.getOwner(), null);
+        return ObjectUtil.equal(userId, assignee);
+    }
+
+    /**
+     * 判断指定用户,是否是当前任务的加签人
+     *
+     * @param userId 用户 Id
+     * @param task 任务
+     * @return 是否
+     */
+    private boolean isAddSignUserTask(Long userId, Task task) {
+        return (isAssignUserTask(userId, task) || isOwnerUserTask(userId, task))
+                && BpmTaskSignTypeEnum.of(task.getScopeType()) != null;
+    }
+
     // ========== Update 写入相关方法 ==========
 
     @Override

部分文件因为文件数量过多而无法显示