- 本地端口转发隧道管理(密码/私钥认证,自动重连,随应用启动) - 主机与隧道可视化配置,DPAPI 加密存储机密,known_hosts 校验 - 自定义无边框窗口,深色界面,托盘驻留(最小化/关闭到托盘) - 内置本地测试 SSH 服务端与端到端自测脚本
118 lines
5.4 KiB
HTML
118 lines
5.4 KiB
HTML
<!doctype html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>SSH 隧道管理器</title>
|
|
<link rel="stylesheet" href="style.css">
|
|
</head>
|
|
<body>
|
|
|
|
<header id="titlebar" class="titlebar">
|
|
<div class="drag-zone pywebview-drag-region" id="dragZone">
|
|
<span class="logo"><img src="logo.svg" alt=""></span>
|
|
<span class="title">SSH 隧道管理器</span>
|
|
</div>
|
|
<div class="win-controls">
|
|
<button class="wbtn" id="btnMin" title="最小化">
|
|
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M5 12h14"/></svg>
|
|
</button>
|
|
<button class="wbtn" id="btnMax" title="最大化 / 还原">
|
|
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="5" y="5" width="14" height="14" rx="2"/></svg>
|
|
</button>
|
|
<button class="wbtn close" id="btnClose" title="关闭">
|
|
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M6 6l12 12M18 6L6 18"/></svg>
|
|
</button>
|
|
</div>
|
|
</header>
|
|
|
|
<div id="app">
|
|
<nav id="nav">
|
|
<button class="nav-item on" data-view="tunnels">
|
|
<svg class="ic" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><circle cx="12" cy="12" r="3.2"/><path d="M3 12h5.6M15.4 12H21"/></svg>
|
|
隧道
|
|
<span class="nav-badge" id="badgeTunnels"></span>
|
|
</button>
|
|
<button class="nav-item" data-view="hosts">
|
|
<svg class="ic" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><rect x="3" y="4" width="18" height="7" rx="2"/><rect x="3" y="13" width="18" height="7" rx="2"/><path d="M7 7.5h.01M7 16.5h.01"/></svg>
|
|
主机
|
|
<span class="nav-badge" id="badgeHosts"></span>
|
|
</button>
|
|
<button class="nav-item" data-view="logs">
|
|
<svg class="ic" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z"/><path d="M14 3v5h5"/><path d="M9.5 13h5M9.5 17h3"/></svg>
|
|
日志
|
|
</button>
|
|
<div class="nav-foot">
|
|
<div class="conn-summary" id="connSummary">
|
|
<span class="dot" id="connDot"></span>
|
|
<span id="connText">没有运行中的隧道</span>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<main id="main">
|
|
<section class="view on" id="view-tunnels">
|
|
<header class="view-head">
|
|
<h1>隧道</h1>
|
|
<span class="count" id="tunnelCount"></span>
|
|
<span class="spacer"></span>
|
|
<button class="btn primary" id="btnNewTunnel">
|
|
<svg class="ic" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M12 5v14M5 12h14"/></svg>
|
|
新建隧道
|
|
</button>
|
|
</header>
|
|
<div class="card-grid" id="tunnelGrid"></div>
|
|
<div class="empty" id="tunnelsEmpty" style="display:none">
|
|
<div class="glyph">
|
|
<svg width="38" height="38" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"><circle cx="12" cy="12" r="3.4"/><path d="M2.5 12h4.2M17.3 12h4.2"/></svg>
|
|
</div>
|
|
<h2>还没有隧道</h2>
|
|
<p>把远程主机上只对本机开放的服务,映射到你本机的一个端口</p>
|
|
<button class="btn primary" id="btnEmptyNewTunnel">新建第一条隧道</button>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="view" id="view-hosts">
|
|
<header class="view-head">
|
|
<h1>主机</h1>
|
|
<span class="count" id="hostCount"></span>
|
|
<span class="spacer"></span>
|
|
<button class="btn" id="btnNewHost">
|
|
<svg class="ic" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M12 5v14M5 12h14"/></svg>
|
|
新建主机
|
|
</button>
|
|
</header>
|
|
<div class="host-list" id="hostList"></div>
|
|
<div class="empty" id="hostsEmpty" style="display:none">
|
|
<div class="glyph">
|
|
<svg width="38" height="38" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"><rect x="3" y="4" width="18" height="7" rx="2"/><rect x="3" y="13" width="18" height="7" rx="2"/><path d="M7 7.5h.01M7 16.5h.01"/></svg>
|
|
</div>
|
|
<h2>还没有主机</h2>
|
|
<p>添加一台 SSH 主机后,就可以基于它建立端口隧道</p>
|
|
<button class="btn primary" id="btnEmptyNewHost">添加主机</button>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="view" id="view-logs">
|
|
<header class="view-head">
|
|
<h1>日志</h1>
|
|
<span class="count" id="logCount"></span>
|
|
<span class="spacer"></span>
|
|
<label class="switch-row" style="padding:0">
|
|
<span class="sw-title" style="font-size:12px;color:var(--dim)">自动滚动</span>
|
|
<input type="checkbox" class="switch" id="autoScroll" checked>
|
|
</label>
|
|
<button class="btn subtle sm" id="btnClearLogs">清空显示</button>
|
|
</header>
|
|
<div class="log-feed" id="logFeed"></div>
|
|
</section>
|
|
</main>
|
|
</div>
|
|
|
|
<div id="modalRoot"></div>
|
|
<div id="toastRoot"></div>
|
|
|
|
<script src="app.js"></script>
|
|
</body>
|
|
</html>
|