feat: 下拉组件
This commit is contained in:
parent
c6c8a02535
commit
d578797f5b
139
packages/mobile/src/components/BasePicker.vue
Normal file
139
packages/mobile/src/components/BasePicker.vue
Normal 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>
|
||||
Loading…
x
Reference in New Issue
Block a user