cwg-picker.vue 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. <template>
  2. <!-- 显示区域 -->
  3. <view class="filter-picker" @click="open" :class="{ disabled }">
  4. <view class="picker-value">
  5. <view class="picker-text">
  6. {{ currentLabel || placeholderText }}
  7. </view>
  8. <uni-icons type="down" size="14" color="#6b7280" />
  9. </view>
  10. </view>
  11. <!-- u-picker -->
  12. <!-- v-model="show" -->
  13. <u-picker v-if="show" :show="show" :cancelText="t('common.cancel')" :confirmText="t('common.confirm')"
  14. confirmColor="#ea002a" :columns="columns" keyName="label" :defaultIndex="defaultIndex" @confirm="onConfirm"
  15. @cancel="onCancel" />
  16. </template>
  17. <script setup lang="ts">
  18. import { computed, ref, watch } from 'vue'
  19. import { useI18n } from 'vue-i18n'
  20. type Option = {
  21. value: string | number | undefined
  22. label: string
  23. }
  24. const props = defineProps<{
  25. modelValue?: string | number | null
  26. options: Record<string, string> | Option[]
  27. placeholder?: string
  28. disabled?: boolean
  29. showAll?: boolean
  30. }>()
  31. const emit = defineEmits<{
  32. (e: 'update:modelValue', value: string | number | undefined): void
  33. (e: 'change', option: Option): void
  34. }>()
  35. const { t } = useI18n()
  36. const show = ref(false)
  37. const placeholderText = computed(() =>
  38. props.placeholder || t('common.select')
  39. )
  40. const optionList = computed<Option[]>(() => {
  41. let list: Option[] = []
  42. if (Array.isArray(props.options)) {
  43. list = props.options.map(i => ({
  44. value: i.value,
  45. label: i.label
  46. }))
  47. } else {
  48. list = Object.entries(props.options).map(([value, label]) => ({
  49. value: isNaN(Number(value)) ? value : Number(value),
  50. label:
  51. typeof label === 'string' && label.includes('.')
  52. ? t(label)
  53. : String(label)
  54. }))
  55. }
  56. if (props.showAll !== true) {
  57. list.unshift({
  58. value: undefined,
  59. label: props.placeholder || t('State.All')
  60. })
  61. }
  62. return list
  63. })
  64. const currentIndex = computed(() => {
  65. const index = optionList.value.findIndex(
  66. i => i.value === props.modelValue
  67. )
  68. return index === -1 ? 0 : index
  69. })
  70. const defaultIndex = computed(() => [currentIndex.value])
  71. const currentLabel = computed(() => {
  72. return optionList.value[currentIndex.value]?.label || ''
  73. })
  74. const columns = computed<Option[][]>(() => {
  75. return [optionList.value]
  76. })
  77. function open() {
  78. if (props.disabled) return
  79. show.value = true
  80. }
  81. function onConfirm(e: any) {
  82. const index = e.indexs[0]
  83. const selected = optionList.value[index]
  84. emit('update:modelValue', selected.value)
  85. emit('change', selected)
  86. show.value = false
  87. }
  88. function onCancel() {
  89. show.value = false
  90. }
  91. </script>