mirror of
				https://github.com/YunaiV/ruoyi-vue-pro.git
				synced 2025-10-31 10:37:41 +08:00 
			
		
		
		
	Merge remote-tracking branch 'origin/feature/bpm' into feature/bpm
This commit is contained in:
		| @ -156,7 +156,7 @@ | |||||||
| | 🚀  | 用户分组  | 自定义用户分组,可用于工作流的审批分组                    | | | 🚀  | 用户分组  | 自定义用户分组,可用于工作流的审批分组                    | | ||||||
| | 🚀  | 我的流程  | 查看我发起的工作流程,支持新建、取消流程等操作,高亮流程图、审批时间线    | | | 🚀  | 我的流程  | 查看我发起的工作流程,支持新建、取消流程等操作,高亮流程图、审批时间线    | | ||||||
| | 🚀  | 待办任务  | 查看自己【未】审批的工作任务,支持通过、不通过、转发、委派、退回等操作    | | | 🚀  | 待办任务  | 查看自己【未】审批的工作任务,支持通过、不通过、转发、委派、退回等操作    | | ||||||
| | 🚀  | 已办任务  | 查看自己【已】审批的工作任务,未来会支持回退操作               | | | 🚀  | 已办任务  | 查看自己【已】审批的工作任务,未来会支持退回操作               | | ||||||
| | 🚀  | OA 请假 | 作为业务自定义接入工作流的使用示例,只需创建请求对应的工作流程,即可进行审批 | | | 🚀  | OA 请假 | 作为业务自定义接入工作流的使用示例,只需创建请求对应的工作流程,即可进行审批 | | ||||||
|  |  | ||||||
|  |  | ||||||
|  | |||||||
| @ -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.convert.task.BpmTaskConvert; | ||||||
| import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; | 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.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.BpmProcessInstanceService; | ||||||
| import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService; | 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.DeptApi; | ||||||
| @ -20,7 +19,6 @@ import io.swagger.v3.oas.annotations.Parameter; | |||||||
| import io.swagger.v3.oas.annotations.tags.Tag; | import io.swagger.v3.oas.annotations.tags.Tag; | ||||||
| import jakarta.annotation.Resource; | import jakarta.annotation.Resource; | ||||||
| import jakarta.validation.Valid; | import jakarta.validation.Valid; | ||||||
| import org.flowable.bpmn.model.BpmnModel; |  | ||||||
| import org.flowable.bpmn.model.UserTask; | import org.flowable.bpmn.model.UserTask; | ||||||
| import org.flowable.engine.history.HistoricProcessInstance; | import org.flowable.engine.history.HistoricProcessInstance; | ||||||
| import org.flowable.engine.runtime.ProcessInstance; | 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.validation.annotation.Validated; | ||||||
| import org.springframework.web.bind.annotation.*; | 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 java.util.stream.Stream; | ||||||
|  |  | ||||||
| import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||||||
| @ -49,8 +50,6 @@ public class BpmTaskController { | |||||||
|     private BpmProcessInstanceService processInstanceService; |     private BpmProcessInstanceService processInstanceService; | ||||||
|     @Resource |     @Resource | ||||||
|     private BpmFormService formService; |     private BpmFormService formService; | ||||||
|     @Resource |  | ||||||
|     private BpmProcessDefinitionService bpmProcessDefinitionService; |  | ||||||
|  |  | ||||||
|     @Resource |     @Resource | ||||||
|     private AdminUserApi adminUserApi; |     private AdminUserApi adminUserApi; | ||||||
| @ -135,10 +134,8 @@ public class BpmTaskController { | |||||||
|         // 获得 Form Map |         // 获得 Form Map | ||||||
|         Map<Long, BpmFormDO> formMap = formService.getFormMap( |         Map<Long, BpmFormDO> formMap = formService.getFormMap( | ||||||
|                 convertSet(taskList, task -> NumberUtils.parseLong(task.getFormKey()))); |                 convertSet(taskList, task -> NumberUtils.parseLong(task.getFormKey()))); | ||||||
|         // 获得 BpmnModel |  | ||||||
|         BpmnModel bpmnModel = bpmProcessDefinitionService.getProcessDefinitionBpmnModel(processInstance.getProcessDefinitionId()); |  | ||||||
|         return success(BpmTaskConvert.INSTANCE.buildTaskListByProcessInstanceId(taskList, processInstance, |         return success(BpmTaskConvert.INSTANCE.buildTaskListByProcessInstanceId(taskList, processInstance, | ||||||
|                 formMap, userMap, deptMap, bpmnModel)); |                 formMap, userMap, deptMap)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @PutMapping("/approve") |     @PutMapping("/approve") | ||||||
|  | |||||||
| @ -2,7 +2,6 @@ package cn.iocoder.yudao.module.bpm.convert.task; | |||||||
|  |  | ||||||
| import cn.hutool.core.collection.CollUtil; | import cn.hutool.core.collection.CollUtil; | ||||||
| import cn.hutool.core.map.MapUtil; | 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.pojo.PageResult; | ||||||
| import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | 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.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.instance.BpmProcessInstanceRespVO; | ||||||
| import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO; | 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.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.framework.flowable.core.util.FlowableUtils; | ||||||
| import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO; | 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.dept.dto.DeptRespDTO; | ||||||
| import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | 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.history.HistoricProcessInstance; | ||||||
| import org.flowable.engine.runtime.ProcessInstance; | import org.flowable.engine.runtime.ProcessInstance; | ||||||
| import org.flowable.task.api.Task; | import org.flowable.task.api.Task; | ||||||
| @ -29,7 +25,7 @@ import java.util.Date; | |||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Map; | 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; | import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @ -85,9 +81,8 @@ public interface BpmTaskConvert { | |||||||
|                                                                  HistoricProcessInstance processInstance, |                                                                  HistoricProcessInstance processInstance, | ||||||
|                                                                  Map<Long, BpmFormDO> formMap, |                                                                  Map<Long, BpmFormDO> formMap, | ||||||
|                                                                  Map<Long, AdminUserRespDTO> userMap, |                                                                  Map<Long, AdminUserRespDTO> userMap, | ||||||
|                                                                  Map<Long, DeptRespDTO> deptMap, |                                                                  Map<Long, DeptRespDTO> deptMap) { | ||||||
|                                                                  BpmnModel bpmnModel) { |         return CollectionUtils.convertList(taskList, task -> { | ||||||
|         List<BpmTaskRespVO> taskVOList = CollectionUtils.convertList(taskList, task -> { |  | ||||||
|             BpmTaskRespVO taskVO = BeanUtils.toBean(task, BpmTaskRespVO.class); |             BpmTaskRespVO taskVO = BeanUtils.toBean(task, BpmTaskRespVO.class); | ||||||
|             Integer taskStatus = FlowableUtils.getTaskStatus(task); |             Integer taskStatus = FlowableUtils.getTaskStatus(task); | ||||||
|             taskVO.setStatus(taskStatus).setReason(FlowableUtils.getTaskReason(task)); |             taskVO.setStatus(taskStatus).setReason(FlowableUtils.getTaskReason(task)); | ||||||
| @ -104,21 +99,8 @@ public interface BpmTaskConvert { | |||||||
|             // 用户信息 |             // 用户信息 | ||||||
|             buildTaskAssignee(taskVO, task.getAssignee(), userMap, deptMap); |             buildTaskAssignee(taskVO, task.getAssignee(), userMap, deptMap); | ||||||
|             buildTaskOwner(taskVO, task.getOwner(), userMap, deptMap); |             buildTaskOwner(taskVO, task.getOwner(), userMap, deptMap); | ||||||
|             if (BpmTaskStatusEnum.RUNNING.getStatus().equals(taskStatus)) { |  | ||||||
|                 // 操作按钮设置 |  | ||||||
|                 taskVO.setButtonsSetting(BpmnModelUtils.parseButtonsSetting(bpmnModel, task.getTaskDefinitionKey())); |  | ||||||
|             } |  | ||||||
|             return taskVO; |             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 filterList(taskVOList, r -> StrUtil.isEmpty(r.getParentTaskId())); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     default List<BpmTaskRespVO> buildTaskListByParentTaskId(List<Task> taskList, |     default List<BpmTaskRespVO> buildTaskListByParentTaskId(List<Task> taskList, | ||||||
|  | |||||||
| @ -156,9 +156,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | |||||||
|         BpmnModel bpmnModel = bpmProcessDefinitionService.getProcessDefinitionBpmnModel(processInstance.getProcessDefinitionId()); |         BpmnModel bpmnModel = bpmProcessDefinitionService.getProcessDefinitionBpmnModel(processInstance.getProcessDefinitionId()); | ||||||
|         List<BpmTaskRespVO> taskList = convertList(todoList, task -> { |         List<BpmTaskRespVO> taskList = convertList(todoList, task -> { | ||||||
|             // 找到分配给当前用户,或者当前用户加签的任务(为了减签) |             // 找到分配给当前用户,或者当前用户加签的任务(为了减签) | ||||||
|             //  TODO 3)(!userId.equals(NumberUtil.parseLong(task.getOwner(), null)) || BpmTaskSignTypeEnum.of(task.getScopeType()) == null) 这个判断的目的是啥? |             if (!isAssignUserTask(userId, task) && !isAddSignUserTask(userId, task)) { | ||||||
|             // @芋艿 !isAddSignTask(userId, task) 该判断的目的被用户加签的任务。该用户可以进行减签操作 |  | ||||||
|             if (!isAssignUserTask(userId, task) && !isAddSignTask(userId, task)) { |  | ||||||
|                 return null; |                 return null; | ||||||
|             } |             } | ||||||
|             BpmTaskRespVO taskVO = BeanUtils.toBean(task, BpmTaskRespVO.class); |             BpmTaskRespVO taskVO = BeanUtils.toBean(task, BpmTaskRespVO.class); | ||||||
| @ -166,9 +164,10 @@ public class BpmTaskServiceImpl implements BpmTaskService { | |||||||
|             taskVO.setButtonsSetting(BpmnModelUtils.parseButtonsSetting(bpmnModel, task.getTaskDefinitionKey())); |             taskVO.setButtonsSetting(BpmnModelUtils.parseButtonsSetting(bpmnModel, task.getTaskDefinitionKey())); | ||||||
|             BpmTaskConvert.INSTANCE.buildTaskOwner(taskVO, task.getOwner(), userMap, deptMap); |             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); |                 BpmTaskConvert.INSTANCE.buildTaskChildren(taskVO, childrenTaskMap, userMap, deptMap); | ||||||
|  |  | ||||||
|             } |             } | ||||||
|             return taskVO; |             return taskVO; | ||||||
|         }); |         }); | ||||||
| @ -176,16 +175,24 @@ public class BpmTaskServiceImpl implements BpmTaskService { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 判断是否为被分配给用户的任务 |      * 判断指定用户,是否是当前任务的分配人 | ||||||
|  |      * | ||||||
|  |      * @param userId 用户编号 | ||||||
|  |      * @param task 任务 | ||||||
|  |      * @return 是否 | ||||||
|      */ |      */ | ||||||
|     private boolean isAssignUserTask(Long userId, Task task) { |     private boolean isAssignUserTask(Long userId, Task task) { | ||||||
|         return ObjectUtil.equal(userId, NumberUtil.parseLong(task.getAssignee(), null)); |         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)) |         return userId.equals(NumberUtil.parseLong(task.getOwner(), null)) | ||||||
|                 && BpmTaskSignTypeEnum.of(task.getScopeType()) != null; |                 && BpmTaskSignTypeEnum.of(task.getScopeType()) != null; | ||||||
|     } |     } | ||||||
| @ -994,8 +1001,13 @@ public class BpmTaskServiceImpl implements BpmTaskService { | |||||||
|                 if (ObjectUtil.notEqual(transactionStatus, TransactionSynchronization.STATUS_COMMITTED)) { |                 if (ObjectUtil.notEqual(transactionStatus, TransactionSynchronization.STATUS_COMMITTED)) { | ||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
|  |                 // TODO 芋艿:可以后续优化成 getSelf(); | ||||||
|                 // 特殊情况一:【人工审核】审批人为空,根据配置是否要自动通过、自动拒绝 |                 // 特殊情况一:【人工审核】审批人为空,根据配置是否要自动通过、自动拒绝 | ||||||
|                 if (ObjectUtil.equal(approveType, BpmUserTaskApproveTypeEnum.USER.getType())) { |                 if (ObjectUtil.equal(approveType, BpmUserTaskApproveTypeEnum.USER.getType())) { | ||||||
|  |                     // 如果有审批人、或者拥有人,则说明不满足情况一,不自动通过、不自动拒绝 | ||||||
|  |                     if (!ObjectUtil.isAllEmpty(task.getAssignee(), task.getOwner())) { | ||||||
|  |                         return; | ||||||
|  |                     } | ||||||
|                     if (ObjectUtil.equal(assignEmptyHandlerType, BpmUserTaskAssignEmptyHandlerTypeEnum.APPROVE.getType())) { |                     if (ObjectUtil.equal(assignEmptyHandlerType, BpmUserTaskAssignEmptyHandlerTypeEnum.APPROVE.getType())) { | ||||||
|                         SpringUtil.getBean(BpmTaskService.class).approveTask(null, new BpmTaskApproveReqVO() |                         SpringUtil.getBean(BpmTaskService.class).approveTask(null, new BpmTaskApproveReqVO() | ||||||
|                                 .setId(task.getId()).setReason(BpmReasonEnum.ASSIGN_EMPTY_APPROVE.getReason())); |                                 .setId(task.getId()).setReason(BpmReasonEnum.ASSIGN_EMPTY_APPROVE.getReason())); | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 jason
					jason