BaseSelect.vue 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. <template>
  2. <el-select class="custom-select" @change="selChange" @clear="selClear">
  3. <el-option-group
  4. v-for="(group, index) in renderOptions.groups"
  5. :key="'group-' + index"
  6. v-bind="omit(group, ['options'])"
  7. >
  8. <el-option
  9. v-for="(option, OIndex) in group.options"
  10. :key="'group-' + index + '-option-' + OIndex"
  11. v-bind="omit(option, 'groupKey')"
  12. ></el-option>
  13. </el-option-group>
  14. <el-option
  15. v-for="(option, OIndex) in renderOptions.default"
  16. :key="'group-default' + '-option-' + OIndex"
  17. v-bind="omit(option, 'groupKey')"
  18. ></el-option>
  19. </el-select>
  20. </template>
  21. <script setup lang="ts" name="EpSelect">
  22. import { computed } from 'vue'
  23. import { ElSelect, ElOption, ElOptionGroup } from 'element-plus'
  24. import { omit } from 'lodash-es'
  25. import type { FormItemSelectCustomProp } from 'global-type'
  26. interface SelectProp {
  27. optionGroup?: Required<FormItemSelectCustomProp>['optionGroup']
  28. options?: Required<FormItemSelectCustomProp>['options']
  29. }
  30. const emits = defineEmits(['change', 'clear'])
  31. const props = defineProps<SelectProp>()
  32. type OptionGroup = ExtractRecordValue<SelectProp['optionGroup']> & { options: SelectProp['options'] }
  33. type OptionRender = { default: SelectProp['options']; groups: Record<string | number, OptionGroup> }
  34. const renderOptions = computed<OptionRender>(() => {
  35. const groups = props.options?.reduce(
  36. (result, option, index) => {
  37. if (option.groupKey) {
  38. if (!result.groups[option.groupKey]) {
  39. result.groups[option.groupKey] = { ...props.optionGroup?.[option.groupKey], options: [] }
  40. }
  41. result.groups[option.groupKey]?.options?.push(option)
  42. } else {
  43. result.default ??= []
  44. result.default.push(option)
  45. }
  46. return result
  47. },
  48. { default: [], groups: {} } as OptionRender
  49. )
  50. return groups || { default: [], groups: {} }
  51. })
  52. const selChange = (index: any) => {
  53. emits('change', index)
  54. }
  55. const selClear = () => {
  56. emits('clear')
  57. }
  58. </script>
  59. <style scoped lang="scss">
  60. .custom-select {
  61. // ElSelect Bug: select 中 input高度被硬编码在代码中,它会使用element-plus中定义的常量component-size-map, 而不是sass变量 $common-component-size。
  62. // 目前的修改方式有两个:
  63. // 1. 设置props: collapse-tags = true & filterable = false
  64. // 2. 使用 !important 强制覆盖.
  65. // 为了不过度限制组件功能, 当前使用 css !important. (在组件用到多选tag功能时可能样式异常)
  66. :deep(.el-input__inner) {
  67. height: var(--el-input-inner-height) !important;
  68. line-height: var(--el-input-inner-height) !important;
  69. }
  70. }
  71. </style>