mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-31 18:28:43 +08:00 
			
		
		
		
	BPM:简化 task 接口的 VO,做一些合并。虽然字段上有冗余,但是读代码难度降低
This commit is contained in:
		| @@ -1,21 +1,43 @@ | ||||
| package cn.iocoder.yudao.module.bpm.controller.admin.task; | ||||
|  | ||||
| import cn.hutool.core.collection.CollUtil; | ||||
| import cn.hutool.core.util.StrUtil; | ||||
| import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||||
| 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.BeanUtils; | ||||
| import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceRespVO; | ||||
| import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; | ||||
| import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmConstants; | ||||
| import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; | ||||
| import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService; | ||||
| import cn.iocoder.yudao.module.system.api.dept.DeptApi; | ||||
| import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; | ||||
| import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||||
| import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||||
| import io.swagger.v3.oas.annotations.Operation; | ||||
| import io.swagger.v3.oas.annotations.Parameter; | ||||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||||
| import jakarta.annotation.Resource; | ||||
| import jakarta.validation.Valid; | ||||
| import org.flowable.bpmn.model.UserTask; | ||||
| import org.flowable.engine.history.HistoricProcessInstance; | ||||
| import org.flowable.engine.runtime.ProcessInstance; | ||||
| import org.flowable.task.api.Task; | ||||
| import org.flowable.task.api.history.HistoricTaskInstance; | ||||
| import org.springframework.security.access.prepost.PreAuthorize; | ||||
| import org.springframework.validation.annotation.Validated; | ||||
| import org.springframework.web.bind.annotation.*; | ||||
|  | ||||
| import jakarta.annotation.Resource; | ||||
| import jakarta.validation.Valid; | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.Set; | ||||
| import java.util.stream.Stream; | ||||
|  | ||||
| import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||||
| import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; | ||||
| import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId; | ||||
|  | ||||
| @Tag(name = "管理后台 - 流程任务实例") | ||||
| @@ -26,28 +48,103 @@ public class BpmTaskController { | ||||
|  | ||||
|     @Resource | ||||
|     private BpmTaskService taskService; | ||||
|     @Resource | ||||
|     private BpmProcessInstanceService processInstanceService; | ||||
|  | ||||
|     @Resource | ||||
|     private AdminUserApi adminUserApi; | ||||
|     @Resource | ||||
|     private DeptApi deptApi; | ||||
|  | ||||
|     @GetMapping("todo-page") | ||||
|     @Operation(summary = "获取 Todo 待办任务分页") | ||||
|     @PreAuthorize("@ss.hasPermission('bpm:task:query')") | ||||
|     public CommonResult<PageResult<BpmTaskTodoPageItemRespVO>> getTodoTaskPage(@Valid BpmTaskTodoPageReqVO pageVO) { | ||||
|         return success(taskService.getTodoTaskPage(getLoginUserId(), pageVO)); | ||||
|     public CommonResult<PageResult<BpmTaskRespVO>> getTodoTaskPage(@Valid BpmTaskPageReqVO pageVO) { | ||||
|         PageResult<Task> pageResult = taskService.getTodoTaskPage(getLoginUserId(), pageVO); | ||||
|         // 拼接数据 | ||||
|         Map<String, ProcessInstance> processInstanceMap = processInstanceService.getProcessInstanceMap( | ||||
|                 convertSet(pageResult.getList(), Task::getProcessInstanceId)); | ||||
|         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap( | ||||
|                 convertSet(processInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId()))); | ||||
|         return success(BeanUtils.toBean(pageResult, BpmTaskRespVO.class, taskVO -> { | ||||
|             ProcessInstance processInstance = processInstanceMap.get(taskVO.getProcessInstanceId()); | ||||
|             if (processInstance == null) { | ||||
|                 return; | ||||
|             } | ||||
|             AdminUserRespDTO startUser = userMap.get(NumberUtils.parseLong(processInstance.getStartUserId())); | ||||
|             taskVO.setProcessInstance(BeanUtils.toBean(processInstance, BpmTaskRespVO.ProcessInstance.class, | ||||
|                     processInstanceVO -> processInstanceVO.setStartUser(BeanUtils.toBean(startUser, BpmProcessInstanceRespVO.User.class)))); | ||||
|         })); | ||||
|     } | ||||
|  | ||||
|     @GetMapping("done-page") | ||||
|     @Operation(summary = "获取 Done 已办任务分页") | ||||
|     @PreAuthorize("@ss.hasPermission('bpm:task:query')") | ||||
|     public CommonResult<PageResult<BpmTaskDonePageItemRespVO>> getDoneTaskPage(@Valid BpmTaskDonePageReqVO pageVO) { | ||||
|         return success(taskService.getDoneTaskPage(getLoginUserId(), pageVO)); | ||||
|     public CommonResult<PageResult<BpmTaskRespVO>> getDoneTaskPage(@Valid BpmTaskPageReqVO pageVO) { | ||||
|         PageResult<HistoricTaskInstance> pageResult = taskService.getDoneTaskPage(getLoginUserId(), pageVO); | ||||
|         // 拼接数据 | ||||
|         Map<String, HistoricProcessInstance> processInstanceMap = processInstanceService.getHistoricProcessInstanceMap( | ||||
|                 convertSet(pageResult.getList(), HistoricTaskInstance::getProcessInstanceId)); | ||||
|         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap( | ||||
|                 convertSet(processInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId()))); | ||||
|         return success(BeanUtils.toBean(pageResult, BpmTaskRespVO.class, taskVO -> { | ||||
|             HistoricProcessInstance processInstance = processInstanceMap.get(taskVO.getProcessInstanceId()); | ||||
|             if (processInstance == null) { | ||||
|                 return; | ||||
|             } | ||||
|             AdminUserRespDTO startUser = userMap.get(NumberUtils.parseLong(processInstance.getStartUserId())); | ||||
|             taskVO.setProcessInstance(BeanUtils.toBean(processInstance, BpmTaskRespVO.ProcessInstance.class, | ||||
|                     processInstanceVO -> processInstanceVO.setStartUser(BeanUtils.toBean(startUser, BpmProcessInstanceRespVO.User.class)))); | ||||
|         })); | ||||
|     } | ||||
|  | ||||
|     // TODO @芋艿:怎么优化下 | ||||
|     @GetMapping("/list-by-process-instance-id") | ||||
|     @Operation(summary = "获得指定流程实例的任务列表", description = "包括完成的、未完成的") | ||||
|     @Parameter(name = "processInstanceId", description = "流程实例的编号", required = true) | ||||
|     @PreAuthorize("@ss.hasPermission('bpm:task:query')") | ||||
|     public CommonResult<List<BpmTaskRespVO>> getTaskListByProcessInstanceId( | ||||
|             @RequestParam("processInstanceId") String processInstanceId) { | ||||
|         return success(taskService.getTaskListByProcessInstanceId(processInstanceId)); | ||||
|         List<HistoricTaskInstance> taskList = taskService.getTaskListByProcessInstanceId(processInstanceId); | ||||
|         if (CollUtil.isEmpty(taskList)) { | ||||
|             return success(Collections.emptyList()); | ||||
|         } | ||||
|  | ||||
|         // 拼接数据 | ||||
|         HistoricProcessInstance processInstance = processInstanceService.getHistoricProcessInstance(processInstanceId); | ||||
|         // 获得 User 和 Dept Map | ||||
|         Set<Long> userIds = convertSet(taskList, task -> NumberUtils.parseLong(task.getAssignee())); | ||||
|         userIds.add(NumberUtils.parseLong(processInstance.getStartUserId())); | ||||
|         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds); | ||||
|         Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap( | ||||
|                 convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); | ||||
|         List<BpmTaskRespVO> taskVOList = CollectionUtils.convertList(taskList, task -> { | ||||
|             BpmTaskRespVO taskVO = BeanUtils.toBean(task, BpmTaskRespVO.class); | ||||
|             taskVO.setStatus((Integer) task.getTaskLocalVariables().get(BpmConstants.TASK_VARIABLE_STATUS)); | ||||
|             // 流程实例 | ||||
|             AdminUserRespDTO startUser = userMap.get(NumberUtils.parseLong(processInstance.getStartUserId())); | ||||
|             taskVO.setProcessInstance(BeanUtils.toBean(processInstance, BpmTaskRespVO.ProcessInstance.class, | ||||
|                     processInstanceVO -> processInstanceVO.setStartUser(BeanUtils.toBean(startUser, BpmProcessInstanceRespVO.User.class)))); | ||||
|             // 用户信息 | ||||
|             AdminUserRespDTO assignUser = userMap.get(NumberUtils.parseLong(task.getAssignee())); | ||||
|             if (assignUser != null) { | ||||
|                 taskVO.setAssigneeUser(BeanUtils.toBean(assignUser, BpmProcessInstanceRespVO.User.class)); | ||||
|                 DeptRespDTO dept = deptMap.get(assignUser.getDeptId()); | ||||
|                 if (dept != null) { | ||||
|                     taskVO.getAssigneeUser().setDeptName(dept.getName()); | ||||
|                 } | ||||
|             } | ||||
|             return taskVO; | ||||
|         }); | ||||
|  | ||||
|         // 拼接父子关系 | ||||
|         Map<String, List<BpmTaskRespVO>> childrenTaskMap = convertMultiMap( | ||||
|                 filterList(taskVOList, r -> StrUtil.isNotEmpty(r.getParentTaskId())), | ||||
|                 BpmTaskRespVO::getParentTaskId); | ||||
|         for (BpmTaskRespVO taskVO : taskVOList) { | ||||
|             taskVO.setChildren(childrenTaskMap.get(taskVO.getId())); | ||||
|         } | ||||
|         return success(filterList(taskVOList, r -> StrUtil.isEmpty(r.getParentTaskId()))); | ||||
|     } | ||||
|  | ||||
|     @PutMapping("/approve") | ||||
| @@ -74,12 +171,14 @@ public class BpmTaskController { | ||||
|         return success(true); | ||||
|     } | ||||
|  | ||||
|     @GetMapping("/return-list") | ||||
|     @GetMapping("/list-by-return") | ||||
|     @Operation(summary = "获取所有可回退的节点", description = "用于【流程详情】的【回退】按钮") | ||||
|     @Parameter(name = "taskId", description = "当前任务ID", required = true) | ||||
|     @PreAuthorize("@ss.hasPermission('bpm:task:update')") | ||||
|     public CommonResult<List<BpmTaskSimpleRespVO>> getReturnList(@RequestParam("taskId") String taskId) { | ||||
|         return success(taskService.getReturnTaskList(taskId)); | ||||
|     public CommonResult<List<BpmTaskRespVO>> getTaskListByReturn(@RequestParam("id") String id) { | ||||
|         List<UserTask> userTaskList = taskService.getUserTaskListByReturn(id); | ||||
|         return success(convertList(userTaskList, userTask -> // 只返回 id 和 name | ||||
|                 new BpmTaskRespVO().setName(userTask.getName()).setTaskDefinitionKey(userTask.getId()))); | ||||
|     } | ||||
|  | ||||
|     @PutMapping("/return") | ||||
| @@ -114,12 +213,23 @@ public class BpmTaskController { | ||||
|         return success(true); | ||||
|     } | ||||
|  | ||||
|     @GetMapping("children-list") | ||||
|     @Operation(summary = "获取能被减签的任务") | ||||
|     @Parameter(name = "parentId", description = "父级任务 ID", required = true) | ||||
|     @PreAuthorize("@ss.hasPermission('bpm:task:update')") | ||||
|     public CommonResult<List<BpmTaskSubSignRespVO>> getChildrenTaskList(@RequestParam("parentId") String parentId) { | ||||
|         return success(taskService.getChildrenTaskList(parentId)); | ||||
|     // TODO 芋艿:待测试 | ||||
|     @GetMapping("list-by-parent-task-id") | ||||
|     @Operation(summary = "获得指定父级任务的子任务列表") // 目前用于,减签的时候,获得子任务列表 | ||||
|     @Parameter(name = "parentTaskId", description = "父级任务编号", required = true) | ||||
|     @PreAuthorize("@ss.hasPermission('bpm:task:query')") | ||||
|     public CommonResult<List<BpmTaskRespVO>> getTaskListByParentTaskId(@RequestParam("parentTaskId") String parentTaskId) { | ||||
|         List<Task> taskList = taskService.getTaskListByParentTaskId(parentTaskId); | ||||
|         if (CollUtil.isEmpty(taskList)) { | ||||
|             return success(Collections.emptyList()); | ||||
|         } | ||||
|         // 拼接数据 | ||||
|         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap( | ||||
|                 convertSetByFlatMap(taskList, user -> Stream.of(Long.valueOf(user.getAssignee()), Long.valueOf(user.getOwner())))); | ||||
|         return success(convertList(taskList, task -> BeanUtils.toBean(task, BpmTaskRespVO.class, taskVO -> { | ||||
|             taskVO.setAssigneeUser(BeanUtils.toBean(userMap.get(NumberUtils.parseLong(task.getAssignee())), BpmProcessInstanceRespVO.User.class)); | ||||
|             taskVO.setOwnerUser(BeanUtils.toBean(userMap.get(NumberUtils.parseLong(task.getOwner())), BpmProcessInstanceRespVO.User.class)); | ||||
|         }))); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,27 +0,0 @@ | ||||
| package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task; | ||||
|  | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import lombok.Data; | ||||
| import lombok.EqualsAndHashCode; | ||||
| import lombok.ToString; | ||||
|  | ||||
| import java.time.LocalDateTime; | ||||
|  | ||||
| @Schema(description = "管理后台 - 流程任务的 Done 已完成的分页项 Response VO") | ||||
| @Data | ||||
| @EqualsAndHashCode(callSuper = true) | ||||
| @ToString(callSuper = true) | ||||
| public class BpmTaskDonePageItemRespVO extends BpmTaskTodoPageItemRespVO { | ||||
|  | ||||
|     @Schema(description = "结束时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||||
|     private LocalDateTime endTime; | ||||
|     @Schema(description = "持续时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000") | ||||
|     private Long durationInMillis; | ||||
|  | ||||
|     @Schema(description = "任务状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | ||||
|     private Integer status; // 参见 BpmProcessInstanceResultEnum 枚举 | ||||
|  | ||||
|     @Schema(description = "审批建议", requiredMode = Schema.RequiredMode.REQUIRED, example = "不请假了!") | ||||
|     private String reason; | ||||
|  | ||||
| } | ||||
| @@ -1,31 +0,0 @@ | ||||
| package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import lombok.Data; | ||||
| import lombok.EqualsAndHashCode; | ||||
| import lombok.ToString; | ||||
| import org.springframework.format.annotation.DateTimeFormat; | ||||
|  | ||||
| import java.time.LocalDateTime; | ||||
|  | ||||
| import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | ||||
|  | ||||
| @Schema(description = "管理后台 - 流程任务的 Done 已办的分页 Request VO") | ||||
| @Data | ||||
| @EqualsAndHashCode(callSuper = true) | ||||
| @ToString(callSuper = true) | ||||
| public class BpmTaskDonePageReqVO extends PageParam { | ||||
|  | ||||
|     @Schema(description = "流程任务名", example = "芋道") | ||||
|     private String name; | ||||
|  | ||||
|     @Schema(description = "开始的创建收间") | ||||
|     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||||
|     private LocalDateTime beginCreateTime; | ||||
|  | ||||
|     @Schema(description = "结束的创建时间") | ||||
|     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||||
|     private LocalDateTime endCreateTime; | ||||
|  | ||||
| } | ||||
| @@ -10,13 +10,11 @@ import org.springframework.format.annotation.DateTimeFormat; | ||||
| 
 | ||||
| import java.time.LocalDateTime; | ||||
| 
 | ||||
| import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | ||||
| 
 | ||||
| @Schema(description = "管理后台 - 流程任务的 TODO 待办的分页 Request VO") | ||||
| @Schema(description = "管理后台 - 流程任务的的分页 Request VO") // 待办、已办,都使用该分页 | ||||
| @Data | ||||
| @EqualsAndHashCode(callSuper = true) | ||||
| @ToString(callSuper = true) | ||||
| public class BpmTaskTodoPageReqVO extends PageParam { | ||||
| public class BpmTaskPageReqVO extends PageParam { | ||||
| 
 | ||||
|     @Schema(description = "流程任务名", example = "芋道") | ||||
|     private String name; | ||||
| @@ -1,47 +1,84 @@ | ||||
| package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task; | ||||
|  | ||||
| import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceRespVO; | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import lombok.Data; | ||||
| import lombok.EqualsAndHashCode; | ||||
| import lombok.ToString; | ||||
|  | ||||
| import java.time.LocalDateTime; | ||||
| import java.util.List; | ||||
|  | ||||
| @Schema(description = "管理后台 - 流程任务的 Response VO") | ||||
| @Schema(description = "管理后台 - 流程任务 Response VO") | ||||
| @Data | ||||
| @EqualsAndHashCode(callSuper = true) | ||||
| @ToString(callSuper = true) | ||||
| public class BpmTaskRespVO extends BpmTaskDonePageItemRespVO { | ||||
| public class BpmTaskRespVO { | ||||
|  | ||||
|     @Schema(description = "任务定义的标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "user-001") | ||||
|     private String definitionKey; | ||||
|     @Schema(description = "任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||||
|     private String id; | ||||
|  | ||||
|     @Schema(description = "任务名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道") | ||||
|     private String name; | ||||
|  | ||||
|     @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||||
|     private LocalDateTime createTime; | ||||
|  | ||||
|     @Schema(description = "结束时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||||
|     private LocalDateTime endTime; | ||||
|  | ||||
|     @Schema(description = "持续时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000") | ||||
|     private Long durationInMillis; | ||||
|  | ||||
|     @Schema(description = "任务状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | ||||
|     private Integer status; // 参见 BpmProcessInstanceResultEnum 枚举 | ||||
|  | ||||
|     /** | ||||
|      * 负责人的用户信息 | ||||
|      */ | ||||
|     private BpmProcessInstanceRespVO.User ownerUser; | ||||
|     /** | ||||
|      * 审核的用户信息 | ||||
|      */ | ||||
|     private User assigneeUser; | ||||
|     private BpmProcessInstanceRespVO.User assigneeUser; | ||||
|  | ||||
|     // TODO @芋艿:这个 key 有点问题,应该是 taskDefinitionId | ||||
|     @Schema(description = "任务定义的标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "user-001") | ||||
|     private String definitionKey; | ||||
|     @Schema(description = "任务定义的标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "Activity_one") | ||||
|     private String taskDefinitionKey; | ||||
|  | ||||
|     @Schema(description = "所属流程实例编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8888") | ||||
|     private String processInstanceId; | ||||
|  | ||||
|     /** | ||||
|      * 父任务ID | ||||
|      * 所属流程实例 | ||||
|      */ | ||||
|     private ProcessInstance processInstance; | ||||
|  | ||||
|     @Schema(description = "父任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||||
|     private String parentTaskId; | ||||
|  | ||||
|     @Schema(description = "子任务(由加签生成)", requiredMode = Schema.RequiredMode.REQUIRED, example = "childrenTask") | ||||
|     @Schema(description = "子任务列表(由加签生成)", requiredMode = Schema.RequiredMode.REQUIRED, example = "childrenTask") | ||||
|     private List<BpmTaskRespVO> children; | ||||
|  | ||||
|     @Schema(description = "用户信息") | ||||
|     @Data | ||||
|     public static class User { | ||||
|     @Schema(description = "流程实例") | ||||
|     public static class ProcessInstance { | ||||
|  | ||||
|         @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||
|         private Long id; | ||||
|         @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") | ||||
|         private String nickname; | ||||
|         @Schema(description = "流程实例编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||||
|         private String id; | ||||
|  | ||||
|         @Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||
|         private Long deptId; | ||||
|         @Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "研发部") | ||||
|         private String deptName; | ||||
|         @Schema(description = "流程实例名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道") | ||||
|         private String name; | ||||
|  | ||||
|         @Schema(description = "提交时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||||
|         private LocalDateTime createTime; | ||||
|  | ||||
|         @Schema(description = "流程定义的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") | ||||
|         private String processDefinitionId; | ||||
|  | ||||
|         /** | ||||
|          * 发起人的用户信息 | ||||
|          */ | ||||
|         private BpmProcessInstanceRespVO.User startUser; | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -15,7 +15,7 @@ public class BpmTaskReturnReqVO { | ||||
|  | ||||
|     @Schema(description = "回退到的任务 Key", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||
|     @NotEmpty(message = "回退到的任务 Key 不能为空") | ||||
|     private String targetDefinitionKey; | ||||
|     private String targetTaskDefinitionKey; | ||||
|  | ||||
|     @Schema(description = "回退意见", requiredMode = Schema.RequiredMode.REQUIRED, example = "我就是想驳回") | ||||
|     @NotEmpty(message = "回退意见不能为空") | ||||
|   | ||||
| @@ -1,16 +0,0 @@ | ||||
| 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") | ||||
| @Data | ||||
| public class BpmTaskSimpleRespVO { | ||||
|  | ||||
|     @Schema(description = "任务定义的标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "Activity_one") | ||||
|     private String definitionKey; | ||||
|  | ||||
|     @Schema(description = "任务名词", requiredMode = Schema.RequiredMode.REQUIRED, example = "经理审批") | ||||
|     private String name; | ||||
|  | ||||
| } | ||||
| @@ -1,19 +0,0 @@ | ||||
| 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") | ||||
| @Data | ||||
| public class BpmTaskSubSignRespVO { | ||||
|  | ||||
|     @Schema(description = "审核的用户信息", requiredMode = Schema.RequiredMode.REQUIRED, example = "小李") | ||||
|     private BpmTaskRespVO.User assigneeUser; | ||||
|  | ||||
|     @Schema(description = "任务 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "12312") | ||||
|     private String id; | ||||
|  | ||||
|     @Schema(description = "任务名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "经理审批") | ||||
|     private String name; | ||||
|  | ||||
| } | ||||
| @@ -1,53 +0,0 @@ | ||||
| package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task; | ||||
|  | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import lombok.Data; | ||||
|  | ||||
| import java.time.LocalDateTime; | ||||
|  | ||||
| @Schema(description = "管理后台 - 流程任务的 Running 进行中的分页项 Response VO") | ||||
| @Data | ||||
| public class BpmTaskTodoPageItemRespVO { | ||||
|  | ||||
|     @Schema(description = "任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||||
|     private String id; | ||||
|  | ||||
|     @Schema(description = "任务名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道") | ||||
|     private String name; | ||||
|  | ||||
|     @Schema(description = "接收时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||||
|     private LocalDateTime claimTime; | ||||
|  | ||||
|     @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||||
|     private LocalDateTime createTime; | ||||
|  | ||||
|     @Schema(description = "激活状态-参见 SuspensionState 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||
|     private Integer suspensionState; | ||||
|  | ||||
|     /** | ||||
|      * 所属流程实例 | ||||
|      */ | ||||
|     private ProcessInstance processInstance; | ||||
|  | ||||
|     @Data | ||||
|     @Schema(description = "流程实例") | ||||
|     public static class ProcessInstance { | ||||
|  | ||||
|         @Schema(description = "流程实例编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||||
|         private String id; | ||||
|  | ||||
|         @Schema(description = "流程实例名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道") | ||||
|         private String name; | ||||
|  | ||||
|         @Schema(description = "发起人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||||
|         private Long startUserId; | ||||
|  | ||||
|         @Schema(description = "发起人的用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") | ||||
|         private String startUserNickname; | ||||
|  | ||||
|         @Schema(description = "流程定义的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") | ||||
|         private String processDefinitionId; | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -1,35 +1,16 @@ | ||||
| package cn.iocoder.yudao.module.bpm.convert.task; | ||||
|  | ||||
| import cn.hutool.core.util.ObjectUtil; | ||||
| import cn.hutool.core.util.StrUtil; | ||||
| import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | ||||
| import cn.iocoder.yudao.framework.common.util.collection.MapUtils; | ||||
| import cn.iocoder.yudao.framework.common.util.date.DateUtils; | ||||
| import cn.iocoder.yudao.framework.common.util.number.NumberUtils; | ||||
| import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; | ||||
| import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmConstants; | ||||
| 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.FlowElement; | ||||
| import org.flowable.common.engine.impl.db.SuspensionState; | ||||
| import org.flowable.engine.history.HistoricProcessInstance; | ||||
| import org.flowable.engine.runtime.ProcessInstance; | ||||
| import org.flowable.task.api.Task; | ||||
| import org.flowable.task.api.history.HistoricTaskInstance; | ||||
| import org.flowable.task.service.impl.persistence.entity.TaskEntityImpl; | ||||
| import org.mapstruct.Mapper; | ||||
| import org.mapstruct.Mapping; | ||||
| import org.mapstruct.Mappings; | ||||
| import org.mapstruct.Named; | ||||
| import org.mapstruct.factory.Mappers; | ||||
|  | ||||
| import java.util.Date; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
|  | ||||
| import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; | ||||
| import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; | ||||
|  | ||||
| /** | ||||
|  * Bpm 任务 Convert | ||||
| @@ -41,91 +22,6 @@ public interface BpmTaskConvert { | ||||
|  | ||||
|     BpmTaskConvert INSTANCE = Mappers.getMapper(BpmTaskConvert.class); | ||||
|  | ||||
|     default List<BpmTaskTodoPageItemRespVO> convertList1(List<Task> tasks, | ||||
|                                                          Map<String, ProcessInstance> processInstanceMap, | ||||
|                                                          Map<Long, AdminUserRespDTO> userMap) { | ||||
|         return CollectionUtils.convertList(tasks, task -> { | ||||
|             BpmTaskTodoPageItemRespVO respVO = convert1(task); | ||||
|             ProcessInstance processInstance = processInstanceMap.get(task.getProcessInstanceId()); | ||||
|             if (processInstance != null) { | ||||
|                 AdminUserRespDTO startUser = userMap.get(NumberUtils.parseLong(processInstance.getStartUserId())); | ||||
|                 respVO.setProcessInstance(convert(processInstance, startUser)); | ||||
|             } | ||||
|             return respVO; | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     @Mapping(source = "suspended", target = "suspensionState", qualifiedByName = "convertSuspendedToSuspensionState") | ||||
|     BpmTaskTodoPageItemRespVO convert1(Task bean); | ||||
|  | ||||
|     @Named("convertSuspendedToSuspensionState") | ||||
|     default Integer convertSuspendedToSuspensionState(boolean suspended) { | ||||
|         return suspended ? SuspensionState.SUSPENDED.getStateCode() : SuspensionState.ACTIVE.getStateCode(); | ||||
|     } | ||||
|  | ||||
|     default List<BpmTaskDonePageItemRespVO> convertList2(List<HistoricTaskInstance> tasks, | ||||
|                                                          Map<String, HistoricProcessInstance> historicProcessInstanceMap, | ||||
|                                                          Map<Long, AdminUserRespDTO> userMap) { | ||||
|         return CollectionUtils.convertList(tasks, task -> { | ||||
|             BpmTaskDonePageItemRespVO respVO = convert2(task); | ||||
|             respVO.setStatus((Integer) task.getTaskLocalVariables().get(BpmConstants.TASK_VARIABLE_STATUS)); | ||||
|             // 流程实例 | ||||
|             HistoricProcessInstance processInstance = historicProcessInstanceMap.get(task.getProcessInstanceId()); | ||||
|             if (processInstance != null) { | ||||
|                 AdminUserRespDTO startUser = userMap.get(NumberUtils.parseLong(processInstance.getStartUserId())); | ||||
|                 respVO.setProcessInstance(convert(processInstance, startUser)); | ||||
|             } | ||||
|             return respVO; | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     BpmTaskDonePageItemRespVO convert2(HistoricTaskInstance bean); | ||||
|  | ||||
|     @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(ProcessInstance processInstance, AdminUserRespDTO startUser); | ||||
|  | ||||
|     default List<BpmTaskRespVO> convertList3(List<HistoricTaskInstance> tasks, | ||||
|                                              HistoricProcessInstance processInstance, | ||||
|                                              Map<Long, AdminUserRespDTO> userMap, Map<Long, DeptRespDTO> deptMap) { | ||||
|         return CollectionUtils.convertList(tasks, task -> { | ||||
|             BpmTaskRespVO respVO = convert3(task); | ||||
|             respVO.setStatus((Integer) task.getTaskLocalVariables().get(BpmConstants.TASK_VARIABLE_STATUS)); | ||||
|             // 流程实例 | ||||
|             if (processInstance != null) { | ||||
|                 AdminUserRespDTO startUser = userMap.get(NumberUtils.parseLong(processInstance.getStartUserId())); | ||||
|                 respVO.setProcessInstance(convert(processInstance, startUser)); | ||||
|             } | ||||
|             AdminUserRespDTO assignUser = userMap.get(NumberUtils.parseLong(task.getAssignee())); | ||||
|             if (assignUser != null) { | ||||
|                 respVO.setAssigneeUser(convert3(assignUser)); | ||||
|                 DeptRespDTO dept = deptMap.get(assignUser.getDeptId()); | ||||
|                 if (dept != null) { | ||||
|                     respVO.getAssigneeUser().setDeptName(dept.getName()); | ||||
|                 } | ||||
|             } | ||||
|             return respVO; | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     @Mapping(source = "taskDefinitionKey", target = "definitionKey") | ||||
|     BpmTaskRespVO convert3(HistoricTaskInstance bean); | ||||
|  | ||||
|     BpmTaskRespVO.User convert3(AdminUserRespDTO bean); | ||||
|  | ||||
|     @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, | ||||
|                                                       AdminUserRespDTO startUser); | ||||
|  | ||||
|     default BpmMessageSendWhenTaskCreatedReqDTO convert(ProcessInstance processInstance, AdminUserRespDTO startUser, | ||||
|                                                         Task task) { | ||||
|         BpmMessageSendWhenTaskCreatedReqDTO reqDTO = new BpmMessageSendWhenTaskCreatedReqDTO(); | ||||
| @@ -136,12 +32,6 @@ public interface BpmTaskConvert { | ||||
|         return reqDTO; | ||||
|     } | ||||
|  | ||||
|     default List<BpmTaskSimpleRespVO> convertList(List<? extends FlowElement> elementList) { | ||||
|         return CollectionUtils.convertList(elementList, element -> new BpmTaskSimpleRespVO() | ||||
|                 .setName(element.getName()) | ||||
|                 .setDefinitionKey(element.getId())); | ||||
|     } | ||||
|  | ||||
|     //此处不用 mapstruct 映射,因为 TaskEntityImpl 还有很多其他属性,这里我们只设置我们需要的 | ||||
|     //使用 mapstruct 会将里面嵌套的各个属性值都设置进去,会出现意想不到的问题 | ||||
|     default TaskEntityImpl convert(TaskEntityImpl task,TaskEntityImpl parentTask){ | ||||
| @@ -160,33 +50,4 @@ public interface BpmTaskConvert { | ||||
|         return task; | ||||
|     } | ||||
|  | ||||
|     default List<BpmTaskSubSignRespVO> convertList(List<Task> bpmTaskExtDOList, | ||||
|                                                    Map<Long, AdminUserRespDTO> userMap){ | ||||
|         return CollectionUtils.convertList(bpmTaskExtDOList, task -> { | ||||
|             BpmTaskSubSignRespVO bpmTaskSubSignRespVO = new BpmTaskSubSignRespVO() | ||||
|                     .setId(task.getId()).setName(task.getName()); | ||||
|             // 后加签任务不会直接设置 assignee ,所以不存在 assignee 的情况,则去取 owner | ||||
| //            Task sourceTask = idTaskMap.get(task.getTaskId()); | ||||
|             String assignee = ObjectUtil.defaultIfBlank(task.getOwner(), task.getAssignee()); | ||||
|             MapUtils.findAndThen(userMap,NumberUtils.parseLong(assignee), | ||||
|                     assignUser-> bpmTaskSubSignRespVO.setAssigneeUser(convert3(assignUser))); | ||||
|             return bpmTaskSubSignRespVO; | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换任务为父子级 | ||||
|      * | ||||
|      * @param sourceList 原始数据 | ||||
|      * @return 转换后的父子级数组 | ||||
|      */ | ||||
|     default List<BpmTaskRespVO> convertChildrenList(List<BpmTaskRespVO> sourceList) { | ||||
|         List<BpmTaskRespVO> childrenTaskList = filterList(sourceList, r -> StrUtil.isNotEmpty(r.getParentTaskId())); | ||||
|         Map<String, List<BpmTaskRespVO>> parentChildrenTaskListMap = convertMultiMap(childrenTaskList, BpmTaskRespVO::getParentTaskId); | ||||
|         for (BpmTaskRespVO bpmTaskRespVO : sourceList) { | ||||
|             bpmTaskRespVO.setChildren(parentChildrenTaskListMap.get(bpmTaskRespVO.getId())); | ||||
|         } | ||||
|         return filterList(sourceList, r -> StrUtil.isEmpty(r.getParentTaskId())); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,87 +0,0 @@ | ||||
| package cn.iocoder.yudao.module.bpm.dal.dataobject.task; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | ||||
| import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; | ||||
| import com.baomidou.mybatisplus.annotation.TableId; | ||||
| import com.baomidou.mybatisplus.annotation.TableName; | ||||
| import lombok.Data; | ||||
| import lombok.EqualsAndHashCode; | ||||
| import lombok.ToString; | ||||
|  | ||||
| import java.time.LocalDateTime; | ||||
|  | ||||
| /** | ||||
|  * Bpm 流程任务的拓展表 | ||||
|  * 主要解决 Flowable Task 和 HistoricTaskInstance 不支持拓展字段,所以新建拓展表 | ||||
|  * | ||||
|  * @author 芋道源码 | ||||
|  */ | ||||
| @TableName(value = "bpm_task_ext", autoResultMap = true) | ||||
| @Data | ||||
| @EqualsAndHashCode(callSuper = true) | ||||
| @ToString(callSuper = true) | ||||
| @Deprecated | ||||
| public class BpmTaskExtDO extends BaseDO { | ||||
|  | ||||
|     /** | ||||
|      * 编号,自增 | ||||
|      */ | ||||
|     @TableId | ||||
|     private Long id; | ||||
|  | ||||
|     /** | ||||
|      * 任务的审批人 | ||||
|      * | ||||
|      * 冗余 Task 的 assignee 属性 | ||||
|      */ | ||||
|     private Long assigneeUserId; | ||||
|     /** | ||||
|      * 任务的名字 | ||||
|      * | ||||
|      * 冗余 Task 的 name 属性,为了筛选 | ||||
|      */ | ||||
|     private String name; | ||||
|     /** | ||||
|      * 任务的编号 | ||||
|      * | ||||
|      * 关联 Task 的 id 属性 | ||||
|      */ | ||||
|     private String taskId; | ||||
| //    /** | ||||
| //     * 任务的标识 | ||||
| //     * | ||||
| //     * 关联 {@link Task#getTaskDefinitionKey()} | ||||
| //     */ | ||||
| //    private String definitionKey; | ||||
|     /** | ||||
|      * 任务的结果 | ||||
|      * | ||||
|      * 枚举 {@link BpmProcessInstanceResultEnum} | ||||
|      */ | ||||
|     private Integer result; | ||||
|     /** | ||||
|      * 审批建议 | ||||
|      */ | ||||
|     @Deprecated | ||||
|     private String reason; | ||||
|     /** | ||||
|      * 任务的结束时间 | ||||
|      * | ||||
|      * 冗余 HistoricTaskInstance 的 endTime  属性 | ||||
|      */ | ||||
|     private LocalDateTime endTime; | ||||
|  | ||||
|     /** | ||||
|      * 流程实例的编号 | ||||
|      * | ||||
|      * 关联 ProcessInstance 的 id 属性 | ||||
|      */ | ||||
|     private String processInstanceId; | ||||
|     /** | ||||
|      * 流程定义的编号 | ||||
|      * | ||||
|      * 关联 ProcessDefinition 的 id 属性 | ||||
|      */ | ||||
|     private String processDefinitionId; | ||||
|  | ||||
| } | ||||
| @@ -1,33 +0,0 @@ | ||||
| package cn.iocoder.yudao.module.bpm.dal.mysql.task; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | ||||
| import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO; | ||||
| import org.apache.ibatis.annotations.Mapper; | ||||
|  | ||||
| @Mapper | ||||
| public interface BpmTaskExtMapper extends BaseMapperX<BpmTaskExtDO> { | ||||
|  | ||||
| //    default void updateByTaskId(BpmTaskExtDO entity) { | ||||
| //        update(entity, new LambdaQueryWrapper<BpmTaskExtDO>().eq(BpmTaskExtDO::getTaskId, entity.getTaskId())); | ||||
| //    } | ||||
|  | ||||
| //    default List<BpmTaskExtDO> selectListByTaskIds(Collection<String> taskIds) { | ||||
| //        return selectList(BpmTaskExtDO::getTaskId, taskIds); | ||||
| //    } | ||||
|  | ||||
|     // TODO @海:BpmProcessInstanceResultEnum.CAN_SUB_SIGN_STATUS_LIST) 应该作为条件,mapper 不要有业务 | ||||
| //    default List<BpmTaskExtDO> selectProcessListByTaskIds(Collection<String> taskIds) { | ||||
| //        return selectList(new LambdaQueryWrapperX<BpmTaskExtDO>() | ||||
| //                .in(BpmTaskExtDO::getTaskId, taskIds) | ||||
| //                .in(BpmTaskExtDO::getResult, BpmProcessInstanceResultEnum.CAN_SUB_SIGN_STATUS_LIST)); | ||||
| //    } | ||||
|  | ||||
| //    default BpmTaskExtDO selectByTaskId(String taskId) { | ||||
| //        return selectOne(BpmTaskExtDO::getTaskId, taskId); | ||||
| //    } | ||||
|  | ||||
| //    default void updateBatchByTaskIdList(List<String> taskIdList, BpmTaskExtDO updateObj) { | ||||
| //        update(updateObj, new LambdaQueryWrapper<BpmTaskExtDO>().in(BpmTaskExtDO::getTaskId, taskIdList)); | ||||
| //    } | ||||
|  | ||||
| } | ||||
| @@ -4,7 +4,9 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||
| import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | ||||
| import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; | ||||
| import jakarta.validation.Valid; | ||||
| import org.flowable.bpmn.model.UserTask; | ||||
| import org.flowable.task.api.Task; | ||||
| import org.flowable.task.api.history.HistoricTaskInstance; | ||||
|  | ||||
| import java.util.Collection; | ||||
| import java.util.List; | ||||
| @@ -25,7 +27,7 @@ public interface BpmTaskService { | ||||
|      * @param pageReqVO 分页请求 | ||||
|      * @return 流程任务分页 | ||||
|      */ | ||||
|     PageResult<BpmTaskTodoPageItemRespVO> getTodoTaskPage(Long userId, BpmTaskTodoPageReqVO pageReqVO); | ||||
|     PageResult<Task> getTodoTaskPage(Long userId, BpmTaskPageReqVO pageReqVO); | ||||
|  | ||||
|     /** | ||||
|      * 获得已办的流程任务分页 | ||||
| @@ -34,7 +36,7 @@ public interface BpmTaskService { | ||||
|      * @param pageReqVO 分页请求 | ||||
|      * @return 流程任务分页 | ||||
|      */ | ||||
|     PageResult<BpmTaskDonePageItemRespVO> getDoneTaskPage(Long userId, BpmTaskDonePageReqVO pageReqVO); | ||||
|     PageResult<HistoricTaskInstance> getDoneTaskPage(Long userId, BpmTaskPageReqVO pageReqVO); | ||||
|  | ||||
|     /** | ||||
|      * 获得流程任务 Map | ||||
| @@ -56,12 +58,12 @@ public interface BpmTaskService { | ||||
|     List<Task> getTasksByProcessInstanceIds(List<String> processInstanceIds); | ||||
|  | ||||
|     /** | ||||
|      * 获得指令流程实例的流程任务列表,包括所有状态的 | ||||
|      * 获得指定流程实例的流程任务列表,包括所有状态的 | ||||
|      * | ||||
|      * @param processInstanceId 流程实例的编号 | ||||
|      * @return 流程任务列表 | ||||
|      */ | ||||
|     List<BpmTaskRespVO> getTaskListByProcessInstanceId(String processInstanceId); | ||||
|     List<HistoricTaskInstance> getTaskListByProcessInstanceId(String processInstanceId); | ||||
|  | ||||
|     /** | ||||
|      * 通过任务 | ||||
| @@ -126,12 +128,12 @@ public interface BpmTaskService { | ||||
|     Task getTask(String id); | ||||
|  | ||||
|     /** | ||||
|      * 获取当前任务的可回退的流程集合 | ||||
|      * 获取当前任务的可回退的 UserTask 集合 | ||||
|      * | ||||
|      * @param taskId 当前的任务 ID | ||||
|      * @param id 当前的任务 ID | ||||
|      * @return 可以回退的节点列表 | ||||
|      */ | ||||
|     List<BpmTaskSimpleRespVO> getReturnTaskList(String taskId); | ||||
|     List<UserTask> getUserTaskListByReturn(String id); | ||||
|  | ||||
|     /** | ||||
|      * 将任务回退到指定的 targetDefinitionKey 位置 | ||||
| @@ -158,7 +160,7 @@ public interface BpmTaskService { | ||||
|     void createSignTask(Long userId, BpmTaskAddSignReqVO reqVO); | ||||
|  | ||||
|     /** | ||||
|      * 任务减签名 | ||||
|      * 任务减签 | ||||
|      * | ||||
|      * @param userId 当前用户ID | ||||
|      * @param reqVO  被减签的任务 ID,理由 | ||||
| @@ -166,12 +168,12 @@ public interface BpmTaskService { | ||||
|     void deleteSignTask(Long userId, BpmTaskSubSignReqVO reqVO); | ||||
|  | ||||
|     /** | ||||
|      * 获取指定任务的子任务和审批人信息 | ||||
|      * 获取指定任务的子任务列表 | ||||
|      * | ||||
|      * @param parentId 指定任务ID | ||||
|      * @param parentTaskId 父任务ID | ||||
|      * @return 子任务列表 | ||||
|      */ | ||||
|     List<BpmTaskSubSignRespVO> getChildrenTaskList(String parentId); | ||||
|     List<Task> getTaskListByParentTaskId(String parentTaskId); | ||||
|  | ||||
|     /** | ||||
|      * 通过任务 ID,查询任务名 Map | ||||
|   | ||||
| @@ -13,15 +13,12 @@ import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils; | ||||
| import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; | ||||
| import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; | ||||
| import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert; | ||||
| import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmTaskExtMapper; | ||||
| import cn.iocoder.yudao.module.bpm.enums.task.BpmCommentTypeEnum; | ||||
| import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; | ||||
| import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskAddSignTypeEnum; | ||||
| import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmConstants; | ||||
| import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService; | ||||
| import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; | ||||
| import cn.iocoder.yudao.module.system.api.dept.DeptApi; | ||||
| import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; | ||||
| import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||||
| import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||||
| import jakarta.annotation.Resource; | ||||
| @@ -34,7 +31,6 @@ import org.flowable.engine.HistoryService; | ||||
| import org.flowable.engine.ManagementService; | ||||
| import org.flowable.engine.RuntimeService; | ||||
| import org.flowable.engine.TaskService; | ||||
| import org.flowable.engine.history.HistoricProcessInstance; | ||||
| import org.flowable.engine.runtime.ProcessInstance; | ||||
| import org.flowable.task.api.DelegationState; | ||||
| import org.flowable.task.api.Task; | ||||
| @@ -50,10 +46,10 @@ import org.springframework.transaction.support.TransactionSynchronizationManager | ||||
| import org.springframework.util.Assert; | ||||
|  | ||||
| import java.util.*; | ||||
| import java.util.stream.Stream; | ||||
|  | ||||
| import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | ||||
| import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; | ||||
| import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||||
| import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | ||||
| import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; | ||||
|  | ||||
| /** | ||||
| @@ -82,49 +78,31 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||||
|  | ||||
|     @Resource | ||||
|     private AdminUserApi adminUserApi; | ||||
|     @Resource | ||||
|     private DeptApi deptApi; | ||||
|  | ||||
|     @Resource | ||||
|     private BpmTaskExtMapper taskExtMapper; | ||||
|  | ||||
|     @Resource | ||||
|     private ManagementService managementService; | ||||
|  | ||||
|     @Override | ||||
|     public PageResult<BpmTaskTodoPageItemRespVO> getTodoTaskPage(Long userId, BpmTaskTodoPageReqVO pageVO) { | ||||
|         // 查询待办任务 | ||||
|     public PageResult<Task> getTodoTaskPage(Long userId, BpmTaskPageReqVO pageVO) { | ||||
|         TaskQuery taskQuery = taskService.createTaskQuery().taskAssignee(String.valueOf(userId)) // 分配给自己 | ||||
|                 .orderByTaskCreateTime().desc(); // 创建时间倒序 | ||||
|         if (StrUtil.isNotBlank(pageVO.getName())) { | ||||
|             taskQuery.taskNameLike("%" + pageVO.getName() + "%"); | ||||
|         } | ||||
|         if (ArrayUtil.get(pageVO.getCreateTime(), 0) != null) { | ||||
|         if (ArrayUtil.isNotEmpty(pageVO.getCreateTime())) { | ||||
|             taskQuery.taskCreatedAfter(DateUtils.of(pageVO.getCreateTime()[0])); | ||||
|             taskQuery.taskCreatedAfter(DateUtils.of(pageVO.getCreateTime()[1])); | ||||
|         } | ||||
|         if (ArrayUtil.get(pageVO.getCreateTime(), 1) != null) { | ||||
|             taskQuery.taskCreatedBefore(DateUtils.of(pageVO.getCreateTime()[1])); | ||||
|         long count = taskQuery.count(); | ||||
|         if (count == 0) { | ||||
|             return PageResult.empty(); | ||||
|         } | ||||
|         // 执行查询 | ||||
|         List<Task> tasks = taskQuery.listPage(PageUtils.getStart(pageVO), pageVO.getPageSize()); | ||||
|         if (CollUtil.isEmpty(tasks)) { | ||||
|             return PageResult.empty(taskQuery.count()); | ||||
|         } | ||||
|  | ||||
|         // 获得 ProcessInstance Map | ||||
|         Map<String, ProcessInstance> processInstanceMap = processInstanceService.getProcessInstanceMap( | ||||
|                 convertSet(tasks, Task::getProcessInstanceId)); | ||||
|         // 获得 User Map | ||||
|         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap( | ||||
|                 convertSet(processInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId()))); | ||||
|         // 拼接结果 | ||||
|         return new PageResult<>(BpmTaskConvert.INSTANCE.convertList1(tasks, processInstanceMap, userMap), | ||||
|                 taskQuery.count()); | ||||
|         return new PageResult<>(tasks, count); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public PageResult<BpmTaskDonePageItemRespVO> getDoneTaskPage(Long userId, BpmTaskDonePageReqVO pageVO) { | ||||
|         // 查询已办任务 | ||||
|     public PageResult<HistoricTaskInstance> getDoneTaskPage(Long userId, BpmTaskPageReqVO pageVO) { | ||||
|         HistoricTaskInstanceQuery taskQuery = historyService.createHistoricTaskInstanceQuery().finished() // 已完成 | ||||
|                 .includeTaskLocalVariables() | ||||
|                 .taskAssignee(String.valueOf(userId)) // 分配给自己 | ||||
| @@ -132,29 +110,17 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||||
|         if (StrUtil.isNotBlank(pageVO.getName())) { | ||||
|             taskQuery.taskNameLike("%" + pageVO.getName() + "%"); | ||||
|         } | ||||
|         // TODO @芋艿:传参风格,统一 | ||||
|         if (pageVO.getBeginCreateTime() != null) { | ||||
|             taskQuery.taskCreatedAfter(DateUtils.of(pageVO.getBeginCreateTime())); | ||||
|         } | ||||
|         if (pageVO.getEndCreateTime() != null) { | ||||
|             taskQuery.taskCreatedBefore(DateUtils.of(pageVO.getEndCreateTime())); | ||||
|         if (ArrayUtil.isNotEmpty(pageVO.getCreateTime())) { | ||||
|             taskQuery.taskCreatedAfter(DateUtils.of(pageVO.getCreateTime()[0])); | ||||
|             taskQuery.taskCreatedAfter(DateUtils.of(pageVO.getCreateTime()[1])); | ||||
|         } | ||||
|         // 执行查询 | ||||
|         List<HistoricTaskInstance> tasks = taskQuery.listPage(PageUtils.getStart(pageVO), pageVO.getPageSize()); | ||||
|         if (CollUtil.isEmpty(tasks)) { | ||||
|             return PageResult.empty(taskQuery.count()); | ||||
|         long count = taskQuery.count(); | ||||
|         if (count == 0) { | ||||
|             return PageResult.empty(); | ||||
|         } | ||||
|  | ||||
|         // 获得 ProcessInstance Map | ||||
|         Map<String, HistoricProcessInstance> historicProcessInstanceMap = processInstanceService.getHistoricProcessInstanceMap( | ||||
|                 convertSet(tasks, HistoricTaskInstance::getProcessInstanceId)); | ||||
|         // 获得 User Map | ||||
|         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap( | ||||
|                 convertSet(historicProcessInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId()))); | ||||
|         // 拼接结果 | ||||
|         return new PageResult<>( | ||||
|                 BpmTaskConvert.INSTANCE.convertList2(tasks, historicProcessInstanceMap, userMap), | ||||
|                 taskQuery.count()); | ||||
|         List<HistoricTaskInstance> tasks = taskQuery.listPage(PageUtils.getStart(pageVO), pageVO.getPageSize()); | ||||
|         return new PageResult<>(tasks, count); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
| @@ -166,8 +132,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public List<BpmTaskRespVO> getTaskListByProcessInstanceId(String processInstanceId) { | ||||
|         // 获得任务列表 | ||||
|     public List<HistoricTaskInstance> getTaskListByProcessInstanceId(String processInstanceId) { | ||||
|         List<HistoricTaskInstance> tasks = historyService.createHistoricTaskInstanceQuery() | ||||
|                 .includeTaskLocalVariables() | ||||
|                 .processInstanceId(processInstanceId) | ||||
| @@ -176,19 +141,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||||
|         if (CollUtil.isEmpty(tasks)) { | ||||
|             return Collections.emptyList(); | ||||
|         } | ||||
|  | ||||
|         // 获得 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, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds); | ||||
|         // 获得 Dept Map | ||||
|         Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); | ||||
|  | ||||
|         // 拼接数据 | ||||
|         List<BpmTaskRespVO> result = BpmTaskConvert.INSTANCE.convertList3(tasks, processInstance, userMap, deptMap); | ||||
|         return BpmTaskConvert.INSTANCE.convertChildrenList(result); | ||||
|         return tasks; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
| @@ -531,10 +484,10 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public List<BpmTaskSimpleRespVO> getReturnTaskList(String taskId) { | ||||
|         // 1. 校验当前任务 task 存在 | ||||
|         Task task = validateTaskExist(taskId); | ||||
|         // 根据流程定义获取流程模型信息 | ||||
|     public List<UserTask> getUserTaskListByReturn(String id) { | ||||
|         // 1.1 校验当前任务 task 存在 | ||||
|         Task task = validateTaskExist(id); | ||||
|         // 1.2 根据流程定义获取流程模型信息 | ||||
|         BpmnModel bpmnModel = bpmModelService.getBpmnModelByDefinitionId(task.getProcessDefinitionId()); | ||||
|         FlowElement source = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey()); | ||||
|         if (source == null) { | ||||
| @@ -548,7 +501,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||||
|         } | ||||
|         // 2.2 过滤:只有串行可到达的节点,才可以回退。类似非串行、子流程无法退回 | ||||
|         previousUserList.removeIf(userTask -> !BpmnModelUtils.isSequentialReachable(source, userTask, null)); | ||||
|         return BpmTaskConvert.INSTANCE.convertList(previousUserList); | ||||
|         return previousUserList; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
| @@ -560,7 +513,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||||
|             throw exception(TASK_IS_PENDING); | ||||
|         } | ||||
|         // 1.2 校验源头和目标节点的关系,并返回目标元素 | ||||
|         FlowElement targetElement = validateTargetTaskCanReturn(task.getTaskDefinitionKey(), reqVO.getTargetDefinitionKey(), task.getProcessDefinitionId()); | ||||
|         FlowElement targetElement = validateTargetTaskCanReturn(task.getTaskDefinitionKey(), reqVO.getTargetTaskDefinitionKey(), task.getProcessDefinitionId()); | ||||
|  | ||||
|         // 3. 更新任务扩展表 TODO 芋艿:需要提前搞 | ||||
|         updateTaskStatus(task.getId(), BpmProcessInstanceResultEnum.BACK.getResult()); | ||||
| @@ -635,7 +588,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||||
|         runtimeService.createChangeActivityStateBuilder() | ||||
|                 .processInstanceId(currentTask.getProcessInstanceId()) | ||||
|                 .moveActivityIdsToSingleActivityId(returnTaskKeyList, // 当前要跳转的节点列表( 1 或多) | ||||
|                         reqVO.getTargetDefinitionKey()) // targetKey 跳转到的节点(1) | ||||
|                         reqVO.getTargetTaskDefinitionKey()) // targetKey 跳转到的节点(1) | ||||
|                 .changeState(); | ||||
|     } | ||||
|  | ||||
| @@ -877,6 +830,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||||
|         return StrUtil.equalsAny(scopeType,BpmTaskAddSignTypeEnum.BEFORE.getType(),scopeType, BpmTaskAddSignTypeEnum.AFTER.getType()); | ||||
|     } | ||||
|  | ||||
| //    TODO @海:BpmProcessInstanceResultEnum.CAN_SUB_SIGN_STATUS_LIST) 应该作为条件,mapper 不要有业务 | ||||
|     /** | ||||
|      * 获取所有要被取消的删除的任务 ID 集合 | ||||
|      * | ||||
| @@ -918,42 +872,17 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||||
|      * @return 所有子任务的 ID 集合 | ||||
|      */ | ||||
|     private List<String> getChildrenTaskIdList(String parentTaskId) { | ||||
|         return convertList(getChildrenTaskList0(parentTaskId), Task::getId); | ||||
|         return convertList(getTaskListByParentTaskId(parentTaskId), Task::getId); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取指定父级任务的所有子任务 ID 集合 | ||||
|      * | ||||
|      * @param parentTaskId 父任务 ID | ||||
|      * @return 所有子任务的 ID 集合 | ||||
|      */ | ||||
|     private List<Task> getChildrenTaskList0(String parentTaskId) { | ||||
|     @Override | ||||
|     public List<Task> getTaskListByParentTaskId(String parentTaskId) { | ||||
|         String tableName = managementService.getTableName(TaskEntity.class); | ||||
|         // taskService.createTaskQuery() 没有 parentId 参数,所以写 sql 查询 | ||||
|         String sql = "select ID_,OWNER_,ASSIGNEE_ from " + tableName + " where PARENT_TASK_ID_=#{parentTaskId}"; | ||||
|         return taskService.createNativeTaskQuery().sql(sql).parameter("parentTaskId", parentTaskId).list(); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     @Override | ||||
|     public List<BpmTaskSubSignRespVO> getChildrenTaskList(String parentId) { | ||||
|         // 1. 只查询进行中的任务 后加签的任务,可能不存在 assignee,所以还需要查询 owner | ||||
|         List<Task> taskList = getChildrenTaskList0(parentId); | ||||
|         if (CollUtil.isEmpty(taskList)) { | ||||
|             return Collections.emptyList(); | ||||
|         } | ||||
|  | ||||
|         // 2.1 将 owner 和 assignee 统一到一个集合中 | ||||
|         List<Long> userIds = convertListByFlatMap(taskList, control -> | ||||
|                 Stream.of(NumberUtils.parseLong(control.getAssignee()), NumberUtils.parseLong(control.getOwner())) | ||||
|                         .filter(Objects::nonNull)); // TODO 芋艿:这里可能可以优化下 | ||||
|         // 2.2 组装数据 | ||||
|         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds); | ||||
| //        List<BpmTaskExtDO> taskExtList = taskExtMapper.selectProcessListByTaskIds(childrenTaskIdList); | ||||
| //        Map<String, Task> idTaskMap = convertMap(taskList, TaskInfo::getId); | ||||
|         return BpmTaskConvert.INSTANCE.convertList(taskList, userMap); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Map<String, String> getTaskNameByTaskIds(Collection<String> taskIds) { | ||||
|         if (CollUtil.isEmpty(taskIds)) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV