diff --git a/ruoyi-fastapi-frontend/src/assets/icons/svg/enter.svg b/ruoyi-fastapi-frontend/src/assets/icons/svg/enter.svg new file mode 100644 index 0000000..f7cabf2 --- /dev/null +++ b/ruoyi-fastapi-frontend/src/assets/icons/svg/enter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ruoyi-fastapi-frontend/src/components/HeaderSearch/index.vue b/ruoyi-fastapi-frontend/src/components/HeaderSearch/index.vue index cb1d075..8fae162 100644 --- a/ruoyi-fastapi-frontend/src/components/HeaderSearch/index.vue +++ b/ruoyi-fastapi-frontend/src/components/HeaderSearch/index.vue @@ -1,19 +1,46 @@ @@ -21,38 +48,46 @@ import Fuse from 'fuse.js' import { getNormalPath } from '@/utils/ruoyi' import { isHttp } from '@/utils/validate' +import useSettingsStore from '@/store/modules/settings' import usePermissionStore from '@/store/modules/permission' -const search = ref(''); -const options = ref([]); -const searchPool = ref([]); -const show = ref(false); -const fuse = ref(undefined); -const headerSearchSelectRef = ref(null); -const router = useRouter(); -const routes = computed(() => usePermissionStore().defaultRoutes); +const search = ref('') +const options = ref([]) +const searchPool = ref([]) +const activeIndex = ref(-1) +const show = ref(false) +const fuse = ref(undefined) +const headerSearchSelectRef = ref(null) +const router = useRouter() +const theme = computed(() => useSettingsStore().theme) +const routes = computed(() => usePermissionStore().defaultRoutes) function click() { show.value = !show.value if (show.value) { headerSearchSelectRef.value && headerSearchSelectRef.value.focus() + options.value = searchPool.value } -}; +} + function close() { headerSearchSelectRef.value && headerSearchSelectRef.value.blur() + search.value = '' options.value = [] show.value = false + activeIndex.value = -1 } + function change(val) { - const path = val.path; - const query = val.query; + const path = val.path + const query = val.query if (isHttp(path)) { // http(s):// 路径新窗口打开 - const pindex = path.indexOf("http"); - window.open(path.substr(pindex, path.length), "_blank"); + const pindex = path.indexOf("http") + window.open(path.substr(pindex, path.length), "_blank") } else { if (query) { - router.push({ path: path, query: JSON.parse(query) }); + router.push({ path: path, query: JSON.parse(query) }) } else { router.push(path) } @@ -64,6 +99,7 @@ function change(val) { show.value = false }) } + function initFuse(list) { fuse.value = new Fuse(list, { shouldSort: true, @@ -80,6 +116,7 @@ function initFuse(list) { }] }) } + // Filter out the routes that can be displayed in the sidebar // And generate the internationalized title function generateRoutes(routes, basePath = '', prefixTitle = []) { @@ -88,16 +125,17 @@ function generateRoutes(routes, basePath = '', prefixTitle = []) { for (const r of routes) { // skip hidden router if (r.hidden) { continue } - const p = r.path.length > 0 && r.path[0] === '/' ? r.path : '/' + r.path; + const p = r.path.length > 0 && r.path[0] === '/' ? r.path : '/' + r.path const data = { path: !isHttp(r.path) ? getNormalPath(basePath + p) : r.path, - title: [...prefixTitle] + title: [...prefixTitle], + icon: '' } if (r.meta && r.meta.title) { data.title = [...data.title, r.meta.title] - - if (r.redirect !== 'noRedirect') { + data.icon = r.meta.icon + if (r.redirect !== "noRedirect") { // only push the routes with title // special case: need to exclude parent router without redirect res.push(data) @@ -117,30 +155,42 @@ function generateRoutes(routes, basePath = '', prefixTitle = []) { } return res } + function querySearch(query) { + activeIndex.value = -1 if (query !== '') { - options.value = fuse.value.search(query) + options.value = fuse.value.search(query).map((item) => item.item) ?? searchPool.value } else { - options.value = [] + options.value = searchPool.value + } +} + +function activeStyle(index) { + if (index !== activeIndex.value) return {} + return { + "background-color": theme.value, + "color": "#fff" + } +} + +function navigateResult(direction) { + if (direction === "up") { + activeIndex.value = activeIndex.value <= 0 ? options.value.length - 1 : activeIndex.value - 1 + } else if (direction === "down") { + activeIndex.value = activeIndex.value >= options.value.length - 1 ? 0 : activeIndex.value + 1 + } +} + +function selectActiveResult() { + if (options.value.length > 0 && activeIndex.value >= 0) { + change(options.value[activeIndex.value]) } } onMounted(() => { - searchPool.value = generateRoutes(routes.value); -}) - -watchEffect(() => { searchPool.value = generateRoutes(routes.value) }) -watch(show, (value) => { - if (value) { - document.body.addEventListener('click', close) - } else { - document.body.removeEventListener('click', close) - } -}) - watch(searchPool, (list) => { initFuse(list) }) @@ -148,40 +198,55 @@ watch(searchPool, (list) => { \ No newline at end of file +