springboot使用flowable(7)

在运行过程中,我们不想使用这个流程了,可以终止掉

package com.dmg.service;


public interface FlowService {


    public void termination(String processInstanceId);
}
package com.dmg.controller;



/**
 * 流程定义控制层
 */
@RestController
public class ProcessDefinitionController {

    @Autowired
    private FlowService flowService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private TaskService taskService;



    /**
     * 终止流程
     * @return
     */
    @PostMapping(value = "termination")
    public Result termination(@RequestBody FlowReq req){
        flowService.termination(req.getProcessInstanceId());
        return Result.success();
    }


}
package com.dmg.service.impl;

/**
 * 流程定义服务实现类
 */
@Service
public class FlowServiceImpl extends FlowServiceFactory implements FlowService {

    @Autowired
    private HisApprovalMapper hisApprovalMapper;
    @Autowired
    private QjMapper qjMapper;

 
    /**
     * 终止流程-- 当前申请单都废掉了,请重新申请
     * @param processInstanceId
     */
    @Override
    public void termination(String processInstanceId) {
        //查询流程实例
        ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if(instance==null){
            throw new RuntimeException("流程实例不能为空");
        }

        //获取bpmn模型 就是对应流程图xml中  这个标签里面的内容
        Process mainProcess = repositoryService.getBpmnModel(instance.getProcessDefinitionId()).getMainProcess();
        //获取流程元素
        Collection list = mainProcess.getFlowElements();
        //结束节点的id
        String activityId="";
        for (FlowElement x : list) {
            if(x instanceof EndEvent){
                //如果是结束 节点 那么说明找到了
                //就是对应 流程图xml 这个标签 
                activityId=x.getId();
                break;
            }
        }
        if(StringUtils.isEmpty(activityId)){
            throw new RuntimeException("结束节点不存在,流程图绘制有问题");
        }
        //获取运行时执行实例表
        List executions = runtimeService.createExecutionQuery().parentId(processInstanceId).list();
        ListexecutionIds=new ArrayList<>();
        for (Execution x : executions) {
            executionIds.add(x.getId());
        }

        //创建更改活动状态生成器
        runtimeService.createChangeActivityStateBuilder()
                //将执行移动到单个活动 ID  将当前的执行实例 全部移动到结束节点
                .moveExecutionsToSingleActivityId(executionIds,activityId)
                //改变状态
                .changeState();

    }

}

这的x instanceof EndEvent就是下面这个图片展示的位置,他是EndEvent结束节点的信息,

所以我们这里这样操作,才能拿到id

springboot使用flowable(7)_第1张图片

我们来看下结果

http://localhost:8080/termination

{

    "processInstanceId":"47bb34eb-6e30-11ed-be7d-005056c00008"

}

springboot使用flowable(7)_第2张图片

可以看到任务表 和执行实例表的数据都清空了

 springboot使用flowable(7)_第3张图片

在领导审批的时候,我们没有设置驳回的地方,那么领导也可以手动选择一些之前审批的节点,进行退回操作;

注意:并行网关要退回多个分支,我们以出差申请为例子

在总经理审批这里,退回选择节点的时候 必须选一个经理审批和组长审批,

不能经理审批和主管审批,因为经理审批了 才能流转到主管审批,顺序不能错误,

否则流程就走不下去了。

springboot使用flowable(7)_第4张图片

我们先来查询当前的活动节点

package com.dmg.controller;


/**
 * 任务控制层
 */
@RestController
public class TaskController {


    @Autowired
    private QjService qjService;
    @Autowired
    private FlowService flowService;



    /**
     *  查询可以退回的任务节点
     */
    @PostMapping("getNodeList")
    public Result getNodeList(@RequestBody FlowReq req){
        List list = flowService.getNodeList(req.getTaskId());
        return Result.success(list);
    }

}
package com.dmg.vo;

import lombok.Data;

@Data
public class TaskNodeVo {


    /**
     * 任务节点的id  userTask 的id
     */
    private String activityId;


    /**
     * 任务节点的名称
     */
    private String name;

}
package com.dmg.service;

public interface FlowService {
    public List getNodeList(String taskId);
}
package com.dmg.service.impl;


/**
 * 流程定义服务实现类
 */
@Service
public class FlowServiceImpl extends FlowServiceFactory implements FlowService {

    @Autowired
    private HisApprovalMapper hisApprovalMapper;
    @Autowired
    private QjMapper qjMapper;

   

    /**
     * 查询可以退回的任务节点
     * @param taskId
     * @return
     */
    @Override
    public List getNodeList(String taskId){
        List result = new ArrayList<>();
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null){
            return result;
        }
        //获取当前任务的节点id userTask的id
        //
        String taskDefinitionKey=task.getTaskDefinitionKey();

        //查询历史节点实例 并且是完成审批的
        List list = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(task.getProcessInstanceId())
                .finished()
                .orderByHistoricActivityInstanceEndTime().asc()
                .list();

        List activityIdList=new ArrayList<>();
        //遍历出 只有userTask的节点
        for (HistoricActivityInstance x : list) {
           if("userTask".equals(x.getActivityType()) && !taskDefinitionKey.equals(x.getActivityId())){
                //是任务节点 并且不是当前节点
               activityIdList.add(x.getActivityId());
           }
        }
        //获取bpmn模型
        BpmnModel bpmnModel=repositoryService.getBpmnModel(task.getProcessDefinitionId());
        //获取主流程 
        Process process=bpmnModel.getMainProcess();
        //查询当前流节点
        FlowNode currentFlowNode=(FlowNode) process.getFlowElement(taskDefinitionKey,true);

        for (String activityId : activityIdList) {
            // activityId 对应的节点
            FlowNode x = (FlowNode) process.getFlowElement(activityId, true);
            // 判断 是否能从这个节点 到目标节点 因为可能存在历史的节点 所以我们这里要判断一下 防止越界
            Set set = new HashSet<>();
            if (x != null && ExecutionGraphUtil.isReachable(process,x,currentFlowNode, set)) {
                TaskNodeVo nodeVo=new TaskNodeVo();
                nodeVo.setActivityId(x.getId());
                nodeVo.setName(x.getName());
                result.add(nodeVo);
            }
        }
        return result;
    }

   

}

我们来看下结果

http://localhost:8080/getNodeList

{

    "taskId":"da20c629-6e60-11ed-885a-005056c00008"

}

springboot使用flowable(7)_第5张图片

 用户就可以在列表选择一个串行退回,多个并行退回,

在并行网关内,要同时审批完才能走到总经理审批,一定要注意

总经理退回到提交,可以选择一个,因为他前面没有并行网关

package com.dmg.service.impl;


/**
 * 流程定义服务实现类
 */
@Service
public class FlowServiceImpl extends FlowServiceFactory implements FlowService {

    @Autowired
    private HisApprovalMapper hisApprovalMapper;
    @Autowired
    private QjMapper qjMapper;



    /**
     * 退回    并行网关退回多个节点,串行网关退回一个节点
     * @param activityIds 节点id 集合
     * @param taskId 任务id
     */
    @Override
    public void goBack(ListactivityIds,String taskId) {
        if(CollectionUtils.isEmpty(activityIds)){
            throw new RuntimeException("节点不能为空");
        }
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null){
           throw new RuntimeException("任务不存在");
        }
        //获取bpmn模型
        BpmnModel bpmnModel=repositoryService.getBpmnModel(task.getProcessDefinitionId());
        //获取主流程 
        Process process=bpmnModel.getMainProcess();
        //判断当前流程图是否存在并行网关
        int parallel=Integer.MAX_VALUE;
        //获取当前节点之前有没有并行网关
        int index=0;
        for (FlowElement flowElement : process.getFlowElements()) {
            if(flowElement instanceof ParallelGateway){
                parallel=index;
                break;
            }
            index++;
        }
        //节点id 对应的索引
        Mapmap=new HashMap<>();
        int index1=0;
        for (FlowElement flowElement : process.getFlowElements()) {
            map.put(flowElement.getId(),index1);
            index1++;
        }
        FlowNode currentFlowNode = (FlowNode) process.getFlowElement(task.getTaskDefinitionKey(), true);
        for (String activityId : activityIds) {
            int x=map.get(activityId);
            if(x1){
                    throw new RuntimeException("串行请选择一个节点");
                }
            }else {
                //如果当前索引比网关的索引大
                if(activityIds.size()==1){
                    throw new RuntimeException("并行网关请选择多个节点");
                }
            }
            //判断activityId 能否回到当前节点
            // activityId 对应的节点
            FlowNode node = (FlowNode) process.getFlowElement(activityId, true);
            if(node==null){
                throw new RuntimeException("节点不存在");
            }
            // 判断 是否能从这个节点 到目标节点
            Set set = new HashSet<>();
            if (!ExecutionGraphUtil.isReachable(process,node,currentFlowNode, set)) {
                throw new RuntimeException("回退节点不正确,请重新选择");
            }

        }

        if(activityIds.size()>1){
            //说明走的是并行网关 那么校验他们之间是否是挨着的
            for (int i = 0; i 
package com.dmg.service;


public interface FlowService {

  
    public void goBack(ListactivityIds,String taskId);
}
package com.dmg.controller;


/**
 * 任务控制层
 */
@RestController
public class TaskController {


    @Autowired
    private QjService qjService;
    @Autowired
    private FlowService flowService;



    /**
     *  退回
     */
    @PostMapping("goBack")
    public Result goBack(@RequestBody FlowReq req){
        flowService.goBack(req.getActivityIds(),req.getTaskId());
        return Result.success();
    }
}
package com.dmg.vo.req;

import lombok.Data;

import java.util.List;

@Data
public class FlowReq extends PageReq{

    /**
     * 流程定义名称
     */
    private String processDefinitionName;


    /**
     * 流程定义key
     */
    private String processDefinitionKey;


    /**
     * 任务id
     */
    private String taskId;


    /**
     *  当前人账号
     */
    private String account;


    /**
     * 流程定义id
     */
    private String processDefinitionId;

    /**
     * 流程实例id
     */
    private String processInstanceId;

    /**
     * 部署id
     */
    private String deploymentId;

    /**
     *  如果为true 已经启动的流程关联的数据也一并删除 历史流程也会删除
     *  如果为false 只删除运行 并且没有任务的流程信息
     */
    private Boolean cascade;

    /**
     * 任务节点id集合
     */
    List activityIds;
}

我们来看下结果

http://localhost:8080/goBack

{

    "taskId":"da20c629-6e60-11ed-885a-005056c00008",

    "activityIds":[

        "sid-F176B67F-64F3-4239-B8EC-2A3BC2E0EFFE"

    ]

}

springboot使用flowable(7)_第6张图片

我们选择回退到提交单,可以在表中act_ru_task看到回退到提交单了

springboot使用flowable(7)_第7张图片

springboot使用flowable(8)_我是一只代码狗的博客-CSDN博客

你可能感兴趣的:(flowable,java,spring,boot,java,后端)