// This is your Prisma schema file, // learn more about it in the docs: https://pris.ly/d/prisma-schema generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") schemas = ["platform_schema", "aia_schema", "pkb_schema", "asl_schema", "common_schema", "dc_schema", "rvw_schema", "admin_schema", "ssa_schema", "st_schema", "public"] } // ==================== 用户模块 ==================== model User { id String @id @default(uuid()) email String @unique password String name String? avatarUrl String? @map("avatar_url") role String @default("user") status String @default("active") kbQuota Int @default(3) @map("kb_quota") kbUsed Int @default(0) @map("kb_used") trialEndsAt DateTime? @map("trial_ends_at") isTrial Boolean @default(true) @map("is_trial") lastLoginAt DateTime? @map("last_login_at") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") projects Project[] conversations Conversation[] knowledgeBases KnowledgeBase[] documents Document[] adminLogs AdminLog[] generalConversations GeneralConversation[] batchTasks BatchTask[] // Phase 3: 批处理任务 taskTemplates TaskTemplate[] // Phase 3: 任务模板 reviewTasks ReviewTask[] // 稿件审查任务 @@index([email]) @@index([status]) @@index([createdAt]) @@map("users") @@schema("platform_schema") } // ==================== 项目模块 ==================== model Project { id String @id @default(uuid()) userId String @map("user_id") name String background String @default("") @db.Text researchType String @default("observational") @map("research_type") conversationCount Int @default(0) @map("conversation_count") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") deletedAt DateTime? @map("deleted_at") user User @relation(fields: [userId], references: [id], onDelete: Cascade) conversations Conversation[] @@index([userId]) @@index([createdAt]) @@index([deletedAt]) @@map("projects") @@schema("aia_schema") } // ==================== 对话模块 ==================== model Conversation { id String @id @default(uuid()) userId String @map("user_id") projectId String? @map("project_id") agentId String @map("agent_id") title String modelName String @default("deepseek-v3") @map("model_name") messageCount Int @default(0) @map("message_count") totalTokens Int @default(0) @map("total_tokens") metadata Json? createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") deletedAt DateTime? @map("deleted_at") user User @relation(fields: [userId], references: [id], onDelete: Cascade) project Project? @relation(fields: [projectId], references: [id], onDelete: Cascade) messages Message[] @@index([userId]) @@index([projectId]) @@index([agentId]) @@index([createdAt]) @@index([deletedAt]) @@map("conversations") @@schema("aia_schema") } model Message { id String @id @default(uuid()) conversationId String @map("conversation_id") role String content String @db.Text model String? metadata Json? tokens Int? isPinned Boolean @default(false) @map("is_pinned") createdAt DateTime @default(now()) @map("created_at") conversation Conversation @relation(fields: [conversationId], references: [id], onDelete: Cascade) @@index([conversationId]) @@index([createdAt]) @@index([isPinned]) @@map("messages") @@schema("aia_schema") } // ==================== 知识库模块 ==================== model KnowledgeBase { id String @id @default(uuid()) userId String @map("user_id") name String description String? difyDatasetId String @map("dify_dataset_id") fileCount Int @default(0) @map("file_count") totalSizeBytes BigInt @default(0) @map("total_size_bytes") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") user User @relation(fields: [userId], references: [id], onDelete: Cascade) documents Document[] batchTasks BatchTask[] // Phase 3: 批处理任务 @@index([userId]) @@index([difyDatasetId]) @@map("knowledge_bases") @@schema("pkb_schema") } model Document { id String @id @default(uuid()) kbId String @map("kb_id") userId String @map("user_id") filename String fileType String @map("file_type") fileSizeBytes BigInt @map("file_size_bytes") fileUrl String @map("file_url") difyDocumentId String @map("dify_document_id") status String @default("uploading") progress Int @default(0) errorMessage String? @map("error_message") segmentsCount Int? @map("segments_count") tokensCount Int? @map("tokens_count") // Phase 2: 全文阅读模式新增字段 extractionMethod String? @map("extraction_method") // pymupdf/nougat/mammoth/direct extractionQuality Float? @map("extraction_quality") // 0-1质量分数 charCount Int? @map("char_count") // 字符数 language String? // 检测到的语言 (chinese/english) extractedText String? @map("extracted_text") @db.Text // 提取的文本内容 uploadedAt DateTime @default(now()) @map("uploaded_at") processedAt DateTime? @map("processed_at") knowledgeBase KnowledgeBase @relation(fields: [kbId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade) batchResults BatchResult[] // Phase 3: 批处理结果 @@index([kbId]) @@index([userId]) @@index([status]) @@index([difyDocumentId]) @@index([extractionMethod]) @@map("documents") @@schema("pkb_schema") } // ==================== Phase 3: 批处理模块 ==================== // 批处理任务 model BatchTask { id String @id @default(uuid()) userId String @map("user_id") kbId String @map("kb_id") // 任务基本信息 name String // 任务名称(用户可自定义) templateType String @map("template_type") // 'preset' | 'custom' templateId String? @map("template_id") // 预设模板ID(如'clinical_research') prompt String @db.Text // 提示词(完整的) // 执行状态 status String // 'processing' | 'completed' | 'failed' | 'paused' totalDocuments Int @map("total_documents") completedCount Int @default(0) @map("completed_count") failedCount Int @default(0) @map("failed_count") // 配置 modelType String @map("model_type") // 使用的模型 concurrency Int @default(3) // 固定为3 // 时间统计 startedAt DateTime? @map("started_at") completedAt DateTime? @map("completed_at") durationSeconds Int? @map("duration_seconds") // 执行时长(秒) // 关联 results BatchResult[] user User @relation(fields: [userId], references: [id], onDelete: Cascade) knowledgeBase KnowledgeBase @relation(fields: [kbId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@index([userId]) @@index([kbId]) @@index([status]) @@index([createdAt]) @@map("batch_tasks") @@schema("pkb_schema") } // 批处理结果(每篇文献一条) model BatchResult { id String @id @default(uuid()) taskId String @map("task_id") documentId String @map("document_id") // 执行结果 status String // 'success' | 'failed' data Json? // 提取的结构化数据(预设模板)或文本(自定义) rawOutput String? @db.Text @map("raw_output") // AI原始输出(备份) errorMessage String? @db.Text @map("error_message") // 错误信息 // 性能指标 processingTimeMs Int? @map("processing_time_ms") // 处理时长(毫秒) tokensUsed Int? @map("tokens_used") // Token使用量 // 关联 task BatchTask @relation(fields: [taskId], references: [id], onDelete: Cascade) document Document @relation(fields: [documentId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) @map("created_at") @@index([taskId]) @@index([documentId]) @@index([status]) @@map("batch_results") @@schema("pkb_schema") } // 任务模板(暂不实现,预留) model TaskTemplate { id String @id @default(uuid()) userId String @map("user_id") name String description String? prompt String @db.Text outputFields Json // 期望的输出字段定义 isPublic Boolean @default(false) @map("is_public") user User @relation(fields: [userId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@index([userId]) @@map("task_templates") @@schema("pkb_schema") } // ==================== 运营管理模块 ==================== model AdminLog { id Int @id @default(autoincrement()) adminId String @map("admin_id") action String resourceType String? @map("resource_type") resourceId String? @map("resource_id") details Json? ipAddress String? @map("ip_address") userAgent String? @map("user_agent") createdAt DateTime @default(now()) @map("created_at") admin User @relation(fields: [adminId], references: [id], onDelete: Cascade) @@index([adminId]) @@index([createdAt]) @@index([action]) @@map("admin_logs") @@schema("public") } // ==================== 通用对话模块 ==================== model GeneralConversation { id String @id @default(uuid()) userId String @map("user_id") title String modelName String? @map("model_name") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @default(now()) @updatedAt @map("updated_at") deletedAt DateTime? @map("deleted_at") user User @relation(fields: [userId], references: [id], onDelete: Cascade) messages GeneralMessage[] @@index([userId]) @@index([createdAt]) @@index([updatedAt]) @@map("general_conversations") @@schema("aia_schema") } model GeneralMessage { id String @id @default(uuid()) conversationId String @map("conversation_id") role String content String @db.Text model String? metadata Json? tokens Int? createdAt DateTime @default(now()) @map("created_at") conversation GeneralConversation @relation(fields: [conversationId], references: [id], onDelete: Cascade) @@index([conversationId]) @@index([createdAt]) @@map("general_messages") @@schema("aia_schema") } // ==================== 稿件审查模块 ==================== // 稿件审查任务 model ReviewTask { id String @id @default(uuid()) userId String @map("user_id") // 文件信息 fileName String @map("file_name") fileSize Int @map("file_size") filePath String? @map("file_path") // 文档内容 extractedText String @map("extracted_text") @db.Text wordCount Int? @map("word_count") // 执行状态 status String @default("pending") // pending, extracting, reviewing_editorial, reviewing_methodology, completed, failed // 评估结果(JSON) editorialReview Json? @map("editorial_review") methodologyReview Json? @map("methodology_review") overallScore Float? @map("overall_score") // 执行信息 modelUsed String? @map("model_used") startedAt DateTime? @map("started_at") completedAt DateTime? @map("completed_at") durationSeconds Int? @map("duration_seconds") errorMessage String? @map("error_message") @db.Text // 元数据 createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") // 关联 user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@index([userId]) @@index([status]) @@index([createdAt]) @@map("review_tasks") @@schema("public") }