feat: add search

This commit is contained in:
tim
2025-07-08 20:06:17 +08:00
parent a6b0ef4290
commit c917d01b78
2 changed files with 31 additions and 32 deletions

View File

@@ -38,8 +38,8 @@
<i class="fas fa-caret-down dropdown-caret"></i> <i class="fas fa-caret-down dropdown-caret"></i>
</slot> </slot>
</div> </div>
<div v-if="open" :class="['dropdown-menu', menuClass]"> <div v-if="open && (loading || filteredOptions.length > 0)" :class="['dropdown-menu', menuClass]">
<div class="dropdown-search"> <div v-if="showSearch" class="dropdown-search">
<i class="fas fa-search search-icon"></i> <i class="fas fa-search search-icon"></i>
<input type="text" v-model="search" placeholder="搜索" /> <input type="text" v-model="search" placeholder="搜索" />
</div> </div>
@@ -76,7 +76,8 @@ export default {
fetchOptions: { type: Function, required: true }, fetchOptions: { type: Function, required: true },
remote: { type: Boolean, default: false }, remote: { type: Boolean, default: false },
menuClass: { type: String, default: '' }, menuClass: { type: String, default: '' },
optionClass: { type: String, default: '' } optionClass: { type: String, default: '' },
showSearch: { type: Boolean, default: true }
}, },
emits: ['update:modelValue'], emits: ['update:modelValue'],
setup(props, { emit }) { setup(props, { emit }) {
@@ -204,7 +205,7 @@ export default {
<style scoped> <style scoped>
.dropdown { .dropdown {
position: relative; position: relative;
width: 200px; min-width: 200px;
} }
.dropdown-display { .dropdown-display {

View File

@@ -1,28 +1,19 @@
<template> <template>
<Dropdown <div class="search-dropdown">
v-model="selected" <Dropdown v-model="selected" :fetch-options="fetchResults" remote menu-class="search-menu"
:fetch-options="fetchResults" option-class="search-option" :show-search="false">
remote <template #display="{ toggle, setSearch }">
menu-class="search-menu" <div class="search-input" @click="toggle">
option-class="search-option" <i class="search-input-icon fas fa-search"></i>
> <input type="text" v-model="keyword" placeholder="Search" @focus="toggle" @input="setSearch(keyword)" />
<template #display="{ toggle, setSearch }"> </div>
<div class="search-input" @click="toggle"> </template>
<i class="search-input-icon fas fa-search"></i> <template #option="{ option }">
<input <i :class="['result-icon', iconMap[option.type] || 'fas fa-question']"></i>
type="text" <span v-html="highlight(option.text)"></span>
v-model="keyword" </template>
placeholder="Search" </Dropdown>
@focus="toggle" </div>
@input="setSearch(keyword)"
/>
</div>
</template>
<template #option="{ option }">
<i :class="['result-icon', iconMap[option.type] || 'fas fa-question']"></i>
<span v-html="highlight(option.text)"></span>
</template>
</Dropdown>
</template> </template>
<script> <script>
@@ -63,15 +54,18 @@ export default {
</script> </script>
<style scoped> <style scoped>
.search-dropdown {
margin-top: 20px;
width: 500px;
}
.search-input { .search-input {
padding: 10px;
display: flex; display: flex;
align-items: center; align-items: center;
border: 1px solid lightgray;
border-radius: 10px;
padding: 10px;
width: 100%; width: 100%;
max-width: 600px;
} }
.search-input input { .search-input input {
border: none; border: none;
outline: none; outline: none;
@@ -79,19 +73,23 @@ export default {
margin-left: 10px; margin-left: 10px;
font-size: 16px; font-size: 16px;
} }
.search-menu { .search-menu {
width: 100%; width: 100%;
max-width: 600px; max-width: 600px;
} }
.search-option { .search-option {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 10px; gap: 10px;
padding: 10px 20px; padding: 10px 20px;
} }
.highlight { .highlight {
color: var(--primary-color); color: var(--primary-color);
} }
.result-icon { .result-icon {
opacity: 0.6; opacity: 0.6;
} }