import { onMounted, onUnmounted, ref } from "vue"; export interface KeyboardShortcut { key: string; ctrl?: boolean; shift?: boolean; alt?: boolean; meta?: boolean; description: string; action: () => void; } // 快捷键管理组合式函数 export function useKeyboard(shortcuts: KeyboardShortcut[]) { const activeKeys = ref>(new Set()); const handleKeyDown = (event: KeyboardEvent) => { activeKeys.value.add(event.key.toLowerCase()); for (const shortcut of shortcuts) { const keyMatch = event.key.toLowerCase() === shortcut.key.toLowerCase(); const ctrlMatch = !!shortcut.ctrl === (event.ctrlKey || event.metaKey); const shiftMatch = !!shortcut.shift === event.shiftKey; const altMatch = !!shortcut.alt === event.altKey; if (keyMatch && ctrlMatch && shiftMatch && altMatch) { // 排除在输入框中的部分快捷键 const target = event.target as HTMLElement; const isInput = target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.isContentEditable; // 这些快捷键在输入框中也生效 const globalShortcuts = ["Escape", "Enter"]; const needsModifier = shortcut.ctrl || shortcut.alt || shortcut.meta; if ( isInput && !globalShortcuts.includes(shortcut.key) && !needsModifier ) { continue; } event.preventDefault(); shortcut.action(); break; } } }; const handleKeyUp = (event: KeyboardEvent) => { activeKeys.value.delete(event.key.toLowerCase()); }; onMounted(() => { window.addEventListener("keydown", handleKeyDown); window.addEventListener("keyup", handleKeyUp); }); onUnmounted(() => { window.removeEventListener("keydown", handleKeyDown); window.removeEventListener("keyup", handleKeyUp); }); return { activeKeys, }; } // 预定义的快捷键配置 export function getDefaultShortcuts(actions: { newChat: () => void; toggleSidebar: () => void; focusInput: () => void; sendMessage: () => void; cancelStream: () => void; toggleTheme: () => void; showShortcuts: () => void; searchConversations: () => void; }): KeyboardShortcut[] { return [ { key: "n", ctrl: true, description: "新建对话", action: actions.newChat, }, { key: "b", ctrl: true, description: "切换侧边栏", action: actions.toggleSidebar, }, { key: "/", ctrl: true, description: "聚焦输入框", action: actions.focusInput, }, { key: "Enter", ctrl: true, description: "发送消息", action: actions.sendMessage, }, { key: "Escape", description: "取消生成", action: actions.cancelStream, }, { key: "d", ctrl: true, shift: true, description: "切换主题", action: actions.toggleTheme, }, { key: "?", ctrl: true, description: "显示快捷键", action: actions.showShortcuts, }, { key: "k", ctrl: true, description: "搜索对话", action: actions.searchConversations, }, ]; }