|
|
@@ -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>
|