# 内容关系模型
**本文引用的文件**
- [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)