package org.jeecg.modules.flowable.service.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.google.common.collect.Lists; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.shiro.SecurityUtils; import org.flowable.bpmn.model.*; import org.flowable.bpmn.model.Process; import org.flowable.common.engine.api.FlowableException; import org.flowable.common.engine.api.FlowableObjectNotFoundException; import org.flowable.common.engine.impl.identity.Authentication; import org.flowable.engine.ProcessEngineConfiguration; import org.flowable.engine.history.HistoricActivityInstance; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.history.HistoricProcessInstanceQuery; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.Execution; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.engine.task.Comment; import org.flowable.identitylink.api.IdentityLinkType; import org.flowable.identitylink.api.history.HistoricIdentityLink; import org.flowable.image.ProcessDiagramGenerator; import org.flowable.task.api.DelegationState; import org.flowable.task.api.Task; import org.flowable.task.api.TaskQuery; import org.flowable.task.api.history.HistoricTaskInstance; import org.jeecg.common.api.vo.Result; import org.jeecg.common.system.vo.LoginUser; import org.jeecg.common.util.SpringContextUtils; import org.jeecg.modules.flowable.apithird.business.dto.FlowMyBusinessDto; import org.jeecg.modules.flowable.apithird.business.entity.FlowMyBusiness; import org.jeecg.modules.flowable.apithird.business.service.impl.FlowMyBusinessServiceImpl; import org.jeecg.modules.flowable.apithird.common.constant.ProcessConstants; import org.jeecg.modules.flowable.apithird.common.enums.FlowComment; import org.jeecg.modules.flowable.apithird.common.exception.CustomException; import org.jeecg.modules.flowable.apithird.entity.SysUser; import org.jeecg.modules.flowable.apithird.service.FlowCallBackServiceI; import org.jeecg.modules.flowable.apithird.service.IFlowThirdService; import org.jeecg.modules.flowable.domain.dto.FlowCommentDto; import org.jeecg.modules.flowable.domain.dto.FlowNextDto; import org.jeecg.modules.flowable.domain.dto.FlowTaskDto; import org.jeecg.modules.flowable.domain.dto.FlowViewerDto; import org.jeecg.modules.flowable.domain.vo.FlowTaskVo; import org.jeecg.modules.flowable.factory.FlowServiceFactory; import org.jeecg.modules.flowable.flow.CustomProcessDiagramGenerator; import org.jeecg.modules.flowable.flow.FindNextNodeUtil; import org.jeecg.modules.flowable.flow.FlowableUtils; import org.jeecg.modules.flowable.service.IFlowTaskService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.io.InputStream; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; /** **/ @Service @Slf4j @Transactional public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTaskService { @Resource private IFlowThirdService iFlowThirdService; @Autowired FlowMyBusinessServiceImpl flowMyBusinessService; /** * 完成任务 * * @param taskVo 请求实体参数 */ @Transactional(rollbackFor = Exception.class) @Override public Result complete(FlowTaskVo taskVo) { Task task = taskService.createTaskQuery().taskId(taskVo.getTaskId()).singleResult(); if (Objects.isNull(task)){ return Result.error("任务不存在"); } if(StringUtils.isNotEmpty(taskVo.getComment())){ task.setDescription(taskVo.getComment()); taskService.saveTask(task); } SysUser loginUser = iFlowThirdService.getLoginUser(); //判断用户是否有权限 if (!task.getAssignee().equals(loginUser.getUsername())){ return Result.error("当前用户无权限"); } if (DelegationState.PENDING.equals(task.getDelegationState())) { taskService.addComment(taskVo.getTaskId(), taskVo.getInstanceId(), FlowComment.DELEGATE.getType(), taskVo.getComment()); //taskService.resolveTask(taskVo.getTaskId(), taskVo.getValues()); } else { System.out.println("taskVo.getTaskId()--->taskVo.getInstanceId()--->FlowComment.NORMAL.getType()--->taskVo.getComment()"+taskVo.getTaskId() + "---" + taskVo.getInstanceId() + "---" + FlowComment.NORMAL.getType() + "---"+taskVo.getComment() ); taskService.addComment(taskVo.getTaskId(), taskVo.getInstanceId(), FlowComment.NORMAL.getType(), taskVo.getComment()); taskService.setAssignee(taskVo.getTaskId(), loginUser.getUsername()); } /*======================审批结束 回调以及关键数据保存======================*/ //业务数据id String dataId = taskVo.getDataId(); //如果保存数据前未调用必调的FlowCommonService.initActBusiness方法,就会有问题 FlowMyBusiness business = flowMyBusinessService.getByDataId(dataId); //spring容器类名 String serviceImplName = business.getServiceImplName(); FlowCallBackServiceI flowCallBackService = (FlowCallBackServiceI) SpringContextUtils.getBean(serviceImplName); // 流程变量 Map flowBeforeParamsValues = flowCallBackService.flowValuesOfTask(business.getTaskNameId(),taskVo.getValues()); //设置数据 Map values = taskVo.getValues(); if (MapUtil.isNotEmpty(flowBeforeParamsValues)){ // 业务层有设置变量,使用业务层的变量 values = flowBeforeParamsValues; } FlowNextDto nextFlowNode = this.getNextFlowNode(task.getId(), values); //下一个实例节点 if (DelegationState.PENDING.equals(task.getDelegationState())) { taskService.resolveTask(taskVo.getTaskId(), values); } else { taskService.complete(taskVo.getTaskId(), values); } List task2List = taskService.createTaskQuery().processInstanceId(business.getProcessInstanceId()).active().list(); Task task2 = null; if (CollUtil.isNotEmpty(task2List)){ task2 = task2List.get(0); } // 下个节点候选人 List beforeParamsCandidateUsernames = Lists.newArrayList(); if(task2!=null){ beforeParamsCandidateUsernames = flowCallBackService.flowCandidateUsernamesOfTask(task2.getTaskDefinitionKey(),taskVo.getValues()); } List candidateUsers = taskVo.getCandidateUsers(); if (CollUtil.isNotEmpty(candidateUsers)){ // 前端传入候选人 覆盖 beforeParamsCandidateUsernames = candidateUsers; } String doneUsers = business.getDoneUsers(); // 处理过流程的人 JSONArray doneUserList = new JSONArray(); if (StrUtil.isNotBlank(doneUsers)){ doneUserList = JSON.parseArray(doneUsers); } if (!doneUserList.contains(loginUser.getUsername())){ doneUserList.add(loginUser.getUsername()); } if (task2!=null && task.getTaskDefinitionKey().equals(task2.getTaskDefinitionKey())){ // * 当前节点是会签节点,没有走完 business.setTaskId(task2.getId()) // .setActStatus(ActStatus.doing) .setDoneUsers(doneUserList.toJSONString()) ; String todoUsersStr = business.getTodoUsers(); JSONArray todosArr = JSON.parseArray(todoUsersStr); // 删除后重写 for (Task task2One : task2List) { for (Object oldUser : todosArr) { taskService.deleteCandidateUser(task2One.getId(),oldUser.toString()); } } // 重写 if (CollUtil.isNotEmpty(beforeParamsCandidateUsernames)){ beforeParamsCandidateUsernames.remove(loginUser.getUsername()); // 业务层有指定候选人,覆盖 for (Task task2One : task2List) { for (String newUser : beforeParamsCandidateUsernames) { taskService.addCandidateUser(task2One.getId(),newUser); } } business.setTodoUsers(JSON.toJSONString(beforeParamsCandidateUsernames)); } else { todosArr.remove(loginUser.getUsername()); for (Task task2One : task2List) { for (Object oldUser : todosArr) { taskService.addCandidateUser(task2One.getId(),oldUser.toString()); } } business.setTodoUsers(todosArr.toJSONString()); } } else { // * 下一节点是会签节点 或 普通用户节点,逻辑一致 if (nextFlowNode!=null){ //**有下一个节点 UserTask nextTask = nextFlowNode.getUserTask(); //能够处理下个节点的候选人 List nextFlowNodeUserList = nextFlowNode.getUserList(); List collect_username = nextFlowNodeUserList.stream().map(SysUser::getUsername).collect(Collectors.toList()); if (CollUtil.isNotEmpty(candidateUsers)){ // 前端传入候选人 collect_username = candidateUsers; } business .setTaskId(task2.getId()) // .setActStatus(ActStatus.doing) .setTaskNameId(nextTask.getId()) .setTaskName(nextTask.getName()) .setPriority(nextTask.getPriority()) .setDoneUsers(doneUserList.toJSONString()) .setTodoUsers(JSON.toJSONString(collect_username)) ; // 删除后重写 for (Task task2One : task2List) { for (String oldUser : collect_username) { taskService.deleteCandidateUser(task2One.getId(),oldUser); } } if (CollUtil.isEmpty(candidateUsers)&&CollUtil.isNotEmpty(beforeParamsCandidateUsernames)){ // 前端没有传入候选人 && 业务层有指定候选人,覆盖 for (Task task2One : task2List) { for (String newUser : beforeParamsCandidateUsernames) { taskService.addCandidateUser(task2One.getId(),newUser); } } business.setTodoUsers(JSON.toJSONString(beforeParamsCandidateUsernames)); } else { for (Task task2One : task2List) { for (String oldUser : collect_username) { taskService.addCandidateUser(task2One.getId(),oldUser); } } } } else { // **没有下一个节点,流程已经结束了 business .setDoneUsers(doneUserList.toJSONString()) .setTodoUsers("") .setTaskId("") .setTaskNameId("") .setTaskName("") ; } } flowMyBusinessService.updateById(business); // 流程处理完后,进行回调业务层 business.setValues(values); if (flowCallBackService!=null)flowCallBackService.afterFlowHandle(business); return Result.OK(); } @Override @Transactional(rollbackFor = Exception.class) public Result completeByDateId(FlowTaskVo flowTaskVo){ return this.complete(flowTaskVo); } @Override public void taskRejectByDataId(FlowTaskVo flowTaskVo){ FlowMyBusiness business = flowMyBusinessService.getByDataId(flowTaskVo.getDataId()); flowTaskVo.setTaskId(business.getTaskId()); this.taskReject(flowTaskVo); } /** * 驳回任务 * * @param flowTaskVo */ @Override public void taskReject(FlowTaskVo flowTaskVo) { if (taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult().isSuspended()) { throw new CustomException("任务处于挂起状态"); } // 当前任务 task Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult(); // 获取流程定义信息 ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult(); // 获取所有节点信息 Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0); // 获取全部节点列表,包含子节点 Collection allElements = FlowableUtils.getAllElements(process.getFlowElements(), null); // 获取当前任务节点元素 FlowElement source = null; if (allElements != null) { for (FlowElement flowElement : allElements) { // 类型为用户节点 if (flowElement.getId().equals(task.getTaskDefinitionKey())) { // 获取节点信息 source = flowElement; } } } // 目的获取所有跳转到的节点 targetIds // 获取当前节点的所有父级用户任务节点 // 深度优先算法思想:延边迭代深入 List parentUserTaskList = FlowableUtils.iteratorFindParentUserTasks(source, null, null); if (parentUserTaskList == null || parentUserTaskList.size() == 0) { throw new CustomException("当前节点为初始任务节点,不能驳回"); } // 获取活动 ID 即节点 Key List parentUserTaskKeyList = new ArrayList<>(); parentUserTaskList.forEach(item -> parentUserTaskKeyList.add(item.getId())); // 获取全部历史节点活动实例,即已经走过的节点历史,数据采用开始时间升序 List historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery().processInstanceId(task.getProcessInstanceId()).orderByHistoricTaskInstanceStartTime().asc().list(); // 数据清洗,将回滚导致的脏数据清洗掉 List lastHistoricTaskInstanceList = FlowableUtils.historicTaskInstanceClean(allElements, historicTaskInstanceList); // 此时历史任务实例为倒序,获取最后走的节点 List targetIds = new ArrayList<>(); // 循环结束标识,遇到当前目标节点的次数 int number = 0; StringBuilder parentHistoricTaskKey = new StringBuilder(); for (String historicTaskInstanceKey : lastHistoricTaskInstanceList) { // 当会签时候会出现特殊的,连续都是同一个节点历史数据的情况,这种时候跳过 if (parentHistoricTaskKey.toString().equals(historicTaskInstanceKey)) { continue; } parentHistoricTaskKey = new StringBuilder(historicTaskInstanceKey); if (historicTaskInstanceKey.equals(task.getTaskDefinitionKey())) { number++; } // 在数据清洗后,历史节点就是唯一一条从起始到当前节点的历史记录,理论上每个点只会出现一次 // 在流程中如果出现循环,那么每次循环中间的点也只会出现一次,再出现就是下次循环 // number == 1,第一次遇到当前节点 // number == 2,第二次遇到,代表最后一次的循环范围 if (number == 2) { break; } // 如果当前历史节点,属于父级的节点,说明最后一次经过了这个点,需要退回这个点 if (parentUserTaskKeyList.contains(historicTaskInstanceKey)) { targetIds.add(historicTaskInstanceKey); } } // 目的获取所有需要被跳转的节点 currentIds // 取其中一个父级任务,因为后续要么存在公共网关,要么就是串行公共线路 UserTask oneUserTask = parentUserTaskList.get(0); // 获取所有正常进行的任务节点 Key,这些任务不能直接使用,需要找出其中需要撤回的任务 List runTaskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list(); List runTaskKeyList = new ArrayList<>(); runTaskList.forEach(item -> runTaskKeyList.add(item.getTaskDefinitionKey())); // 需驳回任务列表 List currentIds = new ArrayList<>(); // 通过父级网关的出口连线,结合 runTaskList 比对,获取需要撤回的任务 List currentUserTaskList = FlowableUtils.iteratorFindChildUserTasks(oneUserTask, runTaskKeyList, null, null); currentUserTaskList.forEach(item -> currentIds.add(item.getId())); // 规定:并行网关之前节点必须需存在唯一用户任务节点,如果出现多个任务节点,则并行网关节点默认为结束节点,原因为不考虑多对多情况 if (targetIds.size() > 1 && currentIds.size() > 1) { throw new CustomException("任务出现多对多情况,无法撤回"); } // 循环获取那些需要被撤回的节点的ID,用来设置驳回原因 List currentTaskIds = new ArrayList<>(); currentIds.forEach(currentId -> runTaskList.forEach(runTask -> { if (currentId.equals(runTask.getTaskDefinitionKey())) { currentTaskIds.add(runTask.getId()); } })); // 设置驳回意见 currentTaskIds.forEach(item -> taskService.addComment(item, task.getProcessInstanceId(), FlowComment.REJECT.getType(), flowTaskVo.getComment())); SysUser loginUser = iFlowThirdService.getLoginUser(); try { // 设置处理人 taskService.setAssignee(task.getId(), loginUser.getUsername()); // 如果父级任务多于 1 个,说明当前节点不是并行节点,原因为不考虑多对多情况 if (targetIds.size() > 1) { // 1 对 多任务跳转,currentIds 当前节点(1),targetIds 跳转到的节点(多) runtimeService.createChangeActivityStateBuilder() .processInstanceId(task.getProcessInstanceId()). moveSingleActivityIdToActivityIds(currentIds.get(0), targetIds).changeState(); } // 如果父级任务只有一个,因此当前任务可能为网关中的任务 if (targetIds.size() == 1) { // 1 对 1 或 多 对 1 情况,currentIds 当前要跳转的节点列表(1或多),targetIds.get(0) 跳转到的节点(1) runtimeService.createChangeActivityStateBuilder() .processInstanceId(task.getProcessInstanceId()) .moveActivityIdsToSingleActivityId(currentIds, targetIds.get(0)).changeState(); } /*======================驳回 回调以及关键数据保存======================*/ //业务数据id String dataId = flowTaskVo.getDataId(); if (dataId==null) return; //如果保存数据前未调用必调的FlowCommonService.initActBusiness方法,就会有问题 FlowMyBusiness business = flowMyBusinessService.getByDataId(dataId); // 驳回到了上一个节点等待处理 List task2List = taskService.createTaskQuery().processInstanceId(business.getProcessInstanceId()).active().list(); Task task2 = task2List.get(0); //spring容器类名 String serviceImplName = business.getServiceImplName(); FlowCallBackServiceI flowCallBackService = (FlowCallBackServiceI) SpringContextUtils.getBean(serviceImplName); Map values = flowTaskVo.getValues(); if (values ==null){ values = MapUtil.newHashMap(); values.put("dataId",dataId); } else { values.put("dataId",dataId); } List beforeParamsCandidateUsernames = flowCallBackService.flowCandidateUsernamesOfTask(task2.getTaskDefinitionKey(), values); //设置数据 String doneUsers = business.getDoneUsers(); // 处理过流程的人 JSONArray doneUserList = new JSONArray(); if (StrUtil.isNotBlank(doneUsers)){ doneUserList = JSON.parseArray(doneUsers); } if (!doneUserList.contains(loginUser.getUsername())){ doneUserList.add(loginUser.getUsername()); } business .setTaskId(task2.getId()) // .setActStatus(ActStatus.reject) .setTaskNameId(task2.getTaskDefinitionKey()) .setTaskName(task2.getName()) .setDoneUsers(doneUserList.toJSONString()) ; FlowElement targetElement = null; if (allElements != null) { for (FlowElement flowElement : allElements) { // 类型为用户节点 if (flowElement.getId().equals(task2.getTaskDefinitionKey())) { // 获取节点信息 targetElement = flowElement; } } } if (targetElement!=null){ UserTask targetTask = (UserTask) targetElement; business.setPriority(targetTask.getPriority()); if (StrUtil.equals(business.getTaskNameId(),ProcessConstants.START_NODE)){ // 开始节点。设置处理人为申请人 business.setTodoUsers(JSON.toJSONString(Lists.newArrayList(business.getProposer()))); taskService.setAssignee(business.getTaskId(),business.getProposer()); } else { List sysUserFromTask = getSysUserFromTask(targetTask); List collect_username = sysUserFromTask.stream().map(SysUser::getUsername).collect(Collectors.toList()); // 前端存入的候选人 List candidateUsers = flowTaskVo.getCandidateUsers(); if (CollUtil.isNotEmpty(candidateUsers)){ collect_username = candidateUsers; } business.setTodoUsers(JSON.toJSONString(collect_username)); // 删除后重写 for (Task task2One : task2List) { for (String oldUser : collect_username) { taskService.deleteCandidateUser(task2One.getId(),oldUser); } } if (CollUtil.isNotEmpty(beforeParamsCandidateUsernames)){ if (CollUtil.isNotEmpty(candidateUsers)){ beforeParamsCandidateUsernames = candidateUsers; } // 业务层有指定候选人,覆盖 for (Task task2One : task2List) { for (String newUser : beforeParamsCandidateUsernames) { taskService.addCandidateUser(task2One.getId(), newUser); } } business.setTodoUsers(JSON.toJSONString(beforeParamsCandidateUsernames)); } else { for (Task task2One : task2List) { for (String oldUser : collect_username) { taskService.addCandidateUser(task2One.getId(), oldUser); } } } } } flowMyBusinessService.updateById(business); // 流程处理完后,进行回调业务层 business.setValues(values); if (flowCallBackService!=null) flowCallBackService.afterFlowHandle(business); } catch (FlowableObjectNotFoundException e) { throw new CustomException("未找到流程实例,流程可能已发生变化"); } catch (FlowableException e) { throw new CustomException("无法取消或开始活动"); } } @Override public void taskReturnByDataId(FlowTaskVo flowTaskVo){ //如果保存数据前未调用必调的FlowCommonService.initActBusiness方法,就会有问题 FlowMyBusiness business = flowMyBusinessService.getByDataId(flowTaskVo.getDataId()); flowTaskVo.setTaskId(business.getTaskId()); taskReturn(flowTaskVo); } /** * 退回任务 * * @param flowTaskVo 请求实体参数 */ @Transactional(rollbackFor = Exception.class) @Override public void taskReturn(FlowTaskVo flowTaskVo) { if (taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult().isSuspended()) { throw new CustomException("任务处于挂起状态"); } // 当前任务 task Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult(); // 获取流程定义信息 ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult(); // 获取所有节点信息 Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0); // 获取全部节点列表,包含子节点 Collection allElements = FlowableUtils.getAllElements(process.getFlowElements(), null); // 获取当前任务节点元素 FlowElement source = null; // 获取跳转的节点元素 FlowElement target = null; if (allElements != null) { for (FlowElement flowElement : allElements) { // 当前任务节点元素 if (flowElement.getId().equals(task.getTaskDefinitionKey())) { source = flowElement; } // 跳转的节点元素 if (flowElement.getId().equals(flowTaskVo.getTargetKey())) { target = flowElement; } } } // 从当前节点向前扫描 // 如果存在路线上不存在目标节点,说明目标节点是在网关上或非同一路线上,不可跳转 // 否则目标节点相对于当前节点,属于串行 Boolean isSequential = FlowableUtils.iteratorCheckSequentialReferTarget(source, flowTaskVo.getTargetKey(), null, null); if (!isSequential) { throw new CustomException("当前节点相对于目标节点,不属于串行关系,无法回退"); } // 获取所有正常进行的任务节点 Key,这些任务不能直接使用,需要找出其中需要撤回的任务 List runTaskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list(); List runTaskKeyList = new ArrayList<>(); runTaskList.forEach(item -> runTaskKeyList.add(item.getTaskDefinitionKey())); // 需退回任务列表 List currentIds = new ArrayList<>(); // 通过父级网关的出口连线,结合 runTaskList 比对,获取需要撤回的任务 List currentUserTaskList = FlowableUtils.iteratorFindChildUserTasks(target, runTaskKeyList, null, null); currentUserTaskList.forEach(item -> { currentIds.add(item.getId()); }); // 循环获取那些需要被撤回的节点的ID,用来设置驳回原因 List currentTaskIds = new ArrayList<>(); currentIds.forEach(currentId -> runTaskList.forEach(runTask -> { if (currentId.equals(runTask.getTaskDefinitionKey())) { currentTaskIds.add(runTask.getId()); } })); // 设置回退意见 for (String currentTaskId : currentTaskIds) { taskService.addComment(currentTaskId, task.getProcessInstanceId(), FlowComment.REBACK.getType(), flowTaskVo.getComment()); } SysUser loginUser = iFlowThirdService.getLoginUser(); try { // 设置处理人 taskService.setAssignee(task.getId(), loginUser.getUsername()); // 1 对 1 或 多 对 1 情况,currentIds 当前要跳转的节点列表(1或多),targetKey 跳转到的节点(1) runtimeService.createChangeActivityStateBuilder() .processInstanceId(task.getProcessInstanceId()) .moveActivityIdsToSingleActivityId(currentIds, flowTaskVo.getTargetKey()).changeState(); /*======================退回 回调以及关键数据保存======================*/ //业务数据id String dataId = flowTaskVo.getDataId(); if (dataId==null) return; //如果保存数据前未调用必调的FlowCommonService.initActBusiness方法,就会有问题 FlowMyBusiness business = flowMyBusinessService.getByDataId(dataId); //spring容器类名 String serviceImplName = business.getServiceImplName(); FlowCallBackServiceI flowCallBackService = (FlowCallBackServiceI) SpringContextUtils.getBean(serviceImplName); //设置数据 String doneUsers = business.getDoneUsers(); // 处理过流程的人 JSONArray doneUserList = new JSONArray(); if (StrUtil.isNotBlank(doneUsers)){ doneUserList = JSON.parseArray(doneUsers); } if (!doneUserList.contains(loginUser.getUsername())){ doneUserList.add(loginUser.getUsername()); } //**跳转到目标节点 List task2List = taskService.createTaskQuery().processInstanceId(business.getProcessInstanceId()).active().list(); Task targetTask = task2List.get(0); business .setTaskId(targetTask.getId()) // .setActStatus(ActStatus.reject) .setTaskNameId(targetTask.getTaskDefinitionKey()) .setTaskName(targetTask.getName()) .setPriority(targetTask.getPriority()+"") .setDoneUsers(doneUserList.toJSONString()) ; if (target!=null){ UserTask target2 = (UserTask) target; business.setPriority(target2.getPriority()); if (StrUtil.equals(business.getTaskNameId(),ProcessConstants.START_NODE)){ // 开始节点。设置处理人为申请人 business.setTodoUsers(JSON.toJSONString(Lists.newArrayList(business.getProposer()))); taskService.setAssignee(business.getTaskId(),business.getProposer()); } else { List sysUserFromTask = getSysUserFromTask(target2); List collect_username = sysUserFromTask.stream().map(SysUser::getUsername).collect(Collectors.toList()); List candidateUsers = flowTaskVo.getCandidateUsers(); if (CollUtil.isNotEmpty(candidateUsers)){ collect_username = candidateUsers; } business.setTodoUsers(JSON.toJSONString(collect_username)); // 删除后重写 for (Task task2One : task2List) { for (String oldUser : collect_username) { taskService.deleteCandidateUser(task2One.getId(),oldUser); } } Map values = flowTaskVo.getValues(); if (values==null){ values = MapUtil.newHashMap(); values.put("dataId",dataId); } else { values.put("dataId",dataId); } List beforeParamsCandidateUsernames = flowCallBackService.flowCandidateUsernamesOfTask(targetTask.getTaskDefinitionKey(), values); if (CollUtil.isNotEmpty(beforeParamsCandidateUsernames)){ if (CollUtil.isNotEmpty(candidateUsers)){ beforeParamsCandidateUsernames = candidateUsers; } // 业务层有指定候选人,覆盖 for (Task task2One : task2List) { for (String newUser : beforeParamsCandidateUsernames) { taskService.addCandidateUser(task2One.getId(),newUser); } } business.setTodoUsers(JSON.toJSONString(beforeParamsCandidateUsernames)); } else { for (Task task2One : task2List) { for (String oldUser : collect_username) { taskService.addCandidateUser(task2One.getId(), oldUser); } } } } } flowMyBusinessService.updateById(business); // 流程处理完后,进行回调业务层 business.setValues(flowTaskVo.getValues()); if (flowCallBackService!=null) flowCallBackService.afterFlowHandle(business); } catch (FlowableObjectNotFoundException e) { throw new CustomException("未找到流程实例,流程可能已发生变化"); } catch (FlowableException e) { throw new CustomException("无法取消或开始活动"); } } @Override public Result findReturnTaskListByDataId(FlowTaskVo flowTaskVo) { FlowMyBusiness business = flowMyBusinessService.getByDataId(flowTaskVo.getDataId()); flowTaskVo.setTaskId(business.getTaskId()); return findReturnTaskList(flowTaskVo); } /** * 结束流程 * @param processInstanceId 流程实例 ID * @param deleteReason 定义删除原因 */ public Result end(String processInstanceId, String deleteReason) { try { // 强制结束流程实例 runtimeService.deleteProcessInstance(processInstanceId, deleteReason); // 删除关联流程的业务 FlowMyBusiness flowMyBusiness=flowMyBusinessService.getFlowMyBusiness(processInstanceId); flowMyBusinessService.removeById(flowMyBusiness.getId()); System.out.println("Process instance with ID " + processInstanceId + " has been forcefully ended."); } catch (Exception e) { System.err.println("Failed to force end process instance: " + e.getMessage()); } // 关闭流程引擎 processEngine.close(); return Result.OK("流程已结束"); } /** * 获取所有可回退的节点 * * @param flowTaskVo * @return */ @Override public Result findReturnTaskList(FlowTaskVo flowTaskVo) { // 当前任务 task Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult(); // 获取流程定义信息 ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult(); // 获取所有节点信息,暂不考虑子流程情况 Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0); Collection flowElements = process.getFlowElements(); // 获取当前任务节点元素 UserTask source = null; if (flowElements != null) { for (FlowElement flowElement : flowElements) { // 类型为用户节点 if (flowElement.getId().equals(task.getTaskDefinitionKey())) { source = (UserTask) flowElement; } } } // 获取节点的所有路线 List> roads = FlowableUtils.findRoad(source, null, null, null); // 可回退的节点列表 List userTaskList = new ArrayList<>(); for (List road : roads) { if (userTaskList.size() == 0) { // 还没有可回退节点直接添加 userTaskList = road; } else { // 如果已有回退节点,则比对取交集部分 userTaskList.retainAll(road); } } return Result.OK(userTaskList); } /** * 删除任务 * * @param flowTaskVo 请求实体参数 */ @Override public void deleteTask(FlowTaskVo flowTaskVo) { // todo 待确认删除任务是物理删除任务 还是逻辑删除,让这个任务直接通过? taskService.deleteTask(flowTaskVo.getTaskId(),flowTaskVo.getComment()); } /** * 认领/签收任务 * * @param flowTaskVo 请求实体参数 */ @Override @Transactional(rollbackFor = Exception.class) public void claim(FlowTaskVo flowTaskVo) { taskService.claim(flowTaskVo.getTaskId(), flowTaskVo.getUserId()); } /** * 取消认领/签收任务 * * @param flowTaskVo 请求实体参数 */ @Override @Transactional(rollbackFor = Exception.class) public void unClaim(FlowTaskVo flowTaskVo) { taskService.unclaim(flowTaskVo.getTaskId()); } /** * 委派任务 * * @param flowTaskVo 请求实体参数 */ @Override @Transactional(rollbackFor = Exception.class) public void delegateTask(FlowTaskVo flowTaskVo) { taskService.delegateTask(flowTaskVo.getTaskId(), flowTaskVo.getAssignee()); } /** * 转办任务 * * @param flowTaskVo 请求实体参数 */ @Override @Transactional(rollbackFor = Exception.class) public void assignTask(FlowTaskVo flowTaskVo) { taskService.setAssignee(flowTaskVo.getTaskId(),flowTaskVo.getAssignee()); } /** * 我发起的流程 * * @param pageNum * @param pageSize * @return */ @Override public Result myProcess(Integer pageNum, Integer pageSize) { Page page = new Page<>(); String username = iFlowThirdService.getLoginUser().getUsername(); HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery() .startedBy(username) .orderByProcessInstanceStartTime() .desc(); List historicProcessInstances = historicProcessInstanceQuery.listPage((pageNum - 1)*pageSize, pageSize); page.setTotal(historicProcessInstanceQuery.count()); List flowList = new ArrayList<>(); for (HistoricProcessInstance hisIns : historicProcessInstances) { FlowTaskDto flowTask = new FlowTaskDto(); flowTask.setCreateTime(hisIns.getStartTime()); flowTask.setFinishTime(hisIns.getEndTime()); flowTask.setProcInsId(hisIns.getId()); // 计算耗时 if (Objects.nonNull(hisIns.getEndTime())) { long time = hisIns.getEndTime().getTime() - hisIns.getStartTime().getTime(); flowTask.setDuration(getDate(time)); } else { long time = System.currentTimeMillis() - hisIns.getStartTime().getTime(); flowTask.setDuration(getDate(time)); } // 流程定义信息 ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() .processDefinitionId(hisIns.getProcessDefinitionId()) .singleResult(); flowTask.setDeployId(pd.getDeploymentId()); flowTask.setProcDefName(pd.getName()); flowTask.setProcDefVersion(pd.getVersion()); flowTask.setCategory(pd.getCategory()); flowTask.setProcDefVersion(pd.getVersion()); // 当前所处流程 todo: 本地启动放开以下注释 List taskList = taskService.createTaskQuery().processInstanceId(hisIns.getId()).list(); if (CollectionUtils.isNotEmpty(taskList)) { flowTask.setTaskId(taskList.get(0).getId()); } else { List historicTaskInstance = historyService.createHistoricTaskInstanceQuery().processInstanceId(hisIns.getId()).orderByHistoricTaskInstanceEndTime().desc().list(); flowTask.setTaskId(historicTaskInstance.get(0).getId()); } flowList.add(flowTask); } page.setRecords(flowList); return Result.OK(page); } /** * 取消申请 * * @param flowTaskVo * @return */ @Override public Result stopProcess(FlowTaskVo flowTaskVo) { List task = taskService.createTaskQuery().processInstanceId(flowTaskVo.getInstanceId()).list(); if (CollectionUtils.isEmpty(task)) { throw new CustomException("流程未启动或已执行完成,取消申请失败"); } SysUser loginUser = iFlowThirdService.getLoginUser(); ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(flowTaskVo.getInstanceId()).singleResult(); BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId()); if (Objects.nonNull(bpmnModel)) { Process process = bpmnModel.getMainProcess(); List endNodes = process.findFlowElementsOfType(EndEvent.class, false); if (CollectionUtils.isNotEmpty(endNodes)) { Authentication.setAuthenticatedUserId(loginUser.getUsername()); taskService.addComment(task.get(0).getId(), processInstance.getProcessInstanceId(), FlowComment.STOP.getType(), StringUtils.isBlank(flowTaskVo.getComment()) ? "取消申请" : flowTaskVo.getComment()); String endId = endNodes.get(0).getId(); List executions = runtimeService.createExecutionQuery().parentId(processInstance.getProcessInstanceId()).list(); List executionIds = new ArrayList<>(); executions.forEach(execution -> executionIds.add(execution.getId())); runtimeService.createChangeActivityStateBuilder().moveExecutionsToSingleActivityId(executionIds, endId).changeState(); } } return Result.OK(); } /** * 撤回流程 todo 目前存在错误 * * @param flowTaskVo * @return */ @Override public Result revokeProcess(FlowTaskVo flowTaskVo) { Task task = taskService.createTaskQuery().processInstanceId(flowTaskVo.getInstanceId()).singleResult(); if (task == null) { throw new CustomException("流程未启动或已执行完成,无法撤回"); } LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); List htiList = historyService.createHistoricTaskInstanceQuery() .processInstanceId(task.getProcessInstanceId()) .orderByTaskCreateTime() .asc() .list(); String myTaskId = null; HistoricTaskInstance myTask = null; for (HistoricTaskInstance hti : htiList) { if (loginUser.getUsername().equals(hti.getAssignee())) { myTaskId = hti.getId(); myTask = hti; break; } } if (null == myTaskId) { throw new CustomException("该任务非当前用户提交,无法撤回"); } String processDefinitionId = myTask.getProcessDefinitionId(); BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId); //变量 // Map variables = runtimeService.getVariableInstances(currentTask.getExecutionId()); String myActivityId = null; List haiList = historyService.createHistoricActivityInstanceQuery() .executionId(myTask.getExecutionId()).finished().list(); for (HistoricActivityInstance hai : haiList) { if (myTaskId.equals(hai.getTaskId())) { myActivityId = hai.getActivityId(); break; } } FlowNode myFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(myActivityId); Execution execution = runtimeService.createExecutionQuery().executionId(task.getExecutionId()).singleResult(); String activityId = execution.getActivityId(); FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityId); //记录原活动方向 List oriSequenceFlows = new ArrayList<>(flowNode.getOutgoingFlows()); return Result.OK(); } /** * 判断多个任务是否处于同一流程节点 * @param taskIds 逗号分隔的任务ID字符串 * @return 统一结果封装 */ @Override public Result isSameNode(String taskIds) { // 1. 参数校验 if (StringUtils.isBlank(taskIds)) { return Result.error("任务ID不能为空"); } // 2. 分割任务ID String[] taskIdArray = taskIds.split(","); if (taskIdArray.length == 0) { return Result.error("未提供有效的任务ID"); } // 3. 单任务直接返回true if (taskIdArray.length == 1) { return Result.ok(true); } // 4. 多任务检查逻辑 String referenceNodeId = null; String currentNodeId = null; for (String taskId : taskIdArray) { // 4.1 查询任务实例 Task task = taskService.createTaskQuery() .taskId(taskId.trim()) .singleResult(); // 4.2 任务不存在处理 if (task == null) { return Result.error("任务不存在: " + taskId); } // 4.3 获取节点标识(TaskDefinitionKey) currentNodeId = task.getTaskDefinitionKey(); // 4.4 首次遍历初始化参考节点 if (referenceNodeId == null) { referenceNodeId = currentNodeId; continue; } // 4.5 节点不一致直接返回 if (!referenceNodeId.equals(currentNodeId)) { return Result.ok("节点不一致"); } } // 5. 所有任务节点一致 return Result.ok(currentNodeId); } /** * 代办任务列表 * * @param pageNum 当前页码 * @param pageSize 每页条数 * @return */ @Override public Result todoList(Integer pageNum, Integer pageSize) { Page page = new Page<>(); String username = iFlowThirdService.getLoginUser().getUsername(); TaskQuery taskQuery = taskService.createTaskQuery() .active() .includeProcessVariables() .taskAssignee(username) .orderByTaskCreateTime().desc(); page.setTotal(taskQuery.count()); List taskList = taskQuery.listPage((pageNum - 1)*pageSize, pageSize); List flowList = new ArrayList<>(); for (Task task : taskList) { FlowTaskDto flowTask = new FlowTaskDto(); // 当前流程信息 flowTask.setTaskId(task.getId()); flowTask.setTaskDefKey(task.getTaskDefinitionKey()); flowTask.setCreateTime(task.getCreateTime()); flowTask.setProcDefId(task.getProcessDefinitionId()); flowTask.setTaskName(task.getName()); // 流程定义信息 ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() .processDefinitionId(task.getProcessDefinitionId()) .singleResult(); flowTask.setDeployId(pd.getDeploymentId()); flowTask.setProcDefName(pd.getName()); flowTask.setProcDefVersion(pd.getVersion()); flowTask.setProcInsId(task.getProcessInstanceId()); // 流程发起人信息 HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() .processInstanceId(task.getProcessInstanceId()) .singleResult(); SysUser startUser = iFlowThirdService.getUserByUsername(historicProcessInstance.getStartUserId()); List departNamesByUsername = iFlowThirdService.getDepartNamesByUsername(historicProcessInstance.getStartUserId()); flowTask.setStartUserId(startUser.getUsername()); flowTask.setStartUserName(startUser.getRealname()); flowTask.setStartDeptName(CollUtil.join(departNamesByUsername,",")); flowList.add(flowTask); } page.setRecords(flowList); return Result.OK(page); } /** * 已办任务列表 * * @param pageNum 当前页码 * @param pageSize 每页条数 * @return */ @Override public Result finishedList(Integer pageNum, Integer pageSize, FlowMyBusinessDto flowMyBusinessDto) { //修改查询,添加查询条件 Page page = new Page(pageNum, pageSize); String username = iFlowThirdService.getLoginUser().getUsername(); flowMyBusinessDto.setCurrentUser(username); List list = flowMyBusinessService.ListMyBusiness(flowMyBusinessDto); list.forEach(flowTaskDto -> { // 流程发起人信息 HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() .processInstanceId(flowTaskDto.getProcInsId()) .singleResult(); if(historicProcessInstance != null) { SysUser startUser = iFlowThirdService.getUserByUsername(historicProcessInstance.getStartUserId()); if(startUser == null) { flowTaskDto.setStartUserId(""); flowTaskDto.setStartUserName(""); }else { flowTaskDto.setStartUserId(startUser.getUsername()); flowTaskDto.setStartUserName(startUser.getRealname()); } List departNamesByUsername = iFlowThirdService.getDepartNamesByUsername(historicProcessInstance.getStartUserId()); flowTaskDto.setStartDeptName(CollUtil.join(departNamesByUsername,",")); } }); IPage flowTaskDtoIPage = new Page<>(); flowTaskDtoIPage.setRecords(list); flowTaskDtoIPage.setTotal(page.getTotal()); return Result.OK(flowTaskDtoIPage); } private static Predicate distinctByKey(Function keyExtractor) { Set seen = ConcurrentHashMap.newKeySet(); return t -> seen.add(keyExtractor.apply(t)); } /** * 流程历史流转记录 * * @param dataId 流程数据Id * @return */ @Override public Result flowRecord(String dataId) { FlowMyBusiness business = flowMyBusinessService.getByDataId(dataId); String procInsId = business.getProcessInstanceId(); Map map = new HashMap(); if (StringUtils.isNotBlank(procInsId)) { List list = historyService .createHistoricActivityInstanceQuery() .processInstanceId(procInsId) .orderByHistoricActivityInstanceStartTime() .desc().list(); List hisFlowList = new ArrayList<>(); for (HistoricActivityInstance histIns : list) { if (StringUtils.isNotBlank(histIns.getTaskId())) { FlowTaskDto flowTask = new FlowTaskDto(); flowTask.setTaskId(histIns.getTaskId()); flowTask.setTaskName(histIns.getActivityName()); flowTask.setTaskDefKey(histIns.getActivityId()); flowTask.setCreateTime(histIns.getStartTime()); flowTask.setFinishTime(histIns.getEndTime()); if (StringUtils.isNotBlank(histIns.getAssignee())) { SysUser sysUser = iFlowThirdService.getUserByUsername(histIns.getAssignee()); flowTask.setAssigneeId(sysUser.getUsername()); flowTask.setAssigneeName(sysUser.getRealname()); List departNamesByUsername = iFlowThirdService.getDepartNamesByUsername(histIns.getAssignee()); flowTask.setDeptName(CollUtil.join(departNamesByUsername,",")); if (StrUtil.equals(histIns.getActivityId(),ProcessConstants.START_NODE)){ // 开始节点,把候选人设置为发起人,这个值已被其他地方设置过,与实际办理人一致即可 flowTask.setCandidate(sysUser.getRealname()); } } // 展示审批人员 List linksForTask = historyService.getHistoricIdentityLinksForTask(histIns.getTaskId()); StringBuilder stringBuilder = new StringBuilder(); for (HistoricIdentityLink identityLink : linksForTask) { if (IdentityLinkType.CANDIDATE.equals(identityLink.getType())) { if (StringUtils.isNotBlank(identityLink.getUserId())) { SysUser sysUser = iFlowThirdService.getUserByUsername(identityLink.getUserId()); stringBuilder.append(sysUser.getRealname()).append(","); } /*已经全部设置到 CANDIDATE 了,不拿组了*/ /*if (StringUtils.isNotBlank(identityLink.getGroupId())) { List allRole = iFlowThirdService.getAllRole(); SysRole sysRole = allRole.stream().filter(o -> StringUtils.equals(identityLink.getGroupId(), o.getId())).findAny().orElse(new SysRole()); stringBuilder.append(sysRole.getRoleName()).append(","); }*/ } } if (StringUtils.isNotBlank(stringBuilder)) { flowTask.setCandidate(stringBuilder.substring(0, stringBuilder.length() - 1)); } flowTask.setDuration(histIns.getDurationInMillis() == null || histIns.getDurationInMillis() == 0 ? null : getDate(histIns.getDurationInMillis())); // 获取意见评论内容 List commentList = taskService.getProcessInstanceComments(histIns.getProcessInstanceId()); commentList.forEach(comment -> { if (histIns.getTaskId().equals(comment.getTaskId())) { flowTask.setComment(FlowCommentDto.builder().type(comment.getType()).comment(comment.getFullMessage()).build()); } }); hisFlowList.add(flowTask); } } map.put("flowList", hisFlowList); } // 获取初始化表单 String serviceImplName = business.getServiceImplName(); FlowCallBackServiceI flowCallBackService = (FlowCallBackServiceI) SpringContextUtils.getBean(serviceImplName); // 流程处理完后,进行回调业务层 if (flowCallBackService!=null){ Object businessDataById = flowCallBackService.getBusinessDataById(dataId); map.put("formData",businessDataById); } return Result.OK(map); } /** * 根据任务ID查询挂载的表单信息 * * @param taskId 任务Id * @return */ @Override public Task getTaskForm(String taskId) { Task task = taskService.createTaskQuery().taskId(taskId).singleResult(); return task; } /** * 获取流程过程图 * * @param processId * @return */ @Override public InputStream diagram(String processId) { String processDefinitionId; // 获取当前的流程实例 ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult(); // 如果流程已经结束,则得到结束节点 if (Objects.isNull(processInstance)) { HistoricProcessInstance pi = historyService.createHistoricProcessInstanceQuery().processInstanceId(processId).singleResult(); processDefinitionId = pi.getProcessDefinitionId(); } else {// 如果流程没有结束,则取当前活动节点 // 根据流程实例ID获得当前处于活动状态的ActivityId合集 ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult(); processDefinitionId = pi.getProcessDefinitionId(); } // 获得活动的节点 List highLightedFlowList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processId).orderByHistoricActivityInstanceStartTime().asc().list(); List highLightedFlows = new ArrayList<>(); List highLightedNodes = new ArrayList<>(); //高亮线 for (HistoricActivityInstance tempActivity : highLightedFlowList) { if ("sequenceFlow".equals(tempActivity.getActivityType())) { //高亮线 highLightedFlows.add(tempActivity.getActivityId()); } else { //高亮节点 highLightedNodes.add(tempActivity.getActivityId()); } } //获取流程图 BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId); ProcessEngineConfiguration configuration = processEngine.getProcessEngineConfiguration(); //获取自定义图片生成器 ProcessDiagramGenerator diagramGenerator = new CustomProcessDiagramGenerator(); InputStream in = diagramGenerator.generateDiagram(bpmnModel, "png", highLightedNodes, highLightedFlows, configuration.getActivityFontName(), configuration.getLabelFontName(), configuration.getAnnotationFontName(), configuration.getClassLoader(), 1.0, true); return in; } /** * 获取流程执行过程 * * @param procInsId * @return */ @Override public List getFlowViewer(String procInsId) { List flowViewerList = new ArrayList<>(); FlowViewerDto flowViewerDto; // 获得活动的节点 List hisActIns = historyService.createHistoricActivityInstanceQuery() .processInstanceId(procInsId) .orderByHistoricActivityInstanceStartTime() .asc().list(); for (HistoricActivityInstance activityInstance : hisActIns) { if (!"sequenceFlow".equals(activityInstance.getActivityType())) { flowViewerDto = new FlowViewerDto(); flowViewerDto.setKey(activityInstance.getActivityId()); flowViewerDto.setCompleted(!Objects.isNull(activityInstance.getEndTime())); for (FlowViewerDto viewerDto : flowViewerList) { String key = viewerDto.getKey(); if (key.equals(flowViewerDto.getKey())){ // 重复删除后面更新 flowViewerList.remove(viewerDto); break; } } flowViewerList.add(flowViewerDto); } } return flowViewerList; } @Override public List getFlowViewerByDataId(String dataId) { LambdaQueryWrapper flowMyBusinessLambdaQueryWrapper = new LambdaQueryWrapper<>(); flowMyBusinessLambdaQueryWrapper.eq(FlowMyBusiness::getDataId,dataId) ; //如果保存数据前未调用必调的FlowCommonService.initActBusiness方法,就会有问题 FlowMyBusiness business = flowMyBusinessService.getOne(flowMyBusinessLambdaQueryWrapper); // 1.执行过的步骤 List flowViewers = this.getFlowViewer(business.getProcessInstanceId()); // 2.获取所有节点信息,根据所有节点 按顺序 和执行过的比较,驳回的节点就被跳过 Process process = repositoryService.getBpmnModel(business.getProcessDefinitionId()).getProcesses().get(0); List flowElements = Lists.newArrayList(process.getFlowElements()); // 获取当前任务节点元素 List reflowViewers = Lists.newArrayList(); // *顺序的Key List orderKeys = Lists.newArrayList(); if (flowElements != null) { for (FlowElement flowElement : flowElements) { try { // 开始节点 StartEvent stev = (StartEvent) flowElement; //第一个key节点, String firstKey = stev.getId(); orderKeys.add(firstKey); //顺序获取节点 this.appendKeys(orderKeys, firstKey,flowElements); } catch (Exception e) { break; } } for (String key : orderKeys) { Optional any = flowViewers.stream().filter(o -> StrUtil.equals(o.getKey(), key)).findAny(); if(any.isPresent()){ FlowViewerDto viewerDto = any.get(); reflowViewers.add(viewerDto); if (!viewerDto.isCompleted()){ // 已到正在等待执行的节点,后面的不要了 break; } } } } for (FlowViewerDto flowViewer : flowViewers) { boolean present = reflowViewers.stream().filter(o -> StrUtil.equals(o.getKey(), flowViewer.getKey())).findAny().isPresent(); flowViewer.setBack(!present); } //return reflowViewers; return flowViewers; } /** * 顺序抽取节点 * @param orderKeys 容器 * @param sourceKey 源 * @param flowElements 所有的节点对象 */ private void appendKeys(List orderKeys, String sourceKey, List flowElements) { for (FlowElement flowElement : flowElements) { try { SequenceFlow sf = (SequenceFlow) flowElement; String sourceRef = sf.getSourceRef(); String targetRef = sf.getTargetRef(); if (sourceKey.equals(sourceRef)&&targetRef!=null){ orderKeys.add(targetRef); this.appendKeys(orderKeys,targetRef,flowElements); } } catch (Exception e) { continue; } } } /** * 获取流程变量 * * @param taskId * @return */ @Override public Result processVariables(String taskId) { // 流程变量 HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().includeProcessVariables().finished().taskId(taskId).singleResult(); if (Objects.nonNull(historicTaskInstance)) { return Result.OK(historicTaskInstance.getProcessVariables()); } else { Map variables = taskService.getVariables(taskId); return Result.OK(variables); } } /** * 获取下一节点 * * @param flowTaskVo 任务 * @return */ @Override public Result getNextFlowNode(FlowTaskVo flowTaskVo) { // todo 似乎逻辑未写完,待检查 FlowNextDto flowNextDto = this.getNextFlowNode(flowTaskVo.getTaskId(), flowTaskVo.getValues()); if (flowNextDto==null) { return Result.OK("流程已完结", null); } return Result.OK(flowNextDto); } /** * 获取下一个节点信息,流程定义上的节点信息 * @param taskId 当前节点id * @param values 流程变量 * @return 如果返回null,表示没有下一个节点,流程结束 */ public FlowNextDto getNextFlowNode(String taskId, Map values) { //当前节点 Task task = taskService.createTaskQuery().taskId(taskId).singleResult(); if (Objects.nonNull(task)) { // 下个任务节点 List nextUserTask = FindNextNodeUtil.getNextUserTasks(repositoryService, task, values); if (CollectionUtils.isNotEmpty(nextUserTask)) { FlowNextDto flowNextDto = new FlowNextDto(); for (UserTask userTask : nextUserTask) { flowNextDto.setUserTask(userTask); //待办人员 List sysUserFromTask = this.getSysUserFromTask(userTask); flowNextDto.setUserList(sysUserFromTask); MultiInstanceLoopCharacteristics multiInstance = userTask.getLoopCharacteristics(); if (Objects.nonNull(multiInstance)) { // 会签 多实例 String collectionString = multiInstance.getInputDataItem(); Object colObj = values.get(collectionString); List userNameList = null; if(colObj!=null){ userNameList = (List) colObj; } if (CollUtil.isNotEmpty(userNameList)){ // 待办人员从变量中获取 否则就是节点中配置的用户 sysUserFromTask List userList = Lists.newArrayList(); for (String username : userNameList) { SysUser userByUsername = iFlowThirdService.getUserByUsername(username); if (userByUsername==null){ throw new CustomException(username + " 用户名未找到"); } else { userList.add(userByUsername); } } flowNextDto.setUserList(userList); } else { // 变量中没有传入,写入节点中配置的用户 List collect_username = sysUserFromTask.stream().map(SysUser::getUsername).collect(Collectors.toList()); values.put(collectionString,collect_username); } } else { // todo 读取自定义节点属性做些啥? //String dataType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_DATA_TYPE); String userType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_USER_TYPE); } } return flowNextDto; } } return null; } public List getSysUserFromTask(UserTask userTask) { String assignee = userTask.getAssignee(); if (StrUtil.isNotBlank(assignee)){ // 指定单人 SysUser userByUsername = iFlowThirdService.getUserByUsername(assignee); return Lists.newArrayList(userByUsername); } List candidateUsers = userTask.getCandidateUsers(); if (CollUtil.isNotEmpty(candidateUsers)){ // 指定多人 List list = iFlowThirdService.getAllUser(); return list.stream().filter(o->candidateUsers.contains(o.getUsername())).collect(Collectors.toList()); } List candidateGroups = userTask.getCandidateGroups(); if (CollUtil.isNotEmpty(candidateGroups)){ // 指定多组 List userList = Lists.newArrayList(); for (String candidateGroup : candidateGroups) { List usersByRoleId = iFlowThirdService.getUsersByRoleId(candidateGroup); userList.addAll(usersByRoleId); } return userList; } return Lists.newArrayList(); } /** * 流程完成时间处理 * * @param ms * @return */ private String getDate(long ms) { long day = ms / (24 * 60 * 60 * 1000); long hour = (ms / (60 * 60 * 1000) - day * 24); long minute = ((ms / (60 * 1000)) - day * 24 * 60 - hour * 60); long second = (ms / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60); if (day > 0) { return day + "天" + hour + "小时" + minute + "分钟"; } if (hour > 0) { return hour + "小时" + minute + "分钟"; } if (minute > 0) { return minute + "分钟"; } if (second > 0) { return second + "秒"; } else { return 0 + "秒"; } } }