# 架构决策记录 (ADR): 数据库 Schema 设计方案 v1.0 **状态**: 已实施 (IMPLEMENTED) **日期**: 2025-12-23 **作者**: 首席系统架构师 **背景**: Next_Edu 平台 - K12 智慧教育管理系统 --- ## 1. 概述 (Overview) 本文档详细记录了 Next_Edu 平台的数据库 Schema 架构设计。本设计优先考虑 **可扩展性 (Scalability)**、**灵活性 (Flexibility)**(针对复杂的嵌套内容)以及 **严格的类型安全 (Strict Type Safety)**,并完全符合 PRD 中规定的领域驱动设计 (DDD) 原则。 ## 2. 技术栈决策 (Technology Stack Decisions) | 组件 | 选择 | 理由 | | :--- | :--- | :--- | | **数据库** | MySQL 8.0+ | 强大的关系型支持,完善的 JSON 能力,行业标准。 | | **ORM** | Drizzle ORM | 轻量级,零运行时开销 (Zero-runtime overhead),业界一流的 TypeScript 类型推断。 | | **ID 策略** | CUID2 | 分布式友好 (k-sortable),安全(防连续猜测攻击),比 UUID 更短。 | | **认证方案** | Auth.js v5 | 标准化的 OAuth 流程,支持自定义数据库适配器。 | --- ## 3. 核心 Schema 领域模型 (Core Schema Domains) 物理文件位于 `src/shared/db/schema.ts`,逻辑上分为三大领域。 ### 3.1 身份与访问管理 (IAM) 我们采用了 **Auth.js 标准表** 与 **自定义 RBAC** 相结合的混合模式。 * **标准表**: `users`, `accounts` (OAuth), `sessions`, `verificationTokens`。 * **RBAC 扩展**: * `roles`: 定义系统角色(例如:`grade_head` 年级主任, `teacher` 老师)。 * `users_to_roles`: 多对多关联表。 * **设计目标**: 解决“一人多职”问题(例如:一个老师同时也是年级主任),避免在 `users` 表中堆砌字段。 ### 3.2 智能题库中心 (Intelligent Question Bank) - 核心 这是最复杂的领域,需要支持无限层级嵌套和富文本内容。 #### 实体定义: 1. **`questions` (题目表)**: * `id`: CUID2。 * `content`: **JSON 类型**。存储结构化内容(如 SlateJS 节点),支持富文本、图片和公式混排。 * `parentId`: **自引用 (Self-Reference)**。 * *若为 NULL*: 独立题目 或 “大题干” (Parent)。 * *若有值*: 子题目 (Child)(例如:一篇阅读理解下的第1小题)。 * `type`: 枚举 (`single_choice`, `text`, `composite` 等)。 2. **`knowledge_points` (知识点表)**: * 通过 `parentId` 实现树状结构。 * 支持无限层级 (学科 -> 章 -> 节 -> 知识点)。 3. **`questions_to_knowledge_points`**: * 多对多关联。一道题可考察多个知识点;一个知识点可关联数千道题。 ### 3.3 教务教学流 (Academic Teaching Flow) 将物理世界的教学过程映射为数字实体。 * **`textbooks` & `chapters`**: 标准的教材大纲映射。`chapters` 同样支持通过 `parentId` 进行嵌套。 * **`exams`**: 考试/作业的聚合实体。 * **`exam_submissions`**: 代表一名学生的单次答题记录。 * **`submission_answers`**: 细粒度的答题详情,记录每道题的答案,支持自动评分 (`score`) 和人工反馈 (`feedback`)。 --- ## 4. 关键设计模式 (Key Design Patterns) ### 4.1 无限嵌套 ("Composite" Pattern) 我们没有为“题干”和“题目”创建单独的表,而是在 `questions` 表上使用 **自引用 (Self-Referencing)** 模式。 * **优点**: * 统一的查询接口 (`db.query.questions.findFirst({ with: { children: true } })`)。 * 递归逻辑可统一应用。 * 当内容结构变化时,迁移更简单。 * **缺点**: * 需要处理递归查询逻辑(已通过 Drizzle Relations 解决)。 ### 4.2 CUID2 优于 自增 ID * **安全性**: 防止 ID 枚举攻击(猜测下一个用户 ID)。 * **分布式**: 支持在客户端或多服务器节点生成,无碰撞风险。 * **性能**: `k-sortable` 特性保证了比随机 UUID v4 更好的索引局部性。 ### 4.3 JSON 存储内容 * 教育内容不仅仅是“文本”。它包含格式、LaTeX 公式和图片引用。 * 使用 `JSON` 存储允许前端 (Next.js) 直接渲染富组件,无需解析复杂的 HTML 字符串。 --- ## 5. 安全与索引策略 (Security & Indexing Strategy) ### 索引 (Indexes) * **外键**: 所有外键列 (`author_id`, `parent_id` 等) 均显式建立索引。 * **性能**: * `parent_id_idx`: 对树形结构的遍历性能至关重要。 * `email_idx`: 登录查询的核心索引。 ### 类型安全 (Type Safety) * 严格的 TypeScript 定义直接从 `src/shared/db/schema.ts` 导出。 * Zod Schema (待生成) 将与这些 Drizzle 定义保持 1:1 对齐。 --- ## 6. 目录结构 (Directory Structure) ```bash src/shared/db/ ├── index.ts # 单例数据库连接池 ├── schema.ts # 物理表结构定义 └── relations.ts # 逻辑 Drizzle 关系定义 ```