记录 uni-app多图片(视频)上传组件封装

效果图 展示

 

后端人员未开发多图上传 只能想个办法一次上传多张

<!-- 使用组件 -->
<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>

以上只是做个模板 提供一个思路 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

招来红月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值