2、核心概念与术语:审批人、申请人、审批节点、审批策略、审批链、超时处理
做流程自动化这么多年,我见过太多团队一上来就画流程图、写代码,结果做到一半发现连基本概念都没对齐。说白了,审批流程里的每个术语背后都对应着一套设计决策。这一章我们就把这些核心概念掰开揉碎,讲清楚。
2.1 申请人(Applicant)
申请人是发起审批流程的人。听起来很简单对吧?但我在项目中遇到过一个问题:申请人到底能不能审批自己的申请?
大部分业务场景下,申请人应该被自动跳过审批节点。比如员工提交请假申请,他的直属上级是审批人,但系统里如果把这个上级配置成申请人自己(比如小团队里组长就是申请人),就会产生逻辑冲突。
核心原则:申请人不应参与自己发起的审批节点的决策。系统应在运行时自动过滤掉申请人身份。
另外,申请人通常拥有以下权限:
- 查看自己发起的审批单的当前状态
- 在审批未完成前撤回或修改申请
- 接收审批结果的推送通知
我的习惯:在设计数据模型时,我会把申请人 ID 单独存为一个字段,而不是从审批节点里反查。这样查询效率高,逻辑也清晰。
2.2 审批人(Approver)
审批人是执行审批动作的人。但这里有个坑:审批人可以是单个用户,也可以是一个角色、一个部门,甚至是一个动态计算出来的集合。
我曾经在一个项目中遇到这样的需求:审批人不是固定的人,而是"申请人的上级的上级"。你想想看,如果写死在配置里,人员一变动就全崩了。所以审批人的解析必须是运行时动态计算的。
审批人的常见类型:
| 类型 | 说明 | 示例 |
|---|---|---|
| 指定用户 | 固定某个人 | CEO 张伟 |
| 角色 | 某个角色下的所有人 | 财务经理角色 |
| 上级 | 申请人的直属上级 | 申请人.reportTo |
| 部门负责人 | 申请人所在部门的负责人 | 部门.manager |
| 表单字段指定 | 由申请人在表单中选择 | 选择审批人下拉框 |
避坑指南:我曾经遇到过审批人解析失败导致流程卡死的情况。原因是组织架构数据没同步,上级字段为空。一定要加兜底逻辑——如果解析不到审批人,应该触发异常通知,而不是让流程默默挂起。
2.3 审批节点(Approval Node)
审批节点是流程中的一个停顿点。流程走到这里,必须等人做出审批决策才能继续往下走。
每个审批节点通常包含以下属性:
- 节点名称:比如"部门经理审批"
- 审批人配置:谁来审
- 审批策略:怎么审(下一节细讲)
- 超时配置:超过多久没审怎么办
- 操作按钮:通过、驳回、转审等
节点之间通过流转条件连接。比如"部门经理审批通过后,转到财务审批"。
关键设计点:每个节点都应该有独立的超时配置和审批策略。不要把多个节点的逻辑揉到一个节点里,否则后期维护会非常痛苦。
2.4 审批策略(Approval Strategy)
审批策略决定了当多个审批人同时存在时,如何达成审批结论。这是流程自动化里最容易出 bug 的地方。
常见的审批策略有四种:
| 策略 | 规则 | 适用场景 |
|---|---|---|
| 或签(任一通过) | 只要有一个审批人通过,节点即通过 | 紧急审批、备选审批人 |
| 会签(全部通过) | 所有审批人都必须通过 | 财务付款、合同审批 |
| 按比例通过 | 超过指定比例的人通过即可 | 委员会评审 |
| 按顺序审批 | 审批人按指定顺序依次审批 | 逐级上报 |
这里有个容易混淆的点:或签和按顺序审批的区别。或签是并行审批,谁先点通过就算过;按顺序审批是串行的,必须第一个人审完第二个人才能看到。
我的建议:在设计审批策略时,一定要考虑"驳回"的逻辑。比如会签场景下,一个人驳回后,其他人还需要继续审吗?我一般会设计成"一票否决"——只要有人驳回,整个节点就驳回,不再等待其他人。
2.5 审批链(Approval Chain)
审批链是多个审批节点按顺序组成的路径。它定义了审批流程的整体骨架。
审批链的设计有两种模式:
- 固定链:节点顺序写死,比如"员工 -> 部门经理 -> 总监 -> CEO"
- 动态链:根据条件动态决定下一个节点是谁。比如金额小于 1000 只需经理审批,大于 1000 需要总监审批
我在实际项目中用得最多的是动态链 + 策略配置的组合。举个例子:
// 伪代码示例:动态审批链解析
function resolveApprovalChain(application) {
const chain = [];
if (application.amount < 1000) {
chain.push({ node: 'manager', strategy: 'single' });
} else if (application.amount < 10000) {
chain.push({ node: 'manager', strategy: 'single' });
chain.push({ node: 'director', strategy: 'single' });
} else {
chain.push({ node: 'manager', strategy: 'single' });
chain.push({ node: 'director', strategy: 'single' });
chain.push({ node: 'ceo', strategy: 'single' });
}
return chain;
}
注意:动态链的解析逻辑必须放在后端,不能依赖前端传参。我曾经见过有人把审批链逻辑写在前端,结果被篡改参数绕过了审批——这是严重的安全漏洞。
下面这张图展示了审批链的整体结构:
2.6 超时处理(Timeout Handling)
超时处理是审批流程里最容易被忽视、但线上出问题最多的环节。审批人可能出差、请假、或者干脆忘了,流程不能无限期等下去。
常见的超时处理策略:
| 策略 | 行为 | 风险 |
|---|---|---|
| 自动通过 | 超时后系统自动判定为通过 | 可能绕过审批控制 |
| 自动驳回 | 超时后系统自动驳回 | 可能影响业务进度 |
| 转审 | 超时后自动转给备选审批人 | 需要提前配置备选人 |
| 升级 | 超时后通知上级或管理员 | 需要人工介入 |
| 重复提醒 | 超时后每隔一段时间发提醒 | 可能造成消息骚扰 |
我的经验:超时时间不要设得太短。我曾经见过一个项目把超时设为 30 分钟,结果审批人上个厕所回来流程就自动过了。一般建议:普通审批 24 小时,紧急审批 4 小时,超时升级到上级。
超时处理的实现要点:
- 使用定时任务或延迟队列来触发超时检查,不要用轮询
- 每个节点独立配置超时时间和策略
- 超时触发后要记录日志,方便追溯
- 考虑节假日和工作时间——周五下班前提交的申请,超时时间应该顺延
避坑指南:我曾经遇到过一个 case:超时自动通过后,审批人又手动点了驳回,导致状态冲突。解决方案是:超时触发后,节点状态立即锁定,不再接受人工操作。如果一定要允许人工干预,需要设计明确的"覆盖"机制并记录操作日志。