# ARCHITECTURE.md 本文是后端架构入口,说明 Django 项目内部模块边界和调用规则。具体业务需求看 `docs/specs/`,字段、接口、状态、安全权限和日志边界以 `docs/contracts/` 为准。 ## 架构原则 1. 第一版采用 Django 模块化单体,不拆微服务。 2. app 负责边界和数据归属,复杂业务逻辑放 service 层。 3. view / serializer 只做请求响应、参数校验和呈现,不承载复杂流程。 4. 所有关键动作必须写操作日志或失败记录。 5. 飞书回调、AI 输出、定时触发必须幂等。 6. 权限必须在接口层和 service 层双重校验。 7. 敏感信息脱敏、飞书验签和访问边界以 `docs/contracts/安全权限日志约定.md` 为准。 ## 运行时与依赖版本 > 第一版新项目采用仍在官方扩展支持期内的 Django 5.2 LTS。Docker / 部署环境固定 Python 3.12.13;本地开发允许 Python 3.11 或 3.12,但提交前必须在部署基线 Python 3.12.13 上跑完整测试。 | 类别 | 版本约定 | | --------------- | -------------------------------------------------------------------------------- | | Python | 部署 `3.12.13`;本地开发 `>=3.11,<3.13` | | Web 框架 | `Django==5.2.15` | | API 框架 | `djangorestframework==3.17.1` | | ORM / Migration | Django ORM + Django Migrations,跟随 `Django==5.2.15` | | 数据库 | PostgreSQL `18.x`,作为唯一数据源;业务表、AI 对话记忆、上下文快照和日志都落同一套 PostgreSQL | | PostgreSQL 驱动 | `psycopg[binary]`,具体 patch 版本以 `requirements.txt` 锁定为准 | | 定时任务 | `APScheduler==3.11.2` + `django-apscheduler==0.7.0`,通过独立 management command 进程运行 | | AI 接入 | `dashscope==1.25.23`;百炼管理类 OpenAPI 可选 `alibabacloud-bailian20231229==2.13.1` | | 飞书接入 | `lark-oapi==1.6.8` | | 登录态 / 加解密 | `PyJWT==2.13.0` + `cryptography==49.0.0` | | HTTP / 配置 | `requests==2.34.2`、`httpx==0.28.1`、`python-dotenv==1.2.2` | | WSGI | `gunicorn==26.0.0` | | Docker 基础镜像 | `python:3.12.13-slim-bookworm`、`postgres:18`、`nginx:stable-alpine` | Python 依赖基线: ```txt Django==5.2.15 djangorestframework==3.17.1 psycopg[binary] asgiref==3.11.1 sqlparse==0.5.5 tzdata==2026.2 python-dotenv==1.2.2 requests==2.34.2 httpx==0.28.1 APScheduler==3.11.2 django-apscheduler==0.7.0 dashscope==1.25.23 alibabacloud-bailian20231229==2.13.1 lark-oapi==1.6.8 PyJWT==2.13.0 cryptography==49.0.0 gunicorn==26.0.0 ``` ## 推荐 Django app | app | 职责 | | --- | --- | | `accounts` | 自定义用户、角色、登录态、飞书身份绑定 | | `people` | 人员映射、称呼匹配、第一批试用人员 | | `drafts` | `AiSecretaryAgent`、AI 草稿、补充/重说、BotContext、对话消息和草稿状态流转 | | `tasks` | 事项创建、程经理确认、事项状态流转 | | `reminders` | 定时提醒、固定周期、触发记录 | | `notifications` | 飞书通知、通知补发、通知状态 | | `feedbacks` | 飞书卡片反馈、平台内反馈 | | `feishu` | 飞书登录、机器人事件、卡片回调、验签 | | `prompts` | 背景摘要、老板风格提示词、业务规则版本 | | `audit` | 失败记录、操作日志、模型调用日志 | ## 分层约定 | 层 | 放什么 | 不放什么 | | --- | --- | --- | | `models` | 字段、索引、基础枚举、简单 model 方法 | 跨模块流程、外部 API 调用 | | `serializers` | 入参出参结构、字段级校验、展示转换 | 状态机、权限决策、飞书调用 | | `views` | DRF ViewSet/APIView、权限入口、调用 service | 复杂业务分支、事务主体 | | `services` | 业务流程、状态流转、事务、幂等、日志 | HTTP 请求细节 | | `clients` | 阿里百炼、飞书 API 等外部调用封装 | 业务状态修改 | | `tasks/commands` | scheduler、补发、批处理命令 | Web 请求上下文依赖 | ## 核心调用方向 ```text views -> serializers -> services -> models / clients -> audit logs / failure records ``` 允许: 1. `drafts` 通过 service 转换为 `tasks` 或 `reminders`。 2. `tasks` / `reminders` 通过 service 创建 `notifications`。 3. `notifications` 通过 `feishu` client 发送消息。 4. `feishu` 回调通过 service 更新 `drafts`、`feedbacks`、`tasks`、`reminders`。 5. 所有模块写入 `audit`。 6. `drafts` 中的 AI 对话记忆只辅助理解和草稿修订,不替代 `tasks`、`reminders`、`notifications` 等正式业务表。 避免: 1. app 之间直接互相改 model 状态。 2. 在 view 里直接调用飞书或模型 API。 3. 在 serializer 里做状态流转。 4. 在 scheduler 中绕过 service 直接改业务表。 ## 必须写日志的动作 1. 飞书登录成功或失败。 2. 机器人收到老板消息。 3. 非老板私聊机器人。 4. AI 生成草稿、解析失败。 5. 人工确认、修改、取消草稿。 6. 老板点击补充/重说。 7. 程经理确认复杂事项。 8. 创建事项、创建提醒。 9. 发送通知、补发通知、通知失败。 10. 接收反馈,尤其是“有问题”反馈。 11. 定时提醒触发成功或失败。 12. 失败记录处理。 13. 背景摘要或老板风格提示词版本启用。 ## 后台任务 定时提醒扫描使用独立进程,不放在 Gunicorn worker 内。生产和测试环境必须保证同一环境同一应用库同时只有一个 scheduler 进程在运行;如果未来多实例部署,需要先引入外部锁、leader election 或数据库级幂等锁。建议命令: ```bash python manage.py run_reminder_scheduler ``` 调度器每次触发前必须检查幂等键: ```text reminder_id + trigger_time + receiver_id + notification_channel ``` 同一个提醒、同一个触发时间、同一个接收人,只允许生成一条有效通知。