This commit is contained in:
huangchenhao 2026-04-07 16:29:40 +08:00
commit 3e7c9dd1af
2 changed files with 143 additions and 0 deletions

View File

@ -0,0 +1,139 @@
<template>
<div class="base-picker">
<!-- 使用 van-field 作为展示区域 -->
<van-field
:modelValue="displayValue"
:label="label"
:placeholder="placeholder"
:disabled="disabled"
:readonly="true"
:right-icon="rightIcon"
:clickable="!disabled"
@click="openPicker"
/>
<!-- 弹出层选择器 -->
<van-popup v-model:show="showPicker" position="bottom" round>
<van-picker
:columns="columns"
:title="pickerTitle"
:loading="loading"
show-toolbar
@confirm="onConfirm"
@cancel="showPicker = false"
/>
</van-popup>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
import { Field, Popup, Picker } from 'vant'
// Props
const props = defineProps({
// (v-model)
modelValue: {
type: [String, Number],
default: null
},
// [{ label: '', value: '' }]
options: {
type: Array,
required: true,
default: () => []
},
//
label: {
type: String,
default: ''
},
//
placeholder: {
type: String,
default: '请选择'
},
//
disabled: {
type: Boolean,
default: false
},
// Picker
pickerTitle: {
type: String,
default: '请选择'
},
//
loading: {
type: Boolean,
default: false
},
//
rightIcon: {
type: String,
default: 'arrow-down'
},
// label
labelKey: {
type: String,
default: 'label'
},
// value
valueKey: {
type: String,
default: 'value'
}
})
// Emits
const emit = defineEmits(['update:modelValue', 'change'])
//
const showPicker = ref(false)
// Picker options Picker
const columns = computed(() => {
return props.options.map(item => {
return {
text: item[props.labelKey],
value: item[props.valueKey]
}
})
})
//
const displayValue = computed(() => {
if (props.modelValue === null || props.modelValue === undefined || props.modelValue === '') {
return ''
}
const selected = props.options.find(item => item[props.valueKey] === props.modelValue)
return selected ? selected[props.labelKey] : ''
})
//
const openPicker = () => {
if (!props.disabled) {
showPicker.value = true
}
}
//
const onConfirm = ({ selectedValues, selectedOptions }) => {
const value = selectedOptions[0][props.valueKey]
const label = selectedOptions[0][props.labelKey]
emit('update:modelValue', value)
emit('change', { value, label })
showPicker.value = false
}
</script>
<style scoped>
.base-picker {
width: 100%;
}
/* 可选:调整 Field 的只读样式 */
:deep(.van-field__control--readonly) {
cursor: pointer;
}
</style>

View File

@ -30,6 +30,10 @@ const props = defineProps({
padding: 20px;
background-color: #fff;
border-radius: 8px;
& + .panel-item {
margin-top: 10px;
}
}
.header {
display: flex;