diff --git a/src/components/SearchMenu/Modal.vue b/src/components/SearchMenu/Modal.vue index 63e19df..9db9527 100644 --- a/src/components/SearchMenu/Modal.vue +++ b/src/components/SearchMenu/Modal.vue @@ -22,7 +22,7 @@ const scrollbarRef = ref | null>(null) const resultRef = ref | null>(null) const keyword = ref("") -const resultList = shallowRef([]) +const result = shallowRef([]) const activeRouteName = ref(undefined) /** 是否按下了上键或下键(用于解决和 mouseenter 事件的冲突) */ const isPressUpOrDown = ref(false) @@ -30,17 +30,16 @@ const isPressUpOrDown = ref(false) /** 控制搜索对话框宽度 */ const modalWidth = computed(() => (isMobile.value ? "80vw" : "40vw")) /** 树形菜单 */ -const menusData = computed(() => cloneDeep(usePermissionStore().routes)) +const menus = computed(() => cloneDeep(usePermissionStore().routes)) /** 搜索(防抖) */ const handleSearch = debounce(() => { - const flatMenusData = flatTree(menusData.value) - resultList.value = flatMenusData.filter(menu => - keyword.value ? menu.meta?.title?.toLocaleLowerCase().includes(keyword.value.toLocaleLowerCase().trim()) : false - ) + const flatMenus = flatTree(menus.value) + const _keywords = keyword.value.toLocaleLowerCase().trim() + result.value = flatMenus.filter(menu => keyword.value ? menu.meta?.title?.toLocaleLowerCase().includes(_keywords) : false) // 默认选中搜索结果的第一项 - const length = resultList.value?.length - activeRouteName.value = length > 0 ? resultList.value[0].name : undefined + const length = result.value?.length + activeRouteName.value = length > 0 ? result.value[0].name : undefined }, 500) /** 将树形菜单扁平化为一维数组,用于菜单搜索 */ @@ -58,7 +57,7 @@ function handleClose() { // 延时处理防止用户看到重置数据的操作 setTimeout(() => { keyword.value = "" - resultList.value = [] + result.value = [] }, 200) } @@ -73,16 +72,16 @@ function scrollTo(index: number) { /** 键盘上键 */ function handleUp() { isPressUpOrDown.value = true - const { length } = resultList.value + const { length } = result.value if (length === 0) return // 获取该 name 在菜单中第一次出现的位置 - const index = resultList.value.findIndex(item => item.name === activeRouteName.value) + const index = result.value.findIndex(item => item.name === activeRouteName.value) // 如果已处在顶部 if (index === 0) { - const bottomName = resultList.value[length - 1].name + const bottomName = result.value[length - 1].name // 如果顶部和底部的 bottomName 相同,且长度大于 1,就再跳一个位置(可解决遇到首尾两个相同 name 导致的上键不能生效的问题) if (activeRouteName.value === bottomName && length > 1) { - activeRouteName.value = resultList.value[length - 2].name + activeRouteName.value = result.value[length - 2].name scrollTo(length - 2) } else { // 跳转到底部 @@ -90,7 +89,7 @@ function handleUp() { scrollTo(length - 1) } } else { - activeRouteName.value = resultList.value[index - 1].name + activeRouteName.value = result.value[index - 1].name scrollTo(index - 1) } } @@ -98,16 +97,16 @@ function handleUp() { /** 键盘下键 */ function handleDown() { isPressUpOrDown.value = true - const { length } = resultList.value + const { length } = result.value if (length === 0) return // 获取该 name 在菜单中最后一次出现的位置(可解决遇到连续两个相同 name 导致的下键不能生效的问题) - const index = resultList.value.map(item => item.name).lastIndexOf(activeRouteName.value) + const index = result.value.map(item => item.name).lastIndexOf(activeRouteName.value) // 如果已处在底部 if (index === length - 1) { - const topName = resultList.value[0].name + const topName = result.value[0].name // 如果底部和顶部的 topName 相同,且长度大于 1,就再跳一个位置(可解决遇到首尾两个相同 name 导致的下键不能生效的问题) if (activeRouteName.value === topName && length > 1) { - activeRouteName.value = resultList.value[1].name + activeRouteName.value = result.value[1].name scrollTo(1) } else { // 跳转到顶部 @@ -115,30 +114,23 @@ function handleDown() { scrollTo(0) } } else { - activeRouteName.value = resultList.value[index + 1].name + activeRouteName.value = result.value[index + 1].name scrollTo(index + 1) } } /** 键盘回车键 */ function handleEnter() { - const { length } = resultList.value + const { length } = result.value if (length === 0) return const name = activeRouteName.value - const path = resultList.value.find(item => item.name === name)?.path - if (path && isExternal(path)) { - window.open(path, "_blank", "noopener, noreferrer") - return - } - if (!name) { - ElMessage.warning("无法通过搜索进入该菜单,请为对应的路由设置唯一的 Name") - return - } + const path = result.value.find(item => item.name === name)?.path + if (path && isExternal(path)) return window.open(path, "_blank", "noopener, noreferrer") + if (!name) return ElMessage.warning("无法通过搜索进入该菜单,请为对应的路由设置唯一的 Name") try { router.push({ name }) } catch { - ElMessage.error("该菜单有必填的动态参数,无法通过搜索进入") - return + return ElMessage.error("该菜单有必填的动态参数,无法通过搜索进入") } handleClose() } @@ -169,21 +161,21 @@ function handleReleaseUpOrDown() { - + diff --git a/src/components/SearchMenu/Result.vue b/src/components/SearchMenu/Result.vue index 753f5bd..00fb3b3 100644 --- a/src/components/SearchMenu/Result.vue +++ b/src/components/SearchMenu/Result.vue @@ -47,19 +47,13 @@ function getScrollTop(index: number) { } // 在组件挂载前添加窗口大小变化事件监听器 -onBeforeMount(() => { - window.addEventListener("resize", getScrollbarHeight) -}) +onBeforeMount(() => window.addEventListener("resize", getScrollbarHeight)) // 在组件挂载时立即计算滚动可视区高度 -onMounted(() => { - getScrollbarHeight() -}) +onMounted(() => getScrollbarHeight()) // 在组件卸载前移除窗口大小变化事件监听器 -onBeforeUnmount(() => { - window.removeEventListener("resize", getScrollbarHeight) -}) +onBeforeUnmount(() => window.removeEventListener("resize", getScrollbarHeight)) defineExpose({ getScrollTop })