20260922224136

This commit is contained in:
oneao committed 2026-09-22 22:41:36 +08:00
1 parent c8dad8d4a6
commit 0abe3706c8
113 files changed
+5057 -2771

No files matched your search

+383 -1
View File
@@ -1,6 +1,6 @@
# FMS 新系统核心表结构设计 V2
> 本文用于记录新版核心表结构方案,权限设计见第 14 节。旧版文档保留作为历史参考。
> 本文用于记录新版核心表结构方案,权限设计见第 14 节,工作流与审批见第 16 节。旧版文档保留作为历史参考。
**本系统以 SQL 为核心驱动。设计时应优先保证查询和数据处理的灵活性,并在各模块预留 SQL 扩展能力,支持传入 SQL、动态拼接查询条件、组合查询及自定义数据处理逻辑,以便通过 SQL 快速适配和解决复杂业务场景。**
@@ -1087,3 +1087,385 @@ fms:
│ aliyun-oss → 取号 → 凭证直传 → POST /file/save-record 落库
└── 删除:POST /file/delete(删存储 → 删 DB 行)
```
## 16. 工作流与审批
工作流是独立子系统,不属于系统内核,表统一使用 `wf_` 前缀(第 1.1 节的业务域前缀约定)。配置表保存流程定义、版本、节点、连线、审批人规则和模块绑定;运行表保存实例、节点运行、待办、抄送和不可变动作历史。
完整语义、审批方式(或签、会签、串行会签、N 人通过、按比例通过)、驳回策略、加签、催办和抄送规则见《FMS工作流与审批设计》,本文只记录表结构。
| 表 | 职责 |
| --- | --- |
| `wf_definition` / `wf_version` | 流程定义与可执行版本 |
| `wf_node` / `wf_edge` / `wf_actor_rule` | 版本内的节点、连线和审批人规则 |
| `wf_binding` | 模块和业务事件到流程版本的绑定 |
| `wf_instance` / `wf_node_run` / `wf_task` | 流程实例、节点运行和待办任务 |
| `wf_action` | 不可变的审批动作历史 |
| `wf_cc` / `wf_delegation` / `wf_outbox` | 抄送记录、委托和通知消息 |
表结构约定:
- 配置表使用 `varchar` 业务编码主键;运行表使用应用层生成的 UUIDv7(`uniqueidentifier`),与 `s_log_*` 一致(第 13 节);
- 业务主键统一按字符串保存在 `b_business_id`,不依赖业务表的物理主键类型;
- 状态、类型和动作编码的取值只写在列注释里,不使用 `CHECK` 约束、外键和触发器,合法性由业务层校验(第 1.10 节);
- 已发布版本不可修改,运行中的实例固定引用提交时的 `b_version_id`;
- 变化频繁的配置使用 `nvarchar(max)` JSON,顶层包含 `schemaVersion`(第 1.8 节)。
### 16.1 流程定义
```sql
-- 流程定义表(稳定逻辑身份,执行内容在版本表)
create table dbo.wf_definition (
b_id varchar(50) not null primary key, -- 流程定义编码(创建后不可修改)
b_name nvarchar(200) not null, -- 流程名称
b_i18n varchar(150) null, -- 多语言资源键(s_i18n.b_key)
b_canuse tinyint not null default 1, -- 是否启用(0/1)
b_bz nvarchar(2000) null, -- 备注
b_created_by varchar(50) null, -- 创建人(用户编码)
b_created_at datetime2 null, -- 创建时间
b_updated_by varchar(50) null, -- 最后修改人
b_updated_at datetime2 null -- 最后修改时间
);
create index ix_wf_definition_canuse
on dbo.wf_definition (b_canuse, b_id);
```
### 16.2 流程版本
```sql
-- 流程版本表(draft/published/retired,已发布版本不可原地修改)
create table dbo.wf_version (
b_id varchar(50) not null primary key, -- 版本 ID
b_definition_id varchar(50) not null, -- 流程定义编码(wf_definition.b_id)
b_version_no int not null, -- 版本序号(同一流程内递增)
b_status varchar(20) not null default 'draft', -- 版本状态:draft(草稿)/published(已发布)/retired(已停用)
b_schema_version int not null default 1, -- 配置结构版本(JSON 结构升级用)
b_canvas_json nvarchar(max) null, -- 设计器布局(节点坐标、缩放),不参与执行
b_checksum varchar(128) null, -- 发布时计算的配置摘要
b_published_by varchar(50) null, -- 发布人(用户编码)
b_published_at datetime2 null, -- 发布时间
b_bz nvarchar(2000) null, -- 备注
b_created_by varchar(50) null, -- 创建人
b_created_at datetime2 null, -- 创建时间
b_updated_by varchar(50) null, -- 最后修改人
b_updated_at datetime2 null -- 最后修改时间
);
create unique index ux_wf_version_no
on dbo.wf_version (b_definition_id, b_version_no);
create index ix_wf_version_status
on dbo.wf_version (b_definition_id, b_status, b_version_no);
```
发布校验由业务层完成:开始/结束节点完整、人工节点有审批人规则、条件字段来自 `s_field`、不存在不可达节点和死循环;发布后禁止修改节点和连线。
### 16.3 流程绑定
```sql
-- 流程绑定表(模块 + 业务事件 + 条件 → 流程版本)
create table dbo.wf_binding (
b_id varchar(50) not null primary key, -- 绑定 ID
b_module_id varchar(50) not null, -- 模块编码(s_module.b_id,data/virtual 模块)
b_event varchar(30) not null, -- 业务事件:submit(送审)/resubmit(重新提交)/change(变更)
b_version_id varchar(50) not null, -- 已发布流程版本(wf_version.b_id)
b_match_json nvarchar(max) null, -- 业务匹配条件 AST
b_org_scope_json nvarchar(max) null, -- 公司、组织范围
b_status_field varchar(50) null, -- 业务状态字段(必须来自 s_field)
b_status_map_json nvarchar(max) null, -- 流程状态到业务状态的映射
b_priority int not null default 0, -- 匹配优先级(小的先匹配)
b_effective_from datetime2 null, -- 生效开始时间
b_effective_to datetime2 null, -- 生效结束时间
b_canuse tinyint not null default 1, -- 是否启用(0/1)
b_bz nvarchar(2000) null, -- 备注
b_created_by varchar(50) null, -- 创建人
b_created_at datetime2 null, -- 创建时间
b_updated_by varchar(50) null, -- 最后修改人
b_updated_at datetime2 null -- 最后修改时间
);
create index ix_wf_binding_select
on dbo.wf_binding (b_module_id, b_event, b_canuse, b_priority, b_effective_from, b_effective_to);
```
同一业务上下文只能匹配一个最终流程,优先级冲突由业务层校验。`b_status_field` 用于兼容业务表已有的 `b_state`、`b_status` 字段名。
### 16.4 流程节点
```sql
-- 流程节点表(版本内节点定义)
create table dbo.wf_node (
b_id varchar(50) not null primary key, -- 节点 ID
b_version_id varchar(50) not null, -- 流程版本(wf_version.b_id)
b_node_key varchar(80) not null, -- 版本内稳定编码(历史记录引用它)
b_name nvarchar(200) not null, -- 节点名称
b_i18n varchar(150) null, -- 多语言资源键
b_node_type varchar(30) not null, -- 节点类型:start(开始)/user_task(人工审批)/cc_task(抄送)/exclusive_gateway(条件分支)/parallel_gateway(并行分支)/service_task(服务节点)/end(结束)
b_approval_mode varchar(30) null, -- 审批方式:single(单人)/any(或签)/all(会签)/serial(串行会签)/n_of_m(N 人通过)/percentage(按比例通过)
b_reject_mode varchar(30) null, -- 驳回策略:terminate(驳回结束)/return_initiator(退回发起人)/return_previous(退回上一节点)
b_due_hours decimal(10,2) null, -- 审批时限(小时)
b_config_json nvarchar(max) null, -- 节点扩展配置(requiredCount、requiredRatio、formPolicy 等)
b_xh int not null default 0, -- 显示顺序
b_canuse tinyint not null default 1 -- 是否启用(0/1)
);
create unique index ux_wf_node_key
on dbo.wf_node (b_version_id, b_node_key);
create index ix_wf_node_type
on dbo.wf_node (b_version_id, b_node_type, b_xh, b_node_key);
```
`b_approval_mode` 取值:`single` 单人、`any` 或签、`all` 会签、`serial` 串行会签、`n_of_m` N 人通过、`percentage` 按比例通过。`requiredCount` 只对 `n_of_m` 生效,`requiredRatio` 只对 `percentage` 生效。
### 16.5 节点连线
```sql
-- 节点连线表(含条件分支)
create table dbo.wf_edge (
b_id varchar(50) not null primary key, -- 连线 ID
b_version_id varchar(50) not null, -- 流程版本
b_from_node_key varchar(80) not null, -- 来源节点编码
b_to_node_key varchar(80) not null, -- 目标节点编码
b_condition_json nvarchar(max) null, -- 连线条件 AST
b_priority int not null default 0, -- 判断优先级(小的先判断)
b_canuse tinyint not null default 1, -- 是否启用(0/1)
b_bz nvarchar(1000) null -- 备注
);
create index ix_wf_edge_from
on dbo.wf_edge (b_version_id, b_from_node_key, b_canuse, b_priority, b_to_node_key);
create index ix_wf_edge_to
on dbo.wf_edge (b_version_id, b_to_node_key, b_canuse, b_priority, b_from_node_key);
```
同一来源节点的条件连线按 `b_priority` 从小到大判断,条件分支必须有默认出口,避免条件都不满足时流程卡死。
### 16.6 审批人规则
```sql
-- 审批人规则表(节点内审批人、抄送人的解析规则)
create table dbo.wf_actor_rule (
b_id varchar(50) not null primary key, -- 规则 ID
b_version_id varchar(50) not null, -- 流程版本
b_node_key varchar(80) not null, -- 节点编码
b_actor_type varchar(30) not null, -- 解析类型:user(指定用户)/initiator(发起人)/initiator_manager(发起人直属领导)/dept_manager(部门负责人)/position(岗位)/org_role(组织角色)/field_user(业务字段用户)/custom(自定义解析器)
b_actor_ref varchar(150) null, -- 用户、岗位、角色或字段编码
b_resolve_json nvarchar(max) null, -- 解析参数
b_condition_json nvarchar(max) null, -- 规则适用条件 AST
b_fallback_type varchar(30) null, -- 解析为空时的兜底:none(不兜底)/admin(管理员)/initiator(发起人)/custom(自定义)
b_fallback_ref varchar(150) null, -- 兜底引用
b_priority int not null default 0, -- 优先级(串行会签的顺序来源)
b_canuse tinyint not null default 1, -- 是否启用(0/1)
b_bz nvarchar(1000) null -- 备注
);
create index ix_wf_actor_rule_node
on dbo.wf_actor_rule (b_version_id, b_node_key, b_canuse, b_priority, b_actor_type);
```
解析结果必须把规则快照和实际用户快照写入运行表,组织架构后续变化不影响历史审批责任。
### 16.7 流程实例
```sql
-- 流程实例表(某张业务单据某次提交的运行流程)
create table dbo.wf_instance (
b_id uniqueidentifier not null primary key, -- 实例 ID(应用层生成 UUIDv7)
b_definition_id varchar(50) not null, -- 流程定义编码
b_version_id varchar(50) not null, -- 流程版本(提交时固定)
b_binding_id varchar(50) not null, -- 命中的绑定(wf_binding.b_id)
b_module_id varchar(50) not null, -- 业务模块编码
b_event varchar(30) not null, -- 业务事件:submit(送审)/resubmit(重新提交)/change(变更)
b_business_id varchar(50) not null, -- 业务主键(统一按字符串保存)
b_business_no nvarchar(200) null, -- 业务单号(列表展示)
b_org_id varchar(50) null, -- 公司/组织编码
b_initiator_id varchar(50) not null, -- 发起人(用户编码)
b_initiator_dept_id varchar(50) null, -- 发起人部门编码
b_status varchar(30) not null, -- 实例状态:running(运行中)/approved(已通过)/rejected(已驳回)/returned(已退回)/withdrawn(已撤回)/cancelled(已取消)/expired(已过期)/error(异常待处理)
b_context_json nvarchar(max) null, -- 运行变量
b_snapshot_json nvarchar(max) null, -- 提交时业务快照
b_current_summary_json nvarchar(max) null, -- 列表展示用当前节点摘要
b_row_version bigint not null default 0, -- 乐观锁版本号
b_idempotency_key varchar(100) null, -- 幂等键
b_started_at datetime2 not null, -- 开始时间
b_completed_at datetime2 null, -- 结束时间
b_created_by varchar(50) null, -- 创建人
b_created_at datetime2 null, -- 创建时间
b_updated_by varchar(50) null, -- 最后修改人
b_updated_at datetime2 null -- 最后修改时间
);
create index ix_wf_instance_business
on dbo.wf_instance (b_module_id, b_business_id, b_event, b_status, b_id);
create index ix_wf_instance_initiator
on dbo.wf_instance (b_initiator_id, b_status, b_started_at, b_id);
create index ix_wf_instance_version
on dbo.wf_instance (b_version_id, b_started_at, b_id);
```
“驳回”和“退回”必须区分:驳回结束本次流程,退回允许修改后重新提交。
### 16.8 节点运行
```sql
-- 节点运行表(节点在实例中的一次进入和处理记录)
create table dbo.wf_node_run (
b_id uniqueidentifier not null primary key, -- 节点运行 ID(UUIDv7)
b_instance_id uniqueidentifier not null, -- 流程实例(wf_instance.b_id)
b_node_key varchar(80) not null, -- 节点编码
b_run_no int not null default 1, -- 同一节点的第几次运行(退回、循环用)
b_status varchar(30) not null, -- 节点状态:pending(待激活)/running(运行中)/completed(已完成)/skipped(已跳过)
b_required_count int null, -- 应签人数(按比例时在节点激活时换算)
b_completed_count int not null default 0, -- 已通过人数
b_rejected_count int not null default 0, -- 已驳回人数
b_entered_at datetime2 null, -- 进入时间
b_exited_at datetime2 null, -- 离开时间
b_actor_snapshot_json nvarchar(max) null, -- 审批人规则快照
b_created_at datetime2 null -- 创建时间
);
create index ix_wf_node_run_instance
on dbo.wf_node_run (b_instance_id, b_status, b_node_key, b_run_no, b_id);
```
`b_required_count`、`b_completed_count` 和 `b_rejected_count` 必须由后端在锁定节点运行记录后更新,不能由前端计算。
### 16.9 待办任务
```sql
-- 待办任务表(一名实际审批人一行)
create table dbo.wf_task (
b_id uniqueidentifier not null primary key, -- 任务 ID(UUIDv7)
b_instance_id uniqueidentifier not null, -- 流程实例
b_node_run_id uniqueidentifier not null, -- 节点运行(会签、或签聚合判断用)
b_node_key varchar(80) not null, -- 节点编码
b_actor_rule_id varchar(50) null, -- 命中的审批人规则
b_assignee_type varchar(30) not null, -- 受理人类型:user(指定用户)/position(岗位)/role(角色)/delegate(委托)
b_assignee_id varchar(50) not null, -- 实际用户编码
b_seq int not null default 0, -- 同节点内处理顺序(串行会签生效)
b_status varchar(30) not null, -- 任务状态:waiting(未激活)/pending(待处理)/claimed(已抢占)/approved(已通过)/rejected(已驳回)/cancelled(已取消)/expired(已过期)
b_due_at datetime2 null, -- 应处理时间
b_claimed_by varchar(50) null, -- 抢占人
b_claimed_at datetime2 null, -- 抢占时间
b_completed_by varchar(50) null, -- 处理人
b_completed_at datetime2 null, -- 处理时间
b_rule_snapshot_json nvarchar(max) null, -- 审批人解析快照
b_created_at datetime2 null, -- 创建时间
b_updated_at datetime2 null -- 最后修改时间
);
create index ix_wf_task_assignee
on dbo.wf_task (b_assignee_id, b_status, b_due_at, b_id);
create index ix_wf_task_instance
on dbo.wf_task (b_instance_id, b_status, b_node_run_id, b_id);
create index ix_wf_task_due
on dbo.wf_task (b_status, b_due_at, b_id);
```
会签、或签和串行会签通过同一个 `b_node_run_id` 聚合判断;串行会签的未激活任务使用 `waiting` 状态,只有 `pending` 任务出现在待办列表。
### 16.10 审批动作
```sql
-- 审批动作表(只追加,不更新历史动作)
create table dbo.wf_action (
b_id uniqueidentifier not null primary key, -- 动作 ID(UUIDv7)
b_instance_id uniqueidentifier not null, -- 流程实例
b_node_run_id uniqueidentifier null, -- 节点运行
b_task_id uniqueidentifier null, -- 待办任务
b_action varchar(30) not null, -- 动作编码:submit(送审)/approve(通过)/reject(驳回)/return(退回)/withdraw(撤回)/cancel(取消)/claim(抢占)/transfer(转交)/delegate(委托)/reassign(转派)/add_approver(加签)/urge(催办)/cc(抄送)
b_operator_id varchar(50) null, -- 操作人(用户编码,系统动作为空)
b_from_status varchar(30) null, -- 变更前状态
b_to_status varchar(30) null, -- 变更后状态
b_comment nvarchar(2000) null, -- 审批意见
b_payload_json nvarchar(max) null, -- 动作载荷(命中的条件、边、加签位置等)
b_request_id varchar(64) null, -- 请求 ID
b_trace_id varchar(64) null, -- 链路 ID
b_occurdatetime datetime2 not null -- 发生时间
);
create index ix_wf_action_instance
on dbo.wf_action (b_instance_id, b_occurdatetime, b_id);
create index ix_wf_action_operator
on dbo.wf_action (b_operator_id, b_occurdatetime, b_id);
```
撤回、转交、加签和管理员转派也必须形成动作记录,历史动作只追加不修改。
### 16.11 抄送记录
```sql
-- 抄送记录表(抄送人不产生待办,不参与节点判定)
create table dbo.wf_cc (
b_id uniqueidentifier not null primary key, -- 抄送 ID(UUIDv7)
b_instance_id uniqueidentifier not null, -- 流程实例
b_node_run_id uniqueidentifier null, -- 来源节点运行
b_node_key varchar(80) null, -- 来源节点编码
b_recipient_id varchar(50) not null, -- 抄送接收人(用户编码)
b_actor_rule_id varchar(50) null, -- 命中的抄送规则
b_status varchar(20) not null default 'unread', -- 阅读状态:unread(未读)/read(已读)
b_read_at datetime2 null, -- 阅读时间
b_rule_snapshot_json nvarchar(max) null, -- 抄送人解析快照
b_created_at datetime2 null -- 创建时间
);
create index ix_wf_cc_recipient
on dbo.wf_cc (b_recipient_id, b_status, b_created_at, b_id);
create index ix_wf_cc_instance
on dbo.wf_cc (b_instance_id, b_created_at, b_id);
```
### 16.12 委托
```sql
-- 委托表(审批人把待办委托给他人处理)
create table dbo.wf_delegation (
b_id varchar(50) not null primary key, -- 委托 ID
b_from_user_id varchar(50) not null, -- 委托人(用户编码)
b_to_user_id varchar(50) not null, -- 受托人(用户编码)
b_scope_json nvarchar(max) null, -- 委托范围(模块、动作、组织)
b_start_at datetime2 not null, -- 生效时间
b_end_at datetime2 not null, -- 失效时间
b_reason nvarchar(500) null, -- 委托原因
b_canuse tinyint not null default 1, -- 是否启用(0/1)
b_created_by varchar(50) null, -- 创建人
b_created_at datetime2 null, -- 创建时间
b_updated_by varchar(50) null, -- 最后修改人
b_updated_at datetime2 null -- 最后修改时间
);
create index ix_wf_delegation_user
on dbo.wf_delegation (b_from_user_id, b_canuse, b_start_at, b_end_at, b_to_user_id);
```
### 16.13 通知消息
```sql
-- 通知消息表(outbox,异步发送,不阻塞审批事务)
create table dbo.wf_outbox (
b_id uniqueidentifier not null primary key, -- 消息 ID(UUIDv7)
b_event_code varchar(80) not null, -- 事件编码
b_aggregate_type varchar(30) not null, -- 聚合类型:instance(流程实例)/task(待办任务)
b_aggregate_id varchar(50) not null, -- 聚合 ID
b_payload_json nvarchar(max) not null, -- 消息载荷
b_status varchar(20) not null default 'pending', -- 发送状态:pending(待发送)/sent(已发送)/failed(发送失败)
b_retry_count int not null default 0, -- 重试次数
b_next_retry_at datetime2 null, -- 下次重试时间
b_last_error nvarchar(2000) null, -- 最后错误
b_occurdatetime datetime2 not null -- 发生时间
);
create index ix_wf_outbox_dispatch
on dbo.wf_outbox (b_status, b_next_retry_at, b_occurdatetime, b_id);
```
实例、任务、抄送记录和业务状态在同一数据库事务中提交;通知发送失败不回滚审批事务,超过阈值进入人工处理队列。