activiti6實現駁回上一環節功能

實現原理及步驟

activiti6自帶的命令接口很強大,可以實現各種自定義功能。我們現在就可以利用這個命令接口,實現自由跳轉任意節點功能。我們先來看看跳轉任意節點的實現代碼:

實現跳轉任意節點功能
/**
 * 跳轉任意節點命令
 * Create by Kalvin on 2020/5/1.
 */
public class JumpAnyWhereCmd implements Command<Void> {

    private final RepositoryService repositoryService = SpringContextKit.getBean(RepositoryService.class);

    private final String taskId;

    private final String targetNodeId;

    /**
     * @param taskId 當前任務ID
     * @param targetNodeId 目標節點定義ID
     */
    public JumpAnyWhereCmd(String taskId, String targetNodeId) {
        this.taskId = taskId;
        this.targetNodeId = targetNodeId;
    }

    @Override
    public Void execute(CommandContext commandContext) {
        // 獲取任務實例管理類
        TaskEntityManager taskEntityManager = commandContext.getTaskEntityManager();
        // 獲取當前任務實例
        TaskEntity currentTask = taskEntityManager.findById(this.taskId);

        // 獲取當前節點的執行實例
        ExecutionEntity execution = currentTask.getExecution();
        String executionId = execution.getId();

        // 獲取流程定義id
        String processDefinitionId = execution.getProcessDefinitionId();
        // 獲取目標節點
//        Process process = ProcessDefinitionUtil.getProcess(processDefinitionId);
        BpmnModel bpmnModel = this.repositoryService.getBpmnModel(processDefinitionId);
        Process process = bpmnModel.getProcesses().get(0);
        FlowElement flowElement = process.getFlowElement(this.targetNodeId);
        // 獲取歷史管理
        HistoryManager historyManager = commandContext.getHistoryManager();
        // 通知當前活動結束(更新act_hi_actinst)
        historyManager.recordActivityEnd(execution, this.comment);
        // 通知任務節點結束(更新act_hi_taskinst)
        historyManager.recordTaskEnd(this.taskId, this.comment);
        // 刪除正在執行的當前任務
        taskEntityManager.delete(taskId);

        // 此時設置執行實例的當前活動節點爲目標節點
        execution.setCurrentFlowElement(flowElement);

        // 向operations中壓入繼續流程的操作類
        commandContext.getAgenda().planContinueProcessOperation(execution);

        return null;
    }
}

好了,自由跳轉任意節點功能已經實現了,但是我們是要實現駁回上一環節的功能,即跳轉到上一環節節點。我們來看看參數【當前任務ID,目標節點ID】;當前任務ID就是當前流程任務ID,接下來我們需要獲取到目標節點ID這個參數。

獲取上一環節節點信息

如果獲取上一環節節點呢?我們可以通過獲取整個流程定義信息,通過當前節點ID去遞歸往上查找類型爲UserTask的任務節點,再通過歷史節點實例數據過濾不符合的節點,即可得到上一環節任務節點。上代碼:

// 獲取上一環節節點信息
public static ProcessNode getPreOneIncomeNode(String currentNodeId, String processDefId) {
    final List<ProcessNode> preNodes = new ArrayList<>();
    ProcessKit.getIncomeNodesRecur(currentNodeId, processDefId, preNodes, false);
    preNodes.forEach(node -> {
        List<HistoricActivityInstance> historicActivityInstances = historyService.createHistoricActivityInstanceQuery()
                .processDefinitionId(processDefId).activityId(node.getNodeId()).finished().list();
        if (CollectionUtil.isEmpty(historicActivityInstances)) {
            preNodes.remove(node);
        }
    });
    if (CollectionUtil.isEmpty(preNodes)) {
        return null;
    }
    return preNodes.get(0);
}
    
public static void getIncomeNodesRecur(String currentNodeId, String processDefId, List<ProcessNode> incomeNodes, boolean isAll) {
    Process process = ProcessKit.getProcess(processDefId);
    FlowElement currentFlowElement = process.getFlowElement(currentNodeId);
    List<SequenceFlow> incomingFlows = null;
    if (currentFlowElement instanceof UserTask) {
        incomingFlows = ((UserTask) currentFlowElement).getIncomingFlows();
    } else if (currentFlowElement instanceof Gateway) {
        incomingFlows = ((Gateway) currentFlowElement).getIncomingFlows();
    } else if (currentFlowElement instanceof StartEvent) {
        incomingFlows = ((StartEvent) currentFlowElement).getIncomingFlows();
    }
    if (incomingFlows != null && incomingFlows.size() > 0) {
        incomingFlows.forEach(incomingFlow -> {
            String expression = incomingFlow.getConditionExpression();
            // 出線的上一節點
            String sourceFlowElementID = incomingFlow.getSourceRef();
            // 查詢上一節點的信息
            FlowElement preFlowElement = process.getFlowElement(sourceFlowElementID);

            //用戶任務
            if (preFlowElement instanceof UserTask) {
                incomeNodes.add(new ProcessNode(preFlowElement.getId(), preFlowElement.getName()));
                if (isAll) {
                    getIncomeNodesRecur(preFlowElement.getId(), processDefId, incomeNodes, true);
                }
            }
            //排他網關
            else if (preFlowElement instanceof ExclusiveGateway) {
                getIncomeNodesRecur(preFlowElement.getId(), processDefId, incomeNodes, isAll);
            }
            //並行網關
            else if (preFlowElement instanceof ParallelGateway) {
                getIncomeNodesRecur(preFlowElement.getId(), processDefId, incomeNodes, isAll);
            }
        });
    }
}
最後執行駁回上環節的命令
ProcessNode preNode = getPreOneIncomeNode(currentNodeId, processDefId);
CommandExecutor commandExecutor = ((TaskServiceImpl) taskService).getCommandExecutor();
commandExecutor.execute(new JumpAnyWhereCmd(currentNodeId, preNode.getNodeId()));

到此,已完成了駁回上一環節功能的實現。

查看完整代碼

可到以下開源項目查看完整代碼。
【kvf-admin】

此項目基於kvf-admin基礎腳手架 + activiti6已集成大部分工作流核心API及功能,如下:

  • 核心API(支持啓動流程、提交任務、駁回、駁回任意環節、駁回首環節、撤回、掛起/激活流程等API)
  • 流程管理(支持流程在線設計器、發佈/部署、掛起、激活、導出/導入、配置表單、啓動、刪除)
  • 表單管理(支持快速表單在線設計器、增/刪/改/查、預覽表單)
  • 我的流程(發起流程申請)
  • 我的待辦(支持快速辦理、查看任務表單辦理、歷史審批意見、流程實時流轉圖等)
  • 我的已辦(支持撤回功能)
  • 我的申請(查看所有當前用戶申請過的流程情況)
  • 更多功能,還在不懈努力地完善中…
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章