121 lines
2.5 KiB
Vue
121 lines
2.5 KiB
Vue
<template>
|
|
<db-popup :show="show" height="70vh" @close="close" @update:show="(v) => emit('update:show', v)">
|
|
<view class="picker">
|
|
<view class="picker__search">
|
|
<db-search
|
|
v-model="keyword"
|
|
placeholder="搜索产品名称"
|
|
@change="onKeyword"
|
|
@search="load"
|
|
@clear="onClear"
|
|
/>
|
|
</view>
|
|
<scroll-view scroll-y class="picker__list">
|
|
<view
|
|
v-for="item in options"
|
|
:key="item.id"
|
|
class="picker__cell"
|
|
@click="onSelect(item)"
|
|
>
|
|
<text class="picker__title">{{ item.productName }}</text>
|
|
<text v-if="meta(item)" class="picker__label">{{ meta(item) }}</text>
|
|
</view>
|
|
<view v-if="!loading && !options.length" class="db-empty">暂无匹配</view>
|
|
</scroll-view>
|
|
</view>
|
|
</db-popup>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, watch } from 'vue'
|
|
import { fetchProductOptions } from '@/api/dbOptions'
|
|
import DbPopup from '@/components/db-ui/db-popup.vue'
|
|
import DbSearch from '@/components/db-ui/db-search.vue'
|
|
|
|
const props = defineProps({ show: Boolean })
|
|
const emit = defineEmits(['update:show', 'select'])
|
|
|
|
const keyword = ref('')
|
|
const loading = ref(false)
|
|
const options = ref([])
|
|
let timer = null
|
|
|
|
watch(
|
|
() => props.show,
|
|
(v) => {
|
|
if (v) {
|
|
keyword.value = ''
|
|
load()
|
|
}
|
|
}
|
|
)
|
|
|
|
function close() {
|
|
emit('update:show', false)
|
|
}
|
|
function onClear() {
|
|
keyword.value = ''
|
|
load()
|
|
}
|
|
function onKeyword() {
|
|
if (timer) clearTimeout(timer)
|
|
timer = setTimeout(load, 300)
|
|
}
|
|
function meta(item) {
|
|
const parts = []
|
|
if (item.model?.trim()) parts.push(item.model.trim())
|
|
if (item.status === 'off') parts.push('已下架')
|
|
return parts.join(' · ')
|
|
}
|
|
async function load() {
|
|
loading.value = true
|
|
try {
|
|
options.value = await fetchProductOptions(keyword.value)
|
|
} catch (e) {
|
|
options.value = []
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
function onSelect(item) {
|
|
emit('select', item)
|
|
close()
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.picker {
|
|
display: flex;
|
|
flex-direction: column;
|
|
height: 70vh;
|
|
}
|
|
.picker__search {
|
|
padding: 12px;
|
|
}
|
|
.picker__list {
|
|
flex: 1;
|
|
height: 0;
|
|
}
|
|
.picker__cell {
|
|
padding: 14px 16px;
|
|
border-bottom: 1px solid #f5f6f8;
|
|
}
|
|
.picker__title {
|
|
display: block;
|
|
font-size: 15px;
|
|
color: #323233;
|
|
}
|
|
.picker__label {
|
|
display: block;
|
|
margin-top: 4px;
|
|
font-size: 12px;
|
|
color: #969799;
|
|
}
|
|
.db-empty {
|
|
padding: 40px;
|
|
text-align: center;
|
|
color: #969799;
|
|
font-size: 14px;
|
|
}
|
|
</style>
|