Files
nxxmdata/backend/routes/smart-alerts.js
2025-09-22 19:09:45 +08:00

760 lines
24 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 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
*/
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');
// 公开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'
*/
publicRoutes.get('/eartag/stats', smartEartagAlertController.getEartagAlertStats);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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'
*/
publicRoutes.get('/eartag/export', smartEartagAlertController.exportEartagAlerts);
/**
* @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);
/**
* @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);
/**
* @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);
module.exports = router;