Explorar o código

编辑器-素材选择弹窗:添加图片、视频、音频的上传功能

(cherry picked from commit 7326d010c02e68dd9e547c2fcaf851c27f69563b)
任一存 %!s(int64=3) %!d(string=hai) anos
pai
achega
8df1056555

+ 10 - 0
packages/qjkankan-editor/src/Store/index.js

@@ -162,6 +162,16 @@ const store = new Vuex.Store({
       state.backupHotSpot = data
     },
 
+    setUploadStatusListImage(state, data) {
+      state.uploadStatusListImage = data
+    },
+    setUploadStatusListAudio(state, data) {
+      state.uploadStatusListAudio = data
+    },
+    setUploadStatusListVideo(state, data) {
+      state.uploadStatusListVideo = data
+    },
+    
     setEditorNavDragType(state, data) {
       if (!['topologyGroupLevel1', 'topologyGroupLevel2', 'scene'].includes(data)) {
         throw("拖拽类型必须是'topologyGroupLevel1', 'topologyGroupLevel2', 'scene'之一!")

+ 726 - 13
packages/qjkankan-editor/src/components/materialSelectorForEditor.vue

@@ -38,11 +38,71 @@
         <span class="table-head" v-for="(item,i) in tableHeadersForImage" :key="i">{{item.name}}</span>
       </div>
       <div
-        v-if="imageList.length !== 0 || hasMoreImageData"
+        v-if="imageListRealLength !== 0 || hasMoreImageData"
         class="table-body"
         v-infinite-scroll="requestMoreImageData"
         :infinite-scroll-disabled="!hasMoreImageData || isRequestingMoreImageData"
       >
+        <!-- vuex中的上传中数据 -->
+        <div class="table-body-row" v-for="(item, i) in uploadStatusListImage" :key="item.uid">
+          <!-- 如果已经上传成功 -->
+          <template v-if="item.status === 'SUCCESS'">
+            <span class="table-data">
+              <div class="checkbox">
+                <!-- 负责功能 -->
+                <input
+                  type="checkbox"
+                  @change="e => selectItem(item.successInfo, e)"
+                  :checked="select.some(i => i[primaryKey] === item.successInfo[primaryKey])"
+                >
+                <!-- 负责外观 -->
+                <span class="for-outer-circle"></span>
+                <span class="for-inner-circle"></span>
+              </div>
+            </span>
+            <span class="table-data" v-for="(tableItemStructure, idx) in tableHeadersForImage" :key="idx">
+              <div v-if="tableItemStructure.type=='image'" class="list-img">
+                <img :src="item.successInfo[tableItemStructure.key] + `?x-oss-process=image/resize,p_10&${Math.random()}`" alt="">
+              </div>
+              <span  v-else class="ellipsis" v-title="tableItemStructure.key === 'name' ? item.successInfo[tableItemStructure.key] : ''">{{ item.successInfo[tableItemStructure.key] }}</span>
+            </span>
+          </template>
+          <!-- 如果还在上传中 -->
+          <template v-else-if="item.status = 'LOADING'">
+            <span class="table-data">
+              <div class="checkbox">
+                <span class="for-outer-circle"></span>
+                <span class="for-inner-circle disabled"></span>
+              </div>
+            </span>
+            <span class="table-data" v-for="(tableItemStructure, idx) in tableHeadersForImage" :key="idx">
+              <div v-if="tableItemStructure.type=='image'" class="list-img">
+                <img src="@/assets/images/icons/upload-file-type-icon-image@2x.png" alt="">
+              </div>
+              <span  v-if="tableItemStructure.key !== 'name' && tableItemStructure.key !== 'dpi'"></span>
+              <span  v-if="tableItemStructure.key === 'dpi'">上传素材 {{item.progress * 100}}%</span>
+              <span  v-if="tableItemStructure.key === 'name'" class="ellipsis" v-title="tableItemStructure.key === 'name' ? item.title : ''">{{ item.title }}</span>
+            </span>
+          </template>
+          <!-- 如果上传失败了 -->
+          <template v-else-if="item.status = 'FAIL'">
+            <span class="table-data">
+              <div class="checkbox">
+                <span class="for-outer-circle"></span>
+                <span class="for-inner-circle disabled"></span>
+              </div>
+            </span>
+            <span class="table-data" v-for="(tableItemStructure, idx) in tableHeadersForImage" :key="idx">
+              <div v-if="tableItemStructure.type=='image'" class="list-img">
+                <img src="@/assets/images/icons/upload-file-type-icon-image@2x.png" alt="">
+              </div>
+              <span  v-if="tableItemStructure.key !== 'name' && tableItemStructure.key !== 'dpi'"></span>
+              <span  v-if="tableItemStructure.key === 'dpi'">上传失败</span>
+              <span  v-if="tableItemStructure.key === 'name'" class="ellipsis" v-title="tableItemStructure.key === 'name' ? item.title : ''">{{ item.title }}</span>
+            </span>
+          </template>
+        </div>
+        <!-- 本组件内的列表数据 -->
         <div class="table-body-row" v-for="(item,i) in imageList" :key="i">
           <span class="table-data">
             <div class="checkbox">
@@ -66,7 +126,7 @@
         </div>
       </div>
       <!-- 无数据时的提示 -->
-      <div v-if="imageList.length === 0 && !hasMoreImageData" class="no-data">
+      <div v-else class="no-data">
         <div v-if="latestUsedSearchKey">
           <img :src="require('@/assets/images/default/empty_04_search.png')" alt="">
           <span>{{'未搜索到结果~'}}</span>
@@ -130,11 +190,83 @@
         <span class="table-head" v-for="(item,i) in tableHeadersForAudio" :key="i">{{item.name}}</span>
       </div>
       <div
-        v-if="audioList.length !== 0 || hasMoreAudioData"
+        v-if="audioListRealLength !== 0 || hasMoreAudioData"
         class="table-body"
         v-infinite-scroll="requestMoreAudioData"
         :infinite-scroll-disabled="!hasMoreAudioData || isRequestingMoreAudioData"
       >
+        <!-- vuex中的上传中数据 -->
+        <div class="table-body-row" v-for="(item, i) in uploadStatusListAudio" :key="item.uid">
+          <!-- 如果已经上传成功 -->
+          <template v-if="item.status === 'SUCCESS'">
+            <span class="table-data">
+              <div class="checkbox">
+                <!-- 负责功能 -->
+                <input
+                  type="checkbox"
+                  @change="e => selectItem(item.successInfo, e)"
+                  :checked="select.some(i => i[primaryKey] === item.successInfo[primaryKey])"
+                >
+                <!-- 负责外观 -->
+                <span class="for-outer-circle"></span>
+                <span class="for-inner-circle"></span>
+              </div>
+            </span>
+            <span class="table-data" v-for="(tableItemStructure, idx) in tableHeadersForAudio" :key="idx">
+              <div v-if="tableItemStructure.type=='audio'" class="list-img">
+                <img
+                  :src="require('@/assets/images/icons/upload-file-type-icon-audio@2x.png')"
+                  style="object-fit: contain;"
+                  alt=""
+                >
+              </div>
+              <span  v-else class="ellipsis" v-title="tableItemStructure.key === 'name' ? item.successInfo[tableItemStructure.key] : ''">{{ item.successInfo[tableItemStructure.key] }}</span>
+            </span>
+          </template>
+          <!-- 如果还在上传中 -->
+          <template v-else-if="item.status = 'LOADING'">
+            <span class="table-data">
+              <div class="checkbox">
+                <span class="for-outer-circle"></span>
+                <span class="for-inner-circle disabled"></span>
+              </div>
+            </span>
+            <span class="table-data" v-for="(tableItemStructure, idx) in tableHeadersForAudio" :key="idx">
+              <div v-if="tableItemStructure.type=='audio'" class="list-img">
+                <img
+                  :src="require('@/assets/images/icons/upload-file-type-icon-audio@2x.png')"
+                  style="object-fit: contain;"
+                  alt=""
+                >
+              </div>
+              <span  v-if="tableItemStructure.key !== 'name' && tableItemStructure.key !== 'fileSize'"></span>
+              <span  v-if="tableItemStructure.key === 'fileSize'">上传素材 {{item.progress * 100}}%</span>
+              <span  v-if="tableItemStructure.key === 'name'" class="ellipsis" v-title="tableItemStructure.key === 'name' ? item.title : ''">{{ item.title }}</span>
+            </span>
+          </template>
+          <!-- 如果上传失败了 -->
+          <template v-else-if="item.status = 'FAIL'">
+            <span class="table-data">
+              <div class="checkbox">
+                <span class="for-outer-circle"></span>
+                <span class="for-inner-circle disabled"></span>
+              </div>
+            </span>
+            <span class="table-data" v-for="(tableItemStructure, idx) in tableHeadersForImage" :key="idx">
+              <div v-if="tableItemStructure.type=='audio'" class="list-img">
+                <img
+                  :src="require('@/assets/images/icons/upload-file-type-icon-audio@2x.png')"
+                  style="object-fit: contain;"
+                  alt=""
+                >
+              </div>
+              <span  v-if="tableItemStructure.key !== 'name' && tableItemStructure.key !== 'fileSize'"></span>
+              <span  v-if="tableItemStructure.key === 'fileSize'">上传失败</span>
+              <span  v-if="tableItemStructure.key === 'name'" class="ellipsis" v-title="tableItemStructure.key === 'name' ? item.title : ''">{{ item.title }}</span>
+            </span>
+          </template>
+        </div>
+        <!-- 本组件内的列表数据 -->
         <div class="table-body-row" v-for="(item,i) in audioList" :key="i">
           <span class="table-data">
             <div class="checkbox">
@@ -152,7 +284,7 @@
           <span class="table-data" v-for="(sub,idx) in tableHeadersForAudio" :key="idx">
             <div v-if="sub.type=='audio'" class="list-img">
               <img
-                :src="require('@/assets/images/icons/icon-music@2x.png')"
+                :src="require('@/assets/images/icons/upload-file-type-icon-audio@2x.png')"
                 style="object-fit: contain;"
                 alt=""
               >
@@ -180,11 +312,82 @@
         <span class="table-head" v-for="(item,i) in tableHeadersForVideo" :key="i">{{item.name}}</span>
       </div>
       <div
-        v-if="videoList.length !== 0 || hasMoreVideoData"
+        v-if="videoListRealLength !== 0 || hasMoreVideoData"
         class="table-body"
         v-infinite-scroll="requestMoreVideoData"
         :infinite-scroll-disabled="!hasMoreVideoData || isRequestingMoreVideoData"
       >
+        <!-- vuex中的上传中数据 -->
+        <div class="table-body-row" v-for="(item, i) in uploadStatusListVideo" :key="item.uid">
+          <!-- 如果已经上传成功 -->
+          <template v-if="item.status === 'SUCCESS'">
+            <span class="table-data">
+              <div class="checkbox">
+                <!-- 负责功能 -->
+                <input
+                  type="checkbox"
+                  @change="e => selectItem(item.successInfo, e)"
+                  :checked="select.some(i => i[primaryKey] === item.successInfo[primaryKey])"
+                >
+                <!-- 负责外观 -->
+                <span class="for-outer-circle"></span>
+                <span class="for-inner-circle"></span>
+              </div>
+            </span>
+            <span class="table-data" v-for="(tableItemStructure, idx) in tableHeadersForVideo" :key="idx">
+              <div v-if="tableItemStructure.type=='image'" class="list-img">
+                <img
+                  :src="item.successInfo[tableItemStructure.key]"
+                  alt=""
+                >
+              </div>
+              <span  v-else class="ellipsis" v-title="tableItemStructure.key === 'name' ? item.successInfo[tableItemStructure.key] : ''">{{ item.successInfo[tableItemStructure.key] }}</span>
+            </span>
+          </template>
+          <!-- 如果还在上传中 -->
+          <template v-else-if="item.status = 'LOADING'">
+            <span class="table-data">
+              <div class="checkbox">
+                <span class="for-outer-circle"></span>
+                <span class="for-inner-circle disabled"></span>
+              </div>
+            </span>
+            <span class="table-data" v-for="(tableItemStructure, idx) in tableHeadersForVideo" :key="idx">
+              <div v-if="tableItemStructure.type=='image'" class="list-img">
+                <img
+                  :src="require('@/assets/images/icons/upload-file-type-icon-video@2x.png')"
+                  style="object-fit: contain;"
+                  alt=""
+                >
+              </div>
+              <span  v-if="tableItemStructure.key !== 'name' && tableItemStructure.key !== 'fileSize'"></span>
+              <span  v-if="tableItemStructure.key === 'fileSize'">上传素材 {{item.progress * 100}}%</span>
+              <span  v-if="tableItemStructure.key === 'name'" class="ellipsis" v-title="tableItemStructure.key === 'name' ? item.title : ''">{{ item.title }}</span>
+            </span>
+          </template>
+          <!-- 如果上传失败了 -->
+          <template v-else-if="item.status = 'FAIL'">
+            <span class="table-data">
+              <div class="checkbox">
+                <span class="for-outer-circle"></span>
+                <span class="for-inner-circle disabled"></span>
+              </div>
+            </span>
+            <span class="table-data" v-for="(tableItemStructure, idx) in tableHeadersForImage" :key="idx">
+              <div v-if="tableItemStructure.type=='image'" class="list-img">
+                <img
+                  :src="require('@/assets/images/icons/upload-file-type-icon-video@2x.png')"
+                  style="object-fit: contain;"
+                  alt=""
+                >
+              </div>
+              <span  v-if="tableItemStructure.key !== 'name' && tableItemStructure.key !== 'fileSize'"></span>
+              <span  v-if="tableItemStructure.key === 'fileSize'">上传失败</span>
+              <span  v-if="tableItemStructure.key === 'name'" class="ellipsis" v-title="tableItemStructure.key === 'name' ? item.title : ''">{{ item.title }}</span>
+            </span>
+          </template>
+        </div>
+        <!-- 本组件内的列表数据 -->
         <div class="table-body-row" v-for="(item,i) in videoList" :key="i">
           <span class="table-data">
             <div class="checkbox">
@@ -271,7 +474,7 @@
     </div>
 
     <div class="btns">
-      <button class="ui-button upload-btn">
+      <button v-if="currentMaterialType !== '3D'" class="ui-button upload-btn" @click="$refs['file-input'].click()">
         <span>上传素材</span>
         <i class="iconfont icon-material_prompt tool-tip-for-editor"
           v-tooltip="
@@ -279,7 +482,17 @@
             currentMaterialType === 'pano' ? '请上传2:1、120MB以内、jpg格式的图片' : ''
           ">
         </i>
+        <FileInput
+          ref="file-input"
+          :failString="fileInputFailString"
+          :limitFailStr="fileInputLimitFailStr"
+          :acceptType="fileInputAcceptType"
+          :mediaType="currentMaterialType"
+          :limit="fileInputLimit"
+          @file-change="onFileInputChange"
+        ></FileInput>
       </button>
+      <div v-else class="button-placeholder"></div>
       <div>
         <button class="ui-button deepcancel" @click="$emit('cancle')">取消</button>
         <button class="ui-button submit" :class="{disable: !select.length}" @click="$emit('submit', select)">
@@ -291,10 +504,18 @@
 </template>
 
 <script>
-import { getMaterialList, getSceneList } from "@/api";
+import {
+  getMaterialList,
+  getSceneList,
+  uploadMaterial,
+  editMaterial,
+  delMaterial,
+} from "@/api";
 import { changeByteUnit } from '@/utils/file'
 import config from "@/config";
 import { debounce } from "@/utils/other.js"
+import FileInput from "@/components/shared/uploads/UploadMultiple.vue";
+import { mapState } from "vuex";
 
 export default {
   props:{
@@ -327,6 +548,7 @@ export default {
     }
   },
   components:{
+    FileInput,
   },
   watch:{
     searchKey: {
@@ -353,6 +575,12 @@ export default {
     }
   },
   computed:{
+    ...mapState({
+      uploadStatusListAudio: 'uploadStatusListAudio',
+      uploadStatusListImage: 'uploadStatusListImage',
+      uploadStatusListPano: 'uploadStatusListPano',
+      uploadStatusListVideo: 'uploadStatusListVideo',
+    }),
     tableHeadersForImage() {
       return this.$MAPTABLEHEADER['image'].filter(item => {
         return ['icon', 'name', 'fileSize', 'dpi'].includes(item.key)
@@ -378,6 +606,121 @@ export default {
         return ['thumb', 'sceneName', 'createTime'].includes(item.key)
       })
     },
+    fileInputFailString() {
+      let ret = ''
+      switch (this.currentMaterialType) {
+        case 'pano':
+          ret = '格式错误,请上传2:1、120MB以内、jpg格式的全景图片'
+          break;
+        case 'image':
+          ret = '格式错误,请上传10MB以内、jpg/png格式的图片'
+          break;
+        case 'audio':
+          ret = '格式错误,请上传20MB以内、mp3格式的音频'
+          break;
+        case 'video':
+          ret = '格式错误,请上传200MB以内、mp4格式的视频'
+          break;
+        default:
+          break;
+      }
+      return ret
+    },
+    fileInputLimitFailStr() {
+      let ret = ''
+      switch (this.currentMaterialType) {
+        case 'pano':
+          ret = '过大,请上传2:1、120MB以内、jpg格式的全景图片'
+          break;
+        case 'image':
+          ret = '过大,请上传10MB以内、jpg/png格式的图片'
+          break;
+        case 'audio':
+          ret = '过大,请上传20MB以内、mp3格式的音频'
+          break;
+        case 'video':
+          ret = '过大,请上传200MB以内、mp4格式的视频'
+          break;
+        default:
+          break;
+      }
+      return ret
+    },
+    fileInputAcceptType() {
+      let ret = ''
+      switch (this.currentMaterialType) {
+        case 'pano':
+          ret = 'image/jpeg'
+          break;
+        case 'image':
+          ret = 'image/png,image/jpeg'
+          break;
+        case 'audio':
+          ret = 'audio/mp3'
+          break;
+        case 'video':
+          ret = 'video/mp4'
+          break;
+        default:
+          break;
+      }
+      return ret
+    },
+    fileInputmediaType() {
+      let ret = ''
+      switch (this.currentMaterialType) {
+        case 'pano':
+          ret = 'image'
+          break;
+        case 'image':
+          ret = 'image'
+          break;
+        case 'audio':
+          ret = 'audio'
+          break;
+        case 'video':
+          ret = 'video'
+          break;
+        default:
+          break;
+      }
+      return ret
+    },
+    fileInputLimit() {
+      let ret
+      switch (this.currentMaterialType) {
+        case 'pano':
+          ret = 120
+          break;
+        case 'image':
+          ret = 10
+          break;
+        case 'audio':
+          ret = 20
+          break;
+        case 'video':
+          ret = 200
+          break;
+        default:
+          break;
+      }
+      return ret
+    },
+    imageListRealLength() {
+      return this.imageList.length + this.uploadStatusListImage.filter((item) => {
+        return item.status === 'SUCCESS'
+      }).length
+    },
+    audioListRealLength() {
+      return this.audioList.length + this.uploadStatusListAudio.filter((item) => {
+        return item.status === 'SUCCESS'
+      }).length
+    },
+    videoListRealLength() {
+      return this.videoList.length + this.uploadStatusListVideo.filter((item) => {
+        return item.status === 'SUCCESS'
+      }).length
+    },
   },
   data () {
     return {
@@ -437,7 +780,7 @@ export default {
       const latestUsedSearchKey = this.searchKey
       getMaterialList(
         {
-          pageNum: Math.floor(this.imageList.length / config.PAGE_SIZE) + 1,
+          pageNum: Math.floor(this.imageListRealLength.length / config.PAGE_SIZE) + 1,
           pageSize: config.PAGE_SIZE,
           searchKey: this.searchKey,
           type: 'image',
@@ -450,7 +793,7 @@ export default {
             return i;
           });
           this.imageList = this.imageList.concat(newData)
-          if (this.imageList.length === data.data.total) {
+          if (this.imageListRealLength.length === data.data.total) {
             this.hasMoreImageData = false
           }
           this.isRequestingMoreImageData = false
@@ -497,7 +840,7 @@ export default {
       const latestUsedSearchKey = this.searchKey
       getMaterialList(
         {
-          pageNum: Math.floor(this.audioList.length / config.PAGE_SIZE) + 1,
+          pageNum: Math.floor(this.audioListRealLength / config.PAGE_SIZE) + 1,
           pageSize: config.PAGE_SIZE,
           searchKey: this.searchKey,
           type: 'audio',
@@ -510,7 +853,7 @@ export default {
             return i;
           });
           this.audioList = this.audioList.concat(newData)
-          if (this.audioList.length === data.data.total) {
+          if (this.audioListRealLength.length === data.data.total) {
             this.hasMoreAudioData = false
           }
           this.isRequestingMoreAudioData = false
@@ -527,7 +870,7 @@ export default {
       const latestUsedSearchKey = this.searchKey
       getMaterialList(
         {
-          pageNum: Math.floor(this.videoList.length / config.PAGE_SIZE) + 1,
+          pageNum: Math.floor(this.videoListReallength / config.PAGE_SIZE) + 1,
           pageSize: config.PAGE_SIZE,
           searchKey: this.searchKey,
           type: 'video',
@@ -541,7 +884,7 @@ export default {
             return i;
           });
           this.videoList = this.videoList.concat(newData)
-          if (this.videoList.length === data.data.total) {
+          if (this.videoListReallength === data.data.total) {
             this.hasMoreVideoData = false
           }
           this.isRequestingMoreVideoData = false
@@ -584,6 +927,10 @@ export default {
         this.isRequestingMoreImageData = false
         this.hasMoreImageData = true
         this.imageList = []
+        let filterResult = this.uploadStatusListImage.filter((item) => {
+          return item.status === 'LOADING'
+        })
+        this.$store.commit('setUploadStatusListImage', filterResult)
         this.requestMoreImageData()
       } else if (type === 'pano') {
         this.isRequestingMorePanoData = false
@@ -594,7 +941,20 @@ export default {
         this.isRequestingMoreAudioData = false
         this.hasMoreAudioData = true
         this.audioList = []
+        let filterResult = this.uploadStatusListAudio.filter((item) => {
+          return item.status === 'LOADING'
+        })
+        this.$store.commit('setUploadStatusListAudio', filterResult)
         this.requestMoreAudioData()
+      } else if (type === 'video') {
+        this.isRequestingMoreVideoData = false
+        this.hasMoreVideoData = true
+        this.videoList = []
+        let filterResult = this.uploadStatusListVideo.filter((item) => {
+          return item.status === 'LOADING'
+        })
+        this.$store.commit('setUploadStatusListVideo', filterResult)
+        this.requestMoreVideoData()
       } else if (type === '3D') {
         this.isRequestingMore3DData = false
         this.hasMore3DData = true
@@ -602,8 +962,355 @@ export default {
         this.requestMore3DData()
       }
     }, 700, false),
+    onFileInputChange(e) {
+      switch (this.currentMaterialType) {
+        case 'pano':
+          this.onPanoFileInputChange(e)
+          break;
+        case 'image':
+          this.onImageFileInputChange(e)
+          break;
+        case 'audio':
+          this.onAudioFileInputChange(e)
+          break;
+        case 'video':
+          this.onVideoFileInputChange(e)
+          break;
+        default:
+          break;
+      }
+    },
+    onPanoFileInputChange(e) {
+      e.files.forEach(async (eachFile, i) => {
+        if (
+          eachFile.type.indexOf("jpeg") <= -1
+        ) {
+          setTimeout(() => {
+            this.$msg({
+              message: `“${eachFile.name}”格式错误,请上传2:1、120MB以内、jpg格式的全景图片`,
+              type: "warning",
+            });
+          }, i * 100);
+          return;
+        }
+
+        if (eachFile.name.substring(0, eachFile.name.lastIndexOf(".")).length > 50) {
+          setTimeout(() => {
+            this.$msg({
+              message: `“${eachFile.name}”名称过长,请上传标题在50字以内的全景图片`,
+              type: "warning",
+            });
+          }, i * 100);
+          return;
+        }
+
+        let WHRate = null
+        try {
+          const {width, height} = await getImgWH(eachFile)
+          WHRate = width / height
+        } catch(e) {
+          console.error('获取图像宽高失败:', e)
+          setTimeout(() => {
+            this.$msg({
+              message: `“${eachFile.name}”格式错误,请上传2:1、120MB以内、jpg格式的全景图片`,
+              type: "warning",
+            });
+          }, i * 100);
+          return
+        }
+        if (WHRate !== 2) {
+          setTimeout(() => {
+            this.$msg({
+              message: `“${eachFile.name}”格式错误,请上传2:1、120MB以内、jpg格式的全景图片`,
+              type: "warning",
+            });
+          }, i * 100);
+          return
+        }
+
+        let itemInUploadList = {
+          title: eachFile.name,
+          ifKnowProgress: true,
+          progress: 0,
+          status: 'LOADING',
+          statusText: "正在上传素材",
+          uid: `u_${this.$randomWord(true, 8, 8)}`,
+          abortHandler: null,
+          backendId: '',
+        };
+
+        itemInUploadList.abortHandler = uploadMaterial(
+          {
+            file: eachFile
+          },
+          {
+            type: TYPE,
+            uid: itemInUploadList.uid,
+          },
+          (response) => { // 上传成功
+            itemInUploadList.statusText = '正在切图处理'
+            itemInUploadList.ifKnowProgress = false
+            itemInUploadList.backendId = response.data.id
+          },
+          (err) => {
+            if (err.statusText === 'abort') { // 用户取消了上传任务。
+              const index = this.uploadListForUI.findIndex((eachItem) => {
+                return eachItem.uid === itemInUploadList.uid
+              })
+              this.uploadListForUI.splice(index, 1)
+            } else {
+              itemInUploadList.status = 'FAIL'
+              itemInUploadList.statusText = '素材上传失败'
+            }
+          },
+          (progress) => {
+            itemInUploadList.progress = progress
+          }
+        )
+
+        this.uploadListForUI.push(itemInUploadList);
+      })
+    },
+    onImageFileInputChange(e) {
+      console.log('tableHeadersForImage: ', this.tableHeadersForImage);
+      
+      e.files.forEach((eachFile, i) => {
+        if (
+          eachFile.type.indexOf("jpeg") <= -1 &&
+          eachFile.type.indexOf("png") <= -1
+        ) {
+          setTimeout(() => {
+            this.$msg({
+              message: `“${eachFile.name}”格式错误,请上传10MB以内、jpg/png格式的图片`,
+              type: "warning",
+            });
+          }, i * 100);
+          return;
+        }
+
+        if (eachFile.name.substring(0, eachFile.name.lastIndexOf(".")).length > 50) {
+          setTimeout(() => {
+            this.$msg({
+              message: `“${eachFile.name}”名称过长,请上传标题在50字以内的图片`,
+              type: "warning",
+            });
+          }, i * 100);
+          return;
+        }
+
+        let itemInUploadList = {
+          title: eachFile.name,
+          ifKnowProgress: true,
+          progress: 0,
+          status: 'LOADING',
+          statusText: "正在上传素材",
+          uid: `u_${this.$randomWord(true, 8, 8)}`,
+          abortHandler: null,
+          successInfo: null,
+        };
+        
+        itemInUploadList.abortHandler = uploadMaterial(
+          {
+            file: eachFile
+          },
+          {
+            type: 'image',
+            uid: itemInUploadList.uid,
+          },
+          (result) => { // 上传成功
+            const index = this.uploadStatusListImage.findIndex((eachItem) => {
+              return eachItem.uid === itemInUploadList.uid
+            })
+            result.data.fileSize = changeByteUnit(Number(result.data.fileSize));
+            result.data.createTime = result.data.createTime.substring(0, result.data.createTime.length - 3)
+            result.data.updateTime = result.data.updateTime.substring(0, result.data.updateTime.length - 3)
+            this.uploadStatusListImage[index].status = 'SUCCESS'
+            this.uploadStatusListImage[index].successInfo = result.data
+            return i;
+          },
+          (err) => {
+            if (err.statusText === 'abort') { // 用户取消了上传任务。
+              console.log('用户取消了任务!');
+              const index = this.uploadStatusListImage.findIndex((eachItem) => {
+                return eachItem.uid === itemInUploadList.uid
+              })
+              this.uploadStatusListImage.splice(index, 1)
+            } else {
+              console.log('失败!');
+              itemInUploadList.status = 'FAIL'
+              itemInUploadList.statusText = '素材上传失败'
+            }
+          },
+          (progress) => {
+            console.log('进度:', progress);
+            itemInUploadList.progress = progress
+          }
+        );
+
+        this.uploadStatusListImage.unshift(itemInUploadList);
+      });
+    },
+    onAudioFileInputChange(e) {
+      e.files.forEach((eachFile, i) => {
+        if (eachFile.name.toLowerCase().indexOf("mp3") <= -1) {
+          setTimeout(() => {
+            this.$msg({
+              message: `“${eachFile.name}”格式错误,请上传20MB以内、mp3格式的音频`,
+              type: "warning",
+            });
+          }, i * 100);
+          return;
+        }
+
+        if (eachFile.name.substring(0, eachFile.name.lastIndexOf(".")).length > 50) {
+          setTimeout(() => {
+            this.$msg({
+              message: `“${eachFile.name}”名称过长,请上传标题在50字以内的音频`,
+              type: "warning",
+            });
+          }, i * 100);
+          return;
+        }
+
+        let itemInUploadList = {
+          title: eachFile.name,
+          ifKnowProgress: true,
+          progress: 0,
+          status: 'LOADING',
+          statusText: "正在上传素材",
+          uid: `u_${this.$randomWord(true, 8, 8)}`,
+          abortHandler: null,
+        };
+        
+        itemInUploadList.abortHandler = uploadMaterial(
+          {
+            file: eachFile
+          },
+          {
+            type: 'audio',
+            uid: itemInUploadList.uid,
+          },
+          (result) => { // 上传成功
+            console.log('success');
+            const index = this.uploadStatusListAudio.findIndex((eachItem) => {
+              return eachItem.uid === itemInUploadList.uid
+            })
+            result.data.fileSize = changeByteUnit(Number(result.data.fileSize));
+            result.data.createTime = result.data.createTime.substring(0, result.data.createTime.length - 3)
+            result.data.updateTime = result.data.updateTime.substring(0, result.data.updateTime.length - 3)
+            this.uploadStatusListAudio[index].status = 'SUCCESS'
+            this.uploadStatusListAudio[index].successInfo = result.data
+          },
+          (err) => {
+            console.log('error');
+            if (err.statusText === 'abort') { // 用户取消了上传任务。
+              console.log('用户取消了');
+              const index = this.uploadStatusListAudio.findIndex((eachItem) => {
+                return eachItem.uid === itemInUploadList.uid
+              })
+              this.uploadStatusListAudio.splice(index, 1)
+            } else {
+              console.log('上传失败');
+              itemInUploadList.status = 'FAIL'
+              itemInUploadList.statusText = '素材上传失败'
+            }
+          },
+          (progress) => {
+            console.log('progress');
+            itemInUploadList.progress = progress
+          }
+        );
+
+        this.uploadStatusListAudio.unshift(itemInUploadList);
+      });
+    },
+    onVideoFileInputChange(e) {
+      e.files.forEach((eachFile, i) => {
+        if (eachFile.name.toLowerCase().indexOf("mp4") <= -1) {
+          setTimeout(() => {
+            this.$msg({
+              message: `“${eachFile.name}”格式错误,请上传200MB以内、mp4格式的视频`,
+              type: "warning",
+            });
+          }, i * 100);
+          return;
+        }
+
+        if (eachFile.name.substring(0, eachFile.name.lastIndexOf(".")).length > 50) {
+          setTimeout(() => {
+            this.$msg({
+              message: `“${eachFile.name}”名称过长,请上传标题在50字以内的视频`,
+              type: "warning",
+            });
+          }, i * 100);
+          return;
+        }
+
+        let itemInUploadList = {
+          title: eachFile.name,
+          ifKnowProgress: true,
+          progress: 0,
+          status: 'LOADING',
+          statusText: "正在上传素材",
+          uid: `u_${this.$randomWord(true, 8, 8)}`,
+          abortHandler: null,
+        };
+        
+        itemInUploadList.abortHandler = uploadMaterial(
+          {
+            file: eachFile
+          },
+          {
+            type: 'video',
+            uid: itemInUploadList.uid,
+          },
+          (result) => { // 上传成功
+            console.log('成功!');
+            const index = this.uploadStatusListVideo.findIndex((eachItem) => {
+              return eachItem.uid === itemInUploadList.uid
+            })
+            result.data.fileSize = changeByteUnit(Number(result.data.fileSize));
+            result.data.createTime = result.data.createTime.substring(0, result.data.createTime.length - 3)
+            result.data.updateTime = result.data.updateTime.substring(0, result.data.updateTime.length - 3)
+            result.data.icon = result.data.ossPath + '?x-oss-process=video/snapshot,t_0,f_jpg,w_0,h_0,m_fast,ar_auto';
+            this.uploadStatusListVideo[index].status = 'SUCCESS'
+            this.uploadStatusListVideo[index].successInfo = result.data
+          },
+          (err) => {
+            if (err.statusText === 'abort') { // 用户取消了上传任务。
+              const index = this.uploadStatusListVideo.findIndex((eachItem) => {
+                return eachItem.uid === itemInUploadList.uid
+              })
+              this.uploadStatusListVideo.splice(index, 1)
+            } else {
+              itemInUploadList.status = 'FAIL'
+              itemInUploadList.statusText = '素材上传失败'
+            }
+          },
+          (progress) => {
+            console.log('进度:', progress);
+            itemInUploadList.progress = progress
+          }
+        );
+
+        this.uploadStatusListVideo.unshift(itemInUploadList);
+      });
+    },
   },
   mounted() {
+    console.log('tableHeadersForAudio: ', this.tableHeadersForAudio);
+    console.log('tableHeadersForVideo: ', this.tableHeadersForVideo);
+  },
+  unmounted() {
+    this.$store.commit('setUploadStatusListImage', this.uploadStatusListImage.filter((item) => {
+      return item.status === 'LOADING'
+    }))
+    this.$store.commit('setUploadStatusListAudio', this.uploadStatusListAudio.filter((item) => {
+      return item.status === 'LOADING'
+    }))
+    this.$store.commit('setUploadStatusListVideo', this.uploadStatusListVideo.filter((item) => {
+      return item.status === 'LOADING'
+    }))
   }
 }
 </script>
@@ -920,6 +1627,12 @@ export default {
     background: #0076F6;
     pointer-events: none;
     opacity: 0;
+    &.disabled {
+      width: 14px;
+      height: 14px;
+      background: rgba(255, 255, 255, 0.0800);
+      opacity: 1;
+    }
   }
 }