Эх сурвалжийг харах

新增 bpm 基于流程实例查询任务列表

YunaiV 3 жил өмнө
parent
commit
a4d31f9c45

+ 5 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmTaskController.http

@@ -7,3 +7,8 @@ Authorization: Bearer {{token}}
 GET {{baseUrl}}/bpm/task/done-page?pageSize=100
 tenant-id: 1
 Authorization: Bearer {{token}}
+
+### 请求 /bpm/task/list-by-process-instance-id 接口 => 成功
+GET {{baseUrl}}/bpm/task/list-by-process-instance-id?processInstanceId=537cceb3-768c-11ec-afcd-a2380e71991a
+tenant-id: 1
+Authorization: Bearer {{token}}

+ 2 - 2
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmTaskController.java

@@ -57,10 +57,10 @@ public class BpmTaskController {
     }
 
     @GetMapping("/list-by-process-instance-id")
-    @ApiOperation(value = "获得指定流程实例的任务列表", notes = "包括完成的、未完成的")
+    @ApiOperation(value = "获得指定流程实例的任务列表", notes = "包括完成的、未完成的") // TODO 芋艿:注解
     public CommonResult<List<BpmTaskRespVO>> getTaskListByProcessInstanceId(
             @RequestParam("processInstanceId") String processInstanceId) {
-        return success(taskService.getTaskSteps(taskQuery));
+        return success(taskService.getTaskListByProcessInstanceId(processInstanceId));
     }
 
     /**

+ 5 - 38
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskDonePageItemRespVO.java

@@ -3,24 +3,17 @@ package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
 
 import java.util.Date;
 
 @ApiModel("流程任务的 Done 已完成的分页项 Response VO")
 @Data
-public class BpmTaskDonePageItemRespVO {
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class BpmTaskDonePageItemRespVO extends BpmTaskTodoPageItemRespVO {
 
-    @ApiModelProperty(value = "任务编号", required = true, example = "1024")
-    private String id;
-
-    @ApiModelProperty(value = "任务名字", required = true, example = "芋道")
-    private String name;
-
-    @ApiModelProperty(value = "接收时间", required = true)
-    private Date claimTime;
-
-    @ApiModelProperty(value = "创建时间", required = true)
-    private Date createTime;
     @ApiModelProperty(value = "结束时间", required = true)
     private Date endTime;
     @ApiModelProperty(value = "持续时间", required = true, example = "1000")
@@ -31,30 +24,4 @@ public class BpmTaskDonePageItemRespVO {
     @ApiModelProperty(value = "审批建议", required = true, example = "不请假了!")
     private String comment;
 
-    /**
-     * 所属流程实例
-     */
-    private ProcessInstance processInstance;
-
-    @Data
-    @ApiModel("流程实例")
-    public static class ProcessInstance {
-
-        @ApiModelProperty(value = "流程实例编号", required = true, example = "1024")
-        private String id;
-
-        @ApiModelProperty(value = "流程实例名称", required = true, example = "芋道")
-        private String name;
-
-        @ApiModelProperty(value = "发起人的用户编号", required = true, example = "1024")
-        private Long startUserId;
-
-        @ApiModelProperty(value = "发起人的用户昵称", required = true, example = "芋艿")
-        private String startUserNickname;
-
-        @ApiModelProperty(value = "流程定义的编号", required = true, example = "2048")
-        private String processDefinitionId;
-
-    }
-
 }

+ 24 - 1
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskRespVO.java

@@ -1,15 +1,38 @@
 package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task;
 
 import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 import lombok.ToString;
 
 import java.util.List;
 
 @ApiModel("流程任务的 Response VO")
 @Data
-public class BpmTaskRespVO extends Page{
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class BpmTaskRespVO extends BpmTaskDonePageItemRespVO {
 
+    /**
+     * 审核的用户信息
+     */
+    private User assigneeUser;
 
+    @ApiModel("用户信息")
+    @Data
+    public static class User {
+
+        @ApiModelProperty(value = "用户编号", required = true, example = "1")
+        private Long id;
+        @ApiModelProperty(value = "用户昵称", required = true, example = "芋艿")
+        private String nickname;
+
+        @ApiModelProperty(value = "部门编号", required = true, example = "1")
+        private Long deptId;
+        @ApiModelProperty(value = "部门名称", required = true, example = "研发部")
+        private String deptName;
+
+    }
 
 }

+ 42 - 14
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/task/BpmTaskConvert.java

@@ -1,21 +1,19 @@
 package cn.iocoder.yudao.adminserver.modules.bpm.convert.task;
 
 import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task.BpmTaskDonePageItemRespVO;
+import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task.BpmTaskRespVO;
 import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task.BpmTaskTodoPageItemRespVO;
-import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task.TaskStepVO;
 import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task.BpmTaskExtDO;
+import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO;
 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
-import org.activiti.engine.history.HistoricActivityInstance;
+import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
 import org.activiti.engine.history.HistoricProcessInstance;
 import org.activiti.engine.history.HistoricTaskInstance;
 import org.activiti.engine.impl.persistence.entity.SuspensionState;
 import org.activiti.engine.runtime.ProcessInstance;
 import org.activiti.engine.task.Task;
-import org.mapstruct.Mapper;
-import org.mapstruct.Mapping;
-import org.mapstruct.Mappings;
-import org.mapstruct.Named;
+import org.mapstruct.*;
 import org.mapstruct.factory.Mappers;
 
 import java.util.List;
@@ -31,12 +29,6 @@ public interface BpmTaskConvert {
 
     BpmTaskConvert INSTANCE = Mappers.getMapper(BpmTaskConvert.class);
 
-    @Mappings(value = {
-            @Mapping(source = "activityName", target = "stepName"),
-            @Mapping(source = "assignee", target = "assignee")
-    })
-    TaskStepVO convert(HistoricActivityInstance instance);
-
     default List<BpmTaskTodoPageItemRespVO> convertList(List<Task> tasks, Map<String, ProcessInstance> processInstanceMap,
                                                         Map<Long, SysUserDO> userMap) {
         return CollectionUtils.convertList(tasks, task -> {
@@ -89,9 +81,9 @@ public interface BpmTaskConvert {
             @Mapping(source = "processInstance.name", target = "processInstance.name"),
             @Mapping(source = "processInstance.startUserId", target = "processInstance.startUserId"),
             @Mapping(source = "processInstance.processDefinitionId", target = "processInstance.processDefinitionId"),
-            @Mapping(source = "user.nickname", target = "processInstance.startUserNickname")
+            @Mapping(source = "startUser.nickname", target = "processInstance.startUserNickname")
     })
-    BpmTaskDonePageItemRespVO convert(HistoricTaskInstance task, BpmTaskExtDO taskExtDO, HistoricProcessInstance processInstance, SysUserDO user);
+    BpmTaskDonePageItemRespVO convert(HistoricTaskInstance task, BpmTaskExtDO taskExtDO, HistoricProcessInstance processInstance, SysUserDO startUser);
 
     @Mappings({
             @Mapping(source = "id", target = "taskId"),
@@ -100,4 +92,40 @@ public interface BpmTaskConvert {
     })
     BpmTaskExtDO convert(org.activiti.api.task.model.Task bean);
 
+    default List<BpmTaskRespVO> convertList3(List<HistoricTaskInstance> tasks, Map<String, BpmTaskExtDO> bpmTaskExtDOMap,
+                                             HistoricProcessInstance processInstance, Map<Long, SysUserDO> userMap,
+                                             Map<Long, SysDeptDO> deptMap) {
+        return CollectionUtils.convertList(tasks, task -> {
+            BpmTaskRespVO respVO = convert3(task);
+            BpmTaskExtDO taskExtDO = bpmTaskExtDOMap.get(task.getId());
+            copyTo3(taskExtDO, respVO);
+            if (processInstance != null) {
+                SysUserDO startUser = userMap.get(NumberUtils.parseLong(processInstance.getStartUserId()));
+                respVO.setProcessInstance(convert(processInstance, startUser));
+            }
+            SysUserDO assignUser = userMap.get(NumberUtils.parseLong(task.getAssignee()));
+            if (assignUser != null) {
+                respVO.setAssigneeUser(convert3(assignUser));
+                SysDeptDO dept = deptMap.get(assignUser.getDeptId());
+                if (dept != null) {
+                    respVO.getAssigneeUser().setDeptName(dept.getName());
+                }
+            }
+            return respVO;
+        });
+    }
+
+    BpmTaskRespVO convert3(HistoricTaskInstance bean);
+    BpmTaskRespVO.User convert3(SysUserDO bean);
+    void copyTo3(BpmTaskExtDO from, @MappingTarget BpmTaskRespVO to);
+
+    @Mappings({
+            @Mapping(source = "processInstance.id", target = "id"),
+            @Mapping(source = "processInstance.name", target = "name"),
+            @Mapping(source = "processInstance.startUserId", target = "startUserId"),
+            @Mapping(source = "processInstance.processDefinitionId", target = "processDefinitionId"),
+            @Mapping(source = "startUser.nickname", target = "startUserNickname")
+    })
+    BpmTaskTodoPageItemRespVO.ProcessInstance convert(HistoricProcessInstance processInstance, SysUserDO startUser);
+
 }

+ 21 - 45
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmTaskServiceImpl.java

@@ -2,6 +2,7 @@ package cn.iocoder.yudao.adminserver.modules.bpm.service.task.impl;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.io.IoUtil;
+import cn.hutool.core.util.NumberUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task.*;
 import cn.iocoder.yudao.adminserver.modules.bpm.convert.task.BpmTaskConvert;
@@ -10,10 +11,13 @@ import cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.task.BpmTaskExtMapper;
 import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceResultEnum;
 import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmProcessInstanceService;
 import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmTaskService;
+import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO;
+import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService;
 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
 import cn.iocoder.yudao.framework.common.util.object.PageUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.activiti.bpmn.constants.BpmnXMLConstants;
@@ -44,6 +48,7 @@ import javax.validation.Valid;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.*;
+import java.util.function.Function;
 
 import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.*;
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -75,6 +80,8 @@ public class BpmTaskServiceImpl implements BpmTaskService {
     @Resource
     private SysUserService userService;
     @Resource
+    private SysDeptService deptService;
+    @Resource
     @Lazy // 解决循环依赖
     private BpmProcessInstanceService processInstanceService;
 
@@ -91,13 +98,25 @@ public class BpmTaskServiceImpl implements BpmTaskService {
         // 获得任务列表
         List<HistoricTaskInstance> tasks = historyService.createHistoricTaskInstanceQuery()
                 .processInstanceId(processInstanceId)
-                .orderByTaskCreateTime().list();
+                .orderByTaskCreateTime().desc().list();
         if (CollUtil.isEmpty(tasks)) {
             return Collections.emptyList();
         }
 
+        // 获得 TaskExtDO Map
+        List<BpmTaskExtDO> bpmTaskExtDOs = taskExtMapper.selectListByTaskIds(convertSet(tasks, HistoricTaskInstance::getId));
+        Map<String, BpmTaskExtDO> bpmTaskExtDOMap = convertMap(bpmTaskExtDOs, BpmTaskExtDO::getTaskId);
+        // 获得 ProcessInstance Map
+        HistoricProcessInstance processInstance = processInstanceService.getHistoricProcessInstance(processInstanceId);
+        // 获得 User Map
+        Set<Long> userIds = convertSet(tasks, task -> NumberUtils.parseLong(task.getAssignee()));
+        userIds.add(NumberUtils.parseLong(processInstance.getStartUserId()));
+        Map<Long, SysUserDO> userMap = userService.getUserMap(userIds);
+        // 获得 Dept Map
+        Map<Long, SysDeptDO> deptMap = deptService.getDeptMap(convertSet(userMap.values(), SysUserDO::getDeptId));
+
         // 拼接数据
-        return null;
+        return BpmTaskConvert.INSTANCE.convertList3(tasks, bpmTaskExtDOMap, processInstance, userMap, deptMap);
     }
 
     @Override
@@ -113,7 +132,6 @@ public class BpmTaskServiceImpl implements BpmTaskService {
         // 查询待办任务
         TaskQuery taskQuery = taskService.createTaskQuery()
                 .taskAssignee(String.valueOf(userId)) // 分配给自己
-                .taskCandidateUser(String.valueOf(userId))
                 .orderByTaskCreateTime().desc(); // 创建时间倒序
         if (StrUtil.isNotBlank(pageVO.getName())) {
             taskQuery.taskNameLike("%" + pageVO.getName() + "%");
@@ -232,48 +250,6 @@ public class BpmTaskServiceImpl implements BpmTaskService {
 //        taskService.addComment(task.getId(), task.getProcessInstanceId(), reqVO.getComment());
     }
 
-    private List<TaskStepVO> getTaskSteps(String processInstanceId) {
-        // 获得已完成的活动
-        List<HistoricActivityInstance> finished = historyService.createHistoricActivityInstanceQuery()
-                .processInstanceId(processInstanceId)
-                .activityType("userTask")
-                .finished()
-                .orderByHistoricActivityInstanceStartTime().asc().list();
-        // 获得对应的步骤
-        List<TaskStepVO> steps = new ArrayList<>();
-        finished.forEach(instance -> {
-            TaskStepVO stepVO = BpmTaskConvert.INSTANCE.convert(instance);
-            stepVO.setStatus(1); // TODO @jason:1 这个 magic number 要枚举起来。
-            // TODO @jason:可以考虑把 comments 读取后,在统一调用 convert 拼接。另外 Comment 是废弃的类,有没其它可以使用的哈?
-            List<Comment> comments = taskService.getTaskComments(instance.getTaskId());
-            if (!CollUtil.isEmpty(comments)) {
-                stepVO.setComment(Optional.ofNullable(comments.get(0)).map(Comment::getFullMessage).orElse(""));
-            }
-            steps.add(stepVO);
-        });
-
-        // 获得未完成的活动
-        List<HistoricActivityInstance> unfinished = historyService
-                .createHistoricActivityInstanceQuery()
-                .processInstanceId(processInstanceId)
-                .activityType("userTask")
-                .unfinished().list();
-        // 获得对应的步骤
-        for (HistoricActivityInstance instance : unfinished) {
-            TaskStepVO stepVO = BpmTaskConvert.INSTANCE.convert(instance);
-            stepVO.setComment("");
-            stepVO.setStatus(0);
-            steps.add(stepVO);
-        }
-        return steps;
-    }
-
-
-    @Override
-    public List<TaskStepVO> getHistorySteps(String processInstanceId) {
-        return getTaskSteps(processInstanceId);
-    }
-
     @Override
     public FileResp getHighlightImg(String processInstanceId) {
         // 查询历史

+ 16 - 0
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/NumberUtils.java

@@ -0,0 +1,16 @@
+package cn.iocoder.yudao.framework.common.util.number;
+
+import cn.hutool.core.util.StrUtil;
+
+/**
+ * 数字的工具类,补全 {@link cn.hutool.core.util.NumberUtil} 的功能
+ *
+ * @author 芋道源码
+ */
+public class NumberUtils {
+
+    public static Long parseLong(String str) {
+        return StrUtil.isNotEmpty(str) ? Long.valueOf(str) : null;
+    }
+
+}