VbSelect.vue 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. <script setup lang="ts">
  2. const props = withDefaults(
  3. defineProps<{
  4. modelValue?: any
  5. id?: string //id变化后重新加载树
  6. data?: any
  7. dataFun?: () => Promise<any>
  8. url?: string
  9. method?: string
  10. config?: any
  11. props?: {
  12. label?: string
  13. value?: string
  14. class?: string
  15. style?: string
  16. disabled?: string | ((v?: any) => boolean)
  17. }
  18. dataMapFun?: (v: any) => {
  19. label: string
  20. value: string
  21. class?: string
  22. style?: string
  23. disabled?: boolean
  24. }
  25. needFormate?: boolean
  26. placeholder?: string
  27. listeners?: any
  28. type?: "select" | "checkbox" | "radio"
  29. }>(),
  30. {
  31. placeholder: "请选择",
  32. type: "select",
  33. method: "get",
  34. needFormate: true,
  35. }
  36. )
  37. const emits = defineEmits<{
  38. (e: "update:modelValue", v: any): void
  39. (e: "change", v: any): any
  40. }>()
  41. const { modelValue } = toRefs(props)
  42. const _data = ref<any>([])
  43. const options = computed(() => {
  44. if (props.dataFun || props.url) {
  45. return _data.value
  46. }
  47. formatData(typeof props.data == "function" ? props.data() : props.data)
  48. return _data.value
  49. })
  50. function onChange(v: any) {
  51. emits("update:modelValue", v)
  52. emits("change", v)
  53. return v
  54. }
  55. function onChange2(v: Array<any>) {
  56. emits("update:modelValue", v)
  57. emits("change", v)
  58. return v
  59. }
  60. function formatData(data: Array<any>) {
  61. if (!props.needFormate) {
  62. _data.value = data
  63. } else {
  64. if (props.dataMapFun) {
  65. _data.value =
  66. data?.map((v: any) => {
  67. return props.dataMapFun ? props.dataMapFun(v) : v
  68. }) || []
  69. } else if (props.props) {
  70. _data.value =
  71. data?.map((v: any) => {
  72. return {
  73. label: v[props.props?.label ?? "label"],
  74. value: v[props.props?.value ?? "value"],
  75. class: v[props.props?.class ?? "class"],
  76. style: v[props.props?.style ?? "style"],
  77. disabled:
  78. typeof props.props?.disabled == "function"
  79. ? props.props?.disabled(v)
  80. : v[props.props?.disabled ?? "disabled"],
  81. }
  82. }) || []
  83. } else {
  84. _data.value = data
  85. }
  86. }
  87. }
  88. function load() {
  89. if (props.dataFun) {
  90. props.dataFun().then((res) => {
  91. formatData(res.data || res)
  92. })
  93. } else if (props.url) {
  94. const opts = Object.assign({}, { method: props.method }, props.config || {})
  95. RequestService.request(opts).then((res) => {
  96. formatData(res.data)
  97. })
  98. } else {
  99. formatData(typeof props.data == "function" ? props.data() : props.data)
  100. }
  101. }
  102. function init() {
  103. load()
  104. }
  105. watch(() => props.id, init)
  106. onMounted(() => {
  107. init()
  108. })
  109. </script>
  110. <template>
  111. <template v-if="type == 'checkbox'">
  112. <el-checkbox-group
  113. :id="id"
  114. v-model="modelValue"
  115. :placeholder="placeholder"
  116. @change="onChange2"
  117. v-bind="$attrs"
  118. v-on="listeners"
  119. >
  120. <el-checkbox
  121. v-for="(v, i) in options"
  122. :label="v.value"
  123. :key="i"
  124. :class="v.class"
  125. :style="v.style"
  126. :disabled="v.disabled"
  127. >
  128. {{ v.label }}
  129. </el-checkbox>
  130. </el-checkbox-group>
  131. </template>
  132. <template v-else-if="type == 'radio'">
  133. <el-radio-group
  134. :id="id"
  135. v-model="modelValue"
  136. :placeholder="placeholder"
  137. @change="onChange"
  138. v-bind="$attrs"
  139. v-on="listeners"
  140. >
  141. <el-radio
  142. v-for="(v, i) in options"
  143. :label="v.value"
  144. :key="i"
  145. :class="v.class"
  146. :style="v.style"
  147. :disabled="v.disabled"
  148. >
  149. {{ v.label }}
  150. </el-radio>
  151. </el-radio-group>
  152. </template>
  153. <template v-else>
  154. <el-select
  155. v-model="modelValue"
  156. :id="id"
  157. :placeholder="placeholder"
  158. @change="onChange"
  159. v-bind="$attrs"
  160. v-on="listeners"
  161. >
  162. <el-option
  163. v-for="(v, i) in options"
  164. :label="v.label"
  165. :value="v.value"
  166. :key="i"
  167. :class="v.class"
  168. :style="v.style"
  169. :disabled="v.disabled"
  170. ></el-option>
  171. </el-select>
  172. </template>
  173. </template>
  174. <style lang="scss" scoped>
  175. :deep(.el-select-dropdown__list) {
  176. .el-select-dropdown__item {
  177. &.hover {
  178. color: var(--bs-primary);
  179. background: var(--bs-primary-light);
  180. }
  181. }
  182. }
  183. </style>