import React, { useState, useRef, useEffect, useCallback } from 'react'; import { Button, Tooltip, Dropdown } from 'antd'; import { ArrowLeftOutlined, CloudServerOutlined, ReloadOutlined, EyeOutlined, SettingOutlined, FullscreenOutlined, MenuOutlined, SwapOutlined, } from '@ant-design/icons'; import CascadingRackPanel from './CascadingRackPanel'; import { useResponsiveLayout } from '../../hooks/useResponsiveLayout'; const ACTION_BUTTONS_CONFIG = [ { key: 'refresh', icon: , label: '刷新', tooltip: '刷新数据', }, { key: 'resetView', icon: , label: '重置视角', tooltip: '重置3D视图', }, { key: 'config', icon: , label: '显示配置', tooltip: '配置显示字段', }, ]; const RackSelectorHeader = ({ rooms, selectedRoomKey, selectedRack, onRackSelect, onPrevRack, onNextRack, racksInSelectedRoom, deviceSlideEnabled, onDeviceSlideToggle, onRefresh, onResetView, onOpenConfig, onBack, }) => { const [selectorVisible, setSelectorVisible] = useState(false); const selectorRef = useRef(null); const { screenSize, config, isMobile } = useResponsiveLayout(); useEffect(() => { const handleClickOutside = event => { if (selectorRef.current && !selectorRef.current.contains(event.target)) { setSelectorVisible(false); } }; if (selectorVisible) { document.addEventListener('mousedown', handleClickOutside); } return () => { document.removeEventListener('mousedown', handleClickOutside); }; }, [selectorVisible]); const handleRackSelect = useCallback( (rack, room) => { onRackSelect(rack, room); setSelectorVisible(false); }, [onRackSelect] ); const handleKeyDown = useCallback(e => { if (e.key === 'Escape') { setSelectorVisible(false); } if ((e.ctrlKey || e.metaKey) && e.key === 'k') { e.preventDefault(); setSelectorVisible(prev => !prev); } }, []); useEffect(() => { document.addEventListener('keydown', handleKeyDown); return () => document.removeEventListener('keydown', handleKeyDown); }, [handleKeyDown]); const selectedRoom = rooms.find(r => r.key === selectedRoomKey); const displayText = selectedRack ? `${selectedRoom?.name || ''} / ${selectedRack.name}` : '选择机房 / 机柜'; const canNavigatePrev = racksInSelectedRoom && racksInSelectedRoom.length > 1 && selectedRack; const canNavigateNext = racksInSelectedRoom && racksInSelectedRoom.length > 1 && selectedRack; const getCurrentRackIndex = () => { if (!selectedRack || !racksInSelectedRoom) return -1; return racksInSelectedRoom.findIndex(r => r.rackId === selectedRack.rackId); }; const dropdownMenuItems = ACTION_BUTTONS_CONFIG.map(btn => ({ key: btn.key, label: ( {btn.icon} {btn.label} ), onClick: () => { switch (btn.key) { case 'refresh': onRefresh(); break; case 'resetView': onResetView(); break; case 'config': onOpenConfig(); break; default: break; } }, })); const renderLeftSection = () => (
); const renderSelector = () => { const panelWidth = isMobile ? '100%' : 520; return (
setSelectorVisible(prev => !prev)} style={{ display: 'flex', alignItems: 'center', background: selectorVisible ? 'rgba(59, 130, 246, 0.15)' : 'rgba(255, 255, 255, 0.08)', border: selectorVisible ? '1px solid rgba(59, 130, 246, 0.5)' : '1px solid rgba(255, 255, 255, 0.12)', borderRadius: 10, padding: '8px 14px', cursor: 'pointer', transition: 'all 0.2s ease', minHeight: 40, }} >
{displayText}
{canNavigatePrev && (
{ e.stopPropagation(); onPrevRack(); }} style={{ padding: '4px 8px', borderRadius: 6, background: 'rgba(255,255,255,0.08)', cursor: 'pointer', display: 'flex', alignItems: 'center', color: 'rgba(255,255,255,0.7)', fontSize: 12, transition: 'all 0.15s', }} onMouseEnter={e => { e.currentTarget.style.background = 'rgba(255,255,255,0.15)'; }} onMouseLeave={e => { e.currentTarget.style.background = 'rgba(255,255,255,0.08)'; }} > ←
)} {canNavigateNext && (
{ e.stopPropagation(); onNextRack(); }} style={{ padding: '4px 8px', borderRadius: 6, background: 'rgba(255,255,255,0.08)', cursor: 'pointer', display: 'flex', alignItems: 'center', color: 'rgba(255,255,255,0.7)', fontSize: 12, transition: 'all 0.15s', }} onMouseEnter={e => { e.currentTarget.style.background = 'rgba(255,255,255,0.15)'; }} onMouseLeave={e => { e.currentTarget.style.background = 'rgba(255,255,255,0.08)'; }} > →
)}
setSelectorVisible(false)} triggerRef={selectorRef} />
); }; const renderActionButton = (btn, index) => { if (isMobile && btn.key === 'config') { return null; } return ( ); }; const renderDeviceSlideToggle = () => { if (!config.showDeviceSlide) return null; return (
{!isMobile && ( 设备弹出 )}
onDeviceSlideToggle(!deviceSlideEnabled)} style={{ width: 32, height: 18, borderRadius: 9, background: deviceSlideEnabled ? '#22c55e' : 'rgba(255,255,255,0.2)', position: 'relative', cursor: 'pointer', transition: 'background 0.2s', }} >
); }; const renderRightSection = () => { if (config.collapseActions) { return (
{renderDeviceSlideToggle()}
); } return (
{renderDeviceSlideToggle()} {ACTION_BUTTONS_CONFIG.map(renderActionButton)}
); }; return (
{renderLeftSection()} {renderSelector()} {renderRightSection()}
); }; export default RackSelectorHeader;