generator client { provider = "prisma-client-js" previewFeatures = ["multiSchema"] } datasource db { provider = "postgresql" url = env("DATABASE_URL") schemas = ["admin_schema", "aia_schema", "asl_schema", "common_schema", "dc_schema", "iit_schema", "pkb_schema", "platform_schema", "public", "rvw_schema", "ssa_schema", "st_schema"] } /// 应用缓存表 - Postgres-Only架构 /// 用于替代Redis缓存,支持LLM结果缓存、健康检查缓存等 model AppCache { id Int @id @default(autoincrement()) key String @unique @db.VarChar(500) value Json expiresAt DateTime @map("expires_at") @db.Timestamp(6) createdAt DateTime? @default(now()) @map("created_at") @db.Timestamp(6) @@index([expiresAt], map: "idx_app_cache_expires") @@index([key, expiresAt], map: "idx_app_cache_key_expires") @@map("app_cache") @@schema("platform_schema") } 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") @@index([createdAt], map: "idx_platform_users_created_at") @@index([email], map: "idx_platform_users_email") @@index([status], map: "idx_platform_users_status") @@map("users") @@schema("platform_schema") } model Project { id String @id @default(uuid()) userId String @map("user_id") name String background String @default("") 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") // 关系字段(手动添加) conversations Conversation[] @relation("ProjectConversations") @@index([createdAt], map: "idx_aia_projects_created_at") @@index([deletedAt], map: "idx_aia_projects_deleted_at") @@index([userId], map: "idx_aia_projects_user_id") @@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") // 关系字段(手动添加) project Project? @relation("ProjectConversations", fields: [projectId], references: [id], onDelete: SetNull) messages Message[] @relation("ConversationMessages") @@index([agentId], map: "idx_aia_conversations_agent_id") @@index([createdAt], map: "idx_aia_conversations_created_at") @@index([deletedAt], map: "idx_aia_conversations_deleted_at") @@index([projectId], map: "idx_aia_conversations_project_id") @@index([userId], map: "idx_aia_conversations_user_id") @@map("conversations") @@schema("aia_schema") } model Message { id String @id @default(uuid()) conversationId String @map("conversation_id") role String content String model String? metadata Json? tokens Int? isPinned Boolean @default(false) @map("is_pinned") createdAt DateTime @default(now()) @map("created_at") // 关系字段(手动添加) conversation Conversation @relation("ConversationMessages", fields: [conversationId], references: [id], onDelete: Cascade) @@index([conversationId], map: "idx_aia_messages_conversation_id") @@index([createdAt], map: "idx_aia_messages_created_at") @@index([isPinned], map: "idx_aia_messages_is_pinned") @@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") // 关系字段(手动添加) documents Document[] @relation("KnowledgeBaseDocuments") batchTasks BatchTask[] @relation("KnowledgeBaseBatchTasks") @@index([difyDatasetId], map: "idx_pkb_knowledge_bases_dify_dataset_id") @@index([userId], map: "idx_pkb_knowledge_bases_user_id") @@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") extractionMethod String? @map("extraction_method") extractionQuality Float? @map("extraction_quality") charCount Int? @map("char_count") language String? extractedText String? @map("extracted_text") uploadedAt DateTime @default(now()) @map("uploaded_at") processedAt DateTime? @map("processed_at") // 关系字段(手动添加) knowledgeBase KnowledgeBase @relation("KnowledgeBaseDocuments", fields: [kbId], references: [id], onDelete: Cascade) batchResults BatchResult[] @relation("DocumentBatchResults") @@index([difyDocumentId], map: "idx_pkb_documents_dify_document_id") @@index([extractionMethod], map: "idx_pkb_documents_extraction_method") @@index([kbId], map: "idx_pkb_documents_kb_id") @@index([status], map: "idx_pkb_documents_status") @@index([userId], map: "idx_pkb_documents_user_id") @@map("documents") @@schema("pkb_schema") } model BatchTask { id String @id @default(uuid()) userId String @map("user_id") kbId String @map("kb_id") name String templateType String @map("template_type") templateId String? @map("template_id") prompt String status String 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) startedAt DateTime? @map("started_at") completedAt DateTime? @map("completed_at") durationSeconds Int? @map("duration_seconds") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") // 关系字段(手动添加) knowledgeBase KnowledgeBase @relation("KnowledgeBaseBatchTasks", fields: [kbId], references: [id], onDelete: Cascade) results BatchResult[] @relation("TaskBatchResults") @@index([createdAt], map: "idx_pkb_batch_tasks_created_at") @@index([kbId], map: "idx_pkb_batch_tasks_kb_id") @@index([status], map: "idx_pkb_batch_tasks_status") @@index([userId], map: "idx_pkb_batch_tasks_user_id") @@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 data Json? rawOutput String? @map("raw_output") errorMessage String? @map("error_message") processingTimeMs Int? @map("processing_time_ms") tokensUsed Int? @map("tokens_used") createdAt DateTime @default(now()) @map("created_at") // 关系字段(手动添加) task BatchTask @relation("TaskBatchResults", fields: [taskId], references: [id], onDelete: Cascade) document Document @relation("DocumentBatchResults", fields: [documentId], references: [id], onDelete: Cascade) @@index([documentId], map: "idx_pkb_batch_results_document_id") @@index([status], map: "idx_pkb_batch_results_status") @@index([taskId], map: "idx_pkb_batch_results_task_id") @@map("batch_results") @@schema("pkb_schema") } model TaskTemplate { id String @id @default(uuid()) userId String @map("user_id") name String description String? prompt String isPublic Boolean @default(false) @map("is_public") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") outputFields Json @@index([userId], map: "idx_pkb_task_templates_user_id") @@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 users @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") @@index([createdAt], map: "idx_aia_general_conversations_created_at") @@index([updatedAt], map: "idx_aia_general_conversations_updated_at") @@index([userId], map: "idx_aia_general_conversations_user_id") @@map("general_conversations") @@schema("aia_schema") } model GeneralMessage { id String @id @default(uuid()) conversationId String @map("conversation_id") role String content String model String? metadata Json? tokens Int? createdAt DateTime @default(now()) @map("created_at") @@index([conversationId], map: "idx_aia_general_messages_conversation_id") @@index([createdAt], map: "idx_aia_general_messages_created_at") @@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") wordCount Int? @map("word_count") status String @default("pending") 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") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") user users @relation(fields: [userId], references: [id], onDelete: Cascade) @@index([userId]) @@index([status]) @@index([createdAt]) @@map("review_tasks") @@schema("public") } model AslScreeningProject { id String @id @default(uuid()) userId String @map("user_id") projectName String @map("project_name") picoCriteria Json @map("pico_criteria") inclusionCriteria String @map("inclusion_criteria") exclusionCriteria String @map("exclusion_criteria") status String @default("draft") screeningConfig Json? @map("screening_config") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") // 关系字段(手动添加) literatures AslLiterature[] @relation("ProjectLiteratures") screeningResults AslScreeningResult[] @relation("ProjectScreeningResults") screeningTasks AslScreeningTask[] @relation("ProjectScreeningTasks") fulltextTasks AslFulltextScreeningTask[] @relation("ProjectFulltextTasks") fulltextResults AslFulltextScreeningResult[] @relation("ProjectFulltextResults") @@index([status], map: "idx_screening_projects_status") @@index([userId], map: "idx_screening_projects_user_id") @@map("screening_projects") @@schema("asl_schema") } model AslLiterature { id String @id @default(uuid()) projectId String @map("project_id") pmid String? title String abstract String authors String? journal String? publicationYear Int? @map("publication_year") doi String? pdfUrl String? @map("pdf_url") pdfOssKey String? @map("pdf_oss_key") pdfFileSize Int? @map("pdf_file_size") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") stage String @default("imported") @map("stage") hasPdf Boolean @default(false) @map("has_pdf") pdfStorageType String? @map("pdf_storage_type") pdfStorageRef String? @map("pdf_storage_ref") pdfStatus String? @map("pdf_status") pdfUploadedAt DateTime? @map("pdf_uploaded_at") fullTextStorageType String? @map("full_text_storage_type") fullTextStorageRef String? @map("full_text_storage_ref") fullTextUrl String? @map("full_text_url") fullTextFormat String? @map("full_text_format") fullTextSource String? @map("full_text_source") fullTextTokenCount Int? @map("full_text_token_count") fullTextExtractedAt DateTime? @map("full_text_extracted_at") // 关系字段(手动添加) project AslScreeningProject @relation("ProjectLiteratures", fields: [projectId], references: [id], onDelete: Cascade) screeningResults AslScreeningResult[] @relation("LiteratureScreeningResults") fulltextResults AslFulltextScreeningResult[] @relation("LiteratureFulltextResults") @@unique([projectId, pmid], map: "unique_project_pmid") @@index([doi], map: "idx_literatures_doi") @@index([hasPdf], map: "idx_literatures_has_pdf") @@index([pdfStatus], map: "idx_literatures_pdf_status") @@index([projectId], map: "idx_literatures_project_id") @@index([stage], map: "idx_literatures_stage") @@map("literatures") @@schema("asl_schema") } model AslScreeningResult { id String @id @default(uuid()) projectId String @map("project_id") literatureId String @map("literature_id") dsModelName String @map("ds_model_name") dsPJudgment String? @map("ds_p_judgment") dsIJudgment String? @map("ds_i_judgment") dsCJudgment String? @map("ds_c_judgment") dsSJudgment String? @map("ds_s_judgment") dsConclusion String? @map("ds_conclusion") dsConfidence Float? @map("ds_confidence") dsPEvidence String? @map("ds_p_evidence") dsIEvidence String? @map("ds_i_evidence") dsCEvidence String? @map("ds_c_evidence") dsSEvidence String? @map("ds_s_evidence") dsReason String? @map("ds_reason") qwenModelName String @map("qwen_model_name") qwenPJudgment String? @map("qwen_p_judgment") qwenIJudgment String? @map("qwen_i_judgment") qwenCJudgment String? @map("qwen_c_judgment") qwenSJudgment String? @map("qwen_s_judgment") qwenConclusion String? @map("qwen_conclusion") qwenConfidence Float? @map("qwen_confidence") qwenPEvidence String? @map("qwen_p_evidence") qwenIEvidence String? @map("qwen_i_evidence") qwenCEvidence String? @map("qwen_c_evidence") qwenSEvidence String? @map("qwen_s_evidence") qwenReason String? @map("qwen_reason") conflictStatus String @default("none") @map("conflict_status") conflictFields Json? @map("conflict_fields") finalDecision String? @map("final_decision") finalDecisionBy String? @map("final_decision_by") finalDecisionAt DateTime? @map("final_decision_at") exclusionReason String? @map("exclusion_reason") aiProcessingStatus String @default("pending") @map("ai_processing_status") aiProcessedAt DateTime? @map("ai_processed_at") aiErrorMessage String? @map("ai_error_message") promptVersion String @default("v1.0.0") @map("prompt_version") rawOutput Json? @map("raw_output") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") // 关系字段(手动添加) project AslScreeningProject @relation("ProjectScreeningResults", fields: [projectId], references: [id], onDelete: Cascade) literature AslLiterature @relation("LiteratureScreeningResults", fields: [literatureId], references: [id], onDelete: Cascade) @@unique([projectId, literatureId], map: "unique_project_literature") @@index([conflictStatus], map: "idx_screening_results_conflict_status") @@index([finalDecision], map: "idx_screening_results_final_decision") @@index([literatureId], map: "idx_screening_results_literature_id") @@index([projectId], map: "idx_screening_results_project_id") @@map("screening_results") @@schema("asl_schema") } model AslScreeningTask { id String @id @default(uuid()) projectId String @map("project_id") taskType String @map("task_type") status String @default("pending") totalItems Int @map("total_items") processedItems Int @default(0) @map("processed_items") successItems Int @default(0) @map("success_items") failedItems Int @default(0) @map("failed_items") conflictItems Int @default(0) @map("conflict_items") startedAt DateTime? @map("started_at") completedAt DateTime? @map("completed_at") estimatedEndAt DateTime? @map("estimated_end_at") errorMessage String? @map("error_message") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") // 关系字段(手动添加) project AslScreeningProject @relation("ProjectScreeningTasks", fields: [projectId], references: [id], onDelete: Cascade) @@index([projectId], map: "idx_screening_tasks_project_id") @@index([status], map: "idx_screening_tasks_status") @@map("screening_tasks") @@schema("asl_schema") } model AslFulltextScreeningTask { id String @id @default(uuid()) projectId String @map("project_id") modelA String @map("model_a") modelB String @map("model_b") promptVersion String @default("v1.0.0") @map("prompt_version") status String @default("pending") totalCount Int @map("total_count") processedCount Int @default(0) @map("processed_count") successCount Int @default(0) @map("success_count") failedCount Int @default(0) @map("failed_count") degradedCount Int @default(0) @map("degraded_count") totalTokens Int @default(0) @map("total_tokens") totalCost Float @default(0) @map("total_cost") startedAt DateTime? @map("started_at") completedAt DateTime? @map("completed_at") estimatedEndAt DateTime? @map("estimated_end_at") errorMessage String? @map("error_message") errorStack String? @map("error_stack") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") // 关系字段(手动添加) project AslScreeningProject @relation("ProjectFulltextTasks", fields: [projectId], references: [id], onDelete: Cascade) results AslFulltextScreeningResult[] @relation("TaskFulltextResults") @@index([createdAt], map: "idx_fulltext_tasks_created_at") @@index([projectId], map: "idx_fulltext_tasks_project_id") @@index([status], map: "idx_fulltext_tasks_status") @@map("fulltext_screening_tasks") @@schema("asl_schema") } model AslFulltextScreeningResult { id String @id @default(uuid()) taskId String @map("task_id") projectId String @map("project_id") literatureId String @map("literature_id") modelAName String @map("model_a_name") modelAStatus String @map("model_a_status") modelAFields Json @map("model_a_fields") modelAOverall Json @map("model_a_overall") modelAProcessingLog Json? @map("model_a_processing_log") modelAVerification Json? @map("model_a_verification") modelATokens Int? @map("model_a_tokens") modelACost Float? @map("model_a_cost") modelAError String? @map("model_a_error") modelBName String @map("model_b_name") modelBStatus String @map("model_b_status") modelBFields Json @map("model_b_fields") modelBOverall Json @map("model_b_overall") modelBProcessingLog Json? @map("model_b_processing_log") modelBVerification Json? @map("model_b_verification") modelBTokens Int? @map("model_b_tokens") modelBCost Float? @map("model_b_cost") modelBError String? @map("model_b_error") medicalLogicIssues Json? @map("medical_logic_issues") evidenceChainIssues Json? @map("evidence_chain_issues") isConflict Boolean @default(false) @map("is_conflict") conflictSeverity String? @map("conflict_severity") conflictFields String[] @map("conflict_fields") conflictDetails Json? @map("conflict_details") reviewPriority Int? @map("review_priority") reviewDeadline DateTime? @map("review_deadline") finalDecision String? @map("final_decision") finalDecisionBy String? @map("final_decision_by") finalDecisionAt DateTime? @map("final_decision_at") exclusionReason String? @map("exclusion_reason") reviewNotes String? @map("review_notes") processingStatus String @default("pending") @map("processing_status") isDegraded Boolean @default(false) @map("is_degraded") degradedModel String? @map("degraded_model") processedAt DateTime? @map("processed_at") promptVersion String @default("v1.0.0") @map("prompt_version") rawOutputA Json? @map("raw_output_a") rawOutputB Json? @map("raw_output_b") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") // 关系字段(手动添加) task AslFulltextScreeningTask @relation("TaskFulltextResults", fields: [taskId], references: [id], onDelete: Cascade) project AslScreeningProject @relation("ProjectFulltextResults", fields: [projectId], references: [id], onDelete: Cascade) literature AslLiterature @relation("LiteratureFulltextResults", fields: [literatureId], references: [id], onDelete: Cascade) @@unique([projectId, literatureId], map: "unique_project_literature_fulltext") @@index([finalDecision], map: "idx_fulltext_results_final_decision") @@index([isConflict], map: "idx_fulltext_results_is_conflict") @@index([literatureId], map: "idx_fulltext_results_literature_id") @@index([projectId], map: "idx_fulltext_results_project_id") @@index([reviewPriority], map: "idx_fulltext_results_review_priority") @@index([taskId], map: "idx_fulltext_results_task_id") @@map("fulltext_screening_results") @@schema("asl_schema") } model DCHealthCheck { id String @id @default(uuid()) userId String @map("user_id") fileName String @map("file_name") columnName String @map("column_name") emptyRate Float @map("empty_rate") avgLength Float @map("avg_length") totalRows Int @map("total_rows") estimatedTokens Int @map("estimated_tokens") status String @map("status") message String @map("message") createdAt DateTime @default(now()) @map("created_at") @@index([userId, fileName]) @@map("dc_health_checks") @@schema("dc_schema") } model DCTemplate { id String @id @default(uuid()) diseaseType String @map("disease_type") reportType String @map("report_type") displayName String @map("display_name") fields Json @map("fields") promptTemplate String @map("prompt_template") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@unique([diseaseType, reportType]) @@map("dc_templates") @@schema("dc_schema") } model DCExtractionTask { id String @id @default(uuid()) userId String @map("user_id") projectName String @map("project_name") sourceFileKey String @map("source_file_key") textColumn String @map("text_column") diseaseType String @map("disease_type") reportType String @map("report_type") targetFields Json @map("target_fields") modelA String @default("deepseek-v3") @map("model_a") modelB String @default("qwen-max") @map("model_b") status String @default("pending") @map("status") totalCount Int @default(0) @map("total_count") processedCount Int @default(0) @map("processed_count") cleanCount Int @default(0) @map("clean_count") conflictCount Int @default(0) @map("conflict_count") failedCount Int @default(0) @map("failed_count") totalTokens Int @default(0) @map("total_tokens") totalCost Float @default(0) @map("total_cost") error String? @map("error") createdAt DateTime @default(now()) @map("created_at") startedAt DateTime? @map("started_at") completedAt DateTime? @map("completed_at") items DCExtractionItem[] @@index([userId, status]) @@map("dc_extraction_tasks") @@schema("dc_schema") } model DCExtractionItem { id String @id @default(uuid()) taskId String @map("task_id") rowIndex Int @map("row_index") originalText String @map("original_text") resultA Json? @map("result_a") resultB Json? @map("result_b") status String @default("pending") @map("status") conflictFields String[] @default([]) @map("conflict_fields") finalResult Json? @map("final_result") tokensA Int @default(0) @map("tokens_a") tokensB Int @default(0) @map("tokens_b") error String? @map("error") createdAt DateTime @default(now()) @map("created_at") resolvedAt DateTime? @map("resolved_at") task DCExtractionTask @relation(fields: [taskId], references: [id], onDelete: Cascade) @@index([taskId, status]) @@map("dc_extraction_items") @@schema("dc_schema") } model DcToolCSession { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid userId String @map("user_id") @db.VarChar(255) fileName String @map("file_name") @db.VarChar(500) fileKey String @map("file_key") @db.VarChar(500) totalRows Int? @map("total_rows") totalCols Int? @map("total_cols") columns Json? @map("columns") encoding String? @map("encoding") @db.VarChar(50) fileSize Int @map("file_size") createdAt DateTime @default(now()) @map("created_at") @db.Timestamp(6) updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamp(6) expiresAt DateTime @map("expires_at") @db.Timestamp(6) dataStats Json? @map("data_stats") columnMapping Json? @map("column_mapping") cleanDataKey String? @map("clean_data_key") @db.VarChar(1000) @@index([expiresAt], map: "idx_dc_tool_c_sessions_expires_at") @@index([userId], map: "idx_dc_tool_c_sessions_user_id") @@map("dc_tool_c_sessions") @@schema("dc_schema") } model DcToolCAiHistory { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid sessionId String @map("session_id") @db.VarChar(255) userId String @map("user_id") @db.VarChar(255) role String @map("role") @db.VarChar(50) content String generatedCode String? @map("generated_code") codeExplanation String? @map("code_explanation") executeStatus String? @map("execute_status") @db.VarChar(50) executeResult Json? @map("execute_result") executeError String? @map("execute_error") retryCount Int? @default(0) @map("retry_count") model String? @map("model") @db.VarChar(100) createdAt DateTime @default(now()) @map("created_at") @db.Timestamp(6) @@index([createdAt], map: "idx_dc_tool_c_ai_history_created_at") @@index([sessionId], map: "idx_dc_tool_c_ai_history_session_id") @@index([userId], map: "idx_dc_tool_c_ai_history_user_id") @@map("dc_tool_c_ai_history") @@schema("dc_schema") } /// This table is a partition table and requires additional setup for migrations. Visit https://pris.ly/d/partition-tables for more info. model job { id String @default(dbgenerated("gen_random_uuid()")) @db.Uuid name String priority Int @default(0) data Json? state job_state @default(created) retry_limit Int @default(2) retry_count Int @default(0) retry_delay Int @default(0) retry_backoff Boolean @default(false) retry_delay_max Int? expire_seconds Int @default(900) deletion_seconds Int @default(604800) singleton_key String? singleton_on DateTime? @db.Timestamp(6) start_after DateTime @default(now()) @db.Timestamptz(6) created_on DateTime @default(now()) @db.Timestamptz(6) started_on DateTime? @db.Timestamptz(6) completed_on DateTime? @db.Timestamptz(6) keep_until DateTime @default(dbgenerated("(now() + '336:00:00'::interval)")) @db.Timestamptz(6) output Json? dead_letter String? policy String? @@id([name, id]) @@schema("platform_schema") } /// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info. model queue { name String @id policy String retry_limit Int retry_delay Int retry_backoff Boolean retry_delay_max Int? expire_seconds Int retention_seconds Int deletion_seconds Int dead_letter String? partition Boolean table_name String deferred_count Int @default(0) queued_count Int @default(0) warning_queued Int @default(0) active_count Int @default(0) total_count Int @default(0) singletons_active String[] monitor_on DateTime? @db.Timestamptz(6) maintain_on DateTime? @db.Timestamptz(6) created_on DateTime @default(now()) @db.Timestamptz(6) updated_on DateTime @default(now()) @db.Timestamptz(6) queue queue? @relation("queueToqueue", fields: [dead_letter], references: [name], onDelete: NoAction, onUpdate: NoAction) other_queue queue[] @relation("queueToqueue") schedule schedule[] subscription subscription[] @@schema("platform_schema") } model schedule { name String key String @default("") cron String timezone String? data Json? options Json? created_on DateTime @default(now()) @db.Timestamptz(6) updated_on DateTime @default(now()) @db.Timestamptz(6) queue queue @relation(fields: [name], references: [name], onDelete: Cascade, onUpdate: NoAction) @@id([name, key]) @@schema("platform_schema") } model subscription { event String name String created_on DateTime @default(now()) @db.Timestamptz(6) updated_on DateTime @default(now()) @db.Timestamptz(6) queue queue @relation(fields: [name], references: [name], onDelete: Cascade, onUpdate: NoAction) @@id([event, name]) @@schema("platform_schema") } model version { version Int @id cron_on DateTime? @db.Timestamptz(6) @@schema("platform_schema") } model users { id String @id email String @unique password String name String? avatar_url String? role String @default("user") status String @default("active") kb_quota Int @default(3) kb_used Int @default(0) trial_ends_at DateTime? is_trial Boolean @default(true) last_login_at DateTime? created_at DateTime @default(now()) updated_at DateTime adminLogs AdminLog[] reviewTasks ReviewTask[] @@index([created_at]) @@index([email]) @@index([status]) @@schema("public") } enum job_state { created retry active completed cancelled failed @@schema("platform_schema") } // ============================== // IIT Manager Schema (V1.1) // ============================== /// IIT项目表 model IitProject { id String @id @default(uuid()) name String description String? @db.Text // Protocol知识库 difyDatasetId String? @unique @map("dify_dataset_id") protocolFileKey String? @map("protocol_file_key") // V1.1 新增:Dify性能优化 - 缓存关键规则 cachedRules Json? @map("cached_rules") // 字段映射配置(JSON) fieldMappings Json @map("field_mappings") // REDCap配置 redcapProjectId String @map("redcap_project_id") redcapApiToken String @db.Text @map("redcap_api_token") redcapUrl String @map("redcap_url") // V1.1 新增:同步管理 - 记录上次同步时间 lastSyncAt DateTime? @map("last_sync_at") // 项目状态 status String @default("active") // 时间戳 createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") deletedAt DateTime? @map("deleted_at") // 关系 pendingActions IitPendingAction[] taskRuns IitTaskRun[] userMappings IitUserMapping[] auditLogs IitAuditLog[] @@index([status, deletedAt]) @@map("projects") @@schema("iit_schema") } /// 影子状态表(核心) model IitPendingAction { id String @id @default(uuid()) projectId String @map("project_id") recordId String @map("record_id") fieldName String @map("field_name") // 数据对比 currentValue Json? @map("current_value") suggestedValue Json? @map("suggested_value") // 状态流转 status String // PROPOSED/APPROVED/REJECTED/EXECUTED/FAILED agentType String @map("agent_type") // DATA_QUALITY/TASK_DRIVEN/COUNSELING/REPORTING // AI推理信息 reasoning String @db.Text evidence Json // 人类确认信息 approvedBy String? @map("approved_by") approvedAt DateTime? @map("approved_at") rejectionReason String? @db.Text @map("rejection_reason") // 执行信息 executedAt DateTime? @map("executed_at") errorMessage String? @db.Text @map("error_message") // 时间戳 createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") // 关系 project IitProject @relation(fields: [projectId], references: [id]) @@index([projectId, status]) @@index([projectId, recordId]) @@index([status, createdAt]) @@map("pending_actions") @@schema("iit_schema") } /// 任务运行记录(与 pg-boss 关联) model IitTaskRun { id String @id @default(uuid()) projectId String @map("project_id") taskType String @map("task_type") // 关联 pg-boss job jobId String? @unique @map("job_id") // 任务状态 status String // 业务结果 totalItems Int @map("total_items") processedItems Int @default(0) @map("processed_items") successItems Int @default(0) @map("success_items") failedItems Int @default(0) @map("failed_items") // 时间信息 startedAt DateTime? @map("started_at") completedAt DateTime? @map("completed_at") duration Int? // 秒 // 时间戳 createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") // 关系 project IitProject @relation(fields: [projectId], references: [id]) @@index([projectId, taskType, status]) @@index([jobId]) @@map("task_runs") @@schema("iit_schema") } /// 用户映射表(异构系统身份关联) model IitUserMapping { id String @id @default(uuid()) projectId String @map("project_id") // 系统用户ID(本系统) systemUserId String @map("system_user_id") // REDCap用户名 redcapUsername String @map("redcap_username") // 企微OpenID wecomUserId String? @map("wecom_user_id") // V1.1 新增:小程序支持 miniProgramOpenId String? @unique @map("mini_program_open_id") sessionKey String? @map("session_key") // 角色 role String // 时间戳 createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") // 关系 project IitProject @relation(fields: [projectId], references: [id]) @@unique([projectId, systemUserId]) @@unique([projectId, redcapUsername]) @@index([wecomUserId]) @@index([miniProgramOpenId]) @@map("user_mappings") @@schema("iit_schema") } /// 审计日志表 model IitAuditLog { id String @id @default(uuid()) projectId String @map("project_id") // 操作信息 userId String @map("user_id") actionType String @map("action_type") entityType String @map("entity_type") entityId String @map("entity_id") // 详细信息 details Json? // 追踪链 traceId String @map("trace_id") // 时间戳 createdAt DateTime @default(now()) @map("created_at") // 关系 project IitProject @relation(fields: [projectId], references: [id]) @@index([projectId, createdAt]) @@index([userId, createdAt]) @@index([actionType, createdAt]) @@index([traceId]) @@map("audit_logs") @@schema("iit_schema") }