feat: 终端页面 11 项全覆盖迭代 — 多标签/快速命令/字体/历史/重连/右键等
11 项改进: - 多标签会话 (切换/关闭/新建,每标签独立 xterm+WS) - 快速命令栏 (内置5条 + 自定义,localStorage持久化) - 字体大小调节 (A−/A+按钮 + Ctrl+/-) - Ctrl+L 清屏 - 命令历史持久化 (200条 FIFO localStorage) - 右键菜单 (复制/粘贴/清屏/全选) - 断开自动重连 (指数退避 + 倒计时) - 连接信息栏 (时长 + PING RTT) - 终端路径显示 (OSC title + onTitleChange) - 滚动缓冲区调节 (1K/5K/10K/50K) - 快速搜索服务器 后端: PING/PONG + PROMPT_COMMAND 注入 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
# 2026-05-30 终端页面全覆盖迭代
|
||||
|
||||
## 变更摘要
|
||||
terminal.html 全面重构,新增 11 项运维效率特性:
|
||||
|
||||
1. **多标签会话**: 浏览器内多标签管理,每标签独立 xterm + WebSocket,支持新建/切换/关闭,最多 10 标签。恢复时自动重建上次会话
|
||||
2. **快速命令栏**: 右侧面板内置 5 条命令 + 自定义命令(名称+内容),localStorage 持久化。点击发送到终端。弹窗编辑/删除
|
||||
3. **字体调节**: 工具栏 A−/A+ 按钮 + Ctrl+/- 快捷键,范围 10-24,localStorage 持久化
|
||||
4. **Ctrl+L 清屏**: 发送 clear\r + term.clear() 双重保障
|
||||
5. **命令历史持久化**: sendCmd 后存 localStorage(最多 200 条),刷新恢复,ArrowUp/Down 浏览
|
||||
6. **右键菜单**: 自定义右键菜单(复制/粘贴/清屏/全选)
|
||||
7. **断开自动重连**: WebSocket 异常断开指数退避重连(1s→2s→4s→max30s),倒计时显示。手动断开不重连
|
||||
8. **连接信息栏**: 工具栏显示服务器名 + 在线状态 + 连接时长(HH:MM:SS) + PING RTT
|
||||
9. **终端标题路径**: 后端注入 PROMPT_COMMAND(OSC title),前端 onTitleChange 捕获显示
|
||||
10. **滚动缓冲区调节**: 下拉选择器 1K/5K/10K/50K 行,xterm 5.x 热改
|
||||
11. **快速切换服务器**: 右侧面板搜索框实时过滤
|
||||
|
||||
## 动机
|
||||
terminal.html 仅具备基础 WebSSH,缺乏频繁运维所需的效率特性。用户一次连接内需切换多台服务器、快速执行常用命令、持久化历史等。
|
||||
|
||||
## 涉及文件
|
||||
|
||||
### 后端
|
||||
- `server/api/webssh.py` — 轻量改动
|
||||
- 新增 `MSG_PING`/`MSG_PONG` 消息类型
|
||||
- shell 创建后注入 `PROMPT_COMMAND`(OSC title escape)用于路径跟踪
|
||||
- PING handler: 收到 PING 立即回复 PONG(RTT 测量)
|
||||
|
||||
### 前端
|
||||
- `web/app/terminal.html` — 全面重构(~500行新增)
|
||||
- 多标签架构: sessions[] 数组 + 动态 term div
|
||||
- localStorage: 字体/回滚/历史/命令/标签 5 个键
|
||||
- 全新 UI: TabBar + 工具栏(字体/回滚/全屏) + 右侧面板(搜索+快速命令)
|
||||
- ContextMenu: 浮层右键菜单
|
||||
- AutoReconnect: 指数退避定时器
|
||||
|
||||
## 安全影响
|
||||
- PING/PONG: 无关安全的回声确认
|
||||
- PROMPT_COMMAND: 后端注入固定字符串,不走用户输入
|
||||
- 快速命令: 已有 WebSocket DATA 通道,无新攻击面
|
||||
- 右键菜单: 纯前端 UI,无后端交互
|
||||
- 多标签: 每标签独立 WebSSH token 认证,不共享凭据
|
||||
|
||||
## 需要迁移/重启
|
||||
- 是:后端 Python 需重启
|
||||
- 否:无数据库迁移
|
||||
|
||||
## 验证方式
|
||||
1. 多标签: 新建标签 → 切换 → 关闭 → 每标签独立 WS
|
||||
2. 快速命令: 点击 → 终端执行
|
||||
3. 字体: Ctrl+/− 调节,刷新保留
|
||||
4. Ctrl+L: 清屏 + sterm clear
|
||||
5. 历史: ArrowUp/Down,刷新保留
|
||||
6. 右键: 复制/粘贴/清屏/全选
|
||||
7. 重连: 异常断开 → 倒计时 → 自动重连
|
||||
8. 连接信息: 时长 + PING 显示
|
||||
9. 路径: cd 后工具栏更新路径
|
||||
10. 回滚: 下拉切换生效
|
||||
|
||||
## 进度条
|
||||
☑实现 ☑WSL验证 ☐审计8步 ☑部署 ☑健康检查 ☑浏览器验证 ☑changelog
|
||||
@@ -0,0 +1,88 @@
|
||||
# 2026-05-30 终端页面全覆盖迭代 — 技术文档
|
||||
|
||||
## 涉及文件
|
||||
|
||||
| 文件 | 改动 | 功能 |
|
||||
|------|------|------|
|
||||
| `web/app/terminal.html` | 全面重构 | 全部 11 项前端 |
|
||||
| `server/api/webssh.py` | 轻量 | PING/PONG + PROMPT_COMMAND |
|
||||
|
||||
## 实现步骤(11步)
|
||||
|
||||
### Step 1: 字体大小调节
|
||||
- 工具栏加 `−` `+` 按钮 + container `document.addEventListener('keydown')`
|
||||
- `term.options.fontSize = Math.max(10, Math.min(24, val))`
|
||||
- 存 localStorage `nexus_term_fontSize`
|
||||
- 页面加载时恢复
|
||||
|
||||
### Step 2: Ctrl+L 清屏
|
||||
- keydown 监听: `e.ctrlKey && e.key === 'l'` → `ws.send({type:'DATA',data:'clear\r'})` + `term.clear()`
|
||||
|
||||
### Step 3: 滚动缓冲区调节
|
||||
- 工具栏下拉: option 1000/5000/10000/50000
|
||||
- `term.options.scrollback = parseInt(val)` (xterm 5.x 支持热改)
|
||||
- 存 localStorage
|
||||
|
||||
### Step 4: 命令历史持久化
|
||||
- sendCmd 后 push + localStorage.setItem
|
||||
- 最多 200, FIFO (shift if >200)
|
||||
- 页面加载: cmdHistory = JSON.parse(localStorage.getItem(...))
|
||||
|
||||
### Step 5: 右键菜单
|
||||
- `term.element.addEventListener('contextmenu', ...)` 阻止默认
|
||||
- 自定义浮层 div absolute 定位
|
||||
- 四项: 复制/粘贴/清屏/全选
|
||||
- 点击外部消失
|
||||
|
||||
### Step 6: 快速切换服务器
|
||||
- `<input>` oninput 过滤 `#serverListPanel` 中的链接
|
||||
- 复用 push.html filterServerOptions 逻辑
|
||||
|
||||
### Step 7: 快速命令栏
|
||||
- 右侧面板底部: `<div id="quickCmdList">` + `+ 添加`
|
||||
- BUILTIN_CMDS 5 条 + localStorage 自定义
|
||||
- 点击 → ws.send DATA
|
||||
- 添加 → 弹窗(名称+命令) → localStorage
|
||||
- 编辑删除: 仅自定义命令
|
||||
|
||||
### Step 8: 断开自动重连
|
||||
- `ws.onclose` 检查 `!manualDisconnect` → 重连
|
||||
- 指数退避: attempt*1000, max 30000
|
||||
- overlay 显示 "X 秒后重连..."
|
||||
|
||||
### Step 9: 连接信息栏 (PING + 时长 + 路径)
|
||||
|
||||
**后端** (webssh.py):
|
||||
- PING handler: recv `{type:'PING',ts}` → send `{type:'PONG',ts}`
|
||||
- 初始注入: `export PROMPT_COMMAND='...'`
|
||||
- 注入时机: channel opened 后、shell created 前
|
||||
|
||||
**前端**:
|
||||
- uptime 计数器: ws.onopen setInterval 每秒更新
|
||||
- PING: 每 5s 发 `{type:'PING', ts: Date.now()}` → 收到 PONG 计算 RTT
|
||||
- 路径: `term.onTitleChange(title => { ... })`
|
||||
|
||||
### Step 10: 终端标题路径
|
||||
- 后端 shell 创建后发送 `export PROMPT_COMMAND='echo -ne "\033]0;${PWD}\a"'`
|
||||
- 前端 `term.onTitleChange` 捕获 OSC title → 更新工具栏显示
|
||||
|
||||
### Step 11: 会话多标签
|
||||
- 数据结构: `sessions = [{id,serverId,serverName,ws,term,fitAddon}]`
|
||||
- 标签栏: `<div id="tabBar">` 在 terminal 上方
|
||||
- 切换: hide/show terminal div + 更新 cmdInput 绑定
|
||||
- 新建: 弹出服务器选择器 → 创建新 session
|
||||
- 关闭: dispose term + close ws + splice
|
||||
- 右侧面板同步切换
|
||||
|
||||
## 依赖与配置
|
||||
|
||||
无新依赖。无数据库迁移。仅 localStorage。
|
||||
|
||||
## 测试要点
|
||||
|
||||
见验收标准 15 项。
|
||||
|
||||
## 回滚
|
||||
|
||||
1. git revert
|
||||
2. supervisorctl restart nexus (如有后端改动)
|
||||
@@ -0,0 +1,50 @@
|
||||
# 2026-05-30 终端页面全覆盖迭代 — 设计文档
|
||||
|
||||
## 背景与目标
|
||||
|
||||
terminal.html 已具备 WebSSH 基础(xterm.js + Koko 协议 WebSocket + 右侧服务器面板 + 底部命令栏),但缺乏 11 项运维效率特性。用户在频繁切换服务器的运维场景中效率低下。
|
||||
|
||||
11 项改进分三个优先级梯队:
|
||||
- **P0 即时提效**: 快速命令栏、字体调节、Ctrl+L清屏、滚动缓冲、命令历史持久化、右键菜单
|
||||
- **P1 操作增强**: 断开自动重连、连接信息栏(时长/当前路径)、快速搜索服务器
|
||||
- **P2 架构增强**: 会话多标签
|
||||
|
||||
## 方案(全选方案 A — 最简增量)
|
||||
|
||||
全部 11 项选最简实现:复用现有 WebSocket 通道 + localStorage + 已有 UI 组件。仅会话多标签和连接信息栏需要后端轻量改动。
|
||||
|
||||
## 接口/数据模型
|
||||
|
||||
### 后端改动 (webssh.py)
|
||||
- PING/PONG 机制: `{type:'PING', ts}` → `{type:'PONG', ts}`(测 RTT)
|
||||
- 初始 bashrc 注入: `export PROMPT_COMMAND='echo -ne "\033]0;${PWD}\a"'`(OSC title)
|
||||
|
||||
### localStorage 键
|
||||
| Key | 内容 |
|
||||
|-----|------|
|
||||
| `nexus_terminal_cmds` | `[{id, name, cmd}]` |
|
||||
| `nexus_term_fontSize` | `14` |
|
||||
| `nexus_term_history` | `["cmd1", "cmd2", ...]` 最多 200 |
|
||||
| `nexus_term_scrollback` | `1000` |
|
||||
| `nexus_term_tabs` | `[{serverId, serverName}]` 恢复标签 |
|
||||
|
||||
## 安全与性能约束
|
||||
|
||||
- 纯前端功能 9/11 项无安全影响
|
||||
- 快速命令栏: 命令文本走已有 WebSocket DATA 通道,不额外引入
|
||||
- 连接信息栏: WebSocket PING 每 5s 一次,单字符消息不占带宽
|
||||
- 多标签: 每标签独立 WS 连接,最多 10 标签(asyncssh 连接池已有上限)
|
||||
- 终端标题路径: PROMPT_COMMAND 由后端注入,不走用户输入
|
||||
|
||||
## 验收标准(15项)
|
||||
|
||||
1. 快速命令: 点击执行 / 添加编辑删除 / 刷新保留 / 内置不可删
|
||||
2. 字体: Ctrl+/- 或按钮调节,范围 10-24,刷新保留
|
||||
3. 清屏: Ctrl+L → clear + term.clear()
|
||||
4. 历史: sendCmd 存 localStorage,刷新恢复,ArrowUp/Down 可用
|
||||
5. 右键: 复制/粘贴/清屏/全选 四项
|
||||
6. 搜索: 实时过滤服务器列表
|
||||
7. 重连: 异常断开自动重连(1→2→4→8→max30s),手动断开不重连
|
||||
8. 连接信息: 工具栏显示连接时长(HH:MM:SS) + 当前目录路径
|
||||
9. 多标签: 切换/关闭/新建,每标签独立 WS+xterm,保持服务器列表
|
||||
10. 回滚: 下拉选择器 1K/5K/10K/50K 行
|
||||
@@ -29,6 +29,8 @@ MSG_DATA = "DATA"
|
||||
MSG_RESIZE = "RESIZE"
|
||||
MSG_CLOSE = "CLOSE"
|
||||
MSG_ERROR = "ERROR"
|
||||
MSG_PING = "PING"
|
||||
MSG_PONG = "PONG"
|
||||
|
||||
# Command logging configuration
|
||||
COMMAND_LOG_MAX_LENGTH = 2000
|
||||
@@ -216,6 +218,9 @@ async def terminal_ws(
|
||||
"server_id": server.id,
|
||||
})
|
||||
|
||||
# Inject CWD tracking via OSC title escape
|
||||
shell.stdin.write('export PROMPT_COMMAND=\'echo -ne "\\033]0;${PWD}\\a"\'\n')
|
||||
|
||||
# ── Bidirectional relay ──
|
||||
command_buffer = "" # Buffer for command logging
|
||||
|
||||
@@ -283,6 +288,9 @@ async def terminal_ws(
|
||||
rows = msg.get("rows", 24)
|
||||
shell.change_terminal_size(rows, cols)
|
||||
|
||||
elif msg_type == MSG_PING:
|
||||
await websocket.send_json({"type": MSG_PONG, "ts": msg.get("ts")})
|
||||
|
||||
elif msg_type == MSG_CLOSE:
|
||||
break
|
||||
|
||||
|
||||
+780
-284
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user