在Activiti中如何判断当前任务的状态?

在activiti中, 对于正在执行的任务, 已经执行过得任务, 未执行的任务可以判断出来, 但是还有一种状态, 就是任务已经执行过了, 但是因为后面因为流程选择关系又回到了这个任务的前面一些任务, 那这个任务可能还会执行一遍, 如何判断任务的这个状态?

比如下面这个请假流程图
clipboard.png
当执行到人事审批这边, 人事审批拒绝了当前申请, 开始调整申请任务, 所以人事审批有可能还会执行一次, 这个已经执行过, 但是可能还会执行的状态改如何判断?

阅读 10.5k
2 个回答

自己琢磨了一下, 找到了满足自己的这个要求的解决方法, 主要就是对于已经执行过的任务的状态进行判断, 比如审批任务, 如果审批不通过, 则会退回到申请步骤, 所以这个时候审批任务是执行完成过一次, 但是可能还会执行一次, 对于这个状态我判定的思路是这样的:
首先根据ProcessInstanceID可以获得该流程所有的历史活动实例(ACT_HI_ACTINS表)的, 按时间排序后进行遍历, 将activityID放入到一个数组中, 如果一个activityId重复出现了两次, 则这两个activityId中间的则是这种状态的, 然后将部分从数组中移除

代码

    public Map<String, TaskCoordinate> getTaskCoordinates(String processInstanceId) {
        log.debug("in get activiti process image function");

        try {
            // 获取历史流程实例
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                    .processInstanceId(processInstanceId).singleResult();
            if (historicProcessInstance == null) {
                throw new CustomException("示例" + processInstanceId + "不存在");
            }

            ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
                    .getDeployedProcessDefinition(historicProcessInstance.getProcessDefinitionId());

            // 获取流程历史中已执行的节点, 并按照节点在流程中执行先后顺序排序
            List<HistoricActivityInstance> historicActivityInstances = historyService.createHistoricActivityInstanceQuery()
                    .processInstanceId(processInstanceId).orderByHistoricActivityInstanceId().asc().list();

            // 已执行节点的坐标集合
            executedCoordinates = new HashMap<>();

            // 按任务的执行顺序存放taskId
            activityIds = new ArrayList<>();

            log.debug(">>>>>>>>>>>>>>>>>>>>>获取已经执行的节点ID<<<<<<<<<<<<<<<<<<<<<");
            for (HistoricActivityInstance activityInstance : historicActivityInstances) {
                // 如果是用户任务类型
                if (StringUtils.equalsIgnoreCase(activityInstance.getActivityType(), "userTask")) {
                    updateTaskCoordinate(activityInstance, processDefinition);

                }
            }

            return executedCoordinates;
        } catch (Exception e) {
            log.error("获取已执行任务坐标失败, message --> {}", e.getMessage());
             throw new CustomException("获取任务失败!" + e.getMessage());
        }
    }
    
       /**
     * 更新当前活动的状态级添加任务处理信息
     *
     * @param activityInstance 活动示例
     * @param taskCoordinate   任务坐标信息
     */
    private void updateTaskCoordinate(HistoricActivityInstance activityInstance, TaskCoordinate taskCoordinate) {
        // 根据当前任务是否有结束时间来判断是否为进行中的任务
        if (activityInstance.getEndTime() == null) {
            taskCoordinate.setType(TaskCoordinate.TASK_IN_PROCESS);
        } else {
            taskCoordinate.setType(TaskCoordinate.TASK_COMPLETED);
        }
        TaskInfo taskInfo = new TaskInfo(activityInstance.getTaskId(), activityInstance.getAssignee(), activityInstance.getEndTime());
        taskCoordinate.addTaskInfo(taskInfo);
    }

    /**
     * 更新任务状态
     *
     * @param activityInstance
     * @param processDefinition
     */
    private void updateTaskCoordinate(HistoricActivityInstance activityInstance, ProcessDefinitionEntity processDefinition) {
        ActivityImpl activity = processDefinition.findActivity(activityInstance.getActivityId());
        TaskCoordinate taskCoordinate;
        String activityId = activityInstance.getActivityId();

        activityIds.add(activityId);
        log.debug("activity id list  --> {}", activityIds);

        if (executedCoordinates.get(activityId) == null) {
            // 新建coordinate对象, 设置act_id及坐标
            taskCoordinate = new TaskCoordinate();
            taskCoordinate.setNode(activityInstance.getActivityId());
            taskCoordinate.setName(activityInstance.getActivityName());
            taskCoordinate.setCoordinate(activity.getX(), activity.getY(), activity.getWidth(), activity.getHeight());
            // 更新状态和添加任务信息
            updateTaskCoordinate(activityInstance, taskCoordinate);
            executedCoordinates.put(activityId, taskCoordinate);
        } else {
            // 从map中获取coordinate对象
            taskCoordinate = executedCoordinates.get(activityId);
            // 更新状态和添加任务信息
            updateTaskCoordinate(activityInstance, taskCoordinate);
            executedCoordinates.put(activityId, taskCoordinate);


            int preIndex = preIndexOfLastTaskId(activityIds, activityId);
            log.debug("preIndex --> {}", preIndex);
            if (preIndex != -1) {
                // 得到需要设置状态为other的子列表取出来
                List<String> subActivityIds = activityIds.subList(preIndex + 1, activityIds.size() - 1 - 1);
                // 将状态为other的元素去掉
                activityIds = activityIds.subList(0, preIndex + 1);
                if (subActivityIds.size() > 0) {
                    log.info("sub task id list --> ", subActivityIds);
                    for (String subTaskId : subActivityIds) {
                        executedCoordinates.get(subTaskId).setType(TaskCoordinate.TASK_OTHER);
                    }
                }
            }
        }
    }

    /**
     * 得到list最后一个activityID的前一个值相同的小标
     *
     * @param list    list
     * @param lastStr last activity id
     * @return
     */
    private int preIndexOfLastTaskId(List<String> list, String lastStr) {

        return list.subList(0, list.size() - 1 - 1).lastIndexOf(lastStr);
    } 

javaBean

@Data
public class TaskCoordinate {
    public static final Integer TASK_UNEXECUTED = 0;    // 未执行
    public static final Integer TASK_COMPLETED = 1;     // 任务已完成
    public static final Integer TASK_IN_PROCESS = 2;    // 任务进行中
    public static final Integer TASK_OTHER = 3;         // 执行过, 可能还会被执行

    private String node;                // 对应activityId
    private String name;                // 对应activityName
    private Integer type;               // 任务类型
    private List<TaskInfo> taskInfos;

    // 坐标
    private Integer x;
    private Integer y;
    private Integer width;
    private Integer height;

    public TaskCoordinate() {
        this.taskInfos = new ArrayList<>();
    }

    public TaskCoordinate(String node, Integer type) {
        this.taskInfos = new ArrayList<>();
        this.node = node;
        this.type = type;
    }

    /**
     * 给当前的流程节点添加一条任务信息
     *
     * @param taskInfo
     */
    public void addTaskInfo(TaskInfo taskInfo) {
        this.taskInfos.add(taskInfo);
    }

    /**
     * 设置坐标
     *
     * @param x      x
     * @param y      y
     * @param width  宽度
     * @param height 高度
     */
    public void setCoordinate(int x, int y, int width, int height) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
    }
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TaskInfo {
    private String taskId;      // 任务id

    private String assignee;    // 办理人

    private Date completeTime;  // 完成时间
}

因为现在需求中的场景比较简单, 对于使用并行网关的情况并没有考虑, 对于复杂的流程可能还需要改进

带变量,将流程经过的节点写在变量中?
或者直接在数据库中标记流程经过的每一个节点,到达节点的时候根据流程id去判断就可以了。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏