index.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. <template>
  2. <el-select :model-value="modelValue"
  3. @update:modelValue="emitSelect"
  4. class="basic-select-tree"
  5. ref="selectTreeRef"
  6. :clearable="clearable"
  7. :placeholder="placeholder"
  8. :disabled="disabled"
  9. :style="{width}"
  10. @clear="clearValue"
  11. popper-class="basic-select-tree-popper">
  12. <el-option :label="selectOption.label" :value="selectOption.value">
  13. <el-tree class="select-tree-option"
  14. :key="treeProps.value"
  15. ref="selectTree"
  16. :data="options"
  17. :props="treeProps"
  18. :node-key="treeProps.value"
  19. :default-expanded-keys="defaultExpandedKeys"
  20. :current-node-key="modelValue"
  21. :expand-on-click-node="false"
  22. @node-click="handleNodeClick">
  23. </el-tree>
  24. </el-option>
  25. </el-select>
  26. </template>
  27. <script>
  28. import { ElSelect, ElOption, ElTree } from 'element-plus'
  29. import { computed, ref, watchEffect } from 'vue'
  30. import { useFormInput, useOptions } from '@cip/components/hooks/form-input'
  31. import { formInputProps } from '../../form-input-props'
  32. export default {
  33. components: { ElSelect, ElOption, ElTree },
  34. props: formInputProps,
  35. emits: ['update:modelValue', 'update:otherValue'],
  36. setup (props, context) {
  37. const { width, ...formInput } = useFormInput(props, context)
  38. const { options } = useOptions(props, false, formInput.emitInput)
  39. const defaultExpandedKeys = ref([])
  40. const selectOption = ref({ label: '', value: '' })
  41. const selectTreeRef = ref()
  42. const emitSelect = (val) => {
  43. context.emit('update:modelValue', val)
  44. }
  45. const defaultProps = {
  46. value: 'value',
  47. label: 'label',
  48. children: 'children'
  49. }
  50. // tree组件配置
  51. const treeProps = computed(() => {
  52. return Object.assign({}, defaultProps, props.config?.treeProps, props.config?.optionProps)
  53. })
  54. const selectTree = ref()
  55. const formatOption = (data) => {
  56. const option = {}
  57. const keys = treeProps.value
  58. option.label = data[keys.label]
  59. option.value = data[keys.value]
  60. option.children = data[keys.children]
  61. return option
  62. }
  63. const findActiveOption = (treeData = []) => {
  64. const modelValue = props.modelValue
  65. for (let i = 0; i < treeData.length; i++) {
  66. const option = formatOption(treeData[i])
  67. if (option.value === modelValue) {
  68. selectOption.value = option
  69. return true
  70. }
  71. if (option.children?.length > 0) {
  72. const result = findActiveOption(option.children, modelValue)
  73. if (result) {
  74. defaultExpandedKeys.value.push(option.value)
  75. return result
  76. }
  77. }
  78. }
  79. }
  80. watchEffect(() => {
  81. const treeData = options.value
  82. defaultExpandedKeys.value = []
  83. findActiveOption(treeData)
  84. })
  85. // 切换选项
  86. const handleNodeClick = (data, node, treeInstance) => {
  87. const { isLeaf } = node
  88. if (!props.config.leafOnly || (props.config.leafOnly && isLeaf)) {
  89. selectOption.value.label = data[treeProps.value.label]
  90. selectOption.value.value = data[treeProps.value.value]
  91. context.emit('update:modelValue', selectOption.value.value)
  92. context.emit('update:otherValue', selectOption.value.label)
  93. defaultExpandedKeys.value = []
  94. // 选中时收回下拉框
  95. selectTreeRef.value.blur()
  96. } else {
  97. selectTree.value.setCurrentKey(props.modelValue)
  98. }
  99. }
  100. const clearValue = () => {
  101. formInput.emitModelValue(undefined)
  102. formInput.emitOtherValue(undefined)
  103. }
  104. return {
  105. ...formInput,
  106. selectTreeRef,
  107. emitSelect,
  108. options,
  109. defaultExpandedKeys,
  110. width,
  111. selectTree,
  112. treeProps,
  113. handleNodeClick,
  114. selectOption,
  115. clearValue
  116. }
  117. }
  118. }
  119. </script>
  120. <style lang="less" scope>
  121. .basic-select-tree{
  122. width: 100%;
  123. }
  124. .basic-select-tree-popper{
  125. .el-scrollbar .el-scrollbar__view .el-select-dropdown__item{
  126. height: auto;
  127. max-height: 274px;
  128. padding: 0;
  129. overflow: hidden;
  130. overflow-y: auto;
  131. }
  132. .el-select-dropdown__item.selected{
  133. font-weight: normal;
  134. }
  135. .el-tree-node__label{
  136. font-weight: normal;
  137. }
  138. }
  139. .select-tree-option {
  140. .el-tree-node__content{
  141. height: 32px;
  142. padding: 0 20px;
  143. }
  144. .is-current>.el-tree-node__content .el-tree-node__label{
  145. color: #409EFF;
  146. }
  147. }
  148. </style>