# WebSSH 终端命令输入栏

**日期**: 2026-05-26
**变更摘要**: 为 WebSSH 终端底部新增命令输入栏，避免直接在 xterm 中逐字符输入导致的显示错乱问题

## 动机

1. 用户直接在 xterm 终端中逐字符输入时，SSH echo 与 ANSI prompt 序列交错，导致显示错乱（如 "1111312312oot@mqtele:~#"）
2. 根因：逐字符发送 WebSocket 消息时，`read(4096)` 返回的数据可能混合 echo 和 prompt 的 ANSI 片段，时序依赖导致渲染错乱
3. 命令输入栏一次性发送完整命令 + `\r`，完全避免逐字符 echo 交错问题
4. 同时提供 Ctrl+C/D 和 Tab 快捷按钮，方便运维操作

## 变更内容

### web/app/terminal.html — 3处修改

**修改1: CSS 布局调整**
- 旧：`#terminalWrap{height:calc(100vh - 48px)}` — 固定高度，终端占满
- 新：`#terminalWrap{flex:1;min-height:0}` — flex 弹性布局，为底部命令栏留空间
- 全屏样式简化：移除 `height:100vh`，flex:1 + fixed inset 自动撑满

**修改2: HTML 结构 — 新增命令输入栏**
- terminalWrap 改为 `flex flex-col` 容器
- `#terminal` 加 `flex-1 min-h-0` 占据剩余空间
- 新增 `#cmdBar` 底部栏，包含：
  - 命令提示符 `❯`
  - `<input id="cmdInput">` — 命令输入框，monospace 字体
  - `发送` 按钮 — 调用 `sendCmd()`
  - `⌃C` / `⌃D` / `Tab` 快捷按钮 — 分别调用 `sendCtrl()` / `sendKey()`

**修改3: JavaScript — 命令输入逻辑**
- `cmdHistory` / `cmdHistoryIdx` — 命令历史记录 + 上下箭头导航
- `cmdInput keydown` — Enter 发送、ArrowUp/Down 浏览历史
- `sendCmd()` — 发送完整命令 + `\r`，记入历史，清空输入框
- `sendCtrl(key)` — 发送控制字符（charCode - 96）
- `sendKey(key)` — 发送原始按键（如 Tab）

## 技术分析

逐字符输入问题：
```
用户输入 'w' → WS send {type:DATA, data:"w"}
  → SSH echo "\033[...w" → read(4096) 可能返回 "w\033[...root@..."
  → xterm 渲染时 ANSI 序列与 echo 字符交错 → 显示错乱
```

命令输入栏解决方案：
```
用户输入 "whoami" → 点发送 → WS send {type:DATA, data:"whoami\r"}
  → SSH 完整回显 "whoami\r\nroot\r\n" → 一次返回 → 正常渲染
```

## 涉及文件

- `web/app/terminal.html` — 终端页面（CSS + HTML + JS 共3处修改）

## 是否需迁移/重启

- 不需重启后端（纯前端改动）
- 不需 DB 迁移

## 验证方式

1. 打开 terminal.html → 底部显示命令输入栏（❯ 提示符 + 输入框 + 发送按钮）
2. 输入 `whoami` → 点发送 → 终端显示 `root`（无显示错乱）
3. 输入 `ls` → Enter 键发送 → 正常显示文件列表
4. ArrowUp → 回显上一条命令 `ls`，ArrowDown → 清空
5. 点击 `⌃C` 按钮 → 中断当前命令
6. 点击 `Tab` 按钮 → 触发自动补全
7. 终端 xterm 区域自动占满输入栏上方空间
8. 全屏模式下输入栏仍然可见
