<template>
	<image v-if="loadedImage" :lazy-load="true" :src="url" :mode="mode" @load="load" @error="loadfail" class="fade-in-image" />
</template>

<script>
export default {
	props: {
		src: {
			type: String,
			default: ''
		},
		mode: {
			type: String,
			default: 'aspectFill'
		}
	},
	data() {
		return {
			url: '',
			loadedImage: false,
			hasReloaded: false,
			request: null
		};
	},
	watch: {
		src: {
			handler(newVal, oldVal) {
				if (newVal.indexOf('_xfile') != -1) {
					this.loadedImage = false;
					let url = newVal;
					this.error(url);
				} else {
					this.url = newVal;
					this.loadedImage = true;
				}
			},
			immediate: true
		}
	},

	mounted() {},
	beforeDestroy() {
		console.log('销毁');
		if (this.request) {
			this.request.abort();
		}
		if (typeof this.url === 'string' && this.url.startsWith('blob:')) {
			URL.revokeObjectURL(this.url); // 释放 Blob URL 资源
		}
	},
	methods: {
		loadfail(e) {
			if (!this.hasReloaded) {
				this.hasReloaded = true;

				if (this.url.startsWith('data:image/') && this.url.includes(';base64,')) {
					let url = this.url;
					this.loadedImage = true;
					return;
				}
				if (this.url.indexOf('_xfile') != -1) {
					this.loadedImage = false;
					let url = this.url + '?' + new Date().getTime();
					this.error(url);
				} else {
					this.url = this.url + '?' + new Date().getTime();
					this.loadedImage = true;
				}
			} else {
				this.$emit('error');
			}
		},
		load(e) {
			this.$emit('load', true);
		},

		async error(url) {
			this.url = await this.loadImage(url);
			this.loadedImage = true;
			return;
		},
		loadImage(url) {
			return new Promise((resolve, reject) => {
				this.request = uni.request({
					method: 'get',
					url: url,
					responseType: 'arraybuffer',
					success: (res) => {
						// const [error, res] = response;
						if (res && res.statusCode == 200) {
							try {
								var bytes = new Uint8Array(res.data);
								var binary = '';
								var len = bytes.byteLength;

								// 对数据进行异或处理
								for (var i = 0; i < len; i++) {
									bytes[i] = bytes[i] ^ 136; // 注意：136 是数字，不要加引号
								}

								// #ifdef APP-PLUS
								for (var i = 0; i < len; i++) {
									binary += String.fromCharCode(bytes[i]);
								}
								var base64Data = btoa(binary);
								resolve('data:image/jpeg;base64,' + base64Data);
								// #endif

								// #ifdef H5
								var blob = new Blob([bytes], {
									type: 'image/jpeg'
								});
								var reader = new FileReader();
								reader.onloadend = function () {
									resolve(reader.result); // 读取结果为 Base64 格式的 Data URL
								};
								reader.readAsDataURL(blob); // 将 Blob 读取为 Base64 Data URL
								// #endif
							} catch (e) {
								resolve(url);
							}
						} else {
							resolve(url);
						}
					},
					fail: () => {
						resolve(url);
					}
				});
			});
		}
	}
};
</script>

<style>
/* 定义渐显动画 */
.fade-in-image {
	animation: fadeIn ease-in 0.3s;
	-webkit-animation: fadeIn ease-in 0.3s;
	-moz-animation: fadeIn ease-in 0.3s;
	-o-animation: fadeIn ease-in 0.3s;
	-ms-animation: fadeIn ease-in 0.3s;
}

/* 渐显动画的 keyframes */
@keyframes fadeIn {
	from {
		opacity: 0;
	}
	to {
		opacity: 1;
	}
}

@-webkit-keyframes fadeIn {
	from {
		opacity: 0;
	}
	to {
		opacity: 1;
	}
}

@-moz-keyframes fadeIn {
	from {
		opacity: 0;
	}
	to {
		opacity: 1;
	}
}

@-o-keyframes fadeIn {
	from {
		opacity: 0;
	}
	to {
		opacity: 1;
	}
}

@-ms-keyframes fadeIn {
	from {
		opacity: 0;
	}
	to {
		opacity: 1;
	}
}
</style>
