数据库设计.md 19 KB

数据库设计

本文引用的文件

  • database-structure.md
  • schema.prisma
  • index.ts
  • index.ts
  • models.json
  • tts.service.ts
  • tts.controller.ts
  • member.service.ts
  • member.controller.ts
  • auth.service.ts
  • index.ts
  • migration.sql
  • 支付集成指南.md

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖分析
  7. 性能考虑
  8. 故障排查指南
  9. 结论
  10. 附录

简介

本设计文档面向AI有声书生成平台,聚焦MySQL数据库(Prisma ORM)的数据模型与索引设计,覆盖用户、音频、TTS记录、会员与订阅等核心实体。文档同时给出实体关系映射、查询优化策略、生命周期管理、迁移与版本演进建议,并补充数据安全、备份恢复与性能监控的实施要点。

项目结构

  • 数据库层采用Prisma ORM,模型定义集中在schema.prisma,配合迁移脚本管理版本演进。
  • 应用层通过tts.service.ts与member.service.ts等模块读写数据库,控制器负责参数校验与业务编排。
  • 配置层在index.ts中集中管理数据库连接、JWT、模型供应商与TTS参数等。

    graph TB
    subgraph "应用层"
    C1["tts.controller.ts"]
    S1["tts.service.ts"]
    S2["member.service.ts"]
    A1["auth.service.ts"]
    end
    subgraph "数据访问层"
    M1["models/index.ts<br/>PrismaClient"]
    end
    subgraph "数据库层"
    P1["schema.prisma<br/>MySQL"]
    end
    C1 --> S1
    C1 --> S2
    A1 --> M1
    S1 --> M1
    S2 --> M1
    M1 --> P1
    

图表来源

  • index.ts:1-15
  • schema.prisma:1-472
  • tts.controller.ts:1-274
  • tts.service.ts:1-715
  • member.service.ts:1-183
  • auth.service.ts:1-115

章节来源

  • index.ts:1-15
  • schema.prisma:1-472

核心组件

本节对关键数据模型进行逐项说明,包括字段含义、取值范围、约束与典型查询。

  • 用户(User)

    • 关键字段:id、phone、openid、nickname、avatar、memberLevel、memberExpireAt、dailyUsage、lastUsageDate、usedAudioMinutes、subscriptionResetDate、createdAt、updatedAt。
    • 约束与索引:phone与openid唯一;额外索引用于登录与偏好查询。
    • 典型用途:会员等级与配额控制、每日用量重置、订阅周期计算。
  • 订单(Order)

    • 关键字段:id、userId、orderNo、planId、productType、amount、status、paymentMethod、paidAt、createdAt、updatedAt。
    • 约束与索引:orderNo唯一;按用户+创建时间、状态、planId建立索引。
    • 典型用途:订阅购买流水、支付状态追踪。
  • 订阅(Subscription)与套餐(SubscriptionPlan)

    • 关键字段:Subscription包含userId、planId、startDate、endDate、status、autoRenew;SubscriptionPlan包含level、priceMonthly、priceYearly、dailyGenerations、perGenerationLimit、monthlyTokens、monthlyMinutes、features等。
    • 约束与索引:按用户+状态、用户+到期日建立索引;planId外键。
    • 典型用途:会员权益与有效期管理、自动续费与到期提醒。
  • 音频记录(AudioRecord)

    • 关键字段:id、userId、audioId(唯一)、title、text、wordCount、voiceId、voiceParams、audioUrl、audioDuration、audioSize、status、errorMsg、bookId。
    • 约束与索引:audioId唯一;按userId、audioId、bookId建立索引。
    • 典型用途:异步TTS生成状态跟踪、LRC歌词时间轴、章节绑定。
  • 书籍(Book)与章节(BookChapter)

    • 关键字段:Book包含title、subtitle、description、targetAudience、style、bookScale、totalChapters、estimatedWords、progress、isPublished、outlineJson、foreword、afterword、status、genStage、failedStage等;BookChapter包含title、summary、keyPoints、estimatedWords、content、wordCount、audioUrl、audioDuration、videoUrl、videoDuration、isPublic、genStage、lrcLyrics、status等。
    • 约束与索引:章节唯一组合索引(bookId,parentId,level,number);章节按bookId建立索引。
    • 典型用途:有声书生成流程、章节内容与音频绑定、歌词生成。
  • 播放记录(PlayRecord)、收藏(Favorite)、评论(Comment)、播放列表(Playlist/PlaylistItem)、草稿(Draft)、Token余额(TokenBalance)/使用(TokenUsage)、发布任务(PublishTask)、平台账号(PlatformAccount)等。

章节来源

  • schema.prisma:10-393
  • index.ts:1-124

架构总览

下图展示数据库层的核心实体与关系,突出“书籍体系”与“学习路径体系”的并行结构,以及TTS生成链路中的关键关联。

erDiagram
USER ||--o{ ORDER : "拥有"
USER ||--o{ SUBSCRIPTION : "拥有"
USER ||--o{ AUDIO_RECORD : "生成"
USER ||--o{ PLAY_RECORD : "播放"
USER ||--o{ FAVORITE : "收藏"
USER ||--o{ COMMENT : "评论"
USER ||--o{ DRAFT : "草稿"
BOOK ||--o{ BOOK_CHAPTER : "包含"
BOOK_CHAPTER ||--o{ PLAY_RECORD : "被播放"
BOOK_CHAPTER ||--o{ COMMENT : "被评论"
BOOK_CHAPTER ||--o{ VIDEO_PROJECT : "生成视频"
AUDIO_RECORD }o--|| BOOK : "可选绑定"
BOOK_CHAPTER }o--|| AUDIO_RECORD : "章节音频"
PLAYLIST }o--o{ PLAYLIST_ITEM : "包含"
PLAYLIST_ITEM }o--|| BOOK_CHAPTER : "章节项"
PLAYLIST_ITEM }o--|| AUDIO_RECORD : "音频项"
SUBSCRIPTION }o--|| SUBSCRIPTION_PLAN : "订阅"
ORDER }o--|| SUBSCRIPTION_PLAN : "购买"
ORDER }o--|| USER : "由用户创建"
TOKEN_USAGE }o--|| USER : "记录"
TOKEN_BALANCE }o--|| USER : "对应"

图表来源

  • schema.prisma:10-393

章节来源

  • schema.prisma:10-393

详细组件分析

用户与会员模型

  • 用户(User):承载手机号/开放平台标识、昵称头像、会员等级与到期时间、每日用量与重置日期、累计音频时长与订阅重置日期等。
  • 会员权益:通过member.service.ts维护不同等级的配额与特性,结合Subscription与SubscriptionPlan实现有效期与自动续费。
  • 订单(Order):记录购买行为,支持月卡/年卡两种产品类型,状态涵盖pending/paid/failed/refunded。

    classDiagram
    class User {
    +int id
    +string phone
    +string openid
    +string nickname
    +string avatar
    +int memberLevel
    +datetime memberExpireAt
    +int dailyUsage
    +string lastUsageDate
    +int usedAudioMinutes
    +datetime subscriptionResetDate
    }
    class SubscriptionPlan {
    +int id
    +string name
    +int level
    +decimal priceMonthly
    +decimal priceYearly
    +int dailyGenerations
    +int perGenerationLimit
    +int monthlyTokens
    +int monthlyMinutes
    +string features
    }
    class Subscription {
    +int id
    +int userId
    +int planId
    +datetime startDate
    +datetime endDate
    +string status
    +bool autoRenew
    }
    class Order {
    +int id
    +int userId
    +string orderNo
    +int planId
    +string productType
    +decimal amount
    +string status
    +datetime paidAt
    }
    User ||--o{ Subscription : "拥有"
    SubscriptionPlan ||--o{ Subscription : "被订阅"
    SubscriptionPlan ||--o{ Order : "被购买"
    User ||--o{ Order : "创建"
    

图表来源

  • schema.prisma:10-302
  • member.service.ts:1-183

章节来源

  • schema.prisma:10-302
  • member.service.ts:1-183

音频与TTS记录模型

  • 音频记录(AudioRecord):记录单次TTS生成的输入文本、音色参数、输出URL、时长、大小、状态与错误信息,并可选绑定到书籍。
  • TTS服务链路:tts.controller.ts接收请求,调用tts.service.ts执行文本分段、并发合成、合并与上传、AI标题摘要标签生成、LRC歌词生成、章节与记录更新、WebSocket通知等。

    sequenceDiagram
    participant Client as "客户端"
    participant Ctrl as "tts.controller.ts"
    participant Svc as "tts.service.ts"
    participant DB as "Prisma(schema.prisma)"
    participant Storage as "存储服务"
    Client->>Ctrl : POST /tts/generate
    Ctrl->>Svc : generateAudio(userId,text,voiceId,voiceParams,options)
    Svc->>DB : 创建AudioRecord(processing)
    Svc->>Svc : 文本分段/并发合成/合并
    Svc->>Storage : 上传音频
    Storage-->>Svc : 返回URL
    Svc->>DB : 更新AudioRecord(completed)
    Svc->>DB : 更新BookChapter(可选)
    Svc-->>Ctrl : 返回{audioId,audioUrl,bookId}
    Ctrl-->>Client : 任务已创建
    

图表来源

  • tts.controller.ts:52-127
  • tts.service.ts:200-542
  • schema.prisma:354-375

章节来源

  • tts.controller.ts:52-127
  • tts.service.ts:200-542
  • schema.prisma:354-375

书籍与章节模型

  • 书籍(Book):标题、副标题、描述、封面、受众、风格、体量、总章节数、预估字数、进度、发布状态、大纲JSON、前后言、错误信息、状态与生成阶段等。
  • 章节(BookChapter):章节编号、标题、摘要、小节(keyPoints)、预估/实际字数、正文、生成时间、音频URL与时长、视频URL与时长、公开状态、歌词、状态与生成阶段等。
  • 三级目录:Book → BookChapter(章)→ keyPoints(小节,JSON数组)。

    erDiagram
    BOOK {
    int id PK
    int userId
    string title
    string subtitle
    text description
    string targetAudience
    string style
    string bookScale
    int totalChapters
    int estimatedWords
    int progress
    bool isPublished
    longtext outlineJson
    text foreword
    text afterword
    string status
    string genStage
    string failedStage
    }
    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
    string contentError
    datetime generatedAt
    text audioUrl
    int audioDuration
    text videoUrl
    int videoDuration
    bool isPublic
    string genStage
    text lrcLyrics
    string status
    }
    BOOK ||--o{ BOOK_CHAPTER : "包含"
    

图表来源

  • schema.prisma:130-194

章节来源

  • schema.prisma:130-194

订阅与支付模型

  • 订阅计划(SubscriptionPlan):包含月/年价格、日生成次数、单次字数上限、月/年Token配额、音色数、音质、API权限、批量处理、团队管理、超量计费等。
  • 订阅(Subscription):记录用户生效的套餐、起止时间、状态与自动续费。
  • Token余额/使用(TokenBalance/TokenUsage):用于精细化计费与配额控制。
  • 订单(Order):购买订阅的流水记录。

    classDiagram
    class SubscriptionPlan {
    +int id
    +string name
    +int level
    +decimal priceMonthly
    +decimal priceYearly
    +int dailyGenerations
    +int perGenerationLimit
    +int monthlyTokens
    +int monthlyMinutes
    +bool isRecommended
    +bool isActive
    +int sortOrder
    +string features
    }
    class Subscription {
    +int id
    +int userId
    +int planId
    +datetime startDate
    +datetime endDate
    +string status
    +bool autoRenew
    }
    class Order {
    +int id
    +int userId
    +string orderNo
    +int planId
    +string productType
    +decimal amount
    +string status
    +datetime paidAt
    }
    class TokenBalance {
    +int id
    +int userId
    +int totalTokens
    +int usedTokens
    +datetime resetDate
    }
    class TokenUsage {
    +int id
    +int userId
    +string type
    +int amount
    +int contentLength
    +int orderId
    }
    SubscriptionPlan ||--o{ Subscription : "被订阅"
    SubscriptionPlan ||--o{ Order : "被购买"
    Order ||--|| Subscription : "关联"
    User ||--o{ Order : "创建"
    User ||--|| TokenBalance : "拥有"
    TokenBalance ||--o{ TokenUsage : "产生"
    

图表来源

  • schema.prisma:254-332
  • 支付集成指南.md:277-336

章节来源

  • schema.prisma:254-332
  • 支付集成指南.md:277-336

依赖分析

  • 控制器到服务:tts.controller.ts依赖tts.service.ts进行TTS生成与状态查询;member.controller.ts依赖member.service.ts进行会员权益与订单管理。
  • 服务到数据层:tts.service.ts与member.service.ts均通过PrismaClient访问schema.prisma定义的模型。
  • 配置到模型:index.ts中加载models.json,统一管理供应商与默认模型,供TTS服务选择与降级策略使用。

    graph LR
    TTS_C["tts.controller.ts"] --> TTS_S["tts.service.ts"]
    MEM_C["member.controller.ts"] --> MEM_S["member.service.ts"]
    AUTH_S["auth.service.ts"] --> MODELS["models/index.ts"]
    TTS_S --> MODELS
    MEM_S --> MODELS
    MODELS --> PRISMA["schema.prisma"]
    

图表来源

  • tts.controller.ts:1-274
  • tts.service.ts:1-715
  • member.controller.ts:1-90
  • member.service.ts:1-183
  • index.ts:1-15
  • index.ts:1-117
  • models.json:1-168

章节来源

  • tts.controller.ts:1-274
  • tts.service.ts:1-715
  • member.controller.ts:1-90
  • member.service.ts:1-183
  • index.ts:1-15
  • index.ts:1-117
  • models.json:1-168

性能考虑

  • 索引策略
    • 用户:phone、openid唯一索引,便于登录与去重。
    • 订单:按(userId, createdAt)、orderNo、status建立索引,支撑订单查询与状态统计。
    • 章节:(bookId,parentId,level,number)唯一索引与(bookId)索引,保证层级唯一性与快速检索。
    • 音频记录:按userId、audioId、bookId建立索引,支撑用户资产查询与生成状态追踪。
    • 订阅:按(userId,status)、(userId,endDate)建立复合索引,支撑到期与状态扫描。
  • 查询优化
    • 使用select精确投影,避免长文本字段不必要的加载。
    • 分页查询时使用skip/take,结合索引减少排序开销。
    • 对高频过滤条件(状态、用户ID、创建时间)建立复合索引。
  • 缓存与降级
    • 对热点配置(模型列表、默认音色)进行内存缓存,降低数据库压力。
    • TTS提供商失败时按策略切换,必要时降级至模拟服务,保障可用性。
  • IO与存储
    • 音频文件上传统一经由storageService,支持本地或OSS,避免数据库存储大对象。

章节来源

  • schema.prisma:36-319
  • tts.service.ts:160-190

故障排查指南

  • 登录与验证码
    • 生成与验证验证码,支持免验证码登录(开发调试)。
    • 令牌生成与校验,确保用户会话安全。
  • TTS生成状态
    • 通过getAudioStatus基于文件系统与数据库双重状态判断,检测僵尸任务并回写失败状态。
    • 提供预览音频接口,快速验证音色与参数。
  • 订单与会员
    • 订单状态变更与会员等级更新,支持模拟支付(开发环境)。
    • 会员配额检查与每日用量重置逻辑,避免超额使用。

章节来源

  • auth.service.ts:1-115
  • tts.service.ts:547-597
  • member.service.ts:75-155

结论

本设计以Prisma ORM为核心,围绕用户、音频、TTS记录、会员与订阅构建了清晰的数据模型与索引策略。通过控制器-服务-数据层的分层架构,实现了异步TTS生成、配额控制、状态追踪与播放列表等核心能力。建议在生产环境中强化备份与监控、完善灰度与回滚机制,并持续优化索引与查询路径以应对业务增长。

附录

索引与查询优化清单

  • 用户:phone、openid唯一索引
  • 订单:(userId,createdAt)、orderNo、status
  • 章节:(bookId,parentId,level,number)唯一、bookId
  • 音频记录:(userId)、(audioId)、(bookId)
  • 订阅:(userId,status)、(userId,endDate)
  • 建议新增
    • 播放记录:(userId,chapterId)唯一、(chapterId)
    • Token使用:(userId,createdAt)、(userId,type)
    • 草稿:(userId,type)、(userId,updatedAt)

章节来源

  • schema.prisma:36-319

数据模型生命周期管理

  • 版本演进
    • 使用Prisma迁移脚本管理schema变更,确保线上一致性。
    • 新增模型或字段时,先在迁移中添加,再在schema.prisma声明,最后重启服务。
  • 迁移示例
    • 通过migration.sql创建AudioRecord与PlatformAccount等表及索引。
  • 回滚策略
    • 保留历史迁移文件,必要时回退至上一稳定版本。
    • 对破坏性变更采用“先加后删”策略,逐步替换旧字段。

章节来源

  • migration.sql:340-376

数据安全、备份与监控

  • 安全
    • 严格最小权限原则,数据库连接凭据通过环境变量注入。
    • JWT密钥与过期策略集中配置,避免硬编码。
  • 备份
    • 定期快照与增量备份,保留至少7天可恢复点。
  • 监控
    • 关键指标:慢查询、连接池利用率、索引命中率、TTS成功率与延迟。
    • 告警阈值:查询超时、连接池耗尽、TTS失败率上升。