Files
AI-Secretary/docs/contracts/数据对象约定.md
2026-06-22 17:30:59 +08:00

393 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 数据对象约定
本文件是核心表、字段、外键关系和状态字段的唯一事实源。Django model、serializer、接口返回和测试用例中的字段应与本文件一致。
## 1. 通用字段
多数业务表使用:
| 字段 | 说明 |
| --- | --- |
| `id` | 主键,建议 bigint 或 uuid |
| `created_at` | 创建时间 |
| `updated_at` | 更新时间 |
| `created_by` | 创建人,可为空时必须说明来源 |
| `updated_by` | 最后修改人 |
| `deleted_at` | 软删除时间,可选 |
| `remark` | 备注,可选 |
第一版建议使用软删除,避免误删过程记录。
## 2. users
平台登录、角色判断和数据范围控制。Django 项目初始化时建议使用自定义用户模型。
| 字段 | 说明 |
| --- | --- |
| `id` | 用户 ID |
| `username` | 登录名或内部唯一标识 |
| `name` | 显示姓名 |
| `role` | `boss``manager``employee``admin` |
| `phone` | 手机号,可选,普通日志需脱敏 |
| `email` | 邮箱,可选,普通日志需脱敏 |
| `feishu_open_id` | 飞书 open_id,可选 |
| `feishu_user_id` | 飞书 user_id,可选 |
| `feishu_union_id` | 飞书 union_id,可选 |
| `auth_provider` | `local``feishu` |
| `last_login_channel` | `platform``feishu_scan``feishu_in_app` |
| `status` | `active``disabled` |
| `last_login_at` | 最后登录时间 |
## 3. person_mappings
把老板输入中的姓名、称呼、部门或角色映射到平台用户和飞书身份。
| 字段 | 说明 |
| --- | --- |
| `id` | 映射 ID |
| `user_id` | 关联平台用户,可选 |
| `display_name` | 标准姓名 |
| `aliases` | JSON 数组,例如 `["东东", "CJN"]` |
| `department` | 部门 |
| `business_role` | 业务角色,例如行政、程经理、下单员 |
| `manager_user_id` | 第一批试用管理范围归属,可选 |
| `phone` | 手机号,可选 |
| `email` | 邮箱,可选 |
| `feishu_open_id` | 飞书 open_id |
| `feishu_user_id` | 飞书 user_id,可选 |
| `feishu_union_id` | 飞书 union_id,可选 |
| `mapping_status` | `pending``resolved``failed` |
| `is_trial_user` | 是否第一批试用人员 |
| `note` | 备注 |
口径:
1. `users` 是登录、角色和权限判断的权威对象。
2. `person_mappings` 是自然语言称呼、手机号 / 邮箱、飞书身份和第一批试用人员映射的权威对象。
3. 同一个真实人员如果可以登录平台,应在 `person_mappings.user_id` 绑定对应 `users.id`
4. 程经理第一批试用管理范围先用 `manager_user_id` 或等价白名单表达,不引入完整组织树。
## 4. feishu_auth_sessions
记录飞书登录过程和平台用户绑定结果。
| 字段 | 说明 |
| --- | --- |
| `id` | 会话 ID |
| `state` | OAuth state 或登录状态标识 |
| `feishu_open_id` | 飞书 open_id |
| `feishu_user_id` | 飞书 user_id |
| `feishu_union_id` | 飞书 union_id,可选 |
| `matched_user_id` | 匹配到的平台用户 |
| `login_channel` | `feishu_scan``feishu_in_app` |
| `status` | `pending``success``failed` |
| `failure_reason` | 失败原因 |
| `completed_at` | 完成时间 |
## 5. secretary_conversations
老板 AI 秘书会话。第一阶段只有一个老板秘书入口,可先固定 `conversation_id=boss_secretary_default`,但表结构要能支持后续多会话。
| 字段 | 说明 |
| --- | --- |
| `id` | 会话 ID |
| `conversation_id` | 业务会话唯一标识 |
| `boss_id` | 关联老板用户 |
| `source` | `feishu``web``debug` |
| `status` | `active``closed` |
| `last_message_at` | 最近消息时间 |
## 6. secretary_messages
老板输入、AI 回复、AI 追问、普通记录和上下文回顾的统一消息记录。该表只追加,不修改,用于对话回放、上下文回顾和问题复盘。
| 字段 | 说明 |
| --- | --- |
| `id` | 消息 ID |
| `conversation_id` | 关联 `secretary_conversations.conversation_id` |
| `boss_id` | 关联老板用户 |
| `source` | `feishu``web``debug` |
| `message_id` | 外部消息 ID 或内部生成 ID,和 `source` 组成幂等键 |
| `role` | `boss``assistant``system` |
| `text` | 原始输入或 AI 回复 |
| `answer` | AI 给老板的回复,可为空 |
| `intent_type` | `task``reminder``qa``realtime_qa``note``need_more_info``unknown``unsupported``context_summary` |
| `draft_id` | 关联 AI 草稿,可为空 |
| `raw_payload` | 原始请求摘要,避免保存密钥 |
| `bot_context_snapshot` | JSONB,消息发生时的上下文快照 |
| `created_at` | 消息时间 |
## 7. bot_contexts
记录老板机器人私聊中的补充/重说上下文。
| 字段 | 说明 |
| --- | --- |
| `id` | 上下文 ID |
| `conversation_id` | 当前老板秘书会话 ID |
| `boss_id` | PostgreSQL 中的老板用户 ID |
| `status` | `empty``awaiting_more_info``awaiting_confirm``awaiting_follow_up``expired``cleared` |
| `pending_draft_id` | 当前待补充或待确认的草稿 ID |
| `pending_draft_type` | `task``reminder``none` |
| `last_intent` | 上一条有效意图 |
| `expires_at` | 上下文有效期,进入待补充或待确认时重置为 30 分钟后 |
| `follow_up_count` | 当前草稿累计追问轮次 |
| `last_message_id` | 最近一次参与上下文判断的消息 ID |
| `extracted_facts` | JSONB,从多轮对话提取的候选事实,只用于草稿修订 |
| `updated_at` | 上下文最近更新时间 |
`awaiting_follow_up` 专用于老板点击飞书确认卡片上的“补充/重说”后,等待下一条消息修订上一版草稿;该状态必须带 `pending_draft_id``expires_at`
## 8. prompt_contexts
维护 AI 秘书调用模型时加载的上下文版本。
| 字段 | 说明 |
| --- | --- |
| `id` | 上下文 ID |
| `context_type` | `company_background_summary``boss_communication_style``ai_secretary_rules``role_and_alias_rules` |
| `version` | 版本号 |
| `title` | 标题 |
| `content` | 实际使用的摘要或规则文本 |
| `status` | `draft``active``archived` |
| `activated_at` | 启用时间 |
| `created_by` | 创建人 |
模型调用日志只保存本次使用的摘要、版本号和必要规则,避免反复保存完整背景库全文。
## 9. ai_drafts
保存 AI 从一句话整理出的可确认草稿。
| 字段 | 说明 |
| --- | --- |
| `id` | 草稿 ID |
| `source` | `platform``feishu_bot` |
| `source_message_id` | 飞书或外部入口消息 ID,可选 |
| `created_by` | 发起人 |
| `parent_draft_id` | 补充/重说生成新草稿时,关联上一版草稿 |
| `raw_input` | 原始输入 |
| `intent` | `task``reminder``qa``realtime_qa``note``need_more_info``unknown``unsupported` |
| `draft_type` | `task``reminder``none` |
| `should_create_draft` | `task/reminder` 为 true;其他意图必须为 false |
| `status` | 见状态流转约定 |
| `title` | 草稿标题 |
| `content` | 事项或提醒内容 |
| `receiver_candidates` | JSON,接收人候选和置信度 |
| `receiver_text` | 未映射成功时保留老板原始称呼 |
| `selected_receiver_id` | 人工确认后的接收人,可选 |
| `scheduled_at` | 提醒时间,可为空;任务可使用 `schedule_text` 表达期望时间 |
| `schedule_text` | 老板原始时间表达 |
| `recurrence_type` | `none``daily``weekly``monthly` |
| `requires_feedback` | 是否需要反馈 |
| `route_type` | `none``direct_after_boss_confirm``manager_confirm_required` |
| `need_manager_confirm` | 是否需要程经理确认 |
| `missing_fields` | JSON 数组 |
| `questions` | JSON 数组,最多 3 个;确认草稿一般为空 |
| `answer` | 给老板看的回复摘要;不得写“已通知、已创建、已发送”等执行语义 |
| `active_card_notification_id` | 当前有效确认卡片通知,可选 |
| `superseded_by_draft_id` | 被补充/重说的新草稿替代时,指向新草稿 |
| `model_call_log_id` | 关联模型调用日志 |
| `confirmed_by` | 确认人 |
| `confirmed_at` | 确认时间 |
| `cancelled_reason` | 取消原因 |
草稿生命周期口径:
1. 每个草稿同一时间只能有一张有效确认卡片,对应 `active_card_notification_id`
2. 老板点击“补充/重说”后,原草稿进入 `awaiting_follow_up`,原确认卡片应失效。
3. 30 分钟内收到补充消息后,系统生成新草稿,`parent_draft_id` 指向原草稿;原草稿进入 `superseded``superseded_by_draft_id` 指向新草稿。
4. 超过 30 分钟仍未收到补充消息时,`bot_contexts` 标记为 `expired`,原草稿进入 `expired`;老板下一条消息按新输入处理。
5. `note` / `unknown` 不进入事项、提醒或通知闭环;如需留痕,只能保存回复、消息、模型调用日志或最小草稿记录。
## 10. model_call_logs
记录模型输入输出、模型名、耗时和结果。
| 字段 | 说明 |
| --- | --- |
| `id` | 日志 ID |
| `provider` | `bailian` |
| `model_name` | 模型名 |
| `prompt_version` | 提示词版本 |
| `background_context_version` | 公司背景摘要版本 |
| `boss_style_version` | 老板沟通风格版本 |
| `ai_secretary_rules_version` | AI 秘书业务规则版本 |
| `context_snapshot` | 本次使用的上下文版本和摘要 |
| `input_text` | 用户原始输入 |
| `request_payload` | 请求摘要,避免保存密钥 |
| `response_payload` | 模型原始响应结构 |
| `parsed_result` | 后端解析后的 `AiSecretaryResponse` JSON |
| `status` | `success``failed` |
| `error_message` | 失败原因 |
| `latency_ms` | 耗时 |
| `created_by` | 调用发起人 |
## 11. tasks
需要接收人处理并反馈的事情。
| 字段 | 说明 |
| --- | --- |
| `id` | 事项 ID |
| `source_type` | `ai_draft``manual` |
| `source_draft_id` | 来源草稿,可选 |
| `title` | 标题 |
| `content` | 事项内容 |
| `initiator_id` | 发起人 |
| `receiver_id` | 接收人;复杂事项在程经理确认前可为空 |
| `manager_id` | 复杂事项确认人,可选 |
| `status` | 见状态流转约定 |
| `visible_feedback_status` | `received``in_progress``completed``problem` |
| `requires_feedback` | 是否需要反馈 |
| `due_at` | 截止或期望反馈时间,可选 |
| `confirmed_at` | 确认时间 |
| `notified_at` | 通知时间 |
| `completed_at` | 完成时间 |
| `problem_reason` | 有问题原因,可选 |
复杂事项必须在老板确认后创建 `status=pending_manager_confirm` 的事项壳,不得一直停留在草稿中等待程经理补齐。
## 12. reminders
未来某个时间触发的提醒。
| 字段 | 说明 |
| --- | --- |
| `id` | 提醒 ID |
| `source_type` | `ai_draft``manual` |
| `source_draft_id` | 来源草稿,可选 |
| `related_task_id` | 关联事项,可选 |
| `title` | 标题 |
| `content` | 提醒内容 |
| `initiator_id` | 发起人 |
| `receiver_id` | 接收人 |
| `status` | 见状态流转约定 |
| `scheduled_at` | 首次提醒时间 |
| `next_trigger_at` | 下一次触发时间 |
| `recurrence_type` | `none``daily``weekly``monthly` |
| `requires_feedback` | 是否需要反馈 |
| `last_triggered_at` | 最近触发时间 |
| `cancelled_at` | 取消时间 |
## 13. notifications
飞书或平台内通知发送记录。
| 字段 | 说明 |
| --- | --- |
| `id` | 通知 ID |
| `target_type` | `ai_draft``task``reminder``failure_record` |
| `target_id` | 关联对象 ID |
| `purpose` | `draft_confirm``manager_confirm``task_notify``reminder_trigger` |
| `receiver_id` | 接收人 |
| `channel` | `feishu_personal``feishu_group``platform` |
| `message_type` | `text``card` |
| `title` | 通知标题 |
| `summary` | 通知摘要 |
| `link_url` | 平台详情链接 |
| `card_id` | 飞书卡片 ID,可选 |
| `status` | `pending``sending``sent``failed``retrying``cancelled``expired` |
| `trigger_time` | 提醒触发时间;非提醒触发通知可为空 |
| `idempotency_key` | 幂等键,按通知目的生成并唯一约束 |
| `action_token_hash` | 平台反馈页一次性操作 token 的 hash,可选 |
| `feishu_message_id` | 飞书消息 ID |
| `sent_at` | 发送时间 |
| `expires_at` | 卡片或通知操作过期时间,可选 |
| `invalidated_at` | 被新卡片替代或业务取消时的失效时间,可选 |
| `failure_reason` | 失败原因 |
| `retry_count` | 重试次数 |
| `last_retry_at` | 最近重试时间 |
提醒触发类通知的幂等键格式建议:
```text
reminder:{reminder_id}:{trigger_time}:{receiver_id}:{channel}
```
任务通知、草稿确认卡片和程经理待确认提醒也必须生成各自的幂等键,避免重复点击、重复补发或回调重放造成多条有效通知。
## 14. feedbacks
接收人的反馈状态和问题原因。
| 字段 | 说明 |
| --- | --- |
| `id` | 反馈 ID |
| `target_type` | `task``reminder` |
| `target_id` | 关联对象 ID |
| `feedback_by` | 反馈人 |
| `status` | `received``in_progress``completed``problem` |
| `problem_reason` | 有问题原因,`problem` 时必填 |
| `source` | `feishu_card``platform` |
| `notification_id` | 关联通知 |
| `created_at` | 反馈时间 |
## 15. failure_records
AI、通知、回调、调度等失败原因。
| 字段 | 说明 |
| --- | --- |
| `id` | 失败记录 ID |
| `failure_type` | 见状态流转约定中的失败类型 |
| `target_type` | 关联对象类型 |
| `target_id` | 关联对象 ID |
| `status` | `pending``processing``resolved``cancelled` |
| `reason` | 失败原因 |
| `raw_error` | 原始错误摘要,不含密钥 |
| `need_manager_sync` | 是否需要同步程经理 |
| `handled_by` | 处理人 |
| `handled_at` | 处理时间 |
| `handle_result` | 处理结果 |
`target_type` 可使用 `ai_draft``task``reminder``notification``feishu_event``model_call_log` 等实际对象类型。AI 解析失败时,如果无法创建最小 `parse_failed` 草稿,可关联 `model_call_log`
## 16. operation_logs
人工确认、修改、取消、补发等过程留痕。
| 字段 | 说明 |
| --- | --- |
| `id` | 日志 ID |
| `actor_id` | 操作人 |
| `action` | 动作 |
| `target_type` | 对象类型 |
| `target_id` | 对象 ID |
| `channel` | `platform``feishu_bot``feishu_card``scheduler``admin` |
| `result` | `success``failed` |
| `summary` | 操作摘要 |
| `metadata` | JSON,避免敏感明文 |
| `created_at` | 操作时间 |
## 17. feishu_events
飞书回调原始事件和处理结果。
| 字段 | 说明 |
| --- | --- |
| `id` | 事件 ID |
| `event_id` | 飞书事件 ID |
| `event_type` | 事件类型 |
| `operator_open_id` | 操作人 open_id |
| `action_value` | 按钮值 |
| `idempotency_key` | 事件处理幂等键,可选 |
| `target_type` | `ai_draft``task``reminder``auth``bot` |
| `target_id` | 关联业务对象 |
| `notification_id` | 关联通知 |
| `raw_payload` | 原始事件 |
| `process_status` | `pending``processed``failed``ignored` |
| `process_result` | 处理结果 |
| `created_at` | 接收时间 |
`event_id` 应尽量设置唯一约束;如果飞书某类回调没有稳定 `event_id`,则用 `operator_open_id + action_value + notification_id + target_id` 生成 `idempotency_key` 并唯一约束。重复事件只返回已处理结果,不重复创建草稿、事项、提醒、反馈或通知。
## 18. 敏感字段规则
1. `phone``email` 可入库,但普通日志和普通列表接口默认脱敏。
2. API Key、App Secret、飞书 token、飞书回调验签密钥、OAuth code/state、一次性操作 token 明文不得入库到业务表或普通日志。
3. `raw_error``metadata``request_payload``response_payload` 必须避免密钥和完整个人联系方式。
4. 飞书通知内容只保存和发送摘要,不展开敏感全文。
5. `model_call_logs` 原始请求/响应和 `feishu_events.raw_payload` 仅供管理员 / AI 团队排查,普通员工不可见,老板和程经理只在必要业务范围内查看摘要。
6. 平台反馈页一次性操作 token 只能保存 hash,不能保存明文。