uniapp封装上传图片and上传视频组件

 第一步:封装

<!-- media-uploader.vue -->
<template>
	<view class="up-page">
		<!-- 图片展示 -->
		<view class="show-box" v-for="(item,index) in imageList" :key="'img-'+index">
			<image class="full" :src="item" @tap="previewImage(item)" />
			<view class="delect-icon" @tap="handleDelete('image', index)" v-if="!disabled">
				<image class="full" :src="clearIcon" />
			</view>
		</view>

		<!-- 视频展示 -->
		<view class="show-box" v-for="(item, index) in videoList" :key="'video-'+index">
			<video class="full" :src="item" />
			<view class="delect-icon" @tap="handleDelete('video', index)" v-if="!disabled">
				<image class="full" :src="clearIcon" />
			</view>
		</view>

		<!-- 上传按钮 -->
		<view v-if="showUploadBtn&&!disabled" @tap="showMediaPicker" class="box-mode upload-btn">
			<image class="full" :src="selectfile" />
		</view>
	</view>
</template>

<script>
	const DEFAULT_CONFIG = {
		maxCount: 9,
		sourceTypes: ['拍摄', '相册', '拍摄或相册'],
		cameraOptions: [{
				value: 'back',
				name: '后置摄像头',
				checked: true
			},
			{
				value: 'front',
				name: '前置摄像头'
			}
		]
	}

	export default {
		name: 'MediaUploader',
		props: {
			// 配置项
			maxCount: {
				type: Number,
				default: DEFAULT_CONFIG.maxCount
			},
			// 初始媒体文件
			initialImages: {
				type: Array,
				default: () => []
			},
			initialVideos: {
				type: Array,
				default: () => []
			},
            // 是否禁用状态
			disabled: {
				type: Boolean,
				default: false
			}
		},
		data() {
			return {
				clearIcon: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMCAwaDE2YTQgNCAwIDAgMSA0IDR2MTZINGE0IDQgMCAwIDEtNC00VjB6IiBmaWxsPSJ1cmwoI3BhaW50MF9saW5lYXIpIiBmaWxsLW9wYWNpdHk9Ii45OCIgZmlsdGVyPSJ1cmwoI2ZpbHRlcjBfYikiLz48cGF0aCBkPSJNMTAuOTQgOS45OTlsMi44NjMtMi44NTdhLjY2OS42NjkgMCAxIDAtLjk0Ni0uOTQ2TDEwIDkuMDYgNy4xNDMgNi4xOTZhLjY2OS42NjkgMCAwIDAtLjk0Ni45NDZsMi44NjQgMi44NTctMi44NjQgMi44NTdhLjY2Ni42NjYgMCAwIDAgLjIxNyAxLjA5Mi42NjQuNjY0IDAgMCAwIC43MjktLjE0NkwxMCAxMC45MzhsMi44NTcgMi44NjRhLjY2Ny42NjcgMCAwIDAgMS4wOTItLjIxNy42NjYuNjY2IDAgMCAwLS4xNDYtLjcyOUwxMC45MzkgMTB6IiBmaWxsPSIjZmZmIi8+PGRlZnM+PGZpbHRlciBpZD0iZmlsdGVyMF9iIiB4PSItNCIgeT0iLTQiIHdpZHRoPSIyOCIgaGVpZ2h0PSIyOCIgZmlsdGVyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBjb2xvci1pbnRlcnBvbGF0aW9uLWZpbHRlcnM9InNSR0IiPjxmZUZsb29kIGZsb29kLW9wYWNpdHk9IjAiIHJlc3VsdD0iQmFja2dyb3VuZEltYWdlRml4Ii8+PGZlR2F1c3NpYW5CbHVyIGluPSJCYWNrZ3JvdW5kSW1hZ2UiIHN0ZERldmlhdGlvbj0iMiIvPjxmZUNvbXBvc2l0ZSBpbjI9IlNvdXJjZUFscGhhIiBvcGVyYXRvcj0iaW4iIHJlc3VsdD0iZWZmZWN0MV9iYWNrZ3JvdW5kQmx1ciIvPjxmZUJsZW5kIGluPSJTb3VyY2VHcmFwaGljIiBpbjI9ImVmZmVjdDFfYmFja2dyb3VuZEJsdXIiIHJlc3VsdD0ic2hhcGUiLz48L2ZpbHRlcj48bGluZWFyR3JhZGllbnQgaWQ9InBhaW50MF9saW5lYXIiIHgxPSIyMCIgeDI9IjE1LjU4NiIgeTI9IjIyLjk0IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agc3RvcC1jb2xvcj0iIzBEMUUyOCIgc3RvcC1vcGFjaXR5PSIuOCIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzA1MEUxMiIgc3RvcC1vcGFjaXR5PSIuNjUiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48L3N2Zz4=',
				selectfile: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjQiIGhlaWdodD0iNjQiIHZpZXdCb3g9IjAgMCA2NCA2NCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB4PSIuMjUiIHk9Ii4yNSIgd2lkdGg9IjYzLjUiIGhlaWdodD0iNjMuNSIgcng9IjMuNzUiIGZpbGw9IiNGMkYyRjIiIHN0cm9rZT0iI0YyRjJGMiIgc3Ryb2tlLXdpZHRoPSIuNSIvPjxyZWN0IHg9IjE2IiB5PSIzMSIgd2lkdGg9IjMyIiBoZWlnaHQ9IjIiIHJ4PSIxIiBmaWxsPSIjQkZCRkJGIi8+PHJlY3QgeD0iMzMiIHk9IjE2IiB3aWR0aD0iMzIiIGhlaWdodD0iMiIgcng9IjEiIHRyYW5zZm9ybT0icm90YXRlKDkwIDMzIDE2KSIgZmlsbD0iI0JGQkZCRiIvPjwvc3ZnPg==',
				imageList: [...this.initialImages],
				videoList: [...this.initialVideos],
				sourceTypeIndex: 2,
				cameraIndex: 0,
				action: this.$config.apiUrl+'/sys/common/upload',
			}
		},
		computed: {
			showUploadBtn() {
				return (this.imageList.length + this.videoList.length) < this.maxCount
			}
		},
		methods: {
			// 统一媒体选择
			showMediaPicker() {
				uni.showActionSheet({
					title: '选择上传类型',
					itemList: ['图片', '视频'],
					success: ({
						tapIndex
					}) => {
						tapIndex === 0 ? this.chooseImage() : this.chooseVideo()
					}
				})
			},

			// 选择图片
			async chooseImage() {
				try {
					const token = uni.getStorageSync('Access-Token');
					const res = await uni.chooseImage({
						count: this.remainingCount,
						sizeType: ['original', 'compressed'],
						sourceType: ['album', 'camera']
					})
					res[1].tempFiles.map(item=>{
						uni.uploadFile({
							url: this.action,
							fileType: 'image',
							file: item,
							name: 'file',
							header: {
								"X-Access-Token":token
							},
							formData: {
								'biz': 'temp'
							},
							success: (file) =>{
								this.imageList.push(this.$config.apiUrl+'/sys/common/static/'+JSON.parse(file.data).message);
								this.$emit('update:images', this.imageList)
							},
							fail: (err)=>{}
						})
					})
				} catch (error) {
					this.$emit('error', error)
				}
			},

			// 选择视频
			async chooseVideo() {
				try {
					const token = uni.getStorageSync('Access-Token');
					const res = await uni.chooseVideo({
						maxDuration: 15,
						camera: DEFAULT_CONFIG.cameraOptions[this.cameraIndex].value,
						sourceType: ['album', 'camera']
					})
					uni.uploadFile({
						url: this.action,
						fileType: 'video',
						file: res.tempFile,
						name: 'file',
						header: {
							"X-Access-Token":token
						},
						formData: {
							'biz': 'temp'
						},
						success: (file) =>{
							this.videoList.push(this.$config.apiUrl+'/sys/common/static/'+JSON.parse(file.data).message);
							this.$emit('update:videos', this.videoList)
						},
						fail: (err)=>{}
					})
				} catch (error) {
					this.$emit('error', error)
				}
			},

			// 统一删除处理
			async handleDelete(type, index) {
				try {
					await this.confirmDelete(type)
					if (type === 'image') {
						this.imageList.splice(index, 1)
						this.$emit('update:images', this.imageList)
					} else {
						this.videoList.splice(index, 1)
						this.$emit('update:videos', this.videoList)
					}
					this.$emit('delete', {
						type,
						index
					})
				} catch (error) {
					/* 取消删除不处理 */
				}
			},

			// 确认删除弹窗
			confirmDelete(type) {
				return new Promise((resolve, reject) => {
					uni.showModal({
						title: '提示',
						content: `是否要删除该${type === 'image' ? '图片' : '视频'}`,
						success: ({
							confirm
						}) => confirm ? resolve() : reject()
					})
				})
			},

			// 图片预览
			previewImage(current) {
				uni.previewImage({
					current,
					urls: this.imageList
				})
			}
		}
	}
</script>

<style lang="scss" scoped>
	.box-mode {
		width: 27vw;
		height: 27vw;

		border-radius: 8rpx;
		overflow: hidden;
	}

	.full {
		width: 100%;
		height: 100%;
	}

	.up-page {
		display: flex;
		flex-wrap: wrap;
		display: flex;
		width: 100%;
		padding: 0 15px 12px;

		.show-box:nth-child(3n) {
			margin-right: 0;
		}

		.show-box {
			position: relative;
			margin-bottom: 4vw;
			margin-right: 4vw;
			@extend .box-mode;

			.delect-icon {
				height: 40rpx;
				width: 40rpx;
				position: absolute;
				right: 0rpx;
				top: 0rpx;
				z-index: 1;
			}
		}
	}
</style>

 第二步:使用

<media-uploader :max-count="5" :initial-images.sync="localImages1" :initial-videos.sync="localVideos1" @update:images="updateImages1" @update:videos="updateVideos1" :disabled="false"/>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值