286 lines
10 KiB
Plaintext
286 lines
10 KiB
Plaintext
// This is your Prisma schema file,
|
||
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
||
|
||
// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
|
||
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
|
||
|
||
generator client {
|
||
provider = "prisma-client-js"
|
||
}
|
||
|
||
datasource db {
|
||
provider = "postgresql"
|
||
url = env("DATABASE_URL")
|
||
}
|
||
|
||
model User {
|
||
id String @id // 使用Supabase用户ID,不再自动生成
|
||
email String @unique
|
||
username String? @unique // 允许为空,因为有些用户可能没有设置用户名
|
||
avatar String?
|
||
bio String?
|
||
language String @default("en")
|
||
isAdmin Boolean @default(false) // 管理员标记
|
||
versionLimit Int @default(3) // 用户自定义版本数量限制,不能超过套餐限制
|
||
|
||
// 新的订阅系统字段
|
||
subscriptionPlanId String @default("free") // 关联的订阅套餐ID
|
||
|
||
// 旧的订阅系统字段(保留用于迁移,后期会移除)
|
||
subscribePlan String @default("free") // 订阅计划: "free", "pro"
|
||
maxVersionLimit Int @default(3) // 基于订阅的最大版本限制
|
||
promptLimit Int? // 提示词数量限制(已弃用,忽略此字段)
|
||
creditBalance Float @default(0.0) // 信用余额,移除默认值
|
||
|
||
stripeCustomerId String? @unique // Stripe 客户 ID
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
// 关联关系
|
||
subscriptionPlan SubscriptionPlan @relation(fields: [subscriptionPlanId], references: [id])
|
||
prompts Prompt[]
|
||
credits Credit[]
|
||
subscriptions Subscription[]
|
||
simulatorRuns SimulatorRun[]
|
||
|
||
@@map("users")
|
||
}
|
||
|
||
// 订阅套餐模型
|
||
model SubscriptionPlan {
|
||
id String @id // "free", "pro" 等
|
||
name String // 套餐名称
|
||
displayName String // 显示名称(支持国际化)
|
||
description String? // 套餐描述
|
||
price Float @default(0) // 价格(美元)
|
||
currency String @default("usd") // 货币
|
||
interval String @default("month") // 计费周期: "month", "year"
|
||
stripePriceId String? @unique // Stripe 价格 ID
|
||
isActive Boolean @default(true) // 是否激活
|
||
sortOrder Int @default(0) // 排序顺序
|
||
|
||
// 权益配置 (JSON 格式存储)
|
||
features Json // 功能特性配置
|
||
limits Json // 限制配置
|
||
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
// 关联关系
|
||
users User[]
|
||
subscriptions Subscription[]
|
||
models Model[]
|
||
|
||
@@map("subscription_plans")
|
||
}
|
||
|
||
model Prompt {
|
||
id String @id @default(cuid())
|
||
name String
|
||
content String
|
||
description String?
|
||
isPublic Boolean @default(false) // 保留用于向后兼容
|
||
permissions String @default("private") // "private" | "public"
|
||
visibility String? // "under_review" | "published" | null
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
userId String
|
||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||
tags PromptTag[]
|
||
versions PromptVersion[]
|
||
album PromptAlbum? @relation(fields: [albumId], references: [id])
|
||
albumId String?
|
||
tests PromptTestRun[]
|
||
stats PromptStats?
|
||
simulatorRuns SimulatorRun[]
|
||
|
||
@@map("prompts")
|
||
}
|
||
|
||
model PromptVersion {
|
||
id String @id @default(cuid())
|
||
version Int
|
||
content String
|
||
changelog String?
|
||
createdAt DateTime @default(now())
|
||
|
||
promptId String
|
||
prompt Prompt @relation(fields: [promptId], references: [id], onDelete: Cascade)
|
||
simulatorRuns SimulatorRun[]
|
||
|
||
@@unique([promptId, version])
|
||
@@map("prompt_versions")
|
||
}
|
||
|
||
model PromptTag {
|
||
id String @id @default(cuid())
|
||
name String @unique
|
||
color String @default("#3B82F6")
|
||
|
||
prompts Prompt[]
|
||
|
||
@@map("prompt_tags")
|
||
}
|
||
|
||
model PromptAlbum {
|
||
id String @id @default(cuid())
|
||
name String
|
||
description String?
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
prompts Prompt[]
|
||
|
||
@@map("prompt_albums")
|
||
}
|
||
|
||
model PromptTestRun {
|
||
id String @id @default(cuid())
|
||
input String
|
||
output String?
|
||
success Boolean @default(false)
|
||
error String?
|
||
createdAt DateTime @default(now())
|
||
|
||
promptId String
|
||
prompt Prompt @relation(fields: [promptId], references: [id], onDelete: Cascade)
|
||
|
||
@@map("prompt_test_runs")
|
||
}
|
||
|
||
model PromptStats {
|
||
id String @id @default(cuid())
|
||
promptId String @unique
|
||
viewCount Int @default(0) // 浏览计数
|
||
likeCount Int @default(0) // 点赞计数
|
||
rating Float? // 平均评分
|
||
ratingCount Int @default(0) // 评分数量
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
prompt Prompt @relation(fields: [promptId], references: [id], onDelete: Cascade)
|
||
|
||
@@map("prompt_stats")
|
||
}
|
||
|
||
model Credit {
|
||
id String @id @default(cuid())
|
||
userId String
|
||
amount Float // 交易金额(正数为充值,负数为消费)
|
||
balance Float @default(5) // 执行该交易后的余额
|
||
type String // "system_gift", "subscription_monthly", "user_purchase", "consumption"
|
||
category String? // 消费类别: "simulation", "api_call", "export" 等
|
||
note String? // 备注说明
|
||
referenceId String? // 关联的记录ID(如SimulatorRun的ID)
|
||
referenceType String? // 关联记录类型(如"simulator_run")
|
||
expiresAt DateTime? // 过期时间,null表示永久有效
|
||
isActive Boolean @default(true) // 是否激活状态
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||
|
||
@@map("credits")
|
||
}
|
||
|
||
// 订阅记录模型
|
||
model Subscription {
|
||
id String @id @default(cuid())
|
||
userId String // 用户 ID
|
||
subscriptionPlanId String // 订阅套餐 ID
|
||
stripeSubscriptionId String? @unique // Stripe 订阅 ID
|
||
stripeCustomerId String? // Stripe 客户 ID(冗余存储,便于查询)
|
||
|
||
// 订阅状态和时间
|
||
isActive Boolean @default(false) // 是否有效
|
||
startDate DateTime? // 开始时间(订阅激活时设置)
|
||
endDate DateTime? // 结束时间(订阅激活时设置)
|
||
|
||
// 订阅状态
|
||
status String @default("pending") // "pending", "active", "canceled", "expired", "failed"
|
||
|
||
// 元数据
|
||
metadata Json? // 额外的元数据(如 Stripe 的原始数据)
|
||
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
// 关联关系
|
||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||
subscriptionPlan SubscriptionPlan @relation(fields: [subscriptionPlanId], references: [id])
|
||
|
||
@@map("subscriptions")
|
||
}
|
||
|
||
// AI 模型配置表 - 每个模型记录直接关联一个套餐
|
||
model Model {
|
||
id String @id @default(cuid())
|
||
subscriptionPlanId String // 关联的套餐 ID
|
||
modelId String // OpenRouter 的模型 ID,如 "openai/gpt-4"
|
||
name String // 显示名称,如 "GPT-4"
|
||
provider String // 提供商,如 "OpenAI"
|
||
serviceProvider String @default("openrouter") // 服务提供者,如 "openrouter", "replicate"
|
||
outputType String @default("text") // 输出类型,如 "text", "image", "video", "audio"
|
||
description String? // 模型描述
|
||
maxTokens Int? // 最大 token 数
|
||
inputCostPer1k Float? // 输入成本(每1K tokens)
|
||
outputCostPer1k Float? // 输出成本(每1K tokens)
|
||
supportedFeatures Json? // 支持的特性(如 function_calling, vision 等)
|
||
metadata Json? // 其他元数据
|
||
customLimits Json? // 自定义限制(如每日调用次数、最大 tokens 等)
|
||
isActive Boolean @default(true) // 是否启用
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
// 关联关系
|
||
subscriptionPlan SubscriptionPlan @relation(fields: [subscriptionPlanId], references: [id], onDelete: Cascade)
|
||
|
||
// 关联关系
|
||
simulatorRuns SimulatorRun[]
|
||
|
||
// 同一个套餐内不能有相同的模型ID
|
||
@@unique([subscriptionPlanId, modelId])
|
||
@@map("models")
|
||
}
|
||
|
||
// 模拟器运行记录
|
||
model SimulatorRun {
|
||
id String @id @default(cuid())
|
||
userId String
|
||
name String @default("Simulation Run") // 运行名称
|
||
promptId String
|
||
promptVersionId String? // 可选,如果选择了特定版本
|
||
modelId String
|
||
userInput String // 用户输入内容
|
||
promptContent String? // 自定义提示词内容(如果用户修改了原提示词)
|
||
output String? // AI响应输出
|
||
error String? // 错误信息
|
||
status String @default("pending") // "pending", "running", "completed", "failed"
|
||
|
||
// 运行配置
|
||
temperature Float? @default(0.7)
|
||
maxTokens Int?
|
||
topP Float?
|
||
frequencyPenalty Float?
|
||
presencePenalty Float?
|
||
|
||
// 消耗和统计
|
||
inputTokens Int? // 输入token数
|
||
outputTokens Int? // 输出token数
|
||
totalCost Float? // 总消费
|
||
duration Int? // 运行时长(毫秒)
|
||
creditId String? // 关联的信用消费记录ID
|
||
|
||
createdAt DateTime @default(now())
|
||
completedAt DateTime?
|
||
|
||
// 关联关系
|
||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||
prompt Prompt @relation(fields: [promptId], references: [id], onDelete: Cascade)
|
||
promptVersion PromptVersion? @relation(fields: [promptVersionId], references: [id], onDelete: SetNull)
|
||
model Model @relation(fields: [modelId], references: [id])
|
||
|
||
@@map("simulator_runs")
|
||
}
|