| 
									
										
										
										
											2025-09-24 10:02:03 +08:00
										 |  |  |  | // 加载环境变量配置
 | 
					
						
							|  |  |  |  | require('dotenv').config(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | const express = require('express'); | 
					
						
							|  |  |  |  | const cors = require('cors'); | 
					
						
							|  |  |  |  | const bodyParser = require('body-parser'); | 
					
						
							|  |  |  |  | const path = require('path'); | 
					
						
							|  |  |  |  | const rateLimit = require('express-rate-limit'); | 
					
						
							|  |  |  |  | const helmet = require('helmet'); | 
					
						
							|  |  |  |  | const { initDB, getDB, dbConfig } = require('./database'); | 
					
						
							|  |  |  |  | const { logger } = require('./config/logger'); | 
					
						
							|  |  |  |  | const { errorHandler, notFound } = require('./middleware/errorHandler'); | 
					
						
							|  |  |  |  | const fs = require('fs'); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | const app = express(); | 
					
						
							|  |  |  |  | const PORT = process.env.PORT || 3000; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // 确保日志目录存在
 | 
					
						
							|  |  |  |  | const logDir = path.join(__dirname, 'logs'); | 
					
						
							|  |  |  |  | if (!fs.existsSync(logDir)) { | 
					
						
							|  |  |  |  |   fs.mkdirSync(logDir, { recursive: true }); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // 安全中间件
 | 
					
						
							|  |  |  |  | app.use(helmet({ | 
					
						
							|  |  |  |  |   contentSecurityPolicy: false, // 为了支持前端应用
 | 
					
						
							|  |  |  |  |   crossOriginEmbedderPolicy: false, | 
					
						
							|  |  |  |  |   crossOriginOpenerPolicy: false, // 禁用 COOP 头部以避免非 HTTPS 环境的警告
 | 
					
						
							|  |  |  |  |   originAgentCluster: false // 禁用Origin-Agent-Cluster头部
 | 
					
						
							|  |  |  |  | })); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // 中间件配置
 | 
					
						
							|  |  |  |  | // CORS配置 - 允许前端访问静态资源
 | 
					
						
							|  |  |  |  | app.use(cors({ | 
					
						
							|  |  |  |  |   origin: [ | 
					
						
							|  |  |  |  |     'http://localhost:5173',  | 
					
						
							|  |  |  |  |     'http://localhost:5176',  | 
					
						
							|  |  |  |  |     'http://localhost:5175',  | 
					
						
							|  |  |  |  |     'http://localhost:5174',  | 
					
						
							|  |  |  |  |     'http://localhost:3001', | 
					
						
							|  |  |  |  |     'https://www.zrbjr.com', | 
					
						
							|  |  |  |  |     'https://zrbjr.com' | 
					
						
							|  |  |  |  |   ], | 
					
						
							|  |  |  |  |   credentials: true, | 
					
						
							|  |  |  |  |   methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], | 
					
						
							|  |  |  |  |   allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'] | 
					
						
							|  |  |  |  | })); | 
					
						
							|  |  |  |  | app.use(bodyParser.json({ limit: '10mb' })); | 
					
						
							|  |  |  |  | app.use(bodyParser.urlencoded({ extended: true, limit: '10mb' })); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // 请求日志中间件
 | 
					
						
							|  |  |  |  | app.use((req, res, next) => { | 
					
						
							|  |  |  |  |   const start = Date.now(); | 
					
						
							|  |  |  |  |    | 
					
						
							|  |  |  |  |   res.on('finish', () => { | 
					
						
							|  |  |  |  |     const duration = Date.now() - start; | 
					
						
							|  |  |  |  |      | 
					
						
							|  |  |  |  |     // 只记录非正常状态码的请求日志(过滤掉200、304等正常返回)
 | 
					
						
							|  |  |  |  |     if (res.statusCode >= 400 || res.statusCode < 200) { | 
					
						
							|  |  |  |  |       logger.info('HTTP Request', { | 
					
						
							|  |  |  |  |         method: req.method, | 
					
						
							|  |  |  |  |         url: req.originalUrl, | 
					
						
							|  |  |  |  |         statusCode: res.statusCode, | 
					
						
							|  |  |  |  |         duration: `${duration}ms`, | 
					
						
							|  |  |  |  |         ip: req.ip, | 
					
						
							|  |  |  |  |         userAgent: req.get('User-Agent') | 
					
						
							|  |  |  |  |       }); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   }); | 
					
						
							|  |  |  |  |    | 
					
						
							|  |  |  |  |   next(); | 
					
						
							|  |  |  |  | }); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // 限流中间件
 | 
					
						
							|  |  |  |  | const limiter = rateLimit({ | 
					
						
							|  |  |  |  |   windowMs: 15 * 60 * 1000, // 15分钟
 | 
					
						
							|  |  |  |  |   max: 1000, // 限制每个IP 15分钟内最多100个请求
 | 
					
						
							|  |  |  |  |   message: { | 
					
						
							|  |  |  |  |     success: false, | 
					
						
							|  |  |  |  |     error: { | 
					
						
							|  |  |  |  |       code: 'RATE_LIMIT_EXCEEDED', | 
					
						
							|  |  |  |  |       message: '请求过于频繁,请稍后再试' | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | }); | 
					
						
							| 
									
										
										
										
											2025-09-26 14:38:44 +08:00
										 |  |  |  | app.use('/', limiter); | 
					
						
							| 
									
										
										
										
											2025-09-24 10:02:03 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | // 引入数据库初始化模块
 | 
					
						
							|  |  |  |  | const { initDatabase } = require('./config/database-init'); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-24 15:45:49 +08:00
										 |  |  |  | // 商城后台相关接口
 | 
					
						
							| 
									
										
										
										
											2025-09-26 14:38:44 +08:00
										 |  |  |  | app.use('/shopbackend', require('./routes/shopbackend')); | 
					
						
							|  |  |  |  | //订单管理接口
 | 
					
						
							|  |  |  |  | app.use('/orders', require('./routes/orders')) | 
					
						
							|  |  |  |  | //商品列表
 | 
					
						
							|  |  |  |  | app.use('/products', require('./routes/products')) | 
					
						
							|  |  |  |  | //供应商接口
 | 
					
						
							|  |  |  |  | app.use('/supplier',require('./routes/supplier')) | 
					
						
							|  |  |  |  | //规格处理
 | 
					
						
							|  |  |  |  | app.use('/specifications', require('./routes/specifications')); | 
					
						
							| 
									
										
										
										
											2025-09-28 17:28:40 +08:00
										 |  |  |  | // 优惠券商品接口
 | 
					
						
							|  |  |  |  | app.use('/couponproducts', require('./routes/couponproducts')); | 
					
						
							| 
									
										
										
										
											2025-09-24 10:02:03 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-29 14:58:40 +08:00
										 |  |  |  | // 认证接口
 | 
					
						
							|  |  |  |  | app.use('/auth', require('./routes/auth')); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-24 10:02:03 +08:00
										 |  |  |  | // 404处理
 | 
					
						
							|  |  |  |  | app.use(notFound); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // 全局错误处理中间件
 | 
					
						
							|  |  |  |  | app.use(errorHandler); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // 导出数据库连接供路由使用
 | 
					
						
							|  |  |  |  | module.exports = {  | 
					
						
							|  |  |  |  |   get db() { return getDB(); } | 
					
						
							|  |  |  |  | }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // 启动服务器
 | 
					
						
							|  |  |  |  | app.listen(PORT, async () => { | 
					
						
							|  |  |  |  |   try { | 
					
						
							|  |  |  |  |     logger.info('Server starting', { port: PORT }); | 
					
						
							|  |  |  |  |     console.log(`服务器运行在 http://localhost:${PORT}`); | 
					
						
							|  |  |  |  |      | 
					
						
							|  |  |  |  |     await initDatabase(); | 
					
						
							|  |  |  |  |     global.captchaStore = new Map(); | 
					
						
							|  |  |  |  |     logger.info('Server started successfully', { | 
					
						
							|  |  |  |  |       port: PORT, | 
					
						
							|  |  |  |  |       environment: process.env.NODE_ENV || 'development' | 
					
						
							|  |  |  |  |     }); | 
					
						
							|  |  |  |  |   } catch (error) { | 
					
						
							|  |  |  |  |     logger.error('Failed to start server', { error: error.message }); | 
					
						
							|  |  |  |  |     process.exit(1); | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | }); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // 优雅关闭
 | 
					
						
							|  |  |  |  | process.on('SIGTERM', async () => { | 
					
						
							|  |  |  |  |   logger.info('SIGTERM received, shutting down gracefully'); | 
					
						
							|  |  |  |  |   try { | 
					
						
							|  |  |  |  |     const { closeDB } = require('./database'); | 
					
						
							|  |  |  |  |     await closeDB(); | 
					
						
							|  |  |  |  |   } catch (error) { | 
					
						
							|  |  |  |  |     logger.error('Error closing database', { error: error.message }); | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  |   process.exit(0); | 
					
						
							|  |  |  |  | }); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | process.on('SIGINT', async () => { | 
					
						
							|  |  |  |  |   logger.info('SIGINT received, shutting down gracefully'); | 
					
						
							|  |  |  |  |   try { | 
					
						
							|  |  |  |  |     const { closeDB } = require('./database'); | 
					
						
							|  |  |  |  |     await closeDB(); | 
					
						
							|  |  |  |  |   } catch (error) { | 
					
						
							|  |  |  |  |     logger.error('Error closing database', { error: error.message }); | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  |   process.exit(0); | 
					
						
							|  |  |  |  | }); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | process.on('unhandledRejection', (reason, promise) => { | 
					
						
							|  |  |  |  |   logger.error('Unhandled Rejection', { reason, promise }); | 
					
						
							|  |  |  |  | }); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | process.on('uncaughtException', (error) => { | 
					
						
							|  |  |  |  |   logger.error('Uncaught Exception', { error: error.message, stack: error.stack }); | 
					
						
							|  |  |  |  |   process.exit(1); | 
					
						
							|  |  |  |  | }); |