如何使用iview的upload实现vue自定义上传做一个可复用页面

上传实例


先看视频👆

如何使用iviewupload实现自定义上传 带图片放大功能

<template>
    <div class="customerUpload theme2022">
        <Upload
            ref="upload"
            class="file_uploader"
            :data="ticket"
            :show-upload-list="false"
            :on-success="handleSuccess"
            :on-progress="handleProgress"
            :before-upload="onBeforeUpload"
            multiple
            :accept="accept"
            type="drag"
            :action="uploadHost"
            :on-error="handleError"
        >
            <slot name="uploadBtn">
                <div class="ellipsis popup_upload" :class="errorFile?'error_files':''">
                    <div class="upload_field_btn"><icon font="2" class="icon-tianjia" style="font-size: 13px;margin-right: 6px;"></icon>点此上传文件</div>
                    <p class="upload_field_big">文件大小不超过{{size}}M</p>
                </div>
            </slot>
        </Upload>
        
        <!--        文档列表-->
        <ul class="demo-upload-list">
            <li v-for="(fileSrc,index) in uploadFiles" :key="'file1_'+index">
                <div  class="uploadFiles">
                    <icon font="2" class="icon-shangchuanwenjian-2" style="color:#5E6575;float: left;" slot="suffix"></icon>
                    <div class="uploadFilesName">{{fileSrc.fileName}}</div>
                    <div class="upload_mask">
                        <icon font="2" class="icon-shanchu-3 uploadFiles_cancel"  slot="suffix" @click="uploadFilesCancel(fileSrc)"></icon>
                    </div>
                </div>
            </li>
            <li v-for="(fileSrc,index) in uploadingFiles"  :key="'file2_'+index" >
                <div class="uploadFiles">
                    <icon font="2" class="icon-shangchuanwenjian-2" style="color:#5E6575;float: left;" slot="suffix"></icon>
                    <div class="uploadFilesName">{{fileSrc.fileName}}</div>
                    <div class="upload_mask">
                        <icon font="2" class="icon-shanchu-3 uploadFiles_cancel"  slot="suffix" @click="uploadingFilesCancel(fileSrc)"></icon>
                    </div>
                </div>
                <Progress  :stroke-width="3"  :percent="fileSrc.percentage" ></Progress>
            </li>
        </ul>
        <div class="upload-list"  v-for="(item,index) in uploadImgs"  :key="'imgs1'+index">
            <div class="upload-list-img">
                <div class="uploadNav">
                    <img :src="item.fileUrl" >
                    <div class="upload_mask">
                        <icon font="2" class="icon-chakan uploadFiles_cancel" @click="lookImgsPic(index)"></icon>
                        <icon font="2" class="icon-shanchu-3 uploadFiles_cancel" @click="uploadImgsCancel(item)"></icon>
                    </div>
                </div>
                
            </div>
        </div>
        <div class="upload-list"  v-for="(item,index) in uploadingImgs"     :key="'imgs2'+index">
            <div class="progress">
                <Progress  :stroke-width="3"  :percent="item.percentage"  stroke-color="#4a99ec"></Progress>
                <span class="progress_text" :title="item.fileName">{{item.fileName}}</span>
                <div class="upload_mask">
                    <icon font="2" class="icon-chakan uploadFiles_cancel uploading_disabled"></icon>
                    <icon font="2" class="icon-shanchu-3 uploadFiles_cancel" @click="uploadingImgsCancel(item)"></icon>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
import tool from "@/utils/common/tool";
import beforeUpload from "@/utils/common/beforeUpload";

export default {
    name: "customerUpload",
    props:{
        //默认文件数组
        value: {
            type: [Array,Object,Boolean],
            required: false,
            default(){
                return [];
            },
        },
        //最大文件数量
        count: {
            type: Number,
            required: false,
            default: 5,
        },

        //最大文件大小  单位MB
        size: {
            type: [Number,String],
            required: false,
            default: 50,//50MB2
        },
        // 页面点击确定之后文件是必填 但是文件没有内容 出现的error提示
        errorFile:{
            type: Boolean,
            default: false,
            required: false,
        }
    },
    data() {
        return {
            ticket:{},//上传接口的额外参数
            iconCancelShow:false,
            uploadHost: '',
            hostUrl: [],
            fileArr:[],
            format:[],
            //上传完成得文件和图片
            uploadFiles:[],
            uploadImgs:[],
            //正在上传得文件和图片
            uploadingFiles:[],
            uploadingImgs:[],
            accept:'.jpg,.jpeg,.gif,.png,.bmp,.xls,.xlsx,.xlsm,.csv,.ppt,.pptx,.doc,.docx,.pdf,.zip,.rar,.7z,.wav,.m4a,.mp3,.mp4,.avi,.tif,.tiff,.msg,.txt,.dwt,.dwg,.dws,.dxf,.ico',
            acceptImg:'.jpg,.jpeg,.gif,.png,.bmp',
            uploadCount: 0,//正在上传的数量
        }
    },
    computed:{
        limitType(){
            return this.accept.split(',')
        },
        accemtImg(){
            return this.acceptImg.split(',')
        }
    },
    watch: {
        value:{
            handler(newVal){
                console.log(556,newVal)
                this.newListValue(newVal)
            },
            deep:true,
            immediate: true,
        },
        errorFile:{
            handler(newVal){
                console.log('errorFile',newVal)
            },
            deep:true,
            immediate: true,
        }
    },
    methods:{
        handleError(error,file){
            tool.msgError(this,file.name+" 上传失败");
            
            console.log('error',error,file)
        },
        //生成缩略图
        thumbImg(url,w,h){
            console.log(557,url)
            w = w || 20;
            h = h || 20;
            if(url.indexOf('网站') > -1){
                if(url.indexOf('?')>-1){
                    url += '&x-oss-process=image/resize,m_fill,h_'+h+',w_'+w+'';
                }else{
                    url += '?x-oss-process=image/resize,m_fill,h_'+h+',w_'+w+'';
                }
            }
            return url;
        },
        newListValue(data){
            console.log(5567,data)  
            let filesData =[]
            let ImgsData = []
            if(data && data.length > 0){
                data.forEach((v)=>{
                    if(this.judgeListNew(v)){
                        console.log(7775,v)
                        v.thumb = this.thumbImg(v.fileUrl)
                        ImgsData.push(v)
                    }else{
                        console.log(7776,v)
                        filesData.push(v)
                    }
                })
            }
            this.uploadFiles = filesData
            this.uploadImgs = ImgsData
        },
        judgeListNew(file){
            let fileType = file.fileName.substr(file.fileName.lastIndexOf(".")).toLowerCase();  //截取最后一个点号及后字符 示例:'.jpg'
            let judgeImg = this.accemtImg.includes(fileType);//当前文件类型是否在数组中
            return judgeImg
        },
        //图片预览
        lookImgsPic(index){
            console.log(512,this.uploadImgs)
            let arr = []
			//上传成功的图片
            this.uploadImgs.forEach((v)=>{
                arr.push({
                    thumb:v.thumb,
                    url:v.fileUrl,
                    title:v.fileName,
                })
            })
            let opt = {
                images:arr,
                index:index
            };
            // console.log(7798,opt)
            tool.viewImages(this,opt);
        },
        uploadFilesCancel(data){
            console.log('删除所选文件',data,this.uploadFiles)
            this.uploadFiles.forEach((v,index)=>{
                if(data.fileName == v.fileName){
                    this.uploadFiles.splice(index,1)
                }
            })
            this.onChange()
        },
        uploadingFilesCancel(data){
            console.log('删除所选文件',data,this.uploadingFiles)
            this.uploadingFiles.forEach((v,index)=>{
                if(data.fileName == v.fileName){
                    this.uploadingFiles.splice(index,1)
                }
            })
        },
        //
        uploadImgsCancel(data){
            console.log('删除所选图片',data,this.uploadImgs)
            this.uploadImgs.forEach((v,index)=>{
                if(data.fileName == v.fileName){
                    this.uploadImgs.splice(index,1)
                }
            })
            this.onChange()
        },
        uploadingImgsCancel(data){
            console.log('删除所选图片',data,this.uploadingImgs)
            this.uploadingImgs.forEach((v,index)=>{
                if(data.fileName == v.fileName){
                    this.uploadingImgs.splice(index,1)
                }
            })
        },
        //是双向数据绑定触发onChange事件
        onChange() {
            console.log(1113,this.uploadImgs.length,this.uploadingImgs.length,this.uploadFiles.length,this.uploadingFiles.length)
            let fileArr = [];
            this.uploadFiles.forEach((v)=>{
                fileArr.push({
                    fileName: v.fileName,
                    fileUrl: v.fileUrl,
                })
            })
            this.uploadImgs.forEach((v)=>{
                fileArr.push({
                    fileName: v.fileName,
                    fileUrl: v.fileUrl,
                })
            })
            this.$emit('input', fileArr);  //传出外边文件格式
        },
      
        // 本地图片判断图片后缀
        onBeforeUpload(file) {
            //todo:格式限制
            console.log(332,this.$refs.upload.fileList.length)
            const fileType = file.name.substr(file.name.lastIndexOf(".")).toLowerCase();  //截取最后一个点号及后字符 示例:'.jpg'
            const check = (this.$refs.upload.fileList.length + this.uploadCount) < this.count;//fileList是已经上传好的文件列表,uploadCount是未上传的数量
            logDev('fileList.length:',this.$refs.upload.fileList.length,check)
            const isLt2M = file.size / 1024 / 1024 <= this.size;
            
            let isFileType = this.limitType.includes(fileType);//当前文件类型是否在数组中
            logDev(isFileType,fileType,this.limitType);
            if(!isFileType){
                tool.msgError(this,"文件类型应为:"+this.cpuAccept);
                return false;
            }
            if (!isLt2M) {
                tool.msgError(this,'上传文件大小不能超过'+this.size+'MB!');
                return false;
            }
            if (!check) {
                tool.msgError(this, '最多上传'+this.count+'个文件!');
                return check;
            }
            logDev('通过')
            let self = this;
            
            //获取toKen
            let pr1 = beforeUpload.get(file);
            let promise = new Promise((resolve,reject)=>{
                pr1.then((result)=>{
                    console.log(99,result)
                    self.ticket = result[0];
                    self.uploadHost = result[2];
                    file.url = result[1];
                    
                    this.editArr(file)
                    self.fileArr.push(file);//此时file中没有uid属性,且此file与上传成功后的file不相同
                    this.$nextTick(function(){
                        resolve(true)
                    })
                })
            })
            return promise
        },
        judgeList(file){
            let fileType = file.name.substr(file.name.lastIndexOf(".")).toLowerCase();  //截取最后一个点号及后字符 示例:'.jpg'
            let judgeImg = this.accemtImg.includes(fileType);//当前文件类型是否在数组中
            return judgeImg
        },
        editArr(file){
            let data1 = []
            let data2 = []
            console.log(55567,file,this.judgeList(file),file.name,file.url)
            if(this.judgeList(file)){
                data1.push({
                    fileName:file.name,
                    fileUrl:file.url,
                    file:file,
                    percentage:0,
                    thumb:this.thumbImg(file.url),
                })
            }else{
                data2.push({
                    fileName:file.name,
                    fileUrl:file.url,
                    file:file,
                    percentage:0,
                    thumb:this.thumbImg(file.url),
                })
            }
            this.uploadingImgs = data1
            this.uploadingFiles = data2
            console.log(9901,this.uploadingImgs,this.uploadingFiles)
        },
        //上传时的钩子
        handleProgress(event, file, fileList){
            console.log(8888,event, file,file.uid,fileList)
            console.log(44445,this.uploadingImgs,this.uploadingFiles)
			//上传中的文件和图片
            for(let i=0;i<this.uploadingImgs.length;i++){
                if(file.uid === this.uploadingImgs[i].file.uid){
                    console.log(7778, this.uploadingImgs[i].percentage,file.percentage)
                    this.uploadingImgs[i].percentage = parseInt(file.percentage)
                    return;
                }
            }
            for(let k=0;k<this.uploadingFiles.length;k++){
                if(file.uid === this.uploadingFiles[k].file.uid){
                    console.log(7778, this.uploadingFiles[k].percentage,file.percentage)
                    this.uploadingFiles[k].percentage = parseInt(file.percentage)
                    return;
                }

            }
            console.log(444,this.uploadingImgs,this.uploadingFiles)
        },
        // 本地图片上传成功
        handleSuccess(response, file) {
            console.log(664,file, this.uploadingImgs,this.uploadingFiles)
            //上传文件图片成功后将上传中的数组清空
            this.uploadingImgs.forEach((v,index)=>{
                if(file.uid === v.file.uid){
                    v.percentage = 100
                    setTimeout(()=>{
                        this.uploadImgs.push(v)
                        this.uploadingImgs.splice(index)
                        this.onChange()
                    },1000)

                }
            })

            this.uploadingFiles.forEach((v,index)=>{
                if(file.uid === v.file.uid){
                    v.percentage = 100
                    setTimeout((s)=>{
                        this.uploadFiles.push(v)
                        this.uploadingFiles.splice(index)
                        this.onChange()
                    },1000)
                }
            })
            console.log(88834,this.uploadFiles,this.uploadImgs)
        },
    }
}
</script>

<style scoped lang="less">
.customerUpload{
    width: 100%;
}
.upload-list{
    // display: inline-block;
    width: 129px;
    height: 129px;
    text-align: center;
    border-radius: 2px;
    //display: flex;
    border:1px dashed #DDE0E8;
    margin-right: 20px;
    float: left;
    margin-bottom: 10px;
    margin-top: 24px;
    .upload-list-img{
        width: 100%;
        height: 100%;
        .uploadNav{
            width: calc(100% - 12px);
            height: calc(100% - 12px);
            margin: 6px;
            position: relative;
            .upload_mask{
                width: 100%;
                height: 100%;
                display: none;
                position: absolute;
                left: 0;
                top: 0;
            }

            img{
                width: 100%;
                height: 100%;
            }
            &:hover{
                .upload_mask{
                    display: flex;
                    position: absolute;
                    left: 0;
                    top: 0;
                    width: 100%;
                    height: 100%;
                    background: rgba(0,0,0,0.3);
                    z-index: 999;
                    cursor: pointer;
                    justify-content: space-evenly;
                    align-items: center;
                    .uploadFiles_cancel{
                        color: #ffff;
                        font-size: 15px;
                    }
                    
                }
            }
        }
        
        
        
    }
    .progress{
        width: calc(100% - 12px);
        height: calc(100% - 12px);
        margin: 6px;
        display: flex;
        flex-wrap: wrap;
        flex-direction: column;
        position: relative;
        padding: 44px 0px 0px 10px;
        .upload_mask{
            width: 100%;
            height: 100%;
            display: none;
            position: absolute;
            left: 0;
            top: 0;
        }
        &:hover{
            .upload_mask{
                display: flex;
                position: absolute;
                left: 0;
                top: 0;
                width: 100%;
                height: 100%;
                background: rgba(0,0,0,0.3);
                z-index: 999;
                cursor: pointer;
                justify-content: space-evenly;
                align-items: center;
                .uploadFiles_cancel{
                    color: #ffff;
                    font-size: 15px;
                }
            }
        }
        .progress_text{
            width: 102px;
            text-align: center;
            overflow: hidden;
            word-break: keep-all;
            word-wrap: break-word;
            text-overflow: ellipsis;
            white-space: nowrap;
            display: inline-block;
        }
        .ivu-progress{
            /deep/.ivu-progress-outer{
                padding-right: 38px;
                margin-right: -36px;
            }
        }
    }
}
.demo-upload-list{
    display: flex;
    width: 100%;
    li{
        width: calc(24% - 5px);
        height: 100%;
        margin-right: 35px;
        margin-top: 26px;
        .uploadFiles{
            width: 100%;
            height: 36px;
            line-height: 36px;
            border-radius: 2px;
            border:1px dashed #DDE0E8;
            cursor: pointer;
            padding: 0px 9px;
            position: relative;
            .upload_mask{
                display: none;
            }
            &:hover{
                background: #F3F5F7;
                .upload_mask{
                    position: absolute;
                    display: block;
                    background:rgba(243,245,247,0);
                    left: 0;
                    top: 0;
                    width: 100%;
                    height: 100%;
                }
            }
            .uploadFilesName{
                float: left;
                font-size: 13px;
                font-weight: 400;
                color: rgba(0,0,0,0.9);
                margin-left: 5px;
            }
            .uploadFiles_cancel{
                float: right;
                margin-right: 9px;
            }
            
        }
        
    }
}
</style>

由于 iview中的插件不适合我所用的 所以自己封装了一下

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值