index.vue 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. <template>
  2. <el-tree-select :model-value="modelValue"
  3. :data="options"
  4. :clearable="clearable"
  5. :placeholder="placeholder"
  6. :disabled="disabled"
  7. :filterable="filterable"
  8. :node-key="optionProps.value"
  9. :style="{width}"
  10. :multiple="multiple"
  11. :props="optionProps"
  12. :check-strictly="checkStrictly"
  13. :expand-on-click-node="false"
  14. :current-node-key="modelValue"
  15. :default-expanded-keys="defaultExpandedKeys"
  16. @change="updateValue">
  17. </el-tree-select>
  18. </template>
  19. <script>
  20. import { ElTreeSelect } from 'element-plus'
  21. import { computed } from 'vue'
  22. import { useFormInput, useOptions } from '@cip/components/hooks/form-input'
  23. import { formInputProps, fromInputEmits } from '@cip/components/cip-form-input/form-input-props'
  24. import { isInputEmpty } from '@cip/utils/util'
  25. export default {
  26. components: { ElTreeSelect },
  27. props: formInputProps,
  28. emits: [...fromInputEmits],
  29. setup(props, context) {
  30. const {
  31. width,
  32. updateStream,
  33. proxyValue,
  34. securityConfig,
  35. ...formInput
  36. } = useFormInput(props, context)
  37. const { options, optionProps } = useOptions(props, false, updateStream)
  38. const filterable = computed(() => securityConfig.value.filterable ?? false)
  39. const multiple = computed(() => securityConfig.value.multiple ?? false)
  40. const checkStrictly = computed(() => securityConfig.value.checkStrictly ?? true)
  41. function genOptionsMap(options, preNode = null, map = {}) {
  42. for (const item of options) {
  43. map[item[optionProps.value.value]] = {
  44. origin: item,
  45. path: preNode ? [...map[preNode[optionProps.value.value]].path, item[optionProps.value.value]] : [item[optionProps.value.value]]
  46. }
  47. if (item[optionProps.value.children]?.length) {
  48. genOptionsMap(item[optionProps.value.children], item, map)
  49. }
  50. }
  51. return map
  52. }
  53. const modelValue = computed(() => {
  54. if (multiple.value) {
  55. return proxyValue.value?.length ? proxyValue.value.split(',') : []
  56. } else {
  57. return proxyValue.value
  58. }
  59. })
  60. const dataMap = computed(() => {
  61. return genOptionsMap(options.value)
  62. })
  63. const defaultExpandedKeys = computed(() => {
  64. if (multiple.value) {
  65. return modelValue.value.reduce((acc, val) => {
  66. acc.push(dataMap.value[val]?.path ?? [])
  67. return acc
  68. }, [])
  69. } else {
  70. return dataMap.value[modelValue.value]?.path ?? []
  71. }
  72. })
  73. const clearValue = () => {
  74. updateStream.appendValue(undefined)
  75. updateStream.appendOtherValue(undefined)
  76. updateStream.end()
  77. }
  78. const getNodeLabelFromDataMapByValue = (val) => {
  79. return dataMap.value[val].origin[optionProps.value.label] ?? ''
  80. }
  81. const updateValue = (val) => {
  82. if (isInputEmpty(val) || (multiple.value && !val.length)) {
  83. clearValue()
  84. return
  85. }
  86. const otherValue = multiple.value ? val.map(item => getNodeLabelFromDataMapByValue(item)).join(',') : getNodeLabelFromDataMapByValue(val)
  87. const modelValue = multiple.value ? val.join(',') : val
  88. updateStream.appendValue(modelValue)
  89. updateStream.appendOtherValue(otherValue)
  90. updateStream.end()
  91. }
  92. return {
  93. modelValue,
  94. checkStrictly,
  95. defaultExpandedKeys,
  96. ...formInput,
  97. proxyValue,
  98. options,
  99. width,
  100. optionProps,
  101. clearValue,
  102. multiple,
  103. filterable,
  104. updateValue
  105. }
  106. }
  107. }
  108. </script>
  109. <style lang="less" scope>
  110. .basic-select-tree {
  111. width: 100%;
  112. }
  113. .basic-select-tree-popper {
  114. .el-scrollbar .el-scrollbar__view .el-select-dropdown__item {
  115. height: auto;
  116. max-height: 274px;
  117. padding: 0;
  118. overflow: hidden;
  119. overflow-y: auto;
  120. }
  121. .el-select-dropdown__item.selected {
  122. font-weight: normal;
  123. }
  124. .el-tree-node__label {
  125. font-weight: normal;
  126. }
  127. }
  128. .select-tree-option {
  129. .el-tree-node__content {
  130. height: 32px;
  131. padding: 0 20px;
  132. }
  133. .is-current > .el-tree-node__content .el-tree-node__label {
  134. color: #409EFF;
  135. }
  136. }
  137. </style>