index.vue 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. <script setup lang="ts">
  2. import { ElTreeSelect } from 'element-plus'
  3. const props = defineProps({
  4. /* 配置项 */
  5. objMap: {
  6. type: Object,
  7. default: () => {
  8. return {
  9. value: 'id', // ID字段名
  10. label: 'label', // 显示名称
  11. children: 'children' // 子级字段名
  12. }
  13. }
  14. },
  15. /* 自动收起 */
  16. accordion: {
  17. type: Boolean,
  18. default: () => {
  19. return false
  20. }
  21. },
  22. /**当前双向数据绑定的值 */
  23. value: {
  24. type: [String, Number],
  25. default: ''
  26. },
  27. /**当前的数据 */
  28. options: {
  29. type: Array,
  30. default: () => []
  31. },
  32. /**输入框内部的文字 */
  33. placeholder: {
  34. type: String,
  35. default: ''
  36. }
  37. })
  38. const selectTree = ref(ElTreeSelect);
  39. const emit = defineEmits(['update:value']);
  40. const valueId = computed({
  41. get: () => props.value,
  42. set: (val) => {
  43. emit('update:value', val)
  44. }
  45. });
  46. const valueTitle = ref('');
  47. const defaultExpandedKey = ref<any[]>([]);
  48. function initHandle() {
  49. nextTick(() => {
  50. const selectedValue = valueId.value;
  51. if(selectedValue !== null && typeof (selectedValue) !== 'undefined') {
  52. const node = selectTree.value.getNode(selectedValue)
  53. if (node) {
  54. valueTitle.value = node.data[props.objMap.label]
  55. selectTree.value.setCurrentKey(selectedValue) // 设置默认选中
  56. defaultExpandedKey.value = [selectedValue] // 设置默认展开
  57. }
  58. } else {
  59. clearHandle()
  60. }
  61. })
  62. }
  63. function handleNodeClick(node: any) {
  64. valueTitle.value = node[props.objMap.label]
  65. valueId.value = node[props.objMap.value];
  66. defaultExpandedKey.value = [];
  67. selectTree.value.blur()
  68. selectFilterData('')
  69. }
  70. function selectFilterData(val: any) {
  71. selectTree.value.filter(val)
  72. }
  73. function filterNode(value: any, data: any) {
  74. if (!value) return true
  75. return data[props.objMap['label']].indexOf(value) !== -1
  76. }
  77. function clearHandle() {
  78. valueTitle.value = ''
  79. valueId.value = ''
  80. defaultExpandedKey.value = [];
  81. clearSelected()
  82. }
  83. function clearSelected() {
  84. const allNode = document.querySelectorAll('#tree-option .el-tree-node')
  85. allNode.forEach((element) => element.classList.remove('is-current'))
  86. }
  87. onMounted(() => {
  88. initHandle()
  89. })
  90. watch(valueId, () => {
  91. initHandle();
  92. })
  93. </script>
  94. <style lang="scss" scoped>
  95. @import "@/assets/styles/variables.module.scss";
  96. .el-scrollbar .el-scrollbar__view .el-select-dropdown__item {
  97. padding: 0;
  98. background-color: #fff;
  99. height: auto;
  100. }
  101. .el-select-dropdown__item.selected {
  102. font-weight: normal;
  103. }
  104. ul li .el-tree .el-tree-node__content {
  105. height: auto;
  106. padding: 0 20px;
  107. box-sizing: border-box;
  108. }
  109. :deep(.el-tree-node__content:hover),
  110. :deep(.el-tree-node__content:active),
  111. :deep(.is-current > div:first-child),
  112. :deep(.el-tree-node__content:focus) {
  113. background-color: mix(#fff, $--color-primary, 90%);
  114. color: $--color-primary;
  115. }
  116. </style>
  117. <template>
  118. <div class="el-tree-select">
  119. <el-select
  120. style="width: 100%"
  121. v-model="valueId"
  122. ref="treeSelect"
  123. :filterable="true"
  124. :clearable="true"
  125. @clear="clearHandle"
  126. :filter-method="selectFilterData"
  127. :placeholder="placeholder"
  128. >
  129. <el-option :value="valueId" :label="valueTitle">
  130. <el-tree
  131. id="tree-option"
  132. ref="selectTree"
  133. :accordion="accordion"
  134. :data="options"
  135. :props="objMap"
  136. :node-key="objMap.value"
  137. :expand-on-click-node="false"
  138. :default-expanded-keys="defaultExpandedKey"
  139. :filter-node-method="filterNode"
  140. @node-click="handleNodeClick"
  141. ></el-tree>
  142. </el-option>
  143. </el-select>
  144. </div>
  145. </template>