generator client { provider = "prisma-client-js" } datasource db { provider = "mysql" url = env("DATABASE_URL") } model User { id Int @id @default(autoincrement()) phone String? @unique openid String? @unique nickname String @default("用户") avatar String @default("") memberLevel Int @default(0) memberExpireAt DateTime? dailyUsage Int @default(0) lastUsageDate String @default("") createdAt DateTime @default(now()) updatedAt DateTime @updatedAt orders Order[] playRecords PlayRecord[] preferences UserPreference? favorites Favorite[] comments Comment[] @@index([phone]) @@index([openid]) } // 订单 model Order { id Int @id @default(autoincrement()) userId Int orderNo String @unique productType String // monthly 或 yearly amount Decimal @db.Decimal(10, 2) status String @default("pending") paymentMethod String? paidAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id]) @@index([userId, createdAt]) @@index([orderNo]) } // 播放记录(播放的是章节的音频) model PlayRecord { id Int @id @default(autoincrement()) userId Int chapterId Int // BookChapter.id(章节ID) progress Float @default(0) // 播放进度(秒) duration Float @default(0) // 总时长 updatedAt DateTime @updatedAt createdAt DateTime @default(now()) user User @relation(fields: [userId], references: [id]) chapter BookChapter @relation(fields: [chapterId], references: [id]) @@unique([userId, chapterId]) @@index([userId]) @@index([chapterId]) } // 用户偏好 model UserPreference { id Int @id @default(autoincrement()) userId Int @unique playSpeed Float @default(1.0) quality String @default("standard") // standard, high theme String @default("light") updatedAt DateTime @updatedAt createdAt DateTime @default(now()) user User @relation(fields: [userId], references: [id]) } // 收藏(收藏的是书籍/专辑) model Favorite { id Int @id @default(autoincrement()) userId Int bookId Int // Book.id(收藏的是整本书籍) createdAt DateTime @default(now()) user User @relation(fields: [userId], references: [id]) book Book @relation(fields: [bookId], references: [id], onDelete: Cascade) @@unique([userId, bookId]) @@index([userId]) @@index([bookId]) } // 分类 model Category { id Int @id @default(autoincrement()) name String icon String @default("") sort Int @default(0) createdAt DateTime @default(now()) } // 评论(评论的是章节) model Comment { id Int @id @default(autoincrement()) userId Int chapterId Int // BookChapter.id content String @db.Text rating Int // 1-5星 createdAt DateTime @default(now()) user User @relation(fields: [userId], references: [id]) chapter BookChapter @relation(fields: [chapterId], references: [id]) @@index([chapterId]) @@index([userId]) } // 系统通知 model Notification { id String @id @default(uuid()) userId String title String content String @db.Text isRead Boolean @default(false) createdAt DateTime @default(now()) } // ============ 模板管理 ============ model Template { id Int @id @default(autoincrement()) name String category String // 广告营销/知识付费/短视频/企业宣传/日常生活/新闻资讯 content String @db.Text // 模板内容 description String? @db.Text // 模板描述 createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([category]) } // ============ 书籍/章节(核心内容) ============ // 书籍(专辑) model Book { id Int @id @default(autoincrement()) userId Int? title String // 书名 subtitle String? // 副标题 description String @db.Text // 书籍描述/用户输入 coverUrl String? // 封面图 targetAudience String @default("通用") // 目标受众 style String @default("专业严谨") // 写作风格 totalChapters Int @default(10) // 总章节数 estimatedWords Int @default(0) // 预估总字数 status String @default("draft") // draft, planning, generating, completed, failed progress Int @default(0) // 生成进度 0-100 isPublished Boolean @default(false) // 是否已发布 // 大纲(JSON 存储) outlineJson String? @db.LongText // BookOutline JSON // 前言/后记 foreword String? @db.Text afterword String? @db.Text // 错误信息 errorMsg String? @db.Text createdAt DateTime @default(now()) updatedAt DateTime @updatedAt chapters BookChapter[] videoProjects VideoProject[] // 关联的视频项目 favorites Favorite[] // 收藏此书籍的用户 @@index([userId, status]) @@index([createdAt]) } // 书籍章节(内容单元) // 一个章节 = 一份内容,有3种形式:content(文本)、audioUrl(音频)、videoUrl(视频) model BookChapter { id Int @id @default(autoincrement()) bookId Int number Int // 章节序号 title String // 章节标题 summary String? @db.Text // 章节概述 keyPoints String? @db.Text // 核心知识点(JSON数组) estimatedWords Int @default(1000) // 预估字数 content String? @db.LongText // 正文内容(原始文本) wordCount Int @default(0) // 实际字数 status String @default("pending") // pending, generating, completed, failed errorMsg String? @db.Text generatedAt DateTime? // 3种表现形式 audioUrl String? @db.Text // 音频URL(由 content 生成) audioDuration Int @default(0) // 音频时长(秒) videoUrl String? @db.Text // 视频URL(由 content/audio 生成) videoDuration Int? // 视频时长(秒) book Book @relation(fields: [bookId], references: [id], onDelete: Cascade) videoProjects VideoProject[] playRecords PlayRecord[] comments Comment[] @@unique([bookId, number]) @@index([bookId]) } // ============ 学习路径模块 ============ // 学习路径任务 model LearningPath { id Int @id @default(autoincrement()) userId Int? topic String @db.Text // 用户输入的主题 status String @default("pending") // pending, generating, completed, failed progress Int @default(0) // 0-100 进度百分比 totalCount Int @default(0) // 总内容块数 completedCount Int @default(0) // 已完成内容块数 errorMsg String? @db.Text // 错误信息 // 生成模式: progressive(渐进确认) | multi-agent(多Agent并行) generationMode String @default("progressive") // 当前步骤(渐进模式): pending, subjects, chapters, sections, content, completed currentStep String @default("pending") // 多Agent模式状态: 存储各Agent的进度JSON agentStatus String? @db.Text createdAt DateTime @default(now()) updatedAt DateTime @updatedAt subjects Subject[] @@index([userId, status]) } // 学科(大类) model Subject { id Int @id @default(autoincrement()) learningPathId Int name String // 学科名称,如"计算机原理" orderIndex Int @default(0) // 排序 status String @default("pending") // pending, generating, completed aiResponse String? @db.Text // AI返回的原始内容 // 确认状态(渐进模式): pending, confirmed, regenerating confirmationStatus String @default("pending") createdAt DateTime @default(now()) updatedAt DateTime @updatedAt learningPath LearningPath @relation(fields: [learningPathId], references: [id], onDelete: Cascade) chapters Chapter[] @@index([learningPathId, orderIndex]) } // 章节 model Chapter { id Int @id @default(autoincrement()) subjectId Int name String // 章节名称 orderIndex Int @default(0) status String @default("pending") aiResponse String? @db.Text // 确认状态(渐进模式): pending, confirmed, regenerating confirmationStatus String @default("pending") createdAt DateTime @default(now()) updatedAt DateTime @updatedAt subject Subject @relation(fields: [subjectId], references: [id], onDelete: Cascade) sections Section[] @@index([subjectId, orderIndex]) } // 小节 model Section { id Int @id @default(autoincrement()) chapterId Int name String // 小节名称 orderIndex Int @default(0) status String @default("pending") aiResponse String? @db.Text // 确认状态(渐进模式): pending, confirmed, regenerating confirmationStatus String @default("pending") createdAt DateTime @default(now()) updatedAt DateTime @updatedAt chapter Chapter @relation(fields: [chapterId], references: [id], onDelete: Cascade) contentBlocks ContentBlock[] @@index([chapterId, orderIndex]) } // 内容块(详细内容) model ContentBlock { id Int @id @default(autoincrement()) sectionId Int content String @db.Text // 详细内容 orderIndex Int @default(0) wordCount Int @default(0) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt section Section @relation(fields: [sectionId], references: [id], onDelete: Cascade) @@index([sectionId, orderIndex]) } // ============ 视频生成模块 ============ // 视频项目(关联到书籍的某个章节) model VideoProject { id Int @id @default(autoincrement()) userId Int? title String // 项目标题 description String? // 描述 coverUrl String? // 封面图 // 素材配置(JSON存储) configJson String? @db.LongText // VideoConfig JSON // 输出视频 outputUrl String? // 生成后的视频URL duration Int? // 视频时长(秒) fileSize Int? // 文件大小(字节) // 关联:直接关联到章节 bookId Int? // 关联的书籍ID(可选) chapterId Int? // 关联的章节ID(直接关联章节获取 content/audioUrl) status String @default("draft") // draft, processing, completed, failed progress Int @default(0) // 0-100 errorMsg String? @db.Text createdAt DateTime @default(now()) updatedAt DateTime @updatedAt book Book? @relation(fields: [bookId], references: [id]) chapter BookChapter? @relation(fields: [chapterId], references: [id]) @@index([userId, status]) @@index([createdAt]) } // 视频素材库(保留作为独立素材) model VideoMaterial { id Int @id @default(autoincrement()) userId Int? // null 表示公共素材 type String // image, audio, template name String // 素材名称 url String @db.Text // 素材URL thumbnail String? // 缩略图URL tags String? @db.Text // 标签(JSON数组) category String? // 分类:nature, abstract, business, music等 duration Int? // 音频时长(秒) size Int? // 文件大小(字节) width Int? // 图片宽度 height Int? // 图片高度 createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([userId, type]) @@index([type, category]) }