修改管理后台
This commit is contained in:
590
backend/routes/smart-alerts.js
Normal file
590
backend/routes/smart-alerts.js
Normal file
@@ -0,0 +1,590 @@
|
||||
/**
|
||||
* 智能预警路由
|
||||
* @file smart-alerts.js
|
||||
* @description 定义智能预警相关的API路由
|
||||
*/
|
||||
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const { IotJbqClient, IotXqClient } = require('../models');
|
||||
const { Op } = require('sequelize');
|
||||
|
||||
// 公开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
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* 获取智能耳标预警列表
|
||||
*/
|
||||
publicRoutes.get('/eartag', async (req, res) => {
|
||||
try {
|
||||
const { page = 1, limit = 10, status, search, alertType } = req.query;
|
||||
const offset = (page - 1) * limit;
|
||||
|
||||
console.log('智能耳标预警API请求参数:', { page, limit, status, search, alertType });
|
||||
console.log('alertType 详细信息:', {
|
||||
value: alertType,
|
||||
type: typeof alertType,
|
||||
isString: typeof alertType === 'string',
|
||||
isEmpty: alertType === '',
|
||||
isUndefined: alertType === undefined,
|
||||
isNull: alertType === null,
|
||||
length: alertType ? alertType.length : 'N/A'
|
||||
});
|
||||
|
||||
// 构建查询条件
|
||||
const whereConditions = {};
|
||||
|
||||
// 状态筛选
|
||||
if (status) {
|
||||
switch (status) {
|
||||
case 'online':
|
||||
whereConditions.state = 1;
|
||||
break;
|
||||
case 'offline':
|
||||
whereConditions.state = 0;
|
||||
break;
|
||||
case 'alarm':
|
||||
whereConditions.state = 2;
|
||||
break;
|
||||
case 'maintenance':
|
||||
whereConditions.state = 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 搜索条件 - 耳标设备使用aaid字段搜索
|
||||
if (search) {
|
||||
whereConditions[Op.or] = [
|
||||
{ aaid: { [Op.like]: `%${search}%` } },
|
||||
{ cid: { [Op.like]: `%${search}%` } }
|
||||
];
|
||||
console.log('耳标搜索条件:', whereConditions[Op.or]);
|
||||
}
|
||||
|
||||
// 查询所有符合条件的设备数据(用于生成预警)
|
||||
const allDevices = await IotJbqClient.findAll({
|
||||
where: whereConditions,
|
||||
order: [
|
||||
['uptime', 'DESC'],
|
||||
['id', 'DESC']
|
||||
]
|
||||
});
|
||||
|
||||
// 生成预警数据 - 为每个设备生成对应的预警记录
|
||||
const allAlerts = [];
|
||||
|
||||
allDevices.forEach(device => {
|
||||
// 耳标设备编号使用aaid字段
|
||||
const deviceId = device.aaid || `EARTAG${device.id}`;
|
||||
const alertTime = new Date(device.uptime || Date.now()).toISOString().replace('T', ' ').substring(0, 19);
|
||||
|
||||
// 获取实际设备数据
|
||||
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; // 当日步数 = 总步数 - 昨日步数
|
||||
|
||||
// 为所有预警添加当日步数字段的函数
|
||||
const addDailyStepsToAlert = (alert) => {
|
||||
alert.dailySteps = dailySteps;
|
||||
alert.totalSteps = totalSteps;
|
||||
alert.yesterdaySteps = yesterdaySteps;
|
||||
return alert;
|
||||
};
|
||||
|
||||
// 离线预警 - 基于实际设备状态生成预警
|
||||
if (device.state === 0) {
|
||||
allAlerts.push(addDailyStepsToAlert({
|
||||
id: `${device.id}_offline`,
|
||||
eartagNumber: deviceId,
|
||||
alertType: 'offline',
|
||||
alertLevel: 'high',
|
||||
alertTime: alertTime,
|
||||
battery: actualBattery,
|
||||
temperature: actualTemperature,
|
||||
gpsSignal: '无',
|
||||
movementStatus: '静止',
|
||||
description: '设备已离线超过30分钟',
|
||||
longitude: 0,
|
||||
latitude: 0
|
||||
}));
|
||||
}
|
||||
|
||||
// 低电量预警 - 基于实际电量数据生成预警
|
||||
if (actualBattery > 0 && actualBattery < 20) {
|
||||
allAlerts.push(addDailyStepsToAlert({
|
||||
id: `${device.id}_battery`,
|
||||
eartagNumber: deviceId,
|
||||
alertType: 'battery',
|
||||
alertLevel: actualBattery < 10 ? 'high' : 'medium',
|
||||
alertTime: alertTime,
|
||||
battery: actualBattery,
|
||||
temperature: device.temperature || 0,
|
||||
gpsSignal: '强',
|
||||
movementStatus: '正常',
|
||||
description: `设备电量低于20%,当前电量${actualBattery}%`,
|
||||
longitude: 116.3974 + (device.id % 100) * 0.0001,
|
||||
latitude: 39.9093 + (device.id % 100) * 0.0001
|
||||
}));
|
||||
}
|
||||
|
||||
// 温度预警 - 基于实际温度数据生成预警
|
||||
if (actualTemperature > 0) {
|
||||
// 低温预警
|
||||
if (actualTemperature < 30) {
|
||||
allAlerts.push(addDailyStepsToAlert({
|
||||
id: `${device.id}_temperature_low`,
|
||||
eartagNumber: deviceId,
|
||||
alertType: 'temperature',
|
||||
alertLevel: actualTemperature < 20 ? 'high' : 'medium',
|
||||
alertTime: alertTime,
|
||||
battery: actualBattery,
|
||||
temperature: actualTemperature,
|
||||
gpsSignal: '强',
|
||||
movementStatus: '正常',
|
||||
description: `设备温度过低,当前温度${actualTemperature}°C`,
|
||||
longitude: 116.3974 + (device.id % 100) * 0.0001,
|
||||
latitude: 39.9093 + (device.id % 100) * 0.0001
|
||||
}));
|
||||
}
|
||||
// 高温预警
|
||||
else if (actualTemperature > 40) {
|
||||
allAlerts.push(addDailyStepsToAlert({
|
||||
id: `${device.id}_temperature_high`,
|
||||
eartagNumber: deviceId,
|
||||
alertType: 'temperature',
|
||||
alertLevel: actualTemperature > 45 ? 'high' : 'medium',
|
||||
alertTime: alertTime,
|
||||
battery: actualBattery,
|
||||
temperature: actualTemperature,
|
||||
gpsSignal: '强',
|
||||
movementStatus: '正常',
|
||||
description: `设备温度过高,当前温度${actualTemperature}°C`,
|
||||
longitude: 116.3974 + (device.id % 100) * 0.0001,
|
||||
latitude: 39.9093 + (device.id % 100) * 0.0001
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
// 异常运动预警 - 基于实际运动数据生成预警
|
||||
|
||||
// 步数异常预警:当日步数为0
|
||||
if (dailySteps === 0 && totalSteps > 0) {
|
||||
allAlerts.push(addDailyStepsToAlert({
|
||||
id: `${device.id}_movement_zero`,
|
||||
eartagNumber: deviceId,
|
||||
alertType: 'movement',
|
||||
alertLevel: 'high',
|
||||
alertTime: alertTime,
|
||||
battery: actualBattery,
|
||||
temperature: actualTemperature,
|
||||
gpsSignal: '强',
|
||||
movementStatus: '异常',
|
||||
description: `检测到步数异常,当日运动量为0步,可能为设备故障或动物异常`,
|
||||
longitude: 116.3974 + (device.id % 100) * 0.0001,
|
||||
latitude: 39.9093 + (device.id % 100) * 0.0001
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
// 预警类型筛选
|
||||
let filteredAlerts = allAlerts;
|
||||
console.log('=== 开始预警类型筛选 ===');
|
||||
console.log('原始预警数量:', allAlerts.length);
|
||||
console.log('alertType 值:', alertType);
|
||||
console.log('alertType 条件检查:', {
|
||||
'alertType 存在': !!alertType,
|
||||
'alertType.trim() !== ""': alertType && alertType.trim() !== '',
|
||||
'alertType 类型': typeof alertType,
|
||||
'alertType 长度': alertType ? alertType.length : 'N/A'
|
||||
});
|
||||
|
||||
if (alertType && alertType.trim() !== '') {
|
||||
console.log(`执行筛选,筛选类型: ${alertType}`);
|
||||
filteredAlerts = allAlerts.filter(alert => alert.alertType === alertType);
|
||||
console.log(`筛选结果: ${allAlerts.length} -> ${filteredAlerts.length}`);
|
||||
console.log('筛选后的预警类型分布:',
|
||||
filteredAlerts.reduce((acc, alert) => {
|
||||
acc[alert.alertType] = (acc[alert.alertType] || 0) + 1;
|
||||
return acc;
|
||||
}, {})
|
||||
);
|
||||
} else {
|
||||
console.log('跳过筛选,显示所有预警');
|
||||
}
|
||||
|
||||
// 计算统计数据
|
||||
const stats = {
|
||||
lowBattery: filteredAlerts.filter(alert => alert.alertType === 'battery').length,
|
||||
offline: filteredAlerts.filter(alert => alert.alertType === 'offline').length,
|
||||
highTemperature: filteredAlerts.filter(alert => alert.alertType === 'temperature').length,
|
||||
abnormalMovement: filteredAlerts.filter(alert => alert.alertType === 'movement').length
|
||||
};
|
||||
|
||||
// 对筛选后的预警数据进行分页
|
||||
const startIndex = parseInt(offset);
|
||||
const endIndex = startIndex + parseInt(limit);
|
||||
const paginatedAlerts = filteredAlerts.slice(startIndex, endIndex);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: paginatedAlerts,
|
||||
total: filteredAlerts.length,
|
||||
stats: stats,
|
||||
pagination: {
|
||||
page: parseInt(page),
|
||||
limit: parseInt(limit),
|
||||
total: filteredAlerts.length,
|
||||
pages: Math.ceil(filteredAlerts.length / limit)
|
||||
},
|
||||
message: '获取智能耳标预警列表成功'
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('获取智能耳标预警列表失败:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: '获取智能耳标预警列表失败',
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* 获取智能项圈预警列表
|
||||
*/
|
||||
publicRoutes.get('/collar', async (req, res) => {
|
||||
try {
|
||||
const { page = 1, limit = 10, status, search, alertType } = req.query;
|
||||
const offset = (page - 1) * limit;
|
||||
|
||||
console.log('智能项圈预警API请求参数:', { page, limit, status, search, alertType });
|
||||
console.log('alertType 详细信息:', {
|
||||
value: alertType,
|
||||
type: typeof alertType,
|
||||
isString: typeof alertType === 'string',
|
||||
isEmpty: alertType === '',
|
||||
isUndefined: alertType === undefined,
|
||||
isNull: alertType === null,
|
||||
length: alertType ? alertType.length : 'N/A'
|
||||
});
|
||||
|
||||
// 构建查询条件
|
||||
const whereConditions = {};
|
||||
|
||||
// 状态筛选
|
||||
if (status) {
|
||||
switch (status) {
|
||||
case 'online':
|
||||
whereConditions.state = 1;
|
||||
break;
|
||||
case 'offline':
|
||||
whereConditions.state = 0;
|
||||
break;
|
||||
case 'alarm':
|
||||
whereConditions.state = 2;
|
||||
break;
|
||||
case 'maintenance':
|
||||
whereConditions.state = 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 搜索条件 - 项圈设备使用sn字段搜索
|
||||
if (search) {
|
||||
whereConditions[Op.or] = [
|
||||
{ sn: { [Op.like]: `%${search}%` } },
|
||||
{ deviceId: { [Op.like]: `%${search}%` } }
|
||||
];
|
||||
console.log('项圈搜索条件:', whereConditions[Op.or]);
|
||||
}
|
||||
|
||||
// 查询数据库
|
||||
const { count, rows } = await IotXqClient.findAndCountAll({
|
||||
where: whereConditions,
|
||||
limit: parseInt(limit),
|
||||
offset: parseInt(offset),
|
||||
order: [
|
||||
['uptime', 'DESC'],
|
||||
['id', 'DESC']
|
||||
]
|
||||
});
|
||||
|
||||
// 生成预警数据 - 为每个设备生成对应的预警记录
|
||||
const alerts = [];
|
||||
|
||||
rows.forEach(device => {
|
||||
// 项圈设备编号使用sn字段
|
||||
const deviceId = device.sn || `COLLAR${device.id}`;
|
||||
const alertTime = new Date(device.uptime || Date.now()).toISOString().replace('T', ' ').substring(0, 19);
|
||||
|
||||
// 获取步数数据
|
||||
const totalSteps = parseInt(device.steps) || 0;
|
||||
const yesterdaySteps = parseInt(device.y_steps) || 0;
|
||||
const dailySteps = totalSteps - yesterdaySteps; // 当日步数 = 总步数 - 昨日步数
|
||||
|
||||
// 为所有预警添加当日步数字段的函数
|
||||
const addDailyStepsToAlert = (alert) => {
|
||||
alert.dailySteps = dailySteps;
|
||||
alert.totalSteps = totalSteps;
|
||||
alert.yesterdaySteps = yesterdaySteps;
|
||||
return alert;
|
||||
};
|
||||
|
||||
// 离线预警
|
||||
if (device.state === 0) {
|
||||
alerts.push(addDailyStepsToAlert({
|
||||
id: `${device.id}_offline`,
|
||||
collarNumber: deviceId,
|
||||
alertType: 'offline',
|
||||
alertLevel: 'high',
|
||||
alertTime: alertTime,
|
||||
battery: device.battery || 0,
|
||||
temperature: device.temperature || 0,
|
||||
gpsSignal: '无',
|
||||
wearStatus: device.bandge_status === 1 ? '已佩戴' : '未佩戴',
|
||||
description: '设备已离线超过30分钟',
|
||||
longitude: 0,
|
||||
latitude: 0
|
||||
}));
|
||||
}
|
||||
|
||||
// 低电量预警
|
||||
if (device.battery < 20) {
|
||||
alerts.push(addDailyStepsToAlert({
|
||||
id: `${device.id}_battery`,
|
||||
collarNumber: deviceId,
|
||||
alertType: 'battery',
|
||||
alertLevel: device.battery < 10 ? 'high' : 'medium',
|
||||
alertTime: alertTime,
|
||||
battery: device.battery || 0,
|
||||
temperature: device.temperature || 0,
|
||||
gpsSignal: '强',
|
||||
wearStatus: device.bandge_status === 1 ? '已佩戴' : '未佩戴',
|
||||
description: `设备电量低于20%,当前电量${device.battery}%`,
|
||||
longitude: 116.3974 + (device.id % 100) * 0.0001,
|
||||
latitude: 39.9093 + (device.id % 100) * 0.0001
|
||||
}));
|
||||
}
|
||||
|
||||
// 温度预警
|
||||
const actualTemperature = parseFloat(device.temperature) || 0;
|
||||
if (actualTemperature > 0) {
|
||||
// 低温预警
|
||||
if (actualTemperature < 30) {
|
||||
alerts.push(addDailyStepsToAlert({
|
||||
id: `${device.id}_temperature_low`,
|
||||
collarNumber: deviceId,
|
||||
alertType: 'temperature',
|
||||
alertLevel: actualTemperature < 20 ? 'high' : 'medium',
|
||||
alertTime: alertTime,
|
||||
battery: device.battery || 0,
|
||||
temperature: actualTemperature,
|
||||
gpsSignal: '强',
|
||||
wearStatus: device.bandge_status === 1 ? '已佩戴' : '未佩戴',
|
||||
description: `设备温度过低,当前温度${actualTemperature}°C`,
|
||||
longitude: 116.3974 + (device.id % 100) * 0.0001,
|
||||
latitude: 39.9093 + (device.id % 100) * 0.0001
|
||||
}));
|
||||
}
|
||||
// 高温预警
|
||||
else if (actualTemperature > 40) {
|
||||
alerts.push(addDailyStepsToAlert({
|
||||
id: `${device.id}_temperature_high`,
|
||||
collarNumber: deviceId,
|
||||
alertType: 'temperature',
|
||||
alertLevel: actualTemperature > 45 ? 'high' : 'medium',
|
||||
alertTime: alertTime,
|
||||
battery: device.battery || 0,
|
||||
temperature: actualTemperature,
|
||||
gpsSignal: '强',
|
||||
wearStatus: device.bandge_status === 1 ? '已佩戴' : '未佩戴',
|
||||
description: `设备温度过高,当前温度${actualTemperature}°C`,
|
||||
longitude: 116.3974 + (device.id % 100) * 0.0001,
|
||||
latitude: 39.9093 + (device.id % 100) * 0.0001
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
// 异常运动预警 - 基于实际运动数据生成预警
|
||||
|
||||
// 步数异常预警:当日步数为0
|
||||
if (dailySteps === 0 && totalSteps > 0) {
|
||||
alerts.push(addDailyStepsToAlert({
|
||||
id: `${device.id}_movement_zero`,
|
||||
collarNumber: deviceId,
|
||||
alertType: 'movement',
|
||||
alertLevel: 'high',
|
||||
alertTime: alertTime,
|
||||
battery: device.battery || 0,
|
||||
temperature: actualTemperature,
|
||||
gpsSignal: '强',
|
||||
wearStatus: device.bandge_status === 1 ? '已佩戴' : '未佩戴',
|
||||
description: `检测到步数异常,当日运动量为0步,可能为设备故障或动物异常`,
|
||||
longitude: 116.3974 + (device.id % 100) * 0.0001,
|
||||
latitude: 39.9093 + (device.id % 100) * 0.0001
|
||||
}));
|
||||
}
|
||||
|
||||
// 项圈脱落预警
|
||||
if (device.bandge_status === 0) {
|
||||
alerts.push(addDailyStepsToAlert({
|
||||
id: `${device.id}_wear`,
|
||||
collarNumber: deviceId,
|
||||
alertType: 'wear',
|
||||
alertLevel: 'high',
|
||||
alertTime: alertTime,
|
||||
battery: device.battery || 0,
|
||||
temperature: actualTemperature,
|
||||
gpsSignal: '中',
|
||||
wearStatus: '未佩戴',
|
||||
description: '设备佩戴状态异常,可能已脱落',
|
||||
longitude: 116.3974 + (device.id % 100) * 0.0001,
|
||||
latitude: 39.9093 + (device.id % 100) * 0.0001
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
// 预警类型筛选
|
||||
let filteredAlerts = alerts;
|
||||
console.log('=== 开始预警类型筛选 ===');
|
||||
console.log('原始预警数量:', alerts.length);
|
||||
console.log('alertType 值:', alertType);
|
||||
console.log('alertType 条件检查:', {
|
||||
'alertType 存在': !!alertType,
|
||||
'alertType.trim() !== ""': alertType && alertType.trim() !== '',
|
||||
'alertType 类型': typeof alertType,
|
||||
'alertType 长度': alertType ? alertType.length : 'N/A'
|
||||
});
|
||||
|
||||
if (alertType && alertType.trim() !== '') {
|
||||
console.log(`执行筛选,筛选类型: ${alertType}`);
|
||||
filteredAlerts = alerts.filter(alert => alert.alertType === alertType);
|
||||
console.log(`筛选结果: ${alerts.length} -> ${filteredAlerts.length}`);
|
||||
console.log('筛选后的预警类型分布:',
|
||||
filteredAlerts.reduce((acc, alert) => {
|
||||
acc[alert.alertType] = (acc[alert.alertType] || 0) + 1;
|
||||
return acc;
|
||||
}, {})
|
||||
);
|
||||
} else {
|
||||
console.log('跳过筛选,显示所有预警');
|
||||
}
|
||||
|
||||
// 计算统计数据
|
||||
const stats = {
|
||||
lowBattery: filteredAlerts.filter(alert => alert.alertType === 'battery').length,
|
||||
offline: filteredAlerts.filter(alert => alert.alertType === 'offline').length,
|
||||
highTemperature: filteredAlerts.filter(alert => alert.alertType === 'temperature').length,
|
||||
abnormalMovement: filteredAlerts.filter(alert => alert.alertType === 'movement').length,
|
||||
wearOff: filteredAlerts.filter(alert => alert.alertType === 'wear').length
|
||||
};
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: filteredAlerts,
|
||||
total: filteredAlerts.length,
|
||||
stats: stats,
|
||||
pagination: {
|
||||
page: parseInt(page),
|
||||
limit: parseInt(limit),
|
||||
total: filteredAlerts.length,
|
||||
pages: Math.ceil(filteredAlerts.length / limit)
|
||||
},
|
||||
message: '获取智能项圈预警列表成功'
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('获取智能项圈预警列表失败:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: '获取智能项圈预警列表失败',
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
Reference in New Issue
Block a user