import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient(); async function main() { console.log('🔍 系统完整性验证\n'); console.log('=' .repeat(60)); // 1. 检查 schema.prisma 定义的表 vs 数据库实际的表 console.log('\n📋 1. 检查表结构完整性\n'); // 获取数据库中所有用户表 const dbTables: any[] = await prisma.$queryRaw` SELECT table_schema, table_name FROM information_schema.tables WHERE table_schema NOT IN ('pg_catalog', 'information_schema', 'pg_toast') AND table_type = 'BASE TABLE' ORDER BY table_schema, table_name; `; // 按 schema 分组显示 const tablesBySchema: Record = {}; for (const t of dbTables) { if (!tablesBySchema[t.table_schema]) { tablesBySchema[t.table_schema] = []; } tablesBySchema[t.table_schema].push(t.table_name); } for (const [schema, tables] of Object.entries(tablesBySchema)) { console.log(`\n${schema}:`); tables.forEach(t => console.log(` - ${t}`)); } // 2. 检查关键表的列结构 console.log('\n\n📋 2. 检查关键表的列结构\n'); const platformUsersCols: any[] = await prisma.$queryRaw` SELECT column_name, data_type, is_nullable, column_default FROM information_schema.columns WHERE table_schema = 'platform_schema' AND table_name = 'users' ORDER BY ordinal_position; `; console.log('platform_schema.users 列结构:'); platformUsersCols.forEach(c => { console.log(` ${c.column_name}: ${c.data_type} ${c.is_nullable === 'NO' ? 'NOT NULL' : 'NULLABLE'}`); }); // 3. 检查枚举类型 console.log('\n\n📋 3. 检查枚举类型\n'); const enums: any[] = await prisma.$queryRaw` SELECT n.nspname as schema, t.typname as enum_name, string_agg(e.enumlabel, ', ' ORDER BY e.enumsortorder) as values FROM pg_type t JOIN pg_enum e ON t.oid = e.enumtypid JOIN pg_namespace n ON t.typnamespace = n.oid WHERE n.nspname NOT IN ('pg_catalog', 'information_schema') GROUP BY n.nspname, t.typname ORDER BY n.nspname, t.typname; `; enums.forEach(e => { console.log(` ${e.schema}.${e.enum_name}: [${e.values}]`); }); // 4. 验证 Prisma 连接和基本操作 console.log('\n\n📋 4. 验证 Prisma ORM 基本操作\n'); try { // 测试读取用户 const userCount = await prisma.user.count(); console.log(` ✅ User.count(): ${userCount}`); // 测试读取租户 const tenantCount = await prisma.tenant.count(); console.log(` ✅ Tenant.count(): ${tenantCount}`); // 测试读取部门 const deptCount = await prisma.department.count(); console.log(` ✅ Department.count(): ${deptCount}`); // 测试读取权限 const permCount = await prisma.permission.count(); console.log(` ✅ Permission.count(): ${permCount}`); // 测试读取 Prompt 模板 const promptCount = await prisma.promptTemplate.count(); console.log(` ✅ PromptTemplate.count(): ${promptCount}`); // 测试关联查询 const userWithTenant = await prisma.user.findFirst({ include: { tenant: true, department: true } }); if (userWithTenant) { console.log(` ✅ 关联查询成功: ${userWithTenant.name} @ ${userWithTenant.tenant?.name || '无租户'}`); } } catch (e: any) { console.log(` ❌ Prisma 操作失败: ${e.message}`); } // 5. 验证其他模块的表是否可访问 console.log('\n\n📋 5. 验证其他模块表的可访问性\n'); const moduleTests = [ { name: 'AIA Projects', query: 'SELECT COUNT(*) as count FROM aia_schema.projects' }, { name: 'ASL Screening Projects', query: 'SELECT COUNT(*) as count FROM asl_schema.screening_projects' }, { name: 'ASL Literatures', query: 'SELECT COUNT(*) as count FROM asl_schema.literatures' }, { name: 'DC Templates', query: 'SELECT COUNT(*) as count FROM dc_schema.dc_templates' }, { name: 'DC Extraction Tasks', query: 'SELECT COUNT(*) as count FROM dc_schema.dc_extraction_tasks' }, { name: 'IIT Projects', query: 'SELECT COUNT(*) as count FROM iit_schema.projects' }, { name: 'PKB Knowledge Bases', query: 'SELECT COUNT(*) as count FROM pkb_schema.knowledge_bases' }, { name: 'PKB Documents', query: 'SELECT COUNT(*) as count FROM pkb_schema.documents' }, { name: 'RVW Review Tasks', query: 'SELECT COUNT(*) as count FROM rvw_schema.review_tasks' }, ]; for (const test of moduleTests) { try { const result: any = await prisma.$queryRawUnsafe(test.query); console.log(` ✅ ${test.name}: ${result[0].count} 条记录 (表存在)`); } catch (e: any) { console.log(` ❌ ${test.name}: 表不存在或查询失败`); } } // 6. 检查外键约束 console.log('\n\n📋 6. 检查外键约束\n'); const fks: any[] = await prisma.$queryRaw` SELECT tc.table_schema, tc.table_name, kcu.column_name, ccu.table_schema AS foreign_table_schema, ccu.table_name AS foreign_table_name, ccu.column_name AS foreign_column_name FROM information_schema.table_constraints AS tc JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema JOIN information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name WHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_schema IN ('platform_schema', 'admin_schema', 'capability_schema') ORDER BY tc.table_schema, tc.table_name; `; fks.forEach(fk => { console.log(` ${fk.table_schema}.${fk.table_name}.${fk.column_name} -> ${fk.foreign_table_schema}.${fk.foreign_table_name}.${fk.foreign_column_name}`); }); console.log('\n\n' + '=' .repeat(60)); console.log('✅ 系统验证完成!'); } main() .catch(console.error) .finally(() => prisma.$disconnect());