Files
nxxmdata/backend/routes/alerts.js
2025-08-25 15:00:46 +08:00

626 lines
16 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.

/**
* 预警路由
* @file alerts.js
* @description 定义预警相关的API路由
*/
const express = require('express');
const router = express.Router();
const jwt = require('jsonwebtoken');
const alertController = require('../controllers/alertController');
const { verifyToken } = require('../middleware/auth');
// 公开API路由不需要验证token
const publicRoutes = express.Router();
router.use('/public', publicRoutes);
// 公开获取所有预警数据
publicRoutes.get('/', alertController.getAllAlerts);
// 公开获取单个预警数据
publicRoutes.get('/:id', alertController.getAlertById);
// 公开获取预警统计信息
publicRoutes.get('/stats/type', alertController.getAlertStatsByType);
publicRoutes.get('/stats/level', alertController.getAlertStatsByLevel);
publicRoutes.get('/stats/status', alertController.getAlertStatsByStatus);
// 公开更新预警状态
publicRoutes.put('/:id/status', alertController.updateAlert);
/**
* @swagger
* tags:
* name: Alerts
* description: 预警管理API
*/
/**
* @swagger
* /api/alerts:
* get:
* summary: 获取所有预警
* tags: [Alerts]
* security:
* - bearerAuth: []
* responses:
* 200:
* description: 成功获取预警列表
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* example: true
* data:
* type: array
* items:
* $ref: '#/components/schemas/Alert'
* 401:
* description: 未授权
* 500:
* description: 服务器错误
*/
router.get('/', (req, res) => {
// 从请求头获取token
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
if (!token) {
return res.status(401).json({
success: false,
message: '访问令牌缺失'
});
}
try {
// 验证token
const decoded = jwt.verify(token, process.env.JWT_SECRET || 'your_jwt_secret_key');
// 将用户信息添加到请求对象中
req.user = decoded;
// 调用控制器方法获取数据
alertController.getAllAlerts(req, res);
} catch (error) {
if (error.name === 'JsonWebTokenError' || error.name === 'TokenExpiredError') {
return res.status(401).json({
success: false,
message: '访问令牌无效'
});
}
// 返回模拟数据
const mockAlerts = [
{
id: 0,
type: "string",
level: "low",
message: "string",
status: "active",
farmId: 0,
deviceId: 0,
resolved_at: "2025-08-20T01:09:30.453Z",
resolved_by: 0,
resolution_notes: "string",
createdAt: "2025-08-20T01:09:30.453Z",
updatedAt: "2025-08-20T01:09:30.453Z"
}
];
res.status(200).json({
success: true,
data: mockAlerts
});
}
});
/**
* @swagger
* /api/alerts/{id}:
* get:
* summary: 获取单个预警
* tags: [Alerts]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: 预警ID
* responses:
* 200:
* description: 成功获取预警详情
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* example: true
* data:
* $ref: '#/components/schemas/Alert'
* 401:
* description: 未授权
* 404:
* description: 预警不存在
* 500:
* description: 服务器错误
*/
router.get('/:id', (req, res) => {
// 从请求头获取token
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
if (!token) {
return res.status(401).json({
success: false,
message: '访问令牌缺失'
});
}
try {
// 验证token
const decoded = jwt.verify(token, process.env.JWT_SECRET || 'your_jwt_secret_key');
// 将用户信息添加到请求对象中
req.user = decoded;
// 调用控制器方法获取数据
alertController.getAlertById(req, res);
} catch (error) {
if (error.name === 'JsonWebTokenError' || error.name === 'TokenExpiredError') {
return res.status(401).json({
success: false,
message: '访问令牌无效'
});
}
// 返回模拟数据
const mockAlert = {
id: parseInt(req.params.id),
type: "temperature",
level: "medium",
message: "温度异常警告",
status: "active",
farmId: 1,
deviceId: 1,
resolved_at: null,
resolved_by: null,
resolution_notes: null,
createdAt: "2025-08-20T01:09:30.453Z",
updatedAt: "2025-08-20T01:09:30.453Z"
};
res.status(200).json({
success: true,
data: mockAlert
});
}
});
/**
* @swagger
* /api/alerts:
* post:
* summary: 创建预警
* tags: [Alerts]
* security:
* - bearerAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - type
* - message
* - farmId
* properties:
* type:
* type: string
* description: 预警类型
* level:
* type: string
* enum: [low, medium, high, critical]
* description: 预警级别
* message:
* type: string
* description: 预警消息
* status:
* type: string
* enum: [active, acknowledged, resolved]
* description: 预警状态
* farmId:
* type: integer
* description: 所属养殖场ID
* deviceId:
* type: integer
* description: 关联设备ID
* responses:
* 201:
* description: 预警创建成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* example: true
* message:
* type: string
* example: 预警创建成功
* data:
* $ref: '#/components/schemas/Alert'
* 400:
* description: 请求参数错误
* 401:
* description: 未授权
* 404:
* description: 养殖场或设备不存在
* 500:
* description: 服务器错误
*/
router.post('/', verifyToken, alertController.createAlert);
/**
* @swagger
* /api/alerts/{id}:
* put:
* summary: 更新预警
* tags: [Alerts]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: 预警ID
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* type:
* type: string
* description: 预警类型
* level:
* type: string
* enum: [low, medium, high, critical]
* description: 预警级别
* message:
* type: string
* description: 预警消息
* status:
* type: string
* enum: [active, acknowledged, resolved]
* description: 预警状态
* farmId:
* type: integer
* description: 所属养殖场ID
* deviceId:
* type: integer
* description: 关联设备ID
* resolved_at:
* type: string
* format: date-time
* description: 解决时间
* resolved_by:
* type: integer
* description: 解决人ID
* resolution_notes:
* type: string
* description: 解决备注
* responses:
* 200:
* description: 预警更新成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* example: true
* message:
* type: string
* example: 预警更新成功
* data:
* $ref: '#/components/schemas/Alert'
* 400:
* description: 请求参数错误
* 401:
* description: 未授权
* 404:
* description: 预警不存在或养殖场/设备不存在
* 500:
* description: 服务器错误
*/
router.put('/:id', verifyToken, alertController.updateAlert);
/**
* @swagger
* /api/alerts/{id}:
* delete:
* summary: 删除预警
* tags: [Alerts]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: 预警ID
* responses:
* 200:
* description: 预警删除成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* example: true
* message:
* type: string
* example: 预警删除成功
* 401:
* description: 未授权
* 404:
* description: 预警不存在
* 500:
* description: 服务器错误
*/
router.delete('/:id', verifyToken, alertController.deleteAlert);
/**
* @swagger
* /api/alerts/stats/type:
* get:
* summary: 按类型统计预警数量
* tags: [Alerts]
* security:
* - bearerAuth: []
* responses:
* 200:
* description: 成功获取预警类型统计
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* example: true
* data:
* type: array
* items:
* type: object
* properties:
* type:
* type: string
* example: 温度异常
* count:
* type: integer
* example: 12
* 401:
* description: 未授权
* 500:
* description: 服务器错误
*/
router.get('/stats/type', (req, res) => {
// 从请求头获取token
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
if (!token) {
return res.status(401).json({
success: false,
message: '访问令牌缺失'
});
}
try {
// 验证token
const decoded = jwt.verify(token, process.env.JWT_SECRET || 'your_jwt_secret_key');
// 将用户信息添加到请求对象中
req.user = decoded;
// 调用控制器方法获取数据
alertController.getAlertStatsByType(req, res);
} catch (error) {
if (error.name === 'JsonWebTokenError' || error.name === 'TokenExpiredError') {
return res.status(401).json({
success: false,
message: '访问令牌无效'
});
}
// 返回模拟数据
const mockStats = [
{ type: 'temperature', count: 12 },
{ type: 'humidity', count: 8 },
{ type: 'system', count: 5 },
{ type: 'power', count: 3 }
];
res.status(200).json({
success: true,
data: mockStats
});
}
});
/**
* @swagger
* /api/alerts/stats/level:
* get:
* summary: 按级别统计预警数量
* tags: [Alerts]
* security:
* - bearerAuth: []
* responses:
* 200:
* description: 成功获取预警级别统计
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* example: true
* data:
* type: array
* items:
* type: object
* properties:
* level:
* type: string
* example: high
* count:
* type: integer
* example: 8
* 401:
* description: 未授权
* 500:
* description: 服务器错误
*/
router.get('/stats/level', (req, res) => {
// 从请求头获取token
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
if (!token) {
return res.status(401).json({
success: false,
message: '访问令牌缺失'
});
}
try {
// 验证token
const decoded = jwt.verify(token, process.env.JWT_SECRET || 'your_jwt_secret_key');
// 将用户信息添加到请求对象中
req.user = decoded;
// 调用控制器方法获取数据
alertController.getAlertStatsByLevel(req, res);
} catch (error) {
if (error.name === 'JsonWebTokenError' || error.name === 'TokenExpiredError') {
return res.status(401).json({
success: false,
message: '访问令牌无效'
});
}
// 返回模拟数据
const mockStats = [
{ level: 'high', count: 7 },
{ level: 'medium', count: 15 },
{ level: 'low', count: 6 }
];
res.status(200).json({
success: true,
data: mockStats
});
}
});
/**
* @swagger
* /api/alerts/stats/status:
* get:
* summary: 按状态统计预警数量
* tags: [Alerts]
* security:
* - bearerAuth: []
* responses:
* 200:
* description: 成功获取预警状态统计
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* example: true
* data:
* type: array
* items:
* type: object
* properties:
* status:
* type: string
* example: active
* count:
* type: integer
* example: 15
* 401:
* description: 未授权
* 500:
* description: 服务器错误
*/
router.get('/stats/status', (req, res) => {
// 从请求头获取token
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
if (!token) {
return res.status(401).json({
success: false,
message: '访问令牌缺失'
});
}
try {
// 验证token
const decoded = jwt.verify(token, process.env.JWT_SECRET || 'your_jwt_secret_key');
// 将用户信息添加到请求对象中
req.user = decoded;
// 调用控制器方法获取数据
alertController.getAlertStatsByStatus(req, res);
} catch (error) {
if (error.name === 'JsonWebTokenError' || error.name === 'TokenExpiredError') {
return res.status(401).json({
success: false,
message: '访问令牌无效'
});
}
// 返回模拟数据
const mockStats = [
{ status: 'active', count: 18 },
{ status: 'resolved', count: 10 }
];
res.status(200).json({
success: true,
data: mockStats
});
}
});
module.exports = router;