schema.prisma 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. // DoTouch.AI - Prisma Schema
  2. // PostgreSQL 16 datasource, client generated via `pnpm db:generate`
  3. generator client {
  4. provider = "prisma-client-js"
  5. }
  6. datasource db {
  7. provider = "postgresql"
  8. url = env("DATABASE_URL")
  9. }
  10. // ---- 用户 ----
  11. model User {
  12. id String @id @default(cuid())
  13. email String @unique
  14. passwordHash String @map("password_hash")
  15. // 社交登录:provider = local | google | facebook;providerId 为平台唯一 ID(同邮箱绑定后记录)
  16. provider String @default("local")
  17. providerId String? @unique @map("provider_id")
  18. role String @default("user") // user | admin
  19. currency String @default("USD")
  20. balanceCents BigInt @default(0) @map("balance_cents")
  21. status String @default("active") // active | suspended | banned
  22. createdAt DateTime @default(now()) @map("created_at")
  23. updatedAt DateTime @updatedAt @map("updated_at")
  24. // 用量配额(null = 不限)
  25. dailyRequestLimit Int? @map("daily_request_limit")
  26. dailyTokenLimit BigInt? @map("daily_token_limit")
  27. dailyCostCentsLimit Int? @map("daily_cost_cents_limit")
  28. totalRequestLimit Int? @map("total_request_limit")
  29. totalTokenLimit BigInt? @map("total_token_limit")
  30. totalCostCentsLimit Int? @map("total_cost_cents_limit")
  31. alertPct Int @default(80) @map("alert_pct")
  32. apiKeys ApiKey[]
  33. balanceTransactions BalanceTransaction[]
  34. usageRecords UsageRecord[]
  35. orders Order[]
  36. @@map("users")
  37. }
  38. // ---- API 密钥 ----
  39. model ApiKey {
  40. id String @id @default(cuid())
  41. userId String @map("user_id")
  42. name String
  43. keyHash String @unique @map("key_hash")
  44. prefix String // 前 12 位用于展示(dt_ + 32 hex = 36 chars)
  45. expiresAt DateTime? @map("expires_at")
  46. lastUsedAt DateTime? @map("last_used_at")
  47. status String @default("active") // active | revoked
  48. createdAt DateTime @default(now()) @map("created_at")
  49. updatedAt DateTime @updatedAt @map("updated_at")
  50. // 用量配额(null = 不限)
  51. dailyRequestLimit Int? @map("daily_request_limit")
  52. dailyTokenLimit BigInt? @map("daily_token_limit")
  53. dailyCostCentsLimit Int? @map("daily_cost_cents_limit")
  54. totalRequestLimit Int? @map("total_request_limit")
  55. totalTokenLimit BigInt? @map("total_token_limit")
  56. totalCostCentsLimit Int? @map("total_cost_cents_limit")
  57. alertPct Int @default(80) @map("alert_pct")
  58. user User @relation(fields: [userId], references: [id])
  59. usageRecords UsageRecord[]
  60. events ApiKeyEvent[]
  61. @@map("api_keys")
  62. }
  63. // ---- API Key 事件审计日志 ----
  64. model ApiKeyEvent {
  65. id String @id @default(cuid())
  66. apiKeyId String @map("api_key_id")
  67. userId String @map("user_id")
  68. action String // created | rotated | revoked | used
  69. ip String?
  70. createdAt DateTime @default(now()) @map("created_at")
  71. apiKey ApiKey @relation(fields: [apiKeyId], references: [id])
  72. @@map("api_key_events")
  73. }
  74. // ---- 模型目录(DB-backed) ----
  75. model ModelCatalog {
  76. id String @id @default(cuid())
  77. publicId String @unique @map("public_id")
  78. upstreamId String @map("upstream_id")
  79. name String
  80. provider String // Zhipu | DeepSeek | Alibaba | MiniMax | Kimi | SiliconFlow | Other
  81. category String // chat | vision | image | speech
  82. description String?
  83. contextWindow Int? @map("context_window")
  84. maxOutput Int? @map("max_output")
  85. inputPriceCents Int @default(0) @map("input_price_cents")
  86. outputPriceCents Int @default(0) @map("output_price_cents")
  87. isRecommended Boolean @default(false) @map("is_recommended")
  88. status String @default("active") // active | hidden | disabled
  89. sortOrder Int @default(0) @map("sort_order")
  90. createdAt DateTime @default(now()) @map("created_at")
  91. updatedAt DateTime @updatedAt @map("updated_at")
  92. @@map("models")
  93. }
  94. // ---- 余额变动记录 ----
  95. model BalanceTransaction {
  96. id String @id @default(cuid())
  97. userId String @map("user_id")
  98. amountCents BigInt @map("amount_cents")
  99. type String // topup | charge | refund | usage | refund
  100. refId String? @map("ref_id")
  101. createdAt DateTime @default(now()) @map("created_at")
  102. user User @relation(fields: [userId], references: [id])
  103. @@map("balance_transactions")
  104. }
  105. // ---- 用量记录 ----
  106. model UsageRecord {
  107. id String @id @default(cuid())
  108. userId String @map("user_id")
  109. apiKeyId String @map("api_key_id")
  110. model String
  111. promptTokens Int @map("prompt_tokens")
  112. completionTokens Int @map("completion_tokens")
  113. costCents Int @map("cost_cents")
  114. createdAt DateTime @default(now()) @map("created_at")
  115. user User @relation(fields: [userId], references: [id])
  116. apiKey ApiKey @relation(fields: [apiKeyId], references: [id])
  117. @@map("usage_records")
  118. }
  119. // ---- 配额事件(预警 + 超限审计) ----
  120. model QuotaEvent {
  121. id String @id @default(cuid())
  122. userId String @map("user_id")
  123. apiKeyId String? @map("api_key_id")
  124. dimension String // request | token | cost
  125. windowType String @map("window_type") // daily | total
  126. scopeType String @map("scope_type") // account | key
  127. threshold Int
  128. current BigInt
  129. action String // alert | block
  130. createdAt DateTime @default(now()) @map("created_at")
  131. @@map("quota_events")
  132. }
  133. // ---- 订单 ----
  134. model Order {
  135. id String @id @default(cuid())
  136. userId String @map("user_id")
  137. provider String // alipay | stripe | ...
  138. providerOrderId String? @map("provider_order_id")
  139. amountCents BigInt @map("amount_cents")
  140. status String @default("pending") // pending | paid | failed | refunded
  141. currency String @default("USD")
  142. paidAt DateTime? @map("paid_at")
  143. createdAt DateTime @default(now()) @map("created_at")
  144. updatedAt DateTime @updatedAt @map("updated_at")
  145. user User @relation(fields: [userId], references: [id])
  146. @@map("orders")
  147. }