schema.prisma 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. generator client {
  2. provider = "prisma-client-js"
  3. }
  4. datasource db {
  5. provider = "mysql"
  6. url = env("DATABASE_URL")
  7. }
  8. model User {
  9. id Int @id @default(autoincrement())
  10. phone String? @unique
  11. openid String? @unique
  12. nickname String @default("用户")
  13. avatar String @default("")
  14. memberLevel Int @default(0)
  15. memberExpireAt DateTime?
  16. dailyUsage Int @default(0)
  17. lastUsageDate String @default("")
  18. createdAt DateTime @default(now())
  19. updatedAt DateTime @updatedAt
  20. orders Order[]
  21. playRecords PlayRecord[]
  22. preferences UserPreference?
  23. favorites Favorite[]
  24. comments Comment[]
  25. signRecords SignRecord[]
  26. subscriptions Subscription[]
  27. tokenUsages TokenUsage[]
  28. tokenBalance TokenBalance?
  29. @@index([phone])
  30. @@index([openid])
  31. }
  32. // 订单
  33. model Order {
  34. id Int @id @default(autoincrement())
  35. userId Int
  36. orderNo String @unique
  37. planId Int? // 关联的套餐ID
  38. productType String // monthly 或 yearly
  39. amount Decimal @db.Decimal(10, 2)
  40. status String @default("pending") // pending, paid, failed, refunded
  41. paymentMethod String? // alipay, wechat, mock
  42. paymentId String? // 第三方支付单号
  43. paidAt DateTime?
  44. createdAt DateTime @default(now())
  45. updatedAt DateTime @updatedAt
  46. user User @relation(fields: [userId], references: [id])
  47. plan SubscriptionPlan? @relation(fields: [planId], references: [id])
  48. tokenUsages TokenUsage[]
  49. @@index([userId, createdAt])
  50. @@index([orderNo])
  51. @@index([status])
  52. }
  53. // 播放记录(播放的是章节的音频)
  54. model PlayRecord {
  55. id Int @id @default(autoincrement())
  56. userId Int
  57. chapterId Int // BookChapter.id(章节ID)
  58. progress Float @default(0) // 播放进度(秒)
  59. duration Float @default(0) // 总时长
  60. updatedAt DateTime @updatedAt
  61. createdAt DateTime @default(now())
  62. user User @relation(fields: [userId], references: [id])
  63. chapter BookChapter @relation(fields: [chapterId], references: [id])
  64. @@unique([userId, chapterId])
  65. @@index([userId])
  66. @@index([chapterId])
  67. }
  68. // 用户偏好
  69. model UserPreference {
  70. id Int @id @default(autoincrement())
  71. userId Int @unique
  72. playSpeed Float @default(1.0)
  73. quality String @default("standard") // standard, high
  74. theme String @default("light")
  75. updatedAt DateTime @updatedAt
  76. createdAt DateTime @default(now())
  77. user User @relation(fields: [userId], references: [id])
  78. }
  79. // 收藏(收藏的是书籍/专辑)
  80. model Favorite {
  81. id Int @id @default(autoincrement())
  82. userId Int
  83. bookId Int // Book.id(收藏的是整本书籍)
  84. createdAt DateTime @default(now())
  85. user User @relation(fields: [userId], references: [id])
  86. book Book @relation(fields: [bookId], references: [id], onDelete: Cascade)
  87. @@unique([userId, bookId])
  88. @@index([userId])
  89. @@index([bookId])
  90. }
  91. // 分类
  92. model Category {
  93. id Int @id @default(autoincrement())
  94. name String
  95. icon String @default("")
  96. sort Int @default(0)
  97. createdAt DateTime @default(now())
  98. }
  99. // 评论(评论的是章节)
  100. model Comment {
  101. id Int @id @default(autoincrement())
  102. userId Int
  103. chapterId Int // BookChapter.id
  104. content String @db.Text
  105. rating Int // 1-5星
  106. createdAt DateTime @default(now())
  107. user User @relation(fields: [userId], references: [id])
  108. chapter BookChapter @relation(fields: [chapterId], references: [id])
  109. @@index([chapterId])
  110. @@index([userId])
  111. }
  112. // 系统通知
  113. model Notification {
  114. id String @id @default(uuid())
  115. userId String
  116. title String
  117. content String @db.Text
  118. isRead Boolean @default(false)
  119. createdAt DateTime @default(now())
  120. }
  121. // ============ 模板管理 ============
  122. model Template {
  123. id Int @id @default(autoincrement())
  124. name String
  125. category String // 广告营销/知识付费/短视频/企业宣传/日常生活/新闻资讯
  126. content String @db.Text // 模板内容
  127. description String? @db.Text // 模板描述
  128. createdAt DateTime @default(now())
  129. updatedAt DateTime @updatedAt
  130. @@index([category])
  131. }
  132. // ============ 书籍/章节(核心内容) ============
  133. // 书籍(专辑)
  134. model Book {
  135. id Int @id @default(autoincrement())
  136. userId Int?
  137. title String // 书名
  138. subtitle String? // 副标题
  139. description String @db.Text // 书籍描述/用户输入
  140. coverUrl String? // 封面图
  141. targetAudience String @default("通用") // 目标受众
  142. style String @default("专业严谨") // 写作风格
  143. totalChapters Int @default(10) // 总章节数
  144. estimatedWords Int @default(0) // 预估总字数
  145. status String @default("draft") // draft, planning, generating, completed, failed
  146. progress Int @default(0) // 生成进度 0-100
  147. isPublished Boolean @default(false) // 是否已发布
  148. // 大纲(JSON 存储)
  149. outlineJson String? @db.LongText // BookOutline JSON
  150. // 前言/后记
  151. foreword String? @db.Text
  152. afterword String? @db.Text
  153. // 错误信息
  154. errorMsg String? @db.Text
  155. createdAt DateTime @default(now())
  156. updatedAt DateTime @updatedAt
  157. chapters BookChapter[]
  158. videoProjects VideoProject[] // 关联的视频项目
  159. favorites Favorite[] // 收藏此书籍的用户
  160. @@index([userId, status])
  161. @@index([createdAt])
  162. }
  163. // 书籍章节(内容单元)
  164. // 一个章节 = 一份内容,有3种形式:content(文本)、audioUrl(音频)、videoUrl(视频)
  165. model BookChapter {
  166. id Int @id @default(autoincrement())
  167. bookId Int
  168. number Int // 章节序号
  169. title String // 章节标题
  170. summary String? @db.Text // 章节概述
  171. keyPoints String? @db.Text // 核心知识点(JSON数组)
  172. estimatedWords Int @default(1000) // 预估字数
  173. content String? @db.LongText // 正文内容(原始文本)
  174. wordCount Int @default(0) // 实际字数
  175. status String @default("pending") // pending, generating, completed, failed
  176. errorMsg String? @db.Text
  177. generatedAt DateTime?
  178. // 3种表现形式
  179. audioUrl String? @db.Text // 音频URL(由 content 生成)
  180. audioDuration Int @default(0) // 音频时长(秒)
  181. videoUrl String? @db.Text // 视频URL(由 content/audio 生成)
  182. videoDuration Int? // 视频时长(秒)
  183. book Book @relation(fields: [bookId], references: [id], onDelete: Cascade)
  184. videoProjects VideoProject[]
  185. playRecords PlayRecord[]
  186. comments Comment[]
  187. @@unique([bookId, number])
  188. @@index([bookId])
  189. }
  190. // ============ 学习路径模块 ============
  191. // 学习路径任务
  192. model LearningPath {
  193. id Int @id @default(autoincrement())
  194. userId Int?
  195. topic String @db.Text // 用户输入的主题
  196. status String @default("pending") // pending, generating, completed, failed
  197. progress Int @default(0) // 0-100 进度百分比
  198. totalCount Int @default(0) // 总内容块数
  199. completedCount Int @default(0) // 已完成内容块数
  200. errorMsg String? @db.Text // 错误信息
  201. // 生成模式: progressive(渐进确认) | multi-agent(多Agent并行)
  202. generationMode String @default("progressive")
  203. // 当前步骤(渐进模式): pending, subjects, chapters, sections, content, completed
  204. currentStep String @default("pending")
  205. // 多Agent模式状态: 存储各Agent的进度JSON
  206. agentStatus String? @db.Text
  207. createdAt DateTime @default(now())
  208. updatedAt DateTime @updatedAt
  209. subjects Subject[]
  210. @@index([userId, status])
  211. }
  212. // 学科(大类)
  213. model Subject {
  214. id Int @id @default(autoincrement())
  215. learningPathId Int
  216. name String // 学科名称,如"计算机原理"
  217. orderIndex Int @default(0) // 排序
  218. status String @default("pending") // pending, generating, completed
  219. aiResponse String? @db.Text // AI返回的原始内容
  220. // 确认状态(渐进模式): pending, confirmed, regenerating
  221. confirmationStatus String @default("pending")
  222. createdAt DateTime @default(now())
  223. updatedAt DateTime @updatedAt
  224. learningPath LearningPath @relation(fields: [learningPathId], references: [id], onDelete: Cascade)
  225. chapters Chapter[]
  226. @@index([learningPathId, orderIndex])
  227. }
  228. // 章节
  229. model Chapter {
  230. id Int @id @default(autoincrement())
  231. subjectId Int
  232. name String // 章节名称
  233. orderIndex Int @default(0)
  234. status String @default("pending")
  235. aiResponse String? @db.Text
  236. // 确认状态(渐进模式): pending, confirmed, regenerating
  237. confirmationStatus String @default("pending")
  238. createdAt DateTime @default(now())
  239. updatedAt DateTime @updatedAt
  240. subject Subject @relation(fields: [subjectId], references: [id], onDelete: Cascade)
  241. sections Section[]
  242. @@index([subjectId, orderIndex])
  243. }
  244. // 小节
  245. model Section {
  246. id Int @id @default(autoincrement())
  247. chapterId Int
  248. name String // 小节名称
  249. orderIndex Int @default(0)
  250. status String @default("pending")
  251. aiResponse String? @db.Text
  252. // 确认状态(渐进模式): pending, confirmed, regenerating
  253. confirmationStatus String @default("pending")
  254. createdAt DateTime @default(now())
  255. updatedAt DateTime @updatedAt
  256. chapter Chapter @relation(fields: [chapterId], references: [id], onDelete: Cascade)
  257. contentBlocks ContentBlock[]
  258. @@index([chapterId, orderIndex])
  259. }
  260. // 内容块(详细内容)
  261. model ContentBlock {
  262. id Int @id @default(autoincrement())
  263. sectionId Int
  264. content String @db.Text // 详细内容
  265. orderIndex Int @default(0)
  266. wordCount Int @default(0)
  267. createdAt DateTime @default(now())
  268. updatedAt DateTime @updatedAt
  269. section Section @relation(fields: [sectionId], references: [id], onDelete: Cascade)
  270. @@index([sectionId, orderIndex])
  271. }
  272. // ============ 视频生成模块 ============
  273. // 视频项目(关联到书籍的某个章节)
  274. model VideoProject {
  275. id Int @id @default(autoincrement())
  276. userId Int?
  277. title String // 项目标题
  278. description String? // 描述
  279. coverUrl String? // 封面图
  280. // 素材配置(JSON存储)
  281. configJson String? @db.LongText // VideoConfig JSON
  282. // 输出视频
  283. outputUrl String? // 生成后的视频URL
  284. duration Int? // 视频时长(秒)
  285. fileSize Int? // 文件大小(字节)
  286. // 关联:直接关联到章节
  287. bookId Int? // 关联的书籍ID(可选)
  288. chapterId Int? // 关联的章节ID(直接关联章节获取 content/audioUrl)
  289. status String @default("draft") // draft, processing, completed, failed
  290. progress Int @default(0) // 0-100
  291. errorMsg String? @db.Text
  292. createdAt DateTime @default(now())
  293. updatedAt DateTime @updatedAt
  294. book Book? @relation(fields: [bookId], references: [id])
  295. chapter BookChapter? @relation(fields: [chapterId], references: [id])
  296. @@index([userId, status])
  297. @@index([createdAt])
  298. }
  299. // ============ 搜索历史 ============
  300. model SearchHistory {
  301. id Int @id @default(autoincrement())
  302. userId Int // 用户ID,0表示未登录用户
  303. keyword String // 搜索关键词
  304. createdAt DateTime @default(now())
  305. @@index([userId, createdAt])
  306. @@index([userId])
  307. }
  308. // 热门搜索词
  309. model HotSearch {
  310. id Int @id @default(autoincrement())
  311. keyword String // 搜索关键词
  312. count Int @default(0) // 搜索次数
  313. sort Int @default(0) // 排序,数字越大越靠前
  314. createdAt DateTime @default(now())
  315. updatedAt DateTime @updatedAt
  316. @@index([sort])
  317. @@index([count])
  318. }
  319. // 签到记录
  320. model SignRecord {
  321. id Int @id @default(autoincrement())
  322. userId Int
  323. createdAt DateTime @default(now())
  324. user User @relation(fields: [userId], references: [id])
  325. @@unique([userId, createdAt])
  326. @@index([userId, createdAt])
  327. }
  328. // ============ 订阅套餐系统 ============
  329. // 套餐计划
  330. model SubscriptionPlan {
  331. id Int @id @default(autoincrement())
  332. name String // 套餐名称
  333. level Int @default(0) // 套餐等级:0免费 1基础 2专业 3旗舰
  334. priceMonthly Decimal @db.Decimal(10, 2) @default(0) // 月付价格
  335. priceYearly Decimal @db.Decimal(10, 2) @default(0) // 年付价格
  336. description String? @db.Text // 套餐描述
  337. features String? @db.Text // 功能列表(JSON数组)
  338. isRecommended Boolean @default(false) // 是否推荐
  339. isActive Boolean @default(true) // 是否上架
  340. sortOrder Int @default(0) // 排序
  341. // 限制配置
  342. dailyGenerations Int @default(3) // 每日生成次数,-1表示无限制
  343. perGenerationLimit Int @default(2000) // 单次生成限制字数
  344. monthlyTokens Int @default(10000) // 每月token配额,-1表示无限制
  345. yearlyTokens Int? // 每年token配额(旗舰版用)
  346. voiceOptions Int @default(5) // 可用音色数,-1表示全部
  347. audioQuality String @default("standard") // standard, high, lossless
  348. // 高级功能
  349. apiAccess Boolean @default(false) // API访问权限
  350. batchProcessing Boolean @default(false) // 批量处理权限
  351. teamManagement Boolean @default(false) // 团队管理权限
  352. createdAt DateTime @default(now())
  353. updatedAt DateTime @updatedAt
  354. subscriptions Subscription[]
  355. orders Order[]
  356. @@index([level])
  357. @@index([isActive, sortOrder])
  358. }
  359. // 用户订阅记录
  360. model Subscription {
  361. id Int @id @default(autoincrement())
  362. userId Int
  363. planId Int
  364. startDate DateTime
  365. endDate DateTime
  366. status String @default("active") // active, expired, cancelled
  367. autoRenew Boolean @default(false) // 自动续费
  368. createdAt DateTime @default(now())
  369. updatedAt DateTime @updatedAt
  370. user User @relation(fields: [userId], references: [id])
  371. plan SubscriptionPlan @relation(fields: [planId], references: [id])
  372. @@index([userId, status])
  373. @@index([userId, endDate])
  374. }
  375. // Token使用记录
  376. model TokenUsage {
  377. id Int @id @default(autoincrement())
  378. userId Int
  379. type String // text_to_speech, api_call, batch_process
  380. amount Int @default(0) // 消耗token数量
  381. contentLength Int @default(0) // 内容长度(字数)
  382. orderId Int? // 关联的订单ID
  383. description String? @db.Text // 消耗描述
  384. createdAt DateTime @default(now())
  385. user User @relation(fields: [userId], references: [id])
  386. order Order? @relation(fields: [orderId], references: [id])
  387. @@index([userId, createdAt])
  388. @@index([userId, type])
  389. }
  390. // Token余额
  391. model TokenBalance {
  392. id Int @id @default(autoincrement())
  393. userId Int @unique
  394. totalTokens Int @default(0) // 总token配额
  395. usedTokens Int @default(0) // 已使用token
  396. resetDate DateTime? // 重置日期(月/年)
  397. createdAt DateTime @default(now())
  398. updatedAt DateTime @updatedAt
  399. user User @relation(fields: [userId], references: [id])
  400. @@index([userId])
  401. }
  402. // 视频素材库(保留作为独立素材)
  403. model VideoMaterial {
  404. id Int @id @default(autoincrement())
  405. userId Int? // null 表示公共素材
  406. type String // image, audio, template
  407. name String // 素材名称
  408. url String @db.Text // 素材URL
  409. thumbnail String? // 缩略图URL
  410. tags String? @db.Text // 标签(JSON数组)
  411. category String? // 分类:nature, abstract, business, music等
  412. duration Int? // 音频时长(秒)
  413. size Int? // 文件大小(字节)
  414. width Int? // 图片宽度
  415. height Int? // 图片高度
  416. createdAt DateTime @default(now())
  417. updatedAt DateTime @updatedAt
  418. @@index([userId, type])
  419. @@index([type, category])
  420. }