pullDownSelector.vue 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. <template>
  2. <div class="w-full h-full flex flex-col">
  3. <div class="w-full pt-2">
  4. <van-search
  5. v-model.trim="searchForValue"
  6. shape="round"
  7. placeholder="请输入搜索关键词"
  8. @update:model-value="debouncedSearchOptions"
  9. />
  10. </div>
  11. <div class="flex-1 my-2 overflow-y-auto">
  12. <template v-if="!multipleChoice">
  13. <!-- 单选 -->
  14. <van-radio-group v-model="selectChecked">
  15. <template v-for="item in renderingOptions">
  16. <van-cell-group inset>
  17. <van-cell clickable @click="selectChecked = item.value">
  18. <template #right-icon>
  19. <van-radio :name="item.value" />
  20. </template>
  21. <template #title>
  22. {{ item.label }}
  23. </template>
  24. </van-cell>
  25. </van-cell-group>
  26. </template>
  27. </van-radio-group>
  28. </template>
  29. <!-- 多选 -->
  30. <template v-if="multipleChoice">
  31. <van-checkbox-group v-model="selectChecked">
  32. <van-cell-group inset>
  33. <van-cell
  34. v-for="(item, index) in renderingOptions"
  35. clickable
  36. :key="index"
  37. @click="toggle(index)"
  38. >
  39. <template #right-icon>
  40. <van-checkbox
  41. :name="item.value"
  42. :ref="(el) => (checkboxRefs[index] = el)"
  43. @click.stop
  44. />
  45. </template>
  46. <template #title>
  47. {{ item.label }}
  48. </template>
  49. </van-cell>
  50. </van-cell-group>
  51. </van-checkbox-group>
  52. </template>
  53. </div>
  54. <div class="w-full pb-2 px-4">
  55. <van-button
  56. type="primary"
  57. round
  58. class="w-full"
  59. :disabled="!selectChecked"
  60. @click="confirmClick"
  61. >确定</van-button
  62. >
  63. </div>
  64. </div>
  65. </template>
  66. <script setup>
  67. import { ref, onBeforeUpdate, reactive, watch, onMounted } from "vue";
  68. import { manualCopying, useDebounce } from "@hooks/useCommon"
  69. const props = defineProps({
  70. options: {
  71. type: Array,
  72. required: true,
  73. default: () => [],
  74. },
  75. value: {
  76. type: [String, Array],
  77. default: () => null
  78. },
  79. multipleChoice: {
  80. type: Boolean,
  81. default: () => true,
  82. },
  83. });
  84. const emit = defineEmits(['change'])
  85. const selectChecked = ref();
  86. const checkboxRefs = ref([]);
  87. const searchForValue = ref("");
  88. const allOptions = ref([])
  89. const renderingOptions = ref([])
  90. const debouncedSearchOptions = useDebounce(searchOptions, 500);
  91. function searchOptions(val) {
  92. if(!val) {
  93. renderingOptions.value = manualCopying(allOptions.value)
  94. return
  95. }
  96. const list = manualCopying(allOptions.value)
  97. renderingOptions.value = list.filter(item => item.label.indexOf(val) > -1)
  98. }
  99. function toggle(index) {
  100. checkboxRefs.value[index].toggle();
  101. }
  102. function valueTaking(val) {
  103. if(Array.isArray(val)) {
  104. return allOptions.value.filter(item => val.includes(item.value)).map(item => item.label)
  105. } else {
  106. return allOptions.value.find(item => item.value === val)?.label
  107. }
  108. }
  109. function confirmClick() {
  110. emit('change', selectChecked.value, valueTaking(selectChecked.value))
  111. }
  112. onBeforeUpdate(() => {
  113. checkboxRefs.value = [];
  114. });
  115. onMounted(() => {
  116. selectChecked.value = props.multipleChoice ? [] : "";
  117. renderingOptions.value = manualCopying(props.options)
  118. allOptions.value = manualCopying(props.options)
  119. });
  120. </script>