Files
nxxmdata/backend/server.js

287 lines
9.0 KiB
JavaScript
Raw Normal View History

const express = require('express');
2025-09-12 20:08:42 +08:00
const http = require('http');
const cors = require('cors');
const dotenv = require('dotenv');
2025-09-12 20:08:42 +08:00
const multer = require('multer');
const swaggerUi = require('swagger-ui-express');
const swaggerSpec = require('./config/swagger');
const { sequelize } = require('./config/database-simple');
2025-09-12 20:08:42 +08:00
const webSocketManager = require('./utils/websocket');
const logger = require('./utils/logger');
const {
apiRateLimiter,
inputSanitizer,
sessionTimeoutCheck,
securityHeaders
} = require('./middleware/security');
const { autoOperationLogger } = require('./middleware/autoOperationLogger');
// 加载环境变量
dotenv.config();
2025-09-12 20:08:42 +08:00
// 创建Express应用和HTTP服务器
const app = express();
2025-09-12 20:08:42 +08:00
const server = http.createServer(app);
const PORT = process.env.PORT || 5350;
2025-09-12 20:08:42 +08:00
// 配置文件上传
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads/') // 上传文件保存目录
},
filename: function (req, file, cb) {
// 生成唯一文件名
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
cb(null, file.fieldname + '-' + uniqueSuffix + '.' + file.originalname.split('.').pop());
}
});
const upload = multer({
storage: storage,
limits: {
fileSize: 10 * 1024 * 1024 // 限制文件大小为10MB
},
fileFilter: function (req, file, cb) {
// 只允许Excel文件
const allowedTypes = [
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'application/vnd.ms-excel'
];
if (allowedTypes.includes(file.mimetype)) {
cb(null, true);
} else {
cb(new Error('只允许上传Excel文件(.xlsx或.xls格式)'), false);
}
}
});
// 安全中间件
app.use(securityHeaders);
app.use(apiRateLimiter);
app.use(inputSanitizer);
app.use(sessionTimeoutCheck);
// 基础中间件
app.use(cors());
2025-09-12 20:08:42 +08:00
app.use(express.json({ charset: 'utf8' }));
app.use(express.urlencoded({ extended: true, charset: 'utf8' }));
// API统一中间件
const { apiMiddleware, errorHandler, notFoundHandler } = require('./middleware/apiMiddleware');
app.use('/api', apiMiddleware);
2025-09-12 20:08:42 +08:00
// 静态文件服务 - 提供前端构建文件
app.use(express.static(__dirname + '/dist'));
// 自动操作日志中间件在所有API路由之前
app.use('/api', autoOperationLogger);
2025-09-12 20:08:42 +08:00
// 设置响应头确保UTF-8编码仅对API请求
app.use('/api', (req, res, next) => {
res.setHeader('Content-Type', 'application/json; charset=utf-8');
next();
});
// Swagger 文档路由配置
const swaggerOptions = {
explorer: true,
swaggerOptions: {
docExpansion: 'list',
defaultModelsExpandDepth: 2,
defaultModelExpandDepth: 2,
displayRequestDuration: true,
filter: true,
showExtensions: true,
showCommonExtensions: true,
tryItOutEnabled: true,
persistAuthorization: true,
layout: 'BaseLayout',
deepLinking: true,
displayOperationId: false,
syntaxHighlight: {
activate: true,
theme: 'tomorrow-night'
}
},
customCss: `
.swagger-ui .topbar { background: linear-gradient(135deg, #1890ff 0%, #722ed1 100%); }
.swagger-ui .topbar .download-url-wrapper { display: none; }
.swagger-ui .info { margin: 20px 0; }
.swagger-ui .info .title { color: #1890ff; font-size: 2.5em; }
.swagger-ui .scheme-container { background: #f8f9fa; padding: 15px; border-radius: 8px; }
.swagger-ui .btn.authorize { background: #52c41a; border-color: #52c41a; }
.swagger-ui .btn.authorize:hover { background: #73d13d; border-color: #73d13d; }
.swagger-ui .opblock.opblock-post { border-color: #1890ff; background: rgba(24, 144, 255, 0.1); }
.swagger-ui .opblock.opblock-get { border-color: #52c41a; background: rgba(82, 196, 26, 0.1); }
.swagger-ui .opblock.opblock-put { border-color: #fa8c16; background: rgba(250, 140, 22, 0.1); }
.swagger-ui .opblock.opblock-delete { border-color: #f5222d; background: rgba(245, 34, 45, 0.1); }
.swagger-ui .parameters-col_description p { font-size: 13px; line-height: 1.4; }
.swagger-ui .response-col_description { font-size: 13px; }
.swagger-ui .model-box { background: #fafafa; border: 1px solid #d9d9d9; border-radius: 6px; }
.swagger-ui .model-title { color: #1890ff; font-weight: 600; }
.swagger-ui .prop-type { color: #722ed1; font-weight: 500; }
.swagger-ui .prop-format { color: #fa8c16; }
.swagger-ui .opblock-summary-description { font-size: 14px; color: #595959; }
`,
customSiteTitle: '宁夏智慧养殖监管平台 - API文档',
customfavIcon: '/favicon.ico'
};
2025-09-23 18:13:11 +08:00
// Swagger 文档路由配置 - 使用完整的集成配置
const integratedSwaggerSpec = require('./swagger-integrated');
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(integratedSwaggerSpec, swaggerOptions));
// 基础路由
app.get('/', (req, res) => {
res.json({
message: '宁夏智慧养殖监管平台API服务',
version: '1.0.0',
docs: '/api-docs'
});
});
// 数据库同步
sequelize.sync()
.then(() => {
console.log('数据库同步成功');
})
.catch(err => {
console.error('数据库同步失败:', err);
});
// 认证相关路由
app.use('/api/auth', require('./routes/auth'));
// 用户相关路由
app.use('/api/users', require('./routes/users'));
// 产品相关路由
app.use('/api/products', require('./routes/products'));
// 订单相关路由
app.use('/api/orders', require('./routes/orders'));
// 农场相关路由
app.use('/api/farms', require('./routes/farms'));
// 动物相关路由
app.use('/api/animals', require('./routes/animals'));
2025-09-12 20:08:42 +08:00
// 牛只档案相关路由基于iot_cattle表
app.use('/api/iot-cattle', require('./routes/iot-cattle'));
// 栏舍相关路由
app.use('/api/pens', require('./routes/pens'));
app.use('/api/cattle-pens', require('./routes/cattle-pens'));
app.use('/api/cattle-batches', require('./routes/cattle-batches'));
app.use('/api/cattle-transfer-records', require('./routes/cattle-transfer-records'));
app.use('/api/cattle-exit-records', require('./routes/cattle-exit-records'));
2025-09-15 18:18:41 +08:00
// 牛只基础数据路由
app.use('/api/cattle-user', require('./routes/cattle-user'));
app.use('/api/cattle-type', require('./routes/cattle-type'));
// 设备相关路由
app.use('/api/devices', require('./routes/devices'));
2025-09-12 20:08:42 +08:00
// 智能设备相关路由
app.use('/api/smart-devices', require('./routes/smart-devices'));
2025-09-15 18:18:41 +08:00
app.use('/api/iot-jbq-client', require('./routes/iot-jbq-client'));
2025-09-12 20:08:42 +08:00
// 智能预警相关路由
app.use('/api/smart-alerts', require('./routes/smart-alerts'));
// 电子围栏相关路由
app.use('/api/electronic-fence', require('./routes/electronic-fence'));
// 电子围栏坐标点相关路由
app.use('/api/electronic-fence-points', require('./routes/electronic-fence-points'));
// 预警相关路由
app.use('/api/alerts', require('./routes/alerts'));
// 统计数据相关路由
app.use('/api/stats', require('./routes/stats'));
// 百度地图API相关路由
app.use('/api/map', require('./routes/map'));
2025-09-12 20:08:42 +08:00
// 报表管理相关路由
app.use('/api/reports', require('./routes/reports'));
// 系统管理相关路由
app.use('/api/system', require('./routes/system'));
// 数据备份相关路由
app.use('/api/backup', require('./routes/backup'));
// 菜单管理相关路由
app.use('/api/menus', require('./routes/menus'));
// 角色权限管理相关路由
app.use('/api/role-permissions', require('./routes/role-permissions'));
// 表单日志相关路由
app.use('/api/form-logs', require('./routes/formLogs'));
// 操作日志相关路由
app.use('/api/operation-logs', require('./routes/operationLogs'));
// 绑定信息相关路由
app.use('/api/binding', require('./routes/binding'));
// API演示路由
app.use('/api/demo', require('./routes/api-demo'));
// 统一错误处理中间件
app.use(errorHandler);
// 404处理中间件
app.use(notFoundHandler);
2025-09-12 20:08:42 +08:00
// 前端路由 - 处理所有非API请求返回前端应用
app.get('*', (req, res) => {
// 如果是API请求跳过
if (req.path.startsWith('/api')) {
return res.status(404).json({
success: false,
message: 'API接口不存在'
});
}
// 返回前端应用
res.sendFile(__dirname + '/dist/index.html');
});
// 错误处理中间件
app.use((err, req, res, next) => {
console.error('服务器错误:', err);
res.status(500).json({
success: false,
message: '服务器错误'
});
});
2025-09-12 20:08:42 +08:00
// 初始化WebSocket
webSocketManager.init(server);
// 初始化实时数据推送服务
const realtimeService = require('./services/realtimeService');
// 启动服务器
2025-09-12 20:08:42 +08:00
server.listen(PORT, '0.0.0.0', () => {
console.log(`服务器运行在端口 ${PORT}`);
2025-09-12 20:08:42 +08:00
console.log(`服务器监听所有网络接口 (0.0.0.0:${PORT})`);
console.log(`API 文档地址: http://localhost:${PORT}/api-docs`);
2025-09-12 20:08:42 +08:00
console.log(`WebSocket 服务已启动`);
// 启动实时数据推送服务
realtimeService.start();
console.log(`实时数据推送服务已启动`);
logger.info(`宁夏智慧养殖监管平台服务器启动成功,端口: ${PORT}`);
});
2025-09-12 20:08:42 +08:00
// 导出app和webSocketManager供其他模块使用
module.exports = { app, webSocketManager };