重写ssh前端组件,通用化

This commit is contained in:
dengqichen 2025-12-07 23:29:52 +08:00
parent 03f2146546
commit 16b8db336f

View File

@ -0,0 +1,133 @@
/**
*
*
*/
import React, { useState, useCallback, useEffect } from 'react';
import { FolderOpen } from 'lucide-react';
import { FileManager } from './FileManager';
export interface FileManagerWindow {
id: string;
serverId: number;
serverName: string;
isMinimized: boolean;
}
export const FileManagerWindowManager: React.FC = () => {
const [windows, setWindows] = useState<FileManagerWindow[]>([]);
const [activeWindowId, setActiveWindowId] = useState<string | null>(null);
// 打开文件管理器窗口
const openWindow = useCallback((serverId: number, serverName: string) => {
const windowId = `file-manager-${serverId}-${Date.now()}`;
// 检查是否已存在该服务器的窗口
const existingWindow = windows.find(w => w.serverId === serverId && !w.isMinimized);
if (existingWindow) {
// 如果已存在且未最小化,聚焦它
setActiveWindowId(existingWindow.id);
return;
}
const newWindow: FileManagerWindow = {
id: windowId,
serverId,
serverName,
isMinimized: false,
};
setWindows(prev => [...prev, newWindow]);
setActiveWindowId(windowId);
console.log(`✅ 打开文件管理器: ${serverName} (${windowId})`);
}, [windows]);
// 关闭窗口
const closeWindow = useCallback((windowId: string) => {
setWindows(prev => prev.filter(w => w.id !== windowId));
if (activeWindowId === windowId) {
setActiveWindowId(null);
}
console.log(`❌ 关闭文件管理器: ${windowId}`);
}, [activeWindowId]);
// 最小化窗口
const minimizeWindow = useCallback((windowId: string) => {
setWindows(prev => prev.map(w =>
w.id === windowId ? { ...w, isMinimized: true } : w
));
if (activeWindowId === windowId) {
setActiveWindowId(null);
}
console.log(` 最小化文件管理器: ${windowId}`);
}, [activeWindowId]);
// 恢复窗口
const restoreWindow = useCallback((windowId: string) => {
setWindows(prev => prev.map(w =>
w.id === windowId ? { ...w, isMinimized: false } : w
));
setActiveWindowId(windowId);
console.log(` 恢复文件管理器: ${windowId}`);
}, []);
// 聚焦窗口
const focusWindow = useCallback((windowId: string) => {
setActiveWindowId(windowId);
}, []);
// 注册全局打开方法
useEffect(() => {
const globalKey = 'openFileManager';
(window as any)[globalKey] = openWindow;
console.log('📁 文件管理器窗口管理器已就绪');
return () => {
delete (window as any)[globalKey];
};
}, [openWindow]);
return (
<>
{/* 渲染所有文件管理器窗口 */}
{windows.map(win => !win.isMinimized && (
<FileManager
key={win.id}
serverId={win.serverId}
serverName={win.serverName}
open={true}
onClose={() => closeWindow(win.id)}
onMinimize={() => minimizeWindow(win.id)}
isActive={activeWindowId === win.id}
onFocus={() => focusWindow(win.id)}
/>
))}
{/* 最小化的窗口悬浮按钮 */}
{windows.filter(w => w.isMinimized).length > 0 && (
<div className="fixed bottom-4 left-4 flex flex-col-reverse gap-2 z-[1001]">
{windows
.filter(w => w.isMinimized)
.map((win) => (
<button
key={win.id}
className="flex items-center gap-3 px-4 py-3 bg-blue-600 text-white rounded-lg shadow-lg transition-all hover:scale-105 hover:shadow-xl"
onClick={() => restoreWindow(win.id)}
title={`恢复: ${win.serverName}`}
>
<FolderOpen className="h-5 w-5" />
<div className="text-left">
<div className="text-sm font-semibold">
{win.serverName}
</div>
<div className="text-xs opacity-90">
</div>
</div>
</button>
))}
</div>
)}
</>
);
};