activiti6 回退和跳转到指定节点

事件起因

最近突然让我做一个工作流跳转和退回到指定节点,说是用activiti写的,这我哪会,直接措手不及啊
activiti6 回退和跳转到指定节点_第1张图片

回去以后恶补了一下,大概是了解了,不多说,直接进入正题。

实现过程

一上手,直接面向网络了一波,结果发现都让我改模型,改了不就崩了吗,我不能理解。
首先分析一下,要实现跳转得搞清楚几个问题,首先我们是改模型或者实例还是改数据(就是改这个流程现在的人员),首先排除改数据,数据改了,流程不还是继续往前吗,明显不行,再排除改模型,改了模型重新部署,这整个流程不就不对了吗,最后只剩下改实例了

修改实例
        //获取任务信息
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        // 获取实例id
        String processDefinitionId = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult().getProcessDefinitionId();
        // 获取模型配置信息
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        // 获取实例信息
        Execution execution = runtimeService.createExecutionQuery().executionId(task.getExecutionId()).singleResult();

这个时候遇到问题了,完蛋了,我回退啥啊,我都不知道回退到哪,我咋回退,所以我们还需要写一个查询当前节点以前所有节点递归接口

查节点
/**
     * 递归查找当前节点前用户节点
     * @param currentFlowNode 当前节点
     * @param map 所有节点map
     * @param chooseNode 可选的节点集
     * @return
     */
    public List<FlowElement> recursionSearch(FlowNode currentFlowNode, Map<String, List<FlowElement>> map, List<FlowElement> chooseNode,List<SequenceFlow> lineList) {
        // 获取输入线
        List<SequenceFlow> incomingFlows = currentFlowNode.getIncomingFlows();
        // 判断输入线类型
        for (SequenceFlow incomingFlow : incomingFlows) {
            // 判断是否是网关节点
            if (map.get("gateway").stream().filter(e -> e.getId().equals(incomingFlow.getSourceRef())).collect(Collectors.toList()).size() > 0) {
                //是网关节点,继续找上个节点找到后继续加入递归
                List<FlowElement> gateway = map.get("gateway").stream().filter(e -> e.getId().equals(incomingFlow.getSourceRef())).collect(Collectors.toList());
                FlowNode gatewayNode =   (FlowNode)gateway.get(0);
                List<SequenceFlow> gatewayNodeIncomingFlows = gatewayNode.getIncomingFlows();
                List<SequenceFlow> outgoingFlows = gatewayNode.getOutgoingFlows();
                if(gatewayNodeIncomingFlows.size() > 0){
                    List<FlowElement> userTask = map.get("userTask").stream().filter(e -> e.getId().equals(gatewayNodeIncomingFlows.get(0).getSourceRef())).collect(Collectors.toList());
                    List<String> targetRefs = outgoingFlows.stream().map(t -> t.getTargetRef()).collect(Collectors.toList());
                    List<String> startOrEnd = map.get("startOrEnd").stream().map(t -> t.getId()).collect(Collectors.toList());
                    targetRefs.retainAll(startOrEnd);
                    if(userTask.size() > 0 && targetRefs.size() == 0){
                        if(Objects.nonNull(lineList)){
                            lineList.add((incomingFlow));
                            lineList.addAll(gatewayNodeIncomingFlows);
                        }
                        FlowNode flowNode=  (FlowNode)userTask.get(0);
                        chooseNode.add(flowNode);
                        chooseNode.add(gateway.get(0));
                        recursionSearch(flowNode,map,chooseNode,lineList);
                    }else {
                        continue;
                    }
                }else {
                    continue;
                }
            }
            // 判断是开始节点,直接加入数组,结束循环
            else if (map.get("startOrEnd").stream().filter(e -> e.getId().equals(incomingFlow.getSourceRef())).collect(Collectors.toList()).size() > 0) {
                if(Objects.nonNull(lineList)){
                    lineList.add((incomingFlow));
                }
                List<FlowElement> startOrEnd = map.get("startOrEnd").stream().filter(e -> e.getId().equals(incomingFlow.getSourceRef())).collect(Collectors.toList());
                if (Objects.nonNull(startOrEnd.get(0))){
                    chooseNode.add(startOrEnd.get(0));
                }
            }
            // 非网关节点,非开始节点,即用户节点,加入当前节点,继续递归
            else if(map.get("userTask").stream().filter(e -> e.getId().equals(incomingFlow.getSourceRef())).collect(Collectors.toList()).size() > 0){
                if(Objects.nonNull(lineList)){
                    lineList.add((incomingFlow));
                }
                chooseNode.add(currentFlowNode);
             //   找到上个节点
                List<FlowElement> userTask = map.get("userTask").stream().filter(e -> e.getId().equals(incomingFlow.getSourceRef())).collect(Collectors.toList());
                FlowNode flowElement = (FlowNode)userTask.get(0);
                recursionSearch(flowElement,map,chooseNode,lineList);
            }else {
                continue;
            }
        }
        return chooseNode;
    }

这个查节点其实有一定的约束性,遇到并行可选的节点可能需要根据具体做出改变。
这样下来节点有了,可以开始下一步了


    /**
     * 强制跳转节点
     * @param taskId 任务id
     * @param sid 节点id
     * @param comment
     * @param variables
     * @return
     */
    @Override
    public Boolean forceNode1(String taskId, String sid,String comment,Map<String, Object> variables,Long flowVoId){
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        String processDefinitionId = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult().getProcessDefinitionId();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        Execution execution = runtimeService.createExecutionQuery().executionId(task.getExecutionId()).singleResult();
        String activityId = execution.getActivityId();
        FlowNode currentFlowNode =  (FlowNode)bpmnModel.getMainProcess().getFlowElement(activityId);
        FlowNode targetFlowNode =  (FlowNode)bpmnModel.getMainProcess().getFlowElement(sid);
        //拉线
        List<SequenceFlow> sequenceFlowList = new ArrayList<>();
        SequenceFlow sequenceFlow = new SequenceFlow();
        sequenceFlow.setId("newFlow");
        sequenceFlow.setSourceFlowElement(currentFlowNode);
        sequenceFlow.setTargetFlowElement(targetFlowNode);
        sequenceFlowList.add(sequenceFlow);
        // 备份原有
        List<SequenceFlow> dataflows = currentFlowNode.getOutgoingFlows();
        List<SequenceFlow> oriSequenceFlows = new ArrayList<SequenceFlow>();
        oriSequenceFlows.addAll(dataflows);
        currentFlowNode.getOutgoingFlows().clear();
        currentFlowNode.setOutgoingFlows(sequenceFlowList);
        comment = "【回退】"+comment;
        taskService.addComment(taskId, task.getProcessInstanceId(), comment);
//        taskService.resolveTask(taskId, variables);
        taskService.claim(taskId, ShiroUtils.getLoginName());
        taskService.complete(taskId);
        currentFlowNode.setOutgoingFlows(oriSequenceFlows);
        return true;
    }

注意一点,你改完线以后一定要先备份,再拉回去,不然下一个实例会有问题,但是多线程会不会有问题呢,这个值得思考一下
到这就结束了?
activiti6 回退和跳转到指定节点_第2张图片
写了,用户难道不查历史的吗,你这样历史不乱套了吗
所以在历史上还得动手脚
可以先查出所有历史,给加签节点赋值时间,最后按节点时间排序不就成了

 List<FlowVo> flowVoList = results.stream().filter(e -> e.getTaskId() != null && e.getTaskId().equals(bizIncrease.getTaskId()) && e.getTaskName() != "加签节点").collect(Collectors.toList());
                    if(taskName == null || taskName.length() == 0 || taskName.equals("加签节点")){
                        if(flowVoList.size() > 0){
                            // 说明是历史
                            for (FlowVo vo : flowVoList) {
                                FlowVo newFlow = new FlowVo();
                                BeanUtils.copyProperties(vo, newFlow);
                                newFlow.setTaskId(bizIncrease.getTaskId());
                                newFlow.setTaskName("加签节点");
                                if(bizIncrease.getIsHandle().equals("0")){
                                    newFlow.setStartTime(bizIncrease.getTaskCreateTime());
                                }else {
                                    newFlow.setStartTime(bizIncrease.getStartTime());
                                }
                                SysUser sysUser = userMapper.selectUserByLoginName(vo.getApplyUser());
                                newFlow.setApplyUserName(sysUser.getUserName());
                                newFlow.setEndTime(bizIncrease.getStartTime());
                                results.add(newFlow);
                            }
                        }else  {
                            // 说明是当前的
                            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(bizIncrease.getInstanceId()).singleResult();
                            String businessKey = processInstance.getBusinessKey();
                            FlowVo flow1 = activityJobMapper.selectActivityJobById(new Long(businessKey));
                            flow1.setTaskId(bizIncrease.getTaskId());
                            flow1.setTaskName("加签节点");
                            flow1.setEndTime(bizIncrease.getStartTime());
                            if(bizIncrease.getIsHandle().equals("0")){
                                flow1.setStartTime(bizIncrease.getTaskCreateTime());
                            }else {
                                flow1.setStartTime(bizIncrease.getStartTime());
                            }
                            SysUser sysUser = userMapper.selectUserByLoginName(flow1.getApplyUser());
                            flow1.setApplyUserName(sysUser.getUserName());
                            results.add(flow1);
                        }

思路大概是这样。
这样强制跳转和回退就写好了。后面其实还有加签和委派两个功能,其实都类似
activiti6 回退和跳转到指定节点_第3张图片

你可能感兴趣的:(java学习,java,数据结构,开发语言)