import Fastify from 'fastify'; import cors from '@fastify/cors'; import multipart from '@fastify/multipart'; import { config, validateEnv } from './config/env.js'; import { testDatabaseConnection, prisma } from './config/database.js'; import { projectRoutes } from './legacy/routes/projects.js'; import { agentRoutes } from './legacy/routes/agents.js'; import { conversationRoutes } from './legacy/routes/conversations.js'; import knowledgeBaseRoutes from './legacy/routes/knowledgeBases.js'; import { chatRoutes } from './legacy/routes/chatRoutes.js'; import { batchRoutes } from './legacy/routes/batchRoutes.js'; import reviewRoutes from './legacy/routes/reviewRoutes.js'; import { rvwRoutes } from './modules/rvw/index.js'; import { aslRoutes } from './modules/asl/routes/index.js'; import { registerDCRoutes, initDCModule } from './modules/dc/index.js'; import pkbRoutes from './modules/pkb/routes/index.js'; import { aiaRoutes } from './modules/aia/index.js'; import { registerHealthRoutes } from './common/health/index.js'; import { logger } from './common/logging/index.js'; import { authRoutes, registerAuthPlugin } from './common/auth/index.js'; import { promptRoutes } from './common/prompt/index.js'; import { registerTestRoutes } from './test-platform-api.js'; import { registerScreeningWorkers } from './modules/asl/services/screeningWorker.js'; import { registerExtractionWorkers } from './modules/dc/tool-b/workers/extractionWorker.js'; import { registerParseExcelWorker } from './modules/dc/tool-c/workers/parseExcelWorker.js'; import { registerReviewWorker } from './modules/rvw/workers/reviewWorker.js'; import { jobQueue } from './common/jobs/index.js'; // 全局处理BigInt序列化 (BigInt.prototype as any).toJSON = function() { return Number(this); }; // 生产环境使用JSON格式日志(性能更好),开发环境使用pino-pretty(易读) const fastify = Fastify({ logger: config.nodeEnv === 'production' ? { level: config.logLevel, // 生产环境:简单的JSON日志,适合日志收集系统 } : { level: config.logLevel, // 开发环境:使用pino-pretty美化输出 transport: { target: 'pino-pretty', options: { colorize: true, translateTime: 'HH:MM:ss Z', ignore: 'pid,hostname', }, }, }, }); // 注册CORS插件 - 完整配置 await fastify.register(cors, { origin: true, // 开发环境允许所有来源 credentials: true, methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS', 'HEAD'], // 明确允许的HTTP方法 allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With', 'Accept', 'Origin'], // 允许的请求头 exposedHeaders: ['Content-Range', 'X-Content-Range'], // 暴露的响应头 maxAge: 600, // preflight请求缓存时间(秒) preflightContinue: false, // Fastify处理preflight请求 }); console.log('✅ CORS已配置: 允许所有HTTP方法 (GET, POST, PUT, DELETE, PATCH, OPTIONS)'); // 注册文件上传插件 await fastify.register(multipart, { limits: { fileSize: 10 * 1024 * 1024, // 10MB }, }); console.log('✅ 文件上传插件已配置: 最大文件大小 10MB'); // ============================================ // 【平台基础设施】健康检查路由 // ============================================ // 注册健康检查路由(/health, /health/liveness, /health/readiness) await registerHealthRoutes(fastify); logger.info('✅ 健康检查路由已注册'); // ============================================ // 【平台基础设施】认证模块 // ============================================ await registerAuthPlugin(fastify); await fastify.register(authRoutes, { prefix: '/api/v1/auth' }); logger.info('✅ 认证路由已注册: /api/v1/auth'); // ============================================ // 【运营管理】Prompt管理模块 // ============================================ await fastify.register(promptRoutes, { prefix: '/api/admin/prompts' }); logger.info('✅ Prompt管理路由已注册: /api/admin/prompts'); // ============================================ // 【运营管理】租户管理模块 // ============================================ import { tenantRoutes, moduleRoutes } from './modules/admin/routes/tenantRoutes.js'; import { userRoutes } from './modules/admin/routes/userRoutes.js'; await fastify.register(tenantRoutes, { prefix: '/api/admin/tenants' }); await fastify.register(moduleRoutes, { prefix: '/api/admin/modules' }); await fastify.register(userRoutes, { prefix: '/api/admin/users' }); logger.info('✅ 运营管理路由已注册: /api/admin/tenants, /api/admin/modules, /api/admin/users'); // ============================================ // 【临时】平台基础设施测试API // ============================================ await registerTestRoutes(fastify); logger.info('✅ 测试API已注册: /test/platform'); // API路由前缀 fastify.get('/api/v1', async () => { return { message: 'AI Clinical Research Platform API', version: '1.0.0', environment: config.nodeEnv, }; }); // 注册项目管理路由 await fastify.register(projectRoutes, { prefix: '/api/v1' }); // 注册智能体管理路由 await fastify.register(agentRoutes, { prefix: '/api/v1' }); // 注册对话管理路由 await fastify.register(conversationRoutes, { prefix: '/api/v1' }); // 注册知识库管理路由 await fastify.register(knowledgeBaseRoutes, { prefix: '/api/v1' }); // 注册通用对话路由 await fastify.register(chatRoutes, { prefix: '/api/v1' }); // Phase 3: 注册批处理路由 await fastify.register(batchRoutes, { prefix: '/api/v1' }); // 注册稿件审查路由(旧版,保留兼容) await fastify.register(reviewRoutes, { prefix: '/api/v1' }); // ============================================ // 【业务模块】RVW - 稿件审查系统 // ============================================ await fastify.register(rvwRoutes, { prefix: '/api/v1/rvw' }); logger.info('✅ RVW稿件审查路由已注册: /api/v1/rvw'); // ============================================ // 【业务模块】PKB - 个人知识库 // ============================================ await fastify.register(pkbRoutes, { prefix: '/api/v1/pkb' }); logger.info('✅ PKB个人知识库路由已注册: /api/v1/pkb'); // ============================================ // 【业务模块】AIA - AI智能问答 // ============================================ await fastify.register(aiaRoutes, { prefix: '/api/v1/aia' }); logger.info('✅ AIA智能问答路由已注册: /api/v1/aia'); // ============================================ // 【业务模块】ASL - AI智能文献筛选 // ============================================ await fastify.register(aslRoutes, { prefix: '/api/v1/asl' }); logger.info('✅ ASL智能文献筛选路由已注册: /api/v1/asl'); // ============================================ // 【业务模块】DC - 数据清洗整理 // ============================================ await registerDCRoutes(fastify); logger.info('✅ DC数据清洗模块路由已注册: /api/v1/dc/tool-b'); // ============================================ // 【业务模块】IIT Manager Agent - IIT研究智能助手 // ============================================ import { registerIitRoutes, initIitManager } from './modules/iit-manager/index.js'; await registerIitRoutes(fastify); logger.info('✅ IIT Manager Agent路由已注册: /api/v1/iit'); // 启动服务器 const start = async () => { try { // 验证环境变量 validateEnv(); // 测试数据库连接 console.log('🔍 正在测试数据库连接...'); const dbConnected = await testDatabaseConnection(); if (!dbConnected) { console.error('❌ 数据库连接失败,无法启动服务器'); process.exit(1); } // ============================================ // 【Postgres-Only】启动队列和注册Workers // ============================================ try { logger.info('🚀 Starting Postgres-Only queue and workers...'); // 启动队列(pg-boss) await jobQueue.start(); logger.info('✅ Queue started (pg-boss)'); // 注册ASL筛选Workers registerScreeningWorkers(); logger.info('✅ ASL screening workers registered'); // 注册DC提取Workers registerExtractionWorkers(); logger.info('✅ DC extraction workers registered'); // 注册DC Tool C Excel解析Worker registerParseExcelWorker(); logger.info('✅ DC Tool C parse excel worker registered'); // 注册RVW审稿Worker registerReviewWorker(); logger.info('✅ RVW review worker registered'); // 注册IIT Manager Workers await initIitManager(); logger.info('✅ IIT Manager workers registered'); // ⚠️ 等待3秒,确保所有 Worker 异步注册到 pg-boss 完成 console.log('\n⏳ 等待 Workers 异步注册完成...'); await new Promise(resolve => setTimeout(resolve, 3000)); logger.info('✅ All workers registration completed (waited 3s)'); console.log('\n' + '='.repeat(60)); console.log('✅ Postgres-Only 架构已启动'); console.log('='.repeat(60)); console.log('📦 队列类型: pg-boss'); console.log('📦 缓存类型: PostgreSQL'); console.log('📦 注册的Workers:'); console.log(' - asl_screening_batch (文献筛选批次处理)'); console.log(' - dc_extraction_batch (数据提取批次处理)'); console.log(' - dc_toolc_parse_excel (Tool C Excel解析)'); console.log(' - rvw_review_task (稿件审查任务)'); console.log(' - iit_quality_check (IIT质控+企微推送)'); console.log(' - iit_redcap_poll (IIT REDCap轮询)'); console.log('='.repeat(60) + '\n'); } catch (error) { logger.error('❌ Failed to start Postgres-Only architecture', { error }); console.error('❌ Postgres-Only 架构启动失败:', error); process.exit(1); } // 初始化DC模块(Seed预设模板) try { await initDCModule(); logger.info('✅ DC模块初始化成功'); } catch (error) { logger.warn('⚠️ DC模块初始化失败,但不影响启动', { error }); } // 启动Fastify服务器 await fastify.listen({ port: config.port, host: config.host, }); console.log('\n' + '='.repeat(60)); console.log('🚀 AI临床研究平台 - 后端服务器启动成功!'); console.log('='.repeat(60)); console.log(`📍 服务地址: http://${config.host === '0.0.0.0' ? 'localhost' : config.host}:${config.port}`); console.log(`🔍 健康检查: http://localhost:${config.port}/health`); console.log(`📡 API入口: http://localhost:${config.port}/api/v1`); console.log(`🌍 运行环境: ${config.nodeEnv}`); console.log('='.repeat(60) + '\n'); } catch (err) { fastify.log.error(err); process.exit(1); } }; start();