index.vue 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. <template>
  2. <el-select v-model="proxyValue"
  3. class="basic-select-tree"
  4. ref="selectTreeInputRef"
  5. :clearable="clearable"
  6. :placeholder="placeholder"
  7. :disabled="disabled"
  8. :style="{width}"
  9. @clear="clearValue"
  10. popper-class="basic-select-tree-popper">
  11. <el-option :label="selectOption.label" :value="selectOption.value">
  12. <el-tree class="select-tree-option"
  13. :key="optionProps.value"
  14. ref="selectTreeRef"
  15. :data="options"
  16. :props="optionProps"
  17. :node-key="optionProps.value"
  18. :default-expanded-keys="defaultExpandedKeys"
  19. :current-node-key="modelValue"
  20. :expand-on-click-node="false"
  21. @node-click="handleNodeClick">
  22. </el-tree>
  23. </el-option>
  24. </el-select>
  25. </template>
  26. <script>
  27. import { ElSelect, ElOption, ElTree } from 'element-plus'
  28. import { ref, watchEffect } from 'vue'
  29. import { useFormInput, useOptions } from '@cip/components/hooks/form-input'
  30. import { formInputProps, fromInputEmits } from '../../form-input-props'
  31. import { isArray, isNumber } from '@cip/utils/util'
  32. export default {
  33. components: { ElSelect, ElOption, ElTree },
  34. props: formInputProps,
  35. emits: [...fromInputEmits],
  36. setup (props, context) {
  37. const { width, updateStream, proxyValue, securityConfig, emitModelValue, emitOtherValue, ...formInput } = useFormInput(props, context)
  38. const { options, optionProps } = useOptions(props, false, updateStream)
  39. const defaultExpandedKeys = ref([])
  40. const selectOption = ref({ label: '', value: '' })
  41. const selectTreeInputRef = ref()
  42. const selectTreeRef = ref()
  43. // WARN: 移除了对securityConfig.value.treeProps的支持
  44. // tree组件配置
  45. // const treeProps = computed(() => {
  46. // return Object.assign({}, defaultProps, securityConfig.value?.treeProps, securityConfig.value?.optionProps)
  47. // })
  48. const formatOption = (data) => {
  49. const option = {}
  50. const keys = optionProps.value
  51. option.label = data[keys.label]
  52. option.value = data[keys.value]
  53. option.children = data[keys.children]
  54. return option
  55. }
  56. const findActiveOption = (treeData = []) => {
  57. const modelValue = props.modelValue
  58. for (let i = 0; i < treeData.length; i++) {
  59. const option = formatOption(treeData[i])
  60. if (option.value === modelValue) {
  61. selectOption.value = option
  62. return true
  63. }
  64. if (option.children?.length > 0) {
  65. const result = findActiveOption(option.children, modelValue)
  66. if (result) {
  67. defaultExpandedKeys.value.push(option.value)
  68. return result
  69. }
  70. }
  71. }
  72. }
  73. watchEffect(() => {
  74. const treeData = options.value
  75. defaultExpandedKeys.value = []
  76. findActiveOption(treeData)
  77. })
  78. // 切换选项
  79. const handleNodeClick = (data, node, treeInstance) => {
  80. const { isLeaf, level } = node
  81. // selectLevel是配置可选中层级,配置时注意需要配置成number类型
  82. if (securityConfig.value.selectLevel) {
  83. if (isNumber(securityConfig.value.selectLevel) && securityConfig.value.selectLevel !== level) return
  84. if (isArray(securityConfig.value.selectLevel) && !securityConfig.value.selectLevel.includes(level)) return
  85. }
  86. if (!securityConfig.value.leafOnly || (securityConfig.value.leafOnly && isLeaf)) {
  87. selectOption.value.label = data[optionProps.value.label]
  88. selectOption.value.value = data[optionProps.value.value]
  89. updateStream.appendValue(selectOption.value.value)
  90. updateStream.appendOtherValue(selectOption.value.label)
  91. updateStream.end()
  92. defaultExpandedKeys.value = []
  93. // 选中时收回下拉框
  94. selectTreeInputRef.value.blur()
  95. } else {
  96. selectTreeRef.value.setCurrentKey(props.modelValue)
  97. }
  98. }
  99. const clearValue = () => {
  100. updateStream.appendValue(undefined)
  101. updateStream.appendOtherValue(undefined)
  102. updateStream.end()
  103. }
  104. return {
  105. ...formInput,
  106. proxyValue,
  107. selectTreeInputRef,
  108. options,
  109. defaultExpandedKeys,
  110. width,
  111. selectTreeRef,
  112. optionProps,
  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>