upload-image2

137 阅读2分钟
<template>
	<view class="u-upload" v-if="!disabled">
		<!-- <view class="other" v-if="showPanel" @tap.stop="closePanel"></view> -->
		<l-file ref="lFile" @up-success="upSuccess"></l-file>
		<view  v-for="(item, index) in lists" :key="index" class="item-file">
			<view v-if="item.type==='file'" class=" file-box" :style="{
				width: width / 2 + 'rpx',
				height: height + 'rpx'
			}"
			 @click="showPdf(item)">
				<image class="file-img" :src='fileImgSrc' />
				<view class="file-text"><text>{{item.name}}</text></view>
				<view v-if="deletable" class="u-delete-icon" @tap.stop="deleteFile(index)" :style="{
						background: delBgColor
					}">
					<image class="close-img" :src="closeSrc"></image>
				</view>
			</view>
			<view v-else class="u-list-item u-preview-wrap" :style="{
				width: width + 'rpx',
				height: height + 'rpx'
			}">
				<view v-if="deletable" class="u-delete-icon" @tap.stop="deleteItem(index)" :style="{
						background: delBgColor
					}">
					<image class="close-img" :src="closeSrc"></image>
				</view>
				<u-line-progress v-if="showProgress && item.progress > 0 && !item.error && circleOrLine" :show-percent="true"
				 height="8" class="u-progress" :percent="item.progress"></u-line-progress>
				<u-circle-progress v-if="showProgress && item.progress > 0 && !item.error && !circleOrLine&&item.succeedCloseCircle"
				 :active-color="activeColor" :percent="item.progress" :width='progressWidth' class="u-progress" :border-width='borderWidth'
				 bg-color='initial' :inactive-color='inactivecColor'>
					<view class="u-progress-content">
						<view class="u-progress-dot">{{item.progress}}%</view>
					</view>
					<view class="uploading">Uploading</view>
				</u-circle-progress>
				<view v-if="item.video && !item.error" @tap.stop='handelPaly(item)' class="u-video-img-box">
					<image class="u-video-img" :src="videoPlaySrc" mode=""></image>
				</view>
				<view v-if="item.error" @tap.stop="retry(index)" class="u-error-btn">
					<image class="u-error-btn-img" :src='errorImgSrc' />
					<view>{{$i18nMsg.base.uploadModule.clickuploadAgain}}</view>
				</view>
				<image  v-if="item.photo" @tap.stop="doPreviewImage(item.url || item.path, index)" class="u-preview-image" :src="item.url || item.path"
				 :mode="imageMode"></image>
			</view>
		</view>
		<video ref='video' v-if="videoUrl" id="myVideo" class="u-preview-video" :src="videoUrl" :loop='ifFullScreen'
		 :autoplay='true' @fullscreenchange='fullscreenchange' :muted='!ifFullScreen'> </video>
		<slot name="file" :file="lists"></slot>
		<view class="upload__box" style="display: inline-block;" @tap="selectFile" v-if="maxCount > lists.length">
			<slot name="addBtn"></slot>
			<view v-if="!customBtn&&showAddFile" class="u-list-item u-add-wrap" hover-class="u-add-wrap__hover" hover-stay-time="150" :style="{
					width: width + 'rpx',
					height: height + 'rpx',
					backgroundImage:'url('+(baseImg)+')'
				}">
				<u-icon v-if="!baseImg" name="plus" class="u-add-btn" size="20"></u-icon>
				<view v-if="!baseImg" class="u-add-tips">{{ uploadText }}</view>
			</view>
			<view v-if="propsShowPanel">
				<view v-show="showPanel" class="type__select__panel">
					<view class="type__select__panel__item" @tap.stop="handelPanelItem(item.type)" v-for="(item,index) in uploadTypes"
					 :key="index">
						<image class="type__select__panel__item__img" :src="photographSrc" v-if="item.type===0"></image>
						<image class="type__select__panel__item__img" :src="shootSrc" v-if="item.type===1"></image>
						<image class="type__select__panel__item__img" :src="photoSrc" v-if="item.type===2"></image>
						<image class="type__select__panel__item__img" :src="fileSrc" v-if="item.type===3"></image>
						<view class="type__select__panel__item__text">{{item.text}}</view>
					</view>
				</view>
			</view>
		</view>

	</view>
</template>

<script>
	import lFile from './l-file/l-file'
	/**
	 * upload 图片上传
	 * @description 该组件用于上传图片场景
	 * @tutorial https://www.uviewui.com/components/upload.html
	 * @property {String} action 服务器上传地址
	 * @property {String Number} max-count 最大选择图片的数量(默认99)
	 * @property {Boolean} custom-btn 如果需要自定义选择图片的按钮,设置为true(默认false)
	 * @property {Boolean} show-progress 是否显示进度条(默认true)
	 * @property {Boolean} disabled 是否启用(显示/移仓)组件(默认false)
	 * @property {String} image-mode 预览图片等显示模式,可选值为uni的image的mode属性值(默认aspectFill)
	 * @property {String} del-icon 右上角删除图标名称,只能为uView内置图标
	 * @property {String} del-bg-color 右上角关闭按钮的背景颜色
	 * @property {String} del-color 右上角关闭按钮图标的颜色
	 * @property {Object} header 上传携带的头信息,对象形式
	 * @property {Object} form-data 上传额外携带的参数
	 * @property {String} name 上传文件的字段名,供后端获取使用(默认file)
	 * @property {Array<String>} size-type original 原图,compressed 压缩图,默认二者都有(默认['original', 'compressed'])
	 * @property {Array<String>} source-type 选择图片的来源,album-从相册选图,camera-使用相机,默认二者都有(默认['album', 'camera'])
	 * @property {Boolean} preview-full-image	是否可以通过uni.previewImage预览已选择的图片(默认true)
	 * @property {Boolean} multiple	是否开启图片多选,部分安卓机型不支持(默认true)
	 * @property {Boolean} deletable 是否显示删除图片的按钮(默认true)
	 * @property {String Number} max-size 选择单个文件的最大大小,单位B(byte),默认不限制(默认Number.MAX_VALUE)
	 * @property {Array<Object>} file-list 默认显示的图片列表,数组元素为对象,必须提供url属性
	 * @property {Boolean} upload-text 选择图片按钮的提示文字(默认“选择图片”)
	 * @property {Boolean} auto-upload 选择完图片是否自动上传,见上方说明(默认true)
	 * @property {Boolean} show-tips 特殊情况下是否自动提示toast,见上方说明(默认true)
	 * @property {Boolean} show-upload-list 是否显示组件内部的图片预览(默认true)
	 * @event {Function} on-oversize 图片大小超出最大允许大小
	 * @event {Function} on-preview 全屏预览图片时触发
	 * @event {Function} on-remove 移除图片时触发
	 * @event {Function} on-success 图片上传成功时触发
	 * @event {Function} on-change 图片上传后,无论成功或者失败都会触发
	 * @event {Function} on-error 图片上传失败时触发
	 * @event {Function} on-progress 图片上传过程中的进度变化过程触发
	 * @event {Function} on-uploaded 所有图片上传完毕触发
	 * @event {Function} on-choose-complete 每次选择图片后触发,只是让外部可以得知每次选择后,内部的文件列表
	 * @example <u-upload :action="action" :file-list="fileList" ></u-upload>
	 */
	export default {
		name: 'u-upload',
		props: {
			//是否显示组件自带的图片预览功能
			showUploadList: {
				type: Boolean,
				default: true
			},
			// 后端地址
			action: {
				type: String,
				default: ''
			},
			// 最大上传数量
			maxCount: {
				type: [String, Number],
				default: 52
			},
			//  是否显示进度条
			showProgress: {
				type: Boolean,
				default: true
			},
			// 是否启用
			disabled: {
				type: Boolean,
				default: false
			},
			// 预览上传的图片时的裁剪模式,和image组件mode属性一致
			imageMode: {
				type: String,
				default: 'aspectFill'
			},
			// 头部信息
			header: {
				type: Object,
				default () {
					return {};
				}
			},
			// 额外携带的参数
			formData: {
				type: Object,
				default () {
					return {
						type: 0
					}
				}

			},
			// 上传的文件字段名
			name: {
				type: String,
				default: 'file'
			},
			// 所选的图片的尺寸, 可选值为original compressed
			sizeType: {
				type: Array,
				default () {
					return ['original', 'compressed'];
				}
			},
			sourceType: {
				type: Array,
				default () {
					return ['album', 'camera'];
				}
			},
			// 是否在点击预览图后展示全屏图片预览
			previewFullImage: {
				type: Boolean,
				default: true
			},
			// 是否开启图片多选,部分安卓机型不支持
			multiple: {
				type: Boolean,
				default: true
			},
			// 是否展示删除按钮
			deletable: {
				type: Boolean,
				default: true
			},
			// 文件大小限制,单位为byte
			maxSize: {
				type: [String, Number],
				default: Number.MAX_VALUE
			},
			// 显示已上传的文件列表
			fileList: {
				type: Array,
				default () {
					return [];
				}
			},
			// 上传区域的提示文字
			uploadText: {
				type: String,
				default: '选择图片'
			},
			// 是否自动上传
			autoUpload: {
				type: Boolean,
				default: true
			},
			// 是否显示toast消息提示
			showTips: {
				type: Boolean,
				default: true
			},
			// 是否通过slot自定义传入选择图标的按钮
			customBtn: {
				type: Boolean,
				default: false
			},
			// 内部预览图片区域和选择图片按钮的区域宽度,高等于宽
			width: {
				type: [String, Number],
				default: 82.41
			},
			height: {
				type: [String, Number],
				default: 64.81
			},
			// 右上角关闭按钮的背景颜色
			delBgColor: {
				type: String,
				default: '#000'
			},
			// 右上角关闭按钮的叉号图标的颜色
			delColor: {
				type: String,
				default: '#ffffff'
			},
			// 右上角删除图标名称,只能为uView内置图标
			delIcon: {
				type: String,
				default: 'close'
			},
			// 如果上传后的返回值为json字符串,是否自动转json
			toJson: {
				type: Boolean,
				default: true
			},
			// 上传前的钩子,每个文件上传前都会执行
			beforeUpload: {
				type: Function,
				default: null
			},
			// 圆圈宽度,高默认等于宽
			progressWidth: {
				type: [Number, String],
				default: '30'
			},
			// 轨道的宽度
			borderWidth: {
				type: [Number, String],
				default: '2'
			},
			// 激活轨道的颜色
			activeColor: {
				type: String,
				default: '#2979ff',
			},
			// 为激活轨道颜色
			inactivecColor: {
				type: String,
				default: '#fff'
			},
			// 上传进度
			percent: {
				type: [Number, String],
				default: 0
			},
			// 判断上传进度线性还是圆形
			circleOrLine: {
				type: Boolean,
				default: false
			},
			// ui 给定的上传 图片的 图片路径
			baseImg: {
				type: String,
				default: '/static/remote-assist-module/images/fileadd.png'
			},
			// 上传报错时,图片的路径
			errorImgSrc: {
				type: String,
				default: ''
			},
			// 视频播放按钮图片
			videoPlaySrc: {
				type: String,
				default: '/static/remote-assist-module/images/playVideo.png'
			},
			photographSrc:{
				type: String,
				default: '/static/remote-assist-module/images/photographSrc.png'
			},
			// 右上角关闭按钮的图片
			closeSrc: {
				type: String,
				default: '/static/remote-assist-module/images/close1.png'
			},
			// 外界关闭相册面板
			propsShowPanel: {
				type: Boolean,
				default: true
			},
			// 上传目标为文件 文件的背景样式
			fileImgSrc: {
				type: String,
				default:'/static/remote-assist-module/images/fileImgSrc.png'
			},
			// 拍摄前面图片路径
			shootSrc: {
				type: String,
				default:'/static/remote-assist-module/images/shootSrc.png'
			},
			// 相册前面图片路径
			photoSrc: {
				type: String,
				default: '/static/remote-assist-module/images/photoSrc.png'
			},
			// 文件前面图片路径
			fileSrc: {
				type: String,
				default:'/static/remote-assist-module/images/fileSrc.png'
			},
			// 初始上传列表值
			value:{
				type: Array,
				default () {
					return []
				}
			},
			showAddFile:{
				type:Boolean,
				default:true
			},
			uploadTypes: {
				type: Array,
				default () {
					return [{
							type:0,
							text: this.$i18nMsg.base.uploadModule.takePictures
						},
						{
							type: 1,
							text: this.$i18nMsg.base.uploadModule.shoot
						},
						{
							type:2,
							text:this.$i18nMsg.base.uploadModule.album
						},
						{
							type: 3,
							text: this.$i18nMsg.base.uploadModule.file
						}
					];
				}
			}
		},
		components: {
			lFile
		},
		data() {
			return {
				lists:this.value,
				fileLists: [],
				isInCount: true,
				uploading: false,
				type: 'text',
				border: true,
				showPanel: false,
				videoSrc: [],
				videoUrl: '',
				videoContext: '',
				ifFullScreen: false,
				data: {},
				succeedCloseCircle: true
			};
		},
		mounted() {
			this.data = JSON.parse(JSON.stringify(this.formData))
		},
		watch: {
			fileList: {
				immediate: true,
				handler(val) {
					// val.map(value => {
					// 	// 首先检查内部是否已经添加过这张图片,因为外部绑定了一个对象给fileList的话(对象引用),进行修改外部fileList
					// 	// 时,会触发watch,导致重新把原来的图片再次添加到this.lists
					// 	// 数组的some方法意思是,只要数组元素有任意一个元素条件符合,就返回true,而另一个数组的every方法的意思是数组所有元素都符合条件才返回true
					// 	let tmp = this.lists.some(val => {
					// 			return val.url == value.url;
					// 		})
					// 		// 如果内部没有这个图片(tmp为false),则添加到内部
					// 		!tmp && this.lists.push({
					// 			url: value.url,
					// 			error: false,
					// 			progress: 100
					// 		});
					// });
				}
			},
			// 监听value变化
			value:{
                immediate: true,
				handler(val) {
					this.lists = val
				}    
			},
			// 监听lists的变化,发出事件
			lists(n) {
				this.$emit('on-list-change', n);
			}
		},
		methods: {
			// 清除列表
			clear() {
				this.lists = [];
			},
			// 重新上传队列中上传失败的所有文件
			reUpload() {
				this.uploadFile();
			},
			// 预览
			showPdf(item) {
				this.$emit("showPdf", item)
			},
			// 选择图片
			selectFile(e) {
				if (this.disabled) return;
				this.showPanel = !this.showPanel
			},
			handelPanelItem(item) {
				for(let item of this.lists){
					if(item.succeedCloseCircle){
						this.showToast(this.$i18nMsg.base.uploadModule.waitSuccess);
						return
					}
				}
				let value="camera"
				let type="chooseImage"
				if(item===0){
					value="camera"
					type="chooseImage"
				}
				if(item===1){
					value="camera"
					type="chooseVideo"
				}
				if(item===2){
					value="album"
					type="pick"
				}
				if(item===3){
					value="album"
					type="files"
				}
				const {
					name = '', maxCount, multiple, maxSize, sizeType, lists, camera, compressed, maxDuration, sourceType
				} = this;
				if (type === 'chooseImage' || type === 'chooseVideo') {
					let chooseFile = null;
					const newMaxCount = maxCount - lists.length;
					// 设置为只选择图片的时候使用 chooseImage 来实现
					chooseFile = new Promise((resolve, reject) => {
						uni[type]({
							count: multiple ? (newMaxCount > 9 ? 9 : newMaxCount) : 1,
							sourceType: [value],
							sizeType,
							success: resolve,
							fail: reject
						});
					});
					chooseFile
						.then(res => {
							let file = null;
							let listOldLength = this.lists.length;
							if (type === 'chooseVideo') {
								this.data.type = 1
								res.tempFiles = [{
									path: res.tempFilePath,
									video: true
								}]
							}
							res.tempFiles.map((val, index) => {
								// 如果是非多选,index大于等于1或者超出最大限制数量时,不处理
								if (!multiple && index >= 1) return;
								if (val.size > maxSize) {
									this.$emit('on-oversize', val, this.lists);
									this.showToast(this.$i18nMsg.base.uploadModule.exceedSize);
								} else {
									if (maxCount <= lists.length) {
										this.$emit('on-exceed', val, this.lists);
										this.showToast(this.$i18nMsg.base.uploadModule.exceedFile);
										return;
									}
									lists.push({
										url: val.path,
										progress: 0,
										succeedCloseCircle:false,
										task:null,
										error: false,
										photo:val.video ? false : true,
										video: val.video ? true : false
									});
								}
							});
							// 每次图片选择完,抛出一个事件,并将当前内部选择的图片数组抛出去
							this.$emit('on-choose-complete', this.lists);
							this.showPanel = false
							// if(type === 'chooseVideo') {
							// 	console.log(this.$refs['vide'],'进来了')
							// }
							if (this.autoUpload) this.uploadFile(listOldLength);

						})
						.catch(error => {
							this.$emit('on-error', error);
						});
				} else if (type === 'pick') {
					plus.gallery.pick(function(e) {
						let type2 = 0;
						let length = e.length;
						for (let i = 0; i < length; i++) {
							let url = e[i];
							let arr = url.split(".");
							let s = arr[arr.length - 1];
							switch (s) {
								case "png":
									type2 = 0;
									break;
								case "jpg":
									type2 = 0;
									break;
								case "jpeg":
									type2 = 0;
									break;
								case "mp4":
									type2 = 1;
									break;
								case "wma":
									type2 = 1;
									break;
								default:
									type2 = 0;
							}
						}
						let listOldLength = this.lists.length;
						if (type2 === 0) {
							lists.push({
								url: e,
								progress: 0,
								succeedCloseCircle:false,
								error: false,
								photo:true,
								task:null,
								video: false
							});
							this.$emit('on-choose-complete', this.lists);
						} else if (type2 === 1) {
							this.data.type = 1
							lists.push({
								url: e,
								photo:false,
								progress: 0,
								task:null,
								succeedCloseCircle:false,
								error: false,
								video: true
							});
							this.$emit('on-choose-complete', this.lists);
						}
						if (this.autoUpload) this.uploadFile(listOldLength);
					}.bind(this))
				} else if (type === 'files') {

					this.data.type = 2
					this.$refs.lFile.upload({
						// #ifdef APP-PLUS
						currentWebview: this.$mp.page.$getAppWebview(),
						// #endif
						url: this.action,
						name: "file",
						header: this.header,
						//...其他参数
						type: 2,
					});
				}
			},
			upSuccess(value) {
				try {
					let fileName = value.fileName;
					let fileObj = JSON.parse(value.data.id);
					let filePath = fileObj.path;
					let attachmentId = fileObj.attachmentId;
					let fileSize = fileObj.fileSize;
					this.lists.push({
						url: fileObj.path,
						progress: 100,
						succeedCloseCircle:false,
						task:null,
						error: false,
						video: false,
						photo:false,
						name: value.fileName,
						fileSize,
						type: "file"
					});
					this.$emit('on-success', this.lists);
				} catch (e) {
					console.log("pdf上传异常", e);
				}
			},
			// 提示用户消息
			showToast(message, force = false) {
				if (this.showTips || force) {
					uni.showToast({
						title: message,
						icon: 'none',
						duration:3000
					});
				}
			},
			async upVideo() {

			},
			// 该方法供用户通过ref调用,手动上传
			upload() {
				this.uploadFile();
			},
			// 对失败的图片重新上传
			retry(index) {
				this.lists[index].progress = 0;
				this.lists[index].error = false;
				this.lists[index].succeedCloseCircle=false;
				this.lists[index].response = null;
				this.lists[index].task = null;
				uni.showLoading({
					title: this.$i18nMsg.base.uploadModule.uploadAgain
				});
				this.uploadFile(index);
			},
			// 上传图片
			async uploadFile(index = 0) {
				if (this.disabled) return;
				if (this.uploading) return;
				// 全部上传完成
				if (index >= this.lists.length) {
					this.$emit('on-uploaded', this.lists);
					return;
				}
				// 检查上传地址
				if (!this.action) {
					this.showToast('请配置上传地址', true);
					return;
				}
				// 检查是否是已上传或者正在上传中
				if (this.lists[index].progress == 100) {
					if (this.autoUpload == false) this.uploadFile(index + 1);
					return;
				}
				// 执行before-upload钩子
				if (this.beforeUpload && typeof(this.beforeUpload) === 'function') {
					// 执行回调,同时传入索引和文件列表当作参数
					let beforeResponse = this.beforeUpload(index, this.lists);
					// 判断是否返回了promise
					if (!!beforeResponse && typeof beforeResponse.then === 'function') {
						await beforeResponse.then(res => {
							// promise返回成功,不进行动作,继续上传
						}).catch(err => {
							// 进入catch回调的话,继续下一张
							return this.uploadFile(index + 1);
						})
					} else if (beforeResponse === false) {
						// 如果返回false,继续下一张图片的上传
						return this.uploadFile(index + 1);
					}
				}
				this.lists[index].error = false;
				this.uploading = true;
				// 创建上传对象
				this.lists[index].task = uni.uploadFile({
					url: this.action,
					filePath: this.lists[index].url,
					name: this.name,
					formData: this.data,
					header: this.header,
					success: res => {
						console.log("上传成功啦")
						// 判断是否json字符串,将其转为json格式
						let data = this.toJson && this.checkIsJSON(res.data) ? JSON.parse(res.data) : res.data;
						if (![200, 201].includes(res.statusCode)) {
							this.uploadError(index, data);
						} else {
							// 上传成功
							this.lists[index].url=JSON.parse(res.data).path
							this.lists[index].response = data;
							this.lists[index].error = false;
							this.$emit('on-success', this.lists);
							console.log(JSON.stringify(this.lists))
						}
					},
					fail: e => {
						this.uploading = false;
						this.lists[index].task=null;
						this.uploadError(index, e);
					},
					complete: res => {
						uni.hideLoading();
						this.lists[index].progress = 100;
						this.lists[index].succeedCloseCircle=false;
						this.lists[index].task=null;
						console.log("上传完成啦")
						this.uploading = false;
						this.uploadFile(index + 1);
						this.$emit('on-change', res, index, this.lists);
					}
				});
				let time = new Date().getTime()
				this.lists[index].task.onProgressUpdate(res => {
					let nowTime = new Date().getTime()
					if(nowTime - time >20){
						time = new Date().getTime()
                       if (res.progress > 0 && res.progress < 100) {
							this.lists[index].succeedCloseCircle=true;
							this.lists[index].progress=res.progress
						}
					}
					this.$emit('on-progress', res, index, this.lists);
				});
			},
			// 上传失败
			uploadError(index, err) {
				this.lists[index].progress = 0;
				this.lists[index].error = true;
				this.lists[index].response = null;
				this.$emit('on-error', err, index, this.lists);
				this.showToast(this.$i18nMsg.base.uploadModule.uploadFailed);
			},
			// 删除一个图片
			deleteItem(index) {
                if(this.lists[index].task){
                    this.lists[index].task.abort();
				}
				if (this.lists[index].process < 100 && this.lists[index].process > 0) {
					typeof this.lists[index].uploadTask != 'undefined' && this.lists[index].uploadTask.abort();
				}
				this.lists.splice(index, 1);
				this.$forceUpdate();
				this.$emit('on-remove', index, this.lists);
				this.$emit('on-success', this.lists);
				this.showToast(this.$i18nMsg.base.uploadModule.removeSuccess);

			},
			deleteFile(index) {
				if(this.lists[index].task){
                    this.lists[index].task.abort();
				}
				this.lists.splice(index, 1);
				this.$forceUpdate();
				this.$emit('on-remove', index, this.lists);
				this.$emit('on-success', this.lists);
				this.showToast(this.$i18nMsg.base.uploadModule.removeSuccess);
			},
			// 点击其它区域影藏
			closePanel(e){
				this.showPanel = false
				this.$emit("closePanel")
			},
			// 用户通过ref手动的形式,移除一张图片
			remove(index) {
				// 判断索引的合法范围
				if (index >= 0 && index < this.lists.length) {
					this.lists.splice(index, 1);
					this.$emit('on-list-change', this.lists);
				}
			},
			// 预览图片
			doPreviewImage(url, index) {
				if (!this.previewFullImage) return;
				let images = []
				for(let item of this.lists){
					if(item.photo){
						images.push(item.url||item.path)
					}
				}
				uni.previewImage({
					urls: images,
					current: url,
					success: () => {
						this.$emit('on-preview', url, this.lists);
					},
					fail: () => {
						uni.showToast({
							title: this.$i18nMsg.base.uploadModule.failedPicture,
							icon: 'none'
						});
					}
				});
			},
			// 点击播放视频 
			handelPaly(value) {
				let system = uni.getSystemInfoSync().platform
				if (system == 'ios') {
					uni.requireNativePlugin("autel-common-module").videoPlay(value.url)
				} else {
					this.videoUrl = value.url
					setTimeout(() => {
						this.videoContext = uni.createVideoContext('myVideo')
						this.videoContext.requestFullScreen()
					}, 100)
				}
			},
			fullscreenchange(event) {
				if (event.detail.direction === 'vertical') {
					this.ifFullScreen = false
					this.videoUrl = ''
				} else if (event.detail.direction === 'horizontal') {
					this.ifFullScreen = true
				}
			},
			// 判断是否json字符串
			checkIsJSON(str) {
				if (typeof str == 'string') {
					try {
						var obj = JSON.parse(str);
						if (typeof obj == 'object' && obj) {
							return true;
						} else {
							return false;
						}
					} catch (e) {
						return false;
					}
				}
				return false;
			}
		}
	};
</script>

<style lang="scss" scoped>
	.u-upload {
		display: flex;
		flex-wrap: wrap;
		align-items: center;
        max-width:420rpx;
		 .upload__box {
			position: relative;
			 .type__select__panel {
				position: absolute;
				left: 0;
				top: 105%;
				z-index: 999;
				height: 52.19rpx;
				padding: 11rpx;
				background: rgba(225, 225, 225, 1);
				border-radius: 5px;
				border: 1px solid rgba(167, 167, 167, 1);
				box-shadow: 0px 3.84rpx 6.59rpx 0px rgba(0, 0, 0, 0.3);
				display: flex;
				font-size: 9.89rpx;
				align-items: center;
				justify-content: center;

				&::after {
					content: '';
					position: absolute;
					left: 20rpx;
					top: -10rpx;
					border-right: 8rpx solid transparent;
					border-left: 8rpx solid transparent;
					border-bottom: 12rpx solid rgba(225, 225, 225, 1);
				}

				&::before {
					content: '';
					position: absolute;
					left: 20rpx;
					top: -12rpx;
					border-right: 8rpx solid transparent;
					border-left: 8rpx solid transparent;
					border-bottom: 11rpx solid rgba(167, 167, 167, 1);
				}

				&__item {
					// width: 46.15rpx;
					white-space: nowrap;
					padding: 0 6rpx;
					overflow: hidden;
					text-overflow: ellipsis;
					height: 27.47rpx;
					background: linear-gradient(180deg, rgba(247, 247, 247, 1) 0%, rgba(184, 184, 184, 1) 100%);
					box-shadow: 0px 1px 0px 0px rgba(255, 255, 255, 1);
					border-left: 1px solid rgba(177, 177, 177, 1);
					border-top: 1px solid rgba(177, 177, 177, 1);
					border-bottom: 1px solid rgba(177, 177, 177, 1);
					display: flex;
					justify-content: center;
					align-items: center;
					&__img {
						width: 13.18rpx;
						height: 13.18rpx;
					}
					&__text {
						font-size: 9.89rpx;
						margin-left: 3.29rpx;
					}
				}
                &__item:last-child{
					border-right: 1px solid rgba(177, 177, 177, 1);	
				}
				&__item:active {
					background:linear-gradient(180deg,rgba(162,162,162,1) 0%,rgba(239,239,239,1) 100%);
					box-shadow:0px 0.55rpx 0px 0px rgba(255,255,255,1),0px 3.02rpx 4.4rpx 0px rgba(0,0,0,0.35),0px -1.65rpx -1.65rpx 0px rgba(0,0,0,0.17);
					border-image:linear-gradient(180deg, rgba(96,96,96,1), rgba(142,142,142,1)) 2 2;
				}
			}
		}
	}
    .item-file{
		margin-right: (80rpx/3.64);
	}
	.u-list-item {
		position: relative;
		border-radius: 5rpx;
		display: inline-flex;
		align-items: center;
		justify-content: center;
		background-size: 82.41rpx 64.81rpx;
		width: (300rpx/3.64);
		height: (225rpx/3.64);
	}
	.file-box {
		height: 64.81rpx;
		width: 41rpx;
		margin: 5rpx;
		background: rgb(244, 245, 246);
		position: relative;
		border-radius: 5rpx;
		display: inline-flex;
		align-items: center;
		justify-content: center;

	}

	.file-img {
		height: 64.81rpx;
		width: 41rpx;
	}

	.file-text {
		font-size: 10px;
		position: absolute;
		bottom: 10px;
		left: 5px;
		right: 5px;
		color: #ffffff;

		uni-text {
			overflow: hidden;
			text-overflow: ellipsis;
			display: -webkit-box;
			-webkit-box-orient: vertical;
			-webkit-line-clamp: 2;
			word-break: break-all;
		}
	}

	.u-preview-wrap {
		border: 1px solid rgb(235, 236, 238);
	}

	.u-add-wrap {
		flex-direction: column;
		color: #606266;
		font-size: 14rpx;
	}

	.u-add-tips {
		margin-top: 10rpx;
		line-height: 20rpx;
		font-size: 12px;
	}

	.u-add-wrap__hover {
		background-color: rgb(235, 236, 238);
	}

	.u-preview-image {
		display: block;
		width: 100%;
		height: 100%;
		border-radius: 5rpx;
	}

	.u-preview-video {
		width: 0;
		height: 0;
		z-index: 0;
		display: none;
	}
	.u-delete-icon {
		position: absolute;
		top: -4rpx;
		right: -4rpx;
		z-index: 100;
		background-color:#fa3534;
		border-radius: 50rpx;
		width: 13.73rpx;
		height: 13.73rpx;
		display: flex;
		align-items: center;
		justify-content: center;
	}
	.u-icon {
		display: flex;
		align-items: center;
		justify-content: center;
	}

	.close-img {
		width: 13.73rpx;
		height: 13.73rpx;
		z-index: 99;
	}

	.u-progress {
		position: absolute;
		// bottom: 5rpx;
		// left: 4rpx;
		// right: 4rpx;
		z-index: 99;
		width: auto;
        
		.u-progress-content {
			height: 90%;
			width: 90%;
			border-radius: 50%;
			background: rgba(255, 255, 255, 0.4);
			display: flex;
			justify-content: center;
			align-items: center;
			color: #000000;
			font-size: 16px;
            z-index: 999;
			.u-progress-dot {
				font-size: 10px;
			}
		}

		.uploading {
			position: absolute;
			top: 100%;
			font-size: 12px;
			color: #fff;
		}
	}

	.u-video-img-box {
		width: 100%;
		height: 100%;
		position: absolute;
		// z-index: 1;

		.u-video-img {
			width:100%;
			height:100%;
		}
	}

	.u-error-btn {
		color: #ffffff;
		font-size: 10rpx;
		padding: 4px 0;
		text-align: center;
		position: absolute;
		// top: 50%;
		left: 0;
		right: 0;
		z-index: 9;
		font-size: 8.24rpx;
		line-height: 1;

		.u-error-btn-img {
			width: 16.48rpx;
			height: 16.48rpx;
			margin-bottom: 5.49rpx;
		}
	}
</style>