Files
AIclinicalresearch/backend/scripts/create-asl-tables.ts
HaHafeng 3634933ece 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
2025-11-18 21:51:51 +08:00

206 lines
7.2 KiB
TypeScript
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.
/**
* 手动创建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();