基于开源项目KonBAI / RuoYi-Flowable-Plus使用的部分功能调整。原代码可回退至任一用户任务节点,因业务需求不允许重新修改申请表单填写信息,所以在展示回退列表时,需要屏蔽掉发起申请节点(与开始节点直连的用户任务节点)。
回退节点列表
/**
* 获取所有可回退的节点
*
* @param bo
* @return
*/
@Override
public List<UserTask> findReturnTaskList(WfTaskBo bo) {
// 当前任务 task
Task task = taskService.createTaskQuery().taskId(bo.getTaskId()).singleResult();
// 获取流程定义信息
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
// 获取所有节点信息,暂不考虑子流程情况
Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0);
Collection<FlowElement> flowElements = process.getFlowElements();
// 获取当前任务节点元素
UserTask source = null;
if (flowElements != null) {
for (FlowElement flowElement : flowElements) {
// 类型为用户节点
if (flowElement.getId().equals(task.getTaskDefinitionKey())) {
source = (UserTask) flowElement;
}
}
}
// old >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// 获取节点的所有路线
// List<List<UserTask>> roads = FlowableUtils.findRoad(source, source, null, null, null);
// -----------------------------------------------------------
// new >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// 获取节点的所有路线:不将前一个节点是开始节点的用户任务加入回退列表
List<List<UserTask>> roads = FlowableUtils.findRoadNew(source, source, null, null, null);
// -----------------------------------------------------------
// 可回退的节点列表
List<UserTask> userTaskList = new ArrayList<>();
for (List<UserTask> road : roads) {
if (userTaskList.size() == 0) {
// 还没有可回退节点直接添加
userTaskList = road;
} else {
// 如果已有回退节点,则比对取交集部分
userTaskList.retainAll(road);
}
}
return userTaskList;
}
寻路方法
/**
* 从后向前寻路,获取到达节点的所有路线
* 不存在直接回退到子流程,但是存在回退到父级流程的情况
* new:如果任务节点的前一个节点是开始节点,则不将当前节点加入回退列表
* @param source 起始节点
* @param passRoads 已经经过的点集合
* @param hasSequenceFlow 已经经过的路线
* @param roads 路线
* @return
*/
public static List<List<UserTask>> findRoadNew(FlowElement currentsource, FlowElement source, List<UserTask> passRoads, Set<String> hasSequenceFlow, List<List<UserTask>> roads) {
passRoads = passRoads == null ? new ArrayList<>() : passRoads;
roads = roads == null ? new ArrayList<>() : roads;
hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow;
// 如果该节点为开始节点,且存在上级子节点,则顺着上级子节点继续迭代
if (source instanceof StartEvent && source.getSubProcess() != null) {
roads = findRoadNew(currentsource, source.getSubProcess(), passRoads, hasSequenceFlow, roads);
}
// 1.查指向当前任务的连线是否存在
// -> 1.1.存在则继续往前查找节点
// -> 1.1.1.是开始节点 -> 不将当前任务加入路线
// -> 1.1.2.是用户任务节点 -> 将当前任务加入路线
// -> 1.2.不存在则将当前任务直接加入路线
// 根据类型,获取入口连线
List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source);
// 如果当前节点的入口连线存在,将连线加入已记录连线列表中,且记录当前任务;若连线已存在连线列表中,则跳过当前任务
if (sequenceFlows != null && sequenceFlows.size() != 0) {
for (SequenceFlow sequenceFlow: sequenceFlows) {
// 如果发现连线重复,说明循环了,跳过这个循环
if (hasSequenceFlow.contains(sequenceFlow.getId())) {
continue;
}
// 添加已经走过的连线
hasSequenceFlow.add(sequenceFlow.getId());
// new >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// 添加经过路线,当前任务1.不等于传入节点 2.属于用户任务 3.连线的上一节点不是开始节点 -> 记录当前用户任务
if (source instanceof UserTask && currentsource != source && !(sequenceFlow.getSourceFlowElement() instanceof StartEvent)) {
passRoads.add((UserTask) source);
}
// --------------------------------------------
// 继续找上一个节点
roads = findRoadNew(currentsource, sequenceFlow.getSourceFlowElement(), passRoads, hasSequenceFlow, roads);
}
} else {
// 如果不存在上一级连线,添加路线
roads.add(passRoads);
}
return roads;
}