基于若依ruoyi-nbcio支持flowable流程角色,同时修改流转用户为username,流程启动做大调整(一)

简介: 基于若依ruoyi-nbcio支持flowable流程角色,同时修改流转用户为username,流程启动做大调整(一)

更多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);
           }
        }
  }


相关文章
|
7月前
|
前端开发
基于若依ruoyi-nbcio支持flowable流程增加自定义业务表单(二)
基于若依ruoyi-nbcio支持flowable流程增加自定义业务表单(二)
327 1
|
7月前
基于若依ruoyi-nbcio支持flowable流程角色,同时修改流转用户为username,流程启动做大调整(三)
基于若依ruoyi-nbcio支持flowable流程角色,同时修改流转用户为username,流程启动做大调整(三)
329 1
|
7月前
|
SQL JavaScript 前端开发
基于若依ruoyi-nbcio支持flowable流程增加自定义业务表单(一)
基于若依ruoyi-nbcio支持flowable流程增加自定义业务表单(一)
565 2
|
7月前
基于若依ruoyi-nbcio支持flowable流程增加自定义业务表单(三)
基于若依ruoyi-nbcio支持flowable流程增加自定义业务表单(三)
336 1
|
7月前
基于若依ruoyi-nbcio支持flowable流程分类里增加流程应用类型
基于若依ruoyi-nbcio支持flowable流程分类里增加流程应用类型
180 1
|
7月前
基于若依ruoyi-nbcio支持flowable流程角色,同时修改流转用户为username,流程启动做大调整(二)
基于若依ruoyi-nbcio支持flowable流程角色,同时修改流转用户为username,流程启动做大调整(二)
176 0
|
7月前
|
前端开发
基于jeecgboot的flowable流程支持退回到发起人节点表单修改功能
基于jeecgboot的flowable流程支持退回到发起人节点表单修改功能
642 0
|
7月前
|
移动开发 前端开发 Java
基于jeecg-boot的flowable流程提供一种动态设置发起人部门负责人的方式
基于jeecg-boot的flowable流程提供一种动态设置发起人部门负责人的方式
143 0
|
6月前
|
前端开发 数据库 JavaScript
基于Flowable的流程挂接自定义业务表单的设计与实践
文章讨论了如何在Flowable流程引擎中挂接自定义业务表单,以及相关设计和实践的步骤。文章中包含了一些前后端代码示例,如Vue组件的模板和脚本部分,这些代码用于实现与Flowable流程引擎交互的界面。例如,有一个按钮组件用于提交申请,点击后会触发applySubmit方法,该方法会与后端API进行交互,处理流程启动、查询关联流程等逻辑。
49745 11
|
7月前
|
SQL 前端开发 数据库
基于RuoYi-Flowable-Plus的若依ruoyi-nbcio支持自定义业务表单流程的集成方法与步骤(一)
基于RuoYi-Flowable-Plus的若依ruoyi-nbcio支持自定义业务表单流程的集成方法与步骤(一)
323 2
基于RuoYi-Flowable-Plus的若依ruoyi-nbcio支持自定义业务表单流程的集成方法与步骤(一)