import React, { useState, useEffect } from 'react'; import { useNavigate, useLocation, useParams } from 'react-router'; import { Button, Space, Form, Input, Select, message, Card, Spin, Typography, Switch, Divider, Descriptions, Tag, List, } from 'antd'; import { FileImageOutlined, FilePdfOutlined, FileOutlined, } from '@ant-design/icons'; import dayjs from 'dayjs'; import 'dayjs/locale/zh-cn'; // 从share/types.ts导入所有类型,包括MapMode import type { Attachment, } from '@/share/monitorTypes'; import { AlertLevel, AlertStatus, HandleType, ProblemType, HandleTypeNameMap, ProblemTypeNameMap, } from '@/share/monitorTypes'; import { getEnumOptions } from '../utils'; import { alertsClient, alertsHandleLogsClient } from '@/client/api'; import type { InferRequestType, InferResponseType } from 'hono/client'; import { Uploader } from "../components/components_uploader"; type AlertResponse = InferResponseType; type AlertHandleLogRequest = InferRequestType['json']; type DeviceAlert = InferResponseType['data'][0]; type AlertHandleLog = InferResponseType; const { Text } = Typography; // 告警处理页面 export const AlertHandlePage = () => { const { id } = useParams<{ id: string }>(); const [loading, setLoading] = useState(false); const [submitting, setSubmitting] = useState(false); const [alert, setAlert] = useState(null); const [form] = Form.useForm(); const navigate = useNavigate(); const [uploadedFiles, setUploadedFiles] = useState([]); const location = useLocation(); const searchParams = new URLSearchParams(location.search); const mode = searchParams.get('mode') || 'view'; // 默认为查看模式 // 判断是否可编辑 const isEditable = mode === 'edit' && alert && (alert.status === AlertStatus.PENDING || alert.status === AlertStatus.HANDLING); useEffect(() => { if (id) { fetchAlertData(parseInt(id)); } }, [id]); const fetchAlertData = async (alertId: number) => { setLoading(true); try { const res = await alertsClient[':id'].$get({ param: { id: alertId } }); if (res.status === 200) { const data = await res.json(); setAlert(data); } else { throw new Error(res.statusText); } } catch (error) { console.error('获取告警数据失败:', error); message.error('获取告警数据失败'); } finally { setLoading(false); } }; const handleSubmit = async (values: any) => { if (!id) return; setSubmitting(true); try { const alertHandleLog: AlertHandleLogRequest = { alertId: parseInt(id), handleType: values.handleType, problemType: values.problemType, handleResult: values.handleResult, notifyDisabled: values.notifyDisabled ? 1 : 0, attachments: uploadedFiles }; const res = await alertsHandleLogsClient.$post({ json: alertHandleLog }); if (res.status === 200) { message.success('告警处理成功'); navigate('/admin/alert-records'); } else { const error = await res.json(); throw new Error(error.message || '处理失败'); } } catch (error) { console.error('告警处理失败:', error); message.error('告警处理失败'); } finally { setSubmitting(false); } }; // 文件上传成功回调 const handleFileUploadSuccess = (fileUrl: string, fileInfo: any) => { // 添加上传成功的文件到列表 const newFile: Attachment = { id: fileInfo.id || String(Date.now()), name: fileInfo.file_name, url: fileUrl, type: fileInfo.file_type, size: fileInfo.file_size, upload_time: new Date().toISOString() }; setUploadedFiles(prev => [...prev, newFile]); }; // 删除已上传文件 const handleFileDelete = (fileId: string) => { setUploadedFiles(prev => prev.filter(file => file.id !== fileId)); }; const handleTypeOptions = getEnumOptions(HandleType, HandleTypeNameMap); const problemTypeOptions = getEnumOptions(ProblemType, ProblemTypeNameMap); const getAlertLevelTag = (level: AlertLevel | null) => { if (level === null) return 未知; switch (level) { case AlertLevel.MINOR: return 次要; case AlertLevel.NORMAL: return 一般; case AlertLevel.IMPORTANT: return 重要; case AlertLevel.URGENT: return 紧急; default: return 未知; } }; const getAlertStatusTag = (status?: AlertStatus) => { if (status === undefined) return 未知; switch (status) { case AlertStatus.PENDING: return 待处理; case AlertStatus.HANDLING: return 处理中; case AlertStatus.RESOLVED: return 已解决; case AlertStatus.IGNORED: return 已忽略; default: return 未知; } }; if (loading) { return (
); } if (!alert) { return (
未找到告警数据
); } return (
{alert.id} {alert.deviceName} {getAlertLevelTag(alert.alertLevel)} {getAlertStatusTag(alert.status)} {alert.metricType} {alert.metricValue} {alert.alertMessage} {dayjs(alert.createdAt).format('YYYY-MM-DD HH:mm:ss')} {/* 只有可编辑模式或者已经有处理记录的情况下才显示表单 */} {isEditable && ( <>
{/* 使用MinIOUploader代替原始Upload组件 */} message.error(`上传失败: ${error.message}`)} onProgress={(percent) => console.log(`上传进度: ${percent}%`)} prefix="alerts/" maxSize={20 * 1024 * 1024} allowedTypes={['image/jpeg', 'image/png', 'application/pdf', 'text/plain', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document']} /> {/* 已上传文件列表 */} {uploadedFiles.length > 0 && (

已上传文件:

( handleFileDelete(file.id)} > 删除 ]} > {file.type.includes('image') ? : file.type.includes('pdf') ? : } {file.name} ({file.size < 1024 * 1024 ? `${(file.size / 1024).toFixed(2)} KB` : `${(file.size / 1024 / 1024).toFixed(2)} MB`}) )} />
)}
)} {/* 不可编辑模式时只显示返回按钮 */} {!isEditable && ( )}
); };