dept-tree.vue 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. <template>
  2. <div class="nav-tree">
  3. <el-input class="filter" v-model="filter" :placeholder="placeholder" size="mini" clearable></el-input>
  4. <el-tree
  5. ref="tree"
  6. :show-checkbox="showCheckbox"
  7. :getCheckedNodes="true"
  8. :data="treeItems"
  9. :props="navProps"
  10. node-key="id"
  11. @node-click="handleNavClick"
  12. @check-change="handleCheckChange"
  13. :highlight-current="true"
  14. :expand-on-click-node="false"
  15. >
  16. <template v-slot="{ node, data }">
  17. <slot>
  18. <span v-if="node.label.length <= 8 - node.level" class="dept-tree-node">
  19. <i :class="iconCls(data.icon || 'folder')" style="margin-right: 5px;" v-if="showIcon"></i>
  20. <span>{{ node.label }}</span>
  21. <el-badge :value="data.desc" class="item" type="info"></el-badge>
  22. </span>
  23. <el-tooltip v-else effect="dark" :content="data.desc ? node.label + '(' + data.desc + ')' : node.label" placement="right">
  24. <span class="dept-tree-node">
  25. <i :class="iconCls(data.icon || 'folder')" style="margin-right: 5px;" v-if="showIcon"></i>
  26. <span>{{ node.label }}</span>
  27. <el-badge :value="data.desc" class="item" type="info"></el-badge>
  28. </span>
  29. </el-tooltip>
  30. </slot>
  31. </template>
  32. </el-tree>
  33. </div>
  34. </template>
  35. <script>
  36. export default {
  37. props: {
  38. navItems: Array,
  39. dataItems: Array,
  40. virtualRoot: String,
  41. showIcon: { type: Boolean, default: false },
  42. placeholder: String,
  43. showCheckbox: { type: Boolean, default: false },
  44. keys: Array,
  45. },
  46. data() {
  47. return {
  48. navProps: {
  49. children: 'children',
  50. label: 'name',
  51. },
  52. filter: null,
  53. };
  54. },
  55. methods: {
  56. handleCheckChange() {
  57. const data = this.$refs.tree.getCheckedNodes();
  58. this.$emit('checkchange', data);
  59. },
  60. handleNavClick(data) {
  61. this.$emit('selected', data && !data.isRoot ? data : null);
  62. },
  63. setCurrentKey(key) {
  64. this.$refs['tree'].setCurrentKey(key);
  65. },
  66. iconCls(icon) {
  67. if (icon && !(icon.indexOf('el-') === 0)) {
  68. return `naf-icons naf-icon-${icon}`;
  69. }
  70. return icon;
  71. },
  72. },
  73. computed: {
  74. treeItems() {
  75. if (this.filter) {
  76. return this.dataItems.filter(p => p.name && p.name.includes(this.filter));
  77. } else {
  78. if (this.navItems) return this.navItems;
  79. const items = this.dataItems || [];
  80. let roots = items.filter(a => !items.some(b => b.id === a.pid));
  81. const fetchChildren = item => {
  82. if (!item.path) item.path = [item.name];
  83. const children = items.filter(p => p.pid === item.id).map(p => fetchChildren({ ...p, parent: item, path: item.path.concat(p.name) }));
  84. return { ...item, children };
  85. };
  86. roots = roots.map(p => fetchChildren(p));
  87. if (!this.virtualRoot) {
  88. return roots;
  89. }
  90. // 显示虚拟根目录
  91. return [{ [this.navProps.label]: this.virtualRoot, children: roots, isRoot: true, icon: 'dept' }];
  92. }
  93. },
  94. },
  95. watch: {
  96. keys(val) {
  97. this.$refs.tree.setCheckedKeys(val);
  98. },
  99. },
  100. };
  101. </script>
  102. <style lang="less" scoped>
  103. .item {
  104. margin-top: 6px;
  105. margin-left: 5px;
  106. }
  107. .nav-tree {
  108. width: 100%;
  109. overflow-x: auto;
  110. /deep/ .el-tree-node.is-current > .el-tree-node__content {
  111. background-color: #409eff;
  112. color: white;
  113. .naf-icon-dian {
  114. display: inline;
  115. color: white;
  116. }
  117. }
  118. /deep/ .naf-icon-dian {
  119. display: none;
  120. }
  121. /deep/ .el-tree-node__content:hover .naf-icon-dian {
  122. display: inline;
  123. }
  124. .filter {
  125. display: block;
  126. position: relative;
  127. width: 90%;
  128. margin: 0 auto;
  129. margin-bottom: 10px;
  130. margin-top: 10px;
  131. }
  132. .el-tree {
  133. width: 100%;
  134. overflow: hidden;
  135. }
  136. /deep/ .dept-tree-node {
  137. overflow: hidden;
  138. display: flex;
  139. .el-tooltip {
  140. overflow: hidden;
  141. width: 100%;
  142. display: inline-grid;
  143. }
  144. }
  145. }
  146. </style>