refactor(asl): ASL frontend architecture refactoring with left navigation
- feat: Create ASLLayout component with 7-module left navigation - feat: Implement Title Screening Settings page with optimized PICOS layout - feat: Add placeholder pages for Workbench and Results - fix: Fix nested routing structure for React Router v6 - fix: Resolve Spin component warning in MainLayout - fix: Add QueryClientProvider to App.tsx - style: Optimize PICOS form layout (P+I left, C+O+S right) - style: Align Inclusion/Exclusion criteria side-by-side - docs: Add architecture refactoring and routing fix reports Ref: Week 2 Frontend Development Scope: ASL module MVP - Title Abstract Screening
This commit is contained in:
205
backend/scripts/create-asl-tables.ts
Normal file
205
backend/scripts/create-asl-tables.ts
Normal file
@@ -0,0 +1,205 @@
|
||||
/**
|
||||
* 手动创建ASL模块的4张表
|
||||
* 避免影响现有表
|
||||
*/
|
||||
|
||||
import { prisma } from '../src/config/database.js';
|
||||
|
||||
async function createAslTables() {
|
||||
try {
|
||||
console.log('🔍 开始创建ASL模块表...\n');
|
||||
|
||||
// 1. 创建筛选项目表
|
||||
await prisma.$executeRawUnsafe(`
|
||||
CREATE TABLE IF NOT EXISTS asl_schema.screening_projects (
|
||||
id TEXT PRIMARY KEY,
|
||||
user_id TEXT NOT NULL,
|
||||
project_name TEXT NOT NULL,
|
||||
pico_criteria JSONB NOT NULL,
|
||||
inclusion_criteria TEXT NOT NULL,
|
||||
exclusion_criteria TEXT NOT NULL,
|
||||
status TEXT NOT NULL DEFAULT 'draft',
|
||||
screening_config JSONB,
|
||||
created_at TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES platform_schema.users(id) ON DELETE CASCADE
|
||||
);
|
||||
`);
|
||||
console.log('✅ 创建 asl_schema.screening_projects');
|
||||
|
||||
// 创建索引
|
||||
await prisma.$executeRawUnsafe(`
|
||||
CREATE INDEX IF NOT EXISTS idx_screening_projects_user_id ON asl_schema.screening_projects(user_id);
|
||||
`);
|
||||
await prisma.$executeRawUnsafe(`
|
||||
CREATE INDEX IF NOT EXISTS idx_screening_projects_status ON asl_schema.screening_projects(status);
|
||||
`);
|
||||
|
||||
// 2. 创建文献条目表
|
||||
await prisma.$executeRawUnsafe(`
|
||||
CREATE TABLE IF NOT EXISTS asl_schema.literatures (
|
||||
id TEXT PRIMARY KEY,
|
||||
project_id TEXT NOT NULL,
|
||||
pmid TEXT,
|
||||
title TEXT NOT NULL,
|
||||
abstract TEXT NOT NULL,
|
||||
authors TEXT,
|
||||
journal TEXT,
|
||||
publication_year INTEGER,
|
||||
doi TEXT,
|
||||
pdf_url TEXT,
|
||||
pdf_oss_key TEXT,
|
||||
pdf_file_size INTEGER,
|
||||
created_at TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT fk_project FOREIGN KEY (project_id) REFERENCES asl_schema.screening_projects(id) ON DELETE CASCADE,
|
||||
CONSTRAINT unique_project_pmid UNIQUE (project_id, pmid)
|
||||
);
|
||||
`);
|
||||
console.log('✅ 创建 asl_schema.literatures');
|
||||
|
||||
// 创建索引
|
||||
await prisma.$executeRawUnsafe(`
|
||||
CREATE INDEX IF NOT EXISTS idx_literatures_project_id ON asl_schema.literatures(project_id);
|
||||
`);
|
||||
await prisma.$executeRawUnsafe(`
|
||||
CREATE INDEX IF NOT EXISTS idx_literatures_doi ON asl_schema.literatures(doi);
|
||||
`);
|
||||
|
||||
// 3. 创建筛选结果表
|
||||
await prisma.$executeRawUnsafe(`
|
||||
CREATE TABLE IF NOT EXISTS asl_schema.screening_results (
|
||||
id TEXT PRIMARY KEY,
|
||||
project_id TEXT NOT NULL,
|
||||
literature_id TEXT NOT NULL,
|
||||
|
||||
-- DeepSeek判断
|
||||
ds_model_name TEXT NOT NULL,
|
||||
ds_p_judgment TEXT,
|
||||
ds_i_judgment TEXT,
|
||||
ds_c_judgment TEXT,
|
||||
ds_s_judgment TEXT,
|
||||
ds_conclusion TEXT,
|
||||
ds_confidence DOUBLE PRECISION,
|
||||
ds_p_evidence TEXT,
|
||||
ds_i_evidence TEXT,
|
||||
ds_c_evidence TEXT,
|
||||
ds_s_evidence TEXT,
|
||||
ds_reason TEXT,
|
||||
|
||||
-- Qwen判断
|
||||
qwen_model_name TEXT NOT NULL,
|
||||
qwen_p_judgment TEXT,
|
||||
qwen_i_judgment TEXT,
|
||||
qwen_c_judgment TEXT,
|
||||
qwen_s_judgment TEXT,
|
||||
qwen_conclusion TEXT,
|
||||
qwen_confidence DOUBLE PRECISION,
|
||||
qwen_p_evidence TEXT,
|
||||
qwen_i_evidence TEXT,
|
||||
qwen_c_evidence TEXT,
|
||||
qwen_s_evidence TEXT,
|
||||
qwen_reason TEXT,
|
||||
|
||||
-- 冲突状态
|
||||
conflict_status TEXT NOT NULL DEFAULT 'none',
|
||||
conflict_fields JSONB,
|
||||
|
||||
-- 最终决策
|
||||
final_decision TEXT,
|
||||
final_decision_by TEXT,
|
||||
final_decision_at TIMESTAMP(3),
|
||||
exclusion_reason TEXT,
|
||||
|
||||
-- AI处理状态
|
||||
ai_processing_status TEXT NOT NULL DEFAULT 'pending',
|
||||
ai_processed_at TIMESTAMP(3),
|
||||
ai_error_message TEXT,
|
||||
|
||||
-- 可追溯信息
|
||||
prompt_version TEXT NOT NULL DEFAULT 'v1.0.0',
|
||||
raw_output JSONB,
|
||||
|
||||
created_at TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT fk_project_result FOREIGN KEY (project_id) REFERENCES asl_schema.screening_projects(id) ON DELETE CASCADE,
|
||||
CONSTRAINT fk_literature FOREIGN KEY (literature_id) REFERENCES asl_schema.literatures(id) ON DELETE CASCADE,
|
||||
CONSTRAINT unique_project_literature UNIQUE (project_id, literature_id)
|
||||
);
|
||||
`);
|
||||
console.log('✅ 创建 asl_schema.screening_results');
|
||||
|
||||
// 创建索引
|
||||
await prisma.$executeRawUnsafe(`
|
||||
CREATE INDEX IF NOT EXISTS idx_screening_results_project_id ON asl_schema.screening_results(project_id);
|
||||
`);
|
||||
await prisma.$executeRawUnsafe(`
|
||||
CREATE INDEX IF NOT EXISTS idx_screening_results_literature_id ON asl_schema.screening_results(literature_id);
|
||||
`);
|
||||
await prisma.$executeRawUnsafe(`
|
||||
CREATE INDEX IF NOT EXISTS idx_screening_results_conflict_status ON asl_schema.screening_results(conflict_status);
|
||||
`);
|
||||
await prisma.$executeRawUnsafe(`
|
||||
CREATE INDEX IF NOT EXISTS idx_screening_results_final_decision ON asl_schema.screening_results(final_decision);
|
||||
`);
|
||||
|
||||
// 4. 创建筛选任务表
|
||||
await prisma.$executeRawUnsafe(`
|
||||
CREATE TABLE IF NOT EXISTS asl_schema.screening_tasks (
|
||||
id TEXT PRIMARY KEY,
|
||||
project_id TEXT NOT NULL,
|
||||
task_type TEXT NOT NULL,
|
||||
status TEXT NOT NULL DEFAULT 'pending',
|
||||
total_items INTEGER NOT NULL,
|
||||
processed_items INTEGER NOT NULL DEFAULT 0,
|
||||
success_items INTEGER NOT NULL DEFAULT 0,
|
||||
failed_items INTEGER NOT NULL DEFAULT 0,
|
||||
conflict_items INTEGER NOT NULL DEFAULT 0,
|
||||
started_at TIMESTAMP(3),
|
||||
completed_at TIMESTAMP(3),
|
||||
estimated_end_at TIMESTAMP(3),
|
||||
error_message TEXT,
|
||||
created_at TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT fk_project_task FOREIGN KEY (project_id) REFERENCES asl_schema.screening_projects(id) ON DELETE CASCADE
|
||||
);
|
||||
`);
|
||||
console.log('✅ 创建 asl_schema.screening_tasks');
|
||||
|
||||
// 创建索引
|
||||
await prisma.$executeRawUnsafe(`
|
||||
CREATE INDEX IF NOT EXISTS idx_screening_tasks_project_id ON asl_schema.screening_tasks(project_id);
|
||||
`);
|
||||
await prisma.$executeRawUnsafe(`
|
||||
CREATE INDEX IF NOT EXISTS idx_screening_tasks_status ON asl_schema.screening_tasks(status);
|
||||
`);
|
||||
|
||||
console.log('\n✅ ASL模块4张表创建完成!');
|
||||
console.log('📊 表列表:');
|
||||
console.log(' - asl_schema.screening_projects (筛选项目)');
|
||||
console.log(' - asl_schema.literatures (文献条目)');
|
||||
console.log(' - asl_schema.screening_results (筛选结果)');
|
||||
console.log(' - asl_schema.screening_tasks (筛选任务)');
|
||||
|
||||
// 验证表
|
||||
const tables = await prisma.$queryRawUnsafe<any[]>(`
|
||||
SELECT tablename
|
||||
FROM pg_tables
|
||||
WHERE schemaname = 'asl_schema'
|
||||
ORDER BY tablename;
|
||||
`);
|
||||
|
||||
console.log('\n🔍 数据库验证:');
|
||||
tables.forEach(t => console.log(` ✓ ${t.tablename}`));
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 创建表失败:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
await prisma.$disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
createAslTables();
|
||||
|
||||
Reference in New Issue
Block a user