Proceso de activiti rechazado

Dirección del proyecto: activiti-workflow

Habrá una función de rechazo en el flujo de aprobación general, y la interfaz proporcionada por activiti no la rechaza. Este artículo implementa la función de rechazo de procesos ampliando la interfaz proporcionada por activiti. El código principal es el siguiente

		String processInstanceId = taskCurrent.getProcessInstanceId();
        FlowElement targetFlowElement = null;
        if (StringUtil.isNotEmpty(processRejectParam.getTargetNodeId())) {
    
    
            //找到目标节点元素
            targetFlowElement = bpmnModel.getMainProcess().getFlowElement(processRejectParam.getTargetNodeId());
        } else {
    
    
        	//开始节点的下一个节点
            targetFlowElement = BpmnUtil.startEventNextTaskId(bpmnModel);
        }
        //当前待审批节点定义Id集合
        List<Task> taskList = taskService.createTaskQuery().processInstanceId(processInstanceId).list();

        if (CollectionUtil.isNotEmpty(taskList)) {
    
    
            BpmnModel newBpmnModel = bpmnModel;
            Map<String, List<SequenceFlow>> stringListMap = BpmnUtil.invokeSequenceFlows(newBpmnModel, taskList, targetFlowElement);

            for (Task task : taskList) {
    
    
                //记录原活动方向
                List<SequenceFlow> oriSequenceFlows = new ArrayList<>();
                //当前节点
                oriSequenceFlows.addAll(stringListMap.get(task.getTaskDefinitionKey()));
                FlowNode currentFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(task.getTaskDefinitionKey());
                try {
    
    
                    Map<String, Object> variables = new HashMap<>();
                    //当前操作节点
                    if(task.getId().equals(taskCurrent.getId())){
    
    
                        //设置当前审批人为提交人
                        taskService.setAssignee(task.getId(), userId);
                        // 保存任务评价
                        if (StringUtil.isNotEmpty(rejectComment)) {
    
    
                            taskService.addComment(task.getId(), task.getProcessInstanceId(), rejectComment);
                        }
                        //设置节点状态
                        taskService.setVariablesLocal(task.getId(), variables);
                        //完成
                        taskService.complete(task.getId());
                    }else{
    
    
                        //完成
                        taskService.complete(task.getId());
                        //删除任务
                        historyService.deleteHistoricTaskInstance(task.getId());
                    }
                } catch (Exception e) {
    
    
                    e.printStackTrace();
                    throw new ProcessException("流程撤回异常,异常原因:" + e.getMessage());
                } finally {
    
    
                    //恢复原方向
                    currentFlowNode.setOutgoingFlows(oriSequenceFlows);
                }
            }
        }

El método invokeSequenceFlows, el código específico se puede ver en el proyecto.



    /**
     * 处理撤回连线 可能存在分支
     * @param bpmnModel
     * @param taskList
     * @param targetFlowElement
     * @return
     */
    public static Map<String,List<SequenceFlow>> invokeSequenceFlows(BpmnModel bpmnModel , List<Task> taskList, FlowElement targetFlowElement) {
    
    
        Map<String,List<SequenceFlow>> flowElements = new HashMap<>(2);
        //并行网关
        ParallelGateway parallelGateway = new ParallelGateway();
        parallelGateway.setId("parallelGateway" + targetFlowElement.getId());
        parallelGateway.setBehavior(new ParallelGatewayActivityBehavior());
        List<SequenceFlow> parallelSequenceFlowInCome = new ArrayList<>();
        for (Task task : taskList) {
    
    
            //当前节点
            FlowNode currentFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(task.getTaskDefinitionKey());
            flowElements.put(currentFlowNode.getId(),currentFlowNode.getOutgoingFlows());

            //重新绘制流程图,从当前节点到到并行网关
            List<SequenceFlow> parallelSequenceFlowList = new ArrayList<>();
            SequenceFlow parallelSequenceFlow = new SequenceFlow();
            parallelSequenceFlow.setId("newSequenceFlowId" + System.currentTimeMillis());
            parallelSequenceFlow.setSourceFlowElement(currentFlowNode);
            parallelSequenceFlow.setTargetFlowElement(parallelGateway);
            parallelSequenceFlowList.add(parallelSequenceFlow);
            parallelSequenceFlowInCome.add(parallelSequenceFlow);
            currentFlowNode.setOutgoingFlows(parallelSequenceFlowList);
        }
        //重新绘制流程图,从并行网关到开始节点
        List<SequenceFlow> newSequenceFlowList = new ArrayList<>();
        //绘制连线,加入流程信息,并组装到流程图
        SequenceFlow newSequenceFlow = new SequenceFlow();
        newSequenceFlow.setId("newSequenceFlowId" + targetFlowElement.getId());
        newSequenceFlow.setSourceFlowElement(parallelGateway);
        newSequenceFlow.setTargetFlowElement(targetFlowElement);
        newSequenceFlowList.add(newSequenceFlow);
        parallelGateway.setIncomingFlows(parallelSequenceFlowInCome);
        parallelGateway.setOutgoingFlows(newSequenceFlowList);

        return flowElements;
    }

Ordene algunas ideas, rechace la opción de pasar el ID de definición del nodo de destino, si no, seleccione el siguiente nodo del nodo de inicio por defecto. Si hay varias tareas de aprobación en este momento, no se realizarán otras operaciones cuando se completen las tareas ejecutadas esta vez, y otras tareas se eliminarán una vez completadas (sin dejar rastros de aprobación).

El proceso de aprobación actual procesado principalmente por invokeSequenceFlows puede tener múltiples tareas. El método de procesamiento es agregar una puerta de enlace paralela a la tarea frente al nodo actual, conectar el nodo de aprobación actual a la puerta de enlace y la puerta de enlace al nodo de destino. De esta manera, no importa cuántas tareas de aprobación existan actualmente, la puerta de enlace paralela espera a que se completen todos los nodos anteriores antes de continuar con los nodos siguientes, lo que garantiza que se ejecuten todas las tareas de aprobación actuales.

Probablemente el proceso sea así

Inserte la descripción de la imagen aquí
Este método también se utiliza para la retirada (operación del iniciador), puede haber problemas y se requieren muchas pruebas.

Supongo que te gusta

Origin blog.csdn.net/qq_34758074/article/details/106365223
Recomendado
Clasificación