很多人会把审批前端理解成“在记录旁边放两个通过/拒绝按钮”。但企业版 approvals 的做法更巧:它没有另起一个审批壳层,而是把审批交互嵌进 mail/activity 体系里,让用户在熟悉的活动流中直接完成审批。
一、审批人不是散字段,而是一个前端 record 类型
approver_model.js 里定义了 ApprovalApprover record,明确列出 id 与几种状态:new / pending / waiting / approved / refused / cancel。这说明前端并不是只拿一段 JSON 做渲染,而是把审批人纳入 mail store 可理解的数据模型。
一旦进入 record 体系,审批状态就不只是按钮文案,而是可以参与活动模型与 UI 更新的状态对象。
二、审批组件是 patch 进 Activity 的,不是单独挂页面
activity_patch.js 直接把 Approval 组件挂进 Activity.components。这点非常关键:审批 UI 的载体不是某个专门审批页面,而是现有 activity 组件树。
这带来的价值是:
- 用户不必切上下文;
- 审批动作和待办活动天然靠得很近;
- 前端复用 mail/activity 的生命周期和刷新语义。
三、按钮背后其实是“ORM 调用 + 本地状态即时回收”
approval.js 里的 onClickApprove() / onClickRefuse() 并不复杂,却很典型:
- 调
orm.call("approval.approver", "action_approve/refuse"); - 成功后
activity.remove(); - 再调用
onChange()让上层刷新。
这说明前端关注的不是“点完按钮弹个 toast”,而是服务器状态更新后,本地活动项要马上退场,并让上下文重算。
四、顺序审批的前端体验,核心在于反馈及时
虽然顺序审批主逻辑在后端,但前端如果不及时回收已处理 activity、刷新等待中的 approver,用户就会觉得“我明明批了,为什么列表还在”。这正是 approvals 把 UI 补丁做到 Activity 层的原因:反馈要和用户当前任务流保持一致。
五、新手误区
1. 以为审批组件应该独立页面化
企业版更偏向把审批嵌进已有活动流,而不是再造入口。
2. 以为前端按钮只负责发 RPC
真正好的体验来自 RPC 后的本地状态回收和上层刷新。
3. 以为 approver 状态只是展示字段
在 record 模型里,这些状态会直接影响交互表现。
六、实战注意事项
- 若你要自定义审批按钮,别绕开
Activity组件树,否则体验会割裂; - 审批成功后的 remove/onChange 连招不要省略,否则用户会看到“幽灵待办”;
- 如果审批状态扩展了新枚举,记得同步前端 record 定义;
- 排查审批 UI 不刷新的问题时,优先看 patch 是否生效、activity 是否被正确移除。
结语
企业版 Approvals 前端真正做的,不是“让审批按钮长出来”,而是把审批动作、活动流和即时反馈揉成一个连续体验。理解这层,才能看懂为什么它的实现看似轻,实际上很讲究落点。
DISCUSSION
评论区