# 数据模型概览 **本文档引用的文件** - [schema.prisma](file://server/prisma/schema.prisma) - [index.ts](file://server/src/models/index.ts) - [migrate-genstage.ts](file://server/prisma/migrate-genstage.ts) - [sync-genstage.ts](file://server/prisma/sync-genstage.ts) - [book-generator.types.ts](file://server/src/modules/book-generator/book-generator.types.ts) - [stage-manager.ts](file://server/src/modules/book-generator/stage-manager.ts) - [auth.service.ts](file://server/src/modules/auth/auth.service.ts) - [tts.service.ts](file://server/src/modules/tts/tts.service.ts) - [member.service.ts](file://server/src/modules/member/member.service.ts) - [book-generator.service.ts](file://server/src/modules/book-generator/book-generator.service.ts) - [seed-test-user.js](file://server/prisma/seed-test-user.js) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖分析](#依赖分析) 7. [性能考虑](#性能考虑) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 简介 本文件面向AI有声书生成平台,系统性梳理Prisma ORM在该项目中的整体架构设计与数据模型组织方式。重点覆盖以下方面: - 数据模型的组织方式与关系映射策略 - 关键实体(用户、书籍、章节等)的职责划分 - 版本管理机制、迁移策略与向后兼容性保障 - 使用Prisma客户端进行数据操作的最佳实践与示例路径 ## 项目结构 本项目的数据层采用Prisma Schema集中定义,配合模块化的业务服务层进行读写操作。核心文件分布如下: - Prisma Schema:定义数据模型、关系、索引与约束 - Prisma 客户端封装:统一初始化与连接管理 - 迁移与同步脚本:历史数据迁移与状态同步 - 业务服务:围绕模型进行CRUD与复杂事务处理 ```mermaid graph TB subgraph "数据层" PRISMA["Prisma Schema
server/prisma/schema.prisma"] MIGRATE["迁移脚本
server/prisma/migrate-genstage.ts"] SYNC["同步脚本
server/prisma/sync-genstage.ts"] end subgraph "应用层" MODELS["Prisma 客户端封装
server/src/models/index.ts"] AUTH["认证服务
server/src/modules/auth/auth.service.ts"] TTS["TTS服务
server/src/modules/tts/tts.service.ts"] MEMBER["会员服务
server/src/modules/member/member.service.ts"] GEN["书籍生成服务
server/src/modules/book-generator/book-generator.service.ts"] STAGE["阶段管理器
server/src/modules/book-generator/stage-manager.ts"] end PRISMA --> MODELS MIGRATE --> PRISMA SYNC --> PRISMA MODELS --> AUTH MODELS --> TTS MODELS --> MEMBER MODELS --> GEN GEN --> STAGE ``` **图表来源** - [schema.prisma](file://server/prisma/schema.prisma) - [index.ts](file://server/src/models/index.ts) - [migrate-genstage.ts](file://server/prisma/migrate-genstage.ts) - [sync-genstage.ts](file://server/prisma/sync-genstage.ts) - [auth.service.ts](file://server/src/modules/auth/auth.service.ts) - [tts.service.ts](file://server/src/modules/tts/tts.service.ts) - [member.service.ts](file://server/src/modules/member/member.service.ts) - [book-generator.service.ts](file://server/src/modules/book-generator/book-generator.service.ts) - [stage-manager.ts](file://server/src/modules/book-generator/stage-manager.ts) **章节来源** - [schema.prisma](file://server/prisma/schema.prisma) - [index.ts](file://server/src/models/index.ts) ## 核心组件 本节从数据模型视角,介绍关键实体及其职责边界,并说明Prisma的关系映射与约束策略。 - 用户(User) - 职责:平台用户主体,承载会员等级、用量统计、偏好设置等 - 关系:一对多关联评论、草稿、收藏、订单、播放记录、歌单、签到、订阅、令牌余额与使用记录、偏好设置 - 约束:手机号与微信OpenID唯一索引;自动维护创建/更新时间 - 书籍(Book) - 职责:书籍主表,记录生成进度、状态、大纲与元数据 - 关系:一对多章节;可选归属用户;一对多视频项目 - 约束:复合索引覆盖用户+状态、创建时间 - 章节(BookChapter) - 职责:章节树形结构(支持章/节/小节),记录内容、音频、视频、歌词与生成阶段 - 关系:多对一所属书籍;一对多评论、播放记录、歌单项、视频项目 - 约束:唯一索引确保同一层级内章节编号唯一;多维索引覆盖书籍、父子关系与层级 - 生成阶段(genStage)与状态(status) - 设计理念:引入线性阶段字段统一管理生成流程,避免历史遗留的多字段状态分散 - 书籍与章节分别定义阶段枚举,通过阶段管理器进行安全转移与资源清理 - 订单(Order)与订阅(Subscription/Plan) - 职责:会员体系与消费闭环,包含套餐配置、购买记录与订阅生命周期 - 关系:多对一用户与套餐;多对一书籍与章节(用于生成配额与令牌) - 其他重要实体 - TokenBalance/TokenUsage:令牌余额与使用流水 - PlayRecord/Playlist/PlaylistItem:播放记录与歌单 - AudioRecord:音频生成记录(与书籍章节解耦) - Draft/Comment/Feedback/VideoProject/Search/HotSearch:支撑创作、互动与检索生态 **章节来源** - [schema.prisma](file://server/prisma/schema.prisma) - [book-generator.types.ts](file://server/src/modules/book-generator/book-generator.types.ts) - [stage-manager.ts](file://server/src/modules/book-generator/stage-manager.ts) ## 架构总览 下图展示Prisma数据模型在系统中的交互关系与典型调用链: ```mermaid erDiagram USER { int id PK string phone UK string openid UK string nickname string avatar int memberLevel datetime memberExpireAt int dailyUsage string lastUsageDate datetime createdAt datetime updatedAt } ORDER { int id PK int userId FK string orderNo UK int planId FK string productType decimal amount string status string paymentMethod string paymentId datetime paidAt datetime createdAt datetime updatedAt } SUBSCRIPTION_PLAN { int id PK string name int level decimal priceMonthly decimal priceYearly string description string features boolean isRecommended boolean isActive int sortOrder int dailyGenerations int perGenerationLimit int monthlyTokens int monthlyMinutes int yearlyTokens int voiceOptions string audioQuality boolean apiAccess boolean batchProcessing boolean teamManagement boolean overageEnabled decimal overagePrice datetime createdAt datetime updatedAt } SUBSCRIPTION { int id PK int userId FK int planId FK datetime startDate datetime endDate string status boolean autoRenew datetime createdAt datetime updatedAt } BOOK { int id PK int userId FK string title string subtitle text description string coverUrl string targetAudience string style string bookScale int totalChapters int estimatedWords int progress boolean isPublished longtext outlineJson text foreword text afterword text errorMsg datetime createdAt datetime updatedAt varchar failedStage string genStage string status text bookAnalysis } BOOK_CHAPTER { int id PK int bookId FK int parentId int level int number string title text summary text keyPoints int estimatedWords longtext content int wordCount text contentError datetime generatedAt text audioUrl int audioDuration text videoUrl int videoDuration boolean isPublic string genStage string status text lrcLyrics } PLAYLIST { int id PK int userId FK string name text description datetime createdAt datetime updatedAt } PLAYLIST_ITEM { int id PK int playlistId FK int chapterId FK string audioId int order } PLAY_RECORD { int id PK int userId FK int chapterId FK float progress float duration datetime createdAt datetime updatedAt } AUDIO_RECORD { int id PK int userId FK string audioId UK string title longtext text int wordCount string voiceId string voiceParams text audioUrl int audioDuration int audioSize string status text errorMsg datetime createdAt datetime updatedAt } COMMENT { int id PK int userId FK int chapterId FK text content int rating datetime createdAt } DRAFT { int id PK int userId FK string type text title longtext content text metadata datetime autoSavedAt datetime createdAt datetime updatedAt } TOKEN_BALANCE { int id PK int userId UK int totalTokens int usedTokens datetime resetDate datetime createdAt datetime updatedAt } TOKEN_USAGE { int id PK int userId FK string type int amount int contentLength int orderId FK text description datetime createdAt } USER_PREFERENCE { int id PK int userId UK float playSpeed string quality string theme string defaultVoiceId int defaultVolume boolean autoPlayNext boolean wifiOnlyDownload datetime createdAt datetime updatedAt } VIDEO_PROJECT { int id PK int userId FK string title text description string coverUrl longtext configJson string outputUrl int duration int fileSize int bookId FK int chapterId FK string status int progress text errorMsg datetime createdAt datetime updatedAt } USER ||--o{ ORDER : "拥有" SUBSCRIPTION_PLAN ||--o{ SUBSCRIPTION : "被订阅" USER ||--o{ SUBSCRIPTION : "订阅" USER ||--o{ BOOK : "创作" BOOK ||--o{ BOOK_CHAPTER : "包含" USER ||--o{ COMMENT : "发表" BOOK_CHAPTER ||--o{ COMMENT : "被评论" USER ||--o{ PLAYLIST : "创建" PLAYLIST ||--o{ PLAYLIST_ITEM : "包含" USER ||--o{ PLAY_RECORD : "播放" BOOK_CHAPTER ||--o{ PLAY_RECORD : "被播放" USER ||--o{ AUDIO_RECORD : "生成" BOOK ||--o{ VIDEO_PROJECT : "驱动" BOOK_CHAPTER ||--o{ VIDEO_PROJECT : "驱动" USER ||--o{ DRAFT : "保存" USER ||--o{ TOKEN_BALANCE : "持有" USER ||--o{ TOKEN_USAGE : "产生" ORDER ||--o{ TOKEN_USAGE : "关联" USER ||--o{ USER_PREFERENCE : "偏好" ``` **图表来源** - [schema.prisma](file://server/prisma/schema.prisma) ## 详细组件分析 ### 用户模型(User)与相关实体 - 职责与边界 - 用户主体,承载会员等级、每日用量、偏好设置与播放记录 - 与订单、订阅、令牌、播放记录、收藏、草稿、评论、歌单等形成强关联 - 关系映射 - 一对一:偏好设置、令牌余额 - 一对多:订单、订阅、播放记录、收藏、草稿、评论、歌单、签到记录 - 约束与索引 - 手机号与OpenID唯一性;常用查询维度建立索引(如用户+创建时间) **章节来源** - [schema.prisma](file://server/prisma/schema.prisma) - [auth.service.ts](file://server/src/modules/auth/auth.service.ts) - [member.service.ts](file://server/src/modules/member/member.service.ts) ### 书籍模型(Book)与章节模型(BookChapter) - 职责与边界 - 书籍:顶层容器,记录生成进度、状态、大纲与元数据 - 章节:树形结构,承载内容、音频、视频、歌词与生成阶段 - 关系映射 - 书籍与章节:一对多,章节通过bookId关联;章节支持父子关系与层级 - 章节与播放记录、评论、歌单项、视频项目形成多对多间接关联 - 约束与索引 - 章节唯一索引:同一层级下number唯一;多维索引覆盖书籍、父子关系与层级 - 生成阶段(genStage)与状态(status) - 通过阶段管理器进行安全转移,支持前进与回退,自动清理下游资源 - 书籍与章节分别定义阶段枚举,确保线性演进与一致性 ```mermaid classDiagram class Book { +int id +int userId +string title +string status +string genStage +int progress +longtext outlineJson +text foreword +text afterword +datetime createdAt +datetime updatedAt } class BookChapter { +int id +int bookId +int parentId +int level +int number +string title +string status +string genStage +text content +text audioUrl +text videoUrl +text lrcLyrics +datetime createdAt +datetime updatedAt } Book "1" --> "0..*" BookChapter : "包含" ``` **图表来源** - [schema.prisma](file://server/prisma/schema.prisma) - [stage-manager.ts](file://server/src/modules/book-generator/stage-manager.ts) **章节来源** - [schema.prisma](file://server/prisma/schema.prisma) - [stage-manager.ts](file://server/src/modules/book-generator/stage-manager.ts) - [book-generator.types.ts](file://server/src/modules/book-generator/book-generator.types.ts) ### 生成阶段与状态同步 - 阶段定义 - 书籍与章节分别定义阶段枚举,涵盖大纲、内容、音频、视频等阶段 - 安全转移 - 通过转移矩阵与乐观锁,确保并发安全;回退时自动清理下游资源 - 历史数据迁移 - 旧字段(status/contentStatus/audioStatus/videoStatus)迁移至genStage - 同步脚本基于阶段索引进行安全推进或回退 ```mermaid flowchart TD Start(["开始同步"]) --> LoadChapters["加载章节/书籍"] LoadChapters --> InferTarget["根据旧字段推导目标阶段"] InferTarget --> Compare["比较当前阶段与目标阶段"] Compare --> |相同| Skip["无需更新"] Compare --> |目标更大| Advance["前进:safeTransition"] Compare --> |目标更小| Regenerate["回退:safeTransition并清理资源"] Advance --> Update["更新genStage并清理下游资源"] Regenerate --> Update Update --> Done(["完成"]) Skip --> Done ``` **图表来源** - [migrate-genstage.ts](file://server/prisma/migrate-genstage.ts) - [sync-genstage.ts](file://server/prisma/sync-genstage.ts) - [stage-manager.ts](file://server/src/modules/book-generator/stage-manager.ts) **章节来源** - [migrate-genstage.ts](file://server/prisma/migrate-genstage.ts) - [sync-genstage.ts](file://server/prisma/sync-genstage.ts) - [stage-manager.ts](file://server/src/modules/book-generator/stage-manager.ts) ### 令牌与消费模型(TokenBalance/TokenUsage/Order/Subscription) - 令牌余额与使用 - 令牌余额按用户唯一,记录总量、已用与重置时间 - 令牌使用记录按用户+时间维度索引,便于审计与配额控制 - 订单与订阅 - 套餐计划定义生成配额、音色与质量等权益 - 订阅记录生命周期与自动续费策略 - 业务联动 - 生成服务在创建音频记录时更新令牌使用与余额 - 会员服务在支付成功后更新用户会员等级与有效期 **章节来源** - [schema.prisma](file://server/prisma/schema.prisma) - [tts.service.ts](file://server/src/modules/tts/tts.service.ts) - [member.service.ts](file://server/src/modules/member/member.service.ts) ### Prisma 客户端初始化与连接 - 初始化位置 - 在应用启动时创建PrismaClient实例并建立连接 - 连接管理 - 提供连接状态检查与错误处理,确保数据库可用性 **章节来源** - [index.ts](file://server/src/models/index.ts) ## 依赖分析 - 模块耦合 - 业务服务通过统一的Prisma客户端访问数据,降低耦合度 - 阶段管理器独立于具体业务,仅依赖Prisma进行状态更新 - 外部依赖 - 数据库:MySQL(通过Prisma适配) - 第三方服务:TTS提供商、对象存储等(通过服务层抽象) - 循环依赖 - 通过模块拆分与延迟导入避免循环依赖 ```mermaid graph LR MODELS["models/index.ts"] --> AUTH["auth.service.ts"] MODELS --> TTS["tts.service.ts"] MODELS --> MEMBER["member.service.ts"] MODELS --> GEN["book-generator.service.ts"] GEN --> STAGE["stage-manager.ts"] PRISMA["schema.prisma"] --> MODELS ``` **图表来源** - [index.ts](file://server/src/models/index.ts) - [auth.service.ts](file://server/src/modules/auth/auth.service.ts) - [tts.service.ts](file://server/src/modules/tts/tts.service.ts) - [member.service.ts](file://server/src/modules/member/member.service.ts) - [book-generator.service.ts](file://server/src/modules/book-generator/book-generator.service.ts) - [stage-manager.ts](file://server/src/modules/book-generator/stage-manager.ts) - [schema.prisma](file://server/prisma/schema.prisma) **章节来源** - [index.ts](file://server/src/models/index.ts) - [book-generator.service.ts](file://server/src/modules/book-generator/book-generator.service.ts) - [stage-manager.ts](file://server/src/modules/book-generator/stage-manager.ts) ## 性能考虑 - 索引策略 - 为高频查询字段建立复合索引(如用户+状态、书籍+层级、创建时间等) - 查询优化 - 使用select精确投影字段,避免不必要的字段加载 - 对批量操作使用事务与批量写入减少往返 - 并发控制 - 阶段转移采用乐观锁,避免并发冲突导致的数据不一致 - 缓存与队列 - 对热点数据(如用户配额、令牌余额)结合内存缓存与队列处理 ## 故障排查指南 - 连接失败 - 检查DATABASE_URL环境变量与数据库连通性 - 查看Prisma客户端连接日志定位问题 - 状态迁移异常 - 核对阶段转移矩阵与目标阶段合法性 - 检查乐观锁条件是否满足,必要时重试 - 历史数据迁移 - 使用迁移脚本将旧字段映射到genStage - 使用同步脚本进行幂等推进与回退校验 - 令牌与配额 - 核对用户会员等级与配额配置 - 检查令牌使用记录与余额更新是否一致 **章节来源** - [index.ts](file://server/src/models/index.ts) - [migrate-genstage.ts](file://server/prisma/migrate-genstage.ts) - [sync-genstage.ts](file://server/prisma/sync-genstage.ts) - [stage-manager.ts](file://server/src/modules/book-generator/stage-manager.ts) ## 结论 本项目通过Prisma Schema集中定义数据模型,结合模块化的业务服务与严格的阶段管理机制,实现了有声书生成平台的数据一致性与可扩展性。通过迁移与同步脚本,历史数据得以平滑过渡到新的线性阶段模型;通过统一的Prisma客户端封装,降低了模块间的耦合度。建议在后续迭代中持续完善索引策略、监控与告警体系,并保持阶段模型与业务流程的同步演进。 ## 附录 ### 使用示例与最佳实践 - 初始化与连接 - 在应用启动时调用连接函数,确保数据库可用 - 示例路径:[连接函数](file://server/src/models/index.ts) - 用户登录与信息获取 - 登录/注册:查找或创建用户并生成JWT - 获取用户信息:按ID查询用户详情 - 示例路径:[登录与查询](file://server/src/modules/auth/auth.service.ts) - 书籍与章节操作 - 创建默认书籍:若不存在则创建“我的音频”默认书籍 - 更新章节音频:保存音频URL、时长与歌词 - 示例路径:[默认书籍与章节更新](file://server/src/modules/tts/tts.service.ts) - 生成阶段推进 - 前进:推进到下一阶段(仅允许前进) - 回退:清理下游资源并回退到上游阶段 - 示例路径:[阶段推进与回退](file://server/src/modules/book-generator/stage-manager.ts) - 会员与订单 - 创建订单:生成唯一订单号并写入订单记录 - 支付成功:更新订单状态并提升用户会员等级 - 示例路径:[订单与会员](file://server/src/modules/member/member.service.ts) - 测试用户创建 - 脚本化创建测试用户并升级为超级VIP - 示例路径:[测试用户脚本](file://server/prisma/seed-test-user.js)