Files
nxxmdata/backend/controllers/alertController.js
2025-09-12 20:08:42 +08:00

430 lines
10 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 alertController.js
* @description 处理预警相关的请求
*/
const { Alert, Farm, Device } = require('../models');
const { Sequelize } = require('sequelize');
/**
* 获取所有预警
* @param {Object} req - 请求对象
* @param {Object} res - 响应对象
*/
exports.getAllAlerts = async (req, res) => {
try {
const alerts = await Alert.findAll({
include: [
{ model: Farm, as: 'farm', attributes: ['id', 'name', 'location'] },
{ model: Device, as: 'device', attributes: ['id', 'name', 'type'] }
],
order: [['created_at', 'DESC']]
});
res.status(200).json({
success: true,
data: alerts
});
} catch (error) {
console.error('获取预警列表失败:', error);
res.status(500).json({
success: false,
message: '获取预警列表失败',
error: error.message
});
}
};
/**
* 根据养殖场名称搜索预警
* @param {Object} req - 请求对象
* @param {Object} res - 响应对象
*/
exports.searchAlertsByFarmName = async (req, res) => {
try {
const { farmName } = req.query;
if (!farmName) {
return res.status(400).json({
success: false,
message: '请提供养殖场名称参数'
});
}
console.log(`开始搜索养殖场名称包含 "${farmName}" 的预警...`);
// 首先找到匹配的养殖场
const farms = await Farm.findAll({
where: {
name: {
[require('sequelize').Op.like]: `%${farmName}%`
}
},
attributes: ['id', 'name']
});
if (farms.length === 0) {
return res.status(200).json({
success: true,
data: [],
message: '未找到匹配的养殖场'
});
}
const farmIds = farms.map(farm => farm.id);
// 根据养殖场ID查找预警
const alerts = await Alert.findAll({
where: {
farm_id: {
[require('sequelize').Op.in]: farmIds
}
},
include: [
{ model: Farm, as: 'farm', attributes: ['id', 'name', 'location'] },
{ model: Device, as: 'device', attributes: ['id', 'name', 'type'] }
],
order: [['created_at', 'DESC']]
});
console.log(`找到 ${alerts.length} 个匹配的预警`);
res.status(200).json({
success: true,
data: alerts,
message: `找到 ${alerts.length} 个养殖场名称包含 "${farmName}" 的预警`
});
} catch (error) {
console.error('根据养殖场名称搜索预警失败:', error);
res.status(500).json({
success: false,
message: '搜索预警失败',
error: error.message
});
}
};
/**
* 获取单个预警
* @param {Object} req - 请求对象
* @param {Object} res - 响应对象
*/
exports.getAlertById = async (req, res) => {
try {
const { id } = req.params;
const alert = await Alert.findByPk(id, {
include: [
{ model: Farm, as: 'farm', attributes: ['id', 'name'] },
{ model: Device, as: 'device', attributes: ['id', 'name', 'type'] }
]
});
if (!alert) {
return res.status(404).json({
success: false,
message: '预警不存在'
});
}
res.status(200).json({
success: true,
data: alert
});
} catch (error) {
console.error(`获取预警(ID: ${req.params.id})失败:`, error);
res.status(500).json({
success: false,
message: '获取预警详情失败',
error: error.message
});
}
};
/**
* 创建预警
* @param {Object} req - 请求对象
* @param {Object} res - 响应对象
*/
exports.createAlert = async (req, res) => {
try {
const { type, level, message, status, farm_id, device_id } = req.body;
// 验证必填字段
if (!type || !message || !farm_id) {
return res.status(400).json({
success: false,
message: '类型、消息内容和养殖场ID为必填项'
});
}
// 验证养殖场是否存在
const farm = await Farm.findByPk(farm_id);
if (!farm) {
return res.status(404).json({
success: false,
message: '指定的养殖场不存在'
});
}
// 如果提供了设备ID验证设备是否存在
if (device_id) {
const device = await Device.findByPk(device_id);
if (!device) {
return res.status(404).json({
success: false,
message: '指定的设备不存在'
});
}
}
const alert = await Alert.create({
type,
level,
message,
status,
farm_id,
device_id
});
res.status(201).json({
success: true,
message: '预警创建成功',
data: alert
});
} catch (error) {
console.error('创建预警失败:', error);
res.status(500).json({
success: false,
message: '创建预警失败',
error: error.message
});
}
};
/**
* 更新预警
* @param {Object} req - 请求对象
* @param {Object} res - 响应对象
*/
exports.updateAlert = async (req, res) => {
try {
const { id } = req.params;
const { type, level, message, status, farm_id, device_id, resolved_at, resolved_by, resolution_notes } = req.body;
const alert = await Alert.findByPk(id);
if (!alert) {
return res.status(404).json({
success: false,
message: '预警不存在'
});
}
// 如果更新了养殖场ID验证养殖场是否存在
if (farm_id && farm_id !== alert.farm_id) {
const farm = await Farm.findByPk(farm_id);
if (!farm) {
return res.status(404).json({
success: false,
message: '指定的养殖场不存在'
});
}
}
// 如果更新了设备ID验证设备是否存在
if (device_id && device_id !== alert.device_id) {
const device = await Device.findByPk(device_id);
if (!device) {
return res.status(404).json({
success: false,
message: '指定的设备不存在'
});
}
}
// 如果状态更新为已解决,自动设置解决时间
let updateData = {
type,
level,
message,
status,
farm_id,
device_id,
resolved_at,
resolved_by,
resolution_notes
};
// 只更新提供的字段
Object.keys(updateData).forEach(key => {
if (updateData[key] === undefined) {
delete updateData[key];
}
})
if (status === 'resolved' && !resolved_at) {
updateData.resolved_at = new Date();
}
await alert.update(updateData);
res.status(200).json({
success: true,
message: '预警更新成功',
data: alert
});
} catch (error) {
console.error(`更新预警(ID: ${req.params.id})失败:`, error);
res.status(500).json({
success: false,
message: '更新预警失败',
error: error.message
});
}
};
/**
* 删除预警
* @param {Object} req - 请求对象
* @param {Object} res - 响应对象
*/
exports.deleteAlert = async (req, res) => {
try {
const { id } = req.params;
const alert = await Alert.findByPk(id);
if (!alert) {
return res.status(404).json({
success: false,
message: '预警不存在'
});
}
await alert.destroy();
res.status(200).json({
success: true,
message: '预警删除成功'
});
} catch (error) {
console.error(`删除预警(ID: ${req.params.id})失败:`, error);
res.status(500).json({
success: false,
message: '删除预警失败',
error: error.message
});
}
};
/**
* 按类型统计预警数量
* @param {Object} req - 请求对象
* @param {Object} res - 响应对象
*/
exports.getAlertStatsByType = async (req, res) => {
try {
const { sequelize } = require('../config/database-simple');
const stats = await Alert.findAll({
attributes: [
'type',
[sequelize.fn('COUNT', sequelize.col('id')), 'count']
],
group: ['type'],
raw: true
});
// 格式化数据
const formattedStats = stats.map(item => ({
type: item.type,
count: parseInt(item.count) || 0
}));
res.status(200).json({
success: true,
data: formattedStats
});
} catch (error) {
console.error('获取预警类型统计失败:', error);
res.status(500).json({
success: false,
message: '获取预警类型统计失败',
error: error.message
});
}
};
/**
* 按级别统计预警数量
* @param {Object} req - 请求对象
* @param {Object} res - 响应对象
*/
exports.getAlertStatsByLevel = async (req, res) => {
try {
const { sequelize } = require('../config/database-simple');
const stats = await Alert.findAll({
attributes: [
'level',
[sequelize.fn('COUNT', sequelize.col('id')), 'count']
],
group: ['level'],
raw: true
});
// 格式化数据
const formattedStats = stats.map(item => ({
level: item.level,
count: parseInt(item.count) || 0
}));
res.status(200).json({
success: true,
data: formattedStats
});
} catch (error) {
console.error('获取预警级别统计失败:', error);
res.status(500).json({
success: false,
message: '获取预警级别统计失败',
error: error.message
});
}
};
/**
* 按状态统计预警数量
* @param {Object} req - 请求对象
* @param {Object} res - 响应对象
*/
exports.getAlertStatsByStatus = async (req, res) => {
try {
const { sequelize } = require('../config/database-simple');
const stats = await Alert.findAll({
attributes: [
'status',
[sequelize.fn('COUNT', sequelize.col('id')), 'count']
],
group: ['status'],
raw: true
});
// 格式化数据
const formattedStats = stats.map(item => ({
status: item.status,
count: parseInt(item.count) || 0
}));
res.status(200).json({
success: true,
data: formattedStats
});
} catch (error) {
console.error('获取预警状态统计失败:', error);
res.status(500).json({
success: false,
message: '获取预警状态统计失败',
error: error.message
});
}
};