schema.prisma 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  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. usedAudioMinutes Int @default(0)
  21. subscriptionResetDate DateTime?
  22. comments Comment[]
  23. drafts Draft[]
  24. favorites Favorite[]
  25. notifications Notification[]
  26. orders Order[]
  27. playRecords PlayRecord[]
  28. playlists Playlist[]
  29. signRecords SignRecord[]
  30. subscriptions Subscription[]
  31. tokenBalance TokenBalance?
  32. tokenUsages TokenUsage[]
  33. preferences UserPreference?
  34. @@index([phone])
  35. @@index([openid])
  36. }
  37. model Order {
  38. id Int @id @default(autoincrement())
  39. userId Int
  40. orderNo String @unique
  41. planId Int?
  42. productType String
  43. amount Decimal @db.Decimal(10, 2)
  44. status String @default("pending")
  45. paymentMethod String?
  46. paymentId String?
  47. paidAt DateTime?
  48. createdAt DateTime @default(now())
  49. updatedAt DateTime @updatedAt
  50. plan SubscriptionPlan? @relation(fields: [planId], references: [id])
  51. user User @relation(fields: [userId], references: [id])
  52. tokenUsages TokenUsage[]
  53. @@index([userId, createdAt])
  54. @@index([orderNo])
  55. @@index([status])
  56. @@index([planId], map: "Order_planId_fkey")
  57. }
  58. model PlayRecord {
  59. id Int @id @default(autoincrement())
  60. userId Int
  61. chapterId Int
  62. progress Float @default(0)
  63. duration Float @default(0)
  64. updatedAt DateTime @updatedAt
  65. createdAt DateTime @default(now())
  66. chapter BookChapter @relation(fields: [chapterId], references: [id])
  67. user User @relation(fields: [userId], references: [id])
  68. @@unique([userId, chapterId])
  69. @@index([userId])
  70. @@index([chapterId])
  71. }
  72. model UserPreference {
  73. id Int @id @default(autoincrement())
  74. userId Int @unique
  75. playSpeed Float @default(1)
  76. quality String @default("standard")
  77. theme String @default("light")
  78. defaultVoiceId String? @default("cherry")
  79. defaultVolume Int @default(50)
  80. autoPlayNext Boolean @default(true)
  81. wifiOnlyDownload Boolean @default(false)
  82. updatedAt DateTime @updatedAt
  83. createdAt DateTime @default(now())
  84. user User @relation(fields: [userId], references: [id])
  85. }
  86. model Favorite {
  87. id Int @id @default(autoincrement())
  88. userId Int
  89. bookId Int
  90. createdAt DateTime @default(now())
  91. book Book @relation(fields: [bookId], references: [id], onDelete: Cascade)
  92. user User @relation(fields: [userId], references: [id])
  93. @@unique([userId, bookId])
  94. @@index([userId])
  95. @@index([bookId])
  96. }
  97. model Comment {
  98. id Int @id @default(autoincrement())
  99. userId Int
  100. chapterId Int
  101. content String @db.Text
  102. rating Int
  103. createdAt DateTime @default(now())
  104. chapter BookChapter @relation(fields: [chapterId], references: [id])
  105. user User @relation(fields: [userId], references: [id])
  106. @@index([chapterId])
  107. @@index([userId])
  108. }
  109. model Notification {
  110. id String @id @default(uuid())
  111. userId Int
  112. title String
  113. content String @db.Text
  114. isRead Boolean @default(false)
  115. createdAt DateTime @default(now())
  116. user User @relation(fields: [userId], references: [id])
  117. @@index([userId])
  118. }
  119. model Book {
  120. id Int @id @default(autoincrement())
  121. userId Int?
  122. title String
  123. subtitle String?
  124. description String @db.Text
  125. coverUrl String?
  126. targetAudience String @default("通用")
  127. style String @default("专业严谨")
  128. bookScale String @default("130000")
  129. totalChapters Int @default(10)
  130. estimatedWords Int @default(0)
  131. progress Int @default(0)
  132. isPublished Boolean @default(false)
  133. outlineJson String? @db.LongText
  134. foreword String? @db.Text
  135. afterword String? @db.Text
  136. errorMsg String? @db.Text
  137. createdAt DateTime @default(now())
  138. updatedAt DateTime @updatedAt
  139. failedStage String? @db.VarChar(30)
  140. genStage String @default("draft")
  141. bookAnalysis String? @db.Text
  142. chapters BookChapter[]
  143. favorites Favorite[]
  144. videoProjects VideoProject[]
  145. @@index([userId])
  146. @@index([createdAt])
  147. }
  148. model BookChapter {
  149. id Int @id @default(autoincrement())
  150. bookId Int
  151. parentId Int @default(0)
  152. level Int @default(1)
  153. number Int
  154. title String
  155. summary String? @db.Text
  156. keyPoints String? @db.Text
  157. estimatedWords Int @default(1000)
  158. content String? @db.LongText
  159. wordCount Int @default(0)
  160. contentError String? @db.Text
  161. generatedAt DateTime?
  162. audioUrl String? @db.Text
  163. audioDuration Int @default(0)
  164. videoUrl String? @db.Text
  165. videoDuration Int?
  166. isPublic Boolean @default(false)
  167. genStage String @default("idle")
  168. lrcLyrics String? @db.Text
  169. book Book @relation(fields: [bookId], references: [id], onDelete: Cascade)
  170. comments Comment[]
  171. playRecords PlayRecord[]
  172. playlistItems PlaylistItem[]
  173. ttsTasks TtsTask[]
  174. videoProjects VideoProject[]
  175. @@unique([bookId, parentId, level, number])
  176. @@index([bookId])
  177. @@index([bookId, parentId])
  178. @@index([bookId, level])
  179. }
  180. model VideoProject {
  181. id Int @id @default(autoincrement())
  182. userId Int?
  183. title String
  184. description String?
  185. coverUrl String?
  186. configJson String? @db.LongText
  187. outputUrl String?
  188. duration Int?
  189. fileSize Int?
  190. bookId Int?
  191. chapterId Int?
  192. status String @default("draft")
  193. progress Int @default(0)
  194. errorMsg String? @db.Text
  195. createdAt DateTime @default(now())
  196. updatedAt DateTime @updatedAt
  197. book Book? @relation(fields: [bookId], references: [id])
  198. chapter BookChapter? @relation(fields: [chapterId], references: [id])
  199. @@index([userId, status])
  200. @@index([createdAt])
  201. @@index([bookId], map: "VideoProject_bookId_fkey")
  202. @@index([chapterId], map: "VideoProject_chapterId_fkey")
  203. }
  204. model SearchHistory {
  205. id Int @id @default(autoincrement())
  206. userId Int
  207. keyword String
  208. createdAt DateTime @default(now())
  209. @@index([userId, createdAt])
  210. @@index([userId])
  211. }
  212. model HotSearch {
  213. id Int @id @default(autoincrement())
  214. keyword String
  215. count Int @default(0)
  216. sort Int @default(0)
  217. createdAt DateTime @default(now())
  218. updatedAt DateTime @updatedAt
  219. @@index([sort])
  220. @@index([count])
  221. }
  222. model SignRecord {
  223. id Int @id @default(autoincrement())
  224. userId Int
  225. createdAt DateTime @default(now())
  226. user User @relation(fields: [userId], references: [id])
  227. @@unique([userId, createdAt])
  228. @@index([userId, createdAt])
  229. }
  230. model SubscriptionPlan {
  231. id Int @id @default(autoincrement())
  232. name String
  233. level Int @default(0)
  234. priceMonthly Decimal @default(0.00) @db.Decimal(10, 2)
  235. priceYearly Decimal @default(0.00) @db.Decimal(10, 2)
  236. description String? @db.Text
  237. features String? @db.Text
  238. isRecommended Boolean @default(false)
  239. isActive Boolean @default(true)
  240. sortOrder Int @default(0)
  241. dailyGenerations Int @default(3)
  242. perGenerationLimit Int @default(2000)
  243. monthlyTokens Int @default(10000)
  244. monthlyMinutes Int @default(30)
  245. yearlyTokens Int?
  246. voiceOptions Int @default(5)
  247. audioQuality String @default("standard")
  248. apiAccess Boolean @default(false)
  249. batchProcessing Boolean @default(false)
  250. teamManagement Boolean @default(false)
  251. overageEnabled Boolean @default(false)
  252. overagePrice Decimal @default(0.00) @db.Decimal(10, 2)
  253. createdAt DateTime @default(now())
  254. updatedAt DateTime @updatedAt
  255. orders Order[]
  256. subscriptions Subscription[]
  257. @@index([level])
  258. @@index([isActive, sortOrder])
  259. }
  260. model Subscription {
  261. id Int @id @default(autoincrement())
  262. userId Int
  263. planId Int
  264. startDate DateTime
  265. endDate DateTime
  266. status String @default("active")
  267. autoRenew Boolean @default(false)
  268. createdAt DateTime @default(now())
  269. updatedAt DateTime @updatedAt
  270. plan SubscriptionPlan @relation(fields: [planId], references: [id])
  271. user User @relation(fields: [userId], references: [id])
  272. @@index([userId, status])
  273. @@index([userId, endDate])
  274. @@index([planId], map: "Subscription_planId_fkey")
  275. }
  276. model TokenUsage {
  277. id Int @id @default(autoincrement())
  278. userId Int
  279. type String
  280. amount Int @default(0)
  281. contentLength Int @default(0)
  282. orderId Int?
  283. description String? @db.Text
  284. createdAt DateTime @default(now())
  285. order Order? @relation(fields: [orderId], references: [id])
  286. user User @relation(fields: [userId], references: [id])
  287. @@index([userId, createdAt])
  288. @@index([userId, type])
  289. @@index([orderId], map: "TokenUsage_orderId_fkey")
  290. }
  291. model TokenBalance {
  292. id Int @id @default(autoincrement())
  293. userId Int @unique
  294. totalTokens Int @default(0)
  295. usedTokens Int @default(0)
  296. resetDate DateTime?
  297. createdAt DateTime @default(now())
  298. updatedAt DateTime @updatedAt
  299. user User @relation(fields: [userId], references: [id])
  300. @@index([userId])
  301. }
  302. model VideoMaterial {
  303. id Int @id @default(autoincrement())
  304. userId Int?
  305. type String
  306. name String
  307. url String @db.Text
  308. thumbnail String?
  309. tags String? @db.Text
  310. category String?
  311. duration Int?
  312. size Int?
  313. width Int?
  314. height Int?
  315. createdAt DateTime @default(now())
  316. updatedAt DateTime @updatedAt
  317. @@index([userId, type])
  318. @@index([type, category])
  319. }
  320. model AudioRecord {
  321. id Int @id @default(autoincrement())
  322. userId Int?
  323. audioId String @unique
  324. title String @default("未命名音频")
  325. text String? @db.LongText
  326. wordCount Int @default(0)
  327. voiceId String @default("cherry")
  328. voiceParams String?
  329. audioUrl String? @db.Text
  330. audioDuration Int @default(0)
  331. audioSize Int @default(0)
  332. status String @default("processing")
  333. errorMsg String? @db.Text
  334. createdAt DateTime @default(now())
  335. updatedAt DateTime @updatedAt
  336. bookId Int?
  337. @@index([userId])
  338. @@index([audioId])
  339. @@index([bookId])
  340. }
  341. model TtsTask {
  342. id Int @id @default(autoincrement())
  343. taskType String @default("tts") @db.VarChar(20) // "tts" | "content"
  344. chapterId Int
  345. bookId Int?
  346. userId Int?
  347. contentHash String @db.VarChar(64)
  348. content String? @db.LongText
  349. status String @default("pending")
  350. audioUrl String? @db.Text
  351. audioDuration Int @default(0)
  352. errorMsg String? @db.Text
  353. retryCount Int @default(0)
  354. maxRetries Int @default(3)
  355. voiceId String @default("default")
  356. startedAt DateTime?
  357. completedAt DateTime?
  358. createdAt DateTime @default(now())
  359. updatedAt DateTime @updatedAt
  360. chapter BookChapter @relation(fields: [chapterId], references: [id], onDelete: Cascade)
  361. @@index([taskType, status, createdAt])
  362. @@index([chapterId, contentHash])
  363. @@index([contentHash, chapterId])
  364. }
  365. model AiCallLog {
  366. id Int @id @default(autoincrement())
  367. callType String @db.VarChar(20) // tts_create | tts_poll | tts_download | llm_chat | llm_tools
  368. provider String @db.VarChar(30) // minimax | bailian | volcengine
  369. model String @db.VarChar(50) // speech-2.8-hd | qwen3-tts-instruct-flash | MiniMax-M2.7
  370. textLen Int @default(0) // 输入文本长度
  371. prompt String? @db.LongText // 提示词内容
  372. duration Int @default(0) // 耗时(ms)
  373. success Boolean @default(true)
  374. errorMsg String? @db.VarChar(200)
  375. bookId Int?
  376. chapterId Int?
  377. createdAt DateTime @default(now())
  378. @@index([callType, createdAt])
  379. @@index([provider, createdAt])
  380. @@index([bookId])
  381. }
  382. model PlatformAccount {
  383. id Int @id @default(autoincrement())
  384. userId Int
  385. platform String
  386. nickname String @default("")
  387. avatar String @default("")
  388. cookies String @db.Text
  389. headers String? @db.Text
  390. isValid Boolean @default(true)
  391. expireTime DateTime?
  392. createdAt DateTime @default(now())
  393. updatedAt DateTime @updatedAt
  394. @@unique([userId, platform])
  395. @@index([userId])
  396. @@index([platform])
  397. }
  398. model PublishTask {
  399. id Int @id @default(autoincrement())
  400. userId Int
  401. videoProjectId Int
  402. platform String
  403. title String @db.Text
  404. description String? @db.Text
  405. tags String? @db.Text
  406. coverUrl String? @db.Text
  407. videoUrl String? @db.Text
  408. status String @default("pending")
  409. errorMsg String? @db.Text
  410. publishedUrl String? @db.Text
  411. createdAt DateTime @default(now())
  412. updatedAt DateTime @updatedAt
  413. @@index([userId, platform])
  414. @@index([status])
  415. }
  416. model Draft {
  417. id Int @id @default(autoincrement())
  418. userId Int
  419. type String
  420. title String? @db.Text
  421. content String? @db.LongText
  422. metadata String? @db.Text
  423. autoSavedAt DateTime?
  424. createdAt DateTime @default(now())
  425. updatedAt DateTime @updatedAt
  426. user User @relation(fields: [userId], references: [id])
  427. @@index([userId, type])
  428. @@index([userId, updatedAt])
  429. }
  430. model Playlist {
  431. id Int @id @default(autoincrement())
  432. userId Int
  433. name String
  434. description String? @db.Text
  435. createdAt DateTime @default(now())
  436. updatedAt DateTime @updatedAt
  437. user User @relation(fields: [userId], references: [id])
  438. items PlaylistItem[]
  439. @@index([userId])
  440. }
  441. model PlaylistItem {
  442. id Int @id @default(autoincrement())
  443. playlistId Int
  444. chapterId Int?
  445. audioId String?
  446. order Int @default(0)
  447. chapter BookChapter? @relation(fields: [chapterId], references: [id])
  448. playlist Playlist @relation(fields: [playlistId], references: [id], onDelete: Cascade)
  449. @@index([playlistId, order])
  450. @@index([chapterId], map: "PlaylistItem_chapterId_fkey")
  451. }
  452. model Feedback {
  453. id String @id @default(uuid())
  454. type String
  455. title String @db.Text
  456. content String @db.Text
  457. contact String @db.Text
  458. screenshotUrls String @db.Text
  459. status String @default("submitted")
  460. createdAt DateTime @default(now())
  461. updatedAt DateTime @updatedAt
  462. @@index([type])
  463. @@index([status])
  464. @@index([createdAt])
  465. }