feat(dc): Complete Phase 1 - Portal workbench page development

Summary:
- Implement DC module Portal page with 3 tool cards
- Create ToolCard component with decorative background and hover animations
- Implement TaskList component with table layout and progress bars
- Implement AssetLibrary component with tab switching and file cards
- Complete database verification (4 tables confirmed)
- Complete backend API verification (6 endpoints ready)
- Optimize UI to match prototype design (V2.html)

Frontend Components (~715 lines):
- components/ToolCard.tsx - Tool cards with animations
- components/TaskList.tsx - Recent tasks table view
- components/AssetLibrary.tsx - Data asset library with tabs
- hooks/useRecentTasks.ts - Task state management
- hooks/useAssets.ts - Asset state management
- pages/Portal.tsx - Main portal page
- types/portal.ts - TypeScript type definitions

Backend Verification:
- Backend API: 1495 lines code verified
- Database: dc_schema with 4 tables verified
- API endpoints: 6 endpoints tested (templates API works)

Documentation:
- Database verification report
- Backend API test report
- Phase 1 completion summary
- UI optimization report
- Development task checklist
- Development plan for Tool B

Status: Phase 1 completed (100%), ready for browser testing
Next: Phase 2 - Tool B Step 1 and 2 development
This commit is contained in:
2025-12-02 21:53:24 +08:00
parent f240aa9236
commit d4d33528c7
83 changed files with 21863 additions and 1601 deletions

View File

@@ -718,3 +718,131 @@ model AslFulltextScreeningResult {
@@map("fulltext_screening_results")
@@schema("asl_schema")
}
// ==================== DC数据清洗模块 - Tool B (病历结构化机器人) ====================
// 健康检查缓存表
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") // 空值率 (0-1)
avgLength Float @map("avg_length") // 平均文本长度
totalRows Int @map("total_rows")
estimatedTokens Int @map("estimated_tokens")
// 检查结果
status String @map("status") // 'good' | 'bad'
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") // 'lung_cancer', 'diabetes', 'hypertension'
reportType String @map("report_type") // 'pathology', 'admission', 'outpatient'
displayName String @map("display_name") // '肺癌病理报告'
fields Json @map("fields") // [{name, desc, width}]
promptTemplate String @map("prompt_template") @db.Text
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") // Storage中的路径
textColumn String @map("text_column")
// 模板配置
diseaseType String @map("disease_type")
reportType String @map("report_type")
targetFields Json @map("target_fields") // [{name, desc}]
// 双模型配置
modelA String @default("deepseek-v3") @map("model_a")
modelB String @default("qwen-max") @map("model_b")
// 任务状态
status String @default("pending") @map("status") // 'pending'|'processing'|'completed'|'failed'
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") @db.Text
// 双模型结果 (V2核心)
resultA Json? @map("result_a") // DeepSeek结果 {"肿瘤大小": "3cm"}
resultB Json? @map("result_b") // Qwen结果 {"肿瘤大小": "3.0cm"}
// 冲突检测
status String @default("pending") @map("status") // 'pending'|'clean'|'conflict'|'resolved'|'failed'
conflictFields String[] @default([]) @map("conflict_fields") // ["肿瘤大小"]
// 最终结果 (用户裁决后或自动采纳)
finalResult Json? @map("final_result")
// Token统计
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")
}