增加SSH功能

This commit is contained in:
dengqichen 2025-12-05 18:02:21 +08:00
parent 366935c575
commit 86276b2ffd
2 changed files with 42 additions and 28 deletions

View File

@ -254,8 +254,6 @@ export const SSHTerminalContent: React.FC<SSHTerminalContentProps> = ({
ws.onopen = () => { ws.onopen = () => {
console.log('🔗 WebSocket已连接:', wsUrl); console.log('🔗 WebSocket已连接:', wsUrl);
console.log('📺 Terminal实例存在:', !!terminalInstanceRef.current); console.log('📺 Terminal实例存在:', !!terminalInstanceRef.current);
terminalInstanceRef.current?.writeln('\x1b[32m✓ WebSocket连接已建立\x1b[0m');
terminalInstanceRef.current?.writeln('\x1b[36m正在建立SSH会话...\x1b[0m\r\n');
}; };
ws.onmessage = (event) => { ws.onmessage = (event) => {
@ -287,7 +285,13 @@ export const SSHTerminalContent: React.FC<SSHTerminalContentProps> = ({
if (msg.status) { if (msg.status) {
setConnectionStatus(msg.status); setConnectionStatus(msg.status);
if (msg.status === 'connected') { if (msg.status === 'connected') {
terminalInstanceRef.current?.writeln('\x1b[32m✓ SSH会话已建立\x1b[0m\r\n'); // 显示审计警告
terminalInstanceRef.current?.writeln('\r\n\x1b[33m┌────────────────────────────────────────────────────────────┐\x1b[0m');
terminalInstanceRef.current?.writeln('\x1b[33m│ ⚠️ 安全提示本次SSH会话将被全程审计记录 │\x1b[0m');
terminalInstanceRef.current?.writeln('\x1b[33m│ • 所有操作命令、输入、输出都将被完整记录 │\x1b[0m');
terminalInstanceRef.current?.writeln('\x1b[33m│ • 审计日志用于安全审查、故障排查和合规要求 │\x1b[0m');
terminalInstanceRef.current?.writeln('\x1b[33m│ • 请规范操作,遵守企业信息安全管理制度 │\x1b[0m');
terminalInstanceRef.current?.writeln('\x1b[33m└────────────────────────────────────────────────────────────┘\x1b[0m\r\n');
setTimeout(() => { setTimeout(() => {
fitAddonRef.current?.fit(); fitAddonRef.current?.fit();
}, 100); }, 100);

View File

@ -176,33 +176,43 @@ export const SSHWindowManager: React.FC<SSHWindowManagerProps> = ({ onOpenWindow
<div className="fixed bottom-4 right-4 flex flex-col-reverse gap-2 z-[1001]"> <div className="fixed bottom-4 right-4 flex flex-col-reverse gap-2 z-[1001]">
{windows {windows
.filter(w => w.isMinimized) .filter(w => w.isMinimized)
.map((window) => ( .map((window) => {
<button // 计算同一服务器的窗口数量和当前窗口序号
key={window.id} const sameServerWindows = windows.filter(w => w.server.id === window.server.id);
className={`flex items-center gap-3 px-4 py-3 ${getButtonStyle(window.connectionStatus)} text-white rounded-lg shadow-lg transition-all hover:scale-105 hover:shadow-xl relative`} const needsIndex = sameServerWindows.length > 1;
onClick={() => restoreWindow(window.id)} const windowIndex = sameServerWindows.findIndex(w => w.id === window.id) + 1;
title={`恢复: ${window.server.serverName}`}
> return (
{/* 状态指示灯 */} <button
<div className="absolute top-2 right-2"> key={window.id}
<div className={`h-2 w-2 rounded-full ${ className={`flex items-center gap-3 px-4 py-3 ${getButtonStyle(window.connectionStatus)} text-white rounded-lg shadow-lg transition-all hover:scale-105 hover:shadow-xl relative`}
window.connectionStatus === 'connected' ? 'bg-white animate-pulse' : onClick={() => restoreWindow(window.id)}
window.connectionStatus === 'error' || window.connectionStatus === 'disconnected' ? 'bg-white/70' : title={`恢复: ${window.server.serverName}${needsIndex ? ` #${windowIndex}` : ''}`}
'bg-white/50 animate-pulse' >
}`} /> {/* 状态指示灯 */}
</div> <div className="absolute top-2 right-2">
<div className={`h-2 w-2 rounded-full ${
<Terminal className="h-5 w-5" /> window.connectionStatus === 'connected' ? 'bg-white animate-pulse' :
<div className="text-left"> window.connectionStatus === 'error' || window.connectionStatus === 'disconnected' ? 'bg-white/70' :
<div className="text-sm font-semibold"> 'bg-white/50 animate-pulse'
{window.server.serverName} }`} />
</div> </div>
<div className="text-xs opacity-90">
{window.server.hostIp} <Terminal className="h-5 w-5" />
<div className="text-left">
<div className="text-sm font-semibold flex items-center gap-2">
<span>{window.server.serverName}</span>
{needsIndex && (
<span className="text-xs opacity-75">#{windowIndex}</span>
)}
</div>
<div className="text-xs opacity-90">
{window.server.hostIp}
</div>
</div> </div>
</div> </button>
</button> );
))} })}
</div> </div>
)} )}
</> </>