Files
nxxmdata/backend/routes/smart-alerts.js

760 lines
24 KiB
JavaScript
Raw Normal View History

2025-09-12 20:08:42 +08:00
/**
* 智能预警路由
* @file smart-alerts.js
* @description 定义智能预警相关的API路由
*/
/**
* @swagger
* components:
* parameters:
* PageParam:
* in: query
* name: page
* schema:
* type: integer
* default: 1
* minimum: 1
* description: 页码
* LimitParam:
* in: query
* name: limit
* schema:
* type: integer
* default: 10
* minimum: 1
* maximum: 100
* description: 每页数量
* SearchParam:
* in: query
* name: search
* schema:
* type: string
* description: 搜索关键词
* AlertTypeParam:
* in: query
* name: alertType
* schema:
* type: string
* enum: [battery, offline, temperature, movement, wear]
* description: 预警类型筛选
* AlertLevelParam:
* in: query
* name: alertLevel
* schema:
* type: string
* enum: [high, medium, low]
* description: 预警级别筛选
* StatusParam:
* in: query
* name: status
* schema:
* type: string
* enum: [online, offline, alarm, maintenance]
* description: 设备状态筛选
* StartDateParam:
* in: query
* name: startDate
* schema:
* type: string
* format: date
* description: 开始日期
* EndDateParam:
* in: query
* name: endDate
* schema:
* type: string
* format: date
* description: 结束日期
* AlertIdParam:
* in: path
* name: id
* required: true
* schema:
* type: string
* description: 预警ID
*/
2025-09-12 20:08:42 +08:00
const express = require('express');
const router = express.Router();
const { IotJbqClient, IotXqClient } = require('../models');
const { Op } = require('sequelize');
const smartEartagAlertController = require('../controllers/smartEartagAlertController');
const smartCollarAlertController = require('../controllers/smartCollarAlertController');
2025-09-12 20:08:42 +08:00
// 公开API路由不需要验证token
const publicRoutes = express.Router();
router.use('/public', publicRoutes);
/**
* 获取智能预警统计
*/
publicRoutes.get('/stats', async (req, res) => {
try {
// 获取耳标设备数量
const eartagCount = await IotJbqClient.count();
// 获取项圈设备数量
const collarCount = await IotXqClient.count();
// 生成耳标预警数据与预警列表API使用相同逻辑
const eartagDevices = await IotJbqClient.findAll({
order: [['uptime', 'DESC'], ['id', 'DESC']]
});
const eartagAlerts = [];
eartagDevices.forEach(device => {
const actualBattery = parseInt(device.voltage) || 0;
const actualTemperature = parseFloat(device.temperature) || 0;
const totalSteps = parseInt(device.walk) || 0;
const yesterdaySteps = parseInt(device.y_steps) || 0;
const dailySteps = totalSteps - yesterdaySteps; // 当日步数 = 总步数 - 昨日步数
// 离线预警
if (device.state === 0) {
eartagAlerts.push({ type: 'offline' });
}
// 低电量预警
if (actualBattery > 0 && actualBattery < 20) {
eartagAlerts.push({ type: 'battery' });
}
// 温度预警
if (actualTemperature > 0) {
// 低温预警
if (actualTemperature < 30) {
eartagAlerts.push({ type: 'temperature' });
}
// 高温预警
else if (actualTemperature > 40) {
eartagAlerts.push({ type: 'temperature' });
}
}
// 异常运动预警
// 步数异常预警当日步数为0
if (dailySteps === 0 && totalSteps > 0) {
eartagAlerts.push({ type: 'movement' });
}
});
// 生成项圈预警数据(简化版本)
const collarAlerts = await IotXqClient.count({
where: {
state: 2 // 预警状态
}
});
res.json({
success: true,
data: {
totalAlerts: eartagAlerts.length + collarAlerts,
eartagAlerts: eartagAlerts.length,
collarAlerts: collarAlerts,
eartagDevices: eartagCount,
collarDevices: collarCount
},
message: '获取智能预警统计成功'
});
} catch (error) {
console.error('获取智能预警统计失败:', error);
res.status(500).json({
success: false,
message: '获取智能预警统计失败',
error: error.message
});
}
});
/**
* @swagger
* /smart-alerts/public/eartag/stats:
* get:
* tags:
* - 智能耳标预警
* summary: 获取智能耳标预警统计
* description: 获取智能耳标预警的统计数据包括各类预警的数量和设备总数
* responses:
* 200:
* description: 获取统计成功
* content:
* application/json:
* schema:
* allOf:
* - $ref: '#/components/schemas/ApiResponse'
* - type: object
* properties:
* data:
* $ref: '#/components/schemas/AlertStats'
* 500:
* description: 服务器内部错误
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ErrorResponse'
2025-09-12 20:08:42 +08:00
*/
publicRoutes.get('/eartag/stats', smartEartagAlertController.getEartagAlertStats);
2025-09-12 20:08:42 +08:00
/**
* @swagger
* /smart-alerts/public/eartag:
* get:
* tags:
* - 智能耳标预警
* summary: 获取智能耳标预警列表
* description: 获取智能耳标预警列表支持分页搜索和筛选
* parameters:
* - $ref: '#/components/parameters/PageParam'
* - $ref: '#/components/parameters/LimitParam'
* - $ref: '#/components/parameters/SearchParam'
* - $ref: '#/components/parameters/AlertTypeParam'
* - $ref: '#/components/parameters/AlertLevelParam'
* - $ref: '#/components/parameters/StatusParam'
* - $ref: '#/components/parameters/StartDateParam'
* - $ref: '#/components/parameters/EndDateParam'
* responses:
* 200:
* description: 获取列表成功
* content:
* application/json:
* schema:
* allOf:
* - $ref: '#/components/schemas/ApiResponse'
* - type: object
* properties:
* data:
* type: array
* items:
* $ref: '#/components/schemas/EartagAlert'
* 500:
* description: 服务器内部错误
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ErrorResponse'
*/
publicRoutes.get('/eartag', smartEartagAlertController.getEartagAlerts);
2025-09-12 20:08:42 +08:00
/**
* @swagger
* /smart-alerts/public/eartag/{id}:
* get:
* tags:
* - 智能耳标预警
* summary: 获取单个智能耳标预警详情
* description: 获取指定ID的智能耳标预警详细信息
* parameters:
* - $ref: '#/components/parameters/AlertIdParam'
* responses:
* 200:
* description: 获取详情成功
* content:
* application/json:
* schema:
* allOf:
* - $ref: '#/components/schemas/ApiResponse'
* - type: object
* properties:
* data:
* $ref: '#/components/schemas/EartagAlert'
* 400:
* description: 请求参数错误
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ErrorResponse'
* 404:
* description: 预警不存在
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ErrorResponse'
* 500:
* description: 服务器内部错误
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ErrorResponse'
*/
publicRoutes.get('/eartag/:id', smartEartagAlertController.getEartagAlertById);
2025-09-12 20:08:42 +08:00
/**
* @swagger
* /smart-alerts/public/eartag/{id}/handle:
* post:
* tags:
* - 智能耳标预警
* summary: 处理智能耳标预警
* description: 处理指定的智能耳标预警
* parameters:
* - $ref: '#/components/parameters/AlertIdParam'
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* action:
* type: string
* description: 处理动作
* example: acknowledged
* notes:
* type: string
* description: 处理备注
* example: 已联系技术人员处理
* handler:
* type: string
* description: 处理人
* example: 张三
* responses:
* 200:
* description: 处理成功
* content:
* application/json:
* schema:
* allOf:
* - $ref: '#/components/schemas/ApiResponse'
* - type: object
* properties:
* data:
* type: object
* properties:
* alertId:
* type: string
* action:
* type: string
* notes:
* type: string
* handler:
* type: string
* processedAt:
* type: string
* format: date-time
* status:
* type: string
* 400:
* description: 请求参数错误
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ErrorResponse'
* 500:
* description: 服务器内部错误
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ErrorResponse'
*/
publicRoutes.post('/eartag/:id/handle', smartEartagAlertController.handleEartagAlert);
2025-09-12 20:08:42 +08:00
/**
* @swagger
* /smart-alerts/public/eartag/batch-handle:
* post:
* tags:
* - 智能耳标预警
* summary: 批量处理智能耳标预警
* description: 批量处理多个智能耳标预警
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - alertIds
* properties:
* alertIds:
* type: array
* items:
* type: string
* description: 预警ID列表
* example: ["123_offline", "124_battery"]
* action:
* type: string
* description: 处理动作
* example: acknowledged
* notes:
* type: string
* description: 处理备注
* example: 批量处理完成
* handler:
* type: string
* description: 处理人
* example: 李四
* responses:
* 200:
* description: 批量处理成功
* content:
* application/json:
* schema:
* allOf:
* - $ref: '#/components/schemas/ApiResponse'
* - type: object
* properties:
* data:
* type: object
* properties:
* processedCount:
* type: integer
* results:
* type: array
* items:
* type: object
* 400:
* description: 请求参数错误
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ErrorResponse'
* 500:
* description: 服务器内部错误
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ErrorResponse'
*/
publicRoutes.post('/eartag/batch-handle', smartEartagAlertController.batchHandleEartagAlerts);
2025-09-12 20:08:42 +08:00
/**
* @swagger
* /smart-alerts/public/eartag/export:
* get:
* tags:
* - 智能耳标预警
* summary: 导出智能耳标预警数据
* description: 导出智能耳标预警数据支持JSON和CSV格式
* parameters:
* - $ref: '#/components/parameters/SearchParam'
* - $ref: '#/components/parameters/AlertTypeParam'
* - $ref: '#/components/parameters/AlertLevelParam'
* - $ref: '#/components/parameters/StartDateParam'
* - $ref: '#/components/parameters/EndDateParam'
* - in: query
* name: format
* schema:
* type: string
* enum: [json, csv]
* default: json
* description: 导出格式
* responses:
* 200:
* description: 导出成功
* content:
* application/json:
* schema:
* allOf:
* - $ref: '#/components/schemas/ApiResponse'
* - type: object
* properties:
* data:
* type: array
* items:
* $ref: '#/components/schemas/EartagAlert'
* 500:
* description: 服务器内部错误
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ErrorResponse'
2025-09-12 20:08:42 +08:00
*/
publicRoutes.get('/eartag/export', smartEartagAlertController.exportEartagAlerts);
2025-09-12 20:08:42 +08:00
/**
* @swagger
* /smart-alerts/public/collar/stats:
* get:
* tags:
* - 智能项圈预警
* summary: 获取智能项圈预警统计
* description: 获取智能项圈预警的统计数据包括各类预警的数量和设备总数
* responses:
* 200:
* description: 获取统计成功
* content:
* application/json:
* schema:
* allOf:
* - $ref: '#/components/schemas/ApiResponse'
* - type: object
* properties:
* data:
* $ref: '#/components/schemas/AlertStats'
* 500:
* description: 服务器内部错误
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ErrorResponse'
*/
publicRoutes.get('/collar/stats', smartCollarAlertController.getCollarAlertStats);
2025-09-12 20:08:42 +08:00
/**
* @swagger
* /smart-alerts/public/collar:
* get:
* tags:
* - 智能项圈预警
* summary: 获取智能项圈预警列表
* description: 获取智能项圈预警列表支持分页搜索和筛选
* parameters:
* - $ref: '#/components/parameters/PageParam'
* - $ref: '#/components/parameters/LimitParam'
* - $ref: '#/components/parameters/SearchParam'
* - $ref: '#/components/parameters/AlertTypeParam'
* - $ref: '#/components/parameters/AlertLevelParam'
* - $ref: '#/components/parameters/StatusParam'
* - $ref: '#/components/parameters/StartDateParam'
* - $ref: '#/components/parameters/EndDateParam'
* responses:
* 200:
* description: 获取列表成功
* content:
* application/json:
* schema:
* allOf:
* - $ref: '#/components/schemas/ApiResponse'
* - type: object
* properties:
* data:
* type: array
* items:
* $ref: '#/components/schemas/CollarAlert'
* 500:
* description: 服务器内部错误
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ErrorResponse'
*/
publicRoutes.get('/collar', smartCollarAlertController.getCollarAlerts);
2025-09-12 20:08:42 +08:00
/**
* @swagger
* /smart-alerts/public/collar/{id}:
* get:
* tags:
* - 智能项圈预警
* summary: 获取单个智能项圈预警详情
* description: 获取指定ID的智能项圈预警详细信息
* parameters:
* - $ref: '#/components/parameters/AlertIdParam'
* responses:
* 200:
* description: 获取详情成功
* content:
* application/json:
* schema:
* allOf:
* - $ref: '#/components/schemas/ApiResponse'
* - type: object
* properties:
* data:
* $ref: '#/components/schemas/CollarAlert'
* 400:
* description: 请求参数错误
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ErrorResponse'
* 404:
* description: 预警不存在
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ErrorResponse'
* 500:
* description: 服务器内部错误
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ErrorResponse'
*/
publicRoutes.get('/collar/:id', smartCollarAlertController.getCollarAlertById);
/**
* @swagger
* /smart-alerts/public/collar/{id}/handle:
* post:
* tags:
* - 智能项圈预警
* summary: 处理智能项圈预警
* description: 处理指定的智能项圈预警
* parameters:
* - $ref: '#/components/parameters/AlertIdParam'
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* action:
* type: string
* description: 处理动作
* example: acknowledged
* notes:
* type: string
* description: 处理备注
* example: 已联系技术人员处理
* handler:
* type: string
* description: 处理人
* example: 张三
* responses:
* 200:
* description: 处理成功
* content:
* application/json:
* schema:
* allOf:
* - $ref: '#/components/schemas/ApiResponse'
* - type: object
* properties:
* data:
* type: object
* properties:
* alertId:
* type: string
* action:
* type: string
* notes:
* type: string
* handler:
* type: string
* processedAt:
* type: string
* format: date-time
* status:
* type: string
* 400:
* description: 请求参数错误
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ErrorResponse'
* 500:
* description: 服务器内部错误
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ErrorResponse'
*/
publicRoutes.post('/collar/:id/handle', smartCollarAlertController.handleCollarAlert);
/**
* @swagger
* /smart-alerts/public/collar/batch-handle:
* post:
* tags:
* - 智能项圈预警
* summary: 批量处理智能项圈预警
* description: 批量处理多个智能项圈预警
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - alertIds
* properties:
* alertIds:
* type: array
* items:
* type: string
* description: 预警ID列表
* example: ["123_offline", "124_battery"]
* action:
* type: string
* description: 处理动作
* example: acknowledged
* notes:
* type: string
* description: 处理备注
* example: 批量处理完成
* handler:
* type: string
* description: 处理人
* example: 李四
* responses:
* 200:
* description: 批量处理成功
* content:
* application/json:
* schema:
* allOf:
* - $ref: '#/components/schemas/ApiResponse'
* - type: object
* properties:
* data:
* type: object
* properties:
* processedCount:
* type: integer
* results:
* type: array
* items:
* type: object
* 400:
* description: 请求参数错误
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ErrorResponse'
* 500:
* description: 服务器内部错误
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ErrorResponse'
*/
publicRoutes.post('/collar/batch-handle', smartCollarAlertController.batchHandleCollarAlerts);
/**
* @swagger
* /smart-alerts/public/collar/export:
* get:
* tags:
* - 智能项圈预警
* summary: 导出智能项圈预警数据
* description: 导出智能项圈预警数据支持JSON和CSV格式
* parameters:
* - $ref: '#/components/parameters/SearchParam'
* - $ref: '#/components/parameters/AlertTypeParam'
* - $ref: '#/components/parameters/AlertLevelParam'
* - $ref: '#/components/parameters/StartDateParam'
* - $ref: '#/components/parameters/EndDateParam'
* - in: query
* name: format
* schema:
* type: string
* enum: [json, csv]
* default: json
* description: 导出格式
* responses:
* 200:
* description: 导出成功
* content:
* application/json:
* schema:
* allOf:
* - $ref: '#/components/schemas/ApiResponse'
* - type: object
* properties:
* data:
* type: array
* items:
* $ref: '#/components/schemas/CollarAlert'
* 500:
* description: 服务器内部错误
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/ErrorResponse'
*/
publicRoutes.get('/collar/export', smartCollarAlertController.exportCollarAlerts);
2025-09-12 20:08:42 +08:00
module.exports = router;