fix(办公管理): 修复已办任务撤回操作操作失败问题(https://gitee.com/KonBAI-Q/ruoyi-flowable-plus/issues/I61V7N)

This commit is contained in:
konbai
2023-01-01 21:02:12 +08:00
parent 0fcf897479
commit c04be5e308
4 changed files with 134 additions and 57 deletions

View File

@@ -16,7 +16,8 @@ public enum FlowComment {
REJECT("3", "驳回"),
DELEGATE("4", "委派"),
TRANSFER("5", "转办"),
STOP("6", "终止");
STOP("6", "终止"),
REVOKE("7", "撤回");
/**
* 类型

View File

@@ -6,8 +6,7 @@ import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.*;
import org.flowable.common.engine.impl.util.io.StringStreamSource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.*;
/**
* @author KonBAI
@@ -37,6 +36,35 @@ public class ModelUtils {
return bpmnXMLConverter.convertToXML(bpmnModel);
}
/**
* 根据节点,获取入口连线
*
* @param source 起始节点
* @return 入口连线列表
*/
public static List<SequenceFlow> getElementIncomingFlows(FlowElement source) {
List<SequenceFlow> sequenceFlows = new ArrayList<>();
if (source instanceof FlowNode) {
sequenceFlows = ((FlowNode) source).getIncomingFlows();
}
return sequenceFlows;
}
/**
* 根据节点,获取出口连线
*
* @param source 起始节点
* @return 出口连线列表
*/
public static List<SequenceFlow> getElementOutgoingFlows(FlowElement source) {
List<SequenceFlow> sequenceFlows = new ArrayList<>();
if (source instanceof FlowNode) {
sequenceFlows = ((FlowNode) source).getOutgoingFlows();
}
return sequenceFlows;
}
/**
* 获取开始节点
*
@@ -141,4 +169,46 @@ public class ModelUtils {
}
return allElements;
}
/**
* 查找起始节点下一个用户任务列表列表
* @param source 起始节点
* @return 结果
*/
public static List<UserTask> findNextUserTasks(FlowElement source) {
return findNextUserTasks(source, null, null);
}
/**
* 查找起始节点下一个用户任务列表列表
* @param source 起始节点
* @param hasSequenceFlow 已经经过的连线的 ID用于判断线路是否重复
* @param userTaskList 用户任务列表
* @return 结果
*/
public static List<UserTask> findNextUserTasks(FlowElement source, Set<String> hasSequenceFlow, List<UserTask> userTaskList) {
hasSequenceFlow = Optional.ofNullable(hasSequenceFlow).orElse(new HashSet<>());
userTaskList = Optional.ofNullable(userTaskList).orElse(new ArrayList<>());
// 获取出口连线
List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source);
if (!sequenceFlows.isEmpty()) {
for (SequenceFlow sequenceFlow : sequenceFlows) {
// 如果发现连线重复,说明循环了,跳过这个循环
if (hasSequenceFlow.contains(sequenceFlow.getId())) {
continue;
}
// 添加已经走过的连线
hasSequenceFlow.add(sequenceFlow.getId());
FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement();
if (targetFlowElement instanceof UserTask) {
// 若节点为用户任务,加入到结果列表中
userTaskList.add((UserTask) targetFlowElement);
} else {
// 若节点非用户任务,继续递归查找下一个节点
findNextUserTasks(targetFlowElement, hasSequenceFlow, userTaskList);
}
}
}
return userTaskList;
}
}

View File

@@ -50,9 +50,6 @@ import org.springframework.transaction.annotation.Transactional;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
@@ -434,63 +431,71 @@ public class WfTaskServiceImpl extends FlowServiceFactory implements IWfTaskServ
}
/**
* 撤回流程 目前存在错误
* 撤回流程
*
* @param bo
* @return
* @param taskBo 请求实体参数
*/
@Override
public void revokeProcess(WfTaskBo bo) {
Task task = taskService.createTaskQuery().processInstanceId(bo.getProcInsId()).singleResult();
if (task == null) {
throw new RuntimeException("流程未启动或已执行完成,无法撤回");
@Transactional(rollbackFor = Exception.class)
public void revokeProcess(WfTaskBo taskBo) {
String procInsId = taskBo.getProcInsId();
String taskId = taskBo.getTaskId();
// 校验流程是否结束
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
.processInstanceId(procInsId)
.active()
.singleResult();
if(ObjectUtil.isNull(processInstance)) {
throw new RuntimeException("流程已结束或已挂起,无法执行撤回操作");
}
// 获取待撤回任务实例
HistoricTaskInstance currTaskIns = historyService.createHistoricTaskInstanceQuery()
.taskId(taskId)
.taskAssignee(TaskUtils.getUserId())
.singleResult();
if (ObjectUtil.isNull(currTaskIns)) {
throw new RuntimeException("当前任务不存在,无法执行撤回操作");
}
// 获取 bpmn 模型
BpmnModel bpmnModel = repositoryService.getBpmnModel(currTaskIns.getProcessDefinitionId());
UserTask currUserTask = ModelUtils.getUserTaskByKey(bpmnModel, currTaskIns.getTaskDefinitionKey());
// 查找下一级用户任务列表
List<UserTask> nextUserTaskList = ModelUtils.findNextUserTasks(currUserTask);
List<String> nextUserTaskKeys = nextUserTaskList.stream().map(UserTask::getId).collect(Collectors.toList());
List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery()
.processInstanceId(task.getProcessInstanceId())
.orderByTaskCreateTime()
.asc()
// 获取当前节点之后已完成的流程历史节点
List<HistoricTaskInstance> finishedTaskInsList = historyService.createHistoricTaskInstanceQuery()
.processInstanceId(procInsId)
.taskCreatedAfter(currTaskIns.getEndTime())
.finished()
.list();
String myTaskId = null;
HistoricTaskInstance myTask = null;
for (HistoricTaskInstance hti : htiList) {
if (TaskUtils.getUserId().equals(hti.getAssignee())) {
myTaskId = hti.getId();
myTask = hti;
break;
for (HistoricTaskInstance finishedTaskInstance : finishedTaskInsList) {
// 检查已完成流程历史节点是否存在下一级中
if (CollUtil.contains(nextUserTaskKeys, finishedTaskInstance.getTaskDefinitionKey())) {
throw new RuntimeException("下一流程已处理,无法执行撤回操作");
}
}
if (null == myTaskId) {
throw new RuntimeException("该任务非当前用户提交,无法撤回");
}
String processDefinitionId = myTask.getProcessDefinitionId();
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
//变量
// Map<String, VariableInstance> variables = runtimeService.getVariableInstances(currentTask.getExecutionId());
String myActivityId = null;
List<HistoricActivityInstance> haiList = historyService.createHistoricActivityInstanceQuery()
.executionId(myTask.getExecutionId()).finished().list();
for (HistoricActivityInstance hai : haiList) {
if (myTaskId.equals(hai.getTaskId())) {
myActivityId = hai.getActivityId();
break;
// 获取所有激活的任务节点,找到需要撤回的任务
List<Task> activateTaskList = taskService.createTaskQuery().processInstanceId(procInsId).list();
List<String> revokeExecutionIds = new ArrayList<>();
for (Task task : activateTaskList) {
// 检查激活的任务节点是否存在下一级中,如果存在,则加入到需要撤回的节点
if (CollUtil.contains(nextUserTaskKeys, task.getTaskDefinitionKey())) {
// 添加撤回审批信息
taskService.setAssignee(task.getId(), TaskUtils.getUserId());
taskService.addComment(task.getId(), task.getProcessInstanceId(), FlowComment.REVOKE.getType(), LoginHelper.getNickName() + "撤回流程审批");
revokeExecutionIds.add(task.getExecutionId());
}
}
FlowNode myFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(myActivityId);
Execution execution = runtimeService.createExecutionQuery().executionId(task.getExecutionId()).singleResult();
String activityId = execution.getActivityId();
FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityId);
//记录原活动方向
List<SequenceFlow> oriSequenceFlows = new ArrayList<>(flowNode.getOutgoingFlows());
}
private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
Set<Object> seen = ConcurrentHashMap.newKeySet();
return t -> seen.add(keyExtractor.apply(t));
try {
runtimeService.createChangeActivityStateBuilder()
.processInstanceId(procInsId)
.moveExecutionsToSingleActivityId(revokeExecutionIds, currTaskIns.getTaskDefinitionKey()).changeState();
} catch (FlowableObjectNotFoundException e) {
throw new RuntimeException("未找到流程实例,流程可能已发生变化");
} catch (FlowableException e) {
throw new RuntimeException("执行撤回操作失败");
}
}
/**

View File

@@ -225,11 +225,12 @@ export default {
})
},
/** 撤回任务 */
handleRevoke(row){
handleRevoke(row) {
const params = {
procInsId: row.procInsId
}
revokeProcess(params).then( res => {
procInsId: row.procInsId,
taskId: row.taskId
};
revokeProcess(params).then(res => {
this.$modal.msgSuccess(res.msg);
this.getList();
});