总结:会签任务一票否决

此功能以Activiti5.22为基础版本进行设计实现。其他版本仅做参考。

第一、需开启用户任务会签功能

1、会签串行(用户任务结点以三条横线标识)

总结:会签任务一票否决_第1张图片

 2、会签并行(用户任务结点以三条竖线标识)

总结:会签任务一票否决_第2张图片

 第二、启动时设置

    private Map checkAndParseStartVar(Process process, Map processVar) {
        Assert.isTrue (!CollectionUtils.isEmpty(processVar), "流程变量信息为空");

        Map map = new HashMap<>(processVar.size() + 4);

        List userTasks = process.getFlowElements().stream()
            .filter(flowElement -> flowElement instanceof UserTask)
            .map(flowElement -> (UserTask)flowElement)
            .collect(Collectors.toList());

        for (Entry entry : processVar.entrySet()) {
            ProcessVarDTO dto = entry.getValue();

            Assert.notNull (dto , "键值["
                + entry.getKey() + "]对应的值为空");
            boolean isMultiInstance = userTasks.stream()
                .filter(userTask -> Objects.nonNull(userTask.getLoopCharacteristics()))
                .map(UserTask::getLoopCharacteristics)
                .anyMatch(multiInstanceLoopCharacteristics -> {
                    String key = multiInstanceLoopCharacteristics.getInputDataItem();
                    key = key.replace("${", Symbol.EMPTY).replace("}", Symbol.EMPTY).trim();
                    return key.equals(entry.getKey());
                });

            if (dto.getLongVal() != null) {
                map.put(entry.getKey(), dto.getLongVal());
            } else if (dto.getDoubleVal() != null) {
                map.put(entry.getKey(), dto.getDoubleVal());
            } else if (!CollectionUtils.isEmpty(dto.getCandidate())) {
                String candidate = dto.getCandidate().toString();
                candidate = candidate.substring(1, candidate.length() - 1)
                    .replaceAll("\\D+", ",");
                map.put(entry.getKey(), isMultiInstance ? Lists.newArrayList(dto.getCandidate()) : candidate);
            } else if (dto.getStringVal() != null) {
                map.put(entry.getKey(), isMultiInstance ? Lists.newArrayList(dto.getStringVal().split(Symbol.COMMA)) : dto.getStringVal().trim());
            } else {
                Assert.isTrue(false, "未获取到键[" + entry.getKey() + "]对应的值");
            }
        }

        return map;
    }

第三、会签任务一票否决(主要针对并行任务)

/**
     * 会签结点任务一票否决
     * @param task        当前任务
     * @param variables   参数
     * @param isPass      审批结果(true通过,false驳回)
     */
    private void executeCompleteTask(Task task, Map variables, boolean isPass){
        // 获取流程实例对象
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
            .processInstanceId(task.getProcessInstanceId())
            .singleResult();

        // 获取流程定义对象,主要用于判断流程任务结点是否为会签结点
        Process process = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId())
            .getProcessById(historicProcessInstance.getProcessDefinitionKey());
        if(isPass) { // 审批通过,将后续会签结点中人员转换为集合
            process.getFlowElements().stream()
                .filter(flowElement -> flowElement instanceof UserTask)   // 过滤用户任务结点
                .map(flowElement -> (UserTask) flowElement)// 转换为用户任务
                .filter(userTask -> Objects.nonNull(userTask.getLoopCharacteristics()))// 是否为支持会签功能
                .map(UserTask::getLoopCharacteristics)// 获取会签配置信息
                .map(MultiInstanceLoopCharacteristics::getInputDataItem) // 获取会签配置信息中的人员参数
                .forEach(key -> {
                    String varName = key.replace("${","").replace("}", "");
                    
                    if (!variables.containsKey(varName)) {
                        return;
                    }
                    // 将参数值更新为集合
                    variables.put(varName, Collections.singletonList(variables.get(varName)));
                });
        }

        // 获取当前任务结点
        Optional userTask = process.getFlowElements().stream()
            .filter(flowElement -> task.getTaskDefinitionKey().equals(flowElement.getId()))
            .map(flowElement -> (UserTask)flowElement)
            .findAny();

        boolean isMultiTask = userTask.isPresent() // 存在
            && Objects.nonNull(userTask.get().getLoopCharacteristics()); // 为会签结点

        List tempPvmTransitions = Lists.newArrayList();
        TransitionImpl newTransition = null;
        ActivityImpl endActivity = null;
        ActivityImpl currentActivity = null;
        if(!isPass           // 拒绝
            && isMultiTask // 会签结点
            ) {
            // 获取结束结点
            Optional optional = process.getFlowElements().stream()
                .filter(flowElement -> flowElement instanceof EndEvent)
                .findFirst();

            if(!optional.isPresent()){
                return;
            }

            // 获取已部署流程定义对象
            ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) ((RepositoryServiceImpl)repositoryService)
                .getDeployedProcessDefinition(task.getProcessDefinitionId());

            // 获取已部署流程定义中的结束对象
            endActivity = processDefinitionEntity.findActivity(optional.get().getId());
            
            // 获取已部署流程定义中的当前任务对象
            currentActivity = processDefinitionEntity.findActivity(task.getTaskDefinitionKey());
            // 临时存放当前流出
            List currentActivityPvmTransitions = currentActivity.getOutgoingTransitions();
            tempPvmTransitions.addAll(currentActivityPvmTransitions);
            
            // 清空当前任务结点上的流出
            currentActivityPvmTransitions.clear();

            // 新增当前任务结点流出至结束结点
            newTransition = currentActivity.createOutgoingTransition();
            newTransition.setDestination(endActivity);

            // 设置会签任务结点完成条件
            taskService.setVariable(task.getId(), "nrOfInstances", userTask.get().getLoopCharacteristics().isSequential() ? 0 : 1);
        }

        // 执行任务审批
        taskService.complete(task.getId(), variables);

        if(isPass    // 通过
            || !isMultiTask // 非会签结点
            ){
            return;
        }

        // 还原任务结点流出设置
        // 先清空当前任务结点临时流出(流出至结束结点)
        endActivity.getIncomingTransitions().remove(newTransition);
        currentActivity.getOutgoingTransitions().clear();
        // 再设置原来的流出
        currentActivity.getOutgoingTransitions().addAll(tempPvmTransitions);
    }

第四步、调整界面

以上步骤即可实现会签一票否决。

你可能感兴趣的:(Activity工作流,java)