515 lines
32 KiB
HTML
515 lines
32 KiB
HTML
<!doctype html>
|
|
<html lang="zh-CN" data-theme="dark">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<script type="module" src="/src/language-bootstrap.ts"></script>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
|
<meta name="theme-color" content="#080b10" />
|
|
<meta
|
|
name="description"
|
|
content="安全的 Cloudflare Workers 原生 WebSSH 终端"
|
|
data-i18n-content-zh="安全的 Cloudflare Workers 原生 WebSSH 终端"
|
|
data-i18n-content-en="A secure, native Cloudflare Workers WebSSH terminal"
|
|
/>
|
|
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
|
|
<title>Workers WebSSH</title>
|
|
</head>
|
|
<body>
|
|
<div id="app" hidden>
|
|
<header class="topbar">
|
|
<div class="brand-group">
|
|
<button
|
|
id="panel-toggle"
|
|
class="icon-button"
|
|
type="button"
|
|
aria-label="打开连接面板"
|
|
data-i18n-aria-label-zh="打开连接面板"
|
|
data-i18n-aria-label-en="Open connection panel"
|
|
aria-controls="connection-panel"
|
|
aria-expanded="false"
|
|
>
|
|
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 6h16M4 12h16M4 18h16" /></svg>
|
|
</button>
|
|
<a
|
|
class="brand"
|
|
href="/"
|
|
aria-label="Workers WebSSH 首页"
|
|
data-i18n-aria-label-zh="Workers WebSSH 首页"
|
|
data-i18n-aria-label-en="Workers WebSSH home"
|
|
>
|
|
<span class="brand-mark" aria-hidden="true">>_</span>
|
|
<span><strong>Workers</strong> WebSSH</span>
|
|
</a>
|
|
</div>
|
|
|
|
<div class="topbar-actions">
|
|
<button id="language-toggle" class="icon-button" type="button" aria-label="切换到英文" title="切换到英文" data-language="zh-CN">
|
|
<span class="language-icon" aria-hidden="true"><span>中</span><span>E</span></span>
|
|
</button>
|
|
<button
|
|
id="theme-toggle"
|
|
class="icon-button"
|
|
type="button"
|
|
aria-label="切换颜色主题"
|
|
data-i18n-aria-label-zh="切换颜色主题"
|
|
data-i18n-aria-label-en="Toggle color theme"
|
|
>
|
|
<svg class="sun-icon" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="4" /><path d="M12 2v2M12 20v2M4.93 4.93l1.42 1.42M17.65 17.65l1.42 1.42M2 12h2M20 12h2M4.93 19.07l1.42-1.42M17.65 6.35l1.42-1.42" /></svg>
|
|
</button>
|
|
<a
|
|
class="icon-button"
|
|
href="https://github.com/cmliu/CF-Workers-WebSSH"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
aria-label="打开源代码仓库"
|
|
data-i18n-aria-label-zh="打开源代码仓库"
|
|
data-i18n-aria-label-en="Open source repository"
|
|
>
|
|
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 2a10 10 0 0 0-3.16 19.49c.5.09.68-.22.68-.48v-1.87c-2.78.6-3.37-1.18-3.37-1.18-.45-1.16-1.11-1.47-1.11-1.47-.91-.62.07-.61.07-.61 1 .07 1.53 1.03 1.53 1.03.9 1.53 2.35 1.09 2.92.83.09-.65.35-1.09.64-1.34-2.22-.25-4.55-1.11-4.55-4.94 0-1.09.39-1.98 1.03-2.68-.1-.25-.45-1.27.1-2.64 0 0 .84-.27 2.75 1.02A9.56 9.56 0 0 1 12 6.82c.85 0 1.71.11 2.51.34 1.91-1.29 2.75-1.02 2.75-1.02.55 1.37.2 2.39.1 2.64.64.7 1.03 1.59 1.03 2.68 0 3.84-2.34 4.68-4.57 4.93.36.31.68.92.68 1.86v2.76c0 .27.18.58.69.48A10 10 0 0 0 12 2Z" /></svg>
|
|
</a>
|
|
</div>
|
|
</header>
|
|
|
|
<div id="app-shell" class="app-shell">
|
|
<button
|
|
id="panel-scrim"
|
|
class="panel-scrim"
|
|
type="button"
|
|
aria-label="关闭连接面板"
|
|
data-i18n-aria-label-zh="关闭连接面板"
|
|
data-i18n-aria-label-en="Close connection panel"
|
|
hidden
|
|
></button>
|
|
<aside
|
|
id="connection-panel"
|
|
class="connection-panel"
|
|
aria-label="连接管理"
|
|
data-i18n-aria-label-zh="连接管理"
|
|
data-i18n-aria-label-en="Connection management"
|
|
>
|
|
<div class="panel-heading">
|
|
<div>
|
|
<p class="eyebrow" data-i18n-zh="连接管理" data-i18n-en="CONNECTIONS">连接管理</p>
|
|
<h1 data-i18n-zh="SSH 工作台" data-i18n-en="SSH workspace">SSH 工作台</h1>
|
|
</div>
|
|
</div>
|
|
|
|
<section class="profiles-section" aria-labelledby="profiles-title">
|
|
<div class="section-title-row">
|
|
<h2 id="profiles-title" data-i18n-zh="历史记录" data-i18n-en="History">历史记录</h2>
|
|
<span id="profile-count" class="count-badge">0</span>
|
|
</div>
|
|
<div id="profile-list" class="profile-list">
|
|
<p class="empty-list" data-i18n-zh="暂无历史记录" data-i18n-en="No connection history yet.">暂无历史记录</p>
|
|
</div>
|
|
</section>
|
|
|
|
<form id="connection-form" class="connection-form" autocomplete="off" novalidate>
|
|
<input id="profile-id" type="hidden" />
|
|
<div class="field-grid host-grid">
|
|
<label class="field">
|
|
<span data-i18n-zh="主机" data-i18n-en="Host">主机</span>
|
|
<input id="host" name="host" type="text" maxlength="253" placeholder="ssh.example.com" required spellcheck="false" />
|
|
</label>
|
|
<label class="field port-field">
|
|
<span data-i18n-zh="端口" data-i18n-en="Port">端口</span>
|
|
<input id="port" name="port" type="number" value="22" min="1" max="65535" required inputmode="numeric" />
|
|
</label>
|
|
</div>
|
|
|
|
<div class="field-grid single">
|
|
<label class="field">
|
|
<span data-i18n-zh="用户名" data-i18n-en="Username">用户名</span>
|
|
<input id="username" name="username" type="text" value="root" maxlength="128" required autocomplete="username" spellcheck="false" />
|
|
</label>
|
|
</div>
|
|
|
|
<fieldset class="auth-fieldset">
|
|
<legend data-i18n-zh="身份认证" data-i18n-en="Authentication">身份认证</legend>
|
|
<div
|
|
class="segmented-control"
|
|
role="radiogroup"
|
|
aria-label="身份认证方式"
|
|
data-i18n-aria-label-zh="身份认证方式"
|
|
data-i18n-aria-label-en="Authentication method"
|
|
>
|
|
<label><input type="radio" name="authMethod" value="password" checked /><span data-i18n-zh="密码" data-i18n-en="Password">密码</span></label>
|
|
<label><input type="radio" name="authMethod" value="publickey" /><span data-i18n-zh="SSH 密钥" data-i18n-en="SSH key">SSH 密钥</span></label>
|
|
</div>
|
|
|
|
<div id="password-field" class="field secret-field">
|
|
<label for="password">
|
|
<span data-i18n-zh="密码" data-i18n-en="Password">密码</span>
|
|
<small data-i18n-zh="连接成功后使用 AES-GCM 加密保存" data-i18n-en="Encrypted with AES-GCM after a successful connection">连接成功后使用 AES-GCM 加密保存</small>
|
|
</label>
|
|
<span class="input-action-wrap">
|
|
<input id="password" name="password" type="password" maxlength="4096" autocomplete="current-password" />
|
|
<button id="reveal-password" class="input-action" type="button" aria-label="显示密码" aria-pressed="false">
|
|
<svg class="reveal-icon reveal-icon-eye" viewBox="0 0 24 24" aria-hidden="true">
|
|
<path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7Z" />
|
|
<circle cx="12" cy="12" r="3" />
|
|
</svg>
|
|
<svg class="reveal-icon reveal-icon-eye-off" viewBox="0 0 24 24" aria-hidden="true">
|
|
<path d="M9.88 9.88a3 3 0 1 0 4.24 4.24" />
|
|
<path d="M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68" />
|
|
<path d="M6.61 6.61A13.53 13.53 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61" />
|
|
<line x1="2" x2="22" y1="2" y2="22" />
|
|
</svg>
|
|
</button>
|
|
</span>
|
|
</div>
|
|
|
|
<div id="key-field" class="key-field" hidden>
|
|
<label class="field">
|
|
<span>
|
|
<span data-i18n-zh="私钥" data-i18n-en="Private key">私钥</span>
|
|
<small data-i18n-zh="未加密 OpenSSH" data-i18n-en="unencrypted OpenSSH">未加密 OpenSSH</small>
|
|
</span>
|
|
<textarea id="private-key" name="privateKey" rows="5" maxlength="65536" placeholder="-----BEGIN OPENSSH PRIVATE KEY-----"></textarea>
|
|
</label>
|
|
<label class="file-picker">
|
|
<input id="key-file" type="file" accept=".pem,.key,.openssh,text/plain" />
|
|
<span data-i18n-zh="选择密钥文件" data-i18n-en="Choose key file">选择密钥文件</span>
|
|
<small id="key-file-name">未选择文件</small>
|
|
</label>
|
|
</div>
|
|
</fieldset>
|
|
|
|
<details class="advanced-options">
|
|
<summary data-i18n-zh="高级选项" data-i18n-en="Advanced options">高级选项</summary>
|
|
<div class="advanced-body">
|
|
<label class="field">
|
|
<span data-i18n-zh="初始命令" data-i18n-en="Initial command">初始命令</span>
|
|
<input id="initial-command" name="initialCommand" type="text" maxlength="4096" placeholder="tmux attach || tmux" spellcheck="false" />
|
|
</label>
|
|
<div class="field-grid two">
|
|
<label class="field">
|
|
<span data-i18n-zh="终端类型" data-i18n-en="Terminal">终端类型</span>
|
|
<select id="term-type" name="termType">
|
|
<option value="xterm-256color">xterm-256color</option>
|
|
<option value="xterm">xterm</option>
|
|
<option value="screen-256color">screen-256color</option>
|
|
</select>
|
|
</label>
|
|
<label class="field">
|
|
<span data-i18n-zh="字符编码" data-i18n-en="Encoding">字符编码</span>
|
|
<select id="encoding" name="encoding">
|
|
<option value="utf-8">UTF-8</option>
|
|
<option value="gb18030">GB18030</option>
|
|
<option value="big5">Big5</option>
|
|
</select>
|
|
</label>
|
|
</div>
|
|
<label class="field">
|
|
<span>
|
|
<span data-i18n-zh="预期主机指纹" data-i18n-en="Expected host fingerprint">预期主机指纹</span>
|
|
<small>SHA-256</small>
|
|
</span>
|
|
<input
|
|
id="fingerprint"
|
|
name="fingerprint"
|
|
type="text"
|
|
maxlength="128"
|
|
placeholder="首次使用后自动保存"
|
|
data-i18n-placeholder-zh="首次使用后自动保存"
|
|
data-i18n-placeholder-en="Saved after first use"
|
|
spellcheck="false"
|
|
/>
|
|
</label>
|
|
</div>
|
|
</details>
|
|
|
|
<div id="form-error" class="form-error" role="alert" hidden></div>
|
|
<div class="form-actions">
|
|
<button id="connect-button" class="primary-button" type="submit">
|
|
<span class="button-icon" aria-hidden="true">>_</span>
|
|
<span>连接</span>
|
|
</button>
|
|
<button
|
|
id="share-link"
|
|
class="icon-button bordered"
|
|
type="button"
|
|
aria-label="复制连接链接(含密码)"
|
|
data-i18n-aria-label-zh="复制连接链接(含密码)"
|
|
data-i18n-aria-label-en="Copy connection link (includes password)"
|
|
>
|
|
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" /></svg>
|
|
</button>
|
|
</div>
|
|
</form>
|
|
|
|
<p
|
|
class="privacy-note"
|
|
data-i18n-zh="连接成功后会自动加入此浏览器的历史记录;密码使用当前浏览器配置的密钥加密,私钥不会保存。密钥缺失或不匹配时,密码将留空。"
|
|
data-i18n-en="Successful connections are added to this browser's history automatically; passwords are encrypted with a key held by this browser profile, while private keys are not saved. The password remains blank if the key is missing or does not match."
|
|
>连接成功后会自动加入此浏览器的历史记录;密码使用当前浏览器配置的密钥加密,私钥不会保存。密钥缺失或不匹配时,密码将留空。</p>
|
|
</aside>
|
|
|
|
<main class="workspace">
|
|
<section id="terminal-card" class="terminal-card">
|
|
<div class="terminal-pane">
|
|
<div class="terminal-toolbar">
|
|
<div
|
|
class="session-target"
|
|
aria-label="实时连接状态"
|
|
data-i18n-aria-label-zh="实时连接状态"
|
|
data-i18n-aria-label-en="Live connection status"
|
|
>
|
|
<span class="live-orb idle" id="live-orb" role="status" aria-live="polite" aria-atomic="true" title="离线">
|
|
<span id="live-orb-label" class="sr-only">离线</span>
|
|
</span>
|
|
<div>
|
|
<strong id="session-title">无活动会话</strong>
|
|
<span id="session-subtitle">选择目标并连接</span>
|
|
</div>
|
|
</div>
|
|
<div class="resource-metrics" aria-label="系统资源" data-i18n-aria-label-zh="系统资源" data-i18n-aria-label-en="System resources">
|
|
<div class="resource-metric resource-cpu">
|
|
<div class="resource-metric-line">
|
|
<span data-i18n-zh="CPU" data-i18n-en="CPU">CPU</span>
|
|
<strong id="resource-cpu-value" class="resource-percentage">--</strong>
|
|
<strong id="resource-cpu-load" class="resource-detail">-- / -- / --</strong>
|
|
</div>
|
|
<progress id="resource-cpu-progress" max="100" value="0" aria-label="CPU 使用率" data-i18n-aria-label-zh="CPU 使用率" data-i18n-aria-label-en="CPU usage"></progress>
|
|
</div>
|
|
<div class="resource-metric resource-memory">
|
|
<div class="resource-metric-line">
|
|
<span data-i18n-zh="内存" data-i18n-en="MEM">内存</span>
|
|
<strong id="resource-memory-value" class="resource-percentage">--</strong>
|
|
<strong id="resource-memory-amount" class="resource-detail">--/--</strong>
|
|
</div>
|
|
<progress id="resource-memory-progress" max="100" value="0" aria-label="内存使用率" data-i18n-aria-label-zh="内存使用率" data-i18n-aria-label-en="Memory usage"></progress>
|
|
</div>
|
|
<div class="resource-metric resource-swap">
|
|
<div class="resource-metric-line">
|
|
<span data-i18n-zh="Swap" data-i18n-en="SWAP">Swap</span>
|
|
<strong id="resource-swap-value" class="resource-percentage">--</strong>
|
|
<strong id="resource-swap-amount" class="resource-detail">--/--</strong>
|
|
</div>
|
|
<progress id="resource-swap-progress" max="100" value="0" aria-label="Swap 使用率" data-i18n-aria-label-zh="Swap 使用率" data-i18n-aria-label-en="Swap usage"></progress>
|
|
</div>
|
|
</div>
|
|
<div class="session-metrics">
|
|
<div><span data-i18n-zh="延迟" data-i18n-en="RTT">延迟</span><strong id="metric-rtt">--</strong></div>
|
|
<div><span data-i18n-zh="时长" data-i18n-en="UPTIME">时长</span><strong id="metric-uptime">00:00</strong></div>
|
|
<div><span data-i18n-zh="主机密钥" data-i18n-en="HOST KEY">主机密钥</span><strong id="metric-host-key">--</strong></div>
|
|
</div>
|
|
<div class="terminal-actions">
|
|
<button id="clear-terminal" class="toolbar-button" type="button" aria-label="清屏" data-i18n-aria-label-zh="清屏" data-i18n-aria-label-en="Clear">
|
|
<svg class="toolbar-button-icon" viewBox="0 0 24 24" aria-hidden="true">
|
|
<path d="M3 6h18" />
|
|
<path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" />
|
|
<line x1="10" x2="10" y1="11" y2="17" />
|
|
<line x1="14" x2="14" y1="11" y2="17" />
|
|
</svg>
|
|
<span class="button-label" data-i18n-zh="清屏" data-i18n-en="Clear">清屏</span>
|
|
</button>
|
|
<button id="fullscreen-terminal" class="toolbar-button" type="button" aria-label="全屏" data-i18n-aria-label-zh="全屏" data-i18n-aria-label-en="Fullscreen">
|
|
<svg class="toolbar-button-icon" viewBox="0 0 24 24" aria-hidden="true">
|
|
<path d="M8 3H5a2 2 0 0 0-2 2v3" />
|
|
<path d="M21 8V5a2 2 0 0 0-2-2h-3" />
|
|
<path d="M3 16v3a2 2 0 0 0 2 2h3" />
|
|
<path d="M16 21h3a2 2 0 0 0 2-2v-3" />
|
|
</svg>
|
|
<span class="button-label" data-i18n-zh="全屏" data-i18n-en="Fullscreen">全屏</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div id="terminal-stage" class="terminal-stage">
|
|
<div
|
|
id="terminal"
|
|
role="application"
|
|
aria-label="SSH 终端"
|
|
data-i18n-aria-label-zh="SSH 终端"
|
|
data-i18n-aria-label-en="SSH terminal"
|
|
></div>
|
|
<div id="terminal-empty" class="terminal-empty">
|
|
<div class="empty-glyph" aria-hidden="true">>_</div>
|
|
<h2 data-i18n-zh="终端已就绪" data-i18n-en="Your terminal is ready">终端已就绪</h2>
|
|
<p
|
|
data-i18n-zh="从连接面板建立 SSH 连接,开始加密的边缘会话。"
|
|
data-i18n-en="Open an SSH connection from the panel to start an encrypted edge session."
|
|
>从连接面板建立 SSH 连接,开始加密的边缘会话。</p>
|
|
<button id="empty-connect" class="small-button" type="button" data-i18n-zh="配置连接" data-i18n-en="Configure connection">配置连接</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="workspace-dock">
|
|
<div class="event-bar">
|
|
<span id="event-message">Worker 运行时待命</span>
|
|
<div class="dock-tabs" role="tablist" aria-label="工作区面板" data-i18n-aria-label-zh="工作区面板" data-i18n-aria-label-en="Workspace panels">
|
|
<button
|
|
id="file-manager-tab"
|
|
class="dock-tab"
|
|
type="button"
|
|
role="tab"
|
|
aria-selected="false"
|
|
aria-controls="file-manager-panel"
|
|
aria-expanded="false"
|
|
tabindex="0"
|
|
aria-label="文件管理"
|
|
data-i18n-aria-label-zh="文件管理"
|
|
data-i18n-aria-label-en="Files"
|
|
>
|
|
<svg class="dock-tab-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M3.5 7.5h6l2-2h9a1.5 1.5 0 0 1 1.5 1.5v11a1.5 1.5 0 0 1-1.5 1.5h-17A1.5 1.5 0 0 1 2 18V9a1.5 1.5 0 0 1 1.5-1.5Z" /></svg>
|
|
<span class="button-label" data-i18n-zh="文件管理" data-i18n-en="Files">文件管理</span>
|
|
</button>
|
|
<button
|
|
id="process-manager-tab"
|
|
class="dock-tab"
|
|
type="button"
|
|
role="tab"
|
|
aria-selected="false"
|
|
aria-controls="process-manager-panel"
|
|
aria-expanded="false"
|
|
tabindex="-1"
|
|
aria-label="进程管理"
|
|
data-i18n-aria-label-zh="进程管理"
|
|
data-i18n-aria-label-en="Processes"
|
|
>
|
|
<svg class="dock-tab-icon" viewBox="0 0 24 24" aria-hidden="true"><rect x="3" y="4" width="18" height="16" rx="2" /><path d="m7 9 2.5 2.5L7 14M12.5 14H17" /></svg>
|
|
<span class="button-label" data-i18n-zh="进程管理" data-i18n-en="Processes">进程管理</span>
|
|
</button>
|
|
<button
|
|
id="event-toggle"
|
|
class="dock-tab"
|
|
type="button"
|
|
role="tab"
|
|
aria-selected="false"
|
|
aria-controls="event-log"
|
|
aria-expanded="false"
|
|
tabindex="-1"
|
|
aria-label="会话日志"
|
|
data-i18n-aria-label-zh="会话日志"
|
|
data-i18n-aria-label-en="Session log"
|
|
>
|
|
<svg class="dock-tab-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M6 2.5h9l4 4V21H6a2 2 0 0 1-2-2V4.5a2 2 0 0 1 2-2Z" /><path d="M15 2.5V7h4M8 11h7M8 15h7" /></svg>
|
|
<span class="button-label" data-i18n-zh="会话日志" data-i18n-en="Session log">会话日志</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<section id="file-manager-panel" class="file-manager" role="tabpanel" aria-labelledby="file-manager-tab" tabindex="0" hidden>
|
|
<div class="file-toolbar">
|
|
<label class="file-path-field" for="file-manager-path">
|
|
<span class="sr-only" data-i18n-zh="当前路径" data-i18n-en="Current path">当前路径</span>
|
|
<input id="file-manager-path" type="text" value="/" autocomplete="off" spellcheck="false" aria-label="当前路径" data-i18n-aria-label-zh="当前路径" data-i18n-aria-label-en="Current path" />
|
|
</label>
|
|
<div class="file-actions" aria-label="文件操作" data-i18n-aria-label-zh="文件操作" data-i18n-aria-label-en="File actions">
|
|
<button id="file-back" class="file-action" type="button" disabled data-i18n-aria-label-zh="返回" data-i18n-aria-label-en="Back" aria-label="返回" title="返回" data-i18n-title-zh="返回" data-i18n-title-en="Back">←</button>
|
|
<button id="file-up" class="file-action" type="button" disabled data-i18n-aria-label-zh="上一级" data-i18n-aria-label-en="Up one level" aria-label="上一级" title="上一级" data-i18n-title-zh="上一级" data-i18n-title-en="Up one level">↑</button>
|
|
<button id="file-home" class="file-action" type="button" disabled data-i18n-aria-label-zh="主目录" data-i18n-aria-label-en="Home" aria-label="主目录" title="主目录" data-i18n-title-zh="主目录" data-i18n-title-en="Home">⌂</button>
|
|
<button id="file-refresh" class="file-action" type="button" disabled data-i18n-aria-label-zh="刷新" data-i18n-aria-label-en="Refresh" aria-label="刷新" title="刷新" data-i18n-title-zh="刷新" data-i18n-title-en="Refresh">↻</button>
|
|
<span class="file-action-separator" aria-hidden="true"></span>
|
|
<button id="file-upload" class="file-action file-action-wide" type="button" disabled data-i18n-zh="上传" data-i18n-en="Upload">上传</button>
|
|
<button id="file-download" class="file-action file-action-wide" type="button" disabled data-i18n-zh="下载" data-i18n-en="Download">下载</button>
|
|
<button id="file-mkdir" class="file-action file-action-wide" type="button" disabled data-i18n-zh="新建" data-i18n-en="New folder">新建</button>
|
|
<button id="file-rename" class="file-action file-action-wide" type="button" disabled data-i18n-zh="重命名" data-i18n-en="Rename">重命名</button>
|
|
<button id="file-delete" class="file-action file-action-wide danger" type="button" disabled data-i18n-zh="删除" data-i18n-en="Delete">删除</button>
|
|
<input id="file-upload-input" class="sr-only" type="file" tabindex="-1" />
|
|
</div>
|
|
</div>
|
|
|
|
<div class="file-table-wrap">
|
|
<table class="file-table" aria-describedby="file-manager-status">
|
|
<thead>
|
|
<tr>
|
|
<th scope="col" data-i18n-zh="名称" data-i18n-en="Name">名称</th>
|
|
<th scope="col" data-column="size" data-i18n-zh="大小" data-i18n-en="Size">大小</th>
|
|
<th scope="col" data-column="type" data-i18n-zh="类型" data-i18n-en="Type">类型</th>
|
|
<th scope="col" data-column="mtime" data-i18n-zh="修改时间" data-i18n-en="Modified">修改时间</th>
|
|
<th scope="col" data-column="permissions" data-i18n-zh="权限" data-i18n-en="Permissions">权限</th>
|
|
<th scope="col" data-column="owner" data-i18n-zh="用户" data-i18n-en="Owner">用户</th>
|
|
<th scope="col" data-column="group" data-i18n-zh="组" data-i18n-en="Group">组</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="file-table-body"></tbody>
|
|
</table>
|
|
<div id="file-manager-loading" class="file-manager-state" role="status" hidden>
|
|
<span class="file-spinner" aria-hidden="true"></span>
|
|
<span data-i18n-zh="正在读取目录…" data-i18n-en="Loading directory…">正在读取目录…</span>
|
|
</div>
|
|
<div id="file-manager-empty" class="file-manager-state" hidden data-i18n-zh="此目录为空" data-i18n-en="This folder is empty">此目录为空</div>
|
|
<div id="file-manager-error" class="file-manager-state error" role="alert" hidden></div>
|
|
</div>
|
|
<div class="file-statusbar">
|
|
<span id="file-manager-status" role="status" aria-live="polite" data-i18n-zh="连接 SSH 后即可管理文件" data-i18n-en="Connect to SSH to manage files">连接 SSH 后即可管理文件</span>
|
|
<div id="file-manager-progress" class="file-progress" hidden>
|
|
<span id="file-manager-progress-label"></span>
|
|
<progress id="file-manager-progress-bar" max="100" value="0" aria-labelledby="file-manager-progress-label"></progress>
|
|
<button
|
|
id="file-manager-progress-cancel"
|
|
class="file-progress-cancel"
|
|
type="button"
|
|
data-i18n-zh="取消"
|
|
data-i18n-en="Cancel"
|
|
data-i18n-aria-label-zh="取消文件传输"
|
|
data-i18n-aria-label-en="Cancel file transfer"
|
|
aria-label="取消文件传输"
|
|
>取消</button>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<section id="process-manager-panel" class="process-manager" role="tabpanel" aria-labelledby="process-manager-tab" tabindex="0" hidden>
|
|
<div class="process-table-wrap">
|
|
<table class="process-table" aria-describedby="process-manager-status">
|
|
<thead>
|
|
<tr>
|
|
<th scope="col" aria-sort="none"><button class="process-sort" type="button" data-process-sort="pid" data-i18n-zh="PID" data-i18n-en="PID">PID</button></th>
|
|
<th scope="col" aria-sort="none"><button class="process-sort" type="button" data-process-sort="user" data-i18n-zh="用户" data-i18n-en="User">用户</button></th>
|
|
<th scope="col" aria-sort="none"><button class="process-sort" type="button" data-process-sort="memoryBytes" data-i18n-zh="内存" data-i18n-en="Memory">内存</button></th>
|
|
<th scope="col" aria-sort="none"><button class="process-sort" type="button" data-process-sort="memoryPercent" data-i18n-zh="MEM%" data-i18n-en="MEM%">MEM%</button></th>
|
|
<th scope="col" aria-sort="descending"><button class="process-sort" type="button" data-process-sort="cpuPercent" data-i18n-zh="CPU%" data-i18n-en="CPU%">CPU%</button></th>
|
|
<th scope="col" aria-sort="none"><button class="process-sort" type="button" data-process-sort="state" data-i18n-zh="状态" data-i18n-en="State">状态</button></th>
|
|
<th scope="col" aria-sort="none"><button class="process-sort" type="button" data-process-sort="time" data-i18n-zh="时间" data-i18n-en="Time">时间</button></th>
|
|
<th scope="col" aria-sort="none"><button class="process-sort" type="button" data-process-sort="command" data-i18n-zh="名称/命令行" data-i18n-en="Name / command">名称/命令行</button></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="process-table-body"></tbody>
|
|
</table>
|
|
<div id="process-manager-empty" class="process-manager-state" hidden data-i18n-zh="没有可显示的进程" data-i18n-en="No processes to display">没有可显示的进程</div>
|
|
<div id="process-manager-error" class="process-manager-state error" role="alert" hidden></div>
|
|
</div>
|
|
<div class="process-statusbar">
|
|
<span id="process-manager-status" role="status" aria-live="polite" data-i18n-zh="连接 SSH 后即可查看实时进程" data-i18n-en="Connect to SSH to view live processes">连接 SSH 后即可查看实时进程</span>
|
|
<span><span data-i18n-zh="最后更新" data-i18n-en="Last update">最后更新</span> <strong id="process-updated">--</strong></span>
|
|
</div>
|
|
</section>
|
|
<div id="event-log" class="event-log" role="tabpanel" aria-labelledby="event-toggle" tabindex="0" hidden aria-live="polite"></div>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
</div>
|
|
|
|
<div id="toast-region" class="toast-region" aria-live="polite"></div>
|
|
|
|
<dialog id="host-key-dialog" class="host-key-dialog" aria-labelledby="host-key-title">
|
|
<form method="dialog">
|
|
<span id="host-key-icon" class="dialog-icon" aria-hidden="true">密钥</span>
|
|
<div>
|
|
<p id="host-key-eyebrow" class="eyebrow">主机身份</p>
|
|
<h2 id="host-key-title">信任此 SSH 主机?</h2>
|
|
<p id="host-key-description">服务器提供了尚未为此目标固定的密钥。继续前,请通过可信渠道核验。</p>
|
|
</div>
|
|
<dl>
|
|
<div><dt data-i18n-zh="目标" data-i18n-en="Target">目标</dt><dd id="host-key-target">--</dd></div>
|
|
<div><dt data-i18n-zh="密钥类型" data-i18n-en="Key type">密钥类型</dt><dd id="host-key-type">--</dd></div>
|
|
<div id="host-key-expected-row" hidden><dt data-i18n-zh="之前的指纹" data-i18n-en="Previous fingerprint">之前的指纹</dt><dd id="host-key-expected-fingerprint">--</dd></div>
|
|
<div><dt data-i18n-zh="SHA-256 指纹" data-i18n-en="SHA-256 fingerprint">SHA-256 指纹</dt><dd id="host-key-fingerprint">--</dd></div>
|
|
</dl>
|
|
<label class="trust-check">
|
|
<input id="remember-host-key" type="checkbox" checked />
|
|
<span id="remember-host-key-label">下次记住并验证此指纹</span>
|
|
</label>
|
|
<div class="dialog-actions">
|
|
<button id="reject-host-key" class="secondary-button" value="reject" type="submit" data-i18n-zh="取消连接" data-i18n-en="Cancel">取消连接</button>
|
|
<button id="accept-host-key" class="primary-button" value="accept" type="submit">信任并继续</button>
|
|
</div>
|
|
</form>
|
|
</dialog>
|
|
</div>
|
|
<script type="module" src="/src/main.ts"></script>
|
|
</body>
|
|
</html>
|