# 内容关系模型 **本文引用的文件** - [schema.prisma](file://server/prisma/schema.prisma) - [migration.sql](file://server/prisma/migrations/20260422105352_add_content_status/migration.sql) - [book-generator.types.ts](file://server/src/modules/book-generator/book-generator.types.ts) - [book-generator.service.ts](file://server/src/modules/book-generator/book-generator.service.ts) - [book-generator.store.ts](file://server/src/modules/book-generator/book-generator.store.ts) - [album-controller.ts](file://server/src/modules/book-generator/album-controller.ts) - [history.controller.ts](file://server/src/modules/history/history.controller.ts) - [comments.controller.ts](file://server/src/modules/comments/comments.controller.ts) - [favorites.controller.ts](file://server/src/modules/favorites/favorites.controller.ts) - [check-parentid.js](file://server/check-parentid.js) - [fix-null-parentid.js](file://server/fix-null-parentid.js) - [fix-book5-structure.js](file://server/fix-book5-structure.js) - [database-structure.md](file://docs/database-structure.md) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖分析](#依赖分析) 7. [性能考量](#性能考量) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 简介 本文件面向AI有声书生成平台,系统化阐述内容关系模型,重点覆盖: - 书籍与章节的父子关系设计(含级联删除与数据一致性) - 章节层级(parentId、level、number)如何构建树形结构及对导航与播放列表的影响 - 章节与播放记录、评论、收藏、播放列表项等关联表的关系映射 - 外键约束设计原则与索引策略 - 复杂查询场景示例与AI生成流程中的模型支撑 ## 项目结构 围绕内容关系模型的核心文件分布如下: - 数据库模型定义:Prisma Schema - 外键与索引:迁移SQL - 业务层:书籍生成编排、存储与控制器 - 关联模块:历史、评论、收藏、播放列表等 ```mermaid graph TB subgraph "数据层" SCHEMA["schema.prisma
模型与关系定义"] MIG["migration.sql
外键与索引"] end subgraph "业务层" TYPES["book-generator.types.ts
类型定义"] STORE["book-generator.store.ts
存储与查询"] SERVICE["book-generator.service.ts
编排与流程控制"] CTRL["album-controller.ts
专辑/章节API"] end subgraph "关联模块" HIS["history.controller.ts
历史记录"] COM["comments.controller.ts
评论"] FAV["favorites.controller.ts
收藏"] end SCHEMA --> MIG TYPES --> STORE STORE --> SERVICE SERVICE --> CTRL SCHEMA -. 关联 .-> HIS SCHEMA -. 关联 .-> COM SCHEMA -. 关联 .-> FAV ``` 图表来源 - [schema.prisma](file://server/prisma/schema.prisma) - [migration.sql](file://server/prisma/migrations/20260422105352_add_content_status/migration.sql) - [book-generator.types.ts](file://server/src/modules/book-generator/book-generator.types.ts) - [book-generator.store.ts](file://server/src/modules/book-generator/book-generator.store.ts) - [book-generator.service.ts](file://server/src/modules/book-generator/book-generator.service.ts) - [album-controller.ts](file://server/src/modules/book-generator/album-controller.ts) - [history.controller.ts](file://server/src/modules/history/history.controller.ts) - [comments.controller.ts](file://server/src/modules/comments/comments.controller.ts) - [favorites.controller.ts](file://server/src/modules/favorites/favorites.controller.ts) 章节来源 - [schema.prisma](file://server/prisma/schema.prisma) - [migration.sql](file://server/prisma/migrations/20260422105352_add_content_status/migration.sql) ## 核心组件 - 书籍(Book):顶层实体,承载书籍元信息与章节集合 - 章节(BookChapter):树形结构核心,通过parentId、level、number构成层级 - 关联表:播放记录(PlayRecord)、评论(Comment)、收藏(Favorite)、播放列表项(PlaylistItem) 关键点: - 章节树形结构由“bookId + parentId + level + number”唯一约束保障层级唯一性 - 章节与书籍之间存在级联删除,确保书籍删除时自动清理章节 - 章节与播放记录、评论、播放列表项之间建立一对一/一对多关系,支撑播放、互动与播放列表 章节来源 - [schema.prisma](file://server/prisma/schema.prisma) - [book-generator.types.ts](file://server/src/modules/book-generator/book-generator.types.ts) ## 架构总览 内容关系模型在AI生成流程中的作用: - 大纲生成:基于章节树形结构,逐层推进内容生成 - 内容创作:按章节层级生成正文,更新章节状态与媒体资源 - 音频/视频合成:按叶节点(level最大)生成媒体,再向上合并 - 导航与播放:树形结构驱动章节导航;播放列表基于章节或音频项 ```mermaid sequenceDiagram participant U as "用户" participant C as "专辑控制器(album-controller)" participant S as "编排服务(book-generator.service)" participant ST as "存储(book-generator.store)" participant DB as "数据库(schema.prisma)" U->>C : 请求生成书籍内容 C->>S : 触发批量生成编排 S->>ST : 获取章节树(getChapterTree) ST->>DB : 查询章节(level, number排序) DB-->>ST : 返回章节树 S->>ST : 生成叶节点内容(generate_content) ST->>DB : 更新章节(genStage/content) S->>ST : 生成叶节点音频(generate_audio) ST->>DB : 更新章节(audioUrl/duration) S->>ST : 合并父节点音频(merge_audio) ST->>DB : 更新父章节(audioUrl/duration) S-->>U : 推送进度/完成 ``` 图表来源 - [book-generator.service.ts](file://server/src/modules/book-generator/book-generator.service.ts) - [book-generator.store.ts](file://server/src/modules/book-generator/book-generator.store.ts) - [album-controller.ts](file://server/src/modules/book-generator/album-controller.ts) - [schema.prisma](file://server/prisma/schema.prisma) ## 详细组件分析 ### 书籍与章节的父子关系设计 - 章节树形结构 - level:层级,1=章,2=节,3=小节 - parentId:父节点ID,0表示章级根节点 - number:同级序号,用于排序 - 唯一约束:bookId + parentId + level + number,确保同一层级下序号唯一 - 级联删除 - 章节与书籍:onDelete: Cascade,删除书籍时自动删除章节 - 播放列表项与播放列表:onDelete: Cascade,删除播放列表时自动删除项 - 数据一致性 - 通过唯一约束与外键约束,保证章节树的完整性 - 通过事务操作(如发布/取消发布)保证状态变更原子性 ```mermaid erDiagram BOOK { int id PK int userId string title boolean isPublished string genStage } BOOKCHAPTER { int id PK int bookId FK int parentId int level int number string title string audioUrl int audioDuration string genStage } PLAYRECORD { int id PK int userId FK int chapterId FK float progress } COMMENT { int id PK int userId FK int chapterId FK string content } FAVORITE { int id PK int userId FK int bookId FK } PLAYLIST { int id PK int userId FK string name } PLAYLISTITEM { int id PK int playlistId FK int chapterId FK int order } BOOK ||--o{ BOOKCHAPTER : "包含" BOOKCHAPTER ||--o{ PLAYRECORD : "被播放" BOOKCHAPTER ||--o{ COMMENT : "被评论" BOOKCHAPTER ||--o{ PLAYLISTITEM : "作为项" PLAYLIST ||--o{ PLAYLISTITEM : "包含" USER ||--o{ PLAYRECORD : "产生记录" USER ||--o{ COMMENT : "发表" USER ||--o{ FAVORITE : "收藏" BOOK ||--o{ FAVORITE : "被收藏" ``` 图表来源 - [schema.prisma](file://server/prisma/schema.prisma) - [migration.sql](file://server/prisma/migrations/20260422105352_add_content_status/migration.sql) 章节来源 - [schema.prisma](file://server/prisma/schema.prisma) - [migration.sql](file://server/prisma/migrations/20260422105352_add_content_status/migration.sql) ### 章节层级与树形结构 - 层级关系 - level=1:章(parentId=0) - level=2:节(parentId指向章) - level=3:小节(parentId指向节) - 排序与导航 - 同级按number升序排列 - 前端按parentId分组构建树,支持章→节→小节三层导航 - 数据修复与校验 - 修复异常level=1记录与错误parentId - 统一parentId为0(章级)或具体父节点ID ```mermaid flowchart TD Start(["开始"]) --> LoadChapters["加载书籍章节
按 level+number 排序"] LoadChapters --> BuildMap["构建映射:level=1/2 映射表"] BuildMap --> LinkSections["连接节到章
parentId=章ID"] LinkSections --> LinkSubsections["连接小节到节
parentId=节ID"] LinkSubsections --> MergeAudio["按章聚合小节音频"] MergeAudio --> UpdateChapter["更新章音频URL与时长"] UpdateChapter --> End(["结束"]) ``` 图表来源 - [album-controller.ts](file://server/src/modules/book-generator/album-controller.ts) - [book-generator.store.ts](file://server/src/modules/book-generator/book-generator.store.ts) 章节来源 - [album-controller.ts](file://server/src/modules/book-generator/album-controller.ts) - [check-parentid.js](file://server/check-parentid.js) - [fix-null-parentid.js](file://server/fix-null-parentid.js) - [fix-book5-structure.js](file://server/fix-book5-structure.js) ### 与播放记录、评论、收藏、播放列表项的关系映射 - 播放记录(PlayRecord) - 关系:章节→播放记录(一对多) - 约束:onDelete: Restrict,防止误删播放记录 - 用途:记录用户对章节的播放进度与时长 - 评论(Comment) - 关系:章节→评论(一对多) - 约束:onDelete: Restrict - 用途:章节评论与评分 - 收藏(Favorite) - 关系:书籍→收藏(一对多) - 约束:onDelete: Cascade(删除书籍时级联删除收藏) - 用途:用户收藏书籍 - 播放列表项(PlaylistItem) - 关系:播放列表→播放列表项(一对多) - 约束:onDelete: Cascade(删除播放列表时级联删除项) - 约束:onDelete: Set Null(章节删除时将项的chapterId置空) 章节来源 - [schema.prisma](file://server/prisma/schema.prisma) - [migration.sql](file://server/prisma/migrations/20260422105352_add_content_status/migration.sql) ### 外键约束与更新行为 - onDelete行为 - 章节→书籍:Cascade(删除书籍删除章节) - 收藏→书籍:Cascade(删除书籍删除收藏) - 播放列表→播放列表项:Cascade(删除播放列表删除项) - 播放记录/评论:Restrict(禁止删除仍有记录的章节) - 播放列表项→章节:Set Null(章节删除不影响播放列表项,但断链) - onUpdate行为 - 多数关系采用RESTRICT,避免级联更新导致的意外数据漂移 - 个别关系采用CASCADE(如书籍与章节),确保主从一致 章节来源 - [migration.sql](file://server/prisma/migrations/20260422105352_add_content_status/migration.sql) - [schema.prisma](file://server/prisma/schema.prisma) ### 索引策略与查询优化 - 复合唯一约束 - 章节唯一约束:bookId + parentId + level + number,确保层级内序号唯一 - 常用索引 - 章节:bookId、bookId+parentId、bookId+level,支撑树形查询与层级筛选 - 播放记录:userId、chapterId,支撑用户播放历史与章节播放统计 - 收藏:userId、bookId,支撑用户收藏查询 - 播放列表项:playlistId+order,支撑播放列表顺序检索 - 查询优化建议 - 树形查询优先使用bookId+level+number排序 - 播放历史与统计查询结合chapterId与userId索引 - 批量操作使用事务,减少锁竞争 章节来源 - [schema.prisma](file://server/prisma/schema.prisma) - [migration.sql](file://server/prisma/migrations/20260422105352_add_content_status/migration.sql) ### 复杂查询场景示例 - 获取书籍完整大纲 - 依据bookId查询所有章节,按level与number排序,构建章→节→小节树 - 查询章节播放历史 - 以chapterId为条件,结合userId索引,查询PlayRecord列表 - 统计章节使用情况 - 按chapterId分组统计播放次数、平均时长与用户数 章节来源 - [book-generator.store.ts](file://server/src/modules/book-generator/book-generator.store.ts) - [album-controller.ts](file://server/src/modules/book-generator/album-controller.ts) - [schema.prisma](file://server/prisma/schema.prisma) ### 在AI生成流程中的作用 - 大纲生成:根据书籍规模与目标受众生成章节大纲,形成level=1的章 - 内容创作:逐层生成节与小节内容,更新genStage与content - 媒体合成:叶节点(level最大)生成音频/视频,再向上合并至父节点 - 导航与播放:树形结构支撑章节导航;播放列表基于章节或音频项 章节来源 - [book-generator.service.ts](file://server/src/modules/book-generator/book-generator.service.ts) - [book-generator.store.ts](file://server/src/modules/book-generator/book-generator.store.ts) - [database-structure.md](file://docs/database-structure.md) ## 依赖分析 - 组件耦合 - 控制器依赖存储层,存储层依赖Prisma客户端 - 编排服务协调存储与外部TTS/视频服务 - 外部依赖 - Prisma ORM负责模型映射与查询 - MySQL提供持久化存储与外键约束 - 循环依赖 - 无明显循环依赖,模块职责清晰 ```mermaid graph LR CTRL["album-controller.ts"] --> STORE["book-generator.store.ts"] STORE --> PRISMA["@prisma/client"] SERVICE["book-generator.service.ts"] --> STORE SERVICE --> PRISMA TYPES["book-generator.types.ts"] --> STORE TYPES --> SERVICE ``` 图表来源 - [album-controller.ts](file://server/src/modules/book-generator/album-controller.ts) - [book-generator.store.ts](file://server/src/modules/book-generator/book-generator.store.ts) - [book-generator.service.ts](file://server/src/modules/book-generator/book-generator.service.ts) - [book-generator.types.ts](file://server/src/modules/book-generator/book-generator.types.ts) ## 性能考量 - 查询性能 - 利用复合索引与唯一约束,降低重复与冲突 - 树形查询按level与number排序,避免全表扫描 - 写入性能 - 批量upsert减少重复创建与唯一冲突 - 事务包裹批量更新,提升一致性与吞吐 - 存储与归档 - 媒体资源URL化,减少文本字段膨胀 - 播放历史与统计可异步归档,减轻主表压力 ## 故障排查指南 - 章节层级异常 - 症状:level=1但number异常大、parentId为NULL或指向错误 - 处理:统一parentId为0或修正为正确父节点;删除无效记录 - 章节树不完整 - 症状:节/小节缺失或错位 - 处理:按bookId+level+number重建映射,核对parentId - 播放记录/评论丢失 - 症状:删除章节后播放记录/评论仍存在 - 处理:确认onDelete行为为Restrict,避免误删;必要时迁移数据 章节来源 - [check-parentid.js](file://server/check-parentid.js) - [fix-null-parentid.js](file://server/fix-null-parentid.js) - [fix-book5-structure.js](file://server/fix-book5-structure.js) ## 结论 本内容关系模型以“bookId + parentId + level + number”的唯一约束为核心,构建稳定可靠的树形结构,配合级联删除与外键约束,确保书籍与章节数据的一致性。通过合理的索引策略与查询优化,支撑复杂的导航与播放列表需求。在AI生成流程中,该模型为大纲生成、内容创作与媒体合成提供了坚实的数据基础。 ## 附录 - 相关文档与参考 - 数据库结构说明 - 书籍生成模块说明 章节来源 - [database-structure.md](file://docs/database-structure.md)