import React, { useState, useCallback, useMemo } from 'react'; import { Drawer, Tabs, Tag, Space, Typography, Empty, Card, Tooltip, Button, Popconfirm, } from 'antd'; import { ApiOutlined, CloudServerOutlined, EnvironmentOutlined, EditOutlined, PlusCircleOutlined, DeleteOutlined, } from '@ant-design/icons'; import NetworkCardPanel from './NetworkCardPanel'; const { Text, Title } = Typography; const designTokens = { colors: { primary: '#667eea', success: '#10b981', error: '#ef4444', warning: '#f59e0b', }, spacing: { sm: 8, md: 16, }, }; function DeviceDetailDrawer({ device, visible, onClose, cables, onRefreshCables, onEdit, onAddNic, onAddPort, onAddCable, onDeleteCable, tooltipFields, refreshTrigger, }) { const [activeTab, setActiveTab] = useState('ports'); const deviceCables = useMemo(() => { if (!device || !cables) return []; return cables.filter( c => c.sourceDeviceId === device.deviceId || c.targetDeviceId === device.deviceId ); }, [device, cables]); const getStatusTag = useCallback(status => { const config = { running: { color: 'success', text: '运行中' }, normal: { color: 'success', text: '正常' }, warning: { color: 'warning', text: '警告' }, error: { color: 'error', text: '故障' }, fault: { color: 'error', text: '故障' }, offline: { color: 'default', text: '离线' }, maintenance: { color: 'processing', text: '维护中' }, }; const { color, text } = config[status] || { color: 'default', text: status }; return {text}; }, []); const getDeviceTypeName = useCallback(type => { const typeMap = { server: '服务器', switch: '交换机', router: '路由器', storage: '存储设备', firewall: '防火墙', ups: 'UPS', pdu: 'PDU', }; return typeMap[type?.toLowerCase()] || type || '未知设备'; }, []); const renderFieldValue = useCallback( (field, device) => { const fieldKey = field.field; if (fieldKey === 'status') return getStatusTag(device.status); // 优先从device对象获取值,如果没有则从customFields中获取 let value = device[fieldKey]; if ( (value === undefined || value === null) && device.customFields && typeof device.customFields === 'object' ) { value = device.customFields[fieldKey]; } if (fieldKey === 'type') value = getDeviceTypeName(value); else if (fieldKey === 'position') value = `U${device.position} ${device.height ? `(${device.height}U)` : ''}`; return ( {value !== undefined && value !== null ? value : '-'} ); }, [getStatusTag, getDeviceTypeName] ); const displayFields = useMemo(() => { if (tooltipFields && Object.keys(tooltipFields).length > 0) { return Object.values(tooltipFields).filter(f => f.enabled); } // Default fallback fields if no config return [ { field: 'deviceId', label: '设备ID' }, { field: 'type', label: '设备类型' }, { field: 'status', label: '设备状态' }, { field: 'position', label: '位置' }, { field: 'ipAddress', label: 'IP地址' }, { field: 'brand', label: '品牌' }, ]; }, [tooltipFields]); const tabItems = [ { key: 'ports', label: ( 端口与网卡 ), children: ( ), }, { key: 'cables', label: ( 接线 ({deviceCables.length}) ), children: (
{deviceCables.length === 0 ? ( ) : ( {deviceCables.map(cable => ( onDeleteCable?.(cable.cableId)} okText="确定" cancelText="取消" >
), }, ]; if (!device) return null; return ( 设备详情 - {device.name} } placement="right" width={600} open={visible} onClose={onClose} extra={ } styles={{ body: { padding: '16px 20px', overflow: 'auto' } }} >
基本信息
{displayFields.map(field => (
{field.label} {renderFieldValue(field, device)}
))}
); } export default React.memo(DeviceDetailDrawer);