diff --git a/README.md b/README.md index 7e6f766f3..522cfb6f7 100644 --- a/README.md +++ b/README.md @@ -156,7 +156,7 @@ | 🚀 | 用户分组 | 自定义用户分组,可用于工作流的审批分组 | | 🚀 | 我的流程 | 查看我发起的工作流程,支持新建、取消流程等操作,高亮流程图、审批时间线 | | 🚀 | 待办任务 | 查看自己【未】审批的工作任务,支持通过、不通过、转发、委派、退回等操作 | -| 🚀 | 已办任务 | 查看自己【已】审批的工作任务,未来会支持回退操作 | +| 🚀 | 已办任务 | 查看自己【已】审批的工作任务,未来会支持退回操作 | | 🚀 | OA 请假 | 作为业务自定义接入工作流的使用示例,只需创建请求对应的工作流程,即可进行审批 | ![功能图](/.image/common/bpm-feature.png) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java index 9661923ee..bd24fac2e 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java @@ -8,7 +8,6 @@ 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.dataobject.definition.BpmFormDO; import cn.iocoder.yudao.module.bpm.service.definition.BpmFormService; -import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; 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; @@ -20,7 +19,6 @@ 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.BpmnModel; import org.flowable.bpmn.model.UserTask; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.runtime.ProcessInstance; @@ -30,7 +28,10 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import java.util.*; +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; @@ -49,8 +50,6 @@ public class BpmTaskController { private BpmProcessInstanceService processInstanceService; @Resource private BpmFormService formService; - @Resource - private BpmProcessDefinitionService bpmProcessDefinitionService; @Resource private AdminUserApi adminUserApi; @@ -135,10 +134,8 @@ public class BpmTaskController { // 获得 Form Map Map formMap = formService.getFormMap( convertSet(taskList, task -> NumberUtils.parseLong(task.getFormKey()))); - // 获得 BpmnModel - BpmnModel bpmnModel = bpmProcessDefinitionService.getProcessDefinitionBpmnModel(processInstance.getProcessDefinitionId()); return success(BpmTaskConvert.INSTANCE.buildTaskListByProcessInstanceId(taskList, processInstance, - formMap, userMap, deptMap, bpmnModel)); + formMap, userMap, deptMap)); } @PutMapping("/approve") diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java index 2665bb0b9..09f38c1a3 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.bpm.convert.task; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.map.MapUtil; -import cn.hutool.core.util.StrUtil; 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; @@ -10,13 +9,10 @@ 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.BpmTaskRespVO; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; -import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum; -import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils; import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; -import org.flowable.bpmn.model.BpmnModel; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.task.api.Task; @@ -29,7 +25,7 @@ import java.util.Date; import java.util.List; import java.util.Map; -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.MapUtils.findAndThen; /** @@ -85,9 +81,8 @@ public interface BpmTaskConvert { HistoricProcessInstance processInstance, Map formMap, Map userMap, - Map deptMap, - BpmnModel bpmnModel) { - List taskVOList = CollectionUtils.convertList(taskList, task -> { + Map deptMap) { + return CollectionUtils.convertList(taskList, task -> { BpmTaskRespVO taskVO = BeanUtils.toBean(task, BpmTaskRespVO.class); Integer taskStatus = FlowableUtils.getTaskStatus(task); taskVO.setStatus(taskStatus).setReason(FlowableUtils.getTaskReason(task)); @@ -104,21 +99,8 @@ public interface BpmTaskConvert { // 用户信息 buildTaskAssignee(taskVO, task.getAssignee(), userMap, deptMap); buildTaskOwner(taskVO, task.getOwner(), userMap, deptMap); - if (BpmTaskStatusEnum.RUNNING.getStatus().equals(taskStatus)) { - // 操作按钮设置 - taskVO.setButtonsSetting(BpmnModelUtils.parseButtonsSetting(bpmnModel, task.getTaskDefinitionKey())); - } return taskVO; }); - - // 拼接父子关系 - Map> childrenTaskMap = convertMultiMap( - filterList(taskVOList, r -> StrUtil.isNotEmpty(r.getParentTaskId())), - BpmTaskRespVO::getParentTaskId); - for (BpmTaskRespVO taskVO : taskVOList) { - taskVO.setChildren(childrenTaskMap.get(taskVO.getId())); - } - return filterList(taskVOList, r -> StrUtil.isEmpty(r.getParentTaskId())); } default List buildTaskListByParentTaskId(List taskList, diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index b073be39e..29281932d 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -156,9 +156,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { BpmnModel bpmnModel = bpmProcessDefinitionService.getProcessDefinitionBpmnModel(processInstance.getProcessDefinitionId()); List taskList = convertList(todoList, task -> { // 找到分配给当前用户,或者当前用户加签的任务(为了减签) - // TODO 3)(!userId.equals(NumberUtil.parseLong(task.getOwner(), null)) || BpmTaskSignTypeEnum.of(task.getScopeType()) == null) 这个判断的目的是啥? - // @芋艿 !isAddSignTask(userId, task) 该判断的目的被用户加签的任务。该用户可以进行减签操作 - if (!isAssignUserTask(userId, task) && !isAddSignTask(userId, task)) { + if (!isAssignUserTask(userId, task) && !isAddSignUserTask(userId, task)) { return null; } BpmTaskRespVO taskVO = BeanUtils.toBean(task, BpmTaskRespVO.class); @@ -166,9 +164,10 @@ public class BpmTaskServiceImpl implements BpmTaskService { taskVO.setButtonsSetting(BpmnModelUtils.parseButtonsSetting(bpmnModel, task.getTaskDefinitionKey())); BpmTaskConvert.INSTANCE.buildTaskOwner(taskVO, task.getOwner(), userMap, deptMap); // 如果是被加签的任务. 找到它的子任务 (为了减签) - if (isAddSignTask(userId, task)) { + // TODO @jason:如果是向后加签,这个判断有问题哈。因为向后加签后,当前任务,assignee 还是没变。可以简单点,直接拿子任务哈。另外,需要考虑子任务的子任务。 + if (isAddSignUserTask(userId, task)) { + // TODO @jason:这里其实可以考虑,在 157 到 173 把所有需要的数据都拿到,然后交给 BpmTaskConvert.INSTANCE 转换出 taskVO。这样,service 只保留一些逻辑性强的东西,类似 status、buttonsetting,都拿到 convert 里去。 BpmTaskConvert.INSTANCE.buildTaskChildren(taskVO, childrenTaskMap, userMap, deptMap); - } return taskVO; }); @@ -176,16 +175,24 @@ public class BpmTaskServiceImpl implements BpmTaskService { } /** - * 判断是否为被分配给用户的任务 + * 判断指定用户,是否是当前任务的分配人 + * + * @param userId 用户编号 + * @param task 任务 + * @return 是否 */ private boolean isAssignUserTask(Long userId, Task task) { return ObjectUtil.equal(userId, NumberUtil.parseLong(task.getAssignee(), null)); } /** - * 判断是否为被用户加签的任务 + * 判断指定用户,是否是当前任务的加签人 + * + * @param userId 用户编号 + * @param task 任务 + * @return 是否 */ - private boolean isAddSignTask(Long userId, Task task) { + private boolean isAddSignUserTask(Long userId, Task task) { return userId.equals(NumberUtil.parseLong(task.getOwner(), null)) && BpmTaskSignTypeEnum.of(task.getScopeType()) != null; } @@ -994,8 +1001,13 @@ public class BpmTaskServiceImpl implements BpmTaskService { if (ObjectUtil.notEqual(transactionStatus, TransactionSynchronization.STATUS_COMMITTED)) { return; } + // TODO 芋艿:可以后续优化成 getSelf(); // 特殊情况一:【人工审核】审批人为空,根据配置是否要自动通过、自动拒绝 if (ObjectUtil.equal(approveType, BpmUserTaskApproveTypeEnum.USER.getType())) { + // 如果有审批人、或者拥有人,则说明不满足情况一,不自动通过、不自动拒绝 + if (!ObjectUtil.isAllEmpty(task.getAssignee(), task.getOwner())) { + return; + } if (ObjectUtil.equal(assignEmptyHandlerType, BpmUserTaskAssignEmptyHandlerTypeEnum.APPROVE.getType())) { SpringUtil.getBean(BpmTaskService.class).approveTask(null, new BpmTaskApproveReqVO() .setId(task.getId()).setReason(BpmReasonEnum.ASSIGN_EMPTY_APPROVE.getReason()));