重写ssh前端组件,通用化
This commit is contained in:
parent
03f2146546
commit
16b8db336f
133
frontend/src/components/FileManager/FileManagerWindowManager.tsx
Normal file
133
frontend/src/components/FileManager/FileManagerWindowManager.tsx
Normal 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>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user