feat: v0.3.0 版本 - SSH终端、SFTP、端口转发功能实现

核心功能:
- SSH终端: 密码/密钥认证、XTerm.js终端、多主题配色、IP高亮
- SFTP管理: 双栏文件管理、上传下载、传输队列
- 端口转发: 本地/远程转发、SOCKS5动态代理、规则管理

架构改进:
- 拆分大型组件 (SFTPView/TabBar/Sidebar)
- 添加统一日志和错误处理
- 修复React严格模式下的终端黑屏问题

UI更新:
- 新增端口转发视图
- 更新UI预览文档
- 左侧栏右键菜单支持SFTP快捷打开
This commit is contained in:
Logan.Li committed 2026-04-06 01:20:47 +08:00
1 parent cf1c054381
commit 484d850abd
105 files changed
+25330 -64

No files matched your search

+680
View File
@@ -0,0 +1,680 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>OpsXShell - 功能预览与架构设计</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
<style>
body { font-family: 'Inter', sans-serif; }
.terminal-text { font-family: 'Menlo', 'Monaco', 'Courier New', monospace; }
.tab-active {
background: #1e293b;
border-top: 2px solid #22d3ee;
}
.preview-container {
aspect-ratio: 16/10;
}
.feature-done {
border-left: 4px solid #22c55e;
}
.feature-progress {
border-left: 4px solid #f59e0b;
}
.feature-todo {
border-left: 4px solid #6b7280;
}
</style>
</head>
<body class="bg-slate-950 min-h-screen p-8">
<div class="max-w-7xl mx-auto space-y-8">
<!-- Header -->
<div class="text-center mb-8">
<h1 class="text-4xl font-bold text-white mb-3">OpsXShell 功能架构</h1>
<p class="text-slate-400 text-lg">跨平台 SSH/SFTP 终端工具 · 专业级远程连接解决方案</p>
<div class="flex justify-center gap-4 mt-6">
<span class="flex items-center gap-2 text-sm text-green-400">
<div class="w-3 h-3 rounded-full bg-green-500"></div>
已实现
</span>
<span class="flex items-center gap-2 text-sm text-yellow-400">
<div class="w-3 h-3 rounded-full bg-yellow-500"></div>
进行中
</span>
<span class="flex items-center gap-2 text-sm text-gray-400">
<div class="w-3 h-3 rounded-full bg-gray-500"></div>
规划中
</span>
</div>
</div>
<!-- Tab Switcher -->
<div class="flex justify-center gap-2 mb-6 flex-wrap">
<button onclick="showView('terminal')" id="tab-terminal" class="px-6 py-2 rounded-lg text-sm font-medium transition-colors bg-cyan-600 text-white">
<i class="fas fa-terminal mr-2"></i>SSH 终端
</button>
<button onclick="showView('sftp')" id="tab-sftp" class="px-6 py-2 rounded-lg text-sm font-medium transition-colors bg-slate-800 text-slate-300 hover:bg-slate-700">
<i class="fas fa-folder-open mr-2"></i>SFTP 管理
</button>
<button onclick="showView('portforward')" id="tab-portforward" class="px-6 py-2 rounded-lg text-sm font-medium transition-colors bg-slate-800 text-slate-300 hover:bg-slate-700">
<i class="fas fa-network-wired mr-2"></i>端口转发
</button>
<button onclick="showView('features')" id="tab-features" class="px-6 py-2 rounded-lg text-sm font-medium transition-colors bg-slate-800 text-slate-300 hover:bg-slate-700">
<i class="fas fa-list-check mr-2"></i>功能清单
</button>
</div>
<!-- Terminal View -->
<div id="view-terminal" class="preview-container">
<div class="bg-slate-900 rounded-2xl border border-slate-800 overflow-hidden shadow-2xl shadow-cyan-500/10 h-full">
<!-- Title Bar -->
<div class="bg-gradient-to-r from-slate-800 to-slate-700 px-4 py-3 flex items-center justify-between border-b border-slate-700">
<div class="flex items-center gap-3">
<div class="flex gap-2">
<div class="w-3 h-3 rounded-full bg-red-500"></div>
<div class="w-3 h-3 rounded-full bg-yellow-500"></div>
<div class="w-3 h-3 rounded-full bg-green-500"></div>
</div>
<div class="flex items-center gap-2 ml-4">
<i class="fas fa-terminal text-cyan-400"></i>
<span class="text-slate-200 font-medium">OpsXShell</span>
</div>
</div>
</div>
<!-- Main Content -->
<div class="flex h-[calc(100%-48px)]">
<!-- Sidebar -->
<div class="w-60 bg-slate-950 border-r border-slate-800 p-3 flex flex-col">
<div class="flex items-center gap-2 mb-4 px-2 py-2 bg-slate-800 rounded-lg border border-slate-700">
<i class="fas fa-search text-slate-500 text-xs"></i>
<span class="text-slate-500 text-xs">搜索会话...</span>
</div>
<div class="space-y-1 flex-1">
<div class="text-xs text-slate-500 font-semibold px-2 mb-2">生产环境</div>
<div class="flex items-center gap-2 px-2 py-2.5 bg-cyan-500/20 rounded-lg border border-cyan-500/30 cursor-pointer">
<div class="w-2 h-2 rounded-full bg-green-500"></div>
<i class="fas fa-server text-cyan-400 text-xs"></i>
<span class="text-slate-200 text-sm font-medium">Web-Prod-01</span>
</div>
<div class="flex items-center gap-2 px-2 py-2 hover:bg-slate-800 rounded-lg cursor-pointer transition-colors">
<div class="w-2 h-2 rounded-full bg-green-500"></div>
<i class="fas fa-database text-slate-500 text-xs"></i>
<span class="text-slate-400 text-sm">DB-Master</span>
</div>
</div>
<button class="mt-3 w-full bg-cyan-600 hover:bg-cyan-500 text-white text-xs py-2.5 rounded-lg flex items-center justify-center gap-2 transition-colors">
<i class="fas fa-plus"></i> 新建会话
</button>
</div>
<!-- Right Panel -->
<div class="flex-1 flex flex-col bg-slate-950">
<!-- Tab Bar -->
<div class="flex items-center bg-slate-900 border-b border-slate-800 px-2">
<div class="flex items-center gap-1 py-1 flex-1">
<div class="tab-active flex items-center gap-2 px-4 py-2 rounded-t-lg cursor-pointer group">
<i class="fas fa-terminal text-cyan-400 text-xs"></i>
<span class="text-slate-200 text-sm">Web-Prod-01</span>
<div class="flex items-center gap-1 ml-1 opacity-0 group-hover:opacity-100 transition-opacity">
<button class="p-1 hover:bg-slate-600 rounded" title="更多">
<i class="fas fa-ellipsis-h text-slate-400 text-xs"></i>
</button>
<button class="p-1 hover:bg-slate-600 rounded" title="关闭">
<i class="fas fa-times text-slate-400 text-xs"></i>
</button>
</div>
</div>
<div class="flex items-center gap-2 px-4 py-2 hover:bg-slate-800 rounded-t-lg cursor-pointer transition-colors">
<i class="fas fa-folder text-yellow-500 text-xs"></i>
<span class="text-slate-400 text-sm">SFTP</span>
</div>
</div>
<button class="p-2 text-slate-400 hover:text-slate-200 hover:bg-slate-800 rounded-lg transition-colors">
<i class="fas fa-plus text-xs"></i>
</button>
</div>
<!-- Terminal Area -->
<div class="flex-1 p-5 terminal-text text-sm overflow-auto" style="background: #0d1117;">
<div class="text-green-400">➜ ~</div>
<div class="text-slate-300 mt-2">ssh root@192.168.1.100</div>
<div class="text-slate-500 mt-2">Connecting to 192.168.1.100...</div>
<div class="text-green-400 mt-2">✓ Connected to CentOS 7.9</div>
<div class="mt-2 text-slate-400">Last login: Mon Jan 15 10:30:25 2026 from <span class="text-green-400">172.16.2.1</span></div>
<div class="text-cyan-400 mt-3 flex items-center gap-2">
<span>[root@localhost ~]#</span>
<span class="animate-pulse">_</span>
</div>
</div>
<!-- Status Bar -->
<div class="bg-slate-900 border-t border-slate-800 px-4 py-2.5 flex items-center justify-between text-xs">
<div class="flex items-center gap-6">
<span class="text-green-500 flex items-center gap-1.5">
<i class="fas fa-circle text-[8px]"></i>已连接
</span>
<span class="text-cyan-400 flex items-center gap-1.5">
<i class="fas fa-wifi"></i>12ms
</span>
</div>
<div class="flex items-center gap-6 text-slate-500">
<button class="hover:text-slate-300 flex items-center gap-1.5 transition-colors">
<i class="fas fa-exchange-alt"></i>端口转发
</button>
<button class="hover:text-slate-300 flex items-center gap-1.5 transition-colors">
<i class="fas fa-folder-open"></i>SFTP
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- SFTP View -->
<div id="view-sftp" class="preview-container hidden">
<div class="bg-slate-900 rounded-2xl border border-slate-800 overflow-hidden shadow-2xl shadow-cyan-500/10 h-full flex flex-col">
<!-- Title Bar -->
<div class="bg-gradient-to-r from-slate-800 to-slate-700 px-4 py-3 flex items-center justify-between border-b border-slate-700">
<div class="flex items-center gap-3">
<div class="flex gap-2">
<div class="w-3 h-3 rounded-full bg-red-500"></div>
<div class="w-3 h-3 rounded-full bg-yellow-500"></div>
<div class="w-3 h-3 rounded-full bg-green-500"></div>
</div>
<div class="flex items-center gap-2 ml-4">
<i class="fas fa-terminal text-cyan-400"></i>
<span class="text-slate-200 font-medium">OpsXShell</span>
</div>
</div>
</div>
<!-- Main Content -->
<div class="flex-1 flex flex-col min-h-0">
<!-- Toolbar -->
<div class="h-12 flex items-center justify-between px-4 border-b border-slate-800 bg-slate-900">
<div class="flex items-center gap-2">
<span class="text-sm text-slate-400">SFTP - root@192.168.1.100</span>
<span class="px-2 py-0.5 text-xs rounded bg-green-500/20 text-green-400">已连接</span>
</div>
<div class="flex items-center gap-2">
<button class="flex items-center gap-2 px-4 py-1.5 bg-cyan-600 hover:bg-cyan-500 rounded-lg text-sm text-white transition-colors">
<i class="fas fa-download text-xs"></i>下载
</button>
<button class="flex items-center gap-2 px-4 py-1.5 bg-green-600 hover:bg-green-500 rounded-lg text-sm text-white transition-colors">
<i class="fas fa-upload text-xs"></i>上传
</button>
<button class="p-2 text-slate-400 hover:text-slate-200 hover:bg-slate-800 rounded-lg transition-colors">
<i class="fas fa-sync-alt text-xs"></i>
</button>
</div>
</div>
<!-- Dual Pane File Manager -->
<div class="flex-1 flex min-h-0">
<!-- Local Panel -->
<div class="flex-1 flex flex-col border-r border-slate-800">
<div class="h-12 flex items-center justify-between px-4 border-b border-slate-800 bg-slate-800/50">
<div class="flex items-center gap-3">
<i class="fas fa-hdd text-cyan-400"></i>
<span class="font-medium text-slate-200">本地</span>
</div>
</div>
<div class="h-10 flex items-center gap-2 px-4 border-b border-slate-800">
<div class="flex items-center gap-1 text-sm text-slate-300">
<i class="fas fa-home text-slate-400"></i>
<span class="text-slate-500">›</span>
<span>Users</span>
<span class="text-slate-500">›</span>
<span>admin</span>
</div>
</div>
<div class="h-9 flex items-center px-4 bg-slate-800/30 text-xs text-slate-500 border-b border-slate-800">
<div class="flex-1 min-w-0">名称</div>
<div class="w-32 text-right">修改时间</div>
<div class="w-24 text-right">大小</div>
</div>
<div class="flex-1 overflow-y-auto">
<div class="h-10 flex items-center px-4 hover:bg-slate-800/50 cursor-pointer border-b border-slate-800/50">
<div class="flex-1 flex items-center gap-2 min-w-0">
<i class="fas fa-folder text-sky-400 w-4"></i>
<span class="text-sm text-slate-300">Desktop</span>
</div>
<div class="w-32 text-right text-xs text-slate-500">2026/01/15</div>
<div class="w-24 text-right text-xs text-slate-500">--</div>
</div>
<div class="h-10 flex items-center px-4 hover:bg-slate-800/50 cursor-pointer border-b border-slate-800/50">
<div class="flex-1 flex items-center gap-2 min-w-0">
<i class="fas fa-folder text-sky-400 w-4"></i>
<span class="text-sm text-slate-300">Documents</span>
</div>
<div class="w-32 text-right text-xs text-slate-500">2026/01/14</div>
<div class="w-24 text-right text-xs text-slate-500">--</div>
</div>
<div class="h-10 flex items-center px-4 hover:bg-slate-800/50 cursor-pointer border-b border-slate-800/50 bg-cyan-500/10">
<div class="flex-1 flex items-center gap-2 min-w-0">
<i class="fas fa-file text-slate-400 w-4"></i>
<span class="text-sm text-slate-300">deploy.sh</span>
</div>
<div class="w-32 text-right text-xs text-slate-500">2026/01/15</div>
<div class="w-24 text-right text-xs text-slate-500">2.4 KB</div>
</div>
</div>
</div>
<!-- Remote Panel -->
<div class="flex-1 flex flex-col">
<div class="h-12 flex items-center justify-between px-4 border-b border-slate-800 bg-slate-800/50">
<div class="flex items-center gap-3">
<i class="fas fa-desktop text-cyan-400"></i>
<span class="font-medium text-slate-200">192.168.1.100</span>
</div>
</div>
<div class="h-10 flex items-center gap-2 px-4 border-b border-slate-800">
<div class="flex items-center gap-1 text-sm text-slate-300">
<i class="fas fa-hdd text-slate-400"></i>
<span class="text-slate-500">›</span>
<span>root</span>
</div>
</div>
<div class="h-9 flex items-center px-4 bg-slate-800/30 text-xs text-slate-500 border-b border-slate-800">
<div class="flex-1 min-w-0">名称</div>
<div class="w-32 text-right">修改时间</div>
<div class="w-24 text-right">大小</div>
</div>
<div class="flex-1 overflow-y-auto">
<div class="h-10 flex items-center px-4 hover:bg-slate-800/50 cursor-pointer border-b border-slate-800/50">
<div class="flex-1 flex items-center gap-2 min-w-0">
<i class="fas fa-folder text-sky-400 w-4"></i>
<span class="text-sm text-slate-300">..</span>
</div>
</div>
<div class="h-10 flex items-center px-4 hover:bg-slate-800/50 cursor-pointer border-b border-slate-800/50">
<div class="flex-1 flex items-center gap-2 min-w-0">
<i class="fas fa-folder text-sky-400 w-4"></i>
<span class="text-sm text-slate-300">logs</span>
</div>
<div class="w-32 text-right text-xs text-slate-500">2026/01/15</div>
<div class="w-24 text-right text-xs text-slate-500">--</div>
</div>
<div class="h-10 flex items-center px-4 hover:bg-slate-800/50 cursor-pointer border-b border-slate-800/50">
<div class="flex-1 flex items-center gap-2 min-w-0">
<i class="fas fa-file text-slate-400 w-4"></i>
<span class="text-sm text-slate-300">nginx.conf</span>
</div>
<div class="w-32 text-right text-xs text-slate-500">2026/01/14</div>
<div class="w-24 text-right text-xs text-slate-500">1.2 KB</div>
</div>
</div>
</div>
</div>
<!-- Transfer Panel -->
<div class="h-40 border-t border-slate-800 bg-slate-900">
<div class="h-10 flex items-center justify-between px-4 bg-slate-800/50">
<div class="flex items-center gap-2">
<i class="fas fa-chevron-down text-slate-400 text-xs"></i>
<span class="text-sm text-slate-300">传输队列</span>
<span class="px-2 py-0.5 text-xs bg-cyan-500/20 text-cyan-400 rounded">2</span>
</div>
</div>
<div class="p-2 space-y-1">
<div class="flex items-center gap-3 px-3 py-2 bg-slate-800/30 rounded">
<i class="fas fa-download text-cyan-400 w-4"></i>
<div class="flex-1 min-w-0">
<div class="text-sm text-slate-300">nginx.conf</div>
<div class="h-1.5 bg-slate-700 rounded-full mt-1 overflow-hidden">
<div class="h-full bg-cyan-400" style="width: 75%"></div>
</div>
</div>
<div class="text-xs text-slate-500">75%</div>
</div>
<div class="flex items-center gap-3 px-3 py-2 bg-slate-800/30 rounded">
<i class="fas fa-upload text-green-400 w-4"></i>
<div class="flex-1 min-w-0">
<div class="text-sm text-slate-300">deploy.sh</div>
<div class="h-1.5 bg-slate-700 rounded-full mt-1 overflow-hidden">
<div class="h-full bg-green-400" style="width: 30%"></div>
</div>
</div>
<div class="text-xs text-slate-500">30%</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Port Forward View -->
<div id="view-portforward" class="preview-container hidden">
<div class="bg-slate-900 rounded-2xl border border-slate-800 overflow-hidden shadow-2xl shadow-cyan-500/10 h-full flex flex-col">
<!-- Title Bar -->
<div class="bg-gradient-to-r from-slate-800 to-slate-700 px-4 py-3 flex items-center justify-between border-b border-slate-700">
<div class="flex items-center gap-3">
<div class="flex gap-2">
<div class="w-3 h-3 rounded-full bg-red-500"></div>
<div class="w-3 h-3 rounded-full bg-yellow-500"></div>
<div class="w-3 h-3 rounded-full bg-green-500"></div>
</div>
<div class="flex items-center gap-2 ml-4">
<i class="fas fa-terminal text-cyan-400"></i>
<span class="text-slate-200 font-medium">OpsXShell</span>
</div>
</div>
</div>
<!-- Main Content -->
<div class="flex-1 flex flex-col min-h-0">
<!-- Header -->
<div class="h-14 flex items-center justify-between px-6 border-b border-slate-800 bg-slate-900">
<div class="flex items-center gap-3">
<div class="w-10 h-10 bg-orange-500/20 rounded-lg flex items-center justify-center">
<i class="fas fa-exchange-alt text-orange-400"></i>
</div>
<div>
<div class="font-semibold text-white">端口转发</div>
<div class="text-sm text-gray-500">已连接: root@192.168.1.100</div>
</div>
</div>
<button class="flex items-center gap-2 px-4 py-2 bg-orange-600 hover:bg-orange-500 rounded-lg text-sm font-medium text-white transition-colors">
<i class="fas fa-plus mr-1"></i>添加规则
</button>
</div>
<!-- Rules List -->
<div class="flex-1 overflow-y-auto p-6">
<!-- Active Rule - Local Forward -->
<div class="p-4 rounded-lg border border-green-500/30 bg-green-500/10 mb-4">
<div class="flex items-center justify-between">
<div class="flex items-center gap-4">
<div class="w-10 h-10 rounded-lg bg-blue-500/20 flex items-center justify-center text-blue-400">
<i class="fas fa-arrow-right"></i>
</div>
<div>
<div class="flex items-center gap-2">
<span class="font-medium text-white">MySQL 本地转发</span>
<span class="text-xs px-2 py-0.5 rounded bg-blue-500/20 text-blue-400">本地转发</span>
<span class="text-xs px-2 py-0.5 rounded bg-green-500/20 text-green-400">运行中</span>
</div>
<div class="text-sm text-gray-400 mt-1">
127.0.0.1:3306 → 192.168.1.100:3306
</div>
</div>
</div>
<div class="flex items-center gap-2">
<button class="p-2 text-yellow-400 hover:bg-yellow-400/10 rounded" title="停止">
<i class="fas fa-stop"></i>
</button>
<button class="p-2 text-red-400 hover:bg-red-400/10 rounded" title="删除">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
</div>
<!-- Active Rule - Dynamic SOCKS5 -->
<div class="p-4 rounded-lg border border-green-500/30 bg-green-500/10 mb-4">
<div class="flex items-center justify-between">
<div class="flex items-center gap-4">
<div class="w-10 h-10 rounded-lg bg-orange-500/20 flex items-center justify-center text-orange-400">
<i class="fas fa-globe"></i>
</div>
<div>
<div class="flex items-center gap-2">
<span class="font-medium text-white">SOCKS5 代理</span>
<span class="text-xs px-2 py-0.5 rounded bg-orange-500/20 text-orange-400">动态 SOCKS5</span>
<span class="text-xs px-2 py-0.5 rounded bg-green-500/20 text-green-400">运行中</span>
</div>
<div class="text-sm text-gray-400 mt-1">
SOCKS5 代理: 127.0.0.1:1080
</div>
</div>
</div>
<div class="flex items-center gap-2">
<button class="p-2 text-yellow-400 hover:bg-yellow-400/10 rounded" title="停止">
<i class="fas fa-stop"></i>
</button>
<button class="p-2 text-red-400 hover:bg-red-400/10 rounded" title="删除">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
</div>
<!-- Inactive Rule - Remote Forward -->
<div class="p-4 rounded-lg border border-slate-700 bg-slate-800">
<div class="flex items-center justify-between">
<div class="flex items-center gap-4">
<div class="w-10 h-10 rounded-lg bg-purple-500/20 flex items-center justify-center text-purple-400">
<i class="fas fa-arrow-left"></i>
</div>
<div>
<div class="flex items-center gap-2">
<span class="font-medium text-white">Redis 远程转发</span>
<span class="text-xs px-2 py-0.5 rounded bg-purple-500/20 text-purple-400">远程转发</span>
</div>
<div class="text-sm text-gray-400 mt-1">
远程 6379 → 本地 127.0.0.1:6379
</div>
</div>
</div>
<div class="flex items-center gap-2">
<button class="p-2 text-green-400 hover:bg-green-400/10 rounded" title="启动">
<i class="fas fa-play"></i>
</button>
<button class="p-2 text-red-400 hover:bg-red-400/10 rounded" title="删除">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
</div>
</div>
<!-- Info Panel -->
<div class="h-36 border-t border-slate-800 bg-slate-800/50 p-4">
<div class="text-sm text-slate-400">
<p class="mb-2"><i class="fas fa-info-circle mr-2 text-cyan-400"></i><strong class="text-slate-300">端口转发类型说明:</strong></p>
<ul class="space-y-1 ml-6 text-xs">
<li>• <strong class="text-blue-400">本地转发</strong>: 将本地端口映射到远程服务器 (访问内网MySQL/Redis等)</li>
<li>• <strong class="text-purple-400">远程转发</strong>: 将远程端口映射到本地 (让外网访问本地服务)</li>
<li>• <strong class="text-orange-400">动态 SOCKS5</strong>: 创建 SOCKS5 代理服务器 (浏览器代理/科学上网)</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<!-- Features List View -->
<div id="view-features" class="preview-container hidden">
<div class="bg-slate-900 rounded-2xl border border-slate-800 overflow-hidden shadow-2xl h-full p-8 overflow-y-auto">
<h2 class="text-2xl font-bold text-white mb-6 flex items-center gap-3">
<i class="fas fa-list-check text-cyan-400"></i>
功能实现清单
</h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<!-- SSH Terminal -->
<div class="feature-done bg-slate-800/50 rounded-xl p-6">
<div class="flex items-center gap-3 mb-4">
<div class="w-10 h-10 bg-cyan-500/20 rounded-lg flex items-center justify-center">
<i class="fas fa-terminal text-cyan-400"></i>
</div>
<h3 class="text-lg font-semibold text-white">SSH 终端</h3>
</div>
<ul class="space-y-3 text-sm">
<li class="flex items-center gap-2 text-green-400">
<i class="fas fa-check-circle"></i>
<span>密码认证</span>
</li>
<li class="flex items-center gap-2 text-green-400">
<i class="fas fa-check-circle"></i>
<span>密钥认证 (RSA/ED25519)</span>
</li>
<li class="flex items-center gap-2 text-green-400">
<i class="fas fa-check-circle"></i>
<span>XTerm.js 高性能终端</span>
</li>
<li class="flex items-center gap-2 text-green-400">
<i class="fas fa-check-circle"></i>
<span>多主题配色 (Dracula/Monokai/Solarized/One Dark)</span>
</li>
<li class="flex items-center gap-2 text-green-400">
<i class="fas fa-check-circle"></i>
<span>IP 地址高亮显示</span>
</li>
<li class="flex items-center gap-2 text-yellow-400">
<i class="fas fa-clock"></i>
<span>智能命令补全 (规划中)</span>
</li>
</ul>
</div>
<!-- SFTP -->
<div class="feature-done bg-slate-800/50 rounded-xl p-6">
<div class="flex items-center gap-3 mb-4">
<div class="w-10 h-10 bg-green-500/20 rounded-lg flex items-center justify-center">
<i class="fas fa-folder-open text-green-400"></i>
</div>
<h3 class="text-lg font-semibold text-white">SFTP 管理</h3>
</div>
<ul class="space-y-3 text-sm">
<li class="flex items-center gap-2 text-green-400">
<i class="fas fa-check-circle"></i>
<span>双栏文件管理器</span>
</li>
<li class="flex items-center gap-2 text-green-400">
<i class="fas fa-check-circle"></i>
<span>上传/下载文件</span>
</li>
<li class="flex items-center gap-2 text-green-400">
<i class="fas fa-check-circle"></i>
<span>传输队列管理</span>
</li>
<li class="flex items-center gap-2 text-green-400">
<i class="fas fa-check-circle"></i>
<span>传输进度显示</span>
</li>
<li class="flex items-center gap-2 text-yellow-400">
<i class="fas fa-clock"></i>
<span>拖拽上传下载 (进行中)</span>
</li>
<li class="flex items-center gap-2 text-gray-400">
<i class="fas fa-circle text-[8px]"></i>
<span>断点续传 (规划中)</span>
</li>
</ul>
</div>
<!-- Port Forward -->
<div class="feature-done bg-slate-800/50 rounded-xl p-6">
<div class="flex items-center gap-3 mb-4">
<div class="w-10 h-10 bg-orange-500/20 rounded-lg flex items-center justify-center">
<i class="fas fa-network-wired text-orange-400"></i>
</div>
<h3 class="text-lg font-semibold text-white">端口转发</h3>
</div>
<ul class="space-y-3 text-sm">
<li class="flex items-center gap-2 text-green-400">
<i class="fas fa-check-circle"></i>
<span>本地端口转发</span>
</li>
<li class="flex items-center gap-2 text-green-400">
<i class="fas fa-check-circle"></i>
<span>远程端口转发</span>
</li>
<li class="flex items-center gap-2 text-green-400">
<i class="fas fa-check-circle"></i>
<span>动态 SOCKS5 代理</span>
</li>
<li class="flex items-center gap-2 text-green-400">
<i class="fas fa-check-circle"></i>
<span>转发规则管理</span>
</li>
<li class="flex items-center gap-2 text-green-400">
<i class="fas fa-check-circle"></i>
<span>规则持久化存储</span>
</li>
</ul>
</div>
</div>
<!-- Architecture Info -->
<div class="mt-8 p-6 bg-slate-800/30 rounded-xl border border-slate-700">
<h3 class="text-lg font-semibold text-white mb-4 flex items-center gap-2">
<i class="fas fa-sitemap text-cyan-400"></i>
技术架构
</h3>
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 text-sm">
<div class="text-center p-4 bg-slate-800 rounded-lg">
<div class="text-cyan-400 font-semibold mb-1">Electron 28+</div>
<div class="text-slate-500 text-xs">跨平台桌面框架</div>
</div>
<div class="text-center p-4 bg-slate-800 rounded-lg">
<div class="text-cyan-400 font-semibold mb-1">React 18</div>
<div class="text-slate-500 text-xs">UI 组件库</div>
</div>
<div class="text-center p-4 bg-slate-800 rounded-lg">
<div class="text-cyan-400 font-semibold mb-1">TypeScript 5</div>
<div class="text-slate-500 text-xs">类型安全</div>
</div>
<div class="text-center p-4 bg-slate-800 rounded-lg">
<div class="text-cyan-400 font-semibold mb-1">ssh2</div>
<div class="text-slate-500 text-xs">SSH/SFTP 协议</div>
</div>
<div class="text-center p-4 bg-slate-800 rounded-lg">
<div class="text-cyan-400 font-semibold mb-1">XTerm.js</div>
<div class="text-slate-500 text-xs">终端仿真</div>
</div>
<div class="text-center p-4 bg-slate-800 rounded-lg">
<div class="text-cyan-400 font-semibold mb-1">Zustand</div>
<div class="text-slate-500 text-xs">状态管理</div>
</div>
<div class="text-center p-4 bg-slate-800 rounded-lg">
<div class="text-cyan-400 font-semibold mb-1">Tailwind CSS</div>
<div class="text-slate-500 text-xs">样式框架</div>
</div>
<div class="text-center p-4 bg-slate-800 rounded-lg">
<div class="text-cyan-400 font-semibold mb-1">SQLite</div>
<div class="text-slate-500 text-xs">数据持久化</div>
</div>
</div>
</div>
</div>
</div>
<!-- Footer -->
<div class="text-center text-slate-500 text-sm mt-8">
<p>OpsXShell v0.3.0 | 专业级 SSH/SFTP 客户端</p>
</div>
</div>
<script>
function showView(view) {
// Hide all views
const views = ['terminal', 'sftp', 'portforward', 'features'];
views.forEach(v => {
document.getElementById('view-' + v).classList.add('hidden');
});
// Reset all tab styles
views.forEach(tab => {
const el = document.getElementById('tab-' + tab);
if (el) {
el.classList.remove('bg-cyan-600', 'text-white');
el.classList.add('bg-slate-800', 'text-slate-300');
}
});
// Show selected view
document.getElementById('view-' + view).classList.remove('hidden');
document.getElementById('tab-' + view).classList.remove('bg-slate-800', 'text-slate-300');
document.getElementById('tab-' + view).classList.add('bg-cyan-600', 'text-white');
}
</script>
</body>
</html>