index.vue 10.6 KB
<style lang="scss" src="./style.scss">
</style>

<template>
    <div :class="uploadWrapClass" style="position: relative">
        <el-upload
            ref="uploader"
            :accept="setting.accept"
            :multiple="multiple"
            :action="''"
            :drag="setting.drag"
            :list-type="setting.listType"
            :http-request="uploadFile"
            :show-file-list="typeof setting.showFileList ==='boolean'? setting.showFileList:true"
            :file-list="fileList"
            :limit="typeof setting.limit !=='undefined'?setting.limit:limit"
            :on-success="handleSuccess"
            :on-error="handleError"
            :on-remove="handleRemove"
            :before-upload="handleBeforeUpload"
            :on-exceed="handleExceed"
            :on-change="handleChange"
            :class="`uploader${disabled?' disabled':''}`"
            :disabled="disabled"
        >
            <el-checkbox v-if="multiple" v-model="value" type="hidden" style="position: absolute;top:-1000em"/>
            <el-input v-else v-model="value" type="hidden" style="position: absolute"/>
            <template v-if="type === 'cover'">
                <div slot="default">
                    <i class="el-icon-upload"/>
                    <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
                </div>
            </template>
            <template v-else-if="type === 'image' && limit === 1">
                <i slot="default" class="el-icon-plus"/>
            </template>
            <template v-else-if="type === 'image'">
                <i slot="default" class="el-icon-plus"/>
            </template>
            <template v-else>
                <el-button size="small" :disabled="disabled">{{ fileName }}</el-button>
            </template>
        </el-upload>
        <el-dialog :visible.sync="dialogVisible">
            <img v-if="dialogImageUrl" width="100%" :src="dialogImageUrl" alt="">
        </el-dialog>
    </div>

</template>

<script>
    import uploadFile from '@/utils/uploadFile';
    import {numberFormatter} from '@/utils/filters';
    import {deepClone} from '@/utils';

    export default {
        name: 'QgUpload',
        props: {
            value: {
                type: [String, Array],
                default: ''
            },
            id: {
                type: String,
                default: 'qgUpload' + new Date().getTime()
            },
            type: {
                type: String,
                default: 'file' // file or image or cover
            },
            fileName: {
                type: String,
                default: '选择文件'
            },
            multiple: {
                type: Boolean,
                default: false
            },
            disabled: {
                type: Boolean,
                default: false
            },
            limit: {
                type: Number,
                default: 0
            },
            limitSize: {
                type: Number,
                default: 100 * 1024 * 1024 // 默认文件大小限制100M
            },
            accept: {
                type: String,
                default: ''
            },
            defaultFiles: {
                type: [Array, Object],
                default: () => {
                }
            },
            formData: {
                type: Object,
                default: () => {
                    return {
                        appCode: 'dev-uc',
                        funCode: 'user'
                    };
                }
            }
        },
        data() {
            return {
                uploader: null,
                time: 0,
                setting: {
                    listType: 'file'
                },
                dialogImageUrl: '',
                dialogVisible: false,
                fileList: [],
                defaultList: [],
                uploading: false,
                percentage: 0
            };
        },
        computed: {
            uploadWrapClass() {
                console.log(this.type);
                const className = ['qg-fs-uploader'];
                if (this.type === 'cover') {
                    className.push('qg-upload__cover-img');
                    className.push('el-upload-dragger');
                    if (this.fileList.length > 0) {
                        className.push('success');
                    }
                } else if (this.limit === 1 && this.setting.limit === 0 && this.type === 'image') {
                    className.push('qg-upload__single-img');

                    if (this.fileList.length > 0) {
                        className.push('success');
                    }
                } else {
                    className.push('qg-upload__file');
                }

                return className.join(' ');
            }
        },
        watch: {
            defaultFiles(val, oldVal) {
                if (val) {
                    this.transDefFiles(val);
                }
            }
        },
        created() {
            switch (this.type) {
                case 'image':
                    this.setting = {
                        listType: 'picture-card',
                        accept: '.jpg,.jpeg,.png,.gif'
                    };
                    if (this.limit === 1) {
                        this.$set(this.setting, 'limit', 0);
                    }
                    break;
                case 'cover':
                    this.setting = {
                        listType: 'picture-card',
                        drag: true,
                        accept: '.jpg,.jpeg,.png'
                    };
                    this.limit = 1;
                    this.$set(this.setting, 'limit', 0);
                    break;
                case 'file':
                    this.setting = {
                        listType: 'file',
                        accept: '.pdf, .txt, .zip, .rar, .7z, .doc, .docx, .xls, .xlsx, .ppt, .pptx, .mp3, .mp4,.jpg,.jpeg,.png,.gif,.ps,.sketch,.rp,.wps,.sql,.html,.js,.css,.json,.svg,.md,.java'
                    };
                    if (this.limit === 1) {
                        this.$set(this.setting, 'limit', 0);
                    }
                    break;
            }
            if (this.accept) {
                this.$set(this.setting, 'accept', this.accept);
            }

            if (this.defaultFiles) {
                this.transDefFiles(this.defaultFiles);
            }
        },
        mounted() {
        },
        methods: {
            transDefFiles(val) {
                const fileList = [];
                if (val && !Array.isArray(val)) {
                    val = [val];
                }
                val.map(item => {
                    fileList.push({
                        id: item.id || item.fileId,
                        name: item.name || item.fileName,
                        url: item.url || item.viewUrl,
                        downloadUrl: item.downloadUrl || item.url || item.viewUrl,
                        data: item
                    });
                });
                this.defaultList = fileList;
                this.fileList = fileList;
            },
            uploadFile(data) {
                this.uploading = true;
                const _this = this;
                uploadFile(data.file, this.formData, function(res) {
                    if (res && res.success) {
                        data.onSuccess(res);
                    } else {
                        data.onError(res);
                    }
                }, function(progress) {
                    console.log(progress);
                    _this.percentage = progress.percent.toFixed(2);
                    data.onProgress(progress);
                });
            },
            handleBeforeUpload(file) {
                if (file.size > this.limitSize) {
                    this.$message.warning(`“${file.name}”文件超过${numberFormatter(this.limitSize, 2)}大小,无法上传!`);
                    return false;
                }
                file.uploading = true;
                file.progress = 0;
            },
            handleSuccess(res, file, fileList) {
                this.uploading = false;
                file.data = res.data;
                file.id = res.data.fileId;
                file.url = res.data.viewUrl;
                file.uploading = false;
                this.fileList = deepClone(fileList);
                console.log('this.multiple', this.multiple);
                if (this.multiple) {
                    const ids = this.value || [];
                    ids.push(res.data.fileId);
                    this.$emit('input', ids);
                } else {
                    this.$emit('input', res.data.fileId);
                }

                this.$emit('success', res, fileList);
            },
            handleError(err, file) {
                this.uploading = false;
                this.$emit('error', err);
            },
            handleRemove(file, fileList) {
                if (fileList.length === 0) {
                    if (this.multiple) {
                        this.$emit('input', []);
                    } else {
                        this.$emit('input', '');
                    }
                } else {
                    const ids = [];
                    fileList.map(item => {
                        ids.push(item.id);
                    });
                    this.$emit('input', ids);
                }
                this.fileList = fileList;
                this.$emit('remove', file, fileList);
            },
            delFile(index, file) {
                this.fileList.splice(index, 1);
                if (file.data) {
                    this.$refs.uploader.abort(file);
                }
            },
            handleExceed(files, fileList) {
                this.$message.warning(`最多可以上传${this.limit}个文件,已选择 ${fileList.length} 个文件,本次选择了 ${files.length} 个文件,超出限制数量!`);
            },
            handleChange(file, fileList) {
                if (this.limit === 1 && fileList.length > 1) {
                    fileList.shift();
                }
                file.uploading = true;
                file.progress = 0;
                this.fileList = deepClone(fileList);
            },
            handleProgress(event, file, fileList) {
                file.progress = event.percent > 100 ? 100 : event.percent.toFixed(2);
                this.fileList = deepClone(fileList);
            },
            handlePicturePreview(file) {
                this.dialogImageUrl = file.url;
                this.dialogVisible = true;
            }
        }
    };
</script>