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)
- 流程管理(支持流程在線設計器、發佈/部署、掛起、激活、導出/導入、配置表單、啓動、刪除)
- 表單管理(支持快速表單在線設計器、增/刪/改/查、預覽表單)
- 我的流程(發起流程申請)
- 我的待辦(支持快速辦理、查看任務表單辦理、歷史審批意見、流程實時流轉圖等)
- 我的已辦(支持撤回功能)
- 我的申請(查看所有當前用戶申請過的流程情況)
- 更多功能,還在不懈努力地完善中…