zoukankan      html  css  js  c++  java
  • Activiti7开发(三)-流程实例

    0.前言

    流程实例是与业务相关联的,先介绍一下业务:用户申请物品,领导进行审批(同意/拒绝),同意:流程结束,申请状态为通过;拒绝:流程结束,申请状态为拒绝。

    下图为流程图,key为material_apply

    可以看到,"销售支持审批"设置的是变量${sale_support_member},逻辑是只能角色是"销售支持"的用户才可以审批。

    saleSupportVerify这个用户任何节点设置了两个表单属性

    FormProperty_regionAdvice--__!!radio--__!!审批意见--__!!i--__!!同意--__--不同意
    FormProperty_regionText--__!!textarea--__!!批注--__!!f__!!null
    

    一个单选按钮:同意/驳回;一个输入框:可以写驳回理由等等。

    在走向结束时,设置一个监听器,用来修改实体类的状态

    @Slf4j
    @Controller
    public class MaterialListener implements ExecutionListener{
        //获取流程图设置的状态值
        private Expression state;
    
        //一旦是走拒绝和最后审批的同意的都会触发这个监听器
        //拒绝 state=2
        //最后一个审批的同意 state=3
        @Override
        public void notify(DelegateExecution delegateExecution) {
            Material material = new Material();
            String processInstanceId = delegateExecution.getProcessInstanceId();
    
            String status = (String)state.getValue(delegateExecution);
    
            ProcessInstance processInstance = SpringUtils.getBean(RuntimeService.class).createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            material.setId(Long.parseLong(processInstance.getBusinessKey()));
            if(status.equals("3")){
                material.setApplyStatus('3');
            }else if(status.equals("2")){
                material.setApplyStatus('2');
            }
            material.setUpdateBy(SecurityUtils.getUsername());
            material.setUpdateTime(new Date());
    
            SpringUtils.getBean(IMaterialService.class).updateById(material);
        }
    }
    

    1.创建流程实例

    注:businessKey是关键点,是实体类的id,从而与流程定义进行关联,并设置候选人(在此有一个问题,如果后期将某个人设置角色为销售支持,但他在自己的待办任务里面是看不到之前销售提交的审批任务的)

    public AjaxResult submitApply(@RequestBody Material material){
        //目前只设计了一级审批 销售支持部审批
        try{
            //将角色与每个审批用户做关联
            List<String> saleSupportList = materialService.listByRoleName("sale_support_member");
    
            String saleSupportJoin = StringUtils.join(saleSupportList,",");
    
            // regionManager regionDirector president
            ProcessInstance processInstance = runtimeService.createProcessInstanceBuilder()
                    .processDefinitionKey("material_apply")
                    .name(material.getApplyTitle())
                    //将流程实例与物料做关联
                    .businessKey(material.getId()+"")
                    .variable("sale_support_member",saleSupportJoin)
                    .start();
    
            log.info("processInstanceId: "+processInstance.getProcessInstanceId());;
            log.info("id: "+processInstance.getId());
    
            material.setInstanceId(processInstance.getId());
            //申请中
            material.setApplyStatus('1');
            materialService.updateById(material);
            return AjaxResult.success("提交申请成功");
        }catch (Exception e){
            log.error("submitApply error: "+e.getMessage());
            return AjaxResult.error("提交申请失败");
        }
    }
    

    2.撤销申请(未实现)

    逻辑:删除流程实例或者修改流程实例的状态为挂起
    问题: 根据流程实例id没有获取到流程实例?

    如果流程实例已结束,根据流程实例id获取不到流程实例;但目前只是刚创建了流程实例

    public AjaxResult cancelApply(@RequestBody String instanceId) {
    	String msg = processDefinitionService.cancelApply(instanceId, "用户撤销");
    	return success(msg);
    }
    
    public String cancelApply(String instanceId, String reason) {
            ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId(instanceId)
                    .singleResult();
            if(instance != null){
                //说明流程实例还在进行中,可以撤销
                runtimeService.deleteProcessInstance(instanceId,reason);
                return "撤销申请成功";
            }else{
                return "流程已结束,不允许撤销申请";
            }
    }
    
    // 执行此方法后未审批的任务 act_ru_task 会被删除,流程历史 act_hi_taskinst 不会被删除,并且流程历史的状态为finished完成
    
    public String cancelApply(String instanceId, String reason) {
    	ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId("e7361785-ec2c-11eb-89e3-0068ebbadc17")
    					.singleResult();
    		//true-暂停 false-激活
    		boolean suspend = instance.isSuspended();
    		String processInstanceId = instance.getId();
    
    		if(suspend){
    			//如果已暂停,就激活
    			runtimeService.activateProcessInstanceById(processInstanceId);
    			log.info("流程实例已激活");
    			runtimeService.deleteProcessInstance(instanceId, reason);
    			return "流程实例已激活";
    		}else{
    			//如果已激活,就暂停
    			runtimeService.suspendProcessInstanceById(processInstanceId);
    			log.info("流程实例已暂停");
    			runtimeService.deleteProcessInstance(instanceId, reason);
    			return "流程实例已暂停";
    		}
    	}
    }
    

    3.查看审批历史(流程实例)

    有两种:

    • 只获取审批节点(即只获取userTask)
    • 获取全部节点,比如startEvent、userTask、gateWay、endEvent
    public AjaxResult historyProcess(@PathVariable("instanceId") String instanceId) {
    
            List<HistoricTaskInstance> list=historyService // 历史相关Service
                    .createHistoricTaskInstanceQuery() // 创建历史任务实例查询
                    .processInstanceId(instanceId) // 用流程实例id查询
                    .finished() // 查询已经完成的任务
                    .list();
    				
    		list.stream().sorted(Comparator.comparing(HistoricTaskInstance::getStartTime));
    
            List<ApplyHis> applyHisList = new ArrayList<>();
            list.stream().forEach(
                    ht -> {
                        ApplyHis applyHis = new ApplyHis();
                        applyHis.setTaskName(ht.getName());
                        applyHis.setAssignee(ht.getAssignee());
                        applyHis.setStartTime(ht.getStartTime());
                        if(ht.getEndTime() != null){
                            applyHis.setEndTime(ht.getEndTime());
                        }
                        applyHisList.add(applyHis);
                    }
            );
    
            return AjaxResult.success(applyHisList);
     }
    

    4.查看审批高亮图

    该功能设计三个请求:

    1. 根据流程实例id获取流程定义id、部署id、资源名
    public AjaxResult getDefinitionsByInstanceId(@PathVariable("instanceId") String instanceId){
         ProcessInstance pi = runtimeService // 获取运行时Service
                .createProcessInstanceQuery() // 创建流程实例查询
                .processInstanceId(instanceId) // 用流程实例id查询
                .singleResult();
        if(pi != null){
            log.info("流程正在执行!");
            log.info("流程定义id: "+pi.getProcessDefinitionId());
            return AjaxResult.success(processDefinitionService.getDefinitionsByInstanceId(instanceId));
        }else{
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(instanceId).singleResult();
            String processDefinitionId = historicProcessInstance.getProcessDefinitionId();
            ProcessDefinitionQuery pdq = repositoryService.createProcessDefinitionQuery();
            ProcessDefinition pd = pdq.processDefinitionId(processDefinitionId).singleResult();
            log.info("********************************************************************************");
            log.info("deploymentId: "+pd.getDeploymentId());
            String resourceName = pd.getResourceName();
            log.info("resourceName: "+resourceName);
            log.info("流程定义id: "+pd.getId());
            log.info("********************************************************************************");
            return AjaxResult.success(new DefinitionIdDTO(pd.getDeploymentId(),resourceName,pd.getId()));
    
        }
    }
    
    1. 根据流程实例id和流程定义id获取json形式的高亮数据
    public AjaxResult gethighLine(@RequestParam("instanceId") String instanceId,@RequestParam("processDefinitionId") String processDefinitionId) {
    	ActivitiHighLineDTO activitiHighLineDTO = activitiHistoryService.getHighLine(instanceId,processDefinitionId);
    	return AjaxResult.success(activitiHighLineDTO);
    }
    
    public ActivitiHighLineDTO getHighLine(String instanceId,String processDefinitionId) {
    
    	//只有流程没走完的才能查找到流程实例
    	//ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(instanceId).singleResult();
    	//获取bpmnModel对象
    	BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
    	//因为我们这里只定义了一个Process 所以获取集合中的第一个即可
    	Process process = bpmnModel.getProcesses().get(0);
    	//获取所有的FlowElement信息
    	Collection<FlowElement> flowElements = process.getFlowElements();
    
    	Map<String, String> map = new HashMap<>();
    	for (FlowElement flowElement : flowElements) {
    		//判断是否是连线
    		if (flowElement instanceof SequenceFlow) {
    			SequenceFlow sequenceFlow = (SequenceFlow) flowElement;
    			String ref = sequenceFlow.getSourceRef();
    			String targetRef = sequenceFlow.getTargetRef();
    			map.put(ref + targetRef, sequenceFlow.getId());
    		}
    	}
    
    	//获取流程实例 历史节点(全部)
    	List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery()
    			.processInstanceId(instanceId)
    			.list();
    	//各个历史节点   两两组合 key
    	Set<String> keyList = new HashSet<>();
    	for (HistoricActivityInstance i : list) {
    		for (HistoricActivityInstance j : list) {
    			if (i != j) {
    				keyList.add(i.getActivityId() + j.getActivityId());
    			}
    		}
    	}
    	//高亮连线ID
    	Set<String> highLine = new HashSet<>();
    	keyList.forEach(s -> highLine.add(map.get(s)));
    
    
    	//获取流程实例 历史节点(已完成)
    	List<HistoricActivityInstance> listFinished = historyService.createHistoricActivityInstanceQuery()
    			.processInstanceId(instanceId)
    			.finished()
    			.list();
    	//高亮节点ID
    	Set<String> highPoint = new HashSet<>();
    	listFinished.forEach(s -> highPoint.add(s.getActivityId()));
    
    	//获取流程实例 历史节点(待办节点)
    	List<HistoricActivityInstance> listUnFinished = historyService.createHistoricActivityInstanceQuery()
    			.processInstanceId(instanceId)
    			.unfinished()
    			.list();
    
    	//需要移除的高亮连线
    	Set<String> set = new HashSet<>();
    	//待办高亮节点
    	Set<String> waitingToDo = new HashSet<>();
    	listUnFinished.forEach(s -> {
    		waitingToDo.add(s.getActivityId());
    
    		for (FlowElement flowElement : flowElements) {
    			//判断是否是 用户节点
    			if (flowElement instanceof UserTask) {
    				UserTask userTask = (UserTask) flowElement;
    
    				if (userTask.getId().equals(s.getActivityId())) {
    					List<SequenceFlow> outgoingFlows = userTask.getOutgoingFlows();
    					//因为 高亮连线查询的是所有节点  两两组合 把待办 之后  往外发出的连线 也包含进去了  所以要把高亮待办节点 之后 即出的连线去掉
    					if (outgoingFlows != null && outgoingFlows.size() > 0) {
    						outgoingFlows.forEach(a -> {
    							if (a.getSourceRef().equals(s.getActivityId())) {
    								set.add(a.getId());
    							}
    						});
    					}
    				}
    			}
    		}
    	});
    
    	highLine.removeAll(set);
    	Set<String> iDo = new HashSet<>(); //存放 高亮 我的办理节点
    	//当前用户已完成的任务
    	List<HistoricTaskInstance> taskInstanceList = historyService.createHistoricTaskInstanceQuery()
    //                    .taskAssignee(SecurityUtils.getUsername())
    			.finished()
    			.processInstanceId(instanceId).list();
    
    	taskInstanceList.forEach(a -> iDo.add(a.getTaskDefinitionKey()));
    
    	ActivitiHighLineDTO activitiHighLineDTO =new ActivitiHighLineDTO();
    	activitiHighLineDTO.setHighPoint(highPoint);
    	activitiHighLineDTO.setHighLine(highLine);
    	activitiHighLineDTO.setWaitingToDo(waitingToDo);
    	activitiHighLineDTO.setiDo(iDo);
    
    	return activitiHighLineDTO;
    }
    

    返回结果

    {
      "highPoint" : ["StartEvent_1"],
      "highLine" : [null,"Flow_0w19svd"],
      "waitingToDo" : ["saleSupportVerify"],
      "iDo" : []
    }
    
    1. 根据第一个请求返回的部署id和资源名称获取xml
    public void getProcessDefineXML(HttpServletResponse response,
                                        @RequestParam("deploymentId") String deploymentId,
                                        @RequestParam("resourceName") String resourceName) throws IOException {
            processDefinitionService.getProcessDefineXML(response, deploymentId, resourceName);
    }
    
    1. 将xml和第二个请求的响应数据结合,最后显现高亮进度图
  • 相关阅读:
    数据结构与算法----双向链表
    数据结构与算法----数学应用之一元多项式
    数据结构----线性表顺序和链式结构的使用(c)
    Android--Otto事件总线 -- 组件之间通讯框架使用 --模式解析
    递归 —— 二分查找法 —— 归并排序
    自己做悬浮拖拽按钮依赖
    RePlugin 插件化-内置加载
    Android图片处理--缩放
    数据结构与算法---常用三大排序算法
    Android图片处理--全景查看效果
  • 原文地址:https://www.cnblogs.com/lhxBlogs/p/15091786.html
Copyright © 2011-2022 走看看