更多ruoyi-nbcio功能请看演示系统
gitee源代码地址
前后端代码: https://gitee.com/nbacheng/ruoyi-nbcio
演示地址:RuoYi-Nbcio后台管理系统
原来基于的流程不支持角色流转,同时对启动后面的节点逻辑没有做任何处理,就会遇到很多问题,同时原先用id作为流程流转的关键用户,现在修改username账号作为流转关键用户,这些都做统一调整,所以后续不再支持原先继承的项目了。
1、启动流程做如下调整。
/** * 启动流程实例 */ private R startProcess(ProcessDefinition procDef, Map<String, Object> variables) { if (ObjectUtil.isNotNull(procDef) && procDef.isSuspended()) { throw new ServiceException("流程已被挂起,请先激活流程"); } // 设置流程发起人Id到流程中,包括变量 String userStr = TaskUtils.getUserName(); SysUser sysUsr = sysUserService.selectUserByUserName(userStr); setFlowVariables(sysUsr,variables); Map<String, Object> variablesnew = variables; Map<String, Object> usermap = new HashMap<String, Object>(); List<String> userlist = new ArrayList<String>(); boolean bparallelGateway = false; boolean bapprovedEG = false; //获取下个节点信息 getNextFlowInfo(procDef, variablesnew, usermap, variables, userlist); //取出两个特殊的变量 if(variablesnew.containsKey("bparallelGateway")) {//并行网关 bparallelGateway = (boolean) variablesnew.get("bparallelGateway"); variablesnew.remove("bparallelGateway"); } if(variablesnew.containsKey("bapprovedEG")) {//通用拒绝同意排它网关 bapprovedEG = (boolean) variablesnew.get("bapprovedEG"); variablesnew.remove("bapprovedEG"); } // 发起流程实例 ProcessInstance processInstance = runtimeService.startProcessInstanceById(procDef.getId(), variables); // 第一个用户任务为发起人,则自动完成任务 wfTaskService.startFirstTask(processInstance, variables); return setNextAssignee(processInstance, usermap, userlist, sysUsr, variables, bparallelGateway, bapprovedEG); }
2、设置下一个节点处理人代码如下:
/** * 设置下个节点信息处理人员 * add by nbacheng * * @param variablesnew, usermap, * userlist, sysUser, variables, bparallelGateway * * @return */ private R setNextAssignee(ProcessInstance processInstance, Map<String, Object> usermap, List<String> userlist, SysUser sysUser, Map<String, Object> variables, boolean bparallelGateway, boolean bapprovedEG) { // 给第一步申请人节点设置任务执行人和意见 if((usermap.containsKey("isSequential")) && !(boolean)usermap.get("isSequential")) {//并发会签会出现2个以上需要特殊处理 List<Task> nexttasklist = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).active().list(); int i=0; for (Task nexttask : nexttasklist) { String assignee = userlist.get(i).toString(); taskService.addComment(nexttask.getId(), processInstance.getProcessInstanceId(), FlowComment.NORMAL.getType(), sysUser.getNickName() + "发起流程申请"); taskService.setAssignee(nexttask.getId(), assignee); i++; } return R.ok("多实例会签流程启动成功."); } else {// 给第一步申请人节点设置任务执行人和意见 Task task = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).active() .singleResult(); if (Objects.nonNull(task)) { taskService.addComment(task.getId(), processInstance.getProcessInstanceId(), FlowComment.NORMAL.getType(), sysUser.getNickName() + "发起流程申请"); taskService.setAssignee(task.getId(), sysUser.getUserName()); } // 获取下一个节点数据及设置数据 FlowNextDto nextFlowNode = wfTaskService.getNextFlowNode(task.getId(), variables); if(Objects.nonNull(nextFlowNode)) { if (Objects.nonNull(task)) { Map<String, Object> nVariablesMap = taskService.getVariables(task.getId()); if(nVariablesMap.containsKey("SetAssigneeTaskListener")) {//是否通过动态设置审批人的任务监听器 taskService.complete(task.getId(), variables); Task nexttask = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).active().singleResult(); taskService.setAssignee(nexttask.getId(), nVariablesMap.get("SetAssigneeTaskListener").toString()); return R.ok("通过动态设置审批人的任务监听器流程启动成功."); } if(nVariablesMap.containsKey("SetDeptHeadTaskListener")) {//是否通过动态设置发起人部门负责人的任务监听器 taskService.complete(task.getId(), variables); Task nexttask = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).active().singleResult(); if(Objects.nonNull(nexttask)) { if(Objects.nonNull((List<String>) nVariablesMap.get("SetDeptHeadTaskListener"))) { if(((List<String>) nVariablesMap.get("SetDeptHeadTaskListener")).size() == 1) {//是否就一个人 taskService.setAssignee(nexttask.getId(), ((List<String>)nVariablesMap.get("SetDeptHeadTaskListener")).get(0).toString()); return R.ok("设置发起人部门负责人的任务监听器流程启动成功."); } else { for (String username : ((List<String>) nVariablesMap.get("SetDeptHeadTaskListener"))) { taskService.addCandidateUser(nexttask.getId(), username); } return R.ok("设置多个发起人部门负责人的任务监听器流程启动成功,目前用户可通过签收方式完成审批."); } } } } } if(Objects.nonNull(nextFlowNode.getUserList())) { if( nextFlowNode.getUserList().size() == 1 ) { if (nextFlowNode.getUserList().get(0) != null) { if(StringUtils.equalsAnyIgnoreCase(nextFlowNode.getUserList().get(0).getUserName(), "${INITIATOR}")) {//对发起人做特殊处理 taskService.complete(task.getId(), variables); return R.ok("流程启动成功给发起人."); } else if(nextFlowNode.getUserTask().getCandidateUsers().size()>0 && StringUtils.equalsAnyIgnoreCase(nextFlowNode.getUserTask().getCandidateUsers().get(0), "${DepManagerHandler.getUsers(execution)}")) {//对部门经理做特殊处理 //taskService.complete(task.getId(), variables); return R.ok("流程启动成功给部门经理,请到我的待办里进行流程的提交流转."); } else { taskService.complete(task.getId(), variables); return R.ok("流程启动成功."); } } else { return R.fail("审批人不存在,流程启动失败!"); } } else if(nextFlowNode.getType() == ProcessConstants.PROCESS_MULTI_INSTANCE ) {//对多实例会签做特殊处理或者以后在流程设计进行修改也可以 Map<String, Object> approvalmap = new HashMap<>(); List<String> sysuserlist = nextFlowNode.getUserList().stream().map(obj-> (String) obj.getUserName()).collect(Collectors.toList()); approvalmap.put("approval", sysuserlist); taskService.complete(task.getId(), approvalmap); if(!nextFlowNode.isBisSequential()){//对并发会签进行assignee单独赋值 List<Task> nexttasklist = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).active().list(); int i=0; for (Task nexttask : nexttasklist) { String assignee = sysuserlist.get(i).toString(); taskService.setAssignee(nexttask.getId(), assignee); i++; } } return R.ok("多实例会签流程启动成功."); } else if(nextFlowNode.getUserList().size() > 1) { if (bparallelGateway) {//后一个节点是并行网关的话 taskService.complete(task.getId(), variables); return R.ok("流程启动成功."); } else { return R.ok("流程启动成功,请到我的待办里进行流程的提交流转."); } } else { return R.ok("流程启动失败,请检查流程设置人员!"); } } else {//对跳过流程做特殊处理 List<UserTask> nextUserTask = FindNextNodeUtil.getNextUserTasks(repositoryService, task, variables); if (CollectionUtils.isNotEmpty(nextUserTask)) { List<FlowableListener> listlistener = nextUserTask.get(0).getTaskListeners(); if(CollectionUtils.isNotEmpty(listlistener)) { String tasklistener = listlistener.get(0).getImplementation(); if(StringUtils.contains(tasklistener, "AutoSkipTaskListener")) { taskService.complete(task.getId(), variables); return R.ok("流程启动成功."); }else { return R.ok("流程启动失败,请检查流程设置人员!"); } }else { return R.ok("流程启动失败,请检查流程设置人员!"); } } else { return R.ok("流程启动失败,请检查流程设置人员!"); } } } else { if(bapprovedEG) { return R.ok("通用拒绝同意流程启动成功,请到我的待办里进行流程的提交流转."); } taskService.complete(task.getId(), variables); return R.ok("流程启动成功."); } } }
3、设置发起人变量
/** * 设置发起人变量 * add by nbacheng * * @param variables * 流程变量 * @return */ private void setFlowVariables(SysUser sysUser,Map<String, Object> variables) { // 设置流程发起人Id到流程中 identityService.setAuthenticatedUserId(sysUser.getUserName()); variables.put(BpmnXMLConstants.ATTRIBUTE_EVENT_START_INITIATOR, sysUser.getUserName()); // 设置流程状态为进行中 variables.put(ProcessConstants.PROCESS_STATUS_KEY, ProcessStatus.RUNNING.getStatus()); // 设置流程状态为进行中 variables.put(ProcessConstants.PROCESS_STATUS_KEY, ProcessStatus.RUNNING.getStatus()); }
4、获取下个节点信息,对并行与排它网关做处理
/** * 获取下个节点信息,对并行与排它网关做处理 * add by nbacheng * * @param processDefinition, variablesnew, usermap, variables, userlist, bparallelGateway * * @return */ @SuppressWarnings("unchecked") private void getNextFlowInfo(ProcessDefinition processDefinition, Map<String, Object> variablesnew, Map<String, Object> usermap, Map<String, Object> variables, List<String> userlist) { String definitionld = processDefinition.getId(); //获取bpm(模型)对象 BpmnModel bpmnModel = repositoryService.getBpmnModel(definitionld); //传节点定义key获取当前节点 List<org.flowable.bpmn.model.Process> processes = bpmnModel.getProcesses(); //只处理发起人后面排它网关再后面是会签的情况,其它目前不考虑 //List<UserTask> userTasks = process.findFlowElementsOfType(UserTask.class); List<FlowNode> flowNodes = processes.get(0).findFlowElementsOfType(FlowNode.class); List<SequenceFlow> outgoingFlows = flowNodes.get(1).getOutgoingFlows(); //遍历返回下一个节点信息 for (SequenceFlow outgoingFlow : outgoingFlows) { //类型自己判断(获取下个节点是网关还是节点) FlowElement targetFlowElement = outgoingFlow.getTargetFlowElement(); //下个是节点 if(targetFlowElement instanceof ExclusiveGateway){// 下个出口是排它网关的话,后一个用户任务又是会签的情况下需要approval的赋值处理,否则报错 usermap = GetExclusiveGatewayUser(targetFlowElement,variables);//还是需要返回用户与是否并发,因为并发要做特殊处理 if(usermap != null) { userlist = (ArrayList<String>) usermap.get("approval"); variablesnew.put("approval", userlist); } if(FindNextNodeUtil.GetExclusiveGatewayExpression(targetFlowElement)) {//下个出口是通用拒绝同意排它网关 variablesnew.put("bapprovedEG",true); } break; } if(targetFlowElement instanceof ParallelGateway){// 下个出口是并行网关的话,直接需要进行complete,否则报错 variablesnew.put("bparallelGateway",true); } } }