718 lines
22 KiB
Markdown
718 lines
22 KiB
Markdown
|
|
# 审批流程图汇总
|
||
|
|
|
||
|
|
**文档版本**: 1.0
|
||
|
|
**更新时间**: 2026-03-01
|
||
|
|
**适用版本**: feature/debug-feishu-message
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📋 目录
|
||
|
|
|
||
|
|
1. [节点类型说明](#节点类型说明)
|
||
|
|
2. [基础流程图](#基础流程图)
|
||
|
|
3. [按节点类型的流程图](#按节点类型的流程图)
|
||
|
|
4. [特殊场景流程图](#特殊场景流程图)
|
||
|
|
5. [状态流转图](#状态流转图)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 节点类型说明
|
||
|
|
|
||
|
|
### 节点类型定义
|
||
|
|
|
||
|
|
| 类型 | 常量 | 说明 | 完成条件 |
|
||
|
|
|------|------|------|----------|
|
||
|
|
| 单人审批 | `approver` | 配置1个审批人 | 1人通过即可完成 |
|
||
|
|
| 会签 | `and_approve` | 配置多个审批人 | 所有人通过才完成 |
|
||
|
|
| 或签 | `or_approve` | 配置多个审批人 | 任一人通过即可完成 |
|
||
|
|
| 通知 | `notify` | 无需审批 | 自动跳过 |
|
||
|
|
|
||
|
|
### 流程状态
|
||
|
|
|
||
|
|
| 状态 | 常量 | 说明 |
|
||
|
|
|------|------|------|
|
||
|
|
| 待审批 | `pending` | 流程进行中 |
|
||
|
|
| 已通过 | `approved` | 流程完成(通过) |
|
||
|
|
| 已拒绝 | `rejected` | 流程结束(拒绝) |
|
||
|
|
| 已撤销 | `cancelled` | 申请人撤销 |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 基础流程图
|
||
|
|
|
||
|
|
### 完整审批流程
|
||
|
|
|
||
|
|
```
|
||
|
|
┌─────────────┐
|
||
|
|
│ 用户提交申请 │
|
||
|
|
└──────┬──────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌─────────────────────────────┐
|
||
|
|
│ 创建 ApprovalOrder │
|
||
|
|
│ - status = pending │
|
||
|
|
│ - current_nodes = [节点1] │
|
||
|
|
└──────┬──────────────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌─────────────────────────────┐
|
||
|
|
│ 发送飞书消息给审批人 │
|
||
|
|
│ - 保存 feishu_message 映射 │
|
||
|
|
│ - 记录 feishu_message_log │
|
||
|
|
└──────┬──────────────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌─────────────────────────────┐
|
||
|
|
│ 等待审批操作 │
|
||
|
|
│ (通过/拒绝/撤销) │
|
||
|
|
└──────┬──────────────────────┘
|
||
|
|
│
|
||
|
|
├─────────────┬─────────────┐
|
||
|
|
▼ ▼ ▼
|
||
|
|
[通过] [拒绝] [撤销]
|
||
|
|
│ │ │
|
||
|
|
▼ ▼ ▼
|
||
|
|
检查节点 订单结束 订单结束
|
||
|
|
是否完成 (rejected) (cancelled)
|
||
|
|
│
|
||
|
|
├──── [是] └──── [否]
|
||
|
|
▼ ▼
|
||
|
|
移动下一节点 保持pending
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
有下一节点?
|
||
|
|
├──── [是] └──── [否]
|
||
|
|
│ ▼
|
||
|
|
发送通知 订单结束
|
||
|
|
给下一节点 (approved)
|
||
|
|
审批人
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌─────────┐
|
||
|
|
│ 继续等待 │
|
||
|
|
│ 审批 │
|
||
|
|
└─────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 按节点类型的流程图
|
||
|
|
|
||
|
|
### 1. 单人审批 (approver)
|
||
|
|
|
||
|
|
**配置**: 配置1个审批人
|
||
|
|
**完成条件**: 1人通过即可
|
||
|
|
|
||
|
|
```
|
||
|
|
提交申请
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌───────────────────┐
|
||
|
|
│ 当前节点: 单人审批 │
|
||
|
|
│ 审批人: [张三] │
|
||
|
|
│ status: pending │
|
||
|
|
└─────┬─────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌───────────────────┐
|
||
|
|
│ 张三审批操作 │
|
||
|
|
└─────┬─────────────┘
|
||
|
|
│
|
||
|
|
├─────────────┬─────────────┐
|
||
|
|
▼ ▼ ▼
|
||
|
|
[通过] [拒绝] [撤销]
|
||
|
|
│ │ │
|
||
|
|
▼ ▼ ▼
|
||
|
|
1人通过 任一人拒绝 申请人撤销
|
||
|
|
满足条件 流程终止 流程终止
|
||
|
|
│ │ │
|
||
|
|
▼ ▼ ▼
|
||
|
|
┌─────────┐ ┌─────────┐ ┌─────────┐
|
||
|
|
│approved │ │rejected │ │cancelled│
|
||
|
|
│ 已通过 │ │已拒绝 │ │已撤销 │
|
||
|
|
└─────────┘ └─────────┘ └─────────┘
|
||
|
|
|
||
|
|
通知申请人 通知申请人 通知申请人
|
||
|
|
```
|
||
|
|
|
||
|
|
**关键代码逻辑**:
|
||
|
|
```php
|
||
|
|
if ($node->type === 'approver') {
|
||
|
|
// 单人审批:需要一人通过
|
||
|
|
return count($records) >= 1;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 2. 会签 (and_approve)
|
||
|
|
|
||
|
|
**配置**: 配置多个审批人
|
||
|
|
**完成条件**: 所有人通过
|
||
|
|
|
||
|
|
```
|
||
|
|
提交申请
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌───────────────────┐
|
||
|
|
│ 当前节点: 会签 │
|
||
|
|
│ 审批人: [张三,李四] │
|
||
|
|
│ status: pending │
|
||
|
|
└─────┬─────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌───────────────────┐
|
||
|
|
│ 张三审批操作 │
|
||
|
|
└─────┬─────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌───────────────────┐
|
||
|
|
│ 已审批: 1/2 │
|
||
|
|
│ 状态: pending │ ← 仍需其他人审批
|
||
|
|
│ ⚠️ 继续等待 │
|
||
|
|
└─────┬─────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌───────────────────┐
|
||
|
|
│ 李四审批操作 │
|
||
|
|
└─────┬─────────────┘
|
||
|
|
│
|
||
|
|
├─────────────┬─────────────┐
|
||
|
|
▼ ▼ ▼
|
||
|
|
[通过] [拒绝] [撤销]
|
||
|
|
│ │ │
|
||
|
|
▼ ▼ ▼
|
||
|
|
所有人通过 任一人拒绝 申请人撤销
|
||
|
|
2/2 满足条件 流程终止 流程终止
|
||
|
|
│ │ │
|
||
|
|
▼ ▼ ▼
|
||
|
|
┌─────────┐ ┌─────────┐ ┌─────────┐
|
||
|
|
│approved │ │rejected │ │cancelled│
|
||
|
|
│ 已通过 │ │已拒绝 │ │已撤销 │
|
||
|
|
└─────────┘ └─────────┘ └─────────┘
|
||
|
|
|
||
|
|
通知申请人 通知申请人 通知申请人
|
||
|
|
```
|
||
|
|
|
||
|
|
**关键代码逻辑**:
|
||
|
|
```php
|
||
|
|
if ($node->type === 'and_approve') {
|
||
|
|
// 会签:需要所有人通过
|
||
|
|
return count($records) >= count($approverIds);
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**测试结果**:
|
||
|
|
- 第1人通过 → 状态: pending (1/2)
|
||
|
|
- 第2人通过 → 状态: approved (2/2) ✅
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 3. 或签 (or_approve)
|
||
|
|
|
||
|
|
**配置**: 配置多个审批人
|
||
|
|
**完成条件**: 任一人通过
|
||
|
|
|
||
|
|
```
|
||
|
|
提交申请
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌───────────────────┐
|
||
|
|
│ 当前节点: 或签 │
|
||
|
|
│ 审批人: [张三,李四] │
|
||
|
|
│ status: pending │
|
||
|
|
└─────┬─────────────┘
|
||
|
|
│
|
||
|
|
├─────────────┐
|
||
|
|
▼ │
|
||
|
|
┌───────────────────┐ │
|
||
|
|
│ 张三审批操作 │ │
|
||
|
|
└─────┬─────────────┘ │
|
||
|
|
│ │
|
||
|
|
▼ │
|
||
|
|
[通过] │
|
||
|
|
│ │
|
||
|
|
▼ │
|
||
|
|
┌───────────────────┐ │
|
||
|
|
│ 1人通过 │ │
|
||
|
|
│ 满足条件 │ │
|
||
|
|
│ status: approved │ │
|
||
|
|
└─────────┬─────────┘ │
|
||
|
|
│ │
|
||
|
|
▼ │
|
||
|
|
┌────────────┐ │
|
||
|
|
│订单完成 │ │
|
||
|
|
│更新其他人消息│ │ ← 或签/单人特有
|
||
|
|
└────────────┘ │
|
||
|
|
│
|
||
|
|
▼ (李四无需操作)
|
||
|
|
┌─────────┐
|
||
|
|
│approved │
|
||
|
|
│ 已通过 │
|
||
|
|
└─────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
**关键代码逻辑**:
|
||
|
|
```php
|
||
|
|
if ($node->type === 'or_approve') {
|
||
|
|
// 或签:任一人通过即可
|
||
|
|
return count($records) >= 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 或签/单人完成后更新其他人的消息卡片
|
||
|
|
if ($node->type === 'or_approve' || $node->type === 'approver') {
|
||
|
|
$this->notificationService->updateMessageCards(...);
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**测试结果**:
|
||
|
|
- 第1人通过 → 状态: approved (1/2) ✅
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 4. 通知节点 (notify)
|
||
|
|
|
||
|
|
**配置**: 配置通知接收人
|
||
|
|
**完成条件**: 无需审批,自动跳过
|
||
|
|
|
||
|
|
```
|
||
|
|
前置节点完成
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌───────────────────┐
|
||
|
|
│ 检查下一节点 │
|
||
|
|
└─────┬─────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌───────────────────┐
|
||
|
|
│ 下一节点是通知? │
|
||
|
|
└─────┬─────────────┘
|
||
|
|
│
|
||
|
|
├──── [是] └──── [否] (审批节点)
|
||
|
|
│ │
|
||
|
|
▼ ▼
|
||
|
|
┌───────────────────┐ 继续等待审批
|
||
|
|
│ 自动跳过 │
|
||
|
|
│ 发送通知给接收人 │
|
||
|
|
└─────┬─────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌───────────────────┐
|
||
|
|
│ 检查还有后续节点? │
|
||
|
|
└─────┬─────────────┘
|
||
|
|
│
|
||
|
|
├──── [有] └──── [无]
|
||
|
|
│ │
|
||
|
|
▼ ▼
|
||
|
|
继续处理 订单完成
|
||
|
|
下一节点 (approved)
|
||
|
|
```
|
||
|
|
|
||
|
|
**代码逻辑**:
|
||
|
|
```php
|
||
|
|
if ($nextNode && $nextNode->type === 'notify') {
|
||
|
|
// 下一个是抄送节点,跳过并完成流程
|
||
|
|
$approvalOrder->status = ApprovalOrder::STATUS_APPROVED;
|
||
|
|
$approvalOrder->current_nodes = [];
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 特殊场景流程图
|
||
|
|
|
||
|
|
### 1. 拒绝流程 (所有节点类型通用)
|
||
|
|
|
||
|
|
```
|
||
|
|
审批进行中
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌───────────────────┐
|
||
|
|
│ 任一审批人拒绝 │
|
||
|
|
└─────┬─────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌───────────────────┐
|
||
|
|
│ 记录拒绝操作 │
|
||
|
|
│ action: reject │
|
||
|
|
│ comment: 原因... │
|
||
|
|
└─────┬─────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌───────────────────┐
|
||
|
|
│ 订单状态 → rejected│
|
||
|
|
│ 流程立即终止 │
|
||
|
|
│ 后续节点不执行 │
|
||
|
|
└─────┬─────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌───────────────────┐
|
||
|
|
│ 通知申请人 │
|
||
|
|
│ 「您的申请已被拒绝」│
|
||
|
|
└───────────────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
**代码逻辑**:
|
||
|
|
```php
|
||
|
|
if ($action === 'reject') {
|
||
|
|
// 拒绝:直接结束流程
|
||
|
|
$approvalOrder->status = ApprovalOrder::STATUS_REJECTED;
|
||
|
|
$approvalOrder->current_nodes = [];
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 2. 重复操作防护
|
||
|
|
|
||
|
|
```
|
||
|
|
审批人尝试操作
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌───────────────────┐
|
||
|
|
│ 检查是否已审批 │
|
||
|
|
│ 查询 approval_record│
|
||
|
|
└─────┬─────────────┘
|
||
|
|
│
|
||
|
|
├──── [已审批] └──── [未审批]
|
||
|
|
│ │
|
||
|
|
▼ ▼
|
||
|
|
┌───────────────────┐ 继续处理
|
||
|
|
│ 抛出异常 │
|
||
|
|
│ 「您已经XX过此申请」│
|
||
|
|
└───────────────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
**代码逻辑**:
|
||
|
|
```php
|
||
|
|
$existingRecord = ApprovalRecord::where('order_id', $order->id)
|
||
|
|
->where('approver_id', $approverId)
|
||
|
|
->whereIn('action', [ApprovalRecord::ACTION_APPROVE, ApprovalRecord::ACTION_REJECT])
|
||
|
|
->first();
|
||
|
|
|
||
|
|
if ($existingRecord) {
|
||
|
|
throw new \Exception("您已经{$action}过此申请,无需重复操作");
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 3. 撤销流程
|
||
|
|
|
||
|
|
```
|
||
|
|
审批进行中
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌───────────────────┐
|
||
|
|
│ 申请人撤销申请 │
|
||
|
|
└─────┬─────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌───────────────────┐
|
||
|
|
│ 记录撤销操作 │
|
||
|
|
│ action: cancel │
|
||
|
|
│ operato: 申请人 │
|
||
|
|
└─────┬─────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌───────────────────┐
|
||
|
|
│ 订单状态 → cancelled│
|
||
|
|
│ 流程立即终止 │
|
||
|
|
└─────┬─────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌───────────────────┐
|
||
|
|
│ 通知所有审批人 │
|
||
|
|
│ 「申请已被撤销」 │
|
||
|
|
└───────────────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
**代码逻辑**:
|
||
|
|
```php
|
||
|
|
public function cancel(int $orderId, int $userId): ApprovalOrder
|
||
|
|
{
|
||
|
|
$order = ApprovalOrder::findOrFail($orderId);
|
||
|
|
|
||
|
|
if ($order->applicant_id !== $userId) {
|
||
|
|
throw new \Exception('只有申请人可以撤销');
|
||
|
|
}
|
||
|
|
|
||
|
|
// 记录撤销操作
|
||
|
|
ApprovalRecord::create([
|
||
|
|
'order_id' => $order->id,
|
||
|
|
'node_id' => $currentNodeId,
|
||
|
|
'action' => 'cancel',
|
||
|
|
'operator_id' => $userId,
|
||
|
|
]);
|
||
|
|
|
||
|
|
$order->status = ApprovalOrder::STATUS_CANCELLED;
|
||
|
|
$order->current_nodes = [];
|
||
|
|
$order->save();
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 4. 多节点流转
|
||
|
|
|
||
|
|
```
|
||
|
|
提交申请
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌───────────────────┐
|
||
|
|
│ 节点1: 会签 │
|
||
|
|
│ [张三, 李四] │
|
||
|
|
│ status: pending │
|
||
|
|
└─────┬─────────────┘
|
||
|
|
│
|
||
|
|
├─────────────┐
|
||
|
|
▼ │
|
||
|
|
所有人通过 │
|
||
|
|
│ │
|
||
|
|
▼ │
|
||
|
|
┌───────────────────┐ │
|
||
|
|
│ 节点1完成 │ │
|
||
|
|
│ current_nodes │ │
|
||
|
|
│ → [节点2] │ │
|
||
|
|
└─────┬─────────────┘ │
|
||
|
|
│ │
|
||
|
|
▼ │
|
||
|
|
┌───────────────────┐ │
|
||
|
|
│ 节点2: 或签 │ │
|
||
|
|
│ [王五, 赵六] │ │
|
||
|
|
│ status: pending │ │
|
||
|
|
└─────┬─────────────┘ │
|
||
|
|
│ │
|
||
|
|
├─────────────┐ │
|
||
|
|
▼ │ │
|
||
|
|
任一人通过 │ │
|
||
|
|
│ │ │
|
||
|
|
▼ │ │
|
||
|
|
┌───────────────────┐ │
|
||
|
|
│ 节点2完成 │ │
|
||
|
|
│ current_nodes │ │
|
||
|
|
│ → [节点3] │ │
|
||
|
|
└─────┬─────────────┘ │
|
||
|
|
│ │
|
||
|
|
▼ │
|
||
|
|
┌───────────────────┐ │
|
||
|
|
│ 节点3: 通知 │ │
|
||
|
|
│ 自动跳过 │ │
|
||
|
|
└─────┬─────────────┘ │
|
||
|
|
│ │
|
||
|
|
▼ │
|
||
|
|
┌───────────────────┐ │
|
||
|
|
│ 流程完成 │ │
|
||
|
|
│ status: approved │ │
|
||
|
|
│ current_nodes: [] │ │
|
||
|
|
└───────────────────┘ │
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
通知申请人
|
||
|
|
```
|
||
|
|
|
||
|
|
**关键代码逻辑**:
|
||
|
|
```php
|
||
|
|
// 获取当前节点的 order 值
|
||
|
|
$currentOrder = $node->order ?? 0;
|
||
|
|
|
||
|
|
// 查找 order 比当前节点大的下一个节点
|
||
|
|
$nextNode = ApprovalNode::where('flow_id', $approvalOrder->flow_id)
|
||
|
|
->where('order', '>', $currentOrder)
|
||
|
|
->orderBy('order')
|
||
|
|
->first();
|
||
|
|
|
||
|
|
if ($nextNode) {
|
||
|
|
if ($nextNode->type === 'notify') {
|
||
|
|
// 跳过通知节点,完成流程
|
||
|
|
$approvalOrder->status = ApprovalOrder::STATUS_APPROVED;
|
||
|
|
} else {
|
||
|
|
// 移动到下一节点
|
||
|
|
$approvalOrder->current_nodes = [$nextNode->id];
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
// 没有下一节点,流程完成
|
||
|
|
$approvalOrder->status = ApprovalOrder::STATUS_APPROVED;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 状态流转图
|
||
|
|
|
||
|
|
### 完整状态机
|
||
|
|
|
||
|
|
```
|
||
|
|
┌─────────────┐
|
||
|
|
│ pending │ ◄─── 初始状态
|
||
|
|
│ (待审批) │
|
||
|
|
└──────┬──────┘
|
||
|
|
│
|
||
|
|
┌─────────────────┼─────────────────┐
|
||
|
|
│ │ │
|
||
|
|
▼ ▼ ▼
|
||
|
|
┌─────────┐ ┌─────────┐ ┌─────────┐
|
||
|
|
│ 节点完成 │ │ 任何人 │ │ 申请人 │
|
||
|
|
│检查 │ │ 拒绝 │ │ 撤销 │
|
||
|
|
└────┬────┘ └────┬────┘ └────┬────┘
|
||
|
|
│ │ │
|
||
|
|
│ ▼ ▼
|
||
|
|
│ ┌─────────┐ ┌─────────┐
|
||
|
|
│ │rejected │ │cancelled│
|
||
|
|
│ └─────────┘ └─────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌─────────────┐
|
||
|
|
│ 所有人通过? │
|
||
|
|
└────┬────────┘
|
||
|
|
│
|
||
|
|
├──── [是] └──── [否] (继续等待)
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌─────────────┐
|
||
|
|
│ 或签/单人 │
|
||
|
|
│ 任人通过? │
|
||
|
|
└────┬────────┘
|
||
|
|
│
|
||
|
|
├──── [是] └──── [否] (继续等待)
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌─────────────┐
|
||
|
|
│ 有下一节点? │
|
||
|
|
└────┬────────┘
|
||
|
|
│
|
||
|
|
├──── [是] └──── [否]
|
||
|
|
│ │
|
||
|
|
▼ ▼
|
||
|
|
┌─────────┐ ┌─────────┐
|
||
|
|
│移动到 │ │approved │
|
||
|
|
│下一节点 │ └─────────┘
|
||
|
|
└─────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
### 状态转换条件表
|
||
|
|
|
||
|
|
| 当前状态 | 触发条件 | 下一状态 | 说明 |
|
||
|
|
|----------|----------|----------|------|
|
||
|
|
| pending | 所有人通过(会签) | pending | 还有下一节点 |
|
||
|
|
| pending | 所有人通过(会签)+ 无下一节点 | approved | 流程完成 |
|
||
|
|
| pending | 任一人通过(或签/单人) | pending | 还有下一节点 |
|
||
|
|
| pending | 任一人通过(或签/单人)+ 无下一节点 | approved | 流程完成 |
|
||
|
|
| pending | 任一人拒绝 | rejected | 流程终止 |
|
||
|
|
| pending | 申请人撤销 | cancelled | 流程终止 |
|
||
|
|
| pending | 下一节点是notify | approved | 自动跳过通知节点 |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 消息发送流程图
|
||
|
|
|
||
|
|
### 消息类型
|
||
|
|
|
||
|
|
```
|
||
|
|
申请提交
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌───────────────────┐
|
||
|
|
│ 检查审批人列表 │
|
||
|
|
│ form_data.approvers│
|
||
|
|
└─────┬─────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌───────────────────┐
|
||
|
|
│ 遍历每个审批人 │
|
||
|
|
└─────┬─────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌───────────────────┐
|
||
|
|
│ 是否是申请人自己? │
|
||
|
|
└─────┬─────────────┘
|
||
|
|
│
|
||
|
|
├──── [是] └──── [否]
|
||
|
|
│ │
|
||
|
|
▼ ▼
|
||
|
|
┌─────────────┐ ┌─────────────┐
|
||
|
|
│发送文本消息 │ │发送卡片消息 │
|
||
|
|
│(自审批) │ │(带审批按钮) │
|
||
|
|
└─────────────┘ └────┬────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌─────────────┐
|
||
|
|
│保存消息映射 │
|
||
|
|
│feishu_message│
|
||
|
|
│message_id │
|
||
|
|
└─────────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
### 消息卡片更新流程 (或签/单人特有)
|
||
|
|
|
||
|
|
```
|
||
|
|
订单完成(或签/单人)
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌───────────────────┐
|
||
|
|
│ 获取该节点的所有 │
|
||
|
|
│ 消息映射 │
|
||
|
|
└─────┬─────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌───────────────────┐
|
||
|
|
│ 遍历每个其他审批人 │
|
||
|
|
│ (排除已操作的人) │
|
||
|
|
└─────┬─────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌───────────────────┐
|
||
|
|
│ 更新消息卡片 │
|
||
|
|
│ 移除审批按钮 │
|
||
|
|
│ 显示「已被XX处理」 │
|
||
|
|
└─────┬─────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌───────────────────┐
|
||
|
|
│ 记录更新日志 │
|
||
|
|
│ action: update_card│
|
||
|
|
└───────────────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 附录:数据模型关系
|
||
|
|
|
||
|
|
### 核心表关系
|
||
|
|
|
||
|
|
```
|
||
|
|
approval_flow (审批流程)
|
||
|
|
│
|
||
|
|
├── approval_node (审批节点)
|
||
|
|
│ ├── 1: approver (单人)
|
||
|
|
│ ├── 2: and_approve (会签)
|
||
|
|
│ ├── 3: or_approve (或签)
|
||
|
|
│ └── 4: notify (通知)
|
||
|
|
│
|
||
|
|
└── approval_order (审批订单)
|
||
|
|
│
|
||
|
|
├── form_data (表单数据)
|
||
|
|
│ ├── approvers: [1, 2, 3]
|
||
|
|
│ └── cc_users: [4, 5]
|
||
|
|
│
|
||
|
|
├── approval_record (审批记录)
|
||
|
|
│ ├── action: approve/reject/cancel/submit
|
||
|
|
│ └── approver_id: 用户ID
|
||
|
|
│
|
||
|
|
└── feishu_message (消息映射)
|
||
|
|
└── message_id: 飞书消息ID
|
||
|
|
|
||
|
|
feishu_message_log (消息日志)
|
||
|
|
├── action: send/update/update_card
|
||
|
|
├── status: success/failed
|
||
|
|
└── error_message: 错误信息
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
**文档维护**: 开发团队
|
||
|
|
**最后更新**: 2026-03-01
|
||
|
|
**相关文档**:
|
||
|
|
- `docs/APPROVAL_NOTIFICATION_ARCHITECTURE.md` - 审批通知架构文档
|
||
|
|
- `docs/TEST_REPORT_COMPLETE_20260301.md` - 完整测试报告
|