LR 3 anni fa
parent
commit
1c5b949693
1 ha cambiato i file con 111 aggiunte e 0 eliminazioni
  1. 111 0
      src/components/Base/FileUploader/index.vue

+ 111 - 0
src/components/Base/FileUploader/index.vue

@@ -0,0 +1,111 @@
+<template>
+  <div class="tf-file-uploader">
+    <slot name="title">{{ title }}</slot>
+    <span style="margin-left: 5px; color: #ccc">(最多上传{{ limit }}张)</span>
+    <div
+      style="margin-top: 20px"
+      class="upload"
+      :style="`--display: ${files.length >= limit ? 'none' : 'inline-flex'}`"
+    >
+      <el-upload :file-list="files" v-on="$listeners" v-bind="attrs">
+        <i class="el-icon-plus" />
+      </el-upload>
+    </div>
+    <tf-image-preview :visible.sync="visible" :src="url" />
+  </div>
+</template>
+
+<script lang="ts">
+  import { ElUploadInternalFileDetail } from 'element-ui/types/upload'
+  import { Vue, Component, Prop, VModel } from 'vue-property-decorator'
+
+  @Component({ name: 'TfFileUploader', inheritAttrs: false })
+  export default class TfFileUploader extends Vue {
+    @VModel({ type: Array, default: () => [] }) files!: ElUploadInternalFileDetail[]
+    @Prop({ type: String }) title!: string
+    @Prop({ type: Number, default: 9 }) limit!: number
+    @Prop({ type: Number, default: 10 }) maxSize!: number
+
+    url: string = ''
+    visible: boolean = false
+
+    get attrs() {
+      return {
+        listType: 'picture-card',
+        multiple: true,
+        autoUpload: false,
+        action: 'whatever',
+        accept: '.jpg,.jpeg,.png',
+        drag: true,
+        onRemove: this.onRemove,
+        onChange: this.onFileChange,
+        onPreview: this.onPreview,
+        ...this.$attrs
+      }
+    }
+
+    onRemove(file) {
+      this.files = this.files.filter((item) => item.uid !== file.uid)
+    }
+    onPreview(file) {
+      this.url = file.url
+      this.visible = true
+    }
+
+    async onFileChange(file: ElUploadInternalFileDetail, files: ElUploadInternalFileDetail[]) {
+      setTimeout(() => {
+        const imageTypes = ['image/jpeg', 'image/png']
+        const { size, name, raw: { type } = {} } = file
+        const accept = this.attrs.accept.split(',')
+
+        const handleError = (msg) => {
+          console.log(msg, '\n', files.length, this.files.length)
+          this.$message.error(msg)
+          this.onRemove(file)
+          return new Error(msg)
+        }
+        if (!imageTypes.includes(type) || !accept.some((item) => String(name).endsWith(item))) {
+          return handleError(`上传文件只能是 ${accept.join(', ')} 格式!`)
+        }
+        if (size / 1024 / 1024 > this.maxSize) {
+          return handleError(`上传文件大小不能超过 ${this.maxSize} MB!`)
+        }
+        if (this.files.length >= this.limit) {
+          return handleError(`最多可以上传${this.limit}张图片!`)
+        }
+        this.files = [...this.files, file]
+        console.log(this.$attrs)
+        return true
+      }, 0)
+    }
+  }
+</script>
+
+<style lang="scss" scoped>
+  .tf-file-uploader {
+    .upload {
+      overflow: hidden;
+      margin-right: -16px;
+      >>> .el-upload {
+        &-list__item,
+        &--picture-card,
+        &-dragger {
+          width: 130px;
+          height: 130px;
+          line-height: normal;
+          display: inline-flex;
+          align-items: center;
+          justify-content: center;
+        }
+        &-dragger {
+          width: 100%;
+          height: 100%;
+          border: none;
+        }
+        &.el-upload--picture-card {
+          display: var(--display);
+        }
+      }
+    }
+  }
+</style>