const express = require('express'); const cors = require('cors'); const helmet = require('helmet'); const dotenv = require('dotenv'); const rateLimit = require('express-rate-limit'); const mysql = require('mysql2/promise'); const path = require('path'); // 导入路由模块 const authModule = require('./routes/auth'); const usersModule = require('./routes/users'); const cattleModule = require('./routes/cattle'); const financeModule = require('./routes/finance'); const tradingModule = require('./routes/trading'); const governmentModule = require('./routes/government'); const mallModule = require('./routes/mall'); // 加载环境变量 dotenv.config(); // 数据库连接 let pool, testDatabaseConnection; if (process.env.DB_TYPE === 'sqlite') { // 使用SQLite const sqliteDb = require('./database-sqlite'); pool = sqliteDb.pool; testDatabaseConnection = sqliteDb.testDatabaseConnection; } else { // 使用MySQL const mysql = require('mysql2/promise'); // 数据库连接配置 const dbConfig = { host: process.env.DB_HOST, port: process.env.DB_PORT, user: process.env.DB_USER, password: process.env.DB_PASSWORD, database: process.env.DB_NAME, charset: process.env.DB_CHARSET || 'utf8mb4', connectionLimit: 10, acquireTimeout: 60000, timeout: 60000 }; // 创建数据库连接池 pool = mysql.createPool(dbConfig); // 测试数据库连接 testDatabaseConnection = async function() { try { const connection = await pool.getConnection(); console.log('✅ MySQL数据库连接成功'); console.log(`📍 连接到: ${process.env.DB_HOST}:${process.env.DB_PORT}/${process.env.DB_NAME}`); connection.release(); return true; } catch (error) { console.error('❌ 数据库连接失败:', error.message); console.log('⚠️ 服务将继续运行,但数据库功能不可用'); return false; } }; } // 创建Express应用 const app = express(); const PORT = process.env.PORT || 8888; // 初始化数据库和中间件的异步函数 async function initializeApp() { // 启动时测试数据库连接 await testDatabaseConnection(); // 设置路由模块的数据库连接 authModule.setPool(pool); usersModule.setMiddleware(authModule.authenticateToken, authModule.checkPermission, pool); cattleModule.setMiddleware(authModule.authenticateToken, authModule.checkPermission, pool); financeModule.setMiddleware(authModule.authenticateToken, authModule.checkPermission, pool); tradingModule.setMiddleware(authModule.authenticateToken, authModule.checkPermission, pool); governmentModule.setMiddleware(authModule.authenticateToken, authModule.checkPermission, pool); mallModule.setMiddleware(authModule.authenticateToken, authModule.checkPermission, pool); console.log('✅ 中间件初始化完成'); } // 初始化应用(不阻塞服务启动) initializeApp().catch(console.error); // 导入错误处理中间件 const { errorHandler, notFoundHandler, requestLogger, performanceMonitor } = require('./middleware/errorHandler'); // 中间件 app.use(requestLogger); // 请求日志 app.use(performanceMonitor); // 性能监控 app.use(helmet()); // 安全头部 app.use(cors({ origin: process.env.CORS_ORIGIN || '*', credentials: true })); // 跨域支持 app.use(express.json({ limit: '10mb' })); // JSON解析 app.use(express.urlencoded({ extended: true, limit: '10mb' })); // URL编码解析 // 速率限制 const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15分钟 max: 100, // 限制每个IP 15分钟内最多100个请求 message: '请求过于频繁,请稍后再试' }); app.use(limiter); // 基础路由 app.get('/', (req, res) => { res.json({ message: '欢迎使用锡林郭勒盟地区智慧养殖产业平台API服务', version: '1.0.0', timestamp: new Date().toISOString() }); }); app.get('/health', async (req, res) => { try { // 测试数据库连接 const connection = await pool.getConnection(); const [rows] = await connection.execute('SELECT 1 as test'); connection.release(); res.json({ status: 'OK', timestamp: new Date().toISOString(), database: 'Connected', environment: process.env.NODE_ENV, version: '1.0.0' }); } catch (error) { res.status(500).json({ status: 'ERROR', timestamp: new Date().toISOString(), database: 'Disconnected', error: error.message }); } }); // API路由 app.use('/api/v1/auth', authModule.router); app.use('/api/v1/users', usersModule.router); app.use('/api/v1/cattle', cattleModule.router); app.use('/api/v1/finance', financeModule.router); app.use('/api/v1/trading', tradingModule.router); app.use('/api/v1/government', governmentModule.router); app.use('/api/v1/mall', mallModule.router); // 数据库查询接口 app.get('/api/v1/database/tables', async (req, res) => { try { const [tables] = await pool.execute( 'SELECT TABLE_NAME, TABLE_COMMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA = ?', [process.env.DB_NAME] ); res.json({ success: true, data: { database: process.env.DB_NAME, tables: tables, count: tables.length }, timestamp: new Date().toISOString() }); } catch (error) { res.status(500).json({ success: false, error: error.message, timestamp: new Date().toISOString() }); } }); // 数据库连接状态接口 app.get('/api/v1/database/status', async (req, res) => { try { const [statusResult] = await pool.execute('SHOW STATUS LIKE "Threads_connected"'); const [versionResult] = await pool.execute('SELECT VERSION() as version'); res.json({ success: true, data: { connected: true, version: versionResult[0].version, threads_connected: statusResult[0].Value, database: process.env.DB_NAME, host: process.env.DB_HOST, port: process.env.DB_PORT }, timestamp: new Date().toISOString() }); } catch (error) { res.status(500).json({ success: false, error: error.message, timestamp: new Date().toISOString() }); } }); app.get('/api/v1/dashboard/map/regions', (req, res) => { // 模拟锡林郭勒盟各区域数据 const regions = [ { id: 'xlg', name: '锡林浩特市', coordinates: [116.093, 43.946], cattle_count: 25600, farm_count: 120, output_value: 650000000 }, { id: 'dwq', name: '东乌旗', coordinates: [116.980, 45.514], cattle_count: 18500, farm_count: 95, output_value: 480000000 }, { id: 'xwq', name: '西乌旗', coordinates: [117.615, 44.587], cattle_count: 21200, farm_count: 108, output_value: 520000000 }, { id: 'abg', name: '阿巴嘎旗', coordinates: [114.971, 44.022], cattle_count: 16800, farm_count: 86, output_value: 420000000 }, { id: 'snz', name: '苏尼特左旗', coordinates: [113.653, 43.859], cattle_count: 12400, farm_count: 65, output_value: 310000000 } ]; res.json({ regions }); }); app.get('/api/v1/dashboard/map/region/:regionId', (req, res) => { const { regionId } = req.params; // 模拟各区域详细数据 const regionDetails = { 'xlg': { region: { id: 'xlg', name: '锡林浩特市', coordinates: [116.093, 43.946], cattle_count: 25600, farm_count: 120, output_value: 650000000, trend: 'up' }, farms: [ { id: 'FARM001', name: '锡林浩特市第一牧场', coordinates: [116.120, 43.950], cattle_count: 2450, output_value: 62000000 }, { id: 'FARM002', name: '锡林浩特市第二牧场', coordinates: [116.080, 43.930], cattle_count: 2100, output_value: 53000000 } ] }, 'dwq': { region: { id: 'dwq', name: '东乌旗', coordinates: [116.980, 45.514], cattle_count: 18500, farm_count: 95, output_value: 480000000, trend: 'up' }, farms: [ { id: 'FARM003', name: '东乌旗牧场A', coordinates: [116.990, 45.520], cattle_count: 1950, output_value: 49000000 } ] } }; const detail = regionDetails[regionId]; if (detail) { res.json(detail); } else { res.status(404).json({ error: '区域未找到' }); } }); // 错误处理中间件(必须放在所有路由之后) app.use(notFoundHandler); // 404处理 app.use(errorHandler); // 统一错误处理 // 启动服务器 const HOST = process.env.HOST || '0.0.0.0'; app.listen(PORT, HOST, () => { console.log(`API服务器正在监听: http://${HOST}:${PORT}`); console.log(`服务器绑定到: ${HOST}, 端口: ${PORT}`); console.log('尝试使用以下URL访问:'); console.log(` http://localhost:${PORT}`); console.log(` http://127.0.0.1:${PORT}`); }); module.exports = app;