Explorar o código

上传组件 重构

DESKTOP-O04BTUJ\muzen %!s(int64=2) %!d(string=hai) anos
pai
achega
6fc1ce9fe6
Modificáronse 1 ficheiros con 148 adicións e 175 borrados
  1. 148 175
      src/components/Upload/index.vue

+ 148 - 175
src/components/Upload/index.vue

@@ -1,201 +1,130 @@
 <template>
   <div class="upload">
-    <el-upload v-if="hidden" :action="newAction" :headers="headers" :multiple="multiple" :data="data"
-      :accept="accept" :show-file-list="showFileList" :list-type="listType" :on-progress="onProgress"
-      :on-error="onError" :on-success="onSuccess" :before-upload="beforeUpload" :disabled="disabled">
-      <el-button v-if="listType !== 'picture-card'" :type="btnType">{{ newTitle }}</el-button>
-      <i v-else class="el-icon-plus" />
+    <el-upload v-if="isBtn()" :action="action" :headers="headers" :multiple="multiple" :data="data"
+      :name="name" :show-file-list="showFileList" :drag="drag" :accept="accept" :listType="listType"
+      :autoUpload="autoUpload" :disabled="disabled" :before-upload="beforeUpload" :on-progress="onProgress"
+      :on-success="onSuccess" :on-error="onError">
+      <el-button v-if="listType === 'text'" :type="type" size="mini" ref="upload">
+        <slot v-if="percentage <= 0 && !form.file">点击上传</slot>
+        <span v-if="percentage > 0 && !form.file">{{ title }}</span>
+        <span v-if="form.file">上传成功</span>
+      </el-button>
+      <div v-else>
+        <i class="el-icon-plus" />
+      </div>
     </el-upload>
-    <el-progress v-if="isShow()" type="circle" :percentage="percent" :status="isStatus" />
-    <div class="upload-image" v-if="newUrl">
-      <el-image :src="newUrl" />
-      <i v-if="disabled === false" class="el-icon-delete" @click="getDelete" />
+    <el-progress v-if="isPercentage()" type="circle" :percentage="percentage" :status="status"
+      @click.native="handleUpload" :width="146" />
+    <div class="img" v-if="isImg()">
+      <i class="el-icon-delete" v-if="!disabled" @click="onDelete" />
+      <el-image :src="form.file" />
     </div>
   </div>
 </template>
 
 <script>
 const baseUrl = process.env.VUE_APP_BASE_API
-import { getToken } from "@/utils/auth";
+import { getToken } from '@/utils/auth'
 export default {
   props: {
-    action: {
-      type: String,
-      default: ''
-    },
-    // 图片
+    // 回显图片
     url: String,
-    // 类型
-    listType: {
-      type: String,
-      default: 'text'
+    // 是否支持多选文件
+    multiple: {
+      type: Boolean,
+      default: false
     },
-    // 是否显示已上传文件列表
+    // 是否显示文件列表
     showFileList: {
       type: Boolean,
       default: false
     },
-    // 是否支持多选文件
-    multiple: {
+    // 是否支持拖拽上传
+    drag: {
       type: Boolean,
       default: false
     },
+    // 上传类型
+    listType: {
+      type: String,
+      default: 'text'
+    },
+    // 是否支持自动上传
+    autoUpload: {
+      type: Boolean,
+      default: true
+    },
     // 是否禁用
     disabled: {
       type: Boolean,
       default: false
     },
-    // 上传按钮文字
-    title: {
-      type: String,
-      default: '文件上传'
-    },
+    // 最大允许上传个数
+    limit: Number,
     // 图片尺寸
-    measure: {
-      type: String,
-      default: ''
-    },
+    width: Number,
+    height: Number,
     // 文件大小
     size: Number
   },
   data() {
     return {
+      // 上传类型
+      obj: {
+        'text': `${baseUrl}/system/file/file/upload`,
+        'picture-card': `${baseUrl}/system/file/picture/upload`
+      },
       // 上传地址
-      newAction: baseUrl + this.action,
-      // 请求头
+      action: '#',
+      // 请求头
       headers: {
-        Authorization: "Bearer " + getToken(),
+        Authorization: "Bearer " + getToken()
       },
-      // 附带参数
+      // 额外参数
       data: {},
-      // 文件字段名
-      name: '',
-      // 是否显示上传按钮
-      hidden: true,
-      // 按钮文字
-      newTitle: this.title,
-      // 按钮颜色
-      btnType: 'primary',
+      // 文件名
+      name: 'multipartFile',
+      // 文件类型
+      accept: '',
       // 进度条
-      percent: 0,
-      // 上传失败进度条
-      isStatus: null,
-      // 显示图片
-      newUrl: this.url,
-      // 传给父级的参数
-      form: {},
-      // 上传图片的尺寸
-      width: Number(this.measure.split('*')[0]),
-      height: Number(this.measure.split('*')[1]),
-      // 上传的文件格式
-      accept: ''
+      percentage: 0,
+      title: '',
+      // 进度条状态
+      status: null,
+      type: 'primary',
+      // 表单
+      form: {
+        size: 0,
+        file: ''
+      }
     }
   },
-  watch: {
-    measure(val) {
-      this.width = Number(val.split('*')[0])
-      this.height = Number(val.split('*')[1])
-    },
+  watch:{
     url(val) {
-      this.newUrl = val ? val : ''
-      this.hidden = val ? false : true
+      this.form.file = val
     }
   },
-  mounted() {
-    if (!this.action) {
-      if (this.listType === 'picture-card') {
-        this.newAction = `${baseUrl}/system/file/picture/upload`
-        this.accept = '.jpg, .jpeg, .png, .bmp, .icon, .gif'
-      } else if (this.listType === 'text') {
-        this.newAction = `${baseUrl}/system/file/file/upload`
-      } else if (this.listType === 'audio') {
-        this.newAction = `${baseUrl}/system/file/mp3/upload`
-        this.accept = '.mp3, .wav, .aiff, .midi, .wma'
-      }
-    }
-    this.newUrl = this.url ? this.url : ''
-    this.hidden = this.url ? false : true
+  created() {
+    // 根据上传类型 变更 上传地址
+    this.action = this.obj[this.listType]
+    // 根据上传类型 变更 文件类型
+    this.accept = this.listType === 'picture-card' ? '.jpg, .jpeg, .png, .bmp, .icon, .gif' : ''
+    // 回显图片
+    this.form.file = this.url
   },
   methods: {
     // 上传之前
-    async beforeUpload(file) {
-      this.btnType = 'primary'
-      if (this.measure || this.size) {
-        await this.measureChecked(file).then((res) => {
-          if (res) {
-            this.isUpload(file)
-          }
-        })
-      } else {
-        this.isUpload(file)
-      }
-    },
-
-    // 上传
-    isUpload(file) {
-      this.data.multipartFile = file
-      this.name = file.name
-      if (this.listType !== 'picture-card') {
-        this.form.size = file.size
-      } else {
-        this.hidden = false
-      }
-    },
-
-    // 上传过程中
-    onProgress(e) {
-      this.percent = parseInt(e.percent)
-      this.newTitle = `已上传${parseInt(e.percent - 1)}%`
-      this.$emit('loading')
-      this.visible = true
-    },
-
-    // 上传失败
-    onError() {
-      this.newTitle = `上传失败`
-      this.btnType = `danger`
-      this.isStatus = 'exception'
-      this.$emit('upload')
-    },
-
-    // 上传成功
-    onSuccess(res) {
-      if (this.listType === 'picture-card') {
-        // 显示图片
-        this.newUrl = res.data
-      } else {
-        // 按钮文字
-        this.newTitle = '上传成功'
-        this.btnType = 'success'
-      }
-      // 传参
-      this.form.file = res.data
-      this.$emit('upload', this.form)
-    },
-
-    // 删除图片
-    getDelete() {
-      if (this.listType == 'picture-card') {
-        this.hidden = true
-        this.percent = 0
-        this.newUrl = ''
-      }
-      this.$emit('upload', this.form = {})
-    },
-
-    // 是否显示图片进度条
-    isShow() {
-      if (this.listType == 'picture-card') {
-        return !this.hidden && this.newUrl === '' ? true : false
-      } else {
-        return false
+    beforeUpload(file) {
+      if ((this.width && this.height) || this.size) {
+        this.checked(file)
       }
+      this.form.size = file.size
     },
 
     // 判断图片尺寸 或 文件大小
-    measureChecked(file) {
+    checked(file) {
       return new Promise((resolve, reject) => {
-        if (this.measure) {
+        if (this.listType === 'picture-card') {
           let reader = new FileReader()
           reader.readAsDataURL(file)
           reader.onload = () => {
@@ -203,8 +132,8 @@ export default {
             img.src = reader.result
             img.onload = () => {
               if (img.width !== this.width || img.height !== this.height) {
-                this.$message.error(`请上传${this.measure}尺寸的图片`)
-                reject
+                this.$message.error(`请上传${this.width}x${this.height}尺寸的图片`)
+                reject(false)
               } else {
                 resolve(true)
               }
@@ -212,15 +141,56 @@ export default {
           }
         }
 
-        if (this.size) {
-          if ((file.size / 1024 / 1024) > this.size) {
-            this.$message.error(`上传文件过大`)
-            reject
-          } else {
-            resolve(true)
-          }
+        if (this.size !== '' && ((file.size / 1024 / 1024) > this.size)) {
+          this.$message.error(`文件大小不超过${this.size}`)
+          reject(false)
+        } else {
+          resolve(true)
         }
       })
+    },
+
+    // 上传过程中
+    onProgress(file) {
+      this.percentage = parseInt(file.percent - 1)
+      this.title = `已上传 ${parseInt(file.percent - 1)}%`
+    },
+
+    // 上传成功
+    onSuccess(file) {
+      this.form.file = file.data
+      this.$emit('upload', this.form)
+    },
+
+    // 上传失败
+    onError() {
+      this.status = 'exception'
+      this.type = 'danger'
+      this.title = '上传失败'
+    },
+
+    // 删除
+    onDelete() {
+      this.form.file = ''
+      this.percentage = 0
+    },
+
+    // 如果上传失败 重新上传
+    handleUpload() {
+      this.percentage = 0
+    },
+
+    // 上传按钮
+    isBtn() {
+      return this.listType === 'text' || (this.listType === 'picture-card' && this.percentage == 0 && !this.form.file)
+    },
+    // 显示进度条
+    isPercentage() {
+      return this.listType === 'picture-card' && this.percentage !== 0 && !this.form.file
+    },
+    // 显示图片
+    isImg() {
+      return this.listType === 'picture-card' && this.form.file
     }
   }
 }
@@ -230,39 +200,42 @@ export default {
 .upload {
   display: inline-block;
 
-  .el-button {
-    margin: 0;
+  .el-icon-plus {
+    line-height: 146px;
   }
 
-  .upload-image {
+  .img {
     position: relative;
-    width: 148px;
-
-    .el-image {
-      display: block;
-    }
+    width: 146px;
+    height: 146px;
+    border-radius: 5px;
 
     .el-icon-delete {
+      width: 100%;
+      height: 100%;
       position: absolute;
       top: 50%;
       left: 50%;
-      width: 100%;
-      height: 100%;
       transform: translate(-50%, -50%);
-      background: rgb(0 0 0 / 50%);
+      text-align: center;
+      line-height: 146px;
+      z-index: 99;
+      opacity: 0;
+      font-size: 24px;
       color: #fff;
       transition: all 0.3s;
-      font-size: 24px;
-      opacity: 0;
-      display: flex;
-      justify-content: center;
-      align-items: center;
+      background: rgb(0 0 0 / 50%);
     }
 
-    i:hover {
+    .el-icon-delete:hover {
       opacity: 1;
       cursor: pointer;
     }
+
+    .el-image {
+      width: 100%;
+      height: 100%;
+    }
   }
 }
 </style>