Browse Source

管理中心-创建作品-素材选择弹窗:文件夹相关功能

任一存 2 years ago
parent
commit
33186100af

+ 60 - 0
packages/qjkankan-editor/src/components/materialSelectorFolderMixin.js

@@ -0,0 +1,60 @@
+import crumbs from "@/components/crumbs";
+
+import { nodeIdList2nodeInfoListByNodeTree } from "@/utils/other.js";
+import {
+  getFolderTree,
+} from "@/api";
+
+import {i18n} from "@/lang"
+
+export default {
+  components: {
+    crumbs,
+  },
+  data() {
+    return {
+      folderTree: null,
+      folderPath: [],
+    }
+  },
+  computed: {
+    currentFolderId() {
+      return this.folderPath[this.folderPath.length - 1].id
+    },
+  },
+  methods: {
+    onClickPath(idx) {
+      this.searchKey = ''
+      this.folderPath = this.folderPath.slice(0, idx + 1)
+      // this.selectedList = []
+    },
+    onClickFolder(folder) {
+      getFolderTree({
+        type: this.currentMaterialType,
+      }).then((res) => {
+        this.folderTree = res.data
+        const targetPathIdList = folder.ancestors.split(',').map((item) => {
+          return Number(item)
+        })
+        targetPathIdList.push(folder.id)
+        this.folderPath = nodeIdList2nodeInfoListByNodeTree(targetPathIdList, this.folderTree)
+        this.searchKey = ''
+        // this.selectedList = []
+      })
+    },
+  },
+  watch: {
+    folderPath: {
+      handler: function () {
+        this.refreshMaterialList(this.currentMaterialType)
+      },
+      deep: true,
+    },
+  },
+  created() {
+    this.folderPath.push({
+      name: i18n.t(`gather.${this.currentMaterialType}`),
+      id: 1,
+    })
+  }
+}

+ 166 - 98
packages/qjkankan-editor/src/components/materialSelectorForManageCenter.vue

@@ -44,7 +44,14 @@
       <i v-if="!searchKey" class="iconfont icon-editor_search search-icon" />
       <i v-if="searchKey" @click="searchKey = ''" class="iconfont icontoast_red clear-icon"></i>
     </div>
-
+    <crumbs
+      class="crumbs"
+      v-if="!latestUsedSearchKey"
+      :list="folderPath"
+      :rootName="$i18n.t(`gather.${currentMaterialType}`)"
+      @click-path="onClickPath"
+    />
+    <div v-if="latestUsedSearchKey" class="crumbs">{{$i18n.t(`gather.${currentMaterialType}`)}}</div>
     <div class="table table-pano" v-show="currentMaterialType === 'pano'">
       <div class="table-head-row">
         <span class="table-head">1</span>
@@ -116,19 +123,51 @@
           </template>
         </div>
         <!-- 本组件内的列表数据 -->
-        <div class="table-body-row" v-for="(item, i) in panoList" :key="i" @click="onClickRow">
+        <div
+          class="table-body-row"
+          v-for="(item, i) in panoList"
+          :key="i"
+          @click="(e) => {
+            if (item.type === 'dir') {
+              onClickFolder(item)
+            } else {
+              onClickRow(e)
+            }
+          }"
+        >
           <span class="table-data">
-            <RadioOrCheckbox class="checkbox" :isLightTheme="true" :isMultiSelection="isMultiSelection"
+            <RadioOrCheckbox
+              v-if="item.type !== 'dir'"
+              class="checkbox"
+              :isLightTheme="true"
+              :isMultiSelection="isMultiSelection"
               :isCheckedInitial="select.some(i => i[primaryKey] === item[primaryKey])"
-              @change="v => selectItem(item, v)" />
+              @change="v => selectItem(item, v)"
+            />
           </span>
-          <span class="table-data" v-for="(sub, idx) in tableHeadersForPano" :key="idx">
-            <div v-if="sub.type == 'image'" class="list-img">
+          <span
+            class="table-data"
+            v-for="(sub, idx) in tableHeadersForPano"
+            :key="idx"
+          >
+            <div
+              v-if="sub.type == 'image'"
+              class="list-img"
+            >
               <img
-                :src="item[sub.key] + (Number(item.fileSize) > 512 ? $imgsuffix : ``)"
-                alt="">
+                :class="{
+                  folderIcon: item.type === 'dir',
+                }"
+                :src="(item.type === 'dir') ? require('@/assets/images/icons/folder-blue.png') : (item[sub.key] + (Number(item.fileSize) > 512 ? $imgsuffix : ``))"
+                alt=""
+              />
             </div>
-            <span class="ellipsis" v-else v-title="sub.key === 'name' ? item[sub.key] : ''">{{ item[sub.key] }}</span>
+            <span
+              class="ellipsis"
+              v-else v-title="sub.key === 'name' ? item[sub.key] : ''"
+            >
+              {{ item[sub.key] }}
+            </span>
           </span>
         </div>
       </div>
@@ -211,7 +250,8 @@
 </template>
 
 <script>
-import { mapMutations } from "vuex";
+import { mapMutations, mapState, } from "vuex";
+
 import {
   getMaterialList,
   getSceneList,
@@ -219,15 +259,27 @@ import {
   checkMStatus,
   checkUserSize,
 } from "@/api";
+
 import { getImgWH, changeByteUnit } from "@/utils/file";
-import config from "@/config";
 import { debounce } from "@/utils/other.js"
+
+import config from "@/config";
+
 import FileInput from "@/components/shared/uploads/UploadMultiple.vue";
-import { mapState } from "vuex";
 import RadioOrCheckbox from "@/components/shared/RadioOrCheckbox.vue";
+
+import folderMixin from "./materialSelectorFolderMixin.js";
+
 import { i18n } from "@/lang"
 
 export default {
+  components: {
+    FileInput,
+    RadioOrCheckbox,
+  },
+  mixins: [
+    folderMixin,
+  ],
   props: {
     title: {
       default: '',
@@ -258,42 +310,35 @@ export default {
       default: '',
     },
   },
-  components: {
-    FileInput,
-    RadioOrCheckbox,
-  },
-  watch: {
-    searchKey: {
-      handler: function () {
-        this.refreshMaterialList(this.currentMaterialType)
-      },
-      immediate: false,
-    },
-    currentMaterialType: {
-      handler: function (newVal) {
-        if (newVal === 'pano' && this.panoList.length === 0) {
-          this.refreshMaterialList('pano')
-        } else if (newVal === '3D' && this.scene3DList.length === 0) {
-          this.refreshMaterialList('3D')
-        }
-      },
-      immediate: false,
-    },
-    needLongPolling: {
-      handler: function (newVal) {
-        if (!newVal) {
-          clearInterval(this.longPollingIntervalId)
-          this.longPollingIntervalId = null
-        } else {
-          clearInterval(this.longPollingIntervalId)
-          this.longPollingIntervalId = null
-          this.longPollingIntervalId = setInterval(() => {
-            this._checkMStatus();
-          }, 3000);
-        }
-      },
-      immediate: true,
-    },
+  data() {
+    return {
+      no_serch_result: i18n.t("gather.no_serch_result"),
+      no_material_result: i18n.t("gather.no_material_result"),
+      panorama: i18n.t("gather.panorama"),
+      scene: i18n.t("gather.scene"),
+      keywords: i18n.t("gather.keywords"),
+      how_to_shoot: i18n.t("gather.how_to_shoot"),
+      upload_material: i18n.t("gather.upload_material"),
+      pano_size: i18n.t("gather.pano_size"),
+      cancel: i18n.t("gather.cancel"),
+      comfirm: i18n.t("gather.comfirm"),
+
+      panoList: [],
+      scene3DList: [],
+
+      select: [],
+      searchKey: '', // 搜索关键词
+      latestUsedSearchKey: '',
+
+      currentMaterialType: this.initialMaterialType,
+
+      isRequestingMorePanoData: false,
+      isRequestingMore3DData: false,
+      hasMorePanoData: true,
+      hasMore3DData: true,
+
+      longPollingIntervalId: null,
+    }
   },
   computed: {
     ...mapState({
@@ -381,35 +426,38 @@ export default {
       })
     },
   },
-  data() {
-    return {
-      no_serch_result: i18n.t("gather.no_serch_result"),
-      no_material_result: i18n.t("gather.no_material_result"),
-      panorama: i18n.t("gather.panorama"),
-      scene: i18n.t("gather.scene"),
-      keywords: i18n.t("gather.keywords"),
-      how_to_shoot: i18n.t("gather.how_to_shoot"),
-      upload_material: i18n.t("gather.upload_material"),
-      pano_size: i18n.t("gather.pano_size"),
-      cancel: i18n.t("gather.cancel"),
-      comfirm: i18n.t("gather.comfirm"),
-
-      panoList: [],
-      scene3DList: [],
-
-      select: [],
-      searchKey: '', // 搜索关键词
-      latestUsedSearchKey: '',
-
-      currentMaterialType: this.initialMaterialType,
-
-      isRequestingMorePanoData: false,
-      isRequestingMore3DData: false,
-      hasMorePanoData: true,
-      hasMore3DData: true,
-
-      longPollingIntervalId: null,
-    }
+  watch: {
+    searchKey: {
+      handler: function () {
+        this.refreshMaterialList(this.currentMaterialType)
+      },
+      immediate: false,
+    },
+    currentMaterialType: {
+      handler: function (newVal) {
+        if (newVal === 'pano' && this.panoList.length === 0) {
+          this.refreshMaterialList('pano')
+        } else if (newVal === '3D' && this.scene3DList.length === 0) {
+          this.refreshMaterialList('3D')
+        }
+      },
+      immediate: false,
+    },
+    needLongPolling: {
+      handler: function (newVal) {
+        if (!newVal) {
+          clearInterval(this.longPollingIntervalId)
+          this.longPollingIntervalId = null
+        } else {
+          clearInterval(this.longPollingIntervalId)
+          this.longPollingIntervalId = null
+          this.longPollingIntervalId = setInterval(() => {
+            this._checkMStatus();
+          }, 3000);
+        }
+      },
+      immediate: true,
+    },
   },
   methods: {
     ...mapMutations([
@@ -417,30 +465,31 @@ export default {
     ]),
     selectItem(item, v) {
       item.materialType = this.currentMaterialType // 三维场景数据没有type字段来表明自己是三维场景。所以统一加一个字段。
-        if (this.isMultiSelection) {
-          if (v) {
-            this.select.push(item)
-          } else {
-            const toDeleteIdx = this.select.findIndex((eachSelect) => {
-              return eachSelect.id === item.id
-            })
-            if (toDeleteIdx >= 0) {
-              this.select.splice(toDeleteIdx, 1)
-            }
-          }
+      if (this.isMultiSelection) {
+        if (v) {
+          this.select.push(item)
         } else {
-          if (v) {
-            this.select = [item]
-          } else {
-            this.select = []
+          const toDeleteIdx = this.select.findIndex((eachSelect) => {
+            return eachSelect.id === item.id
+          })
+          if (toDeleteIdx >= 0) {
+            this.select.splice(toDeleteIdx, 1)
           }
         }
+      } else {
+        if (v) {
+          this.select = [item]
+        } else {
+          this.select = []
+        }
+      }
     },
     requestMorePanoData() {
       this.isRequestingMorePanoData = true
       const latestUsedSearchKey = this.searchKey
       getMaterialList(
         {
+          dirId: this.currentFolderId,
           pageNum: Math.floor(this.panoListRealLength / config.PAGE_SIZE) + 1,
           pageSize: config.PAGE_SIZE,
           searchKey: this.searchKey,
@@ -448,7 +497,11 @@ export default {
         },
         (data) => {
           const newData = data.data.list.map((i) => {
-            i.fileSize = changeByteUnit(Number(i.fileSize));
+            if (i.fileSize) {
+              i.fileSize = changeByteUnit(Number(i.fileSize));
+            } else {
+              i.fileSize = ''
+            }
             i.createTime = i.createTime.substring(0, i.createTime.length - 3)
             i.updateTime = i.updateTime.substring(0, i.updateTime.length - 3)
             return i;
@@ -588,6 +641,10 @@ export default {
             uid: itemInUploadList.uid,
           },
           (response) => { // 上传成功
+            if (response.code !== 0) {
+              return
+            }
+            console.log('全景图上传成功');
             itemInUploadList.statusText = this.$i18n.t(`gather.cutting`)
             itemInUploadList.ifKnowProgress = false
             itemInUploadList.backendId = response.data.id
@@ -600,7 +657,7 @@ export default {
               })
               this.uploadStatusListPano.splice(index, 1)
             } else {
-              console.log('失败!');
+              console.log('全景图上传失败!');
               itemInUploadList.status = 'FAIL'
               itemInUploadList.statusText = this.$i18n.t(`gather.material_upload_fail`)
             }
@@ -638,7 +695,11 @@ export default {
                 if (index >= 0) {
                   const targetItem = this.uploadStatusListPano[index]
                   targetItem.status = 'SUCCESS'
-                  eachRes.fileSize = changeByteUnit(Number(eachRes.fileSize));
+                  if (eachRes.fileSize) {
+                    eachRes.fileSize = changeByteUnit(Number(eachRes.fileSize));
+                  } else {
+                    eachRes.fileSize = ''
+                  }
                   targetItem.successInfo = eachRes
                 }
               }
@@ -789,12 +850,16 @@ export default {
   }
 }
 
-@table-height: 440px;
+.crumbs {
+  margin-top: 10px;
+}
+
+@table-height: 420px;
 @table-head-row-height: 40px;
 @table-border-size: 1px;
 
 .table {
-  margin-top: 20px;
+  margin-top: 10px;
   border: @table-border-size solid #EBEDF0;
   background: #ffffff;
   width: 100%;
@@ -847,6 +912,9 @@ export default {
             width: 40px;
             height: 40px;
             object-fit: cover;
+            &.folderIcon {
+              object-fit: contain;
+            }
           }
         }
       }
@@ -935,7 +1003,7 @@ export default {
 .btns {
   display: flex;
   justify-content: space-between;
-  margin-top: 40px;
+  margin-top: 32px;
 
   .upload-btn {
     display: flex;