效果图 展示
后端人员未开发多图上传 只能想个办法一次上传多张
<!-- 使用组件 -->
<template>
<view class="container">
<view class="title">上传图片</view>
<!-- 调用方法 -->
<upload-file :style="uploadStyle" :data="uploadData" max="9" type="image" @complete="getFile"></upload-file>
</view>
</template>
<script>
export default {
data() {
return {
uploadStyle: {
columns: 4,
gap: 18,
radius: 0
},
uploadData: {
icon: '/static/icon/upload.png',//点击上传的图片路径 用时替换成自己的
deleteIcon: '/static/icon/delete.png',//删除图标的路径 用时替换成自己的
imageUrl: '', //按自己的需求填写
domainUrl: '', //按自己的需求填写
},
}
},
methods: {
getFile(data) {
console.log(data)
}
}
}
</script>
<style lang="scss" scoped>
.title {
font-size: 36rpx;
color:#000;
font-weight: bold;
}
</style>
组件文件夹及命名 components/upload-file/upload-file.vue 有需要可自行更改
<template>
<view class="content"
:style="{'grid-template-columns': 'repeat('+styleData.columns+', 1fr)','column-gap':styleData.gap+'rpx','row-gap':styleData.gap+'rpx'}">
<view v-for="(item,index) in images" :key="index" class="item">
<image class="image" :src="setImageUrl(item.tempFilePath)" mode="aspectFill"
:style="{'border-radius':styleData.radius+'rpx'}"></image>
<image v-if="item.status!=1" class="delete" :src="data.deleteIcon" mode="widthFix"
@click="deleteClick(index)">
</image>
<view v-if="item.status==1" class="text" :style="{'border-radius':styleData.radius+'rpx'}">上传中</view>
<view v-if="item.status==3" class="text" :style="{'border-radius':styleData.radius+'rpx'}">图片过大</view>
<view v-if="item.status==2" class="text fail" :style="{'border-radius':styleData.radius+'rpx'}" @click="repeatUpload(index)">上传失败</view>
</view>
<view v-if="images.length<max" class="item" @click="uploadImage">
<image class="image" :src="data.icon" mode="widthFix"></image>
</view>
</view>
</template>
<script>
export default {
name: "upload-file",
props: {
styleData: { //样式配置 grid布局
type: Object,
default: {
columns: 4, //每排显示个数
gap: 18, //行列间距 单位rpx
radius: 0 //图片圆角配置
}
},
data: { //基础配置
type: Object,
default: {
icon: '', //点击上传的图片路径
deleteIcon: '', //删除图标的路径
imageUrl: '', //图片的域名 全域名可不填写
domainUrl: '', //上传图片的域名
}
},
max: { //最大上传数量 默认9
type: [String, Number],
default: 9
},
type: { //上传文件的类型 image video
type: String,
default: 'image' //默认为image
},
},
data() {
return {
images: []
};
},
methods: {
uploadImage() {
this.chooseFile(this.max - this.images.length).then(res => {
//循环添加以下初始状态 0上传成功 1上传中 2上传失败 3图片过大
this.images = [...this.images, ...res.tempFiles.map(item => {
item.status = 1
if (item.size >= (1024 * 1024 * 4))
item.status = 3
return item
})]
this.upload()
})
},
// 批量上传
upload(index = 0) {
// 最后一张图片上传完成后通知
if (index >= this.images.length) {
this.uplaodComplete()
return
}
let item = this.images[index];
// 通过图片路径和状态判断是否需要上传
if ((item.tempFilePath.substring(0, 4) == "http" || item.tempFilePath.substring(0, 6) == "wxfile") && item
.status == 1) {
// 上传完成后修改 相应的状态
this.uploadFile(item.tempFilePath).then(res => {
this.images[index].status = 0
this.images[index].tempFilePath = res.data
this.upload(index + 1)
}).catch(err => {
this.images[index].status = 2
this.upload(index + 1)
})
} else {
this.upload(index + 1)
}
},
// 获取图片
chooseFile(num) {
return new Promise((resolve, reject) => {
uni.chooseMedia({
count: num,
mediaType: [this.type],
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera'],
success: res => {
resolve(res)
},
fail(err) {}
});
});
},
// 上传图片
uploadFile(filePath) {
return new Promise((resolve, reject) => {
uni.uploadFile({
header: {
Authorization: uni.getStorageSync('token')
},
url: this.data.domainUrl,
filePath: filePath,
name: 'upload',
formData: {
dir: 'image'
},
success: res => {
let data = JSON.parse(res.data)
resolve(data)
},
fail: err => reject(err)
});
})
},
// 上传失败 重新上传
repeatUpload(index) {
this.images[index].status = 1
this.uploadFile(this.images[index]).then(res => {
this.images[index].status = 0
this.images[index].tempFilePath = res.data
this.uplaodComplete()
}).catch(err => {
this.images[index].status = 2
this.uplaodComplete()
})
},
// 删除图片
deleteClick(index) {
this.images = this.images.filter((v, i) => i != index)
},
// 长传完成通知父级
uplaodComplete() {
this.$emit('complete', this.images)
},
setImageUrl(url) {
if (!/\.(gif|jpg|jpeg|png|GIF|JPG|PNG|pdf|mp4)$/.test(url))
return url
if (url.substring(0, 4) != "http" && url.substring(0, 6) != "wxfile") {
url = this.data.imageUrl + url
}
return url
}
}
}
</script>
<style lang="scss" scoped>
.content {
display: grid;
grid-template-columns: repeat(4, 1fr);
column-gap: 18rpx;
}
.item {
position: relative;
width: 100%;
padding-top: 100%;
overflow: hidden;
}
.upload {
position: relative;
width: 100%;
padding-top: 100%;
}
.image {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
.text {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.2);
z-index: 9;
font-size: 26rpx;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
overflow: hidden;
}
.delete {
position: absolute;
right: 10rpx;
top: 10rpx;
width: 30rpx;
height: 30rpx;
z-index: 11;
}
.text.fail {
color: #f00;
}
</style>
以上只是做个模板 提供一个思路