Files
AIclinicalresearch/backend/prisma/schema.prisma
HaHafeng 4c5bb3d174 feat(iit): Initialize IIT Manager Agent MVP - Day 1 complete
- Add iit_schema with 5 tables
- Create module structure and types (223 lines)
- WeChat integration verified (Access Token success)
- Update system docs to v2.4
- Add REDCap source folders to .gitignore
- Day 1/14 complete (11/11 tasks)
2025-12-31 18:35:05 +08:00

1020 lines
40 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.
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")
}