import React, { useState, useEffect } from 'react'; import { Button, Table, Space, Form, Input, Select, message, Modal, Card, Row, Col, Switch, Popconfirm, Tag, Collapse, } from 'antd'; import 'dayjs/locale/zh-cn'; // 从share/types.ts导入所有类型,包括MapMode import type { ZichanInfo, DeviceAlertRule, } from '../share/monitorTypes.ts'; import { AlertLevel, MetricType, AlertLevelNameMap, MetricTypeNameMap } from '../share/monitorTypes.ts'; import { EnableStatus, EnableStatusNameMap, } from '../share/types.ts'; import { getEnumOptions } from './utils.ts'; import { DeviceInstanceAPI, DeviceAlertRuleAPI} from './api/index.ts'; // 设备告警规则页面 export const DeviceAlertRulePage = () => { const [loading, setLoading] = useState(false); const [ruleData, setRuleData] = useState([]); const [pagination, setPagination] = useState({ current: 1, pageSize: 10, total: 0, }); const [deviceOptions, setDeviceOptions] = useState<{label: string, value: number}[]>([]); const [modalVisible, setModalVisible] = useState(false); const [modalTitle, setModalTitle] = useState('新增告警规则'); const [currentRecord, setCurrentRecord] = useState(null); const [formRef] = Form.useForm(); const [modalForm] = Form.useForm(); useEffect(() => { fetchDeviceOptions(); fetchRuleData(); }, [pagination.current, pagination.pageSize]); const fetchDeviceOptions = async () => { try { const response = await DeviceInstanceAPI.getDeviceInstances(); if (response && response.data) { const options = response.data.map((device: ZichanInfo) => ({ label: device.asset_name || `设备${device.id}`, value: device.id })); setDeviceOptions(options); } } catch (error) { console.error('获取设备列表失败:', error); message.error('获取设备列表失败'); } }; const fetchRuleData = async () => { setLoading(true); try { const values = formRef.getFieldsValue(); const params = { page: pagination.current, pageSize: pagination.pageSize, device_id: values.device_id, metric_type: values.metric_type, alert_level: values.alert_level, is_enabled: values.is_enabled, }; const response = await DeviceAlertRuleAPI.getDeviceAlertRules(params); if (response) { setRuleData(response.data || []); setPagination({ ...pagination, total: response.total || 0, }); } } catch (error) { console.error('获取告警规则失败:', error); message.error('获取告警规则失败'); } finally { setLoading(false); } }; const handleSearch = (values: any) => { setPagination({ ...pagination, current: 1, }); fetchRuleData(); }; const handleTableChange = (newPagination: any) => { setPagination({ ...pagination, current: newPagination.current, pageSize: newPagination.pageSize, }); }; const handleAdd = () => { setModalTitle('新增告警规则'); setCurrentRecord(null); modalForm.resetFields(); setModalVisible(true); }; const handleEdit = (record: DeviceAlertRule) => { setModalTitle('编辑告警规则'); setCurrentRecord(record); modalForm.setFieldsValue(record); setModalVisible(true); }; const handleDelete = async (id: number) => { try { await DeviceAlertRuleAPI.deleteDeviceAlertRule(id); message.success('删除成功'); fetchRuleData(); } catch (error) { console.error('删除失败:', error); message.error('删除失败'); } }; const handleEnableChange = async (record: DeviceAlertRule, enabled: boolean) => { try { await DeviceAlertRuleAPI.updateDeviceAlertRule(record.id, { is_enabled: enabled ? EnableStatus.ENABLED : EnableStatus.DISABLED }); message.success(`${enabled ? '启用' : '禁用'}成功`); fetchRuleData(); } catch (error) { console.error('操作失败:', error); message.error('操作失败'); } }; const handleModalSubmit = async () => { try { const values = await modalForm.validateFields(); if (currentRecord) { // 更新 await DeviceAlertRuleAPI.updateDeviceAlertRule(currentRecord.id, values); message.success('更新成功'); } else { // 新增 await DeviceAlertRuleAPI.createDeviceAlertRule(values); message.success('添加成功'); } setModalVisible(false); fetchRuleData(); } catch (error) { console.error('操作失败:', error); message.error('操作失败'); } }; const metricTypeOptions = getEnumOptions(MetricType, MetricTypeNameMap); const alertLevelOptions = getEnumOptions(AlertLevel, AlertLevelNameMap); const enableStatusOptions = getEnumOptions(EnableStatus, EnableStatusNameMap); const getAlertLevelTag = (level: AlertLevel) => { switch (level) { case AlertLevel.MINOR: return 次要; case AlertLevel.NORMAL: return 一般; case AlertLevel.IMPORTANT: return 重要; case AlertLevel.URGENT: return 紧急; default: return 未知; } }; const columns = [ { title: '规则ID', dataIndex: 'id', key: 'id', width: 80, }, { title: '设备', dataIndex: 'device_id', key: 'device_id', render: (id: number) => { const device = deviceOptions.find(opt => opt.value === id); return device ? device.label : id; }, }, { title: '监控指标', dataIndex: 'metric_type', key: 'metric_type', render: (text: string) => { const option = metricTypeOptions.find(opt => opt.value === text); return option ? option.label : text; }, }, { title: '最小阈值', dataIndex: 'min_value', key: 'min_value', }, { title: '最大阈值', dataIndex: 'max_value', key: 'max_value', }, { title: '持续时间(秒)', dataIndex: 'duration_seconds', key: 'duration_seconds', }, { title: '告警等级', dataIndex: 'alert_level', key: 'alert_level', render: (level: AlertLevel) => getAlertLevelTag(level), }, { title: '状态', dataIndex: 'is_enabled', key: 'is_enabled', render: (status: EnableStatus, record: DeviceAlertRule) => ( handleEnableChange(record, checked)} checkedChildren="启用" unCheckedChildren="禁用" /> ), }, { title: '操作', key: 'action', render: (_: any, record: DeviceAlertRule) => ( handleDelete(record.id)} okText="确定" cancelText="取消" > ), }, ]; return (
setModalVisible(false)} width={600} >

常见阈值参考:

  • 温度(temperature):最大阈值建议设为 30-35℃
  • 湿度(humidity):最小阈值20%,最大阈值80%
  • CPU使用率(cpu_usage):最大阈值建议设为 85-95%
  • 内存使用率(memory_usage):最大阈值建议设为 85-95%
  • 磁盘使用率(disk_usage):最大阈值建议设为 85-95%
  • Ping时间(ping_time):最大阈值建议设为 100-200ms
  • 丢包率(packet_loss):最大阈值建议设为 2-5%
  • 连接状态(connection_status):最大阈值建议设为 0(0表示已连接,大于0表示未连接)

注意:最小值或最大值必须至少填写一项。

); };