vue-图片/视频上传组件封装

封装代码:

<!-- 
    * @Descripttion:上传组件-->
<template>
    <div class='YxkUpload'>
    <div :class="[{
      'YxkUpload__slot': dataBind.isSlot}]">
      <el-upload 
        :before-upload="beforeUpload"
        :on-exceed="onExceed"
        :on-error="onError"
        :on-success="onSuccess"
        :on-remove="onRemove"
        v-bind="dataBind">
          <i class="el-icon-plus"></i>
          <slot></slot>
          <slot name="tip"></slot>
          <slot name="trigger"></slot>
      </el-upload>
    </div>
    </div>
</template>

<script>
    import Bucket from '../../api/modules/Qiniu/Bucket'
    import QiniuBucket from '../../api/modules/Qiniu/QiniuConstant'
    
    export default {
    name: 'YxkUpload',
    componentName: 'YxkUpload',
        props: {
            url: {
                type: String,
                default: ''
            },
            bucket: {
                type: String,
                default: ''
            },
            uploadObj: {
                type: Object
            }
        },
        components: {},
        data() {
            return {
                dataBind: {},    // 上传参数
                isSuccess: true, // 符合上传规则
                number: 0,       // 上传数量
                times: 0         // 防止多文件上传失败
            }
        },
        methods: {
            // 上传成功后数据处理
            changeUrl(file, fileList) {
                let urlObj = {
                    file: {},          // 当前上传文件数据
                    fileList: [],      // 上传文件所有数据
                    originName: [],    // 原文件名称
                    convertName: [],   // 私有化文件名
                    uploadUrl: [],     // 可视化文件数据
                }
                urlObj.file = file
                fileList.forEach(item => {
                    let key = item.response || ''
                    let imageUrl = key ? `${this.dataBind.linkUrl}${key.key}` : item.url
                    urlObj.originName.push(item.name ? item.name.slice(0, item.name.lastIndexOf('.')) : '')
                    urlObj.fileList.push(item)
                    urlObj.convertName.push(key.key)
                    urlObj.uploadUrl.push({
                        name: key.key,
                        url: imageUrl,
                    })
                })
        this.clearFileSet()
                this.$emit('change', urlObj)
            },
            // 上传前校验
            beforeUpload(file) {
                // 文件类型校验
                if (this.dataBind.acceptArr.indexOf(file.type) == -1) {
                    this.$message.error(`只能是${this.dataBind.accept}格式`)
                    this.backTop()
                    return false
                }
                // 文件大小判断
                const isLt = file.size / 1024 / 1024 < this.dataBind.size
                if (!isLt) {
                    const show = this.dataBind.size < 1 ? `${this.dataBind.size * 1024}KB` : `${this.dataBind.size}MB`
                    this.$message.error(`大小不能超过 ${show}!`);
                    this.backTop()
                    return false
                }
                // 文件尺寸大小判断
                if (this.dataBind.imgSize) {
                    let isSize = true
                    const {isRange, width, height} = this.dataBind.imgSize
                    const imgRule = new Promise((resolve, reject) => {
                        const img = new Image()
                        const _URL = window.URL || window.webkitURl
                        img.onload = () => {
                            file.width = img.width
                            file.height = img.height
                            const isValid = isRange ? (img.width <= width && img.height <= height) : (img.width == width && img.height == height);
                            isValid ? resolve(file) : reject();
                        }
                        img.src = _URL.createObjectURL(file)
                    }).then(file => {
                        isSize = true
                        this.setPathName(file)
                        return file
                    }, () => {
                        this.$message.error(`上传图片尺寸必须为${width}*${height}!`)
                        this.backTop()
                        isSize = false
                        return Promise.reject()
                    }).finally(() => {
                        this.isSuccess = isSize
                    })
                    return imgRule
                } else {
                    this.setPathName(file)
                }
            },
            // 文件数目超出
            onExceed() {
                this.$message.error(`当前限制 ${this.dataBind.limit} 数量,如需更换,请删除其它再重新选择!`)
                this.backTop()
            },
            // 上传失败
            onError(err, file, fileList) {
                this.dataBind.pathName = this.uploadObj.pathName // 防止token失效
                this.getQiNiu()
                this.$message.error(`上传出错,重新上传或刷新页面试试!Error:${err}`)
                this.backTop()
                this.$emit('onError', {err: err, file: file, fileList: fileList})
            },
            // 上传成功
            onSuccess(res, file, fileList) {
                this.times += 1
                if (this.times != fileList.length - this.number) { // 防止多文件上传失败
                  return false 
                } else {
                  this.times = 0
                  this.number = fileList.length
                }
                this.isSuccess && this.changeUrl(file, fileList)
            },
            // 文件删除
            onRemove(file, fileList) {
                if (file && file.status === "success") {
                    this.number = fileList.length
                    this.changeUrl(file, fileList);
                    this.$emit('onRemove', {file: file, fileList: fileList})
                }
            },
            // 文件类型
            fileTypeSet() {
                let acceptArr = this.dataBind.accept.split(',')
                this.dataBind.acceptArr = []
                acceptArr.forEach(item => {
                    switch (item) {
                        case '.png':
                            this.dataBind.acceptArr.push('image/png')
                        break;
                        case '.jpg':
                            this.dataBind.acceptArr.push('image/jpg', 'image/jpeg')
                        break;
                        case '.gif':
                            this.dataBind.acceptArr.push('image/gif')
                        break;
                        case '.mp4':
                            this.dataBind.acceptArr.push('video/mp4')
                        break;
                        case '.pdf':
                            this.dataBind.acceptArr.push('application/pdf')
                        break;
                        case '.xls':
                            this.dataBind.acceptArr.push('application/vnd.ms-excel')
                        break;
                        case '.xlsx':
                            this.dataBind.acceptArr.push('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
                        break;
                        case '.doc':
                            this.dataBind.acceptArr.push('application/msword')
                        break;
                        case '.docx':
                            this.dataBind.acceptArr.push('application/vnd.openxmlformats-officedocument.wordprocessingml.document')
                        break;
                    }
                })
            },
            // 设置文件存储
            setPathName(file) {
                let pathName = `${this.dataBind.pathName}`//获取文件后缀
                let suffix = file.name.substring(file.name.lastIndexOf("."), file.name.length)// 设置存储到七牛云文件名称
                let fileName = new Date().getTime(); // 时间戳
                this.dataBind.data.key = `${pathName}${fileName + suffix}`; // 文件夹/文件名称/时间戳/.格式
            },
      // 其它参数设置
      paramsSet() {
        // 是否含有插槽
        this.dataBind.isSlot = this.$slots.default
        if (this.dataBind.isSlot) {
          this.dataBind['show-file-list'] = false
        }
        // 初始化多文件上传
        if(this.dataBind['file-list']) {
          this.number = this.dataBind['file-list'].length
        }
      },
      // 清空已上传文件列表
      clearFileSet() {
        if (this.dataBind.clearFiles) {
          this.times = 0
          this.number = 0
          this.dataBind['show-file-list'] = false
          this.$refs[this.dataBind.ref].clearFiles()
        }
      },
            // 返回顶部
            backTop() {
                if (!this.dataBind.backTop) return
                // 限于iframe嵌入页
                window.parent.scrollTo({
                    top: 0,
                    behavior: 'smooth'
                })
            },
            // default 初始化
            initialSet(obj) {
                let uploadDefault = {
                    ref: 'YxkUpload',
                    action: 'https://up.qiniup.com/',
                    limit: 999,
                    size: 3,
                    accept: '.png,.jpg',
                    pathName: 'product',
                    bucket: QiniuBucket.PUBLIC_GALLERY,
                    multiple: true,
                    backTop: false,
                    drag: true,
                    'show-file-list': true,
                    'list-type': 'picture-card'
                }
                this.dataBind = {...uploadDefault, ...this.dataBind, ...obj}
                this.fileTypeSet()
                this.paramsSet()
            },
            // el-upload 参数
            dataBindSet() {
                return this.deleteParams(this.dataBind, ['size', 'pathName', 'avator', 'acceptArr', 'linkUrl'])
            },
            // delete 
            deleteParams(obj, arr) {
                let params = JSON.parse(JSON.stringify(obj))
                arr.forEach(item => {
                    delete params[item]
                })
                return params
            },
            // 获取七牛token
            getQiNiu() {
                if (this.dataBind.token) {
                    this.$set(this.dataBind, 'data', {token: this.dataBind.token})
                    return false
                }
                const bucketApi = new Bucket(this.bucket || QiniuBucket.PUBLIC_GALLERY, { url: this.url || this.dataBind.url })
                bucketApi.getBucketToken({
                    bucket: this.dataBind.bucket,
                    moduleName: this.dataBind.pathName,
                    path_prefix: this.dataBind.pathName
                }).then((res) => {
                    if (res.code == 200) {
                        this.dataBind.action = res.data.domain || res.data.upDomain  // 七牛存储域
                        this.dataBind.linkUrl = res.data.cdnDomain                   // 文件展示地址
                        this.dataBind.pathName = res.data.path                       // 文件存储地址
                        this.$set(this.dataBind, 'data', {token: res.data.token})    // token
                    } else {
                        this.$message.error(res.msg);
                    }
                })
            }
        },
        computed: {},
        watch: {
            uploadObj: {
                handler(n) {
                    this.initialSet(n)
                },
                deep: true,
                immediate: true
            }
        },
        created() {},
        mounted() {
            this.getQiNiu()
        }
    }
</script>

<style lang='scss'>
    .YxkUpload{
        .el-upload-list{
            .el-upload-list__item{
                width: 100px;
                height: 100px;
            }
        }
        .el-upload{
            width: 100px;
            height: 100px;
            line-height: 100px;
            .el-upload-dragger{
                width: auto;
                height: auto;
                border: none;
                background: none;
            }
        }
    .YxkUpload__slot{
      .el-upload{
        width: auto;
        height: auto;
        line-height: 0;
        border: none;
        .el-icon-plus{
          display: none;
        }
      }
    }
    }
</style>

参数说明:

 

 

 

 

 

 

 

posted @ 2023-11-17 16:34  忙着可爱呀~  阅读(345)  评论(0)    收藏  举报