上传实例
先看视频👆
如何使用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中的插件不适合我所用的 所以自己封装了一下