import React, { useState, useRef, useEffect } from 'react'; import { Table, Input, Button, Form, Select, Space, Tag, Modal, Card, Typography, InputNumber, Row, Col, App, Divider, } from 'antd'; import { SearchOutlined, ReloadOutlined, PlusOutlined, EditOutlined, DeleteOutlined, EyeOutlined, ExclamationCircleOutlined, } from '@ant-design/icons'; import { getErrorListApi, addErrorApi, updateErrorApi, deleteErrorApi, getErrorDetailApi, getErrorListAllApi } from '@/api/systemSetting'; import utils from '@/lib/utils'; import { errorLevelOptions, errorSourceOptions, CompareEnumOptions } from '@/lib/utils'; import { useSelector } from 'react-redux'; import { RootState } from '@/src/store'; import { useTranslation } from 'react-i18next'; const { TextArea } = Input; const { Text, Title } = Typography; const { Option } = Select; const AntdCard = Card as any; export default function ErrorManagement() { const { t } = useTranslation(); const { userInfo } = useSelector((state: RootState) => state.user); const { stationId, currentStation } = useSelector((state: RootState) => state.station); const { modal } = App.useApp(); const [form] = Form.useForm(); const [searchForm] = Form.useForm(); const [loading, setLoading] = useState(false); const [errorList, setErrorList] = useState([]); const [total, setTotal] = useState(0); const [params, setParams] = useState({ errorCode: '', errorName: '', errorSource: '', errorLevel: '', orgId: currentStation?.orgId || '', siteId: stationId || '', }); const [modalVisible, setModalVisible] = useState(false); const [modalType, setModalType] = useState<'add' | 'edit' | 'view'>('add'); const [currentRecord, setCurrentRecord] = useState(null); // 监听对比类型,判断是否是区间 const compareTypeWatch = Form.useWatch('compareType', form); // 获取错误列表 const fetchErrorList = async () => { setLoading(true); try { const requestParams = { ...params, siteId: stationId || '', }; const realParams = Object.fromEntries( Object.entries(requestParams).filter(([_, val]) => val !== '') ); const res = await getErrorListAllApi(realParams); if (res.code === 200) { setErrorList(res.rows || []); setTotal(res.total || res.rows?.length || 0); } } catch (err) { utils.message.error(t('systemSetting.getErrorListFailed')); } finally { setLoading(false); } }; useEffect(() => { setParams(prev => ({ ...prev, siteId: stationId || '' })); }, [stationId]); useEffect(() => { fetchErrorList(); }, [params]); // 打开弹窗 // 打开弹窗 const openModal = (type: 'add' | 'edit' | 'view', record?: any) => { setModalType(type); setCurrentRecord(record); setModalVisible(true); form.resetFields(); if (type === 'edit' || type === 'view') { const fillData = { ...record }; // 区间规则拆分 compareValues 回填 min/max const targetEnum = CompareEnumOptions.find(e => e.value === record.compareType); if (targetEnum?.range && record.compareValues) { const valArr = record.compareValues.split(','); fillData.rangeMin = valArr[0]; fillData.rangeMax = valArr[1]; } form.setFieldsValue(fillData); } }; // 保存错误(字段映射适配后端实体) const handleSave = async (values: any) => { console.log('提交表单数据', values); //return; // 组装后端需要的实体字段 const submitData = { id: modalType == 'edit' ? currentRecord.id : undefined, // 原有基础字段 errorCode: values.errorCode, errorName: values.errorName, errorSource: values.errorSource, errorLevel: values.errorLevel, errorDescription: values.errorDescription, suggestion: values.suggestion, // 新增校验规则字段 field: values.field, compareType: values.compareType, orgId: currentStation?.orgId || '', siteId: stationId || '', // 区间/普通值统一拼接逗号字符串传给 compareValues compareValues: values.rangeMin && values.rangeMax ? `${values.rangeMin},${values.rangeMax}` : values.compareValues || '', }; console.log('提交表单数据', submitData); try { // 真实接口 const res = await addErrorApi(submitData); if (res.code === 200) { utils.message.success(modalType == 'edit' ? t('common.editSuccess') : t('common.addSuccess')); setModalVisible(false); fetchErrorList(); } else { utils.message.error(res.msg || t('systemSetting.operationFailed')); } } catch (err) { utils.message.error(t('systemSetting.operationFailed')); } }; // 删除错误 const handleDelete = (record: any) => { modal.confirm({ title: t('common.confirmDelete'), content: t('systemSetting.confirmDeleteError', { name: record.errorName }), icon: , okText: t('common.ok'), cancelText: t('common.cancel'), onOk: async () => { try { // 真实接口 const data = { ids: [record.id] } console.log('删除请求参数', data); const res = await deleteErrorApi(data.ids); if (res.code == 200) { utils.message.success(t('common.deleteSuccess')); fetchErrorList(); } else { utils.message.error(res.msg || t('common.deleteFail')); } } catch (err) { utils.message.error(t('common.deleteFail')); } }, }); }; // 搜索 const handleSearch = () => { searchForm.validateFields().then(values => { setParams({ ...params, ...values, }); }); }; // 重置 const handleReset = () => { searchForm.resetFields(); setParams({ errorCode: '', errorName: '', errorSource: '', errorLevel: '', }); }; // 标签颜色方法(原有不变) const getTypeColor = (type: string) => { const colorMap: Record = { ROBOT: 'blue', DEVICE: 'green', SYSTEM: 'purple', COMMUNICATION: 'orange', SENSOR: 'cyan', OTHER: 'default', }; return colorMap[type] || 'default'; }; const getSeverityColor = (severity: string) => { const colorMap: Record = { MINOR: 'default', NORMAL: 'blue', SERIOUS: 'orange', CRITICAL: 'red', }; return colorMap[severity] || 'default'; }; const getStatusColor = (status: string) => { const colorMap: Record = { PENDING: 'orange', PROCESSING: 'blue', RESOLVED: 'green', IGNORED: 'default', }; return colorMap[status] || 'default'; }; // 表格列(完全不变) const columns = [ { title: t('systemSetting.errorCode'), dataIndex: 'errorCode', key: 'errorCode', width: 150, fixed: 'left' as const, }, { title: t('systemSetting.errorName'), dataIndex: 'errorName', key: 'errorName', width: 200, }, { title: t('systemSetting.errorSourceLabel'), dataIndex: 'errorSource', key: 'errorSource', width: 120, render: (text: string) => { const typeObj = errorSourceOptions.find(t => t.value === text); return {typeObj?.label || text}; }, }, { title: t('systemSetting.errorLevelLabel'), dataIndex: 'errorLevel', key: 'errorLevel', width: 100, render: (text: string) => { const severityObj = errorLevelOptions.find(t => t.value === text); return {severityObj?.label || text}; }, }, { title: t('systemSetting.checkField'), dataIndex: 'field', key: 'field', width: 130, }, { title: t('systemSetting.compareRule'), dataIndex: 'compareType', key: 'compareType', width: 140, render: (val) => { const item = CompareEnumOptions.find(o => o.value === val); return item?.label || val; }, }, { title: t('systemSetting.compareValueCol'), dataIndex: 'compareValues', key: 'compareValues', width: 140, }, { title: t('common.description'), dataIndex: 'errorDescription', key: 'errorDescription', ellipsis: true, }, { title: t('aiAnalysis.suggestion'), dataIndex: 'suggestion', key: 'suggestion', width: 180, }, { title: t('roles.actions'), key: 'action', width: 300, fixed: 'right' as const, render: (_: any, record: any) => ( ), }, ]; return (
{/* 搜索区域完全不变 */}
`${t('common.total')} ${total} ${t('common.items')}`, onChange: (page, pageSize) => { setParams({ ...params, pageNum: page, pageSize }); }, }} /> {/* 新增/编辑/查看弹窗(核心优化区域) */} { setModalVisible(false); form.resetFields(); }} width={780} footer={ modalType === 'view' ? [ ] : [
, , ] } >
{/* 第一行:基础编码名称 */}
{/* 第二行:来源、等级、校验字段 */} {/* 第三行:对比类型 + 对比值(自动切换单输入/区间双输入) */} {/* 区间类型:BETWEEN / NOT_BETWEEN 显示两个输入框 */} {CompareEnumOptions.find(o => o.value === compareTypeWatch)?.range ? ( <> ) : ( )} {/* 错误描述 */}