89 lines
2.9 KiB
Markdown
89 lines
2.9 KiB
Markdown
|
|
# 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 (如有后端改动)
|