Przeglądaj źródła

feat: 文件上传组件增加上传进度显示功能并优化上传逻辑

yusheng 5 miesięcy temu
rodzic
commit
84a6fe9836
2 zmienionych plików z 280 dodań i 215 usunięć
  1. 2 2
      src/api/system/file/index.js
  2. 278 213
      src/components/upload/fileUpload1.vue

+ 2 - 2
src/api/system/file/index.js

@@ -19,11 +19,11 @@ export async function uploadFile (data) {
  * 上传文件
  * @param file 文件
  */
- export async function uploadFileNew (data) {
+ export async function uploadFileNew (data, config = {}) {
   const formData = new FormData();
   formData.append('multiPartFile', data.multiPartFile);
   formData.append('module', data.module);
-  const res = await request.post('/main/file/uploadFile', formData);
+  const res = await request.post('/main/file/uploadFile', formData, config);
   if (res.data.code === '0') {
     return res.data;
   }

+ 278 - 213
src/components/upload/fileUpload1.vue

@@ -3,8 +3,7 @@
     <el-upload
       class="upload-demo"
       action="#"
-      v-loading="loading"
-      element-loading-text="上传中"
+      :disabled="disabled || loading"
       :http-request="handlRequest"
       :before-remove="beforeRemove"
       :on-remove="handleRemove"
@@ -12,8 +11,7 @@
       :multiple="multiple"
       :before-upload="beforeUpload"
       :file-list="fileList"
-      :show-file-list="!showLib"
-      :disabled="disabled"
+      :show-file-list="!loading"
     >
       <!-- <slot>
         <el-button :disabled="disabled" type="primary" icon="el-icon-plus" size="mini">点击上传</el-button>
@@ -28,233 +26,300 @@
       >
       <slot name="templateBtn"> </slot>
     </el-upload>
+    <div
+      v-if="loading"
+      class="upload-progress"
+      :style="{
+        height: Object.keys(this.fileProgressMap).length * 50 + 'px'
+      }"
+    >
+      <div
+        v-for="(progress, fileId) in fileProgressMap"
+        :key="fileId"
+        class="progress-item"
+      >
+        <div class="file-name">{{ fileNameMap[fileId] }}</div>
+        <el-progress
+          :percentage="progress"
+          :stroke-width="6"
+        ></el-progress>
+      </div>
+    </div>
   </div>
 </template>
 
 <script>
-import {
-  uploadFileNew,
-  removeFile,
-  getFileList,
-  getFile
-} from '@/api/system/file/index.js';
-import { getImageUrl, getImagePath } from '@/utils/file';
-export default {
-  props: {
-    value: {
-      type: [Array, String],
-      default: () => []
-    },
-    multiple: {
-      type: Boolean,
-      default: false
-    },
-    // 所属模块
-    module: {
-      type: String,
-      required: true
-    },
-    // 文档库
-    showLib: {
-      type: Boolean,
-      default: false
-    },
-    // 限制数量
-    limit: {
-      type: Number,
-      default: -1
-    },
-    // 限制大小 mb
-    size: {
-      type: Number,
-      default: 1000
-    },
-    disabled: {
-      default: false,
-      type: Boolean
-    }
-  },
-  data() {
-    return {
-      documentVisible: false,
-      selectItem: null,
-      loading: false,
-      documentForm: {
-        name: ''
+  import {
+    uploadFileNew,
+    removeFile,
+    getFileList,
+    getFile
+  } from '@/api/system/file/index.js';
+  import { getImageUrl, getImagePath } from '@/utils/file';
+  export default {
+    props: {
+      value: {
+        type: [Array, String],
+        default: () => []
       },
-      columns: [
-        {
-          label: '序号',
-          type: 'index',
-          width: 55,
-          align: 'center'
-        },
-        {
-          label: '文档名称',
-          prop: 'name',
-          minWidth: '180',
-          showOverflowTooltip: true
-        },
-        {
-          label: '文档类型',
-          prop: 'type'
-        },
-        {
-          label: '系统'
-        },
-        {
-          label: '储存路径',
-          prop: 'storePath',
-          minWidth: '180',
-          showOverflowTooltip: true
-        },
-        {
-          label: '模块名',
-          prop: 'module'
-        },
-        {
-          label: '上传时间',
-          prop: 'createTime'
-        }
-      ]
-    };
-  },
-  computed: {
-    fileList: {
-      set(val) {
-        // console.log(val);
-        this.$emit(
-          'input',
-          val.map((item) => ({
-            ...item,
-            url: getImagePath(item.url)
-          }))
-        );
+      multiple: {
+        type: Boolean,
+        default: false
       },
-      get() {
-        // console.log(this.value, 2);
-        if (!Array.isArray(this.value)) return [];
-        const arr =
-          (this.value &&
-            this.value.map((item) => ({
-              ...item,
-              url: getImageUrl(item.url)
-            }))) ||
-          [];
-        return arr;
+      // 所属模块
+      module: {
+        type: String,
+        required: true
+      },
+      // 文档库
+      showLib: {
+        type: Boolean,
+        default: false
+      },
+      // 限制数量
+      limit: {
+        type: Number,
+        default: -1
+      },
+      // 限制大小 mb
+      size: {
+        type: Number,
+        default: 1000
+      },
+      disabled: {
+        default: false,
+        type: Boolean
       }
-    }
-  },
-
-  methods: {
-    //点击查看图片
-    handleItem(file) {
-      getFile({ objectName: file.storePath }, file.name);
-    },
-    delFileList() {
-      this.$emit('input', []);
-    },
-    handleOpenLib() {
-      this.documentVisible = true;
-      this.$nextTick(() => {
-        this.reload();
-      });
     },
-    //图文档勾选
-    submitDocument() {
-      this.$emit('input', [
-        { url: this.selectItem.storePath, ...this.selectItem }
-      ]);
-      this.documentVisible = false;
-    },
-    datasource({ page, limit }) {
-      return getFileList({
-        ...this.documentForm,
-        pageNum: page,
-        size: limit
-      });
-    },
-    reload() {
-      this.$refs.table.reload();
+    data() {
+      return {
+        documentVisible: false,
+        selectItem: null,
+        loading: false,
+        uploadProgress: 0,
+        fileProgressMap: {},
+        fileNameMap: {},
+        documentForm: {
+          name: ''
+        },
+        columns: [
+          {
+            label: '序号',
+            type: 'index',
+            width: 55,
+            align: 'center'
+          },
+          {
+            label: '文档名称',
+            prop: 'name',
+            minWidth: '180',
+            showOverflowTooltip: true
+          },
+          {
+            label: '文档类型',
+            prop: 'type'
+          },
+          {
+            label: '系统'
+          },
+          {
+            label: '储存路径',
+            prop: 'storePath',
+            minWidth: '180',
+            showOverflowTooltip: true
+          },
+          {
+            label: '模块名',
+            prop: 'module'
+          },
+          {
+            label: '上传时间',
+            prop: 'createTime'
+          }
+        ]
+      };
     },
-    beforeRemove(file) {
-      if (file.id) {
-        // return removeFile({
-        //   fileId: file.id
-        // }).then(() => {
-        //   return true;
-        // });
-        return true;
-      } else {
-        return true;
+    computed: {
+      fileList: {
+        set(val) {
+          // console.log(val);
+          this.$emit(
+            'input',
+            val.map((item) => ({
+              ...item,
+              url: getImagePath(item.url)
+            }))
+          );
+        },
+        get() {
+          // console.log(this.value, 2);
+          if (!Array.isArray(this.value)) return [];
+          const arr =
+            (this.value &&
+              this.value.map((item) => ({
+                ...item,
+                url: getImageUrl(item.url)
+              }))) ||
+            [];
+          return arr;
+        }
       }
     },
-    handleRemove(file, fileList) {
-      this.fileList = fileList;
-    },
-    beforeUpload(file) {
-      // if (file.size / 1024 / 1024 > this.size) {
-      //   this.$message.error(`大小不能超过 ${this.size}MB`);
-      //   return false;
-      // }
 
-      if (this.limit > 0 && this.fileList.length === this.limit) {
-        this.$message.error(`最多上传 ${this.limit}个文件`);
-        return false;
-      }
-      this.loading = true;
-      return uploadFileNew({
-        module: this.module,
-        multiPartFile: file
-      })
-        .then((res) => {
-          if (res.data) {
-            this.$emit('input', [
-              ...(this.value || []),
-              { ...file, url: res.data.storePath, ...res.data }
-            ]);
-          }
-          this.$emit('fileChange', res.data);
-          return res.data;
-        })
-        .finally(() => {
-          this.loading = false;
+    methods: {
+      //点击查看图片
+      handleItem(file) {
+        getFile({ objectName: file.storePath }, file.name);
+      },
+      delFileList() {
+        this.$emit('input', []);
+      },
+      handleOpenLib() {
+        this.documentVisible = true;
+        this.$nextTick(() => {
+          this.reload();
         });
-    },
-    handlRequest() {
-      return Promise.resolve();
+      },
+      //图文档勾选
+      submitDocument() {
+        this.$emit('input', [
+          { url: this.selectItem.storePath, ...this.selectItem }
+        ]);
+        this.documentVisible = false;
+      },
+      datasource({ page, limit }) {
+        return getFileList({
+          ...this.documentForm,
+          pageNum: page,
+          size: limit
+        });
+      },
+      reload() {
+        this.$refs.table.reload();
+      },
+      beforeRemove(file) {
+        if (file.id) {
+          // return removeFile({
+          //   fileId: file.id
+          // }).then(() => {
+          //   return true;
+          // });
+          return true;
+        } else {
+          return true;
+        }
+      },
+      handleRemove(file, fileList) {
+        removeFile({ fileId: file.id });
+        this.fileList = fileList;
+      },
+      beforeUpload(file) {
+        // if (file.size / 1024 / 1024 > this.size) {
+        //   this.$message.error(`大小不能超过 ${this.size}MB`);
+        //   return false;
+        // }
+
+        if (this.limit > 0 && this.fileList.length === this.limit) {
+          this.$message.error(`最多上传 ${this.limit}个文件`);
+          return false;
+        }
+        const fileId = file.uid || Date.now();
+        this.loading = true;
+        this.$set(this.fileProgressMap, fileId, 0);
+        this.$set(this.fileNameMap, fileId, file.name);
+        return uploadFileNew(
+          {
+            module: this.module,
+            multiPartFile: file
+          },
+          {
+            onUploadProgress: (progressEvent) => {
+              if (progressEvent.total) {
+                this.$set(
+                  this.fileProgressMap,
+                  fileId,
+                  Math.round((progressEvent.loaded * 100) / progressEvent.total)
+                );
+              }
+            }
+          }
+        )
+          .then((res) => {
+            if (res.data) {
+              this.$emit('input', [
+                ...(this.value || []),
+                { ...file, url: res.data.storePath, ...res.data }
+              ]);
+            }
+            this.$emit('fileChange', res.data);
+            return res.data;
+          })
+          .finally(() => {
+            this.$delete(this.fileProgressMap, fileId);
+            this.$delete(this.fileNameMap, fileId);
+            if (Object.keys(this.fileProgressMap).length === 0) {
+              this.loading = false;
+            }
+          });
+      },
+      handlRequest() {
+        return Promise.resolve();
+      }
+      // onSuccess(response, file, fileList){
+      //   alert(1)
+      //    this.$emit('fileChange',file)
+      // },
     }
-    // onSuccess(response, file, fileList){
-    //   alert(1)
-    //    this.$emit('fileChange',file)
-    // },
-  }
-};
+  };
 </script>
 
 <style lang="scss" scoped>
-.upload-file {
-  display: flex;
-  justify-content: flex-start;
-  align-items: center;
+  .upload-file {
+    display: flex;
+    justify-content: flex-start;
+    // align-items: center;
+    flex-direction: column;
+    width: 80%;
 
-  .lib {
-    margin-left: 12px;
-  }
+    .lib {
+      margin-left: 12px;
+    }
 
-  .imgs-box {
-    margin-left: 10px;
-    flex: 1;
-  }
-  .imgs-box .imgs-p {
-    height: 30px;
-    background: #f0f3f3;
-    line-height: 30px;
-    min-width: 480px;
-    margin-bottom: 5px;
-    padding: 0 10px;
-    display: flex;
-    justify-content: space-between;
+    .imgs-box {
+      margin-left: 10px;
+      flex: 1;
+    }
+    .imgs-box .imgs-p {
+      height: 30px;
+      background: #f0f3f3;
+      line-height: 30px;
+      min-width: 480px;
+      margin-bottom: 5px;
+      padding: 0 10px;
+      display: flex;
+      justify-content: space-between;
+    }
+
+    .upload-progress {
+      // position: absolute;
+      // margin-top: 10px;
+      top: 40px;
+      width: 100%;
+      // max-width: 400px;
+
+      .progress-item {
+        margin-bottom: 5px;
+
+        .file-name {
+          height: 25px;
+          font-size: 12px;
+          color: #606266;
+          margin-bottom: 4px;
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+        }
+      }
+    }
   }
-}
 </style>