index.vue 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. <template>
  2. <div class="app-select">
  3. <Field ref="fieldRef" :name="name" :rules="rules" @click="showPicker = true" :is-link="isLink">
  4. <template #label>
  5. <slot name="label">
  6. {{ label }}
  7. </slot>
  8. </template>
  9. <template #input>
  10. <slot name="input">
  11. <input :value="columnLabel" :placeholder="placeholder" readonly />
  12. </slot>
  13. </template>
  14. </Field>
  15. <Popup v-model:show="showPicker" position="bottom" teleport="body">
  16. <Picker :columns="columns" @cancel="onCancel" @confirm="onConfirm" />
  17. </Popup>
  18. </div>
  19. </template>
  20. <script lang="ts" setup>
  21. import { shallowRef, computed, PropType } from 'vue'
  22. import { Field, FieldRule, Popup, Picker, PickerOption, FieldInstance } from 'vant'
  23. const props = defineProps({
  24. modelValue: {
  25. type: [Number, String]
  26. },
  27. options: {
  28. type: Array,
  29. default: () => ([])
  30. },
  31. optionProps: {
  32. type: Object as PropType<{ label?: string; value?: string; }>,
  33. default: () => ({
  34. label: 'label',
  35. value: 'value'
  36. })
  37. },
  38. rules: {
  39. type: Array as PropType<FieldRule[]>
  40. },
  41. name: String,
  42. label: String,
  43. placeholder: {
  44. type: String,
  45. default: '请选择'
  46. },
  47. isLink: {
  48. type: Boolean,
  49. default: true
  50. }
  51. })
  52. const emit = defineEmits(['update:show', 'update:modelValue', 'confirm', 'cancel'])
  53. const fieldRef = shallowRef<FieldInstance>()
  54. const showPicker = shallowRef(false) // 是否弹出选择器
  55. const selectedIndex = shallowRef(-1)
  56. const columns = computed(() => {
  57. if (props.options) {
  58. return props.options.map((e) => e[props.optionProps.label])
  59. }
  60. return []
  61. })
  62. // 当前显示的标签
  63. const columnLabel = computed(() => {
  64. const item = props.options[selectedIndex.value]
  65. if (item) {
  66. return item[props.optionProps.label] ?? ''
  67. }
  68. return ''
  69. })
  70. // 更新当前选中的值
  71. const updateValue = (index: number) => {
  72. const item = props.options[index]
  73. const value = item[props.optionProps.value]
  74. selectedIndex.value = index
  75. fieldRef.value?.validate()
  76. emit('update:modelValue', value)
  77. }
  78. const onCancel = (currentValue: PickerOption, currentIndex: number) => {
  79. showPicker.value = false
  80. emit('cancel', currentValue, currentIndex)
  81. }
  82. const onConfirm = (currentValue: PickerOption, currentIndex: number) => {
  83. showPicker.value = false
  84. updateValue(currentIndex)
  85. emit('confirm', currentValue, currentIndex)
  86. }
  87. </script>
  88. <style lang="less" scoped>
  89. @import './index.less';
  90. </style>