treeList.vue 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. <template>
  2. <div class="vtl-node" :id="model.id" :class="{ 'vtl-leaf-node': !isFolder, 'vtl-tree-node': isFolder }">
  3. <div :class="treeNodeClass" @mouseover="mouseOver" @mouseout="mouseOut" @click.stop="toggle">
  4. <div class="vtl-border-text">
  5. <template v-if="isFolder">
  6. <slot v-if="expanded" :item="{ title: model.title, isFolder: true, expanded: true }" name="icon"> </slot>
  7. <slot v-else :item="{ title: model.title, isFolder: true, expanded: false }" name="icon"></slot>
  8. </template>
  9. <slot v-else :item="{ title: model.title, isFolder: false }" name="icon"></slot>
  10. <span class="vtl-node-content ellipsis">
  11. {{ model.title }}
  12. </span>
  13. </div>
  14. <div class="vtl-operation" v-show="isHover && !isFolder">
  15. <span @click.stop.prevent="delNode">
  16. <slot name="operation" type="detailNode"></slot>
  17. </span>
  18. </div>
  19. </div>
  20. </div>
  21. <div class="vtl-tree-margin" v-show="expanded">
  22. <!-- 这里无法使用$attr来透传属性官方还未解决此bug -->
  23. <treeList
  24. @on-click="(depth) => $emit('onClick', depth)"
  25. @detail-node="(depth) => $emit('detailNode', depth)"
  26. v-for="newmodel in model.children"
  27. :selected="selected"
  28. :model="newmodel"
  29. :key="newmodel.id"
  30. >
  31. <template #icon="slotProps">
  32. <slot name="icon" v-bind="slotProps"></slot>
  33. </template>
  34. <template #operation="slotProps">
  35. <slot name="operation" v-bind="slotProps"></slot>
  36. </template>
  37. </treeList>
  38. </div>
  39. </template>
  40. <script setup lang="ts">
  41. import { computed, ref } from 'vue';
  42. interface IFileSystem {
  43. id: string;
  44. title: string;
  45. pid: string;
  46. isFolder: boolean;
  47. isAdd: boolean;
  48. children?: IFileSystem[];
  49. }
  50. // 吐出去的事件
  51. const emit = defineEmits(['onClick', 'detailNode']);
  52. // 拿到传入的值
  53. const props = withDefaults(
  54. defineProps<{
  55. model: IFileSystem;
  56. selected: IFileSystem;
  57. }>(),
  58. {
  59. // draggable: false,
  60. }
  61. );
  62. //是否移入
  63. const isHover = ref(false);
  64. // 是否展开
  65. const expanded = ref(false);
  66. // 是否是文件夹
  67. const isFolder = computed(() => {
  68. return props.model.isFolder;
  69. });
  70. const isSelected = computed(() => props.selected.id === props.model.id);
  71. // 拖拽样式
  72. const treeNodeClass = computed(() => {
  73. return {
  74. 'vtl-node-main': true,
  75. selected: isSelected.value,
  76. };
  77. });
  78. // 删除目录
  79. const delNode = () => {
  80. emit('detailNode', {
  81. ...props.model,
  82. eventType: 'detail',
  83. });
  84. };
  85. // 展开收起
  86. const toggle = () => {
  87. if (isFolder.value) {
  88. expanded.value = !expanded.value;
  89. emit('onClick', {
  90. ...props.model,
  91. }); //lxh
  92. } else {
  93. emit('onClick', {
  94. ...props.model,
  95. });
  96. }
  97. };
  98. // 拖拽结束
  99. const mouseOver = () => {
  100. isHover.value = true;
  101. };
  102. // 移出
  103. const mouseOut = () => {
  104. isHover.value = false;
  105. };
  106. </script>
  107. <style lang="less">
  108. @import '/@/design/theme.less';
  109. @{theme-deepblue} {
  110. .vtl-node {
  111. --node-select-bg: #3f506a;
  112. }
  113. }
  114. .vtl-node {
  115. --node-select-bg: #1c4869;
  116. .vtl-node-main {
  117. display: flex;
  118. align-items: center;
  119. padding: 2px 0 2px 2px;
  120. cursor: pointer;
  121. &:hover {
  122. .vtl-border-text {
  123. width: 80%;
  124. }
  125. }
  126. .vtl-border-text {
  127. display: flex; //lxh
  128. flex: 1;
  129. align-items: center; //lxh
  130. width: 100%;
  131. padding-left: 5px;
  132. .iconfont {
  133. width: 16px;
  134. height: 16px;
  135. vertical-align: text-bottom;
  136. }
  137. }
  138. &.selected {
  139. // background-color: rgba(45, 113, 134, 0.2);
  140. background-color: var(--node-select-bg);
  141. }
  142. .vtl-node-content {
  143. color: #fff;
  144. padding-left: 5px;
  145. font-size: 14px;
  146. width: 80%;
  147. display: inline-block;
  148. vertical-align: bottom;
  149. }
  150. &:hover {
  151. .vtl-node-content {
  152. color: #fff;
  153. overflow: hidden;
  154. }
  155. }
  156. .vtl-operation {
  157. padding-right: 10px;
  158. }
  159. }
  160. }
  161. .vtl-tree-margin {
  162. padding-left: 1em;
  163. }
  164. </style>