285 lines
8.9 KiB
JavaScript
285 lines
8.9 KiB
JavaScript
const express = require('express');
|
||
const http = require('http');
|
||
const cors = require('cors');
|
||
const dotenv = require('dotenv');
|
||
const multer = require('multer');
|
||
const swaggerUi = require('swagger-ui-express');
|
||
const swaggerSpec = require('./config/swagger');
|
||
const { sequelize } = require('./config/database-simple');
|
||
const logger = require('./utils/logger');
|
||
const {
|
||
apiRateLimiter,
|
||
inputSanitizer,
|
||
sessionTimeoutCheck,
|
||
securityHeaders
|
||
} = require('./middleware/security');
|
||
const { autoOperationLogger } = require('./middleware/autoOperationLogger');
|
||
|
||
// 加载环境变量
|
||
dotenv.config();
|
||
|
||
// 创建Express应用和HTTP服务器
|
||
const app = express();
|
||
const server = http.createServer(app);
|
||
const PORT = process.env.PORT || 5350;
|
||
|
||
// 配置文件上传
|
||
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());
|
||
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);
|
||
|
||
// 静态文件服务 - 提供前端构建文件
|
||
app.use(express.static(__dirname + '/dist'));
|
||
|
||
// 自动操作日志中间件(在所有API路由之前)
|
||
app.use('/api', autoOperationLogger);
|
||
|
||
// 设置响应头确保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'
|
||
};
|
||
|
||
// 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'));
|
||
|
||
// 牛只档案相关路由(基于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'));
|
||
|
||
// 牛只基础数据路由
|
||
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'));
|
||
|
||
// 智能设备相关路由
|
||
app.use('/api/smart-devices', require('./routes/smart-devices'));
|
||
app.use('/api/iot-jbq-client', require('./routes/iot-jbq-client'));
|
||
|
||
// 智能预警相关路由
|
||
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'));
|
||
|
||
// 报表管理相关路由
|
||
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);
|
||
|
||
// 前端路由 - 处理所有非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: '服务器错误'
|
||
});
|
||
});
|
||
|
||
// 初始化WebSocket
|
||
// webSocketManager.init(server);
|
||
|
||
// 初始化实时数据推送服务
|
||
// const realtimeService = require('./services/realtimeService');
|
||
|
||
// 启动服务器
|
||
server.listen(PORT, '0.0.0.0', () => {
|
||
console.log(`服务器运行在端口 ${PORT}`);
|
||
console.log(`服务器监听所有网络接口 (0.0.0.0:${PORT})`);
|
||
console.log(`API 文档地址: http://localhost:${PORT}/api-docs`);
|
||
|
||
// 启动实时数据推送服务
|
||
// realtimeService.start();
|
||
// console.log(`实时数据推送服务已启动`);
|
||
|
||
logger.info(`宁夏智慧养殖监管平台服务器启动成功,端口: ${PORT}`);
|
||
});
|
||
|
||
// 导出app供其他模块使用
|
||
module.exports = { app }; |