Skip to main content

Flowable6.4 – 会签实现方案

Flowable6.4 – 会签实现方案

之前介绍过多实例,但只是理论上如何实现,本文将介绍一种能够实际应用的会签方案。

前面几篇文章描述过如何为一个UserTask节点增加扩展属性,多实例UserTask节点也可以按照之前的方法增加扩展属性。

但是分配办理人时,与普通的UserTask节点稍有不同,不能直接从UserTask节点的扩展属性内获取办理人信息。

如何获得办理人?

首先, 声明一个辅助处理器,用来帮助获得UserTask节点的办理人和检查是否结束多实例节点的办理。主要代码如下:

/**
 * 获得当前节点的处理者列表
 * @param execution 当前执行实例
 * @return 处理者列表
 */
public List<DealerInfo> getList(DelegateExecution execution) {
    FlowElement flowElement = execution.getCurrentFlowElement();
    UserTask userTask = (UserTask) flowElement;
    UserTaskExtension userTaskExtension = FlowUtil.getUserTaskExtension(userTask);
    //DealerInfo是一个实体,用来表示办理人的具体信息
    //从扩展属性内读取UserTask的办理人信息
    //返回一个集合,该集合的数量影响了UserTask多实例的数量
    return userTaskExtension.getDealers();
}

/**
 * 获取会签是否结束
 * @param execution 当前执行实例
 * @return 是否结束
 */
public boolean getComplete(DelegateExecution execution) {
    Integer nrOfCompletedInstances = (Integer) execution.getVariable("nrOfCompletedInstances");
    Integer nrOfInstances = (Integer) execution.getVariable("nrOfInstances");
    int agreeCount = 0, rejectCount = 0, abstainCount = 0;
    Map<String, Object> vars = execution.getVariables();
    for (String key : vars.keySet()) {
        //会签投票以SIGN_VOTE+TaskId标识
        //获得会签投票的统计结果
        if (key.contains(FlowConst.SIGN_VOTE) && !key.equals(FlowConst.SIGN_VOTE_RESULT)) {
            Integer value = (Integer) vars.get(key);
            //统计同意、驳回、弃权票数
            //省略代码若干......
        }
    }
    //以下为一段简单的规则,可以按情况实现自己的会签规则
    if (!nrOfCompletedInstances.equals(nrOfInstances)) {
        //必须等所有的办理人都投票
        return false;
    } else {
        //会签全部完成时,使用默认规则结束
        if (rejectCount > 0) {
            //有反对票,则最终的会签结果为不通过
            //移除SIGN_VOTE+TaskId为标识的参数
            removeSignVars(execution);
            //增加会签结果参数,以便之后流转使用
            execution.setVariable(FlowConst.SIGN_VOTE_RESULT, false);
            //会签结束
            return true;
        } else {
            //没有反对票时,则最终的会签结果为通过
            removeSignVars(execution);
            execution.setVariable(FlowConst.SIGN_VOTE_RESULT, true);
            return true;
        }
    }
}

然后, 对流程图内的UserTask节点进行设置:

上图中的Collection设置为:${mutiInstanceHandler.getList(execution)}

上图中的Completion设置为:${mutiInstanceHandler.getComplete(execution)}

一定要注意的是:Element Var,这个参数将决定多实例中每一个UserTask的办理人。

接下来,设置办理人,之前的教程可以参考《Flowable6.4 - 分派办理人》,主要的代码如下:

/**
 * 分配办理人员
 */
@Override
protected void handleAssignments(TaskService taskService, String assignee, String owner, List<String> candidateUsers, List<String> candidateGroups, TaskEntity task, ExpressionManager expressionManager, DelegateExecution execution) {
    if (null != this.userTaskExtension) {
        //由扩展属性读取办理人规则
        List<DealerInfo> dealerInfos = getDealerInfo();
        if (null == dealerInfos || dealerInfos.size() == 0) {
            throw new RuntimeException("处理者信息不存在");
        }
        if (hasMultiInstanceCharacteristics())
            //多实例节点分配处理者
            //获得传参,流程图中的Element Var
            Object objDealer = execution.getVariable("dealerInfo");
            if (objDealer instanceof DealUserInfo) {
                DealUserInfo userInfo = (DealUserInfo) objDealer;
                assignee = userInfo.getId();
            } else if (objDealer instanceof DealRoleInfo) {
                DealRoleInfo roleInfo = (DealRoleInfo) objDealer;
                task.addGroupIdentityLink(roleInfo.getId(), "role");
            }
        }

    }
    super.handleAssignments(taskService, assignee, owner, candidateUsers, candidateGroups, task, expressionManager, execution);
}

最后, 在Complete流程的时候,按照调用方传回的信息,设置投票的值即可:

//设置会签投票结果
variables.put(FlowConst.SIGN_VOTE + "_" + taskId, signVoteType.getCode());

如何使用会签结果?

在需要判断会签结果的Sequence Flow Condition中直接设置: