const express = require('express'); const cors = require('cors'); const path = require('path'); const morgan = require('morgan'); const fs = require('fs'); // 初始化日志目录 const logsDir = path.join(__dirname, 'logs'); if (!fs.existsSync(logsDir)) { fs.mkdirSync(logsDir, { recursive: true }); } // 初始化数据库 require('./db/init'); const authRoutes = require('./routes/auth'); const ticketRoutes = require('./routes/tickets'); const lotteryRoutes = require('./routes/lottery'); const ocrRoutes = require('./routes/ocr'); const { standardLimiter } = require('./middleware/rateLimiter'); const errorHandler = require('./middleware/errorHandler'); const logger = require('./services/logger'); const app = express(); const PORT = process.env.PORT || 4444; // 创建 morgan stream 用于日志 const morganStream = { write: (message) => logger.http(message.trim()) }; // 中间件 app.use(cors()); app.use(express.json({ limit: '10mb' })); app.use(express.urlencoded({ extended: true, limit: '10mb' })); app.use(morgan('combined', { stream: morganStream })); app.use('/uploads', express.static(path.join(__dirname, 'uploads'))); // 全局限流 (应用于所有API) app.use('/api', standardLimiter); // API 路由 app.use('/api/auth', authRoutes); app.use('/api/tickets', ticketRoutes); app.use('/api/lottery', lotteryRoutes); app.use('/api/ocr', ocrRoutes); // 健康检查 app.get('/api/health', (req, res) => { res.json({ status: 'ok', time: new Date().toISOString() }); }); // 静态文件服务 - 前端构建产物 const clientDist = path.join(__dirname, '../client/dist'); app.use(express.static(clientDist)); // SPA 路由 - 所有非 API 请求返回 index.html app.get('*', (req, res) => { res.sendFile(path.join(clientDist, 'index.html')); }); // 全局错误处理 (必须放在最后) app.use(errorHandler); app.listen(PORT, '0.0.0.0', () => { logger.info(`服务器运行在 http://0.0.0.0:${PORT}`); });