139 lines
2.9 KiB
Vue
139 lines
2.9 KiB
Vue
|
|
<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>
|