Files
xlxumu/backend/api/server.js
mapleaf bd379d505c ```
refactor(server): 更新服务器配置和部署脚本- 更改默认端口为3350,以适应生产环境。
- 增加了API信息端点,提供更详细的API状态信息。
- 提高了速率限制,以适应生产环境的更高请求量。
- 添加了错误处理中间件和404处理,增强了错误处理能力。
- 添加了优雅关机处理,确保服务器在接收到SIGINT或SIGTERM信号时能够优雅关闭。- 创建了生产环境配置文件示例 `.env.production.example`,并提供了详细的部署指南 `DEPLOYMENT_GUIDE.md`。
- 添加了启动脚本 `start-server.sh` 和同步脚本 `sync-to-server.sh`,简化了部署流程。
- 配置了Nginx配置文件 `xlxumu-api.conf`,支持HTTPS和反向代理。
```
2025-09-11 17:11:12 +08:00

213 lines
5.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const express = require('express');
const cors = require('cors');
const helmet = require('helmet');
const dotenv = require('dotenv');
const rateLimit = require('express-rate-limit');
// 加载环境变量
dotenv.config();
// 创建Express应用
const app = express();
const PORT = process.env.PORT || 3350; // 生产环境使用3350端口
// 中间件
app.use(helmet()); // 安全头部
app.use(cors()); // 跨域支持
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: 1000, // 生产环境提高限制
message: '请求过于频繁,请稍后再试'
});
app.use(limiter);
// 基础路由
app.get('/', (req, res) => {
res.json({
message: '欢迎使用锡林郭勒盟地区智慧养殖产业平台API服务',
version: '1.0.0',
environment: process.env.NODE_ENV || 'development',
timestamp: new Date().toISOString(),
docs: 'https://xlapi.jiebanke.com/docs'
});
});
app.get('/health', (req, res) => {
res.json({
status: 'OK',
timestamp: new Date().toISOString(),
uptime: process.uptime(),
memory: process.memoryUsage()
});
});
// API信息端点
app.get('/api/info', (req, res) => {
res.json({
name: 'xlxumu-api',
version: '1.0.0',
environment: process.env.NODE_ENV,
port: PORT,
node_version: process.version,
platform: process.platform
});
});
// 大屏可视化地图数据接口
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((err, req, res, next) => {
console.error('服务器错误:', err.stack);
res.status(500).json({
error: '内部服务器错误',
message: process.env.NODE_ENV === 'development' ? err.message : 'Something went wrong!'
});
});
// 404处理
app.use((req, res) => {
res.status(404).json({
error: '接口未找到',
path: req.path,
method: req.method
});
});
// 优雅关机处理
process.on('SIGINT', () => {
console.log('\n收到SIGINT信号正在优雅关闭服务器...');
process.exit(0);
});
process.on('SIGTERM', () => {
console.log('\n收到SIGTERM信号正在优雅关闭服务器...');
process.exit(0);
});
// 启动服务器
const server = app.listen(PORT, '0.0.0.0', () => {
console.log(`🚀 API服务器正在运行:`);
console.log(` 📍 本地: http://localhost:${PORT}`);
console.log(` 🌐 网络: http://0.0.0.0:${PORT}`);
console.log(` 🏷️ 环境: ${process.env.NODE_ENV || 'development'}`);
console.log(` ⏰ 启动时间: ${new Date().toLocaleString()}`);
});
// 设置超时
server.timeout = 60000;
server.keepAliveTimeout = 5000;
module.exports = app;