审批流(BPM)
GopherForge 内置一套自研轻量审批流引擎——不引入 Flowable/BPMN,Go 原生实现「节点树单游标 + 任务展开器」,能力对标主流工作流产品,部署零额外依赖。
能力全景
| 维度 | 支持 |
|---|---|
| 节点类型 | 发起 / 审批 / 抄送 / 条件分支(排他,可嵌套) |
| 审批人规则 | 指定用户 / 指定角色 / 部门主管(发起人部门或表单字段指定)/ 发起人自选 |
| 多人模式 | 会签(全部同意)/ 或签(一人同意,全拒才拒)/ 依次(逐个流转) |
| 审批动作 | 同意 / 拒绝 / 转办 / 退回发起人(改表单重提)/ 退回上一节点(按实际流转路径回溯)/ 加签 / 委派 / 撤销 |
| 管理动作 | 管理员强制终止(含挂起实例出口)、全部实例管理视图、审批统计 |
| 超时 | 节点级超时小时数 + 到期动作:仅提醒 / 自动通过 / 自动拒绝(系统身份执行,进时间线;扫描周期 BPM_TIMEOUT_SCAN_INTERVAL,默认 5 分钟) |
| 兜底 | 审批人解析为空三策略(自动通过 / 转指定人 / 挂起待管理员);条件求值失败挂起不错批 |
| 版本化 | 定义多版本,发布生效、在途实例冻结旧版不受影响 |
操作走查:从零上线一个请假流程
- 建定义(审批中心 → 流程定义):新建后进入设计器,先在「表单设计」里加字段——请假类型(select)、开始/结束日期(date)、事由(textarea,必填)。
- 搭节点:纵向卡片流上点「+」插入审批节点,审批人选「部门主管」(基准默认取发起人所在部门,部门须已设主管);再加一个 HR 节点用「指定角色」;需要分档就插条件分支(如请假天数 > 3 走加签链)。
- 发布:发布即整树校验(前后端双重)+ 版本激活;旧版自动归档,在途实例继续走旧版。
- 员工发起(审批中心 → 发起申请):选流程、填表单提交。表单快照在服务端按 Schema 权威校验(必填/类型/选项/范围,拒绝夹带字段)。
- 审批(审批中心 → 待办):审批人处理,支持的动作由服务端按节点与状态计算下发(见下表)。
- 回看:发起人在「我发起的」看时间线与流转图(节点运行时标注);管理员在实例管理页可强制终止、看统计。
仿钉钉设计器
纵向卡片流配置器(非自由画布):节点间「+」插入审批/抄送/条件分支,条件分支横向分叉多列子链、末列固定默认兜底;条件编辑器按表单字段声明下拉选字段(且/或组合 + 7 种比较符,金额按分求值)。发布时前后端双重整树校验。
两种表单模式
流程表单(零代码):定义里用「表单设计」声明字段,发布后普通用户在「发起申请」页选流程、填表单即发起——请假/报销类流程不写一行代码。八种字段类型:
| 类型 | 存储 | 约束 |
|---|---|---|
input / textarea | 字符串 | ≤2000 字符 |
number | 浮点 | 可设 min/max |
amount | int64 分 | 元录入分存储,必须整数分,可设 min/max |
select / radio | 字符串 | 值必须在选项内 |
date | YYYY-MM-DD | 正则校验格式 |
switch | 布尔 | — |
业务表单(深度集成):业务后端经 internal 端点权威发起,终态经 HTTP 回调回写业务状态。
业务表单模式接入
1. 发起:POST /api/v1/bpm/internal/instances(X-Internal-Token)
body: { definition_key, title, biz_type, biz_id, form_snapshot, initiator_id }
2. 回调:注册环境变量 BPM_CALLBACK_<BIZTYPE>=<你的回调 URL>
终态时收到 { instance_id, biz_type, biz_id, result: approved|rejected|canceled, ... }
按 (biz_type, biz_id, instance_id) 幂等处理;三次重试后失败仅告警不回滚审批事实
3. 反查:GET /api/v1/bpm/internal/instances/by-biz?biz_type=&biz_id=同一业务对象同时至多一条在途实例由数据库部分唯一索引兜底防重。安全约定:用户侧发起端点只接受流程表单定义(biz 锚点服务端生成),业务审批无法被伪造;BPM_INTERNAL_TOKEN 未配置时 internal 端点一律返回 503(fail-closed,绝不拿开发占位符当真凭据),token 校验用恒定时间比较。
任务动作与约束
任务详情接口会按「节点类型 × 任务状态 × 当前人」计算可用动作下发,前端只渲染服务端给的清单:
| 动作 | 约束 |
|---|---|
| 同意 | 意见可选 |
| 拒绝 | 意见必填;节点可配拒后走向(终态 / 退回发起人重提) |
| 转办 | 任务换人保持待办,记录原受理人,可再转 |
| 退回发起人 | 发起人改表单后重新提交(快照可改,默认沿用) |
| 退回上一节点 | 需节点开启 allowBackPrev 且存在实际审批历史 |
| 加签 | 当前节点动态加审批人,沿用节点多人收敛规则;依次(SEQ)模式不支持 |
| 委派 | 交受托人代办(不能委派给自己);受托人办结后任务回到委派人继续 |
| 撤销 | 仅发起人,且首个审批节点尚无人处理 |
抄送(GET /api/v1/bpm/cc/my)支持未读筛选与已读标记(幂等)。
字段权限
审批节点可将表单字段设为「对此节点隐藏」(如薪酬字段对普通审批人不可见)——任务详情、实例详情、流转图三个口径都在服务端过滤,前端无法绕过。
接口速查
| 分组 | 代表端点 |
|---|---|
| 定义 | GET/POST /api/v1/bpm/definitions · POST /definitions/:id/publish · /new-version · /suspend |
| 发起 | GET /api/v1/bpm/startable · POST /api/v1/bpm/instances(仅流程表单) |
| 实例 | GET /instances/my · GET /instances/:id(含时间线 /timeline、流转图 /diagram)· POST /instances/:id/cancel / resubmit |
| 任务 | GET /tasks/todo · /tasks/done · `POST /tasks/:id/approve |
| 管理 | GET /instances(全部)· POST /instances/:id/terminate · GET /stats —— 仅平台管理员 |
| 内部 | POST /internal/instances · GET /internal/instances/by-biz —— X-Internal-Token |
BPM 走 Bearer JWT 自校验(不挂 ForwardAuth,与其它业务路由一致);菜单可见性由 bpm:definition:* 等权限点控制。
审批统计
平台管理员在流程定义页可打开「审批统计」:状态分布、近 30 天发起趋势、按流程的通过率与平均耗时、节点瓶颈 Top10(平均处理时长)——哪个环节在拖流程一眼可见。
数据表
五张自管表(AutoMigrate):bpm_process_definition(定义 + node_tree/form_schema JSONB)、bpm_process_instance(实例 + 表单快照,(tenant,biz_type,biz_id,running) 部分唯一索引防重)、bpm_task(任务,含加签/委派/轮次字段)、bpm_cc_record(抄送)、bpm_process_log(流转日志,operator_id=0 表示系统动作)。全部带 tenant_id 隔离。
通知与站内信
新待办、抄送、超时提醒、终态结果均对接通知模板(脚手架默认无通知服务时静默跳过,配置 NOTIFY_API_BASE + token 即启用)。