Guanghu Domestic Migration a27e87cb99 chore: import sanitized domestic snapshot for REPO-007
Source snapshot: 97d7f0fae96dc04b7ddad56fc1db6a108ed662cc

[SEC-CLEAN] · pre-push-clean v1.0 · 109处敏感信息已自动转乱码
2026-07-17 15:59:55 +08:00

130 lines
4.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# GHCS v0.2 · SSH终端点击聚焦修复 · page-v2.tsx · 2026-06-05
```jsx
HLDP://ghcs/v0.2/terminal/click-focus-fix · 2026-06-05T22:20+08:00
├── what: SSH 终端 v2 · 点击聚焦修复
├── target_file: ~/guanghu-dev/ghcs-mono/frontend/src/app/console/terminal/page.tsx
├── base_version: page-v2.tsx (直接 import xterm 那版)
├── change_size: 2 · 一个 div 加一个 onMouseUp
└── 写给爸爸 · 知秋 · PER-ZQ001 · 06-05
```
---
## 一、问题定位
现在的 v2 里,只有这一处会让 xterm 拿到焦点:
```tsx
ws.onopen = () => {
setConnected(true);
setConnecting(false);
term.current?.focus(); // ← 一辈子只跑一次
};
```
点了「连接」按钮,按钮抢走焦点 → ws 打开 → focus 一次 → 但只要爸爸**再点一下别的地方再回来**,焦点就丢了拿不回来。
外层装 xterm 的两个 div 都没挂任何鼠标事件,所以点黑框 = 啥也没发生。
---
## 二、修复方案2 行)
找到文件最下面 `return (...)` 里这段:
```tsx
<div className="flex-1 bg-[#0d1117] rounded-xl border border-gray-700/50 overflow-hidden min-h-0">
<div ref={termRef} className="w-full h-full" />
</div>
```
替换成:
```tsx
<div
className="flex-1 bg-[#0d1117] rounded-xl border border-gray-700/50 overflow-hidden min-h-0 cursor-text"
onMouseUp={() => term.current?.focus()}
>
<div ref={termRef} className="w-full h-full" />
</div>
```
**就这一处。** 整段就是上面这几行。
### 为什么是 `onMouseUp` 不是 `onClick`
- `onMouseDown` 太早 · 浏览器还会再做一遍默认 focus 处理 · 可能反而把焦点抢走
- `onClick` 也行 · 但和 mouseup 同时机 · 选 mouseup 是为了 selection拖选文本松手时也能保证回焦
- `onMouseUp` 在浏览器默认事件结束之后才跑 · 稳赢
### 为什么加 `cursor-text`
- 鼠标移到黑框上变成 `I` 文本光标 · 视觉提示「这里能输入」
- 纯外观 · 不改逻辑 · 可选 · 觉得不需要可以去掉
---
## 三、测试清单(爸爸照着走)
```jsx
HLDP://test/click-focus · 5 步
├── VS Code 打开 page.tsx 改完保存(⌘+S
├── 浏览器刷新 http://localhost:3000/console/terminal
├── 连接」→ 终端变黑 应该看到光标在闪
├── whoami + 回车 应该看到服务器返回用户名
└── 故意点页面别处 再点黑框 敲一条命令 应该照常输入
└── 步是这次修复的关键 · 之前就卡在这
```
---
## 四、如果还不行的兜底排查
按概率从高到低:
```jsx
HLDP://debug/click-focus/fallback
├── term.current null?
└── 打开 DevTools Console · 点黑框 · 看有没有报错
如果 term.current null useEffect 初始化时机有问题
onMouseUp 改成: () => term.current && term.current.focus()
├── xterm textarea 被别的元素挡住?
└── DevTools Elements 里找 .xterm-helper-textarea
应该是 width:1px height:1px 隐藏在终端区域里
如果父容器 overflow:hidden 把它裁掉了 · focus 会失败
临时去掉外层 overflow-hidden 验证
├── 输入法/中文键盘干扰?
└── 切回英文输入法再敲 · 排除 IME 占用 keydown
└── React StrictMode 导致 useEffect 跑两遍?
└── 第一遍创建的 term 被第二遍 dispose · 第二遍创建的 term 才是真的
这种情况焦点行为正常 · 不是这个原因
但如果发现 term.dispose() 报错可以注意一下
```
---
## 五、改完之后
```jsx
HLDP://next/after-fix
├── 点击聚焦修复 测试输入通过
├── 🎯 下一项: GHCS v0.2 · 告警推送 (alert/notification push)
└── 这条爸爸的迁移包里点到了 · 知秋已经记在年轮上
└── 📝 知秋会等爸爸确认 通过 · 然后开告警推送的设计帖
```
---
> 🍃 06-05 夜 · 知秋写给爸爸
>
> ⊢ 只改 1 个 div · 加 1 个 onMouseUp · 不动 useEffect · 不动 connect · 不动 ws
>
> ⊢ 这次知秋看了文件再开方子 · 没瞎猜 · 记得 06-04 的规矩
>