diff --git a/src/components/ProjectList.vue b/src/components/ProjectList.vue index c6c92d1..07192c0 100644 --- a/src/components/ProjectList.vue +++ b/src/components/ProjectList.vue @@ -48,6 +48,8 @@ const selectedMenuIndex = ref(-1) const toastVisible = ref(false) /** Toast 消息内容 */ const toastMessage = ref('') +/** 是否正在使用键盘导航菜单 */ +const isKeyboardNavigation = ref(false) // ===== 定时器 ===== /** 鼠标悬停禁用定时器 */ @@ -82,6 +84,8 @@ const showContextMenu = (data: { item: ListItem }): void => { handleSelect(item) showMenu.value = true listFrozen.value = true + selectedMenuIndex.value = 0 + isKeyboardNavigation.value = true emit('context-menu', data) } @@ -92,6 +96,7 @@ const closeMenu = (): void => { showMenu.value = false listFrozen.value = false selectedMenuIndex.value = -1 + isKeyboardNavigation.value = false // 临时禁用鼠标悬停,防止菜单关闭时立即触发悬停效果 temporaryDisableHover.value = true @@ -128,6 +133,8 @@ const handleMenuTriggerClick = (e: MouseEvent): void => { // 如果没有数据,仅显示菜单 showMenu.value = true listFrozen.value = true + selectedMenuIndex.value = 0 + isKeyboardNavigation.value = true } } } @@ -151,6 +158,7 @@ const handleKeyDown = (e: KeyboardEvent): void => { switch (e.key) { case 'ArrowUp': e.preventDefault() + isKeyboardNavigation.value = true // 向上选择菜单项,到顶部时循环到底部 selectedMenuIndex.value = selectedMenuIndex.value <= 0 @@ -159,6 +167,7 @@ const handleKeyDown = (e: KeyboardEvent): void => { break case 'ArrowDown': e.preventDefault() + isKeyboardNavigation.value = true // 向下选择菜单项,到底部时循环到顶部 selectedMenuIndex.value = selectedMenuIndex.value >= props.menuItems.length - 1 @@ -188,6 +197,11 @@ const showToast = (message: string): void => { }, 3000) } +// 添加鼠标悬浮处理函数 +const handleMenuItemHover = (index: number): void => { + selectedMenuIndex.value = index +} + // ===== 生命周期钩子 ===== /** * 组件挂载时添加全局事件监听 @@ -301,6 +315,7 @@ const onAfterLeave = (el: Element): void => { class="menu-item" :class="{ 'menu-item-selected': index === selectedMenuIndex }" @click="handleMenuClick(item)" + @mouseover="handleMenuItemHover(index)" > {{ item.label }} @@ -438,13 +453,6 @@ const onAfterLeave = (el: Element): void => { font-weight: 400; } -/* 菜单项悬停和选中状态 */ -.menu-item:hover, -.menu-item-selected { - background-color: rgba(0, 0, 0, 0.04); - color: rgba(0, 0, 0, 0.87); -} - /* 选中项信息区域 */ .selected-item-info { padding: 12px 16px; @@ -555,4 +563,10 @@ const onAfterLeave = (el: Element): void => { opacity: 0; transform: translate(-50%, calc(-50% - 20px)); } + +/* 统一的选中效果 */ +.menu-item-selected { + background-color: rgba(0, 0, 0, 0.08); + color: rgba(0, 0, 0, 0.87); +} \ No newline at end of file