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)
  • 流程管理(支持流程在线设计器、发布/部署、挂起、激活、导出/导入、配置表单、启动、删除)
  • 表单管理(支持快速表单在线设计器、增/删/改/查、预览表单)
  • 我的流程(发起流程申请)
  • 我的待办(支持快速办理、查看任务表单办理、历史审批意见、流程实时流转图等)
  • 我的已办(支持撤回功能)
  • 我的申请(查看所有当前用户申请过的流程情况)
  • 更多功能,还在不懈努力地完善中…
  • 3
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 22
    评论
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值