我一个人写了个通用审批引擎,能对接所有服务 我做后端这几年见过太多审批系统。有的把审批逻辑硬编码在业务代码里改一个流程要发版有的买了第三方的配置复杂到产品经理都看不懂。去年我开始搭自己的微服务体系第一个想的不是认证、不是权限——而是「审批」这个事能不能抽出来做成一个独立服务不管哪个业务都能接进来。半年过去了审批引擎跑起来了。今天跟你聊聊我是怎么想的、怎么做的以及中间踩的几个坑。不是所有审批都一样刚开始我想得很简单一张申请表、一个审批人、通过或驳回。但真正开始做了才发现审批的复杂度不在「通过/驳回」而在「不同业务长得完全不一样」。权限申请要展示权限名称和理由博客审核要展示文章标题和内容预览考试申请要展示考试名称和时间。如果给每种业务写一套展示逻辑那这个审批引擎就废了——每次接新业务都要改代码。我的解法Schema 快照。每套审批模板定义一份 form_schema描述这个业务有哪些字段、字段叫什么、怎么展示{fields:[{key:permissionName,label:申请的权限,type:text},{key:reason,label:申请理由,type:textarea}]}创建审批单的时候把当时的 schema 拍一个快照存进审批实例。以后不管模板怎么改这个审批单就按创建时的 schema 展示互不影响。这个设计后来被验证了好几次——模板改了十几版历史审批单一个没乱。第一个坑申请人不能审批自己这是测试的时候发现的。我自己提了个权限申请跑到「待我审批」里一看居然能看到自己的申请点了「通过」居然还能通过。这要是在生产环境权限就变成自己给自己发了。前后端双重校验。后端查申请人 ID 和当前用户 ID相等直接抛「不能审批自己的申请」。前端在列表里提前过滤掉不让按钮出现。两边都做了就算绕过前端直接调接口也过不去。第二个坑回调的可靠性审批通过之后要回调业务系统——比如权限申请通过了要调 perm-service 给用户加权限。问题来了如果回调失败了怎么办我见过有的系统直接不管失败了就失败了管理员手动补。这在一个独立开发者手上就是噩梦——你可能过了两天才发现权限没加上。我的方案重试 3 次间隔 1 秒记录状态。审批通过/驳回后立刻 POST 到业务系统配置的回调地址。失败就重试最多 3 次。每次重试的间隔递增。3 次都失败标记 callback_status failed详情页显示一个黄色「通知失败」提示管理员一眼能看到哪些需要手动处理。成功了就显示绿色「已通知」不用管了。第三个坑撤回和重新提交用户提了申请发现填错了想撤回。简单pending 状态的申请直接置为 cancelled。但重新提交呢这时候模板的 schema 可能已经改了。如果按新 schema 展示用户填的是旧字段就对不上了。重新提交继承旧的 schema_snapshot。不会因为模板改了就让用户的申请变样。最后五张表搞定一切审批引擎只有五张表t_approval_template审批模板定义流程和 schemat_approval_node审批节点多级审批t_approval审批实例每一条申请t_approval_record审批记录每一步的操作历史t_user_permission用户权限审批通过后写入多一级审批就加一个 node多一种业务就加一个 template。不用改代码。回头看看这个审批引擎算不上什么高深的技术但它是我自己设计、自己实现、自己验证过的。从 schema 快照的思路到回调重试的机制到撤回重新提交的处理——每一个决策都是踩了坑以后逼出来的。独立开发者有个好处你做的东西不用向任何人妥协。不好用的地方你就改想不通的地方你就推翻。最后留下来的是什么是真正经得起推敲的东西。关于作者无羡独立开发者全栈工程师专注 AI 应用与微服务架构。 分类独立开发实战 个人博客 — 更多技术文章✨ 开发者福利整理 — 云服务资源汇总 软件工坊 — 我的技术分享 个人门户 — 独立开发作品全集