floder-view.vue 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. <template>
  2. <div
  3. :class="{ root: index === 1 }"
  4. class="tree"
  5. v-if="getFlatFloders(root).length !== 0"
  6. >
  7. <div
  8. class="solid header"
  9. :class="{ ['root-header']: index === 1 }"
  10. :style="{ '--index': index }"
  11. @click="showChildren = !showChildren"
  12. >
  13. <span> {{ root.title }} </span>
  14. <ui-icon
  15. :type="`pull-${showChildren ? 'up' : 'down'}`"
  16. class="icon"
  17. ctrl
  18. v-if="floders.length || root.children?.length"
  19. />
  20. </div>
  21. <template v-if="!root.modal && showChildren && (floders.length || children?.length)">
  22. <div class="items" :class="{ ['root-items']: index === 1 }">
  23. <template v-if="floders.length">
  24. <div
  25. :style="{ '--index': index }"
  26. v-for="floder in floders"
  27. :key="floder.filesId"
  28. class="fun-ctrl solid item"
  29. @click="$emit('preview', [floder, root])"
  30. >
  31. <ui-icon :type="typeIcons[floder.metaType]" v-if="floder.metaType" />
  32. <p>{{ floder.filesTitle }}</p>
  33. </div>
  34. </template>
  35. <template v-if="children?.length">
  36. <FloderView
  37. v-for="item in children"
  38. @preview="(v: any) => emit('preview', v)"
  39. :root="item"
  40. :index="index + 1"
  41. />
  42. </template>
  43. </div>
  44. </template>
  45. </div>
  46. <Modal
  47. v-if="root.modal"
  48. width="1200px"
  49. :title="root.title"
  50. @cancel="showChildren = false"
  51. :open="showChildren"
  52. :footer="null"
  53. >
  54. <div class="modal-root-content">
  55. <ModalFloderView :root="root" @preview="(v) => emit('preview', v)" />
  56. </div>
  57. </Modal>
  58. </template>
  59. <script lang="ts" setup>
  60. import { Floder, FloderRoot, getFlatFloders } from "@/store";
  61. import { computed, ref, toRaw, watchEffect } from "vue";
  62. import { MetaType } from "@/utils";
  63. import ModalFloderView from "./modal-floder-view.vue";
  64. import { Modal } from "ant-design-vue";
  65. const props = defineProps<{ root: FloderRoot; index?: number }>();
  66. const emit = defineEmits<{ (e: "preview", v: [Floder, FloderRoot]): void }>();
  67. const index = props.index || 1;
  68. const typeIcons = {
  69. [MetaType.image]: "pic",
  70. [MetaType.video]: "a-film",
  71. [MetaType.other]: "nav-edit",
  72. [MetaType.audio]: "nav-edit",
  73. [MetaType.xfile]: "nav-edit",
  74. };
  75. const floders = computed(() => {
  76. if (props.root.flat) {
  77. return getFlatFloders(props.root);
  78. } else {
  79. return props.root.floders;
  80. }
  81. });
  82. const children = computed(() => {
  83. if (props.root.flat || props.root.modal) {
  84. return [];
  85. } else {
  86. return props.root.children;
  87. }
  88. });
  89. const showChildren = ref(props.root.modal ? false : true);
  90. watchEffect(() => {
  91. if (showChildren.value) {
  92. // console.log(toRaw(props.root));
  93. }
  94. });
  95. </script>
  96. <style lang="scss" scoped>
  97. .tree {
  98. margin-bottom: 0;
  99. }
  100. .modal-root-content {
  101. max-height: 700px;
  102. overflow-y: auto;
  103. }
  104. .root-items {
  105. background: rgba(0, 0, 0, 0.5);
  106. }
  107. .header {
  108. display: flex;
  109. justify-content: space-between;
  110. align-items: center;
  111. margin-bottom: 0;
  112. cursor: pointer;
  113. padding: 20px 0;
  114. position: relative;
  115. padding-left: calc(var(--index) * 20px);
  116. padding-right: 20px;
  117. span {
  118. font-weight: normal;
  119. font-size: 14px;
  120. }
  121. &.root-header {
  122. padding: 20px;
  123. span {
  124. font-weight: bold;
  125. font-size: 16px;
  126. }
  127. }
  128. .icon {
  129. font-size: 14px;
  130. }
  131. }
  132. .solid {
  133. &::after {
  134. content: "";
  135. position: absolute;
  136. left: 20px;
  137. right: 20px;
  138. height: 1px;
  139. background: rgba(255, 255, 255, 0.16);
  140. bottom: 0;
  141. }
  142. }
  143. .item {
  144. margin-right: 20px;
  145. padding: 20px 0;
  146. cursor: pointer;
  147. display: flex;
  148. align-items: center;
  149. position: relative;
  150. padding-left: calc(var(--index) * 20px);
  151. padding-right: 0;
  152. &.solid::after {
  153. right: 0;
  154. }
  155. p {
  156. margin-left: 10px;
  157. font-size: 12px;
  158. color: currentColor;
  159. white-space: nowrap;
  160. text-overflow: ellipsis;
  161. overflow: hidden;
  162. }
  163. }
  164. </style>