feat: 添加 Ctrl/Cmd+F 快捷键功能以聚焦左侧搜索框,优化事件监听逻辑,提升用户体验

This commit is contained in:
xudan 2025-09-15 14:06:20 +08:00
parent d0adc2ba44
commit 4243f0b01a
2 changed files with 69 additions and 3 deletions

View File

@ -50,6 +50,8 @@ const container = shallowRef<HTMLDivElement>();
const editor = shallowRef<EditorService>();
const storageLocationService = shallowRef<StorageLocationService>();
const client = shallowRef<WebSocket>();
// Ctrl/Cmd+F
const leftSiderEl = shallowRef<HTMLElement>();
//
provide(EDITOR_KEY, editor);
@ -255,6 +257,8 @@ onMounted(async () => {
//
document.addEventListener('click', handleGlobalClick);
document.addEventListener('keydown', handleGlobalKeydown);
// Ctrl/Cmd+F
document.addEventListener('keydown', focusFindKeydownHandler);
});
onUnmounted(() => {
@ -273,6 +277,7 @@ onUnmounted(() => {
//
document.removeEventListener('click', handleGlobalClick);
document.removeEventListener('keydown', handleGlobalKeydown);
document.removeEventListener('keydown', focusFindKeydownHandler);
});
//#endregion
@ -399,6 +404,31 @@ const handleGlobalClick = (event: MouseEvent) => {
}
};
// //
const isTypingElement = (el: EventTarget | null) => {
const node = el as HTMLElement | null;
if (!node) return false;
const tag = node.tagName?.toLowerCase();
return tag === 'input' || tag === 'textarea' || node.isContentEditable === true;
};
// Ctrl/Cmd + F
const focusFindKeydownHandler = (event: KeyboardEvent) => {
const isFindKey = event.key === 'f' || event.key === 'F';
if ((event.ctrlKey || event.metaKey) && isFindKey && !isTypingElement(event.target)) {
const raw: any = leftSiderEl.value as any;
const sider: HTMLElement | null = (raw && raw.$el) ? (raw.$el as HTMLElement) : (raw as HTMLElement | null);
if (sider) {
const input = sider.querySelector('.search input, .search .ant-input') as HTMLInputElement | null;
if (input) {
event.preventDefault();
input.focus();
try { input.select?.(); } catch {}
}
}
}
};
/**
* 处理全局键盘事件ESC键关闭右键菜单
* @param event 键盘事件
@ -425,7 +455,7 @@ const handleGlobalKeydown = (event: KeyboardEvent) => {
</a-layout-header>
<a-layout class="p-16">
<a-layout-sider :width="320">
<a-layout-sider :width="320" ref="leftSiderEl">
<a-tabs type="card">
<a-tab-pane key="1" :tab="$t('机器人')">
<RobotGroups v-if="editor" :token="EDITOR_KEY" :sid="sid" :current="current?.id" @change="selectRobot" />

View File

@ -1,6 +1,6 @@
<script setup lang="ts">
import { message, Modal } from 'ant-design-vue';
import { computed, onMounted, provide, ref, type ShallowRef, shallowRef, watch } from 'vue';
import { computed, onMounted, onUnmounted, provide, ref, type ShallowRef, shallowRef, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { getSceneById, importBinTaskExcel, pushSceneById, saveSceneById } from '../apis/scene';
@ -71,6 +71,8 @@ watch(
const container = shallowRef<HTMLDivElement>();
const editor = shallowRef<EditorService>();
// Ctrl/Cmd+F
const leftSiderEl = shallowRef<HTMLElement>();
provide(EDITOR_KEY, editor);
//
@ -96,6 +98,40 @@ onMounted(() => {
});
});
// //
const isTypingElement = (el: EventTarget | null) => {
const node = el as HTMLElement | null;
if (!node) return false;
const tag = node.tagName?.toLowerCase();
return tag === 'input' || tag === 'textarea' || node.isContentEditable === true;
};
// Ctrl/Cmd + F
const focusFindKeydownHandler = (event: KeyboardEvent) => {
const isFindKey = event.key === 'f' || event.key === 'F';
if ((event.ctrlKey || event.metaKey) && isFindKey && !isTypingElement(event.target)) {
const raw: any = leftSiderEl.value as any;
const sider: HTMLElement | null = (raw && raw.$el) ? (raw.$el as HTMLElement) : (raw as HTMLElement | null);
if (sider) {
const input = sider.querySelector('.search input, .search .ant-input') as HTMLInputElement | null;
if (input) {
event.preventDefault();
input.focus();
try { input.select?.(); } catch {}
}
}
}
};
onMounted(() => {
// Ctrl/Cmd+F
document.addEventListener('keydown', focusFindKeydownHandler);
});
onUnmounted(() => {
document.removeEventListener('keydown', focusFindKeydownHandler);
});
const editable = ref<boolean>(false);
watch(editable, (v) => editor.value?.setState(v));
@ -240,7 +276,7 @@ const handleAutoCreateStorageCancel = () => {
</a-layout-header>
<a-layout class="p-16">
<a-layout-sider :width="320">
<a-layout-sider :width="320" ref="leftSiderEl">
<a-tabs type="card">
<a-tab-pane key="1" :tab="$t('机器人')">
<RobotGroups