diff --git a/panel/web/src/pages/Desktop.tsx b/panel/web/src/pages/Desktop.tsx index 29c6024..e661e33 100644 --- a/panel/web/src/pages/Desktop.tsx +++ b/panel/web/src/pages/Desktop.tsx @@ -50,12 +50,14 @@ function installSeamlessIme(win: Window, doc: Document, instId: string): () => v }; // 捕获阶段(iframe window 最外层)抢先拦截,赶在 noVNC 之前 → stopImmediatePropagation 阻止它发 keysym。 + // 关键:队列活跃(有中文正在转发)时,只接管【数字】和回车/退格——它们不参与拼音合成、且是原"混数字丢字"的祸首; + // 字母绝不接管,否则会把下一个词的拼音首字母(如"呀"的 y)当成字面字符抢走,造成"你好y呀"。字母交给输入法合成。 const onKeyDownCapture = (ev: Event) => { const e = ev as KeyboardEvent; - if (e.isComposing) return; // 拼音合成中,交给输入法 + if (e.isComposing) return; // 拼音合成中,交给输入法(候选数字选词也在此放行) if (e.ctrlKey || e.altKey || e.metaKey) return; // 快捷键放行 if (!active()) return; // 没有中文在转发 → 不接管(英文/数字走原生 keysym,零延迟) - if (e.key.length === 1) { + if (/^[0-9]$/.test(e.key)) { e.preventDefault(); e.stopImmediatePropagation(); queue.push({ kind: 'text', data: e.key }); @@ -126,9 +128,14 @@ export default function InstanceView({ onOpenMenu }: { onOpenMenu: () => void }) setInputMode(m); try { window.localStorage.setItem('woc_input_mode', m); + // 同步写好 enable_ime,供下面重挂的 iframe 里 noVNC 连接时读取 + window.localStorage.setItem('enable_ime', m === 'seamless' ? 'true' : 'false'); } catch { /* 隐私模式禁用 localStorage:忽略 */ } + // 关键:重挂 iframe 让 noVNC 重新读取 enable_ime。否则当前已连接的会话仍是旧模式, + // 表现为"刚切到无感还是打出英文,要换页再回来才行"。 + setVncNonce((n) => n + 1); }; const [imeText, setImeText] = useState(''); const [imeSending, setImeSending] = useState(false);