/** * Terminal 工具栏组件 */ import React from 'react'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; import { Search, Trash2, Copy, ZoomIn, ZoomOut, RotateCcw, Loader2, XCircle, Palette, SplitSquareVertical, SplitSquareHorizontal, Plus, ChevronDown, FolderOpen } from 'lucide-react'; import type { ConnectionStatus, TerminalToolbarConfig } from './types'; import type { TerminalTheme } from './themes'; import styles from './index.module.less'; interface TerminalToolbarProps { config: TerminalToolbarConfig; connectionStatus: ConnectionStatus; serverName?: string; hostIp?: string; connectedTime?: Date | null; fontSize: number; currentTheme?: string; themes?: TerminalTheme[]; compact?: boolean; // 紧凑模式 onSearch?: () => void; onClear?: () => void; onCopy?: () => void; onZoomIn?: () => void; onZoomOut?: () => void; onReconnect?: () => void; onThemeChange?: (theme: string) => void; onFileManager?: () => void; // 分屏操作 onSplitUp?: () => void; onSplitDown?: () => void; onSplitLeft?: () => void; onSplitRight?: () => void; onSplitInGroup?: () => void; } export const TerminalToolbar: React.FC = ({ config, connectionStatus, serverName, hostIp, connectedTime, fontSize, currentTheme, themes = [], compact = false, onSearch, onClear, onCopy, onZoomIn, onZoomOut, onReconnect, onThemeChange, onFileManager, onSplitUp, onSplitDown, onSplitLeft, onSplitRight, onSplitInGroup, }) => { const [, forceUpdate] = React.useState(0); // 定期更新连接时长显示 React.useEffect(() => { if (connectionStatus === 'connected' && connectedTime) { const timer = setInterval(() => { forceUpdate(prev => prev + 1); }, 1000); // 每秒更新一次 return () => clearInterval(timer); } }, [connectionStatus, connectedTime]); if (!config.show) return null; // 计算连接时长 const getConnectionDuration = () => { if (!connectedTime) return ''; const now = new Date(); const diff = Math.floor((now.getTime() - connectedTime.getTime()) / 1000); // 秒 const hours = Math.floor(diff / 3600); const minutes = Math.floor((diff % 3600) / 60); const seconds = diff % 60; if (hours > 0) { return `${hours}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`; } return `${minutes}:${seconds.toString().padStart(2, '0')}`; }; const getStatusBadge = () => { // 紧凑模式:只显示状态圆点 if (compact) { switch (connectionStatus) { case 'connecting': return
; case 'connected': return
; case 'reconnecting': return
; case 'error': return
; case 'disconnected': return
; } } // 正常模式:显示带文字的Badge switch (connectionStatus) { case 'connecting': return 连接中; case 'connected': // 已连接状态:显示IP和连接时长 return (
已连接 {hostIp && ( <> | {hostIp} )} {connectedTime && ( <> | {getConnectionDuration()} )} ); case 'reconnecting': return 重连中; case 'error': return 连接失败; case 'disconnected': return 已断开; } }; return (
{/* 左侧:状态指示器 */}
{config.showStatus && getStatusBadge()} {config.showFontSizeLabel && ( {compact ? `${fontSize}px` : `字体 ${fontSize}px`} )}
{/* 右侧:所有操作按钮 */}
{/* 文件管理 */} {onFileManager && ( )} {config.showSearch && ( )} {config.showClear && ( )} {config.showCopy && ( )} {config.showFontSize && ( <>
)} {/* 主题选择器 */} {themes.length > 0 && onThemeChange && ( <>
)} {/* 分屏菜单 */} {(onSplitUp || onSplitDown || onSplitLeft || onSplitRight || onSplitInGroup) && ( <>
{onSplitUp && ( { e.stopPropagation(); onSplitUp(); }}> 向上拆分 )} {onSplitDown && ( { e.stopPropagation(); onSplitDown(); }}> 向下拆分 )} {(onSplitUp || onSplitDown) && (onSplitLeft || onSplitRight) && ( )} {onSplitLeft && ( { e.stopPropagation(); onSplitLeft(); }}> 向左拆分 )} {onSplitRight && ( { e.stopPropagation(); onSplitRight(); }}> 向右拆分 )} {onSplitInGroup && ( <> { e.stopPropagation(); onSplitInGroup(); }}> 在组中拆分 )} )} {(connectionStatus === 'disconnected' || connectionStatus === 'error') && ( <>
)} {config.extraActions}
); };