mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-31 18:28:43 +08:00 
			
		
		
		
	BPM:优化 task 加减签的实现
This commit is contained in:
		| @@ -4,8 +4,6 @@ import cn.hutool.core.collection.CollUtil; | ||||
| import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||
| 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.convert.task.BpmTaskConvert; | ||||
| import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; | ||||
| @@ -94,7 +92,8 @@ public class BpmTaskController { | ||||
|         // 拼接数据 | ||||
|         HistoricProcessInstance processInstance = processInstanceService.getHistoricProcessInstance(processInstanceId); | ||||
|         // 获得 User 和 Dept Map | ||||
|         Set<Long> userIds = convertSet(taskList, task -> NumberUtils.parseLong(task.getAssignee())); | ||||
|         Set<Long> userIds = convertSetByFlatMap(taskList, task -> | ||||
|                 Stream.of(NumberUtils.parseLong(task.getAssignee()), NumberUtils.parseLong(task.getOwner()))); | ||||
|         userIds.add(NumberUtils.parseLong(processInstance.getStartUserId())); | ||||
|         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds); | ||||
|         Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap( | ||||
| @@ -155,7 +154,7 @@ public class BpmTaskController { | ||||
|     @PutMapping("/create-sign") | ||||
|     @Operation(summary = "加签", description = "before 前加签,after 后加签") | ||||
|     @PreAuthorize("@ss.hasPermission('bpm:task:update')") | ||||
|     public CommonResult<Boolean> createSignTask(@Valid @RequestBody BpmTaskAddSignReqVO reqVO) { | ||||
|     public CommonResult<Boolean> createSignTask(@Valid @RequestBody BpmTaskSignCreateReqVO reqVO) { | ||||
|         taskService.createSignTask(getLoginUserId(), reqVO); | ||||
|         return success(true); | ||||
|     } | ||||
| @@ -163,13 +162,12 @@ public class BpmTaskController { | ||||
|     @DeleteMapping("/delete-sign") | ||||
|     @Operation(summary = "减签") | ||||
|     @PreAuthorize("@ss.hasPermission('bpm:task:update')") | ||||
|     public CommonResult<Boolean> deleteSignTask(@Valid @RequestBody BpmTaskSubSignReqVO reqVO) { | ||||
|     public CommonResult<Boolean> deleteSignTask(@Valid @RequestBody BpmTaskSignDeleteReqVO reqVO) { | ||||
|         taskService.deleteSignTask(getLoginUserId(), reqVO); | ||||
|         return success(true); | ||||
|     } | ||||
|  | ||||
|     // TODO 芋艿:待测试 | ||||
|     @GetMapping("list-by-parent-task-id") | ||||
|     @GetMapping("/list-by-parent-task-id") | ||||
|     @Operation(summary = "获得指定父级任务的子任务列表") // 目前用于,减签的时候,获得子任务列表 | ||||
|     @Parameter(name = "parentTaskId", description = "父级任务编号", required = true) | ||||
|     @PreAuthorize("@ss.hasPermission('bpm:task:query')") | ||||
| @@ -179,12 +177,11 @@ public class BpmTaskController { | ||||
|             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)); | ||||
|         }))); | ||||
|         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertSetByFlatMap(taskList, | ||||
|                 user -> Stream.of(NumberUtils.parseLong(user.getAssignee()), NumberUtils.parseLong(user.getOwner())))); | ||||
|         Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap( | ||||
|                 convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); | ||||
|         return success(BpmTaskConvert.INSTANCE.buildTaskListByParentTaskId(taskList, userMap, deptMap)); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,30 +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 jakarta.validation.constraints.NotEmpty; | ||||
| import java.util.Set; | ||||
|  | ||||
| // TODO @海洋:类名,应该是 create 哈 | ||||
| @Schema(description = "管理后台 - 加签流程任务的 Request VO") | ||||
| @Data | ||||
| public class BpmTaskAddSignReqVO { | ||||
|  | ||||
|     @Schema(description = "需要加签的任务 ID") | ||||
|     @NotEmpty(message = "任务编号不能为空") | ||||
|     private String id; | ||||
|  | ||||
|     @Schema(description = "加签的用户 ID") | ||||
|     @NotEmpty(message = "加签用户 ID 不能为空") | ||||
|     private Set<Long> userIdList; | ||||
|  | ||||
|     @Schema(description = "加签类型,before 向前加签,after 向后加签") | ||||
|     @NotEmpty(message = "加签类型不能为空") | ||||
|     private String type; | ||||
|  | ||||
|     @Schema(description = "加签原因") | ||||
|     @NotEmpty(message = "加签原因不能为空") | ||||
|     private String reason; | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,29 @@ | ||||
| package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task; | ||||
|  | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import lombok.Data; | ||||
|  | ||||
| import jakarta.validation.constraints.NotEmpty; | ||||
| import java.util.Set; | ||||
|  | ||||
| @Schema(description = "管理后台 - 加签任务的创建(加签) Request VO") | ||||
| @Data | ||||
| public class BpmTaskSignCreateReqVO { | ||||
|  | ||||
|     @Schema(description = "需要加签的任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||
|     @NotEmpty(message = "任务编号不能为空") | ||||
|     private String id; | ||||
|  | ||||
|     @Schema(description = "加签的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "888") | ||||
|     @NotEmpty(message = "加签用户不能为空") | ||||
|     private Set<Long> userIds; | ||||
|  | ||||
|     @Schema(description = "加签类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "before") | ||||
|     @NotEmpty(message = "加签类型不能为空") | ||||
|     private String type; // 参见 BpmTaskSignTypeEnum 枚举 | ||||
|  | ||||
|     @Schema(description = "加签原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "需要加签") | ||||
|     @NotEmpty(message = "加签原因不能为空") | ||||
|     private String reason; | ||||
|  | ||||
| } | ||||
| @@ -5,16 +5,16 @@ import lombok.Data; | ||||
| 
 | ||||
| import jakarta.validation.constraints.NotEmpty; | ||||
| 
 | ||||
| // TODO @海洋:类名,应该是 delete 哈 | ||||
| @Schema(description = "管理后台 - 减签流程任务的 Request VO") | ||||
| @Schema(description = "管理后台 - 加签任务的删除(减签) Request VO") | ||||
| @Data | ||||
| public class BpmTaskSubSignReqVO { | ||||
| public class BpmTaskSignDeleteReqVO { | ||||
| 
 | ||||
|     @Schema(description = "被减签的任务 ID") | ||||
|     @Schema(description = "被减签的任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||
|     @NotEmpty(message = "任务编号不能为空") | ||||
|     private String id; | ||||
| 
 | ||||
|     @Schema(description = "加签原因") | ||||
|     @Schema(description = "加签原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "需要减签") | ||||
|     @NotEmpty(message = "加签原因不能为空") | ||||
|     private String reason; | ||||
| 
 | ||||
| } | ||||
| @@ -24,8 +24,7 @@ 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; | ||||
| import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; | ||||
|  | ||||
| /** | ||||
|  * Bpm 任务 Convert | ||||
| @@ -91,6 +90,14 @@ public interface BpmTaskConvert { | ||||
|                     taskVO.getAssigneeUser().setDeptName(dept.getName()); | ||||
|                 } | ||||
|             } | ||||
|             AdminUserRespDTO ownerUser = userMap.get(NumberUtils.parseLong(task.getOwner())); | ||||
|             if (ownerUser != null) { | ||||
|                 taskVO.setOwnerUser(BeanUtils.toBean(ownerUser, BpmProcessInstanceRespVO.User.class)); | ||||
|                 DeptRespDTO dept = deptMap.get(ownerUser.getDeptId()); | ||||
|                 if (dept != null) { | ||||
|                     taskVO.getOwnerUser().setDeptName(dept.getName()); | ||||
|                 } | ||||
|             } | ||||
|             return taskVO; | ||||
|         }); | ||||
|  | ||||
| @@ -104,6 +111,29 @@ public interface BpmTaskConvert { | ||||
|         return filterList(taskVOList, r -> StrUtil.isEmpty(r.getParentTaskId())); | ||||
|     } | ||||
|  | ||||
|     default List<BpmTaskRespVO> buildTaskListByParentTaskId(List<Task> taskList, | ||||
|                                                             Map<Long, AdminUserRespDTO> userMap, | ||||
|                                                             Map<Long, DeptRespDTO> deptMap) { | ||||
|         return convertList(taskList, task -> BeanUtils.toBean(task, BpmTaskRespVO.class, taskVO -> { | ||||
|             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()); | ||||
|                 } | ||||
|             } | ||||
|             AdminUserRespDTO ownerUser = userMap.get(NumberUtils.parseLong(task.getOwner())); | ||||
|             if (ownerUser != null) { | ||||
|                 taskVO.setOwnerUser(BeanUtils.toBean(ownerUser, BpmProcessInstanceRespVO.User.class)); | ||||
|                 DeptRespDTO dept = deptMap.get(ownerUser.getDeptId()); | ||||
|                 if (dept != null) { | ||||
|                     taskVO.getOwnerUser().setDeptName(dept.getName()); | ||||
|                 } | ||||
|             } | ||||
|         })); | ||||
|     } | ||||
|  | ||||
|     default BpmMessageSendWhenTaskCreatedReqDTO convert(ProcessInstance processInstance, AdminUserRespDTO startUser, | ||||
|                                                         Task task) { | ||||
|         BpmMessageSendWhenTaskCreatedReqDTO reqDTO = new BpmMessageSendWhenTaskCreatedReqDTO(); | ||||
| @@ -114,22 +144,28 @@ public interface BpmTaskConvert { | ||||
|         return reqDTO; | ||||
|     } | ||||
|  | ||||
|     //此处不用 mapstruct 映射,因为 TaskEntityImpl 还有很多其他属性,这里我们只设置我们需要的 | ||||
|     //使用 mapstruct 会将里面嵌套的各个属性值都设置进去,会出现意想不到的问题 | ||||
|     default TaskEntityImpl convert(TaskEntityImpl task,TaskEntityImpl parentTask){ | ||||
|         task.setCategory(parentTask.getCategory()); | ||||
|         task.setDescription(parentTask.getDescription()); | ||||
|         task.setTenantId(parentTask.getTenantId()); | ||||
|         task.setName(parentTask.getName()); | ||||
|         task.setParentTaskId(parentTask.getId()); | ||||
|         task.setProcessDefinitionId(parentTask.getProcessDefinitionId()); | ||||
|         task.setProcessInstanceId(parentTask.getProcessInstanceId()); | ||||
| //        task.setExecutionId(parentTask.getExecutionId()); // TODO 芋艿:新加的,不太确定;尴尬,不加时,子任务不通过会失败(报错);加了,子任务审批通过会失败(报错) | ||||
|         task.setTaskDefinitionKey(parentTask.getTaskDefinitionKey()); | ||||
|         task.setTaskDefinitionId(parentTask.getTaskDefinitionId()); | ||||
|         task.setPriority(parentTask.getPriority()); | ||||
|         task.setCreateTime(new Date()); | ||||
|         return task; | ||||
|     /** | ||||
|      * 将父任务的属性,拷贝到子任务(加签任务) | ||||
|      * | ||||
|      * 为什么不使用 mapstruct 映射?因为 TaskEntityImpl 还有很多其他属性,这里我们只设置我们需要的。 | ||||
|      * 使用 mapstruct 会将里面嵌套的各个属性值都设置进去,会出现意想不到的问题。 | ||||
|      * | ||||
|      * @param parentTask 父任务 | ||||
|      * @param childTask 加签任务 | ||||
|      */ | ||||
|     default void copyTo(TaskEntityImpl parentTask, TaskEntityImpl childTask) { | ||||
|         childTask.setName(parentTask.getName()); | ||||
|         childTask.setDescription(parentTask.getDescription()); | ||||
|         childTask.setCategory(parentTask.getCategory()); | ||||
|         childTask.setParentTaskId(parentTask.getId()); | ||||
|         childTask.setProcessDefinitionId(parentTask.getProcessDefinitionId()); | ||||
|         childTask.setProcessInstanceId(parentTask.getProcessInstanceId()); | ||||
| //        childTask.setExecutionId(parentTask.getExecutionId()); // TODO 芋艿:新加的,不太确定;尴尬,不加时,子任务不通过会失败(报错);加了,子任务审批通过会失败(报错) | ||||
|         childTask.setTaskDefinitionKey(parentTask.getTaskDefinitionKey()); | ||||
|         childTask.setTaskDefinitionId(parentTask.getTaskDefinitionId()); | ||||
|         childTask.setPriority(parentTask.getPriority()); | ||||
|         childTask.setCreateTime(new Date()); | ||||
|         childTask.setTenantId(parentTask.getTenantId()); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -148,7 +148,7 @@ public interface BpmTaskService { | ||||
|      * @param userId 被加签的用户和任务 ID,加签类型 | ||||
|      * @param reqVO  当前用户 ID | ||||
|      */ | ||||
|     void createSignTask(Long userId, BpmTaskAddSignReqVO reqVO); | ||||
|     void createSignTask(Long userId, BpmTaskSignCreateReqVO reqVO); | ||||
|  | ||||
|     /** | ||||
|      * 任务减签 | ||||
| @@ -156,7 +156,7 @@ public interface BpmTaskService { | ||||
|      * @param userId 当前用户ID | ||||
|      * @param reqVO  被减签的任务 ID,理由 | ||||
|      */ | ||||
|     void deleteSignTask(Long userId, BpmTaskSubSignReqVO reqVO); | ||||
|     void deleteSignTask(Long userId, BpmTaskSignDeleteReqVO reqVO); | ||||
|  | ||||
|     /** | ||||
|      * 获取指定任务的子任务列表 | ||||
|   | ||||
| @@ -13,7 +13,10 @@ 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.enums.task.*; | ||||
| import cn.iocoder.yudao.module.bpm.enums.task.BpmCommentTypeEnum; | ||||
| import cn.iocoder.yudao.module.bpm.enums.task.BpmDeleteReasonEnum; | ||||
| import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskSignTypeEnum; | ||||
| import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatustEnum; | ||||
| 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; | ||||
| @@ -44,10 +47,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.convertList; | ||||
| import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | ||||
| import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; | ||||
| import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; | ||||
|  | ||||
| /** | ||||
| @@ -170,7 +173,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||||
|         } | ||||
|  | ||||
|         // 情况二:审批有【后】加签的任务 | ||||
|         if (BpmTaskAddSignTypeEnum.AFTER.getType().equals(task.getScopeType())) { | ||||
|         if (BpmTaskSignTypeEnum.AFTER.getType().equals(task.getScopeType())) { | ||||
|             approveAfterSignTask(task, reqVO); | ||||
|             return; | ||||
|         } | ||||
| @@ -191,29 +194,23 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||||
|     /** | ||||
|      * 审批通过存在“后加签”的任务。 | ||||
|      * <p> | ||||
|      * 注意:该任务不能马上完成,需要一个中间状态(SIGN_AFTER),并激活剩余所有子任务(PROCESS)为可审批处理 | ||||
|      * 注意:该任务不能马上完成,需要一个中间状态(APPROVING),并激活剩余所有子任务(PROCESS)为可审批处理 | ||||
|      * 如果马上完成,则会触发下一个任务,甚至如果没有下一个任务则流程实例就直接结束了! | ||||
|      * | ||||
|      * @param task  当前任务 | ||||
|      * @param reqVO 前端请求参数 | ||||
|      */ | ||||
|     private void approveAfterSignTask(Task task, BpmTaskApproveReqVO reqVO) { | ||||
|         // 1. 有向后加签,则该任务状态临时设置为 ADD_SIGN_AFTER 状态 | ||||
| //        taskExtMapper.updateByTaskId( | ||||
| //                new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.SIGN_AFTER.getResult()) | ||||
| //                        .setReason(reqVO.getReason()).setEndTime(LocalDateTime.now())); | ||||
|         // TODO @芋艿:reqVO.reason??? | ||||
|         updateTaskStatus(task.getId(), BpmTaskStatustEnum.APPROVING.getStatus()); | ||||
|         // 更新父 task 状态 + 原因 | ||||
|         updateTaskStatusAndReason(task.getId(), BpmTaskStatustEnum.APPROVING.getStatus(), reqVO.getReason()); | ||||
|  | ||||
|         // 2. 激活子任务 | ||||
|         List<String> childrenTaskIdList = getChildrenTaskIdList(task.getId()); | ||||
|         for (String childrenTaskId : childrenTaskIdList) { | ||||
|             taskService.resolveTask(childrenTaskId); | ||||
|             // 更新任务扩展表中子任务为进行中 | ||||
|             updateTaskStatus(childrenTaskId, BpmTaskStatustEnum.RUNNING.getStatus()); | ||||
|         List<Task> childrenTaskList = getTaskListByParentTaskId(task.getId()); | ||||
|         for (Task childrenTask : childrenTaskList) { | ||||
|             taskService.resolveTask(childrenTask.getId()); | ||||
|             // 更新子 task 状态 | ||||
|             updateTaskStatus(childrenTask.getId(), BpmTaskStatustEnum.RUNNING.getStatus()); | ||||
|         } | ||||
|         // 2.1 更新任务扩展表中子任务为进行中 | ||||
| //        taskExtMapper.updateBatchByTaskIdList(childrenTaskIdList, | ||||
| //                new BpmTaskExtDO().setResult(BpmProcessInstanceResultEnum.PROCESS.getResult())); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -229,14 +226,14 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||||
|             return; | ||||
|         } | ||||
|         // 1.1 判断是否还有子任务。如果没有,就不处理 | ||||
|         Long childrenTaskCount = getChildrenTaskCount(parentTaskId); | ||||
|         Long childrenTaskCount = getTaskCountByParentTaskId(parentTaskId); | ||||
|         if (childrenTaskCount > 0) { | ||||
|             return; | ||||
|         } | ||||
|         // 1.2 只处理加签的父任务 | ||||
|         Task parentTask = validateTaskExist(parentTaskId); | ||||
|         String scopeType = parentTask.getScopeType(); | ||||
|         if (!validateSignType(scopeType)){ | ||||
|         if (BpmTaskSignTypeEnum.of(scopeType) == null){ | ||||
|             return; | ||||
|         } | ||||
|  | ||||
| @@ -246,14 +243,20 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||||
|         taskService.saveTask(parentTaskImpl); | ||||
|  | ||||
|         // 3.1 情况一:处理向【向前】加签 | ||||
|         if (BpmTaskAddSignTypeEnum.BEFORE.getType().equals(scopeType)) { | ||||
|         if (BpmTaskSignTypeEnum.BEFORE.getType().equals(scopeType)) { | ||||
|             // 3.1.1 owner 重新赋值给父任务的 assignee,这样它就可以被审批 | ||||
|             taskService.resolveTask(parentTaskId); | ||||
|             // 3.1.2 更新流程任务 status | ||||
|             updateTaskStatus(parentTaskId, BpmTaskStatustEnum.RUNNING.getStatus()); | ||||
|         // 3.2 情况二:处理向【向后】加签 | ||||
|         } else if (BpmTaskAddSignTypeEnum.AFTER.getType().equals(scopeType)) { | ||||
|             // 3.2.1 完成自己(因为它已经没有子任务,所以也可以完成) | ||||
|         } else if (BpmTaskSignTypeEnum.AFTER.getType().equals(scopeType)) { | ||||
|             // 只有 parentTask 处于 APPROVING 的情况下,才可以继续 complete 完成 | ||||
|             // 否则,一个未审批的 parentTask 任务,在加签出来的任务都被减签的情况下,就直接完成审批,这样会存在问题 | ||||
|             Integer status = (Integer) parentTask.getTaskLocalVariables().get(BpmConstants.TASK_VARIABLE_STATUS); | ||||
|             if (ObjectUtil.notEqual(status, BpmTaskStatustEnum.APPROVING.getStatus())) { | ||||
|                 return; | ||||
|             } | ||||
|             // 3.2.2 完成自己(因为它已经没有子任务,所以也可以完成) | ||||
|             updateTaskStatus(parentTaskId, BpmTaskStatustEnum.APPROVE.getStatus()); | ||||
|             taskService.complete(parentTaskId); | ||||
|         } | ||||
| @@ -262,18 +265,6 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||||
|         handleParentTaskIfSign(parentTask.getParentTaskId()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取子任务个数 | ||||
|      * | ||||
|      * @param parentTaskId 父任务 ID | ||||
|      * @return 剩余子任务个数 | ||||
|      */ | ||||
|     private Long getChildrenTaskCount(String parentTaskId) { | ||||
|         String tableName = managementService.getTableName(TaskEntity.class); | ||||
|         String sql = "SELECT COUNT(1) from " + tableName + " WHERE PARENT_TASK_ID_=#{parentTaskId}"; | ||||
|         return taskService.createNativeTaskQuery().sql(sql).parameter("parentTaskId", parentTaskId).count(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 审批被委派的任务 | ||||
|      * | ||||
| @@ -339,7 +330,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 校验任务是否存在, 并且是否是分配给自己的任务 | ||||
|      * 校验任务是否存在,并且是否是分配给自己的任务 | ||||
|      * | ||||
|      * @param userId 用户 id | ||||
|      * @param taskId task id | ||||
| @@ -388,7 +379,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||||
|  | ||||
|             @Override | ||||
|             public void afterCommit() { | ||||
|                 if (StrUtil.isNotEmpty(task.getAssignee())) { | ||||
|                 if (StrUtil.isEmpty(task.getAssignee())) { | ||||
|                     return; | ||||
|                 } | ||||
|                 ProcessInstance processInstance = processInstanceService.getProcessInstance(task.getProcessInstanceId()); | ||||
| @@ -574,52 +565,45 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||||
|  | ||||
|     @Override | ||||
|     @Transactional(rollbackFor = Exception.class) | ||||
|     public void createSignTask(Long userId, BpmTaskAddSignReqVO reqVO) { | ||||
|     public void createSignTask(Long userId, BpmTaskSignCreateReqVO reqVO) { | ||||
|         // 1. 获取和校验任务 | ||||
|         TaskEntityImpl taskEntity = validateAddSign(userId, reqVO); | ||||
|         List<AdminUserRespDTO> userList = adminUserApi.getUserList(reqVO.getUserIdList()); | ||||
|         TaskEntityImpl taskEntity = validateTaskCanCreateSign(userId, reqVO); | ||||
|         List<AdminUserRespDTO> userList = adminUserApi.getUserList(reqVO.getUserIds()); | ||||
|         if (CollUtil.isEmpty(userList)) { | ||||
|             throw exception(TASK_ADD_SIGN_USER_NOT_EXIST); | ||||
|             throw exception(TASK_SIGN_CREATE_USER_NOT_EXIST); | ||||
|         } | ||||
|  | ||||
|         // 2. 处理当前任务 | ||||
|         // 2.1 开启计数功能,主要用于为了让表 ACT_RU_TASK 中的 SUB_TASK_COUNT_ 字段记录下总共有多少子任务,后续可能有用 | ||||
|         taskEntity.setCountEnabled(true); | ||||
|         if (reqVO.getType().equals(BpmTaskAddSignTypeEnum.BEFORE.getType())) { | ||||
|             // 2.2 向前加签,设置 owner,置空 assign。等子任务都完成后,再调用 resolveTask 重新将 owner 设置为 assign | ||||
|             // 原因是:不能和向前加签的子任务一起审批,需要等前面的子任务都完成才能审批 | ||||
|         // 2.2 向前加签,设置 owner,置空 assign。等子任务都完成后,再调用 resolveTask 重新将 owner 设置为 assign | ||||
|         // 原因是:不能和向前加签的子任务一起审批,需要等前面的子任务都完成才能审批 | ||||
|         if (reqVO.getType().equals(BpmTaskSignTypeEnum.BEFORE.getType())) { | ||||
|             taskEntity.setOwner(taskEntity.getAssignee()); | ||||
|             taskEntity.setAssignee(null); | ||||
|             // 2.3 更新扩展表状态 | ||||
| //            taskExtMapper.updateByTaskId( | ||||
| //                    new BpmTaskExtDO().setTaskId(taskEntity.getId()) | ||||
| //                            .setResult(BpmProcessInstanceResultEnum.SIGN_BEFORE.getResult()) | ||||
| //                            .setReason(reqVO.getReason())); | ||||
| //            taskEntity.setTransientVariableLocal(BpmConstants.TASK_VARIABLE_STATUS, BpmProcessInstanceResultEnum.SIGN_BEFORE.getResult()); | ||||
| //            updateTaskStatus(taskEntity.getId(), BpmProcessInstanceResultEnum.SIGN_BEFORE.getResult()); // TODO 芋艿:貌似会有实物并发的问题;所以不能用这个调用,只能 set | ||||
|         } | ||||
|         // 2.4 记录加签方式,完成任务时需要用到判断 | ||||
|         taskEntity.setScopeType(reqVO.getType()); | ||||
|         // 2.5 保存当前任务修改后的值 | ||||
|         taskService.saveTask(taskEntity); | ||||
|         if (reqVO.getType().equals(BpmTaskAddSignTypeEnum.BEFORE.getType())) { | ||||
|             updateTaskStatus(taskEntity.getId(), BpmTaskStatustEnum.WAIT.getStatus()); // TODO 芋艿:貌似只能放在这个地方,不然会有并发修改的报错 | ||||
|         // 2.6 更新 task 状态为 WAIT,只有在向前加签的时候 | ||||
|         if (reqVO.getType().equals(BpmTaskSignTypeEnum.BEFORE.getType())) { | ||||
|             updateTaskStatus(taskEntity.getId(), BpmTaskStatustEnum.WAIT.getStatus()); | ||||
|         } | ||||
|  | ||||
|         // 3. 创建加签任务 | ||||
|         createSignTask(convertList(reqVO.getUserIdList(), String::valueOf), taskEntity); | ||||
|         createSignTaskList(convertList(reqVO.getUserIds(), String::valueOf), taskEntity); | ||||
|  | ||||
|         // 4. 记录加签 comment,拼接结果为: [当前用户]向前加签/向后加签给了[多个用户],理由为:reason | ||||
|         // 4. 记录加签的评论到 task 任务 | ||||
|         AdminUserRespDTO currentUser = adminUserApi.getUser(userId); | ||||
|         String comment = StrUtil.format(BpmCommentTypeEnum.ADD_SIGN.getComment(), currentUser.getNickname(), | ||||
|                 BpmTaskAddSignTypeEnum.formatDesc(reqVO.getType()), String.join(",", convertList(userList, AdminUserRespDTO::getNickname)), reqVO.getReason()); | ||||
|         taskService.addComment(reqVO.getId(), taskEntity.getProcessInstanceId(), | ||||
|                 BpmCommentTypeEnum.ADD_SIGN.getType().toString(), comment); | ||||
|         String comment = StrUtil.format(BpmCommentTypeEnum.ADD_SIGN.getComment(), | ||||
|                 currentUser.getNickname(), BpmTaskSignTypeEnum.nameOfType(reqVO.getType()), | ||||
|                 String.join(",", convertList(userList, AdminUserRespDTO::getNickname)), reqVO.getReason()); | ||||
|         taskService.addComment(reqVO.getId(), taskEntity.getProcessInstanceId(), BpmCommentTypeEnum.ADD_SIGN.getType(), comment); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * 校验任务的加签是否一致 | ||||
|      * 校验任务是否可以加签,主要校验加签类型是否一致: | ||||
|      * <p> | ||||
|      * 1. 如果存在“向前加签”的任务,则不能“向后加签” | ||||
|      * 2. 如果存在“向后加签”的任务,则不能“向前加签” | ||||
| @@ -628,24 +612,23 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||||
|      * @param reqVO  请求参数,包含任务 ID 和加签类型 | ||||
|      * @return 当前任务 | ||||
|      */ | ||||
|     private TaskEntityImpl validateAddSign(Long userId, BpmTaskAddSignReqVO reqVO) { | ||||
|     private TaskEntityImpl validateTaskCanCreateSign(Long userId, BpmTaskSignCreateReqVO reqVO) { | ||||
|         TaskEntityImpl taskEntity = (TaskEntityImpl) validateTask(userId, reqVO.getId()); | ||||
|         // 向前加签和向后加签不能同时存在 | ||||
|         if (taskEntity.getScopeType() != null | ||||
|                 && ObjectUtil.notEqual(taskEntity.getScopeType(), reqVO.getType())) { | ||||
|             throw exception(TASK_ADD_SIGN_TYPE_ERROR, | ||||
|                     BpmTaskAddSignTypeEnum.formatDesc(taskEntity.getScopeType()), BpmTaskAddSignTypeEnum.formatDesc(reqVO.getType())); | ||||
|             throw exception(TASK_SIGN_CREATE_TYPE_ERROR, | ||||
|                     BpmTaskSignTypeEnum.nameOfType(taskEntity.getScopeType()), BpmTaskSignTypeEnum.nameOfType(reqVO.getType())); | ||||
|         } | ||||
|  | ||||
|         // 同一个 key 的任务,审批人不重复 | ||||
|         List<Task> taskList = taskService.createTaskQuery().processInstanceId(taskEntity.getProcessInstanceId()) | ||||
|                 .taskDefinitionKey(taskEntity.getTaskDefinitionKey()).list(); | ||||
|         List<Long> currentAssigneeList = convertList(taskList, task -> NumberUtils.parseLong(task.getAssignee())); | ||||
|         // 保留交集在 currentAssigneeList 中 | ||||
|         currentAssigneeList.retainAll(reqVO.getUserIdList()); | ||||
|         if (CollUtil.isNotEmpty(currentAssigneeList)) { | ||||
|             List<AdminUserRespDTO> userList = adminUserApi.getUserList(currentAssigneeList); | ||||
|             throw exception(TASK_ADD_SIGN_USER_REPEAT, String.join(",", convertList(userList, AdminUserRespDTO::getNickname))); | ||||
|         List<Long> currentAssigneeList = convertListByFlatMap(taskList, task -> // 需要考虑 owner 的情况,因为向后加签时,它暂时没 assignee 而是 owner | ||||
|                 Stream.of(NumberUtils.parseLong(task.getAssignee()), NumberUtils.parseLong(task.getOwner()))); | ||||
|         if (CollUtil.containsAny(currentAssigneeList, reqVO.getUserIds())) { | ||||
|             List<AdminUserRespDTO> userList = adminUserApi.getUserList( CollUtil.intersection(currentAssigneeList, reqVO.getUserIds())); | ||||
|             throw exception(TASK_SIGN_CREATE_USER_REPEAT, String.join(",", convertList(userList, AdminUserRespDTO::getNickname))); | ||||
|         } | ||||
|         return taskEntity; | ||||
|     } | ||||
| @@ -653,15 +636,15 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||||
|     /** | ||||
|      * 创建加签子任务 | ||||
|      * | ||||
|      * @param addSingUserIdList 被加签的用户 ID | ||||
|      * @param userIds 被加签的用户 ID | ||||
|      * @param taskEntity        被加签的任务 | ||||
|      */ | ||||
|     private void createSignTask(List<String> addSingUserIdList, TaskEntityImpl taskEntity) { | ||||
|         if (CollUtil.isEmpty(addSingUserIdList)) { | ||||
|     private void createSignTaskList(List<String> userIds, TaskEntityImpl taskEntity) { | ||||
|         if (CollUtil.isEmpty(userIds)) { | ||||
|             return; | ||||
|         } | ||||
|         // 创建加签人的新任务,全部基于 taskEntity 为父任务来创建 | ||||
|         for (String addSignId : addSingUserIdList) { | ||||
|         for (String addSignId : userIds) { | ||||
|             if (StrUtil.isBlank(addSignId)) { | ||||
|                 continue; | ||||
|             } | ||||
| @@ -678,31 +661,29 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||||
|     private void createSignTask(TaskEntityImpl parentTask, String assignee) { | ||||
|         // 1. 生成子任务 | ||||
|         TaskEntityImpl task = (TaskEntityImpl) taskService.newTask(IdUtil.fastSimpleUUID()); | ||||
|         task = BpmTaskConvert.INSTANCE.convert(task, parentTask); | ||||
|         if (BpmTaskAddSignTypeEnum.BEFORE.getType().equals(parentTask.getScopeType())) { | ||||
|             // 2.1 前加签,设置审批人 | ||||
|         BpmTaskConvert.INSTANCE.copyTo(parentTask, task); | ||||
|  | ||||
|         // 2.1 向前加签,设置审批人 | ||||
|         if (BpmTaskSignTypeEnum.BEFORE.getType().equals(parentTask.getScopeType())) { | ||||
|             task.setAssignee(assignee); | ||||
|         // 2.2 向后加签,设置 owner 不设置 assignee 是因为不能同时审批,需要等父任务完成 | ||||
|         } else { | ||||
|             // 2.2.1 设置 owner 不设置 assignee 是因为不能同时审批,需要等父任务完成 | ||||
|             task.setOwner(assignee); | ||||
|             // 2.2.2 设置向后加签任务的 scopeType 为 afterChildrenTask,用于设置任务扩展表的状态 | ||||
| //            task.setScopeType(BpmTaskAddSignTypeEnum.AFTER_CHILDREN_TASK.getType()); | ||||
| //            task.setVariableLocal(BpmConstants.TASK_VARIABLE_STATUS, BpmProcessInstanceResultEnum.WAIT.getResult()); | ||||
|         } | ||||
|         // 2. 保存子任务 | ||||
|         // 2.3 保存子任务 | ||||
|         taskService.saveTask(task); | ||||
|         // 3. TODO | ||||
|         if (BpmTaskAddSignTypeEnum.AFTER.getType().equals(parentTask.getScopeType())) { | ||||
|  | ||||
|         // 3. 向后前签,设置子任务的状态为 WAIT,因为需要等父任务审批完 | ||||
|         if (BpmTaskSignTypeEnum.AFTER.getType().equals(parentTask.getScopeType())) { | ||||
|             updateTaskStatus(task.getId(), BpmTaskStatustEnum.WAIT.getStatus()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     @Transactional(rollbackFor = Exception.class) | ||||
|     public void deleteSignTask(Long userId, BpmTaskSubSignReqVO reqVO) { | ||||
|     public void deleteSignTask(Long userId, BpmTaskSignDeleteReqVO reqVO) { | ||||
|         // 1.1 校验 task 可以被减签 | ||||
| //        Task task = validateSubSign(reqVO.getId()); // TODO 芋艿:这个判断,暂时有点问题!在前置加签的时候 | ||||
|         Task task = validateTaskExist(reqVO.getId()); | ||||
|         Task task = validateTaskCanSignDelete(reqVO.getId()); | ||||
|         // 1.2 校验取消人存在 | ||||
|         AdminUserRespDTO cancelUser = null; | ||||
|         if (StrUtil.isNotBlank(task.getAssignee())) { | ||||
| @@ -713,21 +694,19 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||||
|         } | ||||
|         Assert.notNull(cancelUser, "任务中没有所有者和审批人,数据错误"); | ||||
|  | ||||
|         // 2. 删除任务和对应子任务 | ||||
|         // 2.1 获取所有需要删除的任务 ID ,包含当前任务和所有子任务 | ||||
|         List<String> allTaskIdList = getAllChildTaskIds(task.getId()); | ||||
|         // 2.1 获得子任务列表,包括子任务的子任务 | ||||
|         List<Task> childTaskList = getAllChildTaskList(task); | ||||
|         childTaskList.add(task); | ||||
|         // 2.2 更新子任务为已取消 | ||||
|         String cancelReason = StrUtil.format("任务被取消,原因:由于[{}]操作[减签],", cancelUser.getNickname()); | ||||
|         childTaskList.forEach(childTask -> updateTaskStatusAndReason(childTask.getId(), BpmTaskStatustEnum.CANCEL.getStatus(), cancelReason)); | ||||
|         // 2.2 删除任务和所有子任务 | ||||
|         taskService.deleteTasks(allTaskIdList); | ||||
|         // 2.3 修改扩展表状态为取消 | ||||
| //        taskExtMapper.updateBatchByTaskIdList(allTaskIdList, new BpmTaskExtDO().setResult(BpmProcessInstanceResultEnum.CANCEL.getResult()) | ||||
| //                .setReason(StrUtil.format("由于{}操作[减签],任务被取消", user.getNickname()))); | ||||
| //        allTaskIdList.forEach(taskId -> updateTaskStatus(taskId, BpmProcessInstanceResultEnum.CANCEL.getResult())); // TODO @芋艿:交给取消;考虑到理由,可能不能直接给; | ||||
|         taskService.deleteTasks(convertList(childTaskList, Task::getId)); | ||||
|  | ||||
|         // 3. 记录日志到父任务中。先记录日志是因为,通过 handleParentTask 方法之后,任务可能被完成了,并且不存在了,会报异常,所以先记录 | ||||
|         AdminUserRespDTO user = adminUserApi.getUser(userId); | ||||
|         String comment = StrUtil.format(BpmCommentTypeEnum.SUB_SIGN.getComment(), user.getNickname(), cancelUser.getNickname()); | ||||
|         taskService.addComment(task.getParentTaskId(), task.getProcessInstanceId(), | ||||
|                 BpmCommentTypeEnum.SUB_SIGN.getType().toString(), comment); | ||||
|         taskService.addComment(task.getParentTaskId(), task.getProcessInstanceId(), BpmCommentTypeEnum.SUB_SIGN.getType(), | ||||
|                 StrUtil.format(BpmCommentTypeEnum.SUB_SIGN.getComment(), user.getNickname(), cancelUser.getNickname())); | ||||
|  | ||||
|         // 4. 处理当前任务的父任务 | ||||
|         handleParentTaskIfSign(task.getParentTaskId()); | ||||
| @@ -736,86 +715,72 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||||
|     /** | ||||
|      * 校验任务是否能被减签 | ||||
|      * | ||||
|      * @param id 任务ID | ||||
|      * @param id 任务编号 | ||||
|      * @return 任务信息 | ||||
|      */ | ||||
|     private Task validateSubSign(String id) { | ||||
|     private Task validateTaskCanSignDelete(String id) { | ||||
|         Task task = validateTaskExist(id); | ||||
|  | ||||
|         // 必须有 scopeType | ||||
|         String scopeType = task.getScopeType(); | ||||
|         if (StrUtil.isEmpty(scopeType)) { | ||||
|             throw exception(TASK_SUB_SIGN_NO_PARENT); | ||||
|         if (task.getParentTaskId() == null) { | ||||
|             throw exception(TASK_SIGN_DELETE_NO_PARENT); | ||||
|         } | ||||
|         // 并且值为 向前和向后加签 | ||||
|         if (!validateSignType(scopeType)) { | ||||
|             throw exception(TASK_SUB_SIGN_NO_PARENT); | ||||
|         Task parentTask = getTask(task.getParentTaskId()); | ||||
|         if (parentTask == null) { | ||||
|             throw exception(TASK_SIGN_DELETE_NO_PARENT); | ||||
|         } | ||||
|         if (BpmTaskSignTypeEnum.of(parentTask.getScopeType()) == null) { | ||||
|             throw exception(TASK_SIGN_DELETE_NO_PARENT); | ||||
|         } | ||||
|         return task; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 判断当前类型是否为加签 | ||||
|      * @param scopeType 任务的 scopeType | ||||
|      * @return 当前 scopeType 为加签则返回 true | ||||
|      */ | ||||
|     private boolean validateSignType(String scopeType){ | ||||
|         return StrUtil.equalsAny(scopeType,BpmTaskAddSignTypeEnum.BEFORE.getType(),scopeType, BpmTaskAddSignTypeEnum.AFTER.getType()); | ||||
|     } | ||||
|  | ||||
| //    TODO @海:BpmProcessInstanceResultEnum.CAN_SUB_SIGN_STATUS_LIST) 应该作为条件,mapper 不要有业务 | ||||
|     /** | ||||
|      * 获取所有要被取消的删除的任务 ID 集合 | ||||
|      * 获得所有子任务列表 | ||||
|      * | ||||
|      * @param parentTaskId 父级任务ID | ||||
|      * @return 所有任务ID | ||||
|      * @param parentTask 父任务 | ||||
|      * @return 所有子任务列表 | ||||
|      */ | ||||
|     public List<String> getAllChildTaskIds(String parentTaskId) { | ||||
|         List<String> allChildTaskIds = new ArrayList<>(); | ||||
|     private List<Task> getAllChildTaskList(Task parentTask) { | ||||
|         List<Task> result = new ArrayList<>(); | ||||
|         // 1. 递归获取子级 | ||||
|         Stack<String> stack = new Stack<>(); | ||||
|         // 1.1 将根任务ID入栈 | ||||
|         stack.push(parentTaskId); | ||||
|         //控制遍历的次数不超过 Byte.MAX_VALUE,避免脏数据造成死循环 | ||||
|         int count = 0; | ||||
|         // TODO @海:< 的前后空格,要注意哈; | ||||
|         while (!stack.isEmpty() && count<Byte.MAX_VALUE) { | ||||
|             // 1.2 弹出栈顶任务ID | ||||
|             String taskId = stack.pop(); | ||||
|             // 1.3 将任务ID添加到结果集合中 | ||||
|             allChildTaskIds.add(taskId); | ||||
|             // 1.4 获取该任务的子任务列表 | ||||
|             // TODO @海:有个更高效的写法;一次性去 in 一层;不然每个节点,都去查询一次 db, 太浪费了;每次 in,最终就是 O(h) 查询,而不是 O(n) 查询; | ||||
|             List<String> childrenTaskIdList = getChildrenTaskIdList(taskId); | ||||
|             if (CollUtil.isNotEmpty(childrenTaskIdList)) { | ||||
|                 for (String childTaskId : childrenTaskIdList) { | ||||
|                     // 1.5 将子任务ID入栈,以便后续处理 | ||||
|                     stack.push(childTaskId); | ||||
|                 } | ||||
|         Stack<Task> stack = new Stack<>(); | ||||
|         stack.push(parentTask); | ||||
|         // 2. 递归遍历 | ||||
|         for (int i = 0; i < Short.MAX_VALUE; i++) { | ||||
|             if (stack.isEmpty()) { | ||||
|                 break; | ||||
|             } | ||||
|             // 2.1 获取子任务们 | ||||
|             Task task = stack.pop(); | ||||
|             List<Task> childTaskList = getTaskListByParentTaskId(task.getId()); | ||||
|             // 2.2 如果非空,则添加到 stack 进一步递归 | ||||
|             if (CollUtil.isNotEmpty(childTaskList)) { | ||||
|                 stack.addAll(childTaskList); | ||||
|                 result.addAll(childTaskList); | ||||
|             } | ||||
|             count++; | ||||
|         } | ||||
|         return allChildTaskIds; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取指定父级任务的所有子任务 ID 集合 | ||||
|      * | ||||
|      * @param parentTaskId 父任务 ID | ||||
|      * @return 所有子任务的 ID 集合 | ||||
|      */ | ||||
|     private List<String> getChildrenTaskIdList(String parentTaskId) { | ||||
|         return convertList(getTaskListByParentTaskId(parentTaskId), Task::getId); | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     @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}"; | ||||
|         String sql = "select ID_,NAME_,OWNER_,ASSIGNEE_ from " + tableName + " where PARENT_TASK_ID_=#{parentTaskId}"; | ||||
|         return taskService.createNativeTaskQuery().sql(sql).parameter("parentTaskId", parentTaskId).list(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取子任务个数 | ||||
|      * | ||||
|      * @param parentTaskId 父任务 ID | ||||
|      * @return 剩余子任务个数 | ||||
|      */ | ||||
|     private Long getTaskCountByParentTaskId(String parentTaskId) { | ||||
|         String tableName = managementService.getTableName(TaskEntity.class); | ||||
|         String sql = "SELECT COUNT(1) from " + tableName + " WHERE PARENT_TASK_ID_=#{parentTaskId}"; | ||||
|         return taskService.createNativeTaskQuery().sql(sql).parameter("parentTaskId", parentTaskId).count(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Map<String, String> getTaskNameByTaskIds(Collection<String> taskIds) { | ||||
|         if (CollUtil.isEmpty(taskIds)) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV