You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
132 lines
3.0 KiB
132 lines
3.0 KiB
<script lang="ts" setup>
|
|
import { ref } from 'vue'
|
|
import { debounce } from 'lodash-es'
|
|
import { asideMap } from '@/config/aside'
|
|
import type { SearchEntity } from '/#/home'
|
|
import { useConfig } from '@/store/modules/asideConfig'
|
|
|
|
defineOptions({ name: 'Search' })
|
|
|
|
const emit = defineEmits<{
|
|
(e: 'close'): void
|
|
(e: 'select', key: string): void
|
|
(e: 'inputChange', value: string): void
|
|
}>()
|
|
|
|
const data = ref<SearchEntity[]>([])
|
|
const popover = ref<ComponentRef | null>(null)
|
|
const configStore = useConfig()
|
|
const searchKeyword = ref('')
|
|
|
|
const inputHandler = debounce((keyword) => {
|
|
searchKeyword.value = keyword;
|
|
emit('inputChange',keyword)
|
|
}, 300)
|
|
|
|
configStore.$subscribe(() => {
|
|
const customConfig = configStore.getCustomConfig
|
|
|
|
if (customConfig == null)
|
|
return
|
|
|
|
const keys = customConfig ? [...customConfig] : []
|
|
|
|
if (keys.length === 0)
|
|
return
|
|
|
|
const list = keys.map((key) => {
|
|
const name = asideMap[key].label
|
|
|
|
return {
|
|
key,
|
|
label: name || '未配置',
|
|
}
|
|
})
|
|
|
|
data.value = list
|
|
})
|
|
|
|
function selectHandler(item: SearchEntity) {
|
|
(popover.value as any).setShow(false)
|
|
emit('select', item.key)
|
|
}
|
|
|
|
// 模糊搜索
|
|
const searchName = () => {
|
|
configStore.setSearchValue(searchKeyword.value);
|
|
}
|
|
|
|
const close = () => {
|
|
searchKeyword.value = "";
|
|
configStore.setSearchValue(searchKeyword.value);
|
|
emit('close');
|
|
}
|
|
|
|
</script>
|
|
|
|
<template>
|
|
<div class="wrapper">
|
|
<n-popover
|
|
ref="popover" :style="{ padding: '0px' }" style="width: 248px" :show-arrow="false" placement="bottom-start"
|
|
trigger="focus"
|
|
>
|
|
<template #trigger>
|
|
<n-input v-model:value="searchKeyword" style="width: 260px;height: 32px;" placeholder="请输入你需要搜索的内容" @input="inputHandler">
|
|
<template #suffix>
|
|
<SvgIcon size="14px" name="magnifying-1" @click="searchName" style="cursor: pointer;" />
|
|
</template>
|
|
</n-input>
|
|
</template>
|
|
<!-- <div class="wrapper-popover">
|
|
<ul class="wrapper-list">
|
|
<li v-for="(item, index) in data" v-show="item.label.includes(searchKeyword)" :key="index" @click="selectHandler(item)">
|
|
{{ item.label }}
|
|
</li>
|
|
</ul>
|
|
</div> -->
|
|
</n-popover>
|
|
|
|
<SvgIcon size="16px" style="margin-left: 6px;cursor: pointer;" name="clear" @click="close" />
|
|
</div>
|
|
</template>
|
|
|
|
<style lang="less" scoped>
|
|
.wrapper {
|
|
display: flex;
|
|
align-items: center;
|
|
|
|
&-popvoer {
|
|
background: #ffffff;
|
|
border-radius: 2px;
|
|
box-shadow: 0px 2px 8px 0px rgba(0, 0, 0, 0.15);
|
|
}
|
|
|
|
&-list {
|
|
border-top: 1px solid #eeeeee;
|
|
padding: 9px 0px;
|
|
height: 200px;
|
|
overflow-x: hidden;
|
|
overflow-y: auto;
|
|
scrollbar-width: none;
|
|
/* firefox */
|
|
-ms-overflow-style: none;
|
|
/* IE 10+ */
|
|
|
|
&::-webkit-scrollbar {
|
|
display: none;
|
|
}
|
|
|
|
li {
|
|
font-size: 14px;
|
|
line-height: 22px;
|
|
padding: 5px 12px;
|
|
|
|
&:hover {
|
|
background-color: #f3f8ff;
|
|
cursor: pointer;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|