Skip to content

Commit

Permalink
feat: BaseSearchMenu support depth fuzzy search
Browse files Browse the repository at this point in the history
  • Loading branch information
flingyp committed Jun 19, 2023
1 parent e0ede8f commit 475716f
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 18 deletions.
36 changes: 28 additions & 8 deletions src/layout/components/layout/BaseSearchItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,19 @@ import RenderIconify from '~/components/common/RenderIconify.vue'
interface BaseSearchItemProps {
menu: VAdmireMenuOption
level: number
}
const props = defineProps<BaseSearchItemProps>()
const props = withDefaults(defineProps<BaseSearchItemProps>(), {
level: 0,
})
const emit = defineEmits(['close'])
const routeKey = props.menu.key as string
const router = useRouter()
const routeMenuStore = useRouteMenuStore()
const navigatorTo = () => {
if (props.menu.children && props.menu.children?.length > 0) return
routeMenuStore.createTabMenuKey(routeKey)
router.push({ name: routeKey })
emit('close')
Expand All @@ -21,13 +25,29 @@ const navigatorTo = () => {

<template>
<div
class="flex items-center p-1 cursor-pointer hover:text-primary"
@click="navigatorTo"
class="cursor-pointer"
:style="{paddingLeft: `${props.level * 16}px`}"
>
<RenderIconify
:icon="menu.iconLabel"
class="w-4 h-4 mr-1"
/>
<span>{{ menu.label }}</span>
<div
class="flex items-center hover:text-primary"
@click="navigatorTo"
>
<RenderIconify
:icon="menu.iconLabel"
class="w-4 h-4 mr-1"
/>
<span>{{ menu.label }}</span>
</div>
<div
v-if="menu.children && menu.children?.length > 0"
class="space-y-1 mt-1"
>
<BaseSearchItem
v-for="item in menu.children"
:key="item.key"
:menu="item"
:level="level + 1"
/>
</div>
</div>
</template>
23 changes: 13 additions & 10 deletions src/layout/components/layout/BaseSearchMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import BaseSearchItem from './BaseSearchItem.vue'
const { t } = useI18n()
const { defaultLocales } = storeToRefs(useVAdmireConfigStore())
const { vadmireChildrenMenuByFlat } = storeToRefs(useRouteMenuStore())
const { vadmireMenu } = storeToRefs(useRouteMenuStore())
const placeholder = computed(() => t('header.searchPlaceholder'))
Expand All @@ -27,48 +27,51 @@ const closeSearchMenu = (type: 'CLICK' | 'BLUR') => {
if (type === 'CLICK') searchKeyWord.value = ''
}
const inputKeywordRef = ref<HTMLInputElement>()
onClickOutside(inputKeywordRef, () => {
const baseSearchMenuRef = ref<HTMLInputElement>()
onClickOutside(baseSearchMenuRef, () => {
if (!isShowSearchMenu.value) return
isShowSearchMenu.value = false
})
const searchMenuList = ref<VAdmireMenuOption[]>([])
const transformVadmireChildrenMenuByFlat = computed(() => vadmireChildrenMenuByFlat.value.map((item) => {
const transformVadmireMenu = computed(() => vadmireMenu.value.map((item) => {
const newMenu = transformMenu(item, t)
return newMenu
}))
const options = {
keys: ['label'],
const options: Fuse.IFuseOptions<VAdmireMenuOption> = {
keys: ['label', 'children.label'],
threshold: 0.3,
includeScore: true,
}
let fuse: Fuse<VAdmireMenuOption>
watch(defaultLocales, () => {
nextTick(() => {
fuse = new Fuse(transformVadmireChildrenMenuByFlat.value, options)
fuse = new Fuse(transformVadmireMenu.value, options)
})
}, { immediate: true })
const inputKeyword = useDebounce(() => {
// remove all Spaces in the string
searchKeyWord.value = searchKeyWord.value.replace(/\s*/g, '')
const searchResult = fuse.search(searchKeyWord.value)
console.log('searchResult->>', searchResult)
// @ts-ignore
searchMenuList.value = searchResult.map((data) => data.item)
}, 200)
</script>

<template>
<div class="flex items-center">
<div
ref="baseSearchMenuRef"
class="flex items-center"
>
<NInput
ref="inputKeywordRef"
v-model:value="searchKeyWord"
:placeholder="placeholder"
@input="inputKeyword"
@focus="showSearchMenu"
@blur="closeSearchMenu('BLUR')"
>
<template #prefix>
<RenderIconify icon="carbon:search" />
Expand Down

0 comments on commit 475716f

Please sign in to comment.