paper-burner/server/prisma/schema.prisma

387 lines
9.7 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Prisma Schema for Paper Burner X
// 支持多租户系统、历史记录持久化、模型配置管理
generator client {
provider = "prisma-client-js"
binaryTargets = ["native", "linux-musl-openssl-3.0.x"]
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
// ==================== 用户与认证 ====================
model User {
id String @id @default(uuid())
email String @unique
password String // bcrypt 加密
name String?
role Role @default(USER)
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// 关联
settings UserSettings?
documents Document[]
apiKeys ApiKey[]
glossaries Glossary[]
annotations Annotation[]
processedFiles ProcessedFile[]
quota UserQuota?
chatMessages ChatMessage[]
references Reference[]
promptPool PromptPool?
@@index([email])
@@map("users")
}
enum Role {
USER
ADMIN
}
// ==================== 用户设置 ====================
model UserSettings {
id String @id @default(uuid())
userId String @unique
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
// OCR 设置
ocrProvider String? // 'mineru' | 'doc2x'
ocrApiKey String? @db.Text
// 翻译设置
translationModel String? // 'deepseek' | 'gemini' | 'claude' | 'custom'
targetLanguage String @default("chinese")
customTargetLanguageName String?
maxTokensPerChunk Int @default(2000)
translationConcurrency Int @default(15)
// 提示词设置
defaultSystemPrompt String? @db.Text
defaultUserPromptTemplate String? @db.Text
useCustomPrompts Boolean @default(false)
// 其他设置
enableGlossary Boolean @default(false)
batchModeEnabled Boolean @default(false)
batchModeTemplate String?
batchModeFormats String[] // ['original', 'markdown', 'pdf']
batchModeZipEnabled Boolean @default(false)
// 扩展配置JSON 字段)
ocrConfig Json? // OCR 引擎和详细配置
academicSearchConfig Json? // 学术搜索配置
uiLayoutConfig Json? // UI 布局配置
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("user_settings")
}
// ==================== API Keys 管理 ====================
model ApiKey {
id String @id @default(uuid())
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
provider String // 'mistral' | 'deepseek' | 'gemini' | 'claude' | 'tongyi' | 'volcano' | 'custom_source_xxx'
keyValue String @db.Text // 加密存储
remark String?
status KeyStatus @default(UNTESTED)
order Int @default(0)
lastUsedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([userId, provider])
@@map("api_keys")
}
enum KeyStatus {
UNTESTED
VALID
INVALID
TESTING
}
// ==================== 自定义模型源站配置 ====================
model CustomSourceSite {
id String @id @default(uuid())
userId String? // null = 管理员全局配置
displayName String
apiBaseUrl String
modelId String?
availableModels String[] // JSON array
requestFormat String @default("openai") // 'openai' | 'anthropic' | 'custom'
temperature Float @default(0.5)
maxTokens Int @default(8000)
endpointMode String @default("auto")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([userId])
@@map("custom_source_sites")
}
// ==================== 文档处理历史 ====================
model Document {
id String @id @default(uuid())
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
// 基本信息
fileName String
fileSize Int?
fileType String
filePath String? // 如果启用文件上传存储
// 处理状态
status DocStatus @default(PENDING)
// OCR 结果
ocrProvider String?
ocrText String? @db.Text
ocrMetadata Json?
// 翻译结果
translationModel String?
translatedText String? @db.Text
translationMetadata Json?
// 其他数据
summary String? @db.Text
toc Json? // Table of Contents
metadata Json? // 其他元数据
processingTime Int? // 处理时间(毫秒)
errorMessage String? @db.Text
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// 关联
annotations Annotation[]
semanticGroups SemanticGroup[]
chatMessages ChatMessage[]
references Reference[]
@@index([userId, createdAt])
@@index([status])
@@map("documents")
}
enum DocStatus {
PENDING
PROCESSING
OCR_COMPLETED
TRANSLATION_COMPLETED
COMPLETED
FAILED
}
// ==================== 高亮与标注 ====================
model Annotation {
id String @id @default(uuid())
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
documentId String
document Document @relation(fields: [documentId], references: [id], onDelete: Cascade)
type String // 'highlight' | 'note'
color String?
startIndex Int
endIndex Int
text String @db.Text
note String? @db.Text
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([documentId])
@@index([userId])
@@map("annotations")
}
// ==================== 意群数据 ====================
model SemanticGroup {
id String @id @default(uuid())
documentId String
document Document @relation(fields: [documentId], references: [id], onDelete: Cascade)
groups Json // 存储意群数组
version String?
source String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([documentId])
@@map("semantic_groups")
}
// ==================== 翻译术语库 ====================
model Glossary {
id String @id @default(uuid())
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
name String
enabled Boolean @default(true)
entries Json // 存储术语条目数组
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([userId])
@@map("glossaries")
}
// ==================== 系统配置(管理员)====================
model SystemConfig {
id String @id @default(uuid())
key String @unique
value String @db.Text
description String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("system_config")
}
// ==================== 已处理文件记录 ====================
model ProcessedFile {
id String @id @default(uuid())
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
fileIdentifier String // 文件标识符 (name + size + lastModified)
fileName String
processedAt DateTime @default(now())
@@unique([userId, fileIdentifier])
@@index([userId])
@@map("processed_files")
}
// ==================== 用户配额管理 ====================
model UserQuota {
id String @id @default(uuid())
userId String @unique
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
// 配额限制 (-1 表示无限制)
maxDocumentsPerDay Int @default(-1)
maxDocumentsPerMonth Int @default(-1)
maxStorageSize Int @default(-1) // MB
maxApiKeysCount Int @default(-1)
// 当前使用量
documentsThisMonth Int @default(0)
currentStorageUsed Int @default(0) // MB
// 重置时间
lastMonthlyReset DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("user_quotas")
}
// ==================== 使用量日志 ====================
model UsageLog {
id String @id @default(uuid())
userId String
action String // 'ocr', 'translate', 'document_create', etc.
resourceId String? // 关联的资源ID如文档ID
metadata Json? // 额外元数据
createdAt DateTime @default(now())
@@index([userId, createdAt])
@@index([action, createdAt])
@@map("usage_logs")
}
// ==================== 聊天消息 ====================
model ChatMessage {
id String @id @default(uuid())
documentId String
document Document @relation(fields: [documentId], references: [id], onDelete: Cascade)
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
role String // 'user' | 'assistant'
content String @db.Text
timestamp DateTime @default(now())
metadata Json? // 扩展信息模型、token 等)
@@index([documentId, timestamp])
@@map("chat_messages")
}
// ==================== 文献引用 ====================
model Reference {
id String @id @default(uuid())
documentId String
document Document @relation(fields: [documentId], references: [id], onDelete: Cascade)
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
citationKey String // 引用标识符(如 "[1]"
doi String?
title String?
authors Json? // [{name, affiliation}]
year Int?
journal String?
volume String?
pages String?
url String?
metadata Json? // 完整元数据
createdAt DateTime @default(now())
@@unique([documentId, citationKey])
@@index([documentId])
@@map("references")
}
// ==================== 提示词池 ====================
model PromptPool {
id String @id @default(uuid())
userId String @unique
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
prompts Json // 提示词数组
healthConfig Json? // 健康检查配置
updatedAt DateTime @default(now()) @updatedAt
@@map("prompt_pool")
}