fix: 修复SSH终端Escape按键

- 将弹框捕获的Escape控制字符直接转发到远端
- 阻止xterm对同一次Escape事件重复发送
This commit is contained in:
Logan.Li committed 2026-07-26 18:21:55 +08:00
1 parent 82b53c043b
commit d666840ed0
1 file changed
+17 -7
@@ -61,6 +61,15 @@ export function TerminalDialog({
const [assigning, setAssigning] = useState(false); const [assigning, setAssigning] = useState(false);
const [authReady, setAuthReady] = useState(hasAuth); // 认证就绪标志 const [authReady, setAuthReady] = useState(hasAuth); // 认证就绪标志
const sendTerminalInput = (data: string) => {
const ws = wsRef.current;
if (ws?.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({ status: 0, data }));
return true;
}
return false;
};
// 加载凭据列表 // 加载凭据列表
useEffect(() => { useEffect(() => {
if (!open || hasAuth) return; if (!open || hasAuth) return;
@@ -123,11 +132,9 @@ export function TerminalDialog({
const ws = new WebSocket(wsUrl); const ws = new WebSocket(wsUrl);
wsRef.current = ws; wsRef.current = ws;
term.onData((data) => { // Escape 由 Dialog 捕获后直接转发,xterm 跳过同一次事件以免重复发送。 // Logan.Li
if (ws.readyState === WebSocket.OPEN) { term.attachCustomKeyEventHandler((event) => event.key !== "Escape");
ws.send(JSON.stringify({ status: 0, data })); term.onData(sendTerminalInput);
}
});
ws.onmessage = (event) => { ws.onmessage = (event) => {
try { try {
@@ -214,8 +221,11 @@ export function TerminalDialog({
<Dialog open={open} onOpenChange={onOpenChange}> <Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent <DialogContent
showCloseButton={false} showCloseButton={false}
// 禁用 Radix Dialog 默认的 ESC 关闭:终端内 vi/top 等会用到 ESC,关闭只能点头部 X 按钮 // Logan.Li // Radix 在捕获阶段收到 Escape,阻止关窗并把控制字符送给远端 Vim。 // Logan.Li
onEscapeKeyDown={(e) => e.preventDefault()} onEscapeKeyDown={(event) => {
event.preventDefault();
sendTerminalInput("\x1b");
}}
className={cn( className={cn(
"min-w-0 overflow-hidden bg-[var(--dg-bg-secondary)] border-[var(--dg-border)] p-0 gap-0", "min-w-0 overflow-hidden bg-[var(--dg-bg-secondary)] border-[var(--dg-border)] p-0 gap-0",
// 禁用 CSS 过渡:终端窗口应该即时缩放,不需要动画 // 禁用 CSS 过渡:终端窗口应该即时缩放,不需要动画