本文以一套运行二十年的工作流引擎为样本,分析其五表分立的控制表设计,供做引擎设计的读者参考。
副标题:流程引擎与业务数据各安其位——该引擎 工作流控制表设计揭秘 系列:该平台 BPM 技术白皮书 · 1.6 关键词:五表分立、WF_GenerWorkFlow、待办驱动、业务报表、轨迹审计、中西方设计差异
如果你打开 Activiti、Camunda 或 Flowable 的数据库,你会看到 ACT_RU_EXECUTION、ACT_RU_TASK、ACT_RU_VARIABLE 等高度抽象的运行时表——所有流程、所有业务,共用同一套"引擎骨架"。
如果你打开该平台工作流(该引擎)的数据库,你会看到另一幅图景:
WF_GenerWorkFlow、WF_GenerWorkerListNDxxRptNDxxxTrackPort_* 体系中这不是"表多",而是二十余年中国企业流程交付沉淀出的设计选择:流程引擎管流转,业务数据管业务,组织身份管人,轨迹表管审计——五类表,各安其位。
本文结合 该引擎 源码(该引擎/Components/BP.WF)与前端实现(``),客观解析这套设计为何成立、与西方引擎有何本质差异,以及各自适合什么交付场景。
该平台工作流将运行期数据划分为五个相互独立、通过 WorkID / OID 松耦合关联的层次:
┌─────────────────────────────────────────────────────────────────┐
│ 该平台工作流 · 五表分立模型 │
├──────────────┬──────────────┬──────────────┬──────────┬─────────┤
│ ① 流程实例 │ ② 工作人员 │ ③ 业务数据 │ ④ 组织身份 │ ⑤ 轨迹 │
│ WF_Gener │ WF_Gener │ NDxxRpt │ Port_* │ NDxx │
│ WorkFlow │ WorkerList │ (+节点表单) │ │ Track │
├──────────────┼──────────────┼──────────────┼──────────┼─────────┤
│ 流程跑到哪了 │ 谁在办、办没办 │ 表单采集了什么 │ 人/部门/岗 │ 历史操作 │
│ 状态/标题/节点│ 待办/已办/会签 │ 报表/查询/归档 │ 选人/权限 │ 审计/回溯 │
└──────────────┴──────────────┴──────────────┴──────────┴─────────┘
WorkID / OID 关联定位:存储流程引擎级别的运行摘要,一条记录对应一个流程实例(WorkID)。
核心字段(见 GenerWorkFlow.cs):
字段 | 含义 |
|---|---|
WorkID | 流程实例唯一标识 |
FK_Flow / FlowName | 流程编号与名称 |
WFState / WFSta | 详细状态 / 概要状态 |
Title | 流程标题 |
Starter / RDT | 发起人 / 发起时间 |
FK_Node / NodeName | 当前停留节点 |
FID | 子流程/分流时的父实例关联 |
PWorkID / PFlowNo | 父流程关联 |
设计意图:待办列表、流程监控、催办预警、子流程导航——凡"流程跑到哪了"的问题,查这一张表即可,无需扫描业务宽表。
在 WorkNode.cs 的发送逻辑中,节点流转时首先更新 GenerWorkerList.IsPass,再同步 HisGenerWorkFlow.WFState、FK_Node 等字段——引擎状态与业务表单写入解耦。
定位:存储"谁在哪个节点办理哪条流程"的工作人员记录,是待办、已办、会签、队列审批的数据源。
核心字段(见 GenerWorkerList.cs):
字段 | 含义 |
|---|---|
WorkID + FK_Node + FK_Emp | 复合主键:实例 × 节点 × 执行人 |
IsPass | 是否已处理(0=待办,1=已办) |
IsRead | 是否已读 |
IsEnable | 是否有效(撤回/跳转后失效) |
SDT / CDT | 应完成时间 / 实际完成时间 |
IsHuiQian / Idx | 会签标识 / 顺序号 |
设计意图:
WorkID 可有多条 GenerWorkerList 记录SELECT * FROM WF_GenerWorkerList WHERE FK_Emp=@emp AND IsPass=0 —— 无需 JOIN 复杂运行时表ACT_RU_TASK 对比:该平台将"任务"与"流程实例摘要"物理分离,待办列表不携带流程全量字段,列表查询更轻前端 TimeBase.vue、CH.vue、Track.vue 均直接消费 WF_GenerWorkerList 数据集,印证其作为待办/轨迹展示的一等公民地位。
定位:每个流程对应一张(或多张)业务物理表,命名规则 ND{流程编号}Rpt,承载表单采集的业务字段 + 流程系统字段的汇总镜像。
典型字段(见 GERpt.cs / GERptAttr):
类别 | 字段示例 |
|---|---|
业务字段 | 设计器配置的表单字段(金额、事由、附件等) |
流程系统字段 | WFState、FlowStarter、FlowEmps、FlowEndNode、FlowDaySpan |
关联字段 | OID(=WorkID)、FID、PWorkID |
设计意图:
SELECT 物理宽表,无需从 ACT_RU_VARIABLE 解析 JSONFlowCheckError.cs 在流程检查时将各节点表单字段合并到 NDxxRpt,保证报表字段与表单一致NDxxRpt 存流程级汇总——适合列表查询与归档前端 SearchFlow.vue 的流程查询直接调用 WF_Rpt.SearchFlow_Init,以 NDxxRpt 为主数据源;当业务表无 Title 列时,再回查 WF_GenerWorkFlow 补标题——业务查询与引擎摘要按需组合,而非硬绑一张大表。
定位:存储人员、部门、岗位、用户组等组织标识信息,如 Port_Emp、Port_Dept。
设计意图:
Port_* 引用——组织变更时不必动流程引擎表WF_WorkOpt.cs 中 Port_Emp + Port_Dept 联查)均依赖此体系WF_GenerWorkerList.FK_Emp 形成"身份 → 待办"的清晰链路定位:每个流程独立一张轨迹表,命名 ND{流程编号}Track,记录发送、退回、移交、抄送、审核意见等历史操作。
典型操作(WorkNode.AddToTrack / Glo.AddToTrack):
ActionType.Forward —— 发送ActionType.Return —— 退回ActionType.UnSend —— 撤销ActionType.WorkCheck —— 审核ActionType.CC —— 抄送设计意图:
Track.vue 读取 NDxxTrack 绘制流程图高亮与时光轴,WorkCheckParseTrack.vue 解析审核轨迹——展示层直接映射物理轨迹表维度 | 西方引擎(Activiti / Camunda / Flowable) | 东方引擎(该平台 该引擎) |
|---|---|---|
出发点 | 流程编排是核心,业务数据是"变量" | 流程 + 表单 + 报表是一体化交付 |
抽象层次 | 高度抽象:所有流程共用 ACT_RU_* / ACT_HI_* | 适度抽象:引擎表全局共用,业务/轨迹按流程分表 |
数据哲学 | "引擎不应懂业务"——变量外挂 | "引擎要懂报表"——NDxxRpt 内置业务镜像 |
扩展方式 | BPMN 扩展元素 + 外部表单 + REST 集成 | 表单设计器 + 流程设计器 + 报表设计器一体化 |
典型用户 | 架构师、集成开发者 | 实施顾问、业务管理员、信息中心 |
西方设计深受 BPMN 标准 与 Unix 哲学(做一件事并做好)影响:引擎只负责状态机流转,表单、报表、组织由周边系统提供。这是"集成型工作流"思维。
东方设计深受 OA/ERP 一体化交付 影响:客户采购的不是"流程引擎许可证",而是"请假能批、采购能查、公文能追溯"的完整系统。这是"交付型工作流"思维。
交付目标 | 西方引擎更优 | 该平台更优 |
|---|---|---|
嵌入现有业务系统,流程作为"胶水" | ✅ | |
快速上线完整 OA/审批/报表系统 | ✅ | |
云原生微服务、多语言 SDK | ✅ | |
国产化、私有化、信创环境批量交付 | ✅ | |
复杂中国特色流程(会签、子线程、队列、加签) | ✅ | |
业务人员自主配置表单+流程+查询 | ✅ |
结论并非"谁更好",而是"为谁交付"。 西方引擎是优秀的流程中间件;该平台是优秀的流程应用平台。
ACT_RE_PROCDEF — 流程定义
ACT_RU_EXECUTION — 运行时执行实例
ACT_RU_TASK — 运行时用户任务
ACT_RU_VARIABLE — 运行时变量(业务数据常在此)
ACT_HI_PROCINST — 历史流程实例
ACT_HI_TASKINST — 历史任务
ACT_HI_VARINST — 历史变量设计特征:
ACT_RU_* 表name-value 存入 ACT_RU_VARIABLE,查询报表需解析或同步到外部库RU vs HI 两套表,归档时数据搬迁ACT_RU_TASK 同时承担"任务分配"职责对比项 | 西方统一抽象 | 该平台五表分立 |
|---|---|---|
待办查询 | ACT_RU_TASK JOIN ACT_RU_EXECUTION | 单表 WF_GenerWorkerList |
流程监控 | ACT_RU_EXECUTION + 变量解析 | 单表 WF_GenerWorkFlow |
业务报表 | 外挂业务库或解析 VARIABLE | 直接查 NDxxRpt 宽表 |
轨迹审计 | ACT_HI_ACTINST / ACT_HI_COMMENT 全局表 | NDxxTrack 按流程分表 |
组织集成 | 外部 Identity Service | 内置 Port_* |
表数量 | 少而统一 | 引擎表少、业务表按流程增长 |
单表数据量 | 全局表随全企业流程膨胀 | 轨迹/业务按流程隔离,利于归档 |
该引擎/Components/BP.WF 目录结构体现了"引擎 / 业务 / 组织"的分工:
BP.WF/
├── WF/
│ ├── GenerWorkFlow.cs ← ① 流程实例
│ ├── GenerWorkerList.cs ← ② 工作人员/待办
│ ├── GERpt.cs ← ③ 业务报表实体
│ ├── WorkNode.cs ← 发送内核(协调五表写入)
│ ├── WorkUnSend.cs ← 撤销(回滚 WorkerList + Track)
│ └── Flow.cs ← 流程元数据 + Rpt 同步
├── HttpHandler/
│ ├── WF_MyFlow.cs ← 发起/办理
│ ├── WF_WorkOpt.cs ← 发送/退回/轨迹
│ └── WF_Rpt.cs ← 报表查询
└── Dev2Interface.cs ← 对外 API 统一入口WorkNode.cs 的发送方法(约 2700+ 行起)典型执行顺序:
GenerWorkerList.IsPass = 1GenerWorkFlow 状态与当前节点GenerWorkerList 待办NDxxRpt 流程系统字段AddToTrack 写入 NDxxTrack五表在同一事务语义下协作,但物理上互不污染。
`` 前端结构同样映射五表分工:
WF/
├── MyFlow*.vue ← 办理页(读 GenerWorkFlow + 节点表单)
├── WorkOpt/
│ ├── Send.ts ← 发送(写 WorkerList + Track)
│ ├── OneWork/
│ │ ├── Track.vue ← 轨迹图(读 NDxxTrack + GenerWorkerList)
│ │ └── TimeBase.vue ← 时光轴(读 Track + GenerWorkFlow)
│ └── WorkCheck*.vue ← 审核意见(写 Track)
├── Rpt/
│ └── SearchFlow.vue ← 流程报表(读 NDxxRpt,按需补 GenerWorkFlow)
└── CCForm/ ← 表单引擎(读写节点业务表 NDxx01…)前端从不假设"一张大对象包含所有数据",而是按场景组装不同表的数据集——这与五表分立架构高度一致。
GenerWorkerList 单表索引查询,不 JOIN 业务宽表NDxxTrack 按流程分表,历史数据可按流程整体迁移NDxxRpt 直接 SQL 聚合,无需从变量表反序列化NDxx01 / NDxxRpt,不动引擎表WF_Node 模板,不动业务数据Port_*,不动流程实例会签、加签、队列、子线程、分流合流、父子流程、抄送、移交、催办、挂起——这些中国企业高频场景,在 GenerWorkerList 的 IsHuiQian、Idx、FID 及 WorkNode 发送逻辑中都有直接映射,而非靠 BPMN 扩展硬拗。
NDxxTrack 记录完整操作链,前端 Track.vue 支持退回记录、撤销记录独立展示——满足政务、国企审计要求。
五表通过 WorkID / OID 关联,而非外键强绑——第三方系统可通过 Dev2Interface.cs 只读写所需表,实现渐进式集成。
西方引擎用"统一的抽象"换"集成的自由";该平台用"五表的分立"换"交付的效率"。
二十余年、数千家企业、政府与大型集团的运行验证,证明这套设计在中国企业的土壤中是经过实战检验的。它不是学术上的最优解,而是交付上的最优解。
-- ① 我的待办
SELECT gwl.*, gwf.Title, gwf.StarterName
FROM WF_GenerWorkerList gwl
JOIN WF_GenerWorkFlow gwf ON gwl.WorkID = gwf.WorkID
WHERE gwl.FK_Emp = @EmpNo AND gwl.IsPass = 0 AND gwl.IsEnable = 1;
-- ② 流程监控(运行中)
SELECT * FROM WF_GenerWorkFlow
WHERE FK_Flow = @FlowNo AND WFState = 2;
-- ③ 业务报表(以流程 001 为例)
SELECT * FROM ND001Rpt
WHERE WFState = 3 AND FK_Dept = @DeptNo;
-- ④ 轨迹回溯(以流程 001 为例)
SELECT * FROM ND001Track
WHERE WorkID = @WorkID
ORDER BY RDT;
-- ⑤ 组织选人
SELECT e.No, e.Name, d.Name AS DeptName
FROM Port_Emp e
JOIN Port_Dept d ON e.FK_Dept = d.No
WHERE e.Name LIKE '%' + @Keyword + '%';该引擎/Components/BP.WF — 工作流引擎核心本文基于 该引擎 开源代码客观分析撰写,旨在帮助架构师与实施顾问理解该平台工作流的数据设计哲学,做出匹配自身场景的技术选型。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。