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;
}

注意:动态链的解析逻辑必须放在后端,不能依赖前端传参。我曾经见过有人把审批链逻辑写在前端,结果被篡改参数绕过了审批——这是严重的安全漏洞。

下面这张图展示了审批链的整体结构:

审批链结构示意图 申请人 节点1:经理审批 策略:单人审批 节点2:总监审批 策略:会签 节点3:CEO审批 策略:单人审批 每个节点可独立配置超时策略 超时自动通过 / 超时转审 / 超时升级 驳回回退到节点1 审批完成 / 终态

2.6 超时处理(Timeout Handling)

超时处理是审批流程里最容易被忽视、但线上出问题最多的环节。审批人可能出差、请假、或者干脆忘了,流程不能无限期等下去。

常见的超时处理策略:

策略 行为 风险
自动通过 超时后系统自动判定为通过 可能绕过审批控制
自动驳回 超时后系统自动驳回 可能影响业务进度
转审 超时后自动转给备选审批人 需要提前配置备选人
升级 超时后通知上级或管理员 需要人工介入
重复提醒 超时后每隔一段时间发提醒 可能造成消息骚扰

我的经验:超时时间不要设得太短。我曾经见过一个项目把超时设为 30 分钟,结果审批人上个厕所回来流程就自动过了。一般建议:普通审批 24 小时,紧急审批 4 小时,超时升级到上级。

超时处理的实现要点:

  • 使用定时任务或延迟队列来触发超时检查,不要用轮询
  • 每个节点独立配置超时时间和策略
  • 超时触发后要记录日志,方便追溯
  • 考虑节假日和工作时间——周五下班前提交的申请,超时时间应该顺延

避坑指南:我曾经遇到过一个 case:超时自动通过后,审批人又手动点了驳回,导致状态冲突。解决方案是:超时触发后,节点状态立即锁定,不再接受人工操作。如果一定要允许人工干预,需要设计明确的"覆盖"机制并记录操作日志。