// DoTouch.AI - Prisma Schema // PostgreSQL 16 datasource, client generated via `pnpm db:generate` generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } // ---- 用户 ---- model User { id String @id @default(cuid()) email String @unique passwordHash String @map("password_hash") // 社交登录:provider = local | google | facebook;providerId 为平台唯一 ID(同邮箱绑定后记录) provider String @default("local") providerId String? @unique @map("provider_id") // 邀请奖励:唯一邀请码 + 被谁邀请 referralCode String? @unique @map("referral_code") referredById String? @map("referred_by_id") referredBy User? @relation("Referrals", fields: [referredById], references: [id]) referrals User[] @relation("Referrals") referralRecords ReferralRecord[] @relation("RecordsAsReferrer") referredRecords ReferralRecord[] referralRewards ReferralReward[] role String @default("user") // user | admin currency String @default("USD") balanceCents BigInt @default(0) @map("balance_cents") status String @default("active") // active | suspended | banned createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") // 用量配额(null = 不限) dailyRequestLimit Int? @map("daily_request_limit") dailyTokenLimit BigInt? @map("daily_token_limit") dailyCostCentsLimit Int? @map("daily_cost_cents_limit") totalRequestLimit Int? @map("total_request_limit") totalTokenLimit BigInt? @map("total_token_limit") totalCostCentsLimit Int? @map("total_cost_cents_limit") alertPct Int @default(80) @map("alert_pct") apiKeys ApiKey[] balanceTransactions BalanceTransaction[] usageRecords UsageRecord[] orders Order[] @@map("users") } // ---- API 密钥 ---- model ApiKey { id String @id @default(cuid()) userId String @map("user_id") name String keyHash String @unique @map("key_hash") prefix String // 前 12 位用于展示(dt_ + 32 hex = 36 chars) expiresAt DateTime? @map("expires_at") lastUsedAt DateTime? @map("last_used_at") status String @default("active") // active | revoked createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") // 用量配额(null = 不限) dailyRequestLimit Int? @map("daily_request_limit") dailyTokenLimit BigInt? @map("daily_token_limit") dailyCostCentsLimit Int? @map("daily_cost_cents_limit") totalRequestLimit Int? @map("total_request_limit") totalTokenLimit BigInt? @map("total_token_limit") totalCostCentsLimit Int? @map("total_cost_cents_limit") alertPct Int @default(80) @map("alert_pct") user User @relation(fields: [userId], references: [id]) usageRecords UsageRecord[] events ApiKeyEvent[] @@map("api_keys") } // ---- API Key 事件审计日志 ---- model ApiKeyEvent { id String @id @default(cuid()) apiKeyId String @map("api_key_id") userId String @map("user_id") action String // created | rotated | revoked | used ip String? createdAt DateTime @default(now()) @map("created_at") apiKey ApiKey @relation(fields: [apiKeyId], references: [id]) @@map("api_key_events") } // ---- 模型目录(DB-backed) ---- model ModelCatalog { id String @id @default(cuid()) publicId String @unique @map("public_id") upstreamId String @map("upstream_id") name String provider String // Zhipu | DeepSeek | Alibaba | MiniMax | Kimi | SiliconFlow | Other category String // chat | vision | image | speech description String? contextWindow Int? @map("context_window") maxOutput Int? @map("max_output") inputPriceCents Int @default(0) @map("input_price_cents") outputPriceCents Int @default(0) @map("output_price_cents") isRecommended Boolean @default(false) @map("is_recommended") status String @default("active") // active | hidden | disabled sortOrder Int @default(0) @map("sort_order") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@map("models") } // ---- 余额变动记录 ---- model BalanceTransaction { id String @id @default(cuid()) userId String @map("user_id") amountCents BigInt @map("amount_cents") type String // topup | charge | refund | usage | refund refId String? @map("ref_id") createdAt DateTime @default(now()) @map("created_at") user User @relation(fields: [userId], references: [id]) @@map("balance_transactions") } // ---- 用量记录 ---- model UsageRecord { id String @id @default(cuid()) userId String @map("user_id") apiKeyId String @map("api_key_id") model String promptTokens Int @map("prompt_tokens") completionTokens Int @map("completion_tokens") costCents Int @map("cost_cents") createdAt DateTime @default(now()) @map("created_at") user User @relation(fields: [userId], references: [id]) apiKey ApiKey @relation(fields: [apiKeyId], references: [id]) @@map("usage_records") } // ---- 配额事件(预警 + 超限审计) ---- model QuotaEvent { id String @id @default(cuid()) userId String @map("user_id") apiKeyId String? @map("api_key_id") dimension String // request | token | cost windowType String @map("window_type") // daily | total scopeType String @map("scope_type") // account | key threshold Int current BigInt action String // alert | block createdAt DateTime @default(now()) @map("created_at") @@map("quota_events") } // ---- 订单 ---- model Order { id String @id @default(cuid()) userId String @map("user_id") provider String // alipay | stripe | ... providerOrderId String? @map("provider_order_id") amountCents BigInt @map("amount_cents") status String @default("pending") // pending | paid | failed | refunded currency String @default("USD") paidAt DateTime? @map("paid_at") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") user User @relation(fields: [userId], references: [id]) @@map("orders") } // 邀请记录:每对被邀请关系一条 model ReferralRecord { id String @id @default(cuid()) referrerId String @map("referrer_id") refereeId String @map("referee_id") refereeEmail String @map("referee_email") status String @default("registered") // registered | paid | rewarded registerAt DateTime @default(now()) @map("register_at") firstPaidAt DateTime? @map("first_paid_at") firstPaidCents BigInt? @map("first_paid_cents") createdAt DateTime @default(now()) @map("created_at") referrer User @relation("RecordsAsReferrer", fields: [referrerId], references: [id]) referee User @relation(fields: [refereeId], references: [id]) rewards ReferralReward[] @@map("referral_records") } // 奖励记录:注册奖励 / 被邀请人首充奖励 / 邀请人付费奖励 model ReferralReward { id String @id @default(cuid()) userId String @map("user_id") recordId String @map("record_id") type String // register | referee_first_pay | referrer_pay amountCents BigInt @map("amount_cents") status String @default("credited") // pending | credited createdAt DateTime @default(now()) @map("created_at") user User @relation(fields: [userId], references: [id]) record ReferralRecord @relation(fields: [recordId], references: [id]) @@map("referral_rewards") } // 系统配置(邀请奖励策略等,管理后台可调) model SystemConfig { id String @id @default(cuid()) key String @unique value String updatedAt DateTime @updatedAt @map("updated_at") @@map("system_configs") }