From 8457f6c4b745495059e1d068dd216b41befdb48b Mon Sep 17 00:00:00 2001 From: Syngnat Date: Fri, 19 Jun 2026 13:43:12 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(shortcuts):=20=E6=8A=8A=20SQL?= =?UTF-8?q?=20=E8=AF=8A=E6=96=AD=E4=B8=8E=E6=85=A2=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E5=BF=AB=E6=8D=B7=E9=94=AE=E6=B3=A8=E5=86=8C=E5=88=B0=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E7=B3=BB=E7=BB=9F=E5=B9=B6=E5=8A=A0=E8=8F=9C=E5=8D=95?= =?UTF-8?q?=E5=85=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 注册到系统:diagnoseQuery 与 showSlowQueries 加入 ShortcutAction,可在快捷键管理面板自定义 - 修复冲突:原硬编码 Ctrl+Shift+D 与 toggleTheme 冲突、Ctrl+Shift+H 与 toggleLogPanel 冲突;改为 Ctrl+Shift+P / Ctrl+Shift+L - 菜单入口:QueryEditor 的"更多"下拉加 SQL 诊断、慢 SQL 历史两个菜单项,附带快捷键提示 - i18n 同步:6 种语言补齐 label/description --- frontend/src/components/QueryEditor.tsx | 76 ++++++++++++++++++------- frontend/src/utils/shortcuts.ts | 28 ++++++++- shared/i18n/de-DE.json | 4 ++ shared/i18n/en-US.json | 4 ++ shared/i18n/ja-JP.json | 4 ++ shared/i18n/ru-RU.json | 4 ++ shared/i18n/zh-CN.json | 4 ++ shared/i18n/zh-TW.json | 4 ++ 8 files changed, 108 insertions(+), 20 deletions(-) diff --git a/frontend/src/components/QueryEditor.tsx b/frontend/src/components/QueryEditor.tsx index 2664901..79292bd 100644 --- a/frontend/src/components/QueryEditor.tsx +++ b/frontend/src/components/QueryEditor.tsx @@ -2211,9 +2211,8 @@ const QueryEditor: React.FC<{ tab: TabData; isActive?: boolean }> = ({ tab, isAc const [saveModalMode, setSaveModalMode] = useState<'save' | 'rename'>('save'); const [saveForm] = Form.useForm(); - // SQL 诊断工作台:Ctrl+Shift+D 触发(Mac 为 Cmd+Shift+D) + // SQL 诊断工作台与慢 SQL 历史:通过快捷键管理系统注册(避免与 toggleTheme/toggleLogPanel 冲突) const [explainOpen, setExplainOpen] = useState(false); - // 慢 SQL 历史:Ctrl+Shift+H 触发 const [slowQueryOpen, setSlowQueryOpen] = useState(false); // Database Selection @@ -2275,23 +2274,6 @@ const QueryEditor: React.FC<{ tab: TabData; isActive?: boolean }> = ({ tab, isAc } as any; }, [connections, currentConnectionId]); - useEffect(() => { - if (!isActive) return; - const handler = (e: KeyboardEvent) => { - if (!(e.ctrlKey || e.metaKey) || !e.shiftKey) return; - const key = e.key.toLowerCase(); - if (key === 'd') { - e.preventDefault(); - setExplainOpen(true); - } else if (key === 'h') { - e.preventDefault(); - setSlowQueryOpen(true); - } - }; - window.addEventListener('keydown', handler); - return () => window.removeEventListener('keydown', handler); - }, [isActive]); - const addSqlLog = useStore(state => state.addSqlLog); const addTab = useStore(state => state.addTab); const setActiveContext = useStore(state => state.setActiveContext); @@ -2323,6 +2305,33 @@ const QueryEditor: React.FC<{ tab: TabData; isActive?: boolean }> = ({ tab, isAc () => resolveShortcutBinding(shortcutOptions, 'runQuery', activeShortcutPlatform), [activeShortcutPlatform, shortcutOptions], ); + // SQL 诊断 / 慢 SQL 历史的快捷键绑定(从 store 读取,用户可在快捷键管理面板自定义) + const diagnoseQueryShortcutBinding = useMemo( + () => resolveShortcutBinding(shortcutOptions, 'diagnoseQuery', activeShortcutPlatform), + [activeShortcutPlatform, shortcutOptions], + ); + const showSlowQueriesShortcutBinding = useMemo( + () => resolveShortcutBinding(shortcutOptions, 'showSlowQueries', activeShortcutPlatform), + [activeShortcutPlatform, shortcutOptions], + ); + + // SQL 诊断 / 慢 SQL 历史的快捷键监听(必须在 binding 声明之后) + useEffect(() => { + if (!isActive) return; + const handler = (e: KeyboardEvent) => { + if (diagnoseQueryShortcutBinding?.enabled && isShortcutMatch(e, diagnoseQueryShortcutBinding.combo)) { + e.preventDefault(); + setExplainOpen(true); + return; + } + if (showSlowQueriesShortcutBinding?.enabled && isShortcutMatch(e, showSlowQueriesShortcutBinding.combo)) { + e.preventDefault(); + setSlowQueryOpen(true); + } + }; + window.addEventListener('keydown', handler); + return () => window.removeEventListener('keydown', handler); + }, [isActive, diagnoseQueryShortcutBinding, showSlowQueriesShortcutBinding]); const selectCurrentStatementShortcutBinding = useMemo( () => resolveShortcutBinding(shortcutOptions, 'selectCurrentStatement', activeShortcutPlatform), [activeShortcutPlatform, shortcutOptions], @@ -5840,6 +5849,35 @@ const QueryEditor: React.FC<{ tab: TabData; isActive?: boolean }> = ({ tab, isAc label: translate('query_editor.action.export_sql_file'), onClick: () => void handleExportSQLFile(), }, + { type: 'divider' }, + { + key: 'diagnose-query', + label: ( + + {translate('app.shortcuts.action.diagnoseQuery.label' as any) || 'SQL 诊断'} + {diagnoseQueryShortcutBinding?.enabled && diagnoseQueryShortcutBinding.combo && ( + + {getShortcutDisplayLabel(diagnoseQueryShortcutBinding.combo, activeShortcutPlatform)} + + )} + + ), + onClick: () => setExplainOpen(true), + }, + { + key: 'show-slow-queries', + label: ( + + {translate('app.shortcuts.action.showSlowQueries.label' as any) || '慢 SQL 历史'} + {showSlowQueriesShortcutBinding?.enabled && showSlowQueriesShortcutBinding.combo && ( + + {getShortcutDisplayLabel(showSlowQueriesShortcutBinding.combo, activeShortcutPlatform)} + + )} + + ), + onClick: () => setSlowQueryOpen(true), + }, ]; useEffect(() => { diff --git a/frontend/src/utils/shortcuts.ts b/frontend/src/utils/shortcuts.ts index ed2555a..2dc500d 100644 --- a/frontend/src/utils/shortcuts.ts +++ b/frontend/src/utils/shortcuts.ts @@ -18,7 +18,9 @@ export type ShortcutAction = | 'toggleTheme' | 'openShortcutManager' | 'toggleMacFullscreen' - | 'resetWindowZoom'; + | 'resetWindowZoom' + | 'diagnoseQuery' + | 'showSlowQueries'; export type ShortcutPlatform = 'mac' | 'windows'; @@ -111,6 +113,8 @@ export const SHORTCUT_ACTION_ORDER: ShortcutAction[] = [ 'toggleAIPanel', 'toggleLogPanel', 'toggleTheme', + 'diagnoseQuery', + 'showSlowQueries', 'openShortcutManager', 'toggleMacFullscreen', 'resetWindowZoom', @@ -202,6 +206,18 @@ const SHORTCUT_ACTION_META_DEFINITIONS: Record