Initial commit: 宁夏智慧养殖监管平台
This commit is contained in:
626
backend/routes/alerts.js
Normal file
626
backend/routes/alerts.js
Normal file
@@ -0,0 +1,626 @@
|
||||
/**
|
||||
* 预警路由
|
||||
* @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;
|
||||
Reference in New Issue
Block a user