基于jeecg-boot的flowable流程收回功能实现(全网首创功能)

更多nbcio-boot功能请看演示系统

gitee源代码地址

后端代码: https://gitee.com/nbacheng/nbcio-boot

前端代码:https://gitee.com/nbacheng/nbcio-vue.git

在线演示(包括H5) : http://122.227.135.243:9888
       

      对于之前的flowable流程,之前有撤回,拒绝,退回等功能,但都不能满足发起人对于流程收回的功能,发起人收回后可以重新进行流程发起,同时能够支持自定义业务的收回功能。

      从目前开源项目与全网的资料看都没有找到相关资料,所以只能自己来写相应的功能,满足用户的需求了。

      版权声明:大家要是单独用我的代码,请注明作者。

     1、首先前端功能

       前端比较简单,只要在已办功能里增加收回菜单功能,同时调用后端代码来实现。

        增加一个菜单按钮

      增加一个收回任务函数基于jeecg-boot的flowable流程收回功能实现(全网首创功能)_第1张图片

      完整的代码如下:



2、后端代码

    2.1  增加一个收回流程功能recallProcess,具体代码如下:

/**
	 *  发起人收回流程
	 *  add by nbacheng
	 *           
	 * @param FlowTaskVo taskVo
	 *           
	 * @return
	 */
	@Override
	@Transactional
	public Result recallProcess(FlowTaskVo flowTaskVo) {
		// 当前任务 listtask
    	List  listtask = taskService.createTaskQuery().processInstanceId(flowTaskVo.getInstanceId()).active().list();
        if (listtask == null) {
            throw new CustomException("流程未启动或已执行完成,无法收回");
        }
        
    	if (taskService.createTaskQuery().taskId(listtask.get(0).getId()).singleResult().isSuspended()) {
            throw new CustomException("任务处于挂起状态");
        }
    	
    	List procInsId = taskService.createNativeTaskQuery().sql("select * from ACT_HI_TASKINST where PROC_INST_ID_ = #{procInsId} ORDER BY START_TIME_ desc").parameter("procInsId", flowTaskVo.getInstanceId()).list();
        
    	SysUser loginUser = iFlowThirdService.getLoginUser();
        String processInstanceId = listtask.get(0).getProcessInstanceId();

        //  获取所有历史任务(按创建时间升序)
        List hisTaskList = historyService.createHistoricTaskInstanceQuery()
        .processInstanceId(processInstanceId).orderByTaskCreateTime()
        .asc()
        .list();
        if (CollectionUtil.isEmpty(hisTaskList) || hisTaskList.size() < 2) {
            log.error("当前流程 【{}】 审批节点 【{}】正在初始节点无法收回", processInstanceId, listtask.get(0).getName());
            throw new FlowableException(String.format("当前流程 【%s】 审批节点【%s】正在初始节点无法收回", processInstanceId, listtask.get(0).getName()));
        }

        //  第一个任务
        HistoricTaskInstance startTask = hisTaskList.get(0);
        //若操作用户不是发起人,不能收回
        if(!StringUtils.equalsAnyIgnoreCase(loginUser.getUsername(), startTask.getAssignee())) {
        	throw new CustomException("操作用户不是发起人,不能收回");
        }
        //  当前任务
        HistoricTaskInstance currentTask = hisTaskList.get(hisTaskList.size() - 1);

        BpmnModel bpmnModel = repositoryService.getBpmnModel(listtask.get(0).getProcessDefinitionId());

        //  获取第一个活动节点
        FlowNode startFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(startTask.getTaskDefinitionKey());
        //  获取当前活动节点
        FlowNode currentFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(currentTask.getTaskDefinitionKey());

        //  临时保存当前活动的原始方向
        List originalSequenceFlowList = new ArrayList<>(currentFlowNode.getOutgoingFlows());
        //  清理活动方向
        currentFlowNode.getOutgoingFlows().clear();

        //  建立新方向
        SequenceFlow newSequenceFlow = new SequenceFlow();
        newSequenceFlow.setId("newSequenceFlowId");
        newSequenceFlow.setSourceFlowElement(currentFlowNode);
        newSequenceFlow.setTargetFlowElement(startFlowNode);
        List newSequenceFlowList = new ArrayList<>();
        newSequenceFlowList.add(newSequenceFlow);
        //  当前节点指向新的方向
        currentFlowNode.setOutgoingFlows(newSequenceFlowList);

        //  完成当前任务
        for(Task task : listtask) {
		    taskService.addComment(task.getId(), listtask.get(0).getProcessInstanceId(),FlowComment.RECALL.getType(), "发起人收回");
		    taskService.setAssignee(task.getId(), startTask.getAssignee());
		    taskService.complete(task.getId());
        }
        

        //  重新查询当前任务
        Task nextTask = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
        if (ObjectUtil.isNotNull(nextTask)) {
            taskService.setAssignee(nextTask.getId(), startTask.getAssignee());
            //taskService.complete(nextTask.getId());;//跳过流程发起节点
        }
        
        //自定义业务处理id
        String dataId = flowTaskVo.getDataId();
        
        // 删除运行和历史的节点信息 
        this.deleteActivity(procInsId.get(1).getTaskDefinitionKey(), flowTaskVo.getInstanceId(), dataId);

        //  恢复原始方向
        currentFlowNode.setOutgoingFlows(originalSequenceFlowList);
        
        //自定义业务处理
        if(StrUtil.isNotBlank(flowTaskVo.getDataId()) && !Objects.equals(flowTaskVo.getDataId(), "null")){
            //如果保存数据前未调用必调的FlowCommonService.initActBusiness方法,就会有问题
            FlowMyBusiness business = flowMyBusinessService.getByDataId(dataId);
            //删除自定义业务任务关联表,以便可以重新发起流程
            if (business != null) {
            	flowMyBusinessService.removeById(business);
            }
	   	}
		return Result.OK("发起人收回成功");
	}

   2.2 调用 删除历史节点信息deleteActivity

/**
     * 删除跳转的历史节点信息
     *
     * @param disActivityId     跳转的节点id
     * @param processInstanceId 流程实例id
     * @param dataId   自定义业务id
     */
    protected void deleteActivity(String disActivityId, String processInstanceId, String dataId) {
        List disActivities = flowTaskMapper
                .queryActivityInstance(disActivityId, processInstanceId, null);

        //删除运行时和历史节点信息
        if (CollectionUtils.isNotEmpty(disActivities)) {
            ActivityInstance activityInstance = disActivities.get(0);
            List datas = flowTaskMapper
                    .queryActivityInstance(disActivityId, processInstanceId, activityInstance.getEndTime());

            //datas.remove(0); //保留流程发起节点信息
            List runActivityIds = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(datas)) {
                datas.forEach(ai -> runActivityIds.add(ai.getId()));
                flowTaskMapper.deleteRunActinstsByIds(runActivityIds);
                flowTaskMapper.deleteHisActinstsByIds(runActivityIds);
            }
            if(dataId != null) {//对于自定义业务, 删除所有相关流程信息
            	//flowTaskMapper.deleteAllHisAndRun(processInstanceId);
                //根据流程实例id 删除去ACT_RU_*与ACT_HI_*流程实例数据
                ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
                if (null != processInstance) {
                    runtimeService.deleteProcessInstance(processInstanceId, "流程实例删除");
                    historyService.deleteHistoricProcessInstance(processInstanceId);
                }
            }
        }
    }

2.3 FlowTaskMapper.xml文件如下:




  
    
    
        delete from act_ru_actinst where ID_ in
        
            #{item}
        
    

    
        delete from act_hi_actinst where ID_ in
        
            #{item}
        
    
    
    
      delete  from  act_ru_actinst  where proc_inst_id_ = #{processInstanceId}; 
      delete  from  act_ru_identitylink  where proc_inst_id_ = #{processInstanceId};
      delete  from  act_ru_task  where proc_inst_id_ = #{processInstanceId};
      delete  from  act_ru_variable  where proc_inst_id_ = #{processInstanceId};
      delete  from  act_ru_execution  where proc_inst_id_ = #{processInstanceId};
      delete  from  act_hi_actinst where proc_inst_id_ = #{processInstanceId};
      delete  from  act_hi_comment where proc_inst_id_ = #{processInstanceId};
      delete  from  act_hi_identitylink  where proc_inst_id_ = #{processInstanceId};
      delete  from  act_hi_procinst where proc_inst_id_ = #{processInstanceId};
      delete  from  act_hi_taskinst where proc_inst_id_ = #{processInstanceId};
      delete  from  act_hi_varinst  where proc_inst_id_ = #{processInstanceId};
    

3、自定义业务与其它流程做分别处理

     其它流程直接删除相关用户任务历史信息,保留初始发送,用户可以直接进行流程重新编辑发送。

     而自定义业务则删除所有实例相关的任务历史信息,不保留任务相关信息,同时删除自定义业务发起时候的写入的关联表,以便用户可以再次发起流程。

你可能感兴趣的:(nbcio-boot,jeecg-boot,java开发,java,spring,boot,vue)