Flowable流程开发笔记

Flowable 流程引擎开发笔记

常用表

运行时表(流程运行中才有数据,结束后自动清理)

表名 存什么 说明
ACT_RU_TASK 当前待办任务 ASSIGNEE_ 为 null 表示在候选人池,有值表示已被认领
ACT_RU_IDENTITYLINK 任务的候选人/参与者 TYPE_ = candidate 是候选人,assignee 是指派人
ACT_RU_VARIABLE 流程变量 存流程实例级别的变量数据
ACT_RU_EXECUTION 流程执行实例 一个流程实例可能有多条执行线(会签时)
ACT_RU_ACTINST 当前活跃的活动节点 当前流程走到哪个节点了

历史表(流程结束后数据移到这些表)

表名 存什么 说明
ACT_HI_TASKINST 所有任务(含已完成的) 流程的所有审批记录都在这里
ACT_HI_PROCINST 所有流程实例 START_USER_ID_ 是发起人
ACT_HI_ACTINST 所有活动节点历史 每个节点的开始、结束时间
ACT_HI_VARINST 历史流程变量 流程变量变更记录

其他

表名 存什么 说明
ACT_RE_PROCDEF 流程定义 部署的 BPMN 模型
ACT_RE_DEPLOYMENT 部署记录 每次发布流程的版本

常用查询

找当前待办

sql 复制代码
-- 查某人的待办
SELECT * FROM ACT_RU_TASK WHERE ASSIGNEE_ = 'loginName';

-- 查候选人池里的任务
SELECT * FROM ACT_RU_TASK WHERE ASSIGNEE_ IS NULL;

查候选人

sql 复制代码
-- 查某个 task 的所有候选人
SELECT * FROM ACT_RU_IDENTITYLINK 
WHERE TASK_ID_ = 'taskId' AND TYPE_ = 'candidate';

-- 查 group 下的候选人
SELECT * FROM ACT_RU_IDENTITYLINK 
WHERE GROUP_ID_ = 'groupId' AND TYPE_ = 'candidate';

查流程历史

sql 复制代码
-- 查某个流程实例的所有审批记录
SELECT * FROM ACT_HI_TASKINST 
WHERE PROC_INST_ID_ = '流程实例ID' 
ORDER BY START_TIME_;

-- 查某人发起的所有流程
SELECT * FROM ACT_HI_PROCINST WHERE START_USER_ID_ = 'loginName';

TaskTransferService

java 复制代码
package com.oda.apps.iplm.service.impl;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.TaskService;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Slf4j
@Service
public class TaskTransferService {

    @Autowired
    private TaskService taskService;

    /**
     * 直接转办给新人(适用于已签收/认领的任务)
     */
    @Transactional(rollbackFor = Exception.class)
    public void reassign(String taskId, String newAssignee) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null) throw new RuntimeException("任务不存在:" + taskId);

        taskService.setAssignee(taskId, newAssignee);
        taskService.addComment(taskId, task.getProcessInstanceId(),
                "转办:" + task.getAssignee() + " → " + newAssignee);
        log.info("转办 {}/{} : {} → {}", taskId, task.getName(), task.getAssignee(), newAssignee);
    }

    /**
     * 替换候选人池:移除旧人,加入新人
     * 适用场景:任务没人认领,离职的人从候选人池移除,新人加进去
     */
    @Transactional(rollbackFor = Exception.class)
    public void replaceCandidate(String taskId, String oldUser, String newUser) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null) throw new RuntimeException("任务不存在:" + taskId);

        // 如果旧人已经签收了,一并转交
        if (StrUtil.isNotBlank(task.getAssignee()) && task.getAssignee().equals(oldUser)) {
            taskService.setAssignee(taskId, newUser);
        }

        taskService.deleteCandidateUser(taskId, oldUser);
        taskService.addCandidateUser(taskId, newUser);
        taskService.addComment(taskId, task.getProcessInstanceId(),
                "候选人变更:" + oldUser + " → " + newUser);
        log.info("候选人变更 {}/{} : {} → {}", taskId, task.getName(), oldUser, newUser);
    }

    /**
     * 通过流程实例ID转办
     */
    @Transactional(rollbackFor = Exception.class)
    public void transferByProcessInstance(String processInstanceId, String oldUser, String newUser) {
        List<Task> tasks = taskService.createTaskQuery()
                .processInstanceId(processInstanceId)
                .active()
                .list();

        for (Task task : tasks) {
            if (StrUtil.isNotBlank(task.getAssignee()) && task.getAssignee().equals(oldUser)) {
                taskService.setAssignee(task.getId(), newUser);
            }
            taskService.deleteCandidateUser(task.getId(), oldUser);
            taskService.addCandidateUser(task.getId(), newUser);
        }
        log.info("流程 {} 转办:{} → {}", processInstanceId, oldUser, newUser);
    }
}

调用方式

java 复制代码
@Autowired
private TaskTransferService taskTransferService;

// 场景一:任务已被离职的人签收,直接转给新人
taskTransferService.reassign(taskId, "新人LoginName");

// 场景二:任务还在候选人池,替换候选人
taskTransferService.replaceCandidate(taskId, "离职人LoginName", "新人LoginName");

// 场景三:只有流程实例ID,不知道taskId
taskTransferService.transferByProcessInstance(processInstanceId, "离职人LoginName", "新人LoginName");

几个概念

概念 说明
taskId 任务ID,具体某个审批节点的ID,ACT_RU_TASK.ID_
processInstanceId 流程实例ID,整条审批的ID,createWorkflow 的返回值
assignee 指派人,任务被谁签收了,不为 null 表示有人认领了
candidate 候选人,任务可以被这些人处理,谁先点谁签收
claim 签收/认领,候选人把任务拿到自己名下,之后只有他能处理
签收 vs 未签收 assignee 有值=签收了,null=还没人认领
相关推荐
喜欢打篮球的普通人7 小时前
MiniMind 学习笔记(十二):Pretrain 实操——从版本梳理到 8GB 显卡上的真实训练
人工智能·笔记·学习
坤坤子吖8 小时前
算法学习——高精度加减乘除
c++·笔记·学习·算法
Answer1st9 小时前
【HAL库】嵌入式思路(一)
笔记
AOI小白新手上路9 小时前
深度学习模块缝合方法论 · 人物蒸馏笔记
人工智能·笔记·深度学习
AOI小白新手上路10 小时前
韦东山 3-5 I.MX6ULL 的 LED 编程 · 学习笔记
arm开发·笔记·单片机·学习·架构·硬件架构
M78佐菲10 小时前
ARM学习笔记(9)
linux·arm开发·笔记·嵌入式硬件·学习
東隅已逝,桑榆非晚11 小时前
priority_queue的介绍和使用
c++·经验分享·笔记·学习
驭渊的小故事11 小时前
MyBatis 入门:从 JDBC 到优雅操作数据库(一)
笔记·sql·spring
zhangrelay13 小时前
机器人或计算机智能与时间相关案例汇总(ROS2-ROS1)
linux·笔记·学习·ubuntu·机器人
Neo Wordsworth13 小时前
随便笔记2
笔记