From d8b41fff43a2cee6a8f714ffa807623b15803786 Mon Sep 17 00:00:00 2001
From: quanyawei <401863037@qq.com>
Date: Fri, 20 Oct 2023 15:21:35 +0800
Subject: [PATCH] fix:立行立改Uniapp小程序新建项目

---
 uni_modules/cl-upload/components/cl-upload/cl-upload.vue | 1031 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 1,031 insertions(+), 0 deletions(-)

diff --git a/uni_modules/cl-upload/components/cl-upload/cl-upload.vue b/uni_modules/cl-upload/components/cl-upload/cl-upload.vue
new file mode 100644
index 0000000..ee28b16
--- /dev/null
+++ b/uni_modules/cl-upload/components/cl-upload/cl-upload.vue
@@ -0,0 +1,1031 @@
+<template>
+	<view class="cl-updata">
+		<view class="file-list" :style="[listRowStyle]">
+
+			<view v-for="(item, index) in previewList" @tap="clickSelectedFile(item, index)" class="file-list-row"
+				:style="[rowStyle]" :key="index">
+
+				<image 
+					class="_image" 
+					v-if="fileUrlType(item) === 'image'" 
+					:src="item.path" 
+					:style="[imgStyle]" 
+					mode="aspectFill">
+				</image>
+
+				<view v-else class="_video" :style="[imgStyle]">
+
+					<!-- #ifdef MP-WEIXIN || MP-ALIPAY -->
+					<video 
+						v-if="!autoUpload || cloudType === 'other'" 
+						class="_video" 
+						:style="[imgStyle]"
+						:src="item.path" 
+						:show-center-play-btn="false" 
+						:show-fullscreen-btn="false"
+						:show-play-btn="false" 
+						:show-loading="false" 
+						:enable-progress-gesture="false" 
+						:controls="false">
+						<view @tap="previewVideo(item, index)" class="play">
+							<image style="width: 100%;" :src="playImg" mode="widthFix"></image>
+						</view>
+					</video>
+
+					<!-- #endif -->
+					
+					<!-- #ifdef APP-PLUS -->
+					<video
+						v-if="cloudType === 'other'" 
+						class="_video" 
+						:style="[imgStyle]" 
+						:src="item.path"
+						:poster="item.path"
+						:controls="false"
+						:show-center-play-btn="false" 
+						:show-fullscreen-btn="false" 
+						:show-play-btn="false"
+						:show-loading="false" 
+						:enable-progress-gesture="false">
+						<cover-image class="app_play" :src="playImg" @tap="previewVideo(item, index)"></cover-image>
+						<cover-view class="remove" v-if="remove" @tap="deleteSelectedFile(item, index)">
+							<cover-image class="image" :src="deleteImg" mode="widthFix" @tap="deleteSelectedFile(item, index)"></cover-image>
+						</cover-view>
+					</video>
+					<!-- #endif -->
+					
+					<!-- #ifndef MP-WEIXIN || MP-ALIPAY || APP-PLUS -->
+					<video 
+						v-if="cloudType === 'other'" 
+						class="_video" 
+						:autoplay="false"
+						:style="[imgStyle]" 
+						:src="item.path"
+						:controls="false"
+						:show-center-play-btn="false" 
+						:show-fullscreen-btn="false" 
+						:show-play-btn="false"
+						:show-loading="false" 
+						:enable-progress-gesture="false" >
+						<cover-view  @tap="previewVideo(item, index)" class="play">
+							<cover-image style="width: 100%;" :src="playImg" mode="widthFix"></cover-image>
+						</cover-view>
+					</video>
+					
+					<!-- #endif -->
+					
+					<template v-else>
+						<cl-image class="pay" :style="[imgStyle]" :cloudType="cloudType"
+							:src="(item.poster || item.path)"></cl-image>
+						
+						<view class="play" @tap="previewVideo(item, index)">
+							<image class="play-img" :src="playImg" mode="widthFix"></image>
+						</view>
+					</template>
+
+				</view>
+				
+				<view class="remove" v-if="remove" @tap.stop="deleteSelectedFile(item, index)">
+					<image class="image" :src="deleteImg" mode="widthFix"></image>
+				</view>
+			</view>
+
+			<view v-if="add && FileList.length < max" @tap="selectFileTypeOnAdd" :style="[rowStyle]" class="file-list-row">
+				<slot name="addImg">
+					<div class="add-image">
+						<image class="_image" :src="addImg" mode="widthFix"></image>
+					</div>
+				</slot>
+			</view>
+		</view>
+
+
+		<view v-if="tempVideoUrl" class="mask">
+			<image @tap="tempVideoUrl = ''" class="_root" :src="closeImg" mode="widthFix"></image>
+
+			<view class="block" @tap.stop>
+				<video class="block_video" autoplay :src="tempVideoUrl"></video>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+import ClImage from '../cl-image/cl-image.vue'
+export default {
+	name: "cl-upload",
+	components: { ClImage },
+	props: {
+		//������������������
+		// #ifdef VUE2
+		value: {
+			type: Array,
+			default: () => [],
+		},
+		// #endif
+
+		// #ifdef VUE3
+		modelValue: {
+			type: Array,
+			default: () => [],
+		},
+		// #endif
+
+		// ��������������� oss���������  vframe���������   process���������  other������
+		cloudType: {
+			type: String,
+			default: 'oss'
+		},
+		// ���������,������������������������
+		fileName: {
+			type: String,
+			default: 'file'
+		},
+		// ������������ 'image', 'video', 'all'
+		fileType: {
+			type: String,
+			default: 'all'
+		},
+		// ������������������
+		imageFormData: {
+			type: Object | null,
+			default: () => { }
+		},
+		// ������������������
+		videoFromData: {
+			type: Object,
+			default: () => { }
+		},
+
+		// ������������������������������
+		action: {
+			type: String,
+			default: ''
+		},
+		
+		// ������������, ���unicloud���������������
+		// https://uniapp.dcloud.net.cn/uniCloud/storage.html#storage-dir
+		cloudPathAsRealPath: {
+			type: Boolean,
+			default: false
+		},
+
+		// ���������������������������
+		headers: {
+			type: Object,
+			default: () => { }
+		},
+
+		// ������������������������������
+		data: {
+			type: Object,
+			default: () => { }
+		},
+
+		// ������������������������
+		isPreviewImage: {
+			type: Boolean,
+			default: true
+		},
+
+		// ������������������������������������"default" - ������������������������ "number" - ������������������������ "none" - ���������������������
+		indicator: {
+			type: String,
+			default: 'none'
+		},
+		// ������������������������������������������	
+		autoUpload: {
+			type: Boolean,
+			default: true
+		},
+		// ������������������������
+		remove: {
+			type: Boolean,
+			default: true
+		},
+		// ������������������
+		add: {
+			type: Boolean,
+			default: true
+		},
+		// ������������������
+		max: {
+			type: Number,
+			default: 9
+		},
+		// ������������������������
+		maxVideo: {
+			type: Number,
+			default: 0
+		},
+		// ������������
+		listStyle: {
+			type: Object,
+			default: () => { }
+		},
+		// ������������������������
+		deleteTitle: {
+			type: String,
+			default: '������'
+		},
+		// ������������������������
+		deleteText: {
+			type: String,
+			default: '������������������������'
+		},
+		// ������������
+		loadingText: {
+			type: String,
+			default: '���������������...'
+		},
+		// ���������������������������
+		useBeforeDelete: {
+			type: Boolean,
+			default: false
+		},
+		// ���������������������������
+		useBeforeUpload: {
+			type: Boolean,
+			default: false
+		},
+		// ������������������
+		addImg: {
+			type: String,
+			default: 'https://mp-61599c79-d7ee-4a75-a24b-e5a288da6dd3.cdn.bspapp.com/cloudstorage/bb1550b3-e0a8-4a90-a86f-00f8c6afa9fb.png'
+		},
+		// ������������������
+		playImg: {
+			type: String,
+			default: 'https://mp-61599c79-d7ee-4a75-a24b-e5a288da6dd3.cdn.bspapp.com/cloudstorage/ae40402f-aa53-4344-b553-2322799bebd6.png'
+		},
+		// ������������������
+		deleteImg: {
+			type: String,
+			default: 'https://mp-61599c79-d7ee-4a75-a24b-e5a288da6dd3.cdn.bspapp.com/cloudstorage/d20177a5-417e-4c5d-a266-1988361c543d.png'
+		},
+		// ������������������������
+		closeImg: {
+			type: String,
+			default: 'https://mp-61599c79-d7ee-4a75-a24b-e5a288da6dd3.cdn.bspapp.com/cloudstorage/cde4362d-7ec7-4cac-a692-12e1f576be1e.png'
+		},
+	},
+	data() {
+		return {
+			// ������������
+			FileList: [],
+
+			// ������������������
+			tempVideoUrl: '',
+
+			// ������������������
+			tempFile_paths: [],
+
+		};
+	},
+	watch: {
+		// #ifdef VUE2
+		'value': {
+			handler: function (newVal, oldVal) {
+				this.FileList = newVal;
+			},
+			deep: true,
+			immediate: true
+		},
+		// #endif
+
+		// #ifdef VUE3
+		'modelValue': {
+			handler: function (newVal, oldVal) {
+				this.FileList = newVal;
+			},
+			deep: true,
+			immediate: true
+		},
+		// #endif
+	},
+	computed: {
+		previewList() {
+			return this.FileList.map(item => {
+				return {
+					path: item.path || item,
+					poster: item.poster || ''
+				}
+			})
+		},
+		listRowStyle() {
+			const style = {
+				'grid-template-columns': `repeat(${this.listStyle?.columns || 4}, 1fr)`, // ������������	
+				'grid-column-gap': this.listStyle?.columnGap || '40rpx', // ���������	
+				'grid-row-gap': this.listStyle?.rowGap || '40rpx', // ���������
+				'padding': this.listStyle?.padding || '0rpx' // ���������������
+			}
+
+			return style;
+		},
+		rowStyle() {
+			const { height = '140rpx', ratio } = this.listStyle || {};
+			const style = {
+				'aspect-ratio': height ? '' : ratio || '1/1', // ������������
+				'height': height,
+			};
+
+			return style;
+		},
+
+		imgStyle() {
+			const style = {
+				'border-radius': this.listStyle?.radius || '6rpx', // ������������
+			}
+			return style;
+		}
+	},
+	methods: {
+		/**
+		 * ���������������������
+		 * @param {object} item ������������
+		 * @param {number} selectedFileIndex ������������
+		 * */
+		deleteSelectedFile(item, selectedFileIndex) {
+
+			const fileToDelete = this.FileList[selectedFileIndex];
+
+			// ���������������
+			if (this.useBeforeDelete) {
+				this.$emit('beforeDelete', fileToDelete, selectedFileIndex, () => {
+					return deleteFileFromList()
+				})
+			}
+
+			if (!this.useBeforeDelete) {
+				uni.showModal({
+					title: this.deleteTitle,
+					content: this.deleteText,
+					success: (res) => {
+						if (res.confirm) {
+							deleteFileFromList()
+						}
+					}
+				});
+			}
+
+			const deleteFileFromList = () => {
+				const tempFileIndex = this.tempFile_paths.indexOf(item || item.path);
+
+				if (tempFileIndex > -1) { 
+					this.tempFile_paths.splice(tempFileIndex, 1)
+				}
+
+				this.FileList.splice(selectedFileIndex, 1) 
+
+				// #ifdef VUE2 
+				this.$emit('input', this.FileList)
+				// #endif
+
+				// #ifdef VUE3
+				this.$emit("update:modelValue", this.FileList);
+				// #endif
+			}
+
+		},
+
+		/**
+		 * ���������������������
+		 * @param {object} item ������������
+		 * @param {number} index ������������ 
+		 * */
+		clickSelectedFile(item, index) {
+			this.previewImage(item?.path ?? item, index);
+			this.$emit('onImage', {
+				item,
+				index
+			})
+		},
+
+		/**
+		 * ������������������������
+		 * */
+		selectFileTypeOnAdd() {
+
+			switch (this.fileType) {
+				case 'image':
+					this.handleFileSelection(1);
+					break;
+				case 'video':
+					this.handleFileSelection(2);
+					break;
+				case 'all':
+					uni.showActionSheet({
+						itemList: ['������', '������'],
+						success: (res) => {
+							const tapIndex = res.tapIndex;
+							if (tapIndex === 0) {
+								this.handleFileSelection(1);
+							} else {
+								this.handleFileSelection(2);
+							}
+						},
+						fail: (res) => {
+							console.error(res.errMsg);
+						}
+					});
+					break;
+				default:
+					this.handleFileSelection(1);
+					break;
+			}
+		},
+
+
+		/**
+		 * ������������������������
+		 * @param { number } updataType ������������ 1:������ 2������
+		 * */
+		async handleFileSelection(updataType) {
+			const that = this;
+			if (updataType === 1) {
+
+				const data = Object.assign({}, {
+					// ������������������������������������������9
+					count: 9,
+					// ������ mediaType ��� image ������������������������������������
+					// #ifndef MP-TOUTIAO
+					sizeType: ['original', 'compressed'],
+					// #endif
+					// album ������������������camera ������������������������������������
+					sourceType: ['camera', 'album'],
+
+					compress: false
+				}, this.imageFormData)
+
+				data['count'] = this.max - this.FileList.length
+
+				uni.chooseImage({
+					...data,
+					success: async (res) => {
+						let tempFiles = res.tempFiles
+						const compress = that.imageFormData?.compress || false;
+
+						// ������������������������
+						if (that.imageFormData?.size ?? false) {
+							const maxSize = that.imageFormData.size * 1024 * 1024
+							
+							tempFiles.map((imgInfo, index) => {
+								if (imgInfo.size > maxSize) {
+									tempFiles.splice(index, 1)
+									that.$emit('onImageSize', imgInfo)
+									return uni.showToast({
+										title: `������������������${that.imageFormData.size}MB`,
+										duration: 2000,
+										icon: 'none'
+									});
+								}
+							})
+						}
+
+						// ������������������
+						if (compress) {
+							const compressedImagePathList = tempFiles.map(imageItem => {
+								return that.compressImage(imageItem.path)
+							})
+
+							Promise.all(compressedImagePathList).then(result => {
+								upload(result);
+							})
+
+						} else {
+							upload(tempFiles);
+						}
+
+						function upload(tempImages) {
+							if (that.autoUpload) {
+								tempImages.map(item => {
+									that.onBeforeUploadFile(item, 'image')
+								})
+							} else {
+								that.FileList = [...that.FileList, ...tempImages]
+								tempImages.map(item => {
+									that.tempFile_paths.push(item)
+								})
+							}
+						}
+
+					},
+					fail(err) {
+						console.error('������������������', err)
+						that.$emit('onError', err)
+					}
+
+				})
+			}
+
+			if (updataType === 2) {
+
+				// ������������������������������
+				const VIDEO_REGEXP = /\.(mp4|flv|avi)/i
+				const videoList = await that.FileList.filter(item => {
+					const fileUrl = item?.url ?? item
+					return VIDEO_REGEXP.test(fileUrl)
+				})
+
+				if (that.maxVideo > 0 && videoList.length >= that.maxVideo) {
+					that.$emit('onVideoMax', that.maxVideo, videoList.length)
+					return uni.showToast({
+						title: '���������������������',
+						duration: 2000,
+						icon: 'none'
+					});
+				}
+
+				const data = Object.assign({}, {
+					// 	��������������������������������������������������������� 60 ������
+					maxDuration: 60,
+					// #ifndef MP-TOUTIAO
+					// 'front'���'back'���������'back'
+					camera: "back",
+					// #endif
+
+					// album ���������������������camera ������������������������������������������
+					sourceType: ['camera', 'album'],
+					// ��������������������������������������������������� true������������������
+					compressed: true,
+					// 'front'���'back'���������'back'
+				}, this.videoFromData)
+
+				uni.chooseVideo({
+					...data,
+					success: (res) => {
+						let tempFilePath = { ...res }
+						tempFilePath['path'] = res.tempFilePath
+
+						// ������������������������
+						if (that.videoFromData?.size ?? false) {
+							const maxSize = that.videoFromData.size * 1024 * 1024
+
+							if (tempFilePath.size > maxSize) {
+								uni.showToast({
+									title: `������������������${that.videoFromData.size}MB`,
+									duration: 2000,
+									icon: 'none'
+								});
+								return false;
+							}
+
+						}
+						if (that.autoUpload) {
+							that.onBeforeUploadFile(tempFilePath, 'video')
+						} else {
+							that.FileList.push(tempFilePath)
+							that.tempFile_paths.push(tempFilePath)
+						}
+					},
+					fail(err) {
+						console.error('������������������', err)
+					}
+
+				})
+			}
+		},
+
+		/**
+		 * ���������������
+		 * @param { tempFile } ������������
+		 * @return { Promise }
+		 * */ 
+		onBeforeUploadFile(tempFile) {
+			if (this.useBeforeUpload) {
+				return this.$emit('beforeUpload', tempFile, () => {
+					return this.updataFile(tempFile);
+				})
+			}
+			return this.updataFile(tempFile);
+		},
+
+		/**
+		 * ������������������������
+		 * @param { tempFile } ������������
+		 * @return { Promise }
+		 * */
+		updataFile(tempFile) {
+			const that = this;
+			const filePath = tempFile.path || tempFile;
+			const fileType = this.fileUrlType(filePath) == 'image' ? '.png' : '.mp4';
+			const fileName = tempFile.name || Date.now() + fileType;
+
+			uni.showLoading({
+				title: this.loadingText,
+				icon: 'loading'
+			})
+
+			return new Promise((resolve, reject) => {
+				// uniCloud������
+				if (that.action === 'uniCloud') {
+
+					uniCloud.uploadFile({
+						cloudPath: String(fileName),
+						filePath: filePath,
+						// #ifdef MP-ALIPAY 
+						fileType: fileType,
+						// #endif
+						cloudPathAsRealPath: this.cloudPathAsRealPath,
+						
+						onUploadProgress: (progressEvent) => {
+							const percentCompleted = Math.round(
+								(progressEvent.loaded * 100) / progressEvent.total
+							);
+							that.$emit('onProgress', percentCompleted)
+						},
+						success(result) {
+							if (that.autoUpload) {
+								that.FileList.push(result.fileID)
+							} else {
+								that.FileList.map((item, index) => {
+									if (item === filePath || item.path === filePath) {
+										that.FileList.splice(index, 1, result.fileID)
+									}
+								})
+							}
+							
+							// #ifdef VUE2
+							that.$emit('input', that.FileList)
+							// #endif
+							// #ifdef VUE3
+							that.$emit("update:modelValue", that.FileList);
+							// #endif
+
+							resolve(result.fileID)
+							uni.hideLoading();
+							that.$emit('onProgress', {
+								...result
+							})
+						},
+						fail: (error) => {
+							uni.hideLoading();
+							console.error('error', error);
+							that.$emit('onError', error)
+							reject(error)
+						}
+					})
+					return false;
+				}
+
+				// ������������������
+				const uploadTask = uni.uploadFile({
+					url: that.action,
+					filePath: filePath,
+					name: that.fileName,
+					formData: that.data,
+					header: that.headers,
+					// #ifdef MP-ALIPAY
+					fileType: filetype,
+					// #endif
+					success: (uploadFileRes) => {
+						const data = JSON.parse(uploadFileRes.data)
+						uni.hideLoading();
+						that.success(data)
+
+						if (!this.autoUpload) {
+							that.FileList.map((item, index) => {
+								if (item === filePath || item.path === filePath) {
+									that.FileList.splice(index, 1)
+								}
+							})
+						}
+
+						resolve(data)
+					},
+					fail: (error) => {
+						uni.hideLoading();
+						console.error('error', error);
+						that.$emit('onError', error)
+						reject(error)
+					}
+				});
+
+				uploadTask.onProgressUpdate((res) => {
+					that.$emit('onProgress', {
+						...res,
+						...tempFile
+					})
+				});
+			})
+		},
+
+		/**
+		 * ������������
+		 * */
+		submit() {
+
+			return new Promise((resolve, reject) => {
+				if (this.tempFile_paths.length <= 0) {
+					resolve([])
+				}
+
+				const uploadedFilePaths = this.tempFile_paths.map(item => {
+					return this.onBeforeUploadFile(item || item.path)
+				})
+
+				Promise.all(uploadedFilePaths).then(res => {
+					this.tempFile_paths = []
+					resolve(res)
+				}).catch(err => {
+					reject(err)
+				})
+			})
+
+		},
+
+		/**
+		 * ������������
+		 * @param {array} data ������������������������
+		 * @return {array} ������������
+		 * */
+		success(data) {
+			this.$emit('onSuccess', data);
+
+			// ���������������������-���������������
+			// const list = data.map(item=> {
+			// 	return JSON.parse(item).data.link;
+			// })
+			// this.$emit('input', [...this.FileList, ...list]);
+		},
+		/**
+		 * ������������
+		 * @param {array} tempFilePaths ������������������
+		 * @return {array} ���������������������������
+		 * */
+		async compressImage(tempFilePaths) {
+			const that = this;
+
+			return new Promise((resolve, reject) => {
+
+				if (typeof tempFilePaths !== 'string') {
+					console.error('������������������')
+					reject([])
+				}
+
+				uni.showLoading({
+					title: '���������...',
+					icon: 'loading',
+				})
+
+				// #ifdef H5
+				this.canvasDataURL(tempFilePaths, {
+					quality: that.imageFormData.quality / 100
+				}, (base64Codes) => {
+					resolve(base64Codes);
+					uni.hideLoading();
+				})
+				// #endif
+
+				// #ifndef H5
+				uni.compressImage({
+					src: tempFilePaths,
+					quality: that.imageFormData.quality || 80,
+					success: res => {
+						resolve(res.tempFilePath);
+						uni.hideLoading();
+					},
+					fail(err) {
+						reject(err);
+						uni.hideLoading();
+					}
+				})
+				// #endif
+
+			})
+		},
+
+		/**
+		 * H5������������������
+		 * @param {string} path ������������
+		 * @param {object} obj ������������
+		 * @param {function} callback ������������
+		 * @return {string} base64
+		 * */
+		canvasDataURL(path, obj, callback) {
+			var img = new Image();
+			img.src = path;
+			img.onload = function () {
+				var that = this;
+				// ���������������������
+				var w = that.width,
+					h = that.height,
+					scale = w / h;
+				w = obj.width || w;
+				h = obj.height || (w / scale);
+				var quality = 0.8; // ���������������������0.8
+				//������canvas
+				var canvas = document.createElement('canvas');
+				var ctx = canvas.getContext('2d');
+				// ������������������
+				var anw = document.createAttribute("width");
+				anw.nodeValue = w;
+				var anh = document.createAttribute("height");
+				anh.nodeValue = h;
+				canvas.setAttributeNode(anw);
+				canvas.setAttributeNode(anh);
+				ctx.drawImage(that, 0, 0, w, h);
+				// ������������
+				if (obj.quality && obj.quality <= 1 && obj.quality > 0) {
+					quality = obj.quality;
+				}
+				// quality������������������������������������������
+				var base64 = canvas.toDataURL('image/jpeg', quality);
+				// ������������������base64������
+				callback(base64);
+			}
+		},
+
+		/**
+		 * ������������
+		 * @param {string, object} item ������������
+		 * */
+		previewImage(item) {
+			if (this.fileUrlType(item) === 'video') return false;
+			if (!this.isPreviewImage) return false;
+
+			const imgs = this.FileList.filter(item => {
+				return this.fileUrlType(item) !== 'video'
+			}).map(item => item?.path ?? item)
+			const current = imgs.indexOf(item || item.path);
+
+			uni.previewImage({
+				current: current,
+				urls: imgs,
+				success() {
+				},
+				fail(err) {
+					console.log(err);
+				}
+			})
+		},
+
+		/**
+		 * ������������
+		 * @param {string, object} item ������������
+		 * @param {number} index ������
+		 * */
+		previewVideo(item, index) {
+			this.$emit('onVideo', {
+				item,
+				index
+			})
+			this.tempVideoUrl = item.path;
+		},
+
+		/**
+		 * ������img������
+		 * @param {string, object} item ������������
+		 * @return {boolean} ������img������
+		 * */
+		fileUrlType(file) {
+			const filePath = file.path || file;
+
+			if (this.isBase64(filePath)) return 'image'
+
+			const fileType = filePath.split('.').pop();
+
+			const IMAGE_REGEXP = /(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg|image)/i
+			if (IMAGE_REGEXP.test(fileType)) {
+				return 'image';
+			} else {
+				return 'video';
+			}
+		},
+		// ���������������base64
+		isBase64(str) {
+			if (str === '' || typeof str !== 'string') return console.error('������������������, base64', str);
+			return str.includes('blob:') || str.includes('data:image');
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+.cl-updata {
+
+	.file-list {
+		display: grid;
+
+		&-row {
+			display: inline-flex;
+			align-items: center;
+			position: relative;
+			
+			.play-img {
+				width: 100%;
+			}
+
+			._image {
+				height: 100%;
+				width: 100%;
+			}
+
+			._video {
+				position: relative;
+				width: 100%;
+				height: 100%;
+				overflow: hidden;
+			}
+			
+			.video-fixed {
+				position: absolute;
+				top: 0;
+				left: 0;
+				bottom: 0;
+				width: 100%;
+				height: 100%;
+				border-radius: 10rpx;
+				z-index: 96;
+			}
+			
+			.play {
+				position: absolute;
+				top: 50%;
+				left: 50%;
+				transform: translate(-50%, -50%);
+				width: 30%;
+				z-index: 95;
+			}
+			
+			.app_play {
+				position: absolute;
+				top: 50%;
+				left: 50%;
+				transform: translate(-50%, -50%);
+				width: 50rpx;
+				height: 50rpx;
+			}
+
+			.remove {
+				position: absolute;
+				top: 0;
+				right: 0;
+				background-color: #373737;
+				height: 50rpx;
+				width: 50rpx;
+				border-bottom-left-radius: 200rpx;
+				z-index: 97;
+
+				.image {
+					width: 20rpx;
+					height: 20rpx;
+					position: absolute;
+					right: 12rpx;
+					top: 12rpx;
+				}
+			}
+		}
+
+		.add-image {
+			display: flex;
+			align-items: center;
+			justify-content: center;
+			border: 2rpx dashed #ccc;
+			width: 100%;
+			height: 100%;
+			border-radius: 5rpx;
+
+			&:active {
+				opacity: 0.8;
+			}
+
+			._image {
+				width: 40%;
+			}
+		}
+	}
+
+	.mask {
+		background-color: #000;
+		position: fixed;
+		top: 0;
+		right: 0;
+		bottom: 0;
+		left: 0;
+		z-index: 99;
+
+		.block {
+			padding: 0 30rpx;
+			position: absolute;
+			top: 50%;
+			left: 50%;
+			transform: translate(-50%, -50%);
+			width: 100%;
+
+			.block_video {
+				width: 100%;
+				height: 78vh;
+			}
+		}
+
+		._root {
+			width: 60rpx;
+			height: 60rpx;
+			position: absolute;
+			left: 40rpx;
+			top: 5vh
+		}
+	}
+}
+</style>

--
Gitblit v1.8.0