🐛 fix(ai-chat): 修复输入法候选阶段回车误发送

- 识别 IME keyCode/which 229 的候选输入事件
- 避免候选词确认触发 AI 对话发送
- 补充发送快捷键回归测试
Refs #461
This commit is contained in:
Syngnat
2026-05-13 20:19:44 +08:00
parent b2b1e6b944
commit 0bcb8ce6c3
2 changed files with 13 additions and 1 deletions

View File

@@ -52,6 +52,9 @@ describe('aiChatSendShortcut', () => {
expect(shouldSendAIChatOnKeyDown(binding('Enter'), { key: 'Enter', shiftKey: true })).toBe(false);
expect(shouldSendAIChatOnKeyDown(binding('Enter'), { key: 'Enter', isComposing: true })).toBe(false);
expect(shouldSendAIChatOnKeyDown(binding('Enter'), { key: 'Enter', nativeEvent: { isComposing: true } })).toBe(false);
expect(shouldSendAIChatOnKeyDown(binding('Enter'), { key: 'Enter', keyCode: 229 })).toBe(false);
expect(shouldSendAIChatOnKeyDown(binding('Enter'), { key: 'Enter', which: 229 })).toBe(false);
expect(shouldSendAIChatOnKeyDown(binding('Enter'), { key: 'Enter', nativeEvent: { keyCode: 229 } })).toBe(false);
expect(shouldSendAIChatOnKeyDown(binding('Enter'), { key: 'a' })).toBe(false);
expect(shouldSendAIChatOnKeyDown(binding('Enter', false), { key: 'Enter' })).toBe(false);
});

View File

@@ -2,6 +2,8 @@ import { DEFAULT_SHORTCUT_OPTIONS, getShortcutDisplay, isShortcutMatch, type Sho
export interface AIChatSendShortcutKeyEventLike {
key?: string;
keyCode?: number;
which?: number;
shiftKey?: boolean;
metaKey?: boolean;
ctrlKey?: boolean;
@@ -9,6 +11,8 @@ export interface AIChatSendShortcutKeyEventLike {
isComposing?: boolean;
nativeEvent?: {
isComposing?: boolean;
keyCode?: number;
which?: number;
};
preventDefault?: () => void;
stopPropagation?: () => void;
@@ -29,7 +33,12 @@ export const shouldSendAIChatOnKeyDown = (
if (!binding?.enabled) {
return false;
}
if (event.shiftKey || event.isComposing || event.nativeEvent?.isComposing) {
// Some IMEs report Enter during an active candidate/composition as keyCode 229.
const isImeCandidateEvent = event.keyCode === 229
|| event.which === 229
|| event.nativeEvent?.keyCode === 229
|| event.nativeEvent?.which === 229;
if (event.shiftKey || event.isComposing || event.nativeEvent?.isComposing || isImeCandidateEvent) {
return false;
}
return isShortcutMatch(event as KeyboardEvent, binding.combo);