import React, { useState, useEffect, useRef, useCallback } from 'react';
import { Button, Empty, Spin, Badge, Typography, Space, Checkbox, Tooltip } from 'antd';
import {
DownOutlined,
UpOutlined,
EyeOutlined,
EyeInvisibleOutlined,
PlusOutlined,
CloudServerOutlined,
} from '@ant-design/icons';
import ServerBackplanePanel from './ServerBackplanePanel';
import PortPanel from './PortPanel';
const { Text } = Typography;
/**
* 虚拟设备列表组件
* 用于优化大量设备面板的渲染性能
*
* @param {Object[]} devices - 设备列表
* @param {Object} groupedPorts - 按设备分组的端口数据
* @param {Object[]} cables - 接线列表
* @param {Object[]} allDevices - 所有设备列表(用于查找设备信息)
* @param {Function} onPortClick - 端口点击回调
* @param {Function} onAddPort - 添加端口回调 (device) => void
* @param {Function} onManageNetworkCards - 网卡管理回调 (device) => void
* @param {number} initialVisibleCount - 初始显示数量
* @param {number} loadMoreCount - 每次加载更多数量
*/
const VirtualDeviceList = ({
devices,
groupedPorts,
cables,
allDevices,
onPortClick,
onAddPort,
onManageNetworkCards,
initialVisibleCount = 5,
loadMoreCount = 5,
}) => {
const [visibleCount, setVisibleCount] = useState(initialVisibleCount);
const [loading, setLoading] = useState(false);
const [expandedDevices, setExpandedDevices] = useState({});
const [showAll, setShowAll] = useState(false);
const containerRef = useRef(null);
const observerRef = useRef(null);
// 初始化展开状态
useEffect(() => {
const initialExpanded = {};
devices.slice(0, initialVisibleCount).forEach((device, index) => {
initialExpanded[device.deviceId] = index < 3; // 前3个默认展开
});
setExpandedDevices(initialExpanded);
}, [devices, initialVisibleCount]);
// 无限滚动观察器
useEffect(() => {
if (showAll) return;
const options = {
root: null,
rootMargin: '100px',
threshold: 0.1,
};
observerRef.current = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting && !loading && visibleCount < devices.length) {
loadMore();
}
});
}, options);
const loadMoreTrigger = document.getElementById('load-more-trigger');
if (loadMoreTrigger) {
observerRef.current.observe(loadMoreTrigger);
}
return () => {
if (observerRef.current) {
observerRef.current.disconnect();
}
};
}, [visibleCount, devices.length, loading, showAll]);
const loadMore = useCallback(() => {
if (loading || visibleCount >= devices.length) return;
setLoading(true);
// 模拟异步加载,实际可以直接同步更新
setTimeout(() => {
setVisibleCount(prev => Math.min(prev + loadMoreCount, devices.length));
setLoading(false);
}, 100);
}, [loading, visibleCount, devices.length, loadMoreCount]);
const handleShowAll = useCallback(() => {
// 先显示所有设备
setVisibleCount(devices.length);
// 展开所有设备
const allExpanded = {};
devices.forEach(device => {
allExpanded[device.deviceId] = true;
});
setExpandedDevices(allExpanded);
setShowAll(true);
}, [devices]);
const handleCollapseAll = useCallback(() => {
// 收起所有面板(折叠所有设备),但保持当前显示的设备数量
const allCollapsed = {};
devices.forEach(device => {
allCollapsed[device.deviceId] = false;
});
setExpandedDevices(allCollapsed);
setShowAll(false);
}, [devices]);
const toggleDeviceExpand = deviceId => {
setExpandedDevices(prev => ({
...prev,
[deviceId]: prev[deviceId] === true ? false : true,
}));
};
const isDeviceExpanded = deviceId => {
return expandedDevices[deviceId] === true;
};
const visibleDevices = devices.slice(0, visibleCount);
const hasMore = visibleCount < devices.length;
if (devices.length === 0) {
return