From f26f29d84e0a68831a6af14dab3eec5500496d2e Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期三, 28 五月 2025 16:48:52 +0800
Subject: [PATCH] 初始化项目

---
 uview-ui/components/u-upload/u-upload.vue |  660 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 660 insertions(+), 0 deletions(-)

diff --git a/uview-ui/components/u-upload/u-upload.vue b/uview-ui/components/u-upload/u-upload.vue
new file mode 100644
index 0000000..e58bb65
--- /dev/null
+++ b/uview-ui/components/u-upload/u-upload.vue
@@ -0,0 +1,660 @@
+<template>
+	<view class="u-upload" v-if="!disabled">
+		<view
+			v-if="showUploadList"
+			class="u-list-item u-preview-wrap"
+			v-for="(item, index) in lists"
+			:key="index"
+			:style="{
+				width: $u.addUnit(width),
+				height: $u.addUnit(height)
+			}"
+		>
+			<view
+				v-if="deletable"
+				class="u-delete-icon"
+				@tap.stop="deleteItem(index)"
+				:style="{
+					background: delBgColor
+				}"
+			>
+				<u-icon class="u-icon" :name="delIcon" size="20" :color="delColor"></u-icon>
+			</view>
+			<u-line-progress
+				v-if="showProgress && item.progress > 0 && !item.error"
+				:show-percent="false"
+				height="16"
+				class="u-progress"
+				:percent="item.progress"
+			></u-line-progress>
+			<view @tap.stop="retry(index)" v-if="item.error" class="u-error-btn">鐐瑰嚮閲嶈瘯</view>
+			<image @tap.stop="doPreviewImage(item.url || item.path, index)" class="u-preview-image" v-if="!item.isImage" :src="item.url || item.path" :mode="imageMode"></image>
+		</view>
+		<slot name="file" :file="lists"></slot>
+		<view style="display: inline-block;" @tap="selectFile" v-if="maxCount > lists.length">
+			<slot name="addBtn"></slot>
+			<view
+				v-if="!customBtn"
+				class="u-list-item u-add-wrap"
+				hover-class="u-add-wrap__hover"
+				hover-stay-time="150"
+				:style="{
+					width: $u.addUnit(width),
+					height: $u.addUnit(height)
+				}"
+			>
+				<u-icon name="plus" class="u-add-btn" size="40"></u-icon>
+				<view class="u-add-tips">{{ uploadText }}</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+/**
+ * upload 鍥剧墖涓婁紶
+ * @description 璇ョ粍浠剁敤浜庝笂浼犲浘鐗囧満鏅�
+ * @tutorial https://www.uviewui.com/components/upload.html
+ * @property {String} action 鏈嶅姟鍣ㄤ笂浼犲湴鍧�
+ * @property {String Number} max-count 鏈�澶ч�夋嫨鍥剧墖鐨勬暟閲忥紙榛樿99锛�
+ * @property {Boolean} custom-btn 濡傛灉闇�瑕佽嚜瀹氫箟閫夋嫨鍥剧墖鐨勬寜閽紝璁剧疆涓簍rue锛堥粯璁alse锛�
+ * @property {Boolean} show-progress 鏄惁鏄剧ず杩涘害鏉★紙榛樿true锛�
+ * @property {Boolean} disabled 鏄惁鍚敤(鏄剧ず/绉讳粨)缁勪欢锛堥粯璁alse锛�
+ * @property {String} image-mode 棰勮鍥剧墖绛夋樉绀烘ā寮忥紝鍙�夊�间负uni鐨刬mage鐨刴ode灞炴�у�硷紙榛樿aspectFill锛�
+ * @property {String} del-icon 鍙充笂瑙掑垹闄ゅ浘鏍囧悕绉帮紝鍙兘涓簎View鍐呯疆鍥炬爣
+ * @property {String} del-bg-color 鍙充笂瑙掑叧闂寜閽殑鑳屾櫙棰滆壊
+ * @property {String | Number} index 鍦ㄥ悇涓洖璋冧簨浠朵腑鐨勬渶鍚庝竴涓弬鏁拌繑鍥烇紝鐢ㄤ簬鍖哄埆鏄摢涓�涓粍浠剁殑浜嬩欢
+ * @property {String} del-color 鍙充笂瑙掑叧闂寜閽浘鏍囩殑棰滆壊
+ * @property {Object} header 涓婁紶鎼哄甫鐨勫ご淇℃伅锛屽璞″舰寮�
+ * @property {Object} form-data 涓婁紶棰濆鎼哄甫鐨勫弬鏁�
+ * @property {String} name 涓婁紶鏂囦欢鐨勫瓧娈靛悕锛屼緵鍚庣鑾峰彇浣跨敤锛堥粯璁ile锛�
+ * @property {Array<String>} size-type original 鍘熷浘锛宑ompressed 鍘嬬缉鍥撅紝榛樿浜岃�呴兘鏈夛紙榛樿['original', 'compressed']锛�
+ * @property {Array<String>} source-type 閫夋嫨鍥剧墖鐨勬潵婧愶紝album-浠庣浉鍐岄�夊浘锛宑amera-浣跨敤鐩告満锛岄粯璁や簩鑰呴兘鏈夛紙榛樿['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)锛岄粯璁や笉闄愬埗锛堥粯璁umber.MAX_VALUE锛�
+ * @property {Array<Object>} file-list 榛樿鏄剧ず鐨勫浘鐗囧垪琛紝鏁扮粍鍏冪礌涓哄璞★紝蹇呴』鎻愪緵url灞炴��
+ * @property {Boolean} upload-text 閫夋嫨鍥剧墖鎸夐挳鐨勬彁绀烘枃瀛楋紙榛樿鈥滈�夋嫨鍥剧墖鈥濓級
+ * @property {Boolean} auto-upload 閫夋嫨瀹屽浘鐗囨槸鍚﹁嚜鍔ㄤ笂浼狅紝瑙佷笂鏂硅鏄庯紙榛樿true锛�
+ * @property {Boolean} show-tips 鐗规畩鎯呭喌涓嬫槸鍚﹁嚜鍔ㄦ彁绀簍oast锛岃涓婃柟璇存槑锛堥粯璁rue锛�
+ * @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
+		},
+		// 棰勮涓婁紶鐨勫浘鐗囨椂鐨勮鍓ā寮忥紝鍜宨mage缁勪欢mode灞炴�т竴鑷�
+		imageMode: {
+			type: String,
+			default: 'aspectFill'
+		},
+		// 澶撮儴淇℃伅
+		header: {
+			type: Object,
+			default() {
+				return {};
+			}
+		},
+		// 棰濆鎼哄甫鐨勫弬鏁�
+		formData: {
+			type: Object,
+			default() {
+				return {};
+			}
+		},
+		// 涓婁紶鐨勬枃浠跺瓧娈靛悕
+		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: 200
+		},
+		// 鍐呴儴棰勮鍥剧墖鍖哄煙鍜岄�夋嫨鍥剧墖鎸夐挳鐨勫尯鍩熼珮搴�
+		height: {
+			type: [String, Number],
+			default: 200
+		},
+		// 鍙充笂瑙掑叧闂寜閽殑鑳屾櫙棰滆壊
+		delBgColor: {
+			type: String,
+			default: '#fa3534'
+		},
+		// 鍙充笂瑙掑叧闂寜閽殑鍙夊彿鍥炬爣鐨勯鑹�
+		delColor: {
+			type: String,
+			default: '#ffffff'
+		},
+		// 鍙充笂瑙掑垹闄ゅ浘鏍囧悕绉帮紝鍙兘涓簎View鍐呯疆鍥炬爣
+		delIcon: {
+			type: String,
+			default: 'close'
+		},
+		// 濡傛灉涓婁紶鍚庣殑杩斿洖鍊间负json瀛楃涓诧紝鏄惁鑷姩杞琷son
+		toJson: {
+			type: Boolean,
+			default: true
+		},
+		// 涓婁紶鍓嶇殑閽╁瓙锛屾瘡涓枃浠朵笂浼犲墠閮戒細鎵ц
+		beforeUpload: {
+			type: Function,
+			default: null
+		},
+		// 绉婚櫎鏂囦欢鍓嶇殑閽╁瓙
+		beforeRemove: {
+			type: Function,
+			default: null
+		},
+		// 鍏佽涓婁紶鐨勫浘鐗囧悗缂�
+		limitType:{
+			type: Array,
+			default() {
+				// 鏀粯瀹濆皬绋嬪簭鐪熸満閫夋嫨鍥剧墖鐨勫悗缂�涓�"image"
+				// https://opendocs.alipay.com/mini/api/media-image
+				return ['png', 'jpg', 'jpeg', 'webp', 'gif', 'image'];
+			}
+		},
+		// 鍦ㄥ悇涓洖璋冧簨浠朵腑鐨勬渶鍚庝竴涓弬鏁拌繑鍥烇紝鐢ㄤ簬鍖哄埆鏄摢涓�涓粍浠剁殑浜嬩欢
+		index: {
+			type: [Number, String],
+			default: ''
+		}
+	},
+	mounted() {},
+	data() {
+		return {
+			lists: [],
+			isInCount: true,
+			uploading: false
+		};
+	},
+	watch: {
+		fileList: {
+			immediate: true,
+			handler(val) {
+				val.map(value => {
+					// 棣栧厛妫�鏌ュ唴閮ㄦ槸鍚﹀凡缁忔坊鍔犺繃杩欏紶鍥剧墖锛屽洜涓哄閮ㄧ粦瀹氫簡涓�涓璞$粰fileList鐨勮瘽(瀵硅薄寮曠敤)锛岃繘琛屼慨鏀瑰閮╢ileList
+					// 鏃讹紝浼氳Е鍙憌atch锛屽鑷撮噸鏂版妸鍘熸潵鐨勫浘鐗囧啀娆℃坊鍔犲埌this.lists
+					// 鏁扮粍鐨剆ome鏂规硶鎰忔�濇槸锛屽彧瑕佹暟缁勫厓绱犳湁浠绘剰涓�涓厓绱犳潯浠剁鍚堬紝灏辫繑鍥瀟rue锛岃�屽彟涓�涓暟缁勭殑every鏂规硶鐨勬剰鎬濇槸鏁扮粍鎵�鏈夊厓绱犻兘绗﹀悎鏉′欢鎵嶈繑鍥瀟rue
+					let tmp = this.lists.some(val => {
+						return val.url == value.url;
+					})
+					// 濡傛灉鍐呴儴娌℃湁杩欎釜鍥剧墖(tmp涓篺alse)锛屽垯娣诲姞鍒板唴閮�
+					!tmp && this.lists.push({ url: value.url, error: false, progress: 100 });
+				});
+			}
+		},
+		// 鐩戝惉lists鐨勫彉鍖栵紝鍙戝嚭浜嬩欢
+		lists(n) {
+			this.$emit('on-list-change', n, this.index);
+		}
+	},
+	methods: {
+		// 娓呴櫎鍒楄〃
+		clear() {
+			this.lists = [];
+		},
+		// 閲嶆柊涓婁紶闃熷垪涓笂浼犲け璐ョ殑鎵�鏈夋枃浠�
+		reUpload() {
+			this.uploadFile();
+		},
+		// 閫夋嫨鍥剧墖
+		selectFile() {
+			if (this.disabled) return;
+			const { name = '', maxCount, multiple, maxSize, sizeType, lists, camera, compressed, maxDuration, sourceType } = this;
+			let chooseFile = null;
+			const newMaxCount = maxCount - lists.length;
+			// 璁剧疆涓哄彧閫夋嫨鍥剧墖鐨勬椂鍊欎娇鐢� chooseImage 鏉ュ疄鐜�
+			chooseFile = new Promise((resolve, reject) => {
+				uni.chooseImage({
+					count: multiple ? (newMaxCount > 9 ? 9 : newMaxCount) : 1,
+					sourceType: sourceType,
+					sizeType,
+					success: resolve,
+					fail: reject
+				});
+			});
+			chooseFile
+				.then(res => {
+					let file = null;
+					let listOldLength = this.lists.length;
+					res.tempFiles.map((val, index) => {
+						// 妫�鏌ユ枃浠跺悗缂�鏄惁鍏佽锛屽鏋滀笉鍦╰his.limitType鍐咃紝灏变細杩斿洖false
+						if(!this.checkFileExt(val)) return ;
+						
+						// 濡傛灉鏄潪澶氶�夛紝index澶т簬绛変簬1鎴栬�呰秴鍑烘渶澶ч檺鍒舵暟閲忔椂锛屼笉澶勭悊
+						if (!multiple && index >= 1) return;
+						if (val.size > maxSize) {
+							this.$emit('on-oversize', val, this.lists, this.index);
+							this.showToast('瓒呭嚭鍏佽鐨勬枃浠跺ぇ灏�');
+						} else {
+							if (maxCount <= lists.length) {
+								this.$emit('on-exceed', val, this.lists, this.index);
+								this.showToast('瓒呭嚭鏈�澶у厑璁哥殑鏂囦欢涓暟');
+								return;
+							}
+							lists.push({
+								url: val.path,
+								progress: 0,
+								error: false,
+								file: val
+							});
+						}
+					});
+					// 姣忔鍥剧墖閫夋嫨瀹岋紝鎶涘嚭涓�涓簨浠讹紝骞跺皢褰撳墠鍐呴儴閫夋嫨鐨勫浘鐗囨暟缁勬姏鍑哄幓
+					this.$emit('on-choose-complete', this.lists, this.index);
+					if (this.autoUpload) this.uploadFile(listOldLength);
+				})
+				.catch(error => {
+					this.$emit('on-choose-fail', error);
+				});
+		},
+		// 鎻愮ず鐢ㄦ埛娑堟伅
+		showToast(message, force = false) {
+			if (this.showTips || force) {
+				uni.showToast({
+					title: message,
+					icon: 'none'
+				});
+			}
+		},
+		// 璇ユ柟娉曚緵鐢ㄦ埛閫氳繃ref璋冪敤锛屾墜鍔ㄤ笂浼�
+		upload() {
+			this.uploadFile();
+		},
+		// 瀵瑰け璐ョ殑鍥剧墖閲嶆柊涓婁紶
+		retry(index) {
+			this.lists[index].progress = 0;
+			this.lists[index].error = false;
+			this.lists[index].response = null;
+			uni.showLoading({
+				title: '閲嶆柊涓婁紶'
+			});
+			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, this.index);
+				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') {
+				// 鎵ц鍥炶皟锛屽悓鏃朵紶鍏ョ储寮曞拰鏂囦欢鍒楄〃褰撲綔鍙傛暟
+				// 鍦ㄥ井淇★紝鏀粯瀹濈瓑鐜(H5姝e父)锛屼細瀵艰嚧鐖剁粍浠跺畾涔夌殑customBack()鍑芥暟浣撲腑鐨則his鍙樻垚瀛愮粍浠剁殑this
+				// 閫氳繃bind()鏂规硶锛岀粦瀹氱埗缁勪欢鐨則his锛岃this.customBack()鐨則his涓虹埗缁勪欢鐨勪笂涓嬫枃
+				// 鍥犱负upload缁勪欢鍙兘浼氳宓屽鍦ㄥ叾浠栫粍浠跺唴锛屾瘮濡倁-form锛岃繖鏃秚his.$parent鍏跺疄涓簎-form鐨則his锛�
+				// 闈為〉闈㈢殑this锛屾墍浠ヨ繖閲岄渶瑕佸線涓婂巻閬嶏紝涓�鐩村鎵惧埌鏈�椤剁鐨�$parent锛岃繖閲岀敤浜唗his.$u.$parent.call(this)
+				// 鏄庣櫧鎰忔�濆嵆鍙紝鏃犻渶绾犵粨this.$u.$parent.call(this)鐨勭粏鑺�
+				let beforeResponse = this.beforeUpload.bind(this.$u.$parent.call(this))(index, this.lists);
+				// 鍒ゆ柇鏄惁杩斿洖浜唒romise
+				if (!!beforeResponse && typeof beforeResponse.then === 'function') {
+					let error = false;
+					await beforeResponse.then(res => {
+						// promise杩斿洖鎴愬姛锛屼笉杩涜鍔ㄤ綔锛岀户缁笂浼�
+					}).catch(err => {
+						// 杩涘叆catch鍥炶皟鐨勮瘽锛岀户缁笅涓�寮�
+						// return this.uploadFile(index + 1);
+						// 鍦� cache 涓� return 鍙槸杩斿洖鏈柟娉曪紝骞朵笉鏄繑鍥� uploadFile 鏂规硶锛岄渶瑕佸湪澶栧眰杩涜杩斿洖 ThinkGem
+						error = true;
+					})
+					if (error){
+						return this.uploadFile(index + 1);
+					}
+				} else if(beforeResponse === false) {
+					// 濡傛灉杩斿洖false锛岀户缁笅涓�寮犲浘鐗囩殑涓婁紶
+					return this.uploadFile(index + 1);
+				} else {
+					// 姝ゅ涓鸿繑鍥�"true"鐨勬儏褰紝杩欓噷涓嶅啓浠g爜锛屽氨璺宠繃姝ゅ锛岀户缁墽琛屽綋鍓嶇殑涓婁紶閫昏緫
+				}
+			}
+			// 妫�鏌ヤ笂浼犲湴鍧�
+			if (!this.action) {
+				this.showToast('璇烽厤缃笂浼犲湴鍧�', true);
+				return;
+			}
+			this.lists[index].error = false;
+			this.uploading = true;
+			// 鍒涘缓涓婁紶瀵硅薄
+			const task = uni.uploadFile({
+				url: this.action,
+				filePath: this.lists[index].url,
+				name: this.name,
+				formData: this.formData,
+				header: this.header,
+				success: res => {
+					// 鍒ゆ柇鏄惁json瀛楃涓诧紝灏嗗叾杞负json鏍煎紡
+					let data = this.toJson && this.$u.test.jsonString(res.data) ? JSON.parse(res.data) : res.data;
+					if (![200, 201, 204].includes(res.statusCode)) {
+						this.uploadError(index, data);
+					} else {
+						// 涓婁紶鎴愬姛
+						this.lists[index].response = data;
+						this.lists[index].progress = 100;
+						this.lists[index].error = false;
+						this.$emit('on-success', data, index, this.lists, this.index);
+					}
+				},
+				fail: e => {
+					this.uploadError(index, e);
+				},
+				complete: res => {
+					uni.hideLoading();
+					this.uploading = false;
+					this.uploadFile(index + 1);
+					this.$emit('on-change', res, index, this.lists, this.index);
+				}
+			});
+			task.onProgressUpdate(res => {
+				if (res.progress > 0) {
+					this.lists[index].progress = res.progress;
+					this.$emit('on-progress', res, index, this.lists, this.index);
+				}
+			});
+		},
+		// 涓婁紶澶辫触
+		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.index);
+			this.showToast('涓婁紶澶辫触锛岃閲嶈瘯');
+		},
+		// 鍒犻櫎涓�涓浘鐗�
+		deleteItem(index) {
+			uni.showModal({
+				title: '鎻愮ず',
+				content: '鎮ㄧ‘瀹氳鍒犻櫎姝ら」鍚楋紵',
+				success: async (res) => {
+					if (res.confirm) {
+						// 鍏堟鏌ユ槸鍚︽湁瀹氫箟before-remove绉婚櫎鍓嶉挬瀛�
+						// 鎵цbefore-remove閽╁瓙
+						if(this.beforeRemove && typeof(this.beforeRemove) === 'function') {
+							// 姝ゅ閽╁瓙鎵ц 鍘熺悊鍚宐efore-remove鍙傛暟锛岃涓婃柟娉ㄩ噴
+							let beforeResponse = this.beforeRemove.bind(this.$u.$parent.call(this))(index, this.lists);
+							// 鍒ゆ柇鏄惁杩斿洖浜唒romise
+							if (!!beforeResponse && typeof beforeResponse.then === 'function') {
+								await beforeResponse.then(res => {
+									// promise杩斿洖鎴愬姛锛屼笉杩涜鍔ㄤ綔锛岀户缁笂浼�
+									this.handlerDeleteItem(index);
+								}).catch(err => {
+									// 濡傛灉杩涘叆promise鐨剅eject锛岀粓姝㈠垹闄ゆ搷浣�
+									this.showToast('宸茬粓姝㈢Щ闄�');
+								})
+							} else if(beforeResponse === false) {
+								// 杩斿洖false锛岀粓姝㈠垹闄�
+								this.showToast('宸茬粓姝㈢Щ闄�');
+							} else {
+								// 濡傛灉杩斿洖true锛屾墽琛屽垹闄ゆ搷浣�
+								this.handlerDeleteItem(index);
+							}
+						} else {
+							// 濡傛灉涓嶅瓨鍦╞efore-remove閽╁瓙锛�
+							this.handlerDeleteItem(index);
+						}
+					}
+				}
+			});
+		},
+		// 鎵ц绉婚櫎鍥剧墖鐨勫姩浣滐紝涓婃柟浠g爜鍙槸鍒ゆ柇鏄惁鍙互绉婚櫎
+		handlerDeleteItem(index) {
+			// 濡傛灉鏂囦欢姝e湪涓婁紶涓紝缁堟涓婁紶浠诲姟锛岃繘搴﹀湪0 < progress < 100鍒欐剰鍛崇潃姝e湪涓婁紶
+			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.index);
+			this.showToast('绉婚櫎鎴愬姛');
+		},
+		// 鐢ㄦ埛閫氳繃ref鎵嬪姩鐨勫舰寮忥紝绉婚櫎涓�寮犲浘鐗�
+		remove(index) {
+			// 鍒ゆ柇绱㈠紩鐨勫悎娉曡寖鍥�
+			if (index >= 0 && index < this.lists.length) {
+				this.lists.splice(index, 1);
+				this.$emit('on-list-change', this.lists, this.index);
+			}
+		},
+		// 棰勮鍥剧墖
+		doPreviewImage(url, index) {
+			if (!this.previewFullImage) return;
+			const images = this.lists.map(item => item.url || item.path);
+			uni.previewImage({
+				urls: images,
+				current: url,
+				success: () => {
+					this.$emit('on-preview', url, this.lists, this.index);
+				},
+				fail: () => {
+					uni.showToast({
+						title: '棰勮鍥剧墖澶辫触',
+						icon: 'none'
+					});
+				}
+			});
+		},
+		// 鍒ゆ柇鏂囦欢鍚庣紑鏄惁鍏佽
+		checkFileExt(file) {
+			// 妫�鏌ユ槸鍚﹀湪鍏佽鐨勫悗缂�涓�
+			let noArrowExt = false;
+			// 鑾峰彇鍚庣紑鍚�
+			let fileExt = '';
+			const reg = /.+\./;
+			// 濡傛灉鏄疕5锛岄渶瑕佷粠name涓垽鏂�
+			// #ifdef H5
+			fileExt = file.name.replace(reg, "").toLowerCase();
+			// #endif
+			// 闈濰5锛岄渶瑕佷粠path涓鍙栧悗缂�
+			// #ifndef H5
+			fileExt = file.path.replace(reg, "").toLowerCase();
+			// #endif
+			// 浣跨敤鏁扮粍鐨剆ome鏂规硶锛屽彧瑕佺鍚坙imitType涓殑涓�涓紝灏辫繑鍥瀟rue
+			noArrowExt = this.limitType.some(ext => {
+				// 杞负灏忓啓
+				return ext.toLowerCase() === fileExt;
+			})
+			if(!noArrowExt) this.showToast(`涓嶅厑璁搁�夋嫨${fileExt}鏍煎紡鐨勬枃浠禶);
+			return noArrowExt;
+		}
+	}
+};
+</script>
+
+<style lang="scss" scoped>
+@import '../../libs/css/style.components.scss';
+
+.u-upload {
+	@include vue-flex;
+	flex-wrap: wrap;
+	align-items: center;
+}
+
+.u-list-item {
+	width: 200rpx;
+	height: 200rpx;
+	overflow: hidden;
+	margin: 10rpx;
+	background: rgb(244, 245, 246);
+	position: relative;
+	border-radius: 10rpx;
+	/* #ifndef APP-NVUE */
+	display: flex;
+	/* #endif */
+	align-items: center;
+	justify-content: center;
+}
+
+.u-preview-wrap {
+	border: 1px solid rgb(235, 236, 238);
+}
+
+.u-add-wrap {
+	flex-direction: column;
+	color: $u-content-color;
+	font-size: 26rpx;
+}
+
+.u-add-tips {
+	margin-top: 20rpx;
+	line-height: 40rpx;
+}
+
+.u-add-wrap__hover {
+	background-color: rgb(235, 236, 238);
+}
+
+.u-preview-image {
+	display: block;
+	width: 100%;
+	height: 100%;
+	border-radius: 10rpx;
+}
+
+.u-delete-icon {
+	position: absolute;
+	top: 10rpx;
+	right: 10rpx;
+	z-index: 10;
+	background-color: $u-type-error;
+	border-radius: 100rpx;
+	width: 44rpx;
+	height: 44rpx;
+	@include vue-flex;
+	align-items: center;
+	justify-content: center;
+}
+
+.u-icon {
+	@include vue-flex;
+	align-items: center;
+	justify-content: center;
+}
+
+.u-progress {
+	position: absolute;
+	bottom: 10rpx;
+	left: 8rpx;
+	right: 8rpx;
+	z-index: 9;
+	width: auto;
+}
+
+.u-error-btn {
+	color: #ffffff;
+	background-color: $u-type-error;
+	font-size: 20rpx;
+	padding: 4px 0;
+	text-align: center;
+	position: absolute;
+	bottom: 0;
+	left: 0;
+	right: 0;
+	z-index: 9;
+	line-height: 1;
+}
+</style>

--
Gitblit v1.9.3