/** * 智能预警路由 * @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;