perf(办公管理): 优化 退回任务限制只能退回串行节点
This commit is contained in:
@@ -310,4 +310,64 @@ public class ModelUtils {
|
|||||||
}
|
}
|
||||||
return userTaskList;
|
return userTaskList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 迭代从后向前扫描,判断目标节点相对于当前节点是否是串行
|
||||||
|
* 不存在直接回退到子流程中的情况,但存在从子流程出去到父流程情况
|
||||||
|
* @param source 起始节点
|
||||||
|
* @param target 目标节点
|
||||||
|
* @param visitedElements 已经经过的连线的 ID,用于判断线路是否重复
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public static boolean isSequentialReachable(FlowElement source, FlowElement target, Set<String> visitedElements) {
|
||||||
|
visitedElements = visitedElements == null ? new HashSet<>() : visitedElements;
|
||||||
|
if (source instanceof StartEvent && isInEventSubprocess(source)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据类型,获取入口连线
|
||||||
|
List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source);
|
||||||
|
if (sequenceFlows != null && sequenceFlows.size() > 0) {
|
||||||
|
// 循环找到目标元素
|
||||||
|
for (SequenceFlow sequenceFlow: sequenceFlows) {
|
||||||
|
// 如果发现连线重复,说明循环了,跳过这个循环
|
||||||
|
if (visitedElements.contains(sequenceFlow.getId())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 添加已经走过的连线
|
||||||
|
visitedElements.add(sequenceFlow.getId());
|
||||||
|
FlowElement sourceFlowElement = sequenceFlow.getSourceFlowElement();
|
||||||
|
// 这条线路存在目标节点,这条线路完成,进入下个线路
|
||||||
|
if (target.getId().equals(sourceFlowElement.getId())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 如果目标节点为并行网关,则不继续
|
||||||
|
if (sourceFlowElement instanceof ParallelGateway) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 否则就继续迭代
|
||||||
|
boolean isSequential = isSequentialReachable(sourceFlowElement, target, visitedElements);
|
||||||
|
if (!isSequential) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static boolean isInEventSubprocess(FlowElement flowElement) {
|
||||||
|
FlowElementsContainer flowElementsContainer = flowElement.getParentContainer();
|
||||||
|
while (flowElementsContainer != null) {
|
||||||
|
if (flowElementsContainer instanceof EventSubProcess) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flowElementsContainer instanceof FlowElement) {
|
||||||
|
flowElementsContainer = ((FlowElement) flowElementsContainer).getParentContainer();
|
||||||
|
} else {
|
||||||
|
flowElementsContainer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.ruoyi.workflow.service;
|
package com.ruoyi.workflow.service;
|
||||||
|
|
||||||
import com.ruoyi.workflow.domain.bo.WfTaskBo;
|
import com.ruoyi.workflow.domain.bo.WfTaskBo;
|
||||||
import org.flowable.bpmn.model.UserTask;
|
import org.flowable.bpmn.model.FlowElement;
|
||||||
import org.flowable.engine.runtime.ProcessInstance;
|
import org.flowable.engine.runtime.ProcessInstance;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@@ -42,7 +42,7 @@ public interface IWfTaskService {
|
|||||||
* @param bo
|
* @param bo
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
List<UserTask> findReturnTaskList(WfTaskBo bo);
|
List<FlowElement> findReturnTaskList(WfTaskBo bo);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除任务
|
* 删除任务
|
||||||
|
|||||||
@@ -167,36 +167,18 @@ public class WfTaskServiceImpl extends FlowServiceFactory implements IWfTaskServ
|
|||||||
}
|
}
|
||||||
// 获取流程定义信息
|
// 获取流程定义信息
|
||||||
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
|
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
|
||||||
// 获取所有节点信息
|
// 获取流程模型信息
|
||||||
Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0);
|
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
|
||||||
// 获取全部节点列表,包含子节点
|
|
||||||
Collection<FlowElement> allElements = FlowableUtils.getAllElements(process.getFlowElements(), null);
|
|
||||||
// 获取当前任务节点元素
|
// 获取当前任务节点元素
|
||||||
FlowElement source = null;
|
FlowElement source = ModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey());
|
||||||
// 获取跳转的节点元素
|
// 获取跳转的节点元素
|
||||||
FlowElement target = null;
|
FlowElement target = ModelUtils.getFlowElementById(bpmnModel, bo.getTargetKey());
|
||||||
if (allElements != null) {
|
// 从当前节点向前扫描,判断当前节点与目标节点是否属于串行,若目标节点是在并行网关上或非同一路线上,不可跳转
|
||||||
for (FlowElement flowElement : allElements) {
|
boolean isSequential = ModelUtils.isSequentialReachable(source, target, new HashSet<>());
|
||||||
// 当前任务节点元素
|
|
||||||
if (flowElement.getId().equals(task.getTaskDefinitionKey())) {
|
|
||||||
source = flowElement;
|
|
||||||
}
|
|
||||||
// 跳转的节点元素
|
|
||||||
if (flowElement.getId().equals(bo.getTargetKey())) {
|
|
||||||
target = flowElement;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 从当前节点向前扫描
|
|
||||||
// 如果存在路线上不存在目标节点,说明目标节点是在网关上或非同一路线上,不可跳转
|
|
||||||
// 否则目标节点相对于当前节点,属于串行
|
|
||||||
Boolean isSequential = FlowableUtils.iteratorCheckSequentialReferTarget(source, bo.getTargetKey(), null, null);
|
|
||||||
if (!isSequential) {
|
if (!isSequential) {
|
||||||
throw new RuntimeException("当前节点相对于目标节点,不属于串行关系,无法回退");
|
throw new RuntimeException("当前节点相对于目标节点,不属于串行关系,无法回退");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 获取所有正常进行的任务节点 Key,这些任务不能直接使用,需要找出其中需要撤回的任务
|
// 获取所有正常进行的任务节点 Key,这些任务不能直接使用,需要找出其中需要撤回的任务
|
||||||
List<Task> runTaskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list();
|
List<Task> runTaskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list();
|
||||||
List<String> runTaskKeyList = new ArrayList<>();
|
List<String> runTaskKeyList = new ArrayList<>();
|
||||||
@@ -245,38 +227,36 @@ public class WfTaskServiceImpl extends FlowServiceFactory implements IWfTaskServ
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<UserTask> findReturnTaskList(WfTaskBo bo) {
|
public List<FlowElement> findReturnTaskList(WfTaskBo bo) {
|
||||||
// 当前任务 task
|
// 当前任务 task
|
||||||
Task task = taskService.createTaskQuery().taskId(bo.getTaskId()).singleResult();
|
Task task = taskService.createTaskQuery().taskId(bo.getTaskId()).singleResult();
|
||||||
// 获取流程定义信息
|
// 获取流程定义信息
|
||||||
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
|
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
|
||||||
// 获取所有节点信息,暂不考虑子流程情况
|
// 获取流程模型信息
|
||||||
Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0);
|
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
|
||||||
Collection<FlowElement> flowElements = process.getFlowElements();
|
// 查询历史节点实例
|
||||||
|
List<HistoricActivityInstance> activityInstanceList = historyService.createHistoricActivityInstanceQuery()
|
||||||
|
.processInstanceId(task.getProcessInstanceId())
|
||||||
|
.activityType(BpmnXMLConstants.ELEMENT_TASK_USER)
|
||||||
|
.finished()
|
||||||
|
.orderByHistoricActivityInstanceEndTime().asc()
|
||||||
|
.list();
|
||||||
|
List<String> activityIdList = activityInstanceList.stream()
|
||||||
|
.map(HistoricActivityInstance::getActivityId)
|
||||||
|
.filter(activityId -> !StringUtils.equals(activityId, task.getTaskDefinitionKey()))
|
||||||
|
.distinct()
|
||||||
|
.collect(Collectors.toList());
|
||||||
// 获取当前任务节点元素
|
// 获取当前任务节点元素
|
||||||
UserTask source = null;
|
FlowElement source = ModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey());
|
||||||
if (flowElements != null) {
|
List<FlowElement> elementList = new ArrayList<>();
|
||||||
for (FlowElement flowElement : flowElements) {
|
for (String activityId : activityIdList) {
|
||||||
// 类型为用户节点
|
FlowElement target = ModelUtils.getFlowElementById(bpmnModel, activityId);
|
||||||
if (flowElement.getId().equals(task.getTaskDefinitionKey())) {
|
boolean isSequential = ModelUtils.isSequentialReachable(source, target, new HashSet<>());
|
||||||
source = (UserTask) flowElement;
|
if (isSequential) {
|
||||||
}
|
elementList.add(target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 获取节点的所有路线
|
return elementList;
|
||||||
List<List<UserTask>> roads = FlowableUtils.findRoad(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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user