import React, { useEffect, useState } from 'react';
import { Modal, Button, Row, Col, Tag, Progress } from 'antd';
import {
AppstoreOutlined,
EnvironmentOutlined,
ThunderboltOutlined,
CalendarOutlined,
ExclamationCircleOutlined,
ClockCircleOutlined,
EditOutlined,
FileTextOutlined,
PlusOutlined,
CheckCircleOutlined,
CloseCircleOutlined,
SyncOutlined,
StopOutlined,
DesktopOutlined,
} from '@ant-design/icons';
import { designTokens } from '../../config/theme';
import { getStatusConfig, getTypeLabel, getDeviceTypeIcon } from '../../utils/deviceUtils.jsx';
const { colors, shadows, borderRadius, transitions, spacing } = designTokens;
const DeviceDetailModal = ({
visible,
device,
deviceFields,
onClose,
onEdit,
onViewTickets,
onCreateTicket,
}) => {
const [isVisible, setIsVisible] = useState(false);
const [activeTab, setActiveTab] = useState('basic');
useEffect(() => {
if (visible) {
setIsVisible(true);
} else {
const timer = setTimeout(() => setIsVisible(false), 300);
return () => clearTimeout(timer);
}
}, [visible]);
if (!device) return null;
const getStatusIcon = (status) => {
const iconMap = {
running: ,
maintenance: ,
offline: ,
fault: ,
idle: ,
};
return iconMap[status] || ;
};
const getDeviceTypeColor = (type) => {
return colors.device[type] || colors.device.other;
};
const isWarrantyExpired = device.warrantyExpiry && new Date(device.warrantyExpiry) < new Date();
const warrantyDaysLeft = device.warrantyExpiry
? Math.ceil((new Date(device.warrantyExpiry) - new Date()) / (1000 * 60 * 60 * 24))
: null;
const InfoCard = ({ title, icon, children, className = '' }) => (
{icon}
{title}
{children}
);
const InfoItem = ({ label, value, status, copyable = false, fullWidth = false }) => {
const renderValue = () => {
if (status === 'warning') {
return (
{value}
);
}
if (status === 'danger') {
return (
{value}
);
}
return {value || '-'};
};
return (
);
};
const tabItems = [
{ key: 'basic', label: '基本信息' },
{ key: 'location', label: '位置信息' },
{ key: 'maintenance', label: '维保信息' },
];
return (
{getDeviceTypeIcon(device.type)}
{device.name}
{device.status && (
{getStatusIcon(device.status)}
{getStatusConfig(device.status).text}
)}
{getTypeLabel(device.type)}
{device.deviceId}
{device.model && (
{device.model}
)}
{tabItems.map((tab) => (
))}
{activeTab === 'basic' && (
}
style={{ animation: 'fadeInUp 0.3s ease-out' }}
>
{device.description && (
)}
{device.customFields && Object.keys(device.customFields).length > 0 && (
自定义字段
{Object.entries(device.customFields).map(([key, value]) => {
const fieldConfig = deviceFields.find((f) => f.fieldName === key);
const displayName = fieldConfig?.displayName || key;
return (
{displayName}
{String(value)}
);
})}
)}
)}
{activeTab === 'location' && (
}
style={{ animation: 'fadeInUp 0.3s ease-out' }}
>
)}
{activeTab === 'maintenance' && (
<>
}
style={{ animation: 'fadeInUp 0.3s ease-out', marginBottom: '20px' }}
>
{warrantyDaysLeft !== null && warrantyDaysLeft > 0 && (
保修剩余天数
{isWarrantyExpired && (
设备已过保,建议续保
)}
>
)}
}
onClick={() => onViewTickets(device)}
style={{
height: '40px',
borderRadius: borderRadius.medium,
border: `1px solid ${colors.border.light}`,
display: 'flex',
alignItems: 'center',
gap: '8px',
fontWeight: 500,
}}
>
查看工单
}
onClick={() => onCreateTicket(device)}
style={{
height: '40px',
borderRadius: borderRadius.medium,
background: colors.primary.gradient,
border: 'none',
display: 'flex',
alignItems: 'center',
gap: '8px',
fontWeight: 500,
boxShadow: shadows.small,
}}
>
创建工单
}
onClick={() => {
onClose();
onEdit(device);
}}
style={{
height: '40px',
borderRadius: borderRadius.medium,
background: colors.primary.gradient,
border: 'none',
display: 'flex',
alignItems: 'center',
gap: '8px',
fontWeight: 500,
boxShadow: shadows.small,
}}
>
编辑设备
);
};
export default React.memo(DeviceDetailModal);