docs(docs): 调整数据库与详细设计目录编号

This commit is contained in:
zhiye.sun
2026-06-10 15:15:02 +08:00
parent db0e94cf26
commit a060c23ba7
8 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,302 @@
# 飞书通知与问答接入数据库设计
## 文档信息
| 项目 | 内容 |
| --- | --- |
| 需求分析文档 | docs/1.需求分析/4.飞书通知与问答接入.md |
| 功能设计文档 | docs/2.功能设计/4.飞书通知与问答接入.md |
| 数据库类型 | SQLite / Django ORM |
| 表名前缀 | ra_ |
| 设计日期 | 2026-06-07 |
| 设计版本 | V1.0 |
---
## 一、设计原则
| 原则 | 说明 |
| --- | --- |
| 统一通知抽象 | 三个工作流共用统一通知服务和通用通知记录,减少重复实现 |
| 兼容现有表 | 现有法规通知、填表通知可保留;新增通用表作为后续统一入口 |
| 可判重 | 通知记录必须支持同一批次、同一流程、同一状态只发送一次 |
| 摘要入库 | 只保存发送摘要、状态、错误,不保存完整富文本 payload |
| 映射可维护 | 系统用户与飞书用户映射独立建表,通过 Django Admin 维护 |
| 问答可扩展 | 预留问答日志表,首期可不接事件回调 |
| SQLite 兼容 | 使用 Django ORM 常规字段,避免数据库特有能力 |
---
## 二、ER 图
```mermaid
erDiagram
AUTH_USER ||--o{ RA_FEISHU_USER_MAPPING : maps
AUTH_USER ||--o{ RA_WORKFLOW_NOTIFICATION_RECORD : triggers
RA_FEISHU_USER_MAPPING ||--o{ RA_WORKFLOW_NOTIFICATION_RECORD : resolves
AUTH_USER ||--o{ RA_FEISHU_QUESTION_LOG : asks
RA_WORKFLOW_NOTIFICATION_RECORD {
bigint id
string workflow_type
bigint workflow_batch_id
string workflow_status
string dedupe_key
string channel
string target
string send_status
}
RA_FEISHU_USER_MAPPING {
bigint id
bigint system_user_id
string feishu_open_id
string feishu_user_id
string feishu_mobile
boolean is_active
}
RA_FEISHU_QUESTION_LOG {
bigint id
bigint system_user_id
string feishu_open_id
string intent
string query_object
string status
}
```
---
## 三、表结构设计
### 3.1 ra_feishu_user_mapping
系统用户与飞书用户标识映射表。首期通知发送给环境变量中配置的指定个人账号,本表通过 Django Admin 手工维护,用于后续按发起人私聊通知和飞书私聊问答身份识别。
| 字段名 | Django 类型 | SQLite 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| id | BigAutoField | integer | 是 | 主键 |
| system_user_id | ForeignKey | bigint | 是 | 关联 Django 用户 |
| feishu_display_name | CharField(120) | varchar(120) | 否 | 飞书展示名,便于后台识别 |
| feishu_open_id | CharField(120) | varchar(120) | 否 | 飞书 open_id优先用于 @ |
| feishu_user_id | CharField(120) | varchar(120) | 否 | 飞书 user_id第二优先级 |
| feishu_mobile | CharField(40) | varchar(40) | 否 | 飞书手机号,兜底 |
| is_active | BooleanField | bool | 是 | 是否启用 |
| remark | CharField(255) | varchar(255) | 否 | 备注 |
| created_at | DateTimeField | datetime | 是 | 创建时间 |
| updated_at | DateTimeField | datetime | 是 | 更新时间 |
约束:
| 约束名 | 字段 | 说明 |
| --- | --- | --- |
| uq_ra_feishu_mapping_user | system_user_id | 一个系统用户首期只维护一条启用映射 |
索引:
| 索引名 | 字段 | 说明 |
| --- | --- | --- |
| idx_ra_feishu_mapping_active | is_active | 后台筛选启用映射 |
| idx_ra_feishu_mapping_open | feishu_open_id | 后续私聊事件反查用户 |
| idx_ra_feishu_mapping_userid | feishu_user_id | 后续私聊事件反查用户 |
| idx_ra_feishu_mapping_mobile | feishu_mobile | 手机号兜底查询 |
校验规则:
| 规则 | 说明 |
| --- | --- |
| 至少一个飞书标识 | `feishu_open_id``feishu_user_id``feishu_mobile` 至少填写一个 |
| @ 优先级 | `feishu_open_id -> feishu_user_id -> feishu_mobile` |
---
### 3.2 ra_workflow_notification_record
通用工作流通知记录表。用于记录自动汇总、法规核查、自动填表的飞书通知发送结果。现有专项通知表可继续保留,后续逐步收敛到本表。
| 字段名 | Django 类型 | SQLite 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| id | BigAutoField | integer | 是 | 主键 |
| workflow_type | CharField(40) | varchar(40) | 是 | file_summary、regulatory_review、application_form_fill |
| workflow_batch_id | PositiveBigIntegerField | bigint | 是 | 对应工作流批次 ID |
| workflow_batch_no | CharField(80) | varchar(80) | 是 | 批次编号冗余,便于展示 |
| workflow_status | CharField(40) | varchar(40) | 是 | success、partial_success、failed 等 |
| dedupe_key | CharField(160) | varchar(160) | 是 | 判重键 |
| trigger_user_id | ForeignKey | bigint | 是 | 发起人或上传人 |
| feishu_mapping_id | ForeignKey | bigint | 否 | 命中的飞书用户映射 |
| channel | CharField(40) | varchar(40) | 是 | mock、feishu_api、disabled |
| target | CharField(160) | varchar(160) | 否 | 指定个人账号名称、open_id、user_id 或目标标识 |
| at_display_name | CharField(120) | varchar(120) | 否 | 被 @ 人展示名 |
| at_identifier_type | CharField(30) | varchar(30) | 否 | open_id、user_id、mobile、missing |
| at_identifier_masked | CharField(120) | varchar(120) | 否 | 脱敏后的 @ 标识 |
| send_status | CharField(30) | varchar(30) | 是 | pending、success、failed、skipped_duplicate、disabled |
| message_title | CharField(200) | varchar(200) | 是 | 通知标题 |
| message_summary | TextField | text | 否 | 发送摘要,不保存完整 payload |
| result_url | CharField(500) | varchar(500) | 否 | 系统结果入口 |
| external_message_id | CharField(120) | varchar(120) | 否 | Webhook 一般为空API 发送时保存 |
| error_code | CharField(80) | varchar(80) | 否 | 飞书或客户端错误码 |
| error_message | TextField | text | 否 | 失败原因 |
| request_duration_ms | PositiveIntegerField | integer | 否 | HTTP 请求耗时 |
| sent_at | DateTimeField | datetime | 否 | 成功发送时间 |
| created_at | DateTimeField | datetime | 是 | 创建时间 |
| updated_at | DateTimeField | datetime | 是 | 更新时间 |
唯一约束:
| 约束名 | 字段 | 说明 |
| --- | --- | --- |
| uq_ra_notify_dedupe_key | dedupe_key | 同一批次、流程、状态只保留一个成功发送意图 |
索引:
| 索引名 | 字段 | 说明 |
| --- | --- | --- |
| idx_ra_notify_workflow | workflow_type, workflow_batch_id | 批次详情页查询通知 |
| idx_ra_notify_user_created | trigger_user_id, created_at | 用户通知历史 |
| idx_ra_notify_status | send_status, created_at | 排查失败通知 |
| idx_ra_notify_batch_no | workflow_batch_no | 按批次编号检索 |
dedupe_key 生成规则:
```text
{workflow_type}:{workflow_batch_id}:{workflow_status}
```
---
### 3.3 ra_feishu_question_log
飞书问答日志预留表。首期可创建表但不接入事件回调;后续私聊问答 MVP 使用该表记录问题、意图、查询对象、回答摘要和错误信息。
| 字段名 | Django 类型 | SQLite 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| id | BigAutoField | integer | 是 | 主键 |
| system_user_id | ForeignKey | bigint | 否 | 识别出的系统用户 |
| feishu_mapping_id | ForeignKey | bigint | 否 | 命中的飞书映射 |
| feishu_open_id | CharField(120) | varchar(120) | 否 | 事件中的 open_id |
| feishu_user_id | CharField(120) | varchar(120) | 否 | 事件中的 user_id |
| source_type | CharField(30) | varchar(30) | 是 | private_chat、group_mention |
| message_id | CharField(120) | varchar(120) | 否 | 飞书消息 ID |
| question_text | TextField | text | 是 | 用户原始问题 |
| intent | CharField(60) | varchar(60) | 否 | batch_status、risk_summary、export_summary 等 |
| query_object | JSONField | text/json | 是 | 批次号、工作流类型、最近批次等查询对象 |
| answer_summary | TextField | text | 否 | 回答摘要,不保存完整回答正文 |
| permission_result | CharField(40) | varchar(40) | 否 | allowed、denied、unbound |
| status | CharField(30) | varchar(30) | 是 | success、failed、ignored |
| error_message | TextField | text | 否 | 异常说明 |
| processed_at | DateTimeField | datetime | 否 | 处理完成时间 |
| created_at | DateTimeField | datetime | 是 | 创建时间 |
索引:
| 索引名 | 字段 | 说明 |
| --- | --- | --- |
| idx_ra_feishu_q_user_created | system_user_id, created_at | 用户问答历史 |
| idx_ra_feishu_q_intent | intent, created_at | 按意图分析 |
| idx_ra_feishu_q_status | status, created_at | 排查失败问答 |
| idx_ra_feishu_q_message | message_id | 消息幂等 |
---
## 四、状态枚举
### 4.1 WorkflowNotificationRecord.channel
| 值 | 说明 |
| --- | --- |
| mock | 模拟通知 |
| disabled | 真实通知未启用 |
| feishu_api | 飞书官方智能体/企业自建应用消息 API |
| feishu_webhook | 备选自定义机器人 Webhook非首期主方案 |
### 4.2 WorkflowNotificationRecord.send_status
| 值 | 说明 |
| --- | --- |
| pending | 待发送 |
| success | 发送成功 |
| failed | 发送失败 |
| skipped_duplicate | 重复通知跳过 |
| disabled | 未启用真实发送 |
### 4.3 FeishuQuestionLog.intent
| 值 | 说明 |
| --- | --- |
| batch_status | 查询批次状态 |
| risk_summary | 查询风险摘要 |
| missing_summary | 查询缺失摘要 |
| export_summary | 查询导出摘要 |
| unknown | 未识别 |
---
## 五、与现有表的兼容关系
| 现有表 | 处理建议 |
| --- | --- |
| `ra_regulatory_notification_record` | 保留现有数据;法规核查真实飞书通知可新增写入通用表,后续再决定是否迁移 |
| `ra_application_form_fill_notification_record` | 保留现有数据;自动填表通知状态展示可优先读通用表,兼容旧表 |
| `ra_exported_summary_file` | 通知摘要中的导出文件数量来自该表 |
| `ra_workflow_event` | 可记录通知节点事件,但不替代通知记录表 |
| `auth_user` | 飞书映射通过外键关联系统用户 |
---
## 六、数据脱敏与安全
| 数据 | 入库策略 |
| --- | --- |
| App ID | 不入库,只在环境变量中维护 |
| App Secret | 不入库,只在环境变量中维护 |
| tenant_access_token | 不持久化入库,仅允许进程内短期缓存 |
| 富文本完整 payload | 不入库 |
| 手机号 | 映射表保存原值;通知记录只保存脱敏值 |
| open_id/user_id | 映射表保存原值;通知记录保存脱敏值 |
| 用户问题 | 问答日志保存原始问题,用于审计;不保存完整回答正文 |
---
## 七、迁移计划
| 步骤 | 说明 |
| --- | --- |
| 1 | 新增 `FeishuUserMapping` 模型和迁移 |
| 2 | 新增 `WorkflowNotificationRecord` 模型和迁移 |
| 3 | 新增 `FeishuQuestionLog` 预留模型和迁移 |
| 4 | 注册 Django Admin 管理入口 |
| 5 | 批次详情页查询通用通知记录展示 |
| 6 | 保留现有专项通知表,不做破坏性迁移 |
---
## 八、验收 SQL 示例
查询某个批次通知状态:
```sql
SELECT workflow_type, workflow_batch_no, workflow_status, channel, send_status, sent_at, error_message
FROM ra_workflow_notification_record
WHERE workflow_type = 'application_form_fill'
AND workflow_batch_no = 'AFF-20260607-001'
ORDER BY created_at DESC;
```
查询未配置飞书映射的失败或降级通知:
```sql
SELECT workflow_type, workflow_batch_no, trigger_user_id, send_status, message_summary
FROM ra_workflow_notification_record
WHERE at_identifier_type = 'missing'
ORDER BY created_at DESC;
```
查询飞书用户映射:
```sql
SELECT u.username, m.feishu_display_name, m.feishu_open_id, m.feishu_user_id, m.feishu_mobile, m.is_active
FROM ra_feishu_user_mapping m
JOIN auth_user u ON u.id = m.system_user_id
ORDER BY u.username;
```