diff --git a/src/components/meLocaleSelect.vue b/src/components/meLocaleSelect.vue index 82bb777f..91fe73e7 100644 --- a/src/components/meLocaleSelect.vue +++ b/src/components/meLocaleSelect.vue @@ -31,7 +31,7 @@ const setLanguage = (locale: string) => { padding: 0 10px; .icon { - font-size: 1.2em; + font-size: 1.3em; } } } diff --git a/src/components/meSearchMenu/index.vue b/src/components/meSearchMenu/index.vue new file mode 100644 index 00000000..83511049 --- /dev/null +++ b/src/components/meSearchMenu/index.vue @@ -0,0 +1,89 @@ + + + diff --git a/src/components/meSearchMenu/useSearchMenu.ts b/src/components/meSearchMenu/useSearchMenu.ts new file mode 100644 index 00000000..3db0424c --- /dev/null +++ b/src/components/meSearchMenu/useSearchMenu.ts @@ -0,0 +1,86 @@ +import { useGlobalStore, useRouteStore } from '@/store'; +import { RouteRecordRaw } from 'vue-router'; +import { resolvePath, jump } from '@/router'; + +import { debounce } from 'lodash-es'; +const menuList = [] as { path: string; isLink?: boolean; title: string[] }[]; + +const createMenuList = (routes: RouteRecordRaw[], baseTitle: string[] = [], basePath = '') => { + routes.forEach((item) => { + if (item.meta?.title) { + const path = resolvePath(item.path, basePath); + const title = [...baseTitle, item.meta.title]; + if (!item.meta.hideMenu && (item.redirect || !item.children?.length)) { + menuList.push({ + path, + title, + isLink: item.meta.isLink, + }); + } + if (item.children) { + createMenuList(item.children, title, path); + } + } + }); +}; + +export const useSearchMenu = (debounceTime = 500) => { + const { i18n } = useGlobalStore(); + const { routes } = useRouteStore(); + !menuList.length && createMenuList(routes); + const filteredMenu = ref<{ path: string; meta: { isLink?: boolean; title: string } }[]>([]); + const activeIndex = ref(0); + const search = debounce((searchText: string) => { + filteredMenu.value = []; + activeIndex.value = 0; + searchText && menuList.forEach((item) => { + const title = item.title.map((v) => i18n.t(v)).join(' > '); + if (title.search(searchText) > -1) { + filteredMenu.value.push({ + path: item.path, + meta: { + title, + isLink: item.isLink, + }, + }); + } + return filteredMenu.value; + }); + }, debounceTime); + + // Arrow key up + function handleUp() { + if (!filteredMenu.value.length) return false; + activeIndex.value--; + if (activeIndex.value < 0) { + activeIndex.value = filteredMenu.value.length - 1; + } + return true; + } + + // Arrow key down + function handleDown() { + if (!filteredMenu.value.length) return false; + activeIndex.value++; + if (activeIndex.value > filteredMenu.value.length - 1) { + activeIndex.value = 0; + } + return true; + } + + // enter keyboard event + async function handleEnter() { + if (!filteredMenu.value[activeIndex.value]) return false; + jump(filteredMenu.value[activeIndex.value]); + return true; + } + + return { + search, + filteredMenu, + activeIndex, + handleUp, + handleDown, + handleEnter + }; +}; diff --git a/src/components/meSettingMenu.vue b/src/components/meSettingMenu.vue index e9d61bba..ebb3400d 100644 --- a/src/components/meSettingMenu.vue +++ b/src/components/meSettingMenu.vue @@ -19,6 +19,9 @@ + + + diff --git a/src/components/meSizeSelect.vue b/src/components/meSizeSelect.vue index 30fbf244..4aa71fe6 100644 --- a/src/components/meSizeSelect.vue +++ b/src/components/meSizeSelect.vue @@ -27,7 +27,7 @@ const { themeConfig } = useSettingStore(); padding: 0 10px; .icon { - font-size: 1.2em; + font-size: 1.3em; } } } diff --git a/src/config/theme.ts b/src/config/theme.ts index 83532813..8db16ba5 100644 --- a/src/config/theme.ts +++ b/src/config/theme.ts @@ -14,4 +14,5 @@ export default { tagBarMenu: true, // 标签栏快捷菜单 tagBarRefresh: true, // 标签栏刷新按钮 showSetting: true, // 展示设置按钮 + showSearchMenu: true,//菜单搜索 }; diff --git a/src/layout/components/header/components/topBar/components/right/components/messageBox.vue b/src/layout/components/header/components/topBar/components/right/components/messageBox.vue index 20bac7d2..4a1e4374 100644 --- a/src/layout/components/header/components/topBar/components/right/components/messageBox.vue +++ b/src/layout/components/header/components/topBar/components/right/components/messageBox.vue @@ -46,7 +46,7 @@ const isDot = ref(true); .message-icon { height: 25px; line-height: 25px; - font-size: 1.2em; + font-size: 1.3em; } } } diff --git a/src/layout/components/header/components/topBar/components/right/index.vue b/src/layout/components/header/components/topBar/components/right/index.vue index 294186b9..de305954 100644 --- a/src/layout/components/header/components/topBar/components/right/index.vue +++ b/src/layout/components/header/components/topBar/components/right/index.vue @@ -1,6 +1,7 @@