更多功能看演示系统
gitee源代码地址
后端代码: https://gitee.com/nbacheng/nbcio-boot
前端代码:https://gitee.com/nbacheng/nbcio-vue.git
在线演示(包括H5) : http://122.227.135.243:9888
因为看很多朋友需要这种同意拒绝的排它网关流程,因为之前还不支持的第一个发起人后面的这种排它网关操作,所以这部分完善这个功能。
1、FindNextNodeUtil类增加一个方法
/** * 获取排他网关分支名称、分支表达式是否存在${approved} * @param flowElement * @param * add by nbacheng */ public static boolean GetExclusiveGatewayExpression(FlowElement flowElement) { // 获取所有网关分支 List<SequenceFlow> targetFlows=((ExclusiveGateway)flowElement).getOutgoingFlows(); // 循环每个网关分支 for(SequenceFlow sequenceFlow : targetFlows){ // 获取下一个网关和节点数据 FlowElement targetFlowElement=sequenceFlow.getTargetFlowElement(); // 网关数据不为空 if (StringUtils.isNotBlank(sequenceFlow.getConditionExpression())) { // 获取网关判断条件 String expression = sequenceFlow.getConditionExpression(); if(expression.contains("${approved}")) { return true; } } } return false; }
2、启动流程里增加下面信息
//取出两个特殊的变量 if(variablesnew.containsKey("bparallelGateway")) {//并行网关 bparallelGateway = (boolean) variablesnew.get("bparallelGateway"); variablesnew.remove("bparallelGateway"); } if(variablesnew.containsKey("bapprovedEG")) {//通用拒绝同意排它网关 bapprovedEG = (boolean) variablesnew.get("bapprovedEG"); variablesnew.remove("bapprovedEG"); }
3、getNextFlowInfo修改如下:
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); } }
4、setNextAssignee 修改如下:
/** * 设置下个节点信息处理人员 * add by nbacheng * * @param variablesnew, usermap, * userlist, sysUser, variables, bparallelGateway * * @return */ private Result 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.getRealname() + "发起流程申请"); taskService.setAssignee(nexttask.getId(), assignee); i++; } return Result.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.getRealname() + "发起流程申请"); taskService.setAssignee(task.getId(), sysUser.getUsername()); //taskService.complete(task.getId(), variables); } // 获取下一个节点数据及设置数据 FlowNextDto nextFlowNode = flowTaskService.getNextFlowNode(task.getId(), variables); if(Objects.nonNull(nextFlowNode)) { Map<String, Object> nVariablesMap = taskService.getVariables(task.getId()); if (Objects.nonNull(task)) { 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 Result.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 Result.OK("流程启动成功给发起人."); } else { taskService.complete(task.getId(), variables); return Result.OK("流程启动成功."); } } else { return Result.error("审批人不存在,流程启动失败!"); } } 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 Result.OK("多实例会签流程启动成功."); } else if(nextFlowNode.getUserList().size() > 1) { if (bparallelGateway) {//后一个节点是并行网关的话 taskService.complete(task.getId(), variables); return Result.OK("流程启动成功."); } else { return Result.OK("流程启动成功,请到我的待办里进行流程的提交流转."); } } else { return Result.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 Result.OK("流程启动成功."); }else { return Result.OK("流程启动失败,请检查流程设置人员!"); } }else { return Result.OK("流程启动失败,请检查流程设置人员!"); } } else { return Result.OK("流程启动失败,请检查流程设置人员!"); } } } else { if(bapprovedEG) { return Result.OK("通用拒绝同意流程启动成功,请到我的待办里进行流程的提交流转."); } taskService.complete(task.getId(), variables); return Result.OK("流程启动成功."); } } }
5、效果图如下: