添加搜索框下拉建议功能,支持键盘导航和模糊搜索,优化输入框交互体验

This commit is contained in:
2025-12-25 11:02:50 +08:00
parent ecd608ad76
commit c8c657c790

View File

@ -3,7 +3,7 @@
<d-layout>
<d-content class="main-content">
<div class="pt-8 px-12 relative hidden lg:block">
<d-input class="devui-input-demo__mt" size="lg" v-model="searchWord" @keyup.enter="search" placeholder="请输入">
<d-input class="devui-input-demo__mt" size="lg" v-model="searchWord" placeholder="请输入">
<template #prepend>
<d-select class="w-48" size="lg" v-model="broswer" :options="options"></d-select>
</template>
@ -11,6 +11,12 @@
<d-icon name="search" style="font-size: inherit;" @click="search" />
</template>
</d-input>
<div v-if="searchBox" class="absolute left-34 mt-2 z-10 bg-white text-sm text-gray-500 max-h-40 rounded-md shadow-md px-4 py-2 max-w-80">
<div class="flex p-2 pr-20 truncate rounded-md items-center hover:text-primary cursor-pointer"
:class="selecedIdx === idx ? 'text-white bg-primary' : ''" v-for="(i, idx) in searchItems"
:key="idx" @click="goExtra(i.menu_link)" @keyup.enter ="goExtra(i.menu_link)"
><span v-if="idx">导航</span> {{i.menu_name }}</div>
</div>
</div>
<!-- 标签组 -->
<!-- <PerfectScrollbar class="w-full overflow-x-auto"> -->
@ -21,7 +27,8 @@
<!-- </PerfectScrollbar> -->
<!-- 图片网格展示区域 -->
<PerfectScrollbar class="" :style="navStyle">
<div ref="navcards" class="navcard grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-6 gap-5 pt-3 pb-6 px-2 lg:px-12">
<div ref="navcards"
class="navcard grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-6 gap-5 pt-3 pb-6 px-2 lg:px-12">
<d-card class="bg-[#ffffff80] h-24" v-for="(item, index) in navlist" :key="index"
@click="goExtra(item.menu_link)" @contextmenu.prevent="handdleContextMenu($event, item)">
<template #content>
@ -162,6 +169,9 @@ const contentStyle: any = ref({})
const navStyle: any = ref({})
const searchWord: any = ref('')
const broswer: any = ref('bing')
const searchItems: any = ref([])
const selecedIdx = ref(0)
const searchBox = ref(false)
const options = ref([
{
name: '必应',
@ -201,6 +211,67 @@ const tagList: any = ref([
const usrLog = $store.log.useLogStore()
let timer: any = null;
// 输入搜索内容时监听searchWord在navlist中模糊搜索
watch(searchWord, () => {
handdleInput()
})
function handdleInput() {
if (!searchWord.value) {
searchItems.value = []
searchBox.value = false
selecedIdx.value = 0
return
}
searchBox.value = true
selecedIdx.value = 0
const keyword = searchWord.value.toLowerCase()
searchItems.value = navlist.value.filter((item: any) =>
item.menu_name.toLowerCase().includes(keyword) ||
item.menu_link.toLowerCase().includes(keyword) ||
item.tag.toLowerCase().includes(keyword)
)
// 在searchItems第一个位置插入一条原本搜索
searchItems.value.unshift({
menu_name: `${getDictValue(options.value, "value", broswer.value, "name")}中搜索"${searchWord.value}"`,
menu_link: getDictValue(options.value, "value", broswer.value, "url") + searchWord.value,
tag: ''
})
}
function handdleKeyup(e: any) {
if (!searchBox.value) return
// console.log('>>> --> haddleDown --> idx:', e.keyCode)
// 向下箭头
if (e.keyCode == 40) {
if (selecedIdx.value < searchItems.value.length - 1) {
selecedIdx.value += 1
} else {
selecedIdx.value = 0
}
}
// 向上箭头
else if (e.keyCode == 38) {
if (selecedIdx.value > 0) {
selecedIdx.value -= 1
} else {
selecedIdx.value = searchItems.value.length - 1
}
}
// 回车键
else if (e.keyCode == 13) {
if (searchItems.value.length > 0) {
const selectedItem = searchItems.value[selecedIdx.value]
window.open(selectedItem.menu_link, "_BLANK")
searchBox.value = false
selecedIdx.value = 0
}
}
}
// 2秒后自动隐藏菜单
const hideMenu = () => {
timer = setTimeout(() => {
@ -443,7 +514,7 @@ onMounted(() => {
}
navStyle.value = {
// height: `calc(100vh - ${navcards.value.getBoundingClientRect().y}px - ${nav.navH}px)`,
height:`${window.innerHeight - navcards.value.getBoundingClientRect().y - 20}px`
height: `${window.innerHeight - navcards.value.getBoundingClientRect().y - 20}px`
}
tagList.value = [
{
@ -453,15 +524,17 @@ onMounted(() => {
}
]
getNavList()
window.addEventListener('resize', ()=>{
contentStyle.value = {
window.addEventListener('resize', () => {
contentStyle.value = {
height: `calc(100vh - ${nav.navH}px)`
}
navStyle.value = {
height:`${window.innerHeight - navcards.value.getBoundingClientRect().top - 20}px`
height: `${window.innerHeight - navcards.value.getBoundingClientRect().top - 20}px`
}
});
});
window.addEventListener('keyup', (e: Event) => {
handdleKeyup(e)
});
})
</script>