From b2639184261f59279c98611f775f3fe821449e15 Mon Sep 17 00:00:00 2001 From: LiuHao <liuhaoai545@gmail> Date: 星期三, 19 四月 2023 23:25:34 +0800 Subject: [PATCH] update searchMenu style --- src/layout/components/topBar/search.vue | 158 +++++++++++++++++++++++++++++++++++++++ .eslintrc.js | 3 src/layout/components/Navbar.vue | 16 +++ src/components/HeaderSearch/index.vue | 8 +- 4 files changed, 178 insertions(+), 7 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 2b2e0d0..b6b10a6 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -29,7 +29,8 @@ // 鍏抽棴绌虹被鍨嬫鏌� {} extendDefaults: true, types: { - '{}': false + '{}': false, + 'Function': false } } ] diff --git a/src/components/HeaderSearch/index.vue b/src/components/HeaderSearch/index.vue index 60ebb9d..f0ab1c9 100644 --- a/src/components/HeaderSearch/index.vue +++ b/src/components/HeaderSearch/index.vue @@ -17,7 +17,7 @@ </div> </template> -<script setup lang="ts"> +<script setup lang="ts" name="HeaderSearch"> import Fuse from 'fuse.js' import { getNormalPath } from '@/utils/ruoyi' import { isHttp } from '@/utils/validate' @@ -123,9 +123,9 @@ searchPool.value = generateRoutes(routes.value); }) -watchEffect(() => { - searchPool.value = generateRoutes(routes.value) -}) +// watchEffect(() => { +// searchPool.value = generateRoutes(routes.value) +// }) watch(show, (value) => { if (value) { diff --git a/src/layout/components/Navbar.vue b/src/layout/components/Navbar.vue index 156011f..8b9624e 100644 --- a/src/layout/components/Navbar.vue +++ b/src/layout/components/Navbar.vue @@ -20,8 +20,13 @@ <template #prefix><svg-icon icon-class="company" class="el-input__icon input-icon" /></template> </el-select> - <header-search id="header-search" class="right-menu-item" /> - + <!-- <header-search id="header-search" class="right-menu-item" /> --> + <search-menu ref="searchMenuRef" /> + <el-tooltip content="鎼滅储" effect="dark" placement="bottom"> + <div class="right-menu-item hover-effect" @click="openSearchMenu"> + <svg-icon class-name="search-icon" icon-class="search" /> + </div> + </el-tooltip> <el-tooltip content="Github" effect="dark" placement="bottom"> <ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" /> </el-tooltip> @@ -68,6 +73,7 @@ </template> <script setup lang="ts"> +import SearchMenu from './topBar/search.vue' import useAppStore from '@/store/modules/app' import useUserStore from '@/store/modules/user' import useSettingsStore from '@/store/modules/settings' @@ -89,6 +95,12 @@ const dynamic = ref(false); // 绉熸埛寮�鍏� const tenantEnabled = ref(true); +// 鎼滅储鑿滃崟 +const searchMenuRef = ref<InstanceType<typeof SearchMenu>>(); + +const openSearchMenu = () => { + searchMenuRef.value?.openSearch() +} // 鍔ㄦ�佸垏鎹� const dynamicTenantEvent = async (tenantId: string) => { diff --git a/src/layout/components/topBar/search.vue b/src/layout/components/topBar/search.vue new file mode 100644 index 0000000..3b707e4 --- /dev/null +++ b/src/layout/components/topBar/search.vue @@ -0,0 +1,158 @@ +<template> + <div class="layout-search-dialog"> + <el-dialog v-model="state.isShowSearch" destroy-on-close :show-close="false"> + <template #footer> + <el-autocomplete + v-model="state.menuQuery" + :fetch-suggestions="menuSearch" + placeholder="鎼滅储" + ref="layoutMenuAutocompleteRef" + @select="onHandleSelect" + :fit-input-width="true" + > + <template #prefix> + <svg-icon class-name="search-icon" icon-class="search" /> + </template> + <template #default="{ item }"> + <div> + <svg-icon :icon-class="item.icon" class="mr5" /> + {{ item.title }} + </div> + </template> + </el-autocomplete> + </template> + </el-dialog> + </div> +</template> + +<script setup lang="ts" name="layoutBreadcrumbSearch"> +import { getNormalPath } from '@/utils/ruoyi'; +import { isHttp } from '@/utils/validate'; +import usePermissionStore from '@/store/modules/permission'; +import { RouteOption } from 'vue-router'; +type Router = Array<{ + path: string; + icon: string; + title: string[]; +}> +type SearchState<T = any> = { + isShowSearch: boolean; + menuQuery: string; + menuList: T[]; +}; +// 瀹氫箟鍙橀噺鍐呭 +const layoutMenuAutocompleteRef = ref(); +const router = useRouter(); +const routes = computed(() => usePermissionStore().routes); +const state = reactive<SearchState>({ + isShowSearch: false, + menuQuery: '', + menuList: [], +}); + +// 鎼滅储寮圭獥鎵撳紑 +const openSearch = () => { + state.menuQuery = ''; + state.isShowSearch = true; + state.menuList = generateRoutes(routes.value); + nextTick(() => { + setTimeout(() => { + layoutMenuAutocompleteRef.value.focus(); + }); + }); +}; +// 鎼滅储寮圭獥鍏抽棴 +const closeSearch = () => { + state.isShowSearch = false; +}; +// 鑿滃崟鎼滅储鏁版嵁杩囨护 +const menuSearch = (queryString: string, cb: Function) => { + let options = state.menuList.filter((item) => { + return item.title.indexOf(queryString) > -1; + }); + cb(options); +}; + +// Filter out the routes that can be displayed in the sidebar +// And generate the internationalized title +const generateRoutes = (routes: RouteOption[], basePath = '', prefixTitle: string[] = []) => { + let res: Router = [] + routes.forEach(r => { + // skip hidden router + if (!r.hidden) { + const p = r.path.length > 0 && r.path[0] === '/' ? r.path : '/' + r.path; + const data: any = { + path: !isHttp(r.path) ? getNormalPath(basePath + p) : r.path, + icon: r.meta?.icon, + title: [...prefixTitle] + } + if (r.meta && r.meta.title) { + data.title = [...data.title, r.meta.title]; + if (r.redirect !== 'noRedirect') { + // only push the routes with title + // special case: need to exclude parent router without redirect + res.push(data); + } + } + // recursive child routes + if (r.children) { + const tempRoutes = generateRoutes(r.children, data.path, data.title); + if (tempRoutes.length >= 1) { + res = [...res, ...tempRoutes]; + } + } + } + }) + res.forEach((item: any) => { + if (item.title instanceof Array) { + item.title = item.title.join('/'); + } + }); + return res; +} +// 褰撳墠鑿滃崟閫変腑鏃� +const onHandleSelect = (val: any) => { + const paths = val.path; + if (isHttp(paths)) { + // http(s):// 璺緞鏂扮獥鍙f墦寮� + const pindex = paths.indexOf("http"); + window.open(paths.substring(pindex, paths.length), "_blank"); + } else { + router.push(paths) + } + state.menuQuery = '' + closeSearch(); + +}; + +// 鏆撮湶鍙橀噺 +defineExpose({ + openSearch +}); +</script> + +<style scoped lang="scss"> +.layout-search-dialog { + position: relative; + :deep(.el-dialog) { + .el-dialog__header, + .el-dialog__body { + display: none; + } + .el-dialog__footer { + width: 100%; + position: absolute; + left: 50%; + transform: translateX(-50%); + top: -53vh; + } + } + :deep(.el-autocomplete) { + width: 560px; + position: absolute; + top: 150px; + left: 50%; + transform: translateX(-50%); + } +} +</style> -- Gitblit v1.9.3