Commit 0a2599152d33aa965eeacb2e80b5d6f24dcdc950
1 parent
ed28d6d5
暂时回退流程推断的能力
Showing
12 changed files
with
38 additions
and
579 deletions
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmActivityConvert.java
| 1 | package cn.iocoder.yudao.module.bpm.convert.task; | 1 | package cn.iocoder.yudao.module.bpm.convert.task; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.activity.BpmActivityRespVO; | 3 | import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.activity.BpmActivityRespVO; |
| 4 | -import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmActivityDO; | ||
| 5 | import org.flowable.engine.history.HistoricActivityInstance; | 4 | import org.flowable.engine.history.HistoricActivityInstance; |
| 6 | import org.mapstruct.Mapper; | 5 | import org.mapstruct.Mapper; |
| 7 | import org.mapstruct.Mapping; | 6 | import org.mapstruct.Mapping; |
| @@ -20,11 +19,11 @@ public interface BpmActivityConvert { | @@ -20,11 +19,11 @@ public interface BpmActivityConvert { | ||
| 20 | 19 | ||
| 21 | BpmActivityConvert INSTANCE = Mappers.getMapper(BpmActivityConvert.class); | 20 | BpmActivityConvert INSTANCE = Mappers.getMapper(BpmActivityConvert.class); |
| 22 | 21 | ||
| 23 | - List<BpmActivityRespVO> convertList(List<BpmActivityDO> list); | 22 | + List<BpmActivityRespVO> convertList(List<HistoricActivityInstance> list); |
| 24 | 23 | ||
| 25 | @Mappings({ | 24 | @Mappings({ |
| 26 | @Mapping(source = "activityId", target = "key"), | 25 | @Mapping(source = "activityId", target = "key"), |
| 27 | @Mapping(source = "activityType", target = "type") | 26 | @Mapping(source = "activityType", target = "type") |
| 28 | }) | 27 | }) |
| 29 | - BpmActivityRespVO convert(BpmActivityDO bean); | 28 | + BpmActivityRespVO convert(HistoricActivityInstance bean); |
| 30 | } | 29 | } |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/task/BpmActivityMapper.java
| @@ -7,20 +7,9 @@ import org.apache.ibatis.annotations.Param; | @@ -7,20 +7,9 @@ import org.apache.ibatis.annotations.Param; | ||
| 7 | 7 | ||
| 8 | import java.util.List; | 8 | import java.util.List; |
| 9 | 9 | ||
| 10 | -/** | ||
| 11 | - * @author kemengkai | ||
| 12 | - * @create 2022-05-09 09:26 TODO @ke:@date 哈。ps:一般这种类,可以不用谢类注释和方法注释。因为是 dao 是通用操作,所以都是通过方法名,可以指导它的用途 | ||
| 13 | - */ | ||
| 14 | @Mapper | 10 | @Mapper |
| 15 | public interface BpmActivityMapper extends BaseMapperX<BpmActivityDO> { | 11 | public interface BpmActivityMapper extends BaseMapperX<BpmActivityDO> { |
| 16 | 12 | ||
| 17 | - // TODO @ke:这个方法,是不是暂时用不到呀。如果是的话,可以删除哈 | ||
| 18 | - /** | ||
| 19 | - * 获取所有历史任务 | ||
| 20 | - * | ||
| 21 | - * @return 返回历史任务 | ||
| 22 | - */ | ||
| 23 | - List<BpmActivityDO> listAll(); | ||
| 24 | 13 | ||
| 25 | // TODO @ke:可以试试,把 activiti 的表,映射成对应的实体,然后读取下。我们尽量避免 xml 操作,因为要做多 db 类型的支持,例如说 oracle 等。通过 mybatis plus 帮助我们生成不同数据库的表操作 | 14 | // TODO @ke:可以试试,把 activiti 的表,映射成对应的实体,然后读取下。我们尽量避免 xml 操作,因为要做多 db 类型的支持,例如说 oracle 等。通过 mybatis plus 帮助我们生成不同数据库的表操作 |
| 26 | /** | 15 | /** |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/domain/vo/ApproveProcInstVO.java deleted
| 1 | -package cn.iocoder.yudao.module.bpm.domain.vo; | ||
| 2 | - | ||
| 3 | -import io.swagger.annotations.ApiModelProperty; | ||
| 4 | -import lombok.AllArgsConstructor; | ||
| 5 | -import lombok.Data; | ||
| 6 | -import lombok.NoArgsConstructor; | ||
| 7 | - | ||
| 8 | -import java.time.LocalDate; | ||
| 9 | - | ||
| 10 | -/** | ||
| 11 | - * 审批流程VO | ||
| 12 | - * | ||
| 13 | - * @author kemengkai | ||
| 14 | - */ | ||
| 15 | -@Data | ||
| 16 | -@AllArgsConstructor | ||
| 17 | -@NoArgsConstructor | ||
| 18 | -// TODO @ke:这个类是不是没用呀 | ||
| 19 | -public class ApproveProcInstVO { | ||
| 20 | - | ||
| 21 | - @ApiModelProperty("任务id") | ||
| 22 | - private String id; | ||
| 23 | - @ApiModelProperty("任务部署key") | ||
| 24 | - private String taskDefKey; | ||
| 25 | - @ApiModelProperty("任务名称") | ||
| 26 | - private String name; | ||
| 27 | - @ApiModelProperty("审批人登录名") | ||
| 28 | - private String assignee; | ||
| 29 | - @ApiModelProperty("审批人姓名") | ||
| 30 | - private String assigneeName; | ||
| 31 | - @ApiModelProperty("审批回复") | ||
| 32 | - private String taskComment; | ||
| 33 | - @ApiModelProperty("审批完成时间") | ||
| 34 | - private LocalDate endTime; | ||
| 35 | -} |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmActivityServiceImpl.java
| 1 | package cn.iocoder.yudao.module.bpm.service.task; | 1 | package cn.iocoder.yudao.module.bpm.service.task; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; | ||
| 4 | import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.activity.BpmActivityRespVO; | 3 | import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.activity.BpmActivityRespVO; |
| 5 | import cn.iocoder.yudao.module.bpm.convert.task.BpmActivityConvert; | 4 | import cn.iocoder.yudao.module.bpm.convert.task.BpmActivityConvert; |
| 6 | -import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmActivityDO; | ||
| 7 | import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmActivityMapper; | 5 | import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmActivityMapper; |
| 8 | import lombok.extern.slf4j.Slf4j; | 6 | import lombok.extern.slf4j.Slf4j; |
| 9 | - | ||
| 10 | import org.flowable.engine.HistoryService; | 7 | import org.flowable.engine.HistoryService; |
| 11 | import org.flowable.engine.history.HistoricActivityInstance; | 8 | import org.flowable.engine.history.HistoricActivityInstance; |
| 12 | import org.springframework.stereotype.Service; | 9 | import org.springframework.stereotype.Service; |
| @@ -32,13 +29,10 @@ public class BpmActivityServiceImpl implements BpmActivityService { | @@ -32,13 +29,10 @@ public class BpmActivityServiceImpl implements BpmActivityService { | ||
| 32 | private BpmActivityMapper bpmActivityMapper; | 29 | private BpmActivityMapper bpmActivityMapper; |
| 33 | 30 | ||
| 34 | @Override | 31 | @Override |
| 35 | - @TenantIgnore | ||
| 36 | - public List<BpmActivityRespVO> getActivityListByProcessInstanceId(String procInstId) { | ||
| 37 | -// List<HistoricActivityInstance> activityList = historyService.createHistoricActivityInstanceQuery() | ||
| 38 | -// .processInstanceId(procInstId).list(); | ||
| 39 | - // TODO @ke:这个是想要过滤掉 aha.act_type_ != 'sequenceFlow' 类型么? | ||
| 40 | - List<BpmActivityDO> bpmActivityDOList = bpmActivityMapper.listAllByProcInstIdAndDelete(procInstId); | ||
| 41 | - return BpmActivityConvert.INSTANCE.convertList(bpmActivityDOList); | 32 | + public List<BpmActivityRespVO> getActivityListByProcessInstanceId(String processInstanceId) { |
| 33 | + List<HistoricActivityInstance> activityList = historyService.createHistoricActivityInstanceQuery() | ||
| 34 | + .processInstanceId(processInstanceId).list(); | ||
| 35 | + return BpmActivityConvert.INSTANCE.convertList(activityList); | ||
| 42 | } | 36 | } |
| 43 | 37 | ||
| 44 | @Override | 38 | @Override |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
| 1 | -package cn.iocoder.yudao.module.bpm.service.task; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum; import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher; import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; 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 lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; import org.flowable.engine.delegate.event.FlowableCancelledEvent; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.task.api.Task; import org.springframework.context.annotation.Lazy; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import javax.validation.Valid; import java.util.*; 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.module.bpm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF; /** * 流程实例 Service 实现类 * * ProcessDefinition & ProcessInstance & Execution & Task 的关系: * 1. <a href="https://blog.csdn.net/bobozai86/article/details/105210414" /> * * HistoricProcessInstance & ProcessInstance 的关系: * 1. <a href=" https://my.oschina.net/843294669/blog/71902" /> * * 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例 * * @author 芋道源码 */ @Service @Validated @Slf4j public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService { @Resource private RuntimeService runtimeService; @Resource private BpmProcessInstanceExtMapper processInstanceExtMapper; @Resource @Lazy // 解决循环依赖 private BpmTaskService taskService; @Resource private BpmProcessDefinitionService processDefinitionService; @Resource private HistoryService historyService; @Resource private AdminUserApi adminUserApi; @Resource private DeptApi deptApi; @Resource private BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher; @Resource private BpmMessageService messageService; @Override public ProcessInstance getProcessInstance(String id) { return runtimeService.createProcessInstanceQuery().processInstanceId(id).singleResult(); } @Override public List<ProcessInstance> getProcessInstances(Set<String> ids) { return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public PageResult<BpmProcessInstancePageItemRespVO> getMyProcessInstancePage(Long userId, BpmProcessInstanceMyPageReqVO pageReqVO) { // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 PageResult<BpmProcessInstanceExtDO> pageResult = processInstanceExtMapper.selectPage(userId, pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { return new PageResult<>(pageResult.getTotal()); } // 获得流程 Task Map List<String> processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId); Map<String, List<Task>> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds); // 转换返回 return BpmProcessInstanceConvert.INSTANCE.convertPage(pageResult, taskMap); } @Override @Transactional(rollbackFor = Exception.class) public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId()); // 发起流程 return createProcessInstance0(userId, definition, createReqVO.getVariables(), null); } @Override public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey()); // 发起流程 return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey()); } @Override public BpmProcessInstanceRespVO getProcessInstanceVO(String id) { // 获得流程实例 HistoricProcessInstance processInstance = getHistoricProcessInstance(id); if (processInstance == null) { return null; } BpmProcessInstanceExtDO processInstanceExt = processInstanceExtMapper.selectByProcessInstanceId(id); Assert.notNull(processInstanceExt, "流程实例拓展({}) 不存在", id); // 获得流程定义 ProcessDefinition processDefinition = processDefinitionService .getProcessDefinition(processInstance.getProcessDefinitionId()); Assert.notNull(processDefinition, "流程定义({}) 不存在", processInstance.getProcessDefinitionId()); BpmProcessDefinitionExtDO processDefinitionExt = processDefinitionService.getProcessDefinitionExt( processInstance.getProcessDefinitionId()); Assert.notNull(processDefinitionExt, "流程定义拓展({}) 不存在", id); String bpmnXml = processDefinitionService.getProcessDefinitionBpmnXML(processInstance.getProcessDefinitionId()); // 获得 User AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId())); DeptRespDTO dept = null; if (startUser != null) { dept = deptApi.getDept(startUser.getDeptId()); } // 拼接结果 return BpmProcessInstanceConvert.INSTANCE.convert2(processInstance, processInstanceExt, processDefinition, processDefinitionExt, bpmnXml, startUser, dept); } @Override public void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) { // 校验流程实例存在 ProcessInstance instance = getProcessInstance(cancelReqVO.getId()); if (instance == null) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS); } // 只能取消自己的 if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF); } // 通过删除流程实例,实现流程实例的取消, // 删除流程实例,正则执行任务 ACT_RU_TASK. 任务会被删除。通过历史表查询 deleteProcessInstance(cancelReqVO.getId(), BpmProcessInstanceDeleteReasonEnum.CANCEL_TASK.format(cancelReqVO.getReason())); } /** * 获得历史的流程实例 * * @param id 流程实例的编号 * @return 历史的流程实例 */ @Override public HistoricProcessInstance getHistoricProcessInstance(String id) { return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult(); } @Override public List<HistoricProcessInstance> getHistoricProcessInstances(Set<String> ids) { return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public void createProcessInstanceExt(ProcessInstance instance) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition2(instance.getProcessDefinitionId()); // 插入 BpmProcessInstanceExtDO 对象 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getId()) .setProcessDefinitionId(definition.getId()) .setName(instance.getProcessDefinitionName()) .setStartUserId(Long.valueOf(instance.getStartUserId())) .setCategory(definition.getCategory()) .setStatus(BpmProcessInstanceStatusEnum.RUNNING.getStatus()) .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()); processInstanceExtMapper.insert(instanceExtDO); } @Override public void updateProcessInstanceExtCancel(FlowableCancelledEvent event) { // 判断是否为 Reject 不通过。如果是,则不进行更新. // 因为,updateProcessInstanceExtReject 方法,已经进行更新了 if (BpmProcessInstanceDeleteReasonEnum.isRejectReason((String)event.getCause())) { return; } // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(event.getProcessInstanceId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(event.getProcessInstanceId()) .setEndTime(new Date()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.CANCEL.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Override public void updateProcessInstanceExtComplete(ProcessInstance instance) { // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getProcessInstanceId()) .setEndTime(new Date()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()); // 如果正常完全,说明审批通过 processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被通过的消息 messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.convert2ApprovedReq(instance)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Transactional(rollbackFor = Exception.class) public void updateProcessInstanceExtReject(String id, String reason) { // 需要主动查询,因为 instance 只有 id 属性 ProcessInstance processInstance = getProcessInstance(id); // 删除流程实例,以实现驳回任务时,取消整个审批流程 deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(reason))); // 更新 status + result // 注意,不能和上面的逻辑更换位置。因为 deleteProcessInstance 会触发流程的取消,进而调用 updateProcessInstanceExtCancel 方法, // 设置 result 为 BpmProcessInstanceStatusEnum.CANCEL,显然和 result 不一定是一致的 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(id) .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.REJECT.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被不通过的消息 messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, reason)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } private void deleteProcessInstance(String id, String reason) { runtimeService.deleteProcessInstance(id, reason); } private String createProcessInstance0(Long userId, ProcessDefinition definition, Map<String, Object> variables, String businessKey) { // 校验流程定义 if (definition == null) { throw exception(PROCESS_DEFINITION_NOT_EXISTS); } if (definition.isSuspended()) { throw exception(PROCESS_DEFINITION_IS_SUSPENDED); } // 创建流程实例 ProcessInstance instance = runtimeService.startProcessInstanceById(definition.getId(), businessKey, variables); // 设置流程名字 runtimeService.setProcessInstanceName(instance.getId(), definition.getName()); // 补全流程实例的拓展表 //TODO startProcessInstance流程里面修改了 BpmProcessInstanceExt,没有提交,和下面的更新 锁持有冲突了,异步更新这个表 // processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId()).setFormVariables(variables)); BpmProcessInstanceExtDO bpmProcessInstanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId()).setFormVariables(variables); asyncUpdateProcesInstance(bpmProcessInstanceExtDO); return instance.getId(); } @Async public void asyncUpdateProcesInstance(BpmProcessInstanceExtDO bpmProcessInstanceExtDO){ log.info("asyncUpdateProcesInstance ,cause MySQL Dead Lock"); processInstanceExtMapper.updateByProcessInstanceId(bpmProcessInstanceExtDO); } } | ||
| 2 | \ No newline at end of file | 1 | \ No newline at end of file |
| 2 | +package cn.iocoder.yudao.module.bpm.service.task; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum; import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher; import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; 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 lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; import org.flowable.engine.delegate.event.FlowableCancelledEvent; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.task.api.Task; import org.springframework.context.annotation.Lazy; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import javax.validation.Valid; import java.util.*; 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.module.bpm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF; /** * 流程实例 Service 实现类 * * ProcessDefinition & ProcessInstance & Execution & Task 的关系: * 1. <a href="https://blog.csdn.net/bobozai86/article/details/105210414" /> * * HistoricProcessInstance & ProcessInstance 的关系: * 1. <a href=" https://my.oschina.net/843294669/blog/71902" /> * * 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例 * * @author 芋道源码 */ @Service @Validated @Slf4j public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService { @Resource private RuntimeService runtimeService; @Resource private BpmProcessInstanceExtMapper processInstanceExtMapper; @Resource @Lazy // 解决循环依赖 private BpmTaskService taskService; @Resource private BpmProcessDefinitionService processDefinitionService; @Resource private HistoryService historyService; @Resource private AdminUserApi adminUserApi; @Resource private DeptApi deptApi; @Resource private BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher; @Resource private BpmMessageService messageService; @Override public ProcessInstance getProcessInstance(String id) { return runtimeService.createProcessInstanceQuery().processInstanceId(id).singleResult(); } @Override public List<ProcessInstance> getProcessInstances(Set<String> ids) { return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public PageResult<BpmProcessInstancePageItemRespVO> getMyProcessInstancePage(Long userId, BpmProcessInstanceMyPageReqVO pageReqVO) { // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 PageResult<BpmProcessInstanceExtDO> pageResult = processInstanceExtMapper.selectPage(userId, pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { return new PageResult<>(pageResult.getTotal()); } // 获得流程 Task Map List<String> processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId); Map<String, List<Task>> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds); // 转换返回 return BpmProcessInstanceConvert.INSTANCE.convertPage(pageResult, taskMap); } @Override @Transactional(rollbackFor = Exception.class) public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId()); // 发起流程 return createProcessInstance0(userId, definition, createReqVO.getVariables(), null); } @Override public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey()); // 发起流程 return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey()); } @Override public BpmProcessInstanceRespVO getProcessInstanceVO(String id) { // 获得流程实例 HistoricProcessInstance processInstance = getHistoricProcessInstance(id); if (processInstance == null) { return null; } BpmProcessInstanceExtDO processInstanceExt = processInstanceExtMapper.selectByProcessInstanceId(id); Assert.notNull(processInstanceExt, "流程实例拓展({}) 不存在", id); // 获得流程定义 ProcessDefinition processDefinition = processDefinitionService .getProcessDefinition(processInstance.getProcessDefinitionId()); Assert.notNull(processDefinition, "流程定义({}) 不存在", processInstance.getProcessDefinitionId()); BpmProcessDefinitionExtDO processDefinitionExt = processDefinitionService.getProcessDefinitionExt( processInstance.getProcessDefinitionId()); Assert.notNull(processDefinitionExt, "流程定义拓展({}) 不存在", id); String bpmnXml = processDefinitionService.getProcessDefinitionBpmnXML(processInstance.getProcessDefinitionId()); // 获得 User AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId())); DeptRespDTO dept = null; if (startUser != null) { dept = deptApi.getDept(startUser.getDeptId()); } // 拼接结果 return BpmProcessInstanceConvert.INSTANCE.convert2(processInstance, processInstanceExt, processDefinition, processDefinitionExt, bpmnXml, startUser, dept); } @Override public void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) { // 校验流程实例存在 ProcessInstance instance = getProcessInstance(cancelReqVO.getId()); if (instance == null) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS); } // 只能取消自己的 if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF); } // 通过删除流程实例,实现流程实例的取消, // 删除流程实例,正则执行任务 ACT_RU_TASK. 任务会被删除。通过历史表查询 deleteProcessInstance(cancelReqVO.getId(), BpmProcessInstanceDeleteReasonEnum.CANCEL_TASK.format(cancelReqVO.getReason())); } /** * 获得历史的流程实例 * * @param id 流程实例的编号 * @return 历史的流程实例 */ @Override public HistoricProcessInstance getHistoricProcessInstance(String id) { return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult(); } @Override public List<HistoricProcessInstance> getHistoricProcessInstances(Set<String> ids) { return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public void createProcessInstanceExt(ProcessInstance instance) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition2(instance.getProcessDefinitionId()); // 插入 BpmProcessInstanceExtDO 对象 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getId()) .setProcessDefinitionId(definition.getId()) .setName(instance.getProcessDefinitionName()) .setStartUserId(Long.valueOf(instance.getStartUserId())) .setCategory(definition.getCategory()) .setStatus(BpmProcessInstanceStatusEnum.RUNNING.getStatus()) .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()); processInstanceExtMapper.insert(instanceExtDO); } @Override public void updateProcessInstanceExtCancel(FlowableCancelledEvent event) { // 判断是否为 Reject 不通过。如果是,则不进行更新. // 因为,updateProcessInstanceExtReject 方法,已经进行更新了 if (BpmProcessInstanceDeleteReasonEnum.isRejectReason((String)event.getCause())) { return; } // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(event.getProcessInstanceId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(event.getProcessInstanceId()) .setEndTime(new Date()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.CANCEL.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Override public void updateProcessInstanceExtComplete(ProcessInstance instance) { // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getProcessInstanceId()) .setEndTime(new Date()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()); // 如果正常完全,说明审批通过 processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被通过的消息 messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.convert2ApprovedReq(instance)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Transactional(rollbackFor = Exception.class) public void updateProcessInstanceExtReject(String id, String reason) { // 需要主动查询,因为 instance 只有 id 属性 ProcessInstance processInstance = getProcessInstance(id); // 删除流程实例,以实现驳回任务时,取消整个审批流程 deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(reason))); // 更新 status + result // 注意,不能和上面的逻辑更换位置。因为 deleteProcessInstance 会触发流程的取消,进而调用 updateProcessInstanceExtCancel 方法, // 设置 result 为 BpmProcessInstanceStatusEnum.CANCEL,显然和 result 不一定是一致的 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(id) .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.REJECT.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被不通过的消息 messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, reason)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } private void deleteProcessInstance(String id, String reason) { runtimeService.deleteProcessInstance(id, reason); } private String createProcessInstance0(Long userId, ProcessDefinition definition, Map<String, Object> variables, String businessKey) { // 校验流程定义 if (definition == null) { throw exception(PROCESS_DEFINITION_NOT_EXISTS); } if (definition.isSuspended()) { throw exception(PROCESS_DEFINITION_IS_SUSPENDED); } // 创建流程实例 ProcessInstance instance = runtimeService.startProcessInstanceById(definition.getId(), businessKey, variables); // 设置流程名字 runtimeService.setProcessInstanceName(instance.getId(), definition.getName()); // 补全流程实例的拓展表 //TODO startProcessInstance流程里面修改了 BpmProcessInstanceExt,没有提交,和下面的更新 锁持有冲突了,异步更新这个表 // processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId()).setFormVariables(variables)); BpmProcessInstanceExtDO bpmProcessInstanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId()).setFormVariables(variables); asyncUpdateProcesInstance(bpmProcessInstanceExtDO); return instance.getId(); } @Async public void asyncUpdateProcesInstance(BpmProcessInstanceExtDO bpmProcessInstanceExtDO){ log.info("asyncUpdateProcesInstance ,cause MySQL Dead Lock"); processInstanceExtMapper.updateByProcessInstanceId(bpmProcessInstanceExtDO); } } | ||
| 3 | \ No newline at end of file | 3 | \ No newline at end of file |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
| @@ -18,8 +18,8 @@ import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmTaskExtMapper; | @@ -18,8 +18,8 @@ import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmTaskExtMapper; | ||
| 18 | import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum; | 18 | import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum; |
| 19 | import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; | 19 | import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; |
| 20 | import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; | 20 | import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; |
| 21 | -import cn.iocoder.yudao.module.business.hi.task.inst.service.HiTaskInstService; | ||
| 22 | import cn.iocoder.yudao.module.system.api.dept.DeptApi; | 21 | import cn.iocoder.yudao.module.system.api.dept.DeptApi; |
| 22 | +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; | ||
| 23 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | 23 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| 24 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | 24 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| 25 | import lombok.extern.slf4j.Slf4j; | 25 | import lombok.extern.slf4j.Slf4j; |
| @@ -78,8 +78,6 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -78,8 +78,6 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 78 | private BpmTaskAssignRuleMapper taskAssignRuleMapper; | 78 | private BpmTaskAssignRuleMapper taskAssignRuleMapper; |
| 79 | @Resource | 79 | @Resource |
| 80 | private BpmActivityMapper bpmActivityMapper; | 80 | private BpmActivityMapper bpmActivityMapper; |
| 81 | - @Resource | ||
| 82 | - private HiTaskInstService hiTaskInstService; | ||
| 83 | 81 | ||
| 84 | @Override | 82 | @Override |
| 85 | public PageResult<BpmTaskTodoPageItemRespVO> getTodoTaskPage(Long userId, BpmTaskTodoPageReqVO pageVO) { | 83 | public PageResult<BpmTaskTodoPageItemRespVO> getTodoTaskPage(Long userId, BpmTaskTodoPageReqVO pageVO) { |
| @@ -161,22 +159,17 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -161,22 +159,17 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 161 | @Override | 159 | @Override |
| 162 | public List<BpmTaskRespVO> getTaskListByProcessInstanceId(String processInstanceId) { | 160 | public List<BpmTaskRespVO> getTaskListByProcessInstanceId(String processInstanceId) { |
| 163 | // 获得任务列表 | 161 | // 获得任务列表 |
| 164 | - /* List<HistoricTaskInstance> tasks = | ||
| 165 | - historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId) | 162 | + List<HistoricTaskInstance> tasks = historyService.createHistoricTaskInstanceQuery() |
| 163 | + .processInstanceId(processInstanceId) | ||
| 166 | .orderByHistoricTaskInstanceStartTime().desc() // 创建时间倒序 | 164 | .orderByHistoricTaskInstanceStartTime().desc() // 创建时间倒序 |
| 167 | .list(); | 165 | .list(); |
| 168 | if (CollUtil.isEmpty(tasks)) { | 166 | if (CollUtil.isEmpty(tasks)) { |
| 169 | return Collections.emptyList(); | 167 | return Collections.emptyList(); |
| 170 | - }*/ | ||
| 171 | - // 获得 TaskExtDO Map | ||
| 172 | - // List<BpmTaskExtDO> bpmTaskExtDOList = | ||
| 173 | - // taskExtMapper.selectListByTaskIds(convertSet(tasks, HistoricTaskInstance::getId)); | ||
| 174 | - | ||
| 175 | -// List<BpmTaskExtDO> bpmTaskExtDOList = taskExtMapper.listByProcInstId(processInstanceId); | ||
| 176 | - // List<BpmTaskExtDO> bpmTaskExtDOList = BpmTaskConvert.INSTANCE.distinct(tmpBpmTaskExtDOList); | ||
| 177 | - // bpmTaskExtDOList.forEach(var -> log.info("var = " + var)); | 168 | + } |
| 178 | 169 | ||
| 179 | - /*Map<String, BpmTaskExtDO> bpmTaskExtDoMap = convertMap(bpmTaskExtDOList, BpmTaskExtDO::getTaskId); | 170 | + // 获得 TaskExtDO Map |
| 171 | + List<BpmTaskExtDO> bpmTaskExtDOs = taskExtMapper.selectListByTaskIds(convertSet(tasks, HistoricTaskInstance::getId)); | ||
| 172 | + Map<String, BpmTaskExtDO> bpmTaskExtDOMap = convertMap(bpmTaskExtDOs, BpmTaskExtDO::getTaskId); | ||
| 180 | // 获得 ProcessInstance Map | 173 | // 获得 ProcessInstance Map |
| 181 | HistoricProcessInstance processInstance = processInstanceService.getHistoricProcessInstance(processInstanceId); | 174 | HistoricProcessInstance processInstance = processInstanceService.getHistoricProcessInstance(processInstanceId); |
| 182 | // 获得 User Map | 175 | // 获得 User Map |
| @@ -184,14 +177,10 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -184,14 +177,10 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 184 | userIds.add(NumberUtils.parseLong(processInstance.getStartUserId())); | 177 | userIds.add(NumberUtils.parseLong(processInstance.getStartUserId())); |
| 185 | Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds); | 178 | Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds); |
| 186 | // 获得 Dept Map | 179 | // 获得 Dept Map |
| 187 | - Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));*/ | 180 | + Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); |
| 188 | 181 | ||
| 189 | // 拼接数据 | 182 | // 拼接数据 |
| 190 | -// List<BpmTaskExtDO> tmpBpmTaskExtDOList = taskExtMapper.listByProcInstId(processInstanceId); | ||
| 191 | - // TODO @ke:这个钉钉是咋处理的?得讨论下流程预测的需要程度哈。 | ||
| 192 | - List<BpmTaskExtDO> tmpBpmTaskExtDOList = taskExtMapper.selectListByProcessInstanceId(processInstanceId); | ||
| 193 | - tmpBpmTaskExtDOList.sort(Comparator.comparing(BpmTaskExtDO::getCreateTime)); | ||
| 194 | - return hiTaskInstService.taskGetComment(tmpBpmTaskExtDOList, ""); | 183 | + return BpmTaskConvert.INSTANCE.convertList3(tasks, bpmTaskExtDOMap, processInstance, userMap, deptMap); |
| 195 | } | 184 | } |
| 196 | 185 | ||
| 197 | @Override | 186 | @Override |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/business/hi/task/inst/domain/HistoricApproveTaskDTO.java deleted
| 1 | -package cn.iocoder.yudao.module.business.hi.task.inst.domain; | ||
| 2 | - | ||
| 3 | -import lombok.AllArgsConstructor; | ||
| 4 | -import lombok.Data; | ||
| 5 | -import lombok.NoArgsConstructor; | ||
| 6 | - | ||
| 7 | -/** | ||
| 8 | - * @author kemengkai | ||
| 9 | - * @create 2022-01-11 15:09 | ||
| 10 | - */ | ||
| 11 | -@Data | ||
| 12 | -@AllArgsConstructor | ||
| 13 | -@NoArgsConstructor | ||
| 14 | -public class HistoricApproveTaskDTO { | ||
| 15 | - | ||
| 16 | - private String procInstId; | ||
| 17 | - private String name; | ||
| 18 | - private String assignee; | ||
| 19 | - | ||
| 20 | -} |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/business/hi/task/inst/domain/vo/HiTaskinstVO.java deleted
| 1 | -package cn.iocoder.yudao.module.business.hi.task.inst.domain.vo; | ||
| 2 | - | ||
| 3 | -import lombok.Data; | ||
| 4 | -import java.util.Date; | ||
| 5 | -import com.fasterxml.jackson.annotation.JsonFormat; | ||
| 6 | -import io.swagger.annotations.ApiModelProperty; | ||
| 7 | - | ||
| 8 | -/** | ||
| 9 | - * [ ] | ||
| 10 | - * | ||
| 11 | - * @author 孟凯 | ||
| 12 | - * @version 1.0 | ||
| 13 | - * @company 1024创新实验室( www.1024lab.net ) | ||
| 14 | - * @copyright (c) 1024创新实验室( www.1024lab.net )Inc. All rights reserved. | ||
| 15 | - * @date 2022-01-17 15:14:27 | ||
| 16 | - * @since JDK1.8 | ||
| 17 | - */ | ||
| 18 | -@Data | ||
| 19 | -public class HiTaskinstVO { | ||
| 20 | - @ApiModelProperty("ID_") | ||
| 21 | - private String id; | ||
| 22 | - | ||
| 23 | - @ApiModelProperty("TASK_DEF_KEY_") | ||
| 24 | - private String taskDefKey; | ||
| 25 | - | ||
| 26 | - @ApiModelProperty("PROC_DEF_KEY_") | ||
| 27 | - private String procDefKey; | ||
| 28 | - | ||
| 29 | - @ApiModelProperty("PROC_DEF_ID_") | ||
| 30 | - private String procDefId; | ||
| 31 | - | ||
| 32 | - @ApiModelProperty("ROOT_PROC_INST_ID_") | ||
| 33 | - private String rootProcInstId; | ||
| 34 | - | ||
| 35 | - @ApiModelProperty("PROC_INST_ID_") | ||
| 36 | - private String procInstId; | ||
| 37 | - | ||
| 38 | - @ApiModelProperty("EXECUTION_ID_") | ||
| 39 | - private String executionId; | ||
| 40 | - | ||
| 41 | - @ApiModelProperty("CASE_DEF_KEY_") | ||
| 42 | - private String caseDefKey; | ||
| 43 | - | ||
| 44 | - @ApiModelProperty("CASE_DEF_ID_") | ||
| 45 | - private String caseDefId; | ||
| 46 | - | ||
| 47 | - @ApiModelProperty("CASE_INST_ID_") | ||
| 48 | - private String caseInstId; | ||
| 49 | - | ||
| 50 | - @ApiModelProperty("CASE_EXECUTION_ID_") | ||
| 51 | - private String caseExecutionId; | ||
| 52 | - | ||
| 53 | - @ApiModelProperty("ACT_INST_ID_") | ||
| 54 | - private String actInstId; | ||
| 55 | - | ||
| 56 | - @ApiModelProperty("NAME_") | ||
| 57 | - private String name; | ||
| 58 | - | ||
| 59 | - @ApiModelProperty("PARENT_TASK_ID_") | ||
| 60 | - private String parentTaskId; | ||
| 61 | - | ||
| 62 | - @ApiModelProperty("DESCRIPTION_") | ||
| 63 | - private String description; | ||
| 64 | - | ||
| 65 | - @ApiModelProperty("OWNER_") | ||
| 66 | - private String owner; | ||
| 67 | - | ||
| 68 | - @ApiModelProperty("ASSIGNEE_") | ||
| 69 | - private String assignee; | ||
| 70 | - | ||
| 71 | - @ApiModelProperty("START_TIME_") | ||
| 72 | - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") | ||
| 73 | - private Date startTime; | ||
| 74 | - | ||
| 75 | - @ApiModelProperty("END_TIME_") | ||
| 76 | - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") | ||
| 77 | - private Date endTime; | ||
| 78 | - | ||
| 79 | - @ApiModelProperty("DURATION_") | ||
| 80 | - private Long duration; | ||
| 81 | - | ||
| 82 | - @ApiModelProperty("DELETE_REASON_") | ||
| 83 | - private String deleteReason; | ||
| 84 | - | ||
| 85 | - @ApiModelProperty("PRIORITY_") | ||
| 86 | - private Integer priority; | ||
| 87 | - | ||
| 88 | - @ApiModelProperty("DUE_DATE_") | ||
| 89 | - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") | ||
| 90 | - private Date dueDate; | ||
| 91 | - | ||
| 92 | - @ApiModelProperty("FOLLOW_UP_DATE_") | ||
| 93 | - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") | ||
| 94 | - private Date followUpDate; | ||
| 95 | - | ||
| 96 | - @ApiModelProperty("TENANT_ID_") | ||
| 97 | - private String tenantId; | ||
| 98 | - | ||
| 99 | - @ApiModelProperty("REMOVAL_TIME_") | ||
| 100 | - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") | ||
| 101 | - private Date removalTime; | ||
| 102 | - | ||
| 103 | - | ||
| 104 | - | ||
| 105 | -} |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/business/hi/task/inst/service/HiTaskInstService.java deleted
| 1 | -package cn.iocoder.yudao.module.business.hi.task.inst.service; | ||
| 2 | - | ||
| 3 | -import cn.hutool.core.bean.BeanUtil; | ||
| 4 | -import cn.hutool.core.collection.CollUtil; | ||
| 5 | -import cn.hutool.core.util.ObjectUtil; | ||
| 6 | -import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; | ||
| 7 | -import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO; | ||
| 8 | -import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskTodoPageItemRespVO; | ||
| 9 | -import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO; | ||
| 10 | -import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO; | ||
| 11 | -import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmTaskAssignRuleMapper; | ||
| 12 | -import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; | ||
| 13 | -import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; | ||
| 14 | -import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; | ||
| 15 | -import cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper; | ||
| 16 | -import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper; | ||
| 17 | -import lombok.extern.slf4j.Slf4j; | ||
| 18 | -import org.flowable.bpmn.model.*; | ||
| 19 | -import org.flowable.common.engine.impl.de.odysseus.el.ExpressionFactoryImpl; | ||
| 20 | -import org.flowable.common.engine.impl.de.odysseus.el.util.SimpleContext; | ||
| 21 | -import org.flowable.common.engine.impl.javax.el.ExpressionFactory; | ||
| 22 | -import org.flowable.common.engine.impl.javax.el.ValueExpression; | ||
| 23 | -import org.flowable.engine.HistoryService; | ||
| 24 | -import org.flowable.engine.RepositoryService; | ||
| 25 | -import org.flowable.engine.history.HistoricProcessInstance; | ||
| 26 | -import org.flowable.task.api.history.HistoricTaskInstance; | ||
| 27 | -import org.flowable.variable.api.history.HistoricVariableInstance; | ||
| 28 | -import org.springframework.stereotype.Service; | ||
| 29 | - | ||
| 30 | -import javax.annotation.Resource; | ||
| 31 | -import java.util.HashMap; | ||
| 32 | -import java.util.LinkedList; | ||
| 33 | -import java.util.List; | ||
| 34 | -import java.util.Map; | ||
| 35 | -import java.util.function.Function; | ||
| 36 | -import java.util.stream.Collectors; | ||
| 37 | - | ||
| 38 | -/** | ||
| 39 | - * [ ] | ||
| 40 | - * | ||
| 41 | - * @author 孟凯 | ||
| 42 | - * @version 1.0 | ||
| 43 | - */ | ||
| 44 | -@Slf4j | ||
| 45 | -@Service | ||
| 46 | -public class HiTaskInstService { | ||
| 47 | - | ||
| 48 | - @Resource | ||
| 49 | - private HistoryService historyService; | ||
| 50 | - @Resource | ||
| 51 | - private RepositoryService repositoryService; | ||
| 52 | - @Resource | ||
| 53 | - private BpmTaskAssignRuleMapper bpmTaskAssignRuleMapper; | ||
| 54 | - @Resource | ||
| 55 | - private BpmProcessInstanceService processInstanceService; | ||
| 56 | - @Resource | ||
| 57 | - private AdminUserMapper adminUserApi; | ||
| 58 | - @Resource | ||
| 59 | - private DeptMapper deptMapper; | ||
| 60 | - | ||
| 61 | - /** | ||
| 62 | - * 获取任务具体流程信息 | ||
| 63 | - * | ||
| 64 | - * @param taskList 任务信息 | ||
| 65 | - * @param approved 任意选择条件 | ||
| 66 | - * | ||
| 67 | - * @return 返回流程信息 | ||
| 68 | - */ | ||
| 69 | - @TenantIgnore | ||
| 70 | - public List<BpmTaskRespVO> taskGetComment(List<BpmTaskExtDO> taskList, Object approved) { | ||
| 71 | - BpmTaskExtDO task = taskList.get(taskList.size() - 1); | ||
| 72 | - Map<String, BpmTaskExtDO> bpmTaskMap = | ||
| 73 | - taskList.stream().collect(Collectors.toMap(BpmTaskExtDO::getTaskId, Function.identity())); | ||
| 74 | - // 获得 ProcessInstance Map | ||
| 75 | - HistoricProcessInstance procInst = | ||
| 76 | - processInstanceService.getHistoricProcessInstance(task.getProcessInstanceId()); | ||
| 77 | - Map<Long, AdminUserDO> userDoMap = | ||
| 78 | - adminUserApi.selectList().stream().collect(Collectors.toMap(AdminUserDO::getId, Function.identity())); | ||
| 79 | - Map<Long, DeptDO> deptMap = | ||
| 80 | - deptMapper.selectList().stream().collect(Collectors.toMap(DeptDO::getId, Function.identity())); | ||
| 81 | - List<HistoricTaskInstance> hisTaskInstList = | ||
| 82 | - historyService.createHistoricTaskInstanceQuery().processInstanceId(task.getProcessInstanceId()) | ||
| 83 | - .orderByHistoricTaskInstanceStartTime().desc().list(); | ||
| 84 | - LinkedList<BpmTaskRespVO> bpmTaskRespVOList = | ||
| 85 | - nowTaskFormat(procInst, hisTaskInstList, bpmTaskMap, userDoMap, deptMap); | ||
| 86 | - | ||
| 87 | - //ProcessInstanceId流程实例 | ||
| 88 | - String procInstId = task.getProcessInstanceId(); | ||
| 89 | - List<BpmTaskAssignRuleDO> tmpBpmTaskAssignRuleDOList = | ||
| 90 | - bpmTaskAssignRuleMapper.selectListByProcessDefinitionId(task.getProcessDefinitionId(), null); | ||
| 91 | - List<HistoricVariableInstance> hisVarInstList = | ||
| 92 | - historyService.createHistoricVariableInstanceQuery().processInstanceId(procInstId).list(); | ||
| 93 | - Map<String, Object> hisVarInstMap = new HashMap<>(); | ||
| 94 | - for (HistoricVariableInstance hisVarInst : hisVarInstList) { | ||
| 95 | - hisVarInstMap.put(hisVarInst.getVariableName(), hisVarInst.getValue()); | ||
| 96 | - } | ||
| 97 | - hisVarInstMap.put("approved", approved); | ||
| 98 | - //获取bpm(模型)对象 | ||
| 99 | - BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId()); | ||
| 100 | - getFlow(bpmnModel, task.getTaskDefKey(), tmpBpmTaskAssignRuleDOList, bpmTaskRespVOList, userDoMap, deptMap, | ||
| 101 | - hisVarInstMap); | ||
| 102 | - return bpmTaskRespVOList; | ||
| 103 | - } | ||
| 104 | - | ||
| 105 | - /** | ||
| 106 | - * 格式化任务信息 | ||
| 107 | - */ | ||
| 108 | - private LinkedList<BpmTaskRespVO> nowTaskFormat(HistoricProcessInstance procInst, List<HistoricTaskInstance> taskList, | ||
| 109 | - Map<String, BpmTaskExtDO> bpmTaskExtDoMap, Map<Long, AdminUserDO> userMap, Map<Long, DeptDO> deptMap) { | ||
| 110 | - LinkedList<BpmTaskRespVO> bpmTaskRespVOList = new LinkedList<>(); | ||
| 111 | - for (HistoricTaskInstance hisTaskInst : taskList) { | ||
| 112 | - BpmTaskRespVO respVO = initRespVo(hisTaskInst, bpmTaskExtDoMap, procInst, userMap); | ||
| 113 | - AdminUserDO user = userMap.get(Long.valueOf(hisTaskInst.getAssignee())); | ||
| 114 | - if (BeanUtil.isNotEmpty(user)) { | ||
| 115 | - respVO.setAssigneeUser(setUser(user)); | ||
| 116 | - DeptDO dept = deptMap.get(user.getDeptId()); | ||
| 117 | - if (BeanUtil.isNotEmpty(dept)) { | ||
| 118 | - respVO.getAssigneeUser().setDeptName(dept.getName()); | ||
| 119 | - } | ||
| 120 | - } | ||
| 121 | - bpmTaskRespVOList.addFirst(respVO); | ||
| 122 | - } | ||
| 123 | - return bpmTaskRespVOList; | ||
| 124 | - } | ||
| 125 | - | ||
| 126 | - private BpmTaskRespVO initRespVo(Object taskInst, Map<String, BpmTaskExtDO> bpmTaskExtDoMap, | ||
| 127 | - HistoricProcessInstance procInst, Map<Long, AdminUserDO> userMap) { | ||
| 128 | - BpmTaskRespVO respVO = new BpmTaskRespVO(); | ||
| 129 | - if (taskInst instanceof HistoricTaskInstance) { | ||
| 130 | - respVO = setBpmnTaskRespVo((HistoricTaskInstance)taskInst); | ||
| 131 | - BeanUtil.copyProperties(taskInst, respVO); | ||
| 132 | - BpmTaskExtDO bpmTaskExtDO = bpmTaskExtDoMap.get(respVO.getId()); | ||
| 133 | - if (ObjectUtil.isNotEmpty(bpmTaskExtDO)) { | ||
| 134 | - BeanUtil.copyProperties(bpmTaskExtDO, respVO); | ||
| 135 | - respVO.setId(bpmTaskExtDO.getTaskId()); | ||
| 136 | - } | ||
| 137 | - } | ||
| 138 | - if (taskInst instanceof BpmTaskExtDO) { | ||
| 139 | - respVO = setBpmnTaskRespVo((BpmTaskExtDO)taskInst); | ||
| 140 | - BeanUtil.copyProperties(taskInst, respVO); | ||
| 141 | - } | ||
| 142 | - // copyTo(bpmTaskExtDO, respVO); | ||
| 143 | - if (procInst != null) { | ||
| 144 | - AdminUserDO startUser = userMap.get(Long.valueOf(procInst.getStartUserId())); | ||
| 145 | - if (BeanUtil.isEmpty(startUser)) { | ||
| 146 | - throw new RuntimeException("查找不到审批用户!!!"); | ||
| 147 | - } | ||
| 148 | - respVO.setProcessInstance(setProcInst(procInst, startUser)); | ||
| 149 | - } | ||
| 150 | - return respVO; | ||
| 151 | - } | ||
| 152 | - | ||
| 153 | - private BpmTaskRespVO.User setUser(AdminUserDO bean) { | ||
| 154 | - if (bean == null) { | ||
| 155 | - return null; | ||
| 156 | - } | ||
| 157 | - | ||
| 158 | - BpmTaskRespVO.User user = new BpmTaskRespVO.User(); | ||
| 159 | - | ||
| 160 | - user.setId(bean.getId()); | ||
| 161 | - user.setNickname(bean.getNickname()); | ||
| 162 | - user.setDeptId(bean.getDeptId()); | ||
| 163 | - | ||
| 164 | - return user; | ||
| 165 | - | ||
| 166 | - } | ||
| 167 | - | ||
| 168 | - private BpmTaskRespVO setBpmnTaskRespVo(BpmTaskExtDO bean) { | ||
| 169 | - if (bean == null) { | ||
| 170 | - return null; | ||
| 171 | - } | ||
| 172 | - | ||
| 173 | - BpmTaskRespVO bpmTaskRespVO = new BpmTaskRespVO(); | ||
| 174 | - | ||
| 175 | - bpmTaskRespVO.setDefinitionKey(bean.getTaskDefKey()); | ||
| 176 | - bpmTaskRespVO.setId(bean.getTaskId()); | ||
| 177 | - bpmTaskRespVO.setName(bean.getName()); | ||
| 178 | - bpmTaskRespVO.setCreateTime(bean.getCreateTime()); | ||
| 179 | - | ||
| 180 | - return bpmTaskRespVO; | ||
| 181 | - } | ||
| 182 | - | ||
| 183 | - public BpmTaskRespVO setBpmnTaskRespVo(HistoricTaskInstance bean) { | ||
| 184 | - if (bean == null) { | ||
| 185 | - return null; | ||
| 186 | - } | ||
| 187 | - | ||
| 188 | - BpmTaskRespVO bpmTaskRespVO = new BpmTaskRespVO(); | ||
| 189 | - | ||
| 190 | - bpmTaskRespVO.setDefinitionKey(bean.getTaskDefinitionKey()); | ||
| 191 | - bpmTaskRespVO.setId(bean.getId()); | ||
| 192 | - bpmTaskRespVO.setName(bean.getName()); | ||
| 193 | - bpmTaskRespVO.setClaimTime(bean.getClaimTime()); | ||
| 194 | - bpmTaskRespVO.setCreateTime(bean.getCreateTime()); | ||
| 195 | - bpmTaskRespVO.setEndTime(bean.getEndTime()); | ||
| 196 | - bpmTaskRespVO.setDurationInMillis(bean.getDurationInMillis()); | ||
| 197 | - | ||
| 198 | - return bpmTaskRespVO; | ||
| 199 | - } | ||
| 200 | - | ||
| 201 | - public BpmTaskTodoPageItemRespVO.ProcessInstance setProcInst(HistoricProcessInstance processInstance, | ||
| 202 | - AdminUserDO startUser) { | ||
| 203 | - if (processInstance == null && startUser == null) { | ||
| 204 | - return null; | ||
| 205 | - } | ||
| 206 | - | ||
| 207 | - BpmTaskTodoPageItemRespVO.ProcessInstance processInstanceResult = | ||
| 208 | - new BpmTaskTodoPageItemRespVO.ProcessInstance(); | ||
| 209 | - | ||
| 210 | - if (processInstance != null) { | ||
| 211 | - processInstanceResult.setId(processInstance.getId()); | ||
| 212 | - processInstanceResult.setName(processInstance.getName()); | ||
| 213 | - if (processInstance.getStartUserId() != null) { | ||
| 214 | - processInstanceResult.setStartUserId(Long.parseLong(processInstance.getStartUserId())); | ||
| 215 | - } | ||
| 216 | - processInstanceResult.setProcessDefinitionId(processInstance.getProcessDefinitionId()); | ||
| 217 | - } | ||
| 218 | - if (startUser != null) { | ||
| 219 | - processInstanceResult.setStartUserNickname(startUser.getNickname()); | ||
| 220 | - } | ||
| 221 | - | ||
| 222 | - return processInstanceResult; | ||
| 223 | - } | ||
| 224 | - | ||
| 225 | - private void getFlow(BpmnModel bpmnModel, String taskDefKey, List<BpmTaskAssignRuleDO> tmpBpmTaskAssignRuleDOList, | ||
| 226 | - LinkedList<BpmTaskRespVO> bpmTaskRespVOList, Map<Long, AdminUserDO> userDoMap, Map<Long, DeptDO> deptMap, | ||
| 227 | - Map<String, Object> taskVarMap) { | ||
| 228 | - //传节点定义key获取当前节点 | ||
| 229 | - FlowNode flowNode = (FlowNode)bpmnModel.getFlowElement(taskDefKey); | ||
| 230 | - //输出连线 | ||
| 231 | - List<SequenceFlow> outgoingFlows = flowNode.getOutgoingFlows(); | ||
| 232 | - //遍历返回下一个节点信息 | ||
| 233 | - for (SequenceFlow outgoingFlow : outgoingFlows) { | ||
| 234 | - //类型自己判断(获取下个节点是网关还是节点) | ||
| 235 | - FlowElement targetFlowElement = outgoingFlow.getTargetFlowElement(); | ||
| 236 | - getFlow(bpmnModel, targetFlowElement, tmpBpmTaskAssignRuleDOList, bpmTaskRespVOList, userDoMap, deptMap, | ||
| 237 | - taskVarMap); | ||
| 238 | - } | ||
| 239 | - } | ||
| 240 | - | ||
| 241 | - private void getFlow(BpmnModel bpmnModel, FlowElement targetFlowElement, | ||
| 242 | - List<BpmTaskAssignRuleDO> tmpBpmTaskAssignRuleDOList, LinkedList<BpmTaskRespVO> bpmTaskRespVOList, | ||
| 243 | - Map<Long, AdminUserDO> userDoMap, Map<Long, DeptDO> deptMap, Map<String, Object> taskVarMap) { | ||
| 244 | - // 下一个taskDefKey | ||
| 245 | - String nextTaskDefKey = null; | ||
| 246 | - //下个是节点 | ||
| 247 | - if (targetFlowElement instanceof UserTask) { | ||
| 248 | - // 判断是否是为并行任务 | ||
| 249 | - List<BpmTaskAssignRuleDO> bpmTaskAssignRuleDOList = tmpBpmTaskAssignRuleDOList.stream().filter( | ||
| 250 | - bpmTaskAssignRuleDO -> bpmTaskAssignRuleDO.getTaskDefinitionKey().equals(targetFlowElement.getId())) | ||
| 251 | - .collect(Collectors.toList()); | ||
| 252 | - if (CollUtil.isEmpty(bpmTaskAssignRuleDOList)) { | ||
| 253 | - throw new RuntimeException("任务key不存在!!!"); | ||
| 254 | - } | ||
| 255 | - for (BpmTaskAssignRuleDO bpmTaskAssignRuleDO : bpmTaskAssignRuleDOList) { | ||
| 256 | - nextTaskDefKey = bpmTaskAssignRuleDO.getTaskDefinitionKey(); | ||
| 257 | - for (Long userId : bpmTaskAssignRuleDO.getOptions()) { | ||
| 258 | - BpmTaskRespVO bpmTaskRespVO = | ||
| 259 | - (BpmTaskRespVO)new BpmTaskRespVO().setName(targetFlowElement.getName()); | ||
| 260 | - bpmTaskRespVOList.addLast(bpmTaskRespVO); | ||
| 261 | - AdminUserDO adminUserDO = userDoMap.get(userId); | ||
| 262 | - DeptDO deptDO = deptMap.get(adminUserDO.getDeptId()); | ||
| 263 | - bpmTaskRespVO.setAssigneeUser(setUser(adminUserDO)); | ||
| 264 | - bpmTaskRespVO.getAssigneeUser().setDeptName(deptDO.getName()); | ||
| 265 | - // edit by 芋艿 TODO | ||
| 266 | -// if (!bpmTaskAssignRuleDO.getType().equals(BpmTaskAssignRuleTypeEnum.USER_OR_SIGN.getType()) | ||
| 267 | -// && !bpmTaskAssignRuleDO.getType().equals(BpmTaskAssignRuleTypeEnum.USER_SIGN.getType())) { | ||
| 268 | -// break; | ||
| 269 | -// } | ||
| 270 | - } | ||
| 271 | - } | ||
| 272 | - getFlow(bpmnModel, nextTaskDefKey, tmpBpmTaskAssignRuleDOList, bpmTaskRespVOList, userDoMap, deptMap, | ||
| 273 | - taskVarMap); | ||
| 274 | - // 下个节点是网关(调用下面的方法) | ||
| 275 | - } else if (targetFlowElement instanceof ExclusiveGateway) { | ||
| 276 | - String defaultFlow = ((ExclusiveGateway)targetFlowElement).getDefaultFlow(); | ||
| 277 | - FlowElement nexFlowElement = getExclusiveGateway(targetFlowElement, taskVarMap, defaultFlow); | ||
| 278 | - getFlow(bpmnModel, nexFlowElement, tmpBpmTaskAssignRuleDOList, bpmTaskRespVOList, userDoMap, deptMap, | ||
| 279 | - taskVarMap); | ||
| 280 | - } | ||
| 281 | - } | ||
| 282 | - | ||
| 283 | - /** | ||
| 284 | - * 获取排他网关分支名称、分支表达式、下一级任务节点 | ||
| 285 | - * | ||
| 286 | - * @param flowElement 任务节点 | ||
| 287 | - * @param taskVarMap 审批数据 | ||
| 288 | - */ | ||
| 289 | - private FlowElement getExclusiveGateway(FlowElement flowElement, Map<String, Object> taskVarMap, | ||
| 290 | - String defaultFlow) { | ||
| 291 | - // 获取所有网关分支 | ||
| 292 | - List<SequenceFlow> targetFlows = ((ExclusiveGateway)flowElement).getOutgoingFlows(); | ||
| 293 | - Boolean elExpressionFlag = Boolean.FALSE; | ||
| 294 | - FlowElement sequenceFlowResult = null; | ||
| 295 | - FlowElement defaultSequenceFlow = null; | ||
| 296 | - // 循环每个网关分支 | ||
| 297 | - for (SequenceFlow sequenceFlow : targetFlows) { | ||
| 298 | - if (defaultFlow.equals(sequenceFlow.getId())) { | ||
| 299 | - defaultSequenceFlow = sequenceFlow.getTargetFlowElement(); | ||
| 300 | - continue; | ||
| 301 | - } | ||
| 302 | - elExpressionFlag = elExpression(sequenceFlow.getConditionExpression(), taskVarMap); | ||
| 303 | - if (elExpressionFlag) { | ||
| 304 | - // 获取下一个网关和节点数据 | ||
| 305 | - FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement(); | ||
| 306 | - // 网关的下个节点是用户节点 | ||
| 307 | - if (targetFlowElement instanceof UserTask) { | ||
| 308 | - sequenceFlowResult = targetFlowElement; | ||
| 309 | - break; | ||
| 310 | - } else if (targetFlowElement instanceof EndEvent) { | ||
| 311 | - log.info("排他网关的下一节点是EndEvent: 结束节点"); | ||
| 312 | - } else if (targetFlowElement instanceof ServiceTask) { | ||
| 313 | - log.info("排他网关的下一节点是ServiceTask: 内部方法"); | ||
| 314 | - } else if (targetFlowElement instanceof ExclusiveGateway) { | ||
| 315 | - defaultFlow = ((ExclusiveGateway)targetFlowElement).getDefaultFlow(); | ||
| 316 | - return getExclusiveGateway(targetFlowElement, taskVarMap, defaultFlow); | ||
| 317 | - } else if (targetFlowElement instanceof SubProcess) { | ||
| 318 | - log.info("排他网关的下一节点是SubProcess: 内部子流程"); | ||
| 319 | - } | ||
| 320 | - } | ||
| 321 | - } | ||
| 322 | - if (!elExpressionFlag) { | ||
| 323 | - if (defaultSequenceFlow instanceof UserTask) { | ||
| 324 | - sequenceFlowResult = defaultSequenceFlow; | ||
| 325 | - } else if (defaultSequenceFlow instanceof ExclusiveGateway) { | ||
| 326 | - defaultFlow = ((ExclusiveGateway)defaultSequenceFlow).getDefaultFlow(); | ||
| 327 | - return getExclusiveGateway(defaultSequenceFlow, taskVarMap, defaultFlow); | ||
| 328 | - } | ||
| 329 | - } | ||
| 330 | - return sequenceFlowResult; | ||
| 331 | - } | ||
| 332 | - | ||
| 333 | - /** | ||
| 334 | - * 网关分叉条件判断,网关分叉,必须要有默认出口 | ||
| 335 | - * | ||
| 336 | - * @param elExpression el表达式 | ||
| 337 | - * @param variableMap 流程所有变量 | ||
| 338 | - * | ||
| 339 | - * @return 返回true或false | ||
| 340 | - */ | ||
| 341 | - private Boolean elExpression(String elExpression, Map<String, Object> variableMap) { | ||
| 342 | - ExpressionFactory factory = new ExpressionFactoryImpl(); | ||
| 343 | - SimpleContext context = new SimpleContext(); | ||
| 344 | - for (String k : variableMap.keySet()) { | ||
| 345 | - if (variableMap.get(k) != null) { | ||
| 346 | - context.setVariable(k, | ||
| 347 | - factory.createValueExpression(variableMap.get(k), variableMap.get(k).getClass())); | ||
| 348 | - } | ||
| 349 | - } | ||
| 350 | - ValueExpression e = factory.createValueExpression(context, elExpression, Boolean.class); | ||
| 351 | - //el表达式和variables得到的结果 | ||
| 352 | - return (Boolean)e.getValue(context); | ||
| 353 | - } | ||
| 354 | -} |
yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/mapper/BpmActivityMapper.xml
| @@ -17,11 +17,6 @@ | @@ -17,11 +17,6 @@ | ||
| 17 | </foreach> | 17 | </foreach> |
| 18 | </delete> | 18 | </delete> |
| 19 | 19 | ||
| 20 | - <select id="listAll" resultType="cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmActivityDO"> | ||
| 21 | - SELECT * | ||
| 22 | - FROM act_hi_taskinst; | ||
| 23 | - </select> | ||
| 24 | - | ||
| 25 | <select id="listAllByProcInstIdAndDelete" | 20 | <select id="listAllByProcInstIdAndDelete" |
| 26 | resultType="cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmActivityDO"> | 21 | resultType="cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmActivityDO"> |
| 27 | SELECT id_ AS `id`, | 22 | SELECT id_ AS `id`, |
yudao-ui-admin/src/components/bpmnProcessDesigner/package/designer/ProcessViewer.vue
| @@ -116,10 +116,11 @@ export default { | @@ -116,10 +116,11 @@ export default { | ||
| 116 | let todoActivity = activityList.find(m => !m.endTime) // 找到待办的任务 | 116 | let todoActivity = activityList.find(m => !m.endTime) // 找到待办的任务 |
| 117 | let endActivity = activityList[activityList.length - 1] // 获得最后一个任务 | 117 | let endActivity = activityList[activityList.length - 1] // 获得最后一个任务 |
| 118 | // debugger | 118 | // debugger |
| 119 | - console.log(this.bpmnModeler.getDefinitions().rootElements[0].flowElements); | 119 | + // console.log(this.bpmnModeler.getDefinitions().rootElements[0].flowElements); |
| 120 | this.bpmnModeler.getDefinitions().rootElements[0].flowElements?.forEach(n => { | 120 | this.bpmnModeler.getDefinitions().rootElements[0].flowElements?.forEach(n => { |
| 121 | let activity = activityList.find(m => m.key === n.id) // 找到对应的活动 | 121 | let activity = activityList.find(m => m.key === n.id) // 找到对应的活动 |
| 122 | if (n.$type === 'bpmn:UserTask') { // 用户任务 | 122 | if (n.$type === 'bpmn:UserTask') { // 用户任务 |
| 123 | + debugger | ||
| 123 | if (!activity) { | 124 | if (!activity) { |
| 124 | return; | 125 | return; |
| 125 | } | 126 | } |
yudao-ui-admin/src/views/bpm/processInstance/detail.vue
| @@ -232,21 +232,27 @@ export default { | @@ -232,21 +232,27 @@ export default { | ||
| 232 | this.auditForms = []; | 232 | this.auditForms = []; |
| 233 | getTaskListByProcessInstanceId(this.id).then(response => { | 233 | getTaskListByProcessInstanceId(this.id).then(response => { |
| 234 | // 审批记录 | 234 | // 审批记录 |
| 235 | - this.tasks = response.data; | 235 | + this.tasks = []; |
| 236 | + // 移除已取消的审批 | ||
| 237 | + response.data.forEach(task => { | ||
| 238 | + if (task.result !== 4) { | ||
| 239 | + this.tasks.push(task); | ||
| 240 | + } | ||
| 241 | + }); | ||
| 236 | // 排序,将未完成的排在前面,已完成的排在后面; | 242 | // 排序,将未完成的排在前面,已完成的排在后面; |
| 237 | - // this.tasks.sort((a, b) => { | ||
| 238 | - // // 有已完成的情况,按照完成时间倒序 | ||
| 239 | - // if (a.endTime && b.endTime) { | ||
| 240 | - // return b.endTime - a.endTime; | ||
| 241 | - // } else if (a.endTime) { | ||
| 242 | - // return 1; | ||
| 243 | - // } else if (b.endTime) { | ||
| 244 | - // return -1; | ||
| 245 | - // // 都是未完成,按照创建时间倒序 | ||
| 246 | - // } else { | ||
| 247 | - // return b.createTime - a.createTime; | ||
| 248 | - // } | ||
| 249 | - // }); | 243 | + this.tasks.sort((a, b) => { |
| 244 | + // 有已完成的情况,按照完成时间倒序 | ||
| 245 | + if (a.endTime && b.endTime) { | ||
| 246 | + return b.endTime - a.endTime; | ||
| 247 | + } else if (a.endTime) { | ||
| 248 | + return 1; | ||
| 249 | + } else if (b.endTime) { | ||
| 250 | + return -1; | ||
| 251 | + // 都是未完成,按照创建时间倒序 | ||
| 252 | + } else { | ||
| 253 | + return b.createTime - a.createTime; | ||
| 254 | + } | ||
| 255 | + }); | ||
| 250 | 256 | ||
| 251 | // 需要审核的记录 | 257 | // 需要审核的记录 |
| 252 | const userId = store.getters.userId; | 258 | const userId = store.getters.userId; |