<template>
	<view v-if="visible" class="poster-page-overlay" @tap="handleOverlayClick">
		<view class="poster-page-container" @tap.stop>
			<!-- 海报背景 -->
			<view class="poster-wrapper">
				<image class="poster-bg" :src="`${$baseUrl}homepage/Q3Res/xingmaLabPosterBg.png`" mode="aspectFit">
				</image>

				<!-- 昵称区域 -->
				<view class="poster-nickname-wrapper">

					<!-- 昵称背景 -->
					<image class="poster-nickname-bg" :src="`${$baseUrl}homepage/Q3Res/xingmaLabPosterNickBg2.png`"
						mode="aspectFit"></image>
					<!-- 头像 -->
					<image v-if="avatar" class="poster-avatar" :src="avatar" mode="aspectFit"></image>
					<text class="poster-nickname-text">{{ nickname || '' }}</text>
				</view>

				<!-- 图片区域 -->
				<view class="poster-image-wrapper">
					<image class="poster-image-bg" :src="`${$baseUrl}homepage/Q3Res/xingmaLabPosterImgBg2.png`"
						mode="aspectFit"></image>
					<image v-if="imageUrl" class="poster-image" :src="imageUrl" mode="aspectFit"></image>
					<!-- 文字内容 -->
					<view class="poster-content">
						<text class="poster-content-text">{{ content || '' }}</text>
					</view>

					<!-- 唯一藏品编号 -->
					<view class="poster-collection-number">
						<text class="collection-number-text">唯一藏品编号: {{ collectionNumber }}</text>
					</view>

					<!-- 下载按钮 -->
					<view class="poster-download-btn" @tap="handleDownload">
						<image class="download-icon" :src="`${$baseUrl}homepage/Q3Res/xingmaLabPosterDownloadBtn.png`"
							mode="aspectFit"></image>
					</view>

					<!-- 二维码区域 -->
					<view class="poster-qrcode-wrapper">
						<image v-if="qrcodeImageUrl" class="poster-qrcode-image" :src="qrcodeImageUrl" mode="aspectFit">
						</image>
					</view>
				</view>




			</view>

			<!-- 关闭按钮 -->
			<view class="poster-close-btn" @tap="handleClose">
				<image class="close-icon" :src="`${$baseUrl}homepage/Q3Res/xingmaLabPosterBtnConCloseBtn2.png`"
					mode="aspectFit"></image>
			</view>
		</view>

		<!-- 隐藏的 canvas 用于合成海报 -->
		<canvas canvas-id="posterCanvas" class="poster-canvas"
			:style="{ width: canvasWidth + 'px', height: canvasHeight + 'px' }"></canvas>
	</view>
</template>

<script setup>
import { ref, watch, getCurrentInstance, nextTick, computed } from 'vue'
import md from '../../md'
import { generateQRCode } from '../../api/xingmaLab'

const { proxy } = getCurrentInstance()
const $baseUrl = proxy.$baseUrl

const props = defineProps({
	visible: {
		type: Boolean,
		default: false
	},
	imageUrl: {
		type: String,
		default: ''
	},
	content: {
		type: String,
		default: '可爱'
	},
	collectionNumber: {
		type: String,
		default: ''
	},
	defaultNickname: {
		type: String,
		default: ''
	},
	avatar: {
		type: String,
		default: ''
	},
	recordId: {
		type: String,
		default: ''
	}
})

const emit = defineEmits(['close', 'download'])

// 昵称从 props 传入，不可编辑
const nickname = computed(() => props.defaultNickname || '')
const qrcodeImageUrl = ref('') // 二维码图片 URL
const isDownloading = ref(false) // 是否正在下载

// Canvas 尺寸（海报尺寸：542rpx x 956rpx）
// 使用 3 倍像素密度提高分辨率
const pixelRatio = 3
const systemInfo = uni.getSystemInfoSync()
const screenWidth = systemInfo.windowWidth || 375
const baseCanvasWidth = (542 / 750) * screenWidth
const baseCanvasHeight = (956 / 750) * screenWidth
const canvasWidth = baseCanvasWidth * pixelRatio
const canvasHeight = baseCanvasHeight * pixelRatio

// 监听 visible 变化，生成二维码
watch(() => props.visible, (newVal) => {
	if (newVal) {
		nextTick(() => {
			generateQrcodeFunc()
		})
	}
})

// 生成二维码
const generateQrcodeFunc = async () => {
	if (!props.recordId) {
		console.warn('recordId 未传入，无法生成二维码')
		return
	}
	console.warn('recordId', props.recordId)

	try {
		const result = await generateQRCode({
			scene: `id=${props.recordId}`,
			page: `pages/XingmaLabDetailPage/XingmaLabDetailPage`,
			// TODO: 切换环境 需要切换envVersion 
			envVersion: 'release'//trial develop release
		})

		if (result && result.ok && result.data && result.data.qrCodeBase64) {
			// 接口返回的二维码图片 Base64 编码
			const qrCodeBase64 = result.data.qrCodeBase64
			// 判断是否为 JPEG 格式（JPEG Base64 通常以 /9j/ 开头）
			const isJPEG = qrCodeBase64.startsWith('/9j/')

			// 移除可能存在的 data:image 前缀，只保留纯 Base64 字符串
			let base64String = qrCodeBase64
			if (base64String.includes(',')) {
				base64String = base64String.split(',')[1]
			}

			// 将 Base64 转换为 Data URI
			const base64Data = isJPEG
				? `data:image/jpeg;base64,${base64String}`
				: `data:image/png;base64,${base64String}`

			// 直接赋值给图片 URL
			qrcodeImageUrl.value = base64Data
		} else {
			console.warn('生成二维码接口返回数据格式异常:', result)
		}
	} catch (error) {
		console.error('生成二维码失败:', error)
	}
}

// 关闭弹窗
const handleClose = () => {
	emit('close')
}

// 点击遮罩关闭
const handleOverlayClick = () => {
	handleClose()
}

// 下载海报
const handleDownload = async () => {
	if (isDownloading.value) {
		return
	}

	// 检查二维码是否已生成，如果没有则等待生成
	if (!qrcodeImageUrl.value) {
		uni.showLoading({
			title: '二维码生成中...',
			mask: true
		})
		// 等待二维码生成，最多等待 5 秒
		let waitCount = 0
		while (!qrcodeImageUrl.value && waitCount < 50) {
			await new Promise(resolve => setTimeout(resolve, 100))
			waitCount++
		}
		uni.hideLoading()

		if (!qrcodeImageUrl.value) {
			uni.showToast({
				title: '二维码生成失败，请重试',
				icon: 'none'
			})
			return
		}
	}

	isDownloading.value = true
	uni.showLoading({
		title: '生成中...',
		mask: true
	})

	try {
		// 等待所有图片加载完成
		await nextTick()
		// 额外等待一下，确保二维码图片已加载
		await new Promise(resolve => setTimeout(resolve, 500))

		const ctx = uni.createCanvasContext('posterCanvas', proxy)

		// 保存初始状态
		ctx.save()

		// 缩放 canvas 上下文以适应高分辨率
		ctx.scale(pixelRatio, pixelRatio)

		// 海报尺寸（使用基础尺寸，因为已经缩放）
		const posterWidth = baseCanvasWidth
		const posterHeight = baseCanvasHeight

		// 绘制背景
		await drawImage(ctx, `${$baseUrl}homepage/Q3Res/xingmaLabPosterBg.png`, 0, 0, posterWidth, posterHeight)

		// 绘制昵称背景和头像、昵称
		const nicknameBgX = (24 / 750) * screenWidth
		const nicknameBgY = (40 / 750) * screenWidth
		const nicknameBgW = (256 / 750) * screenWidth
		const nicknameBgH = (58 / 750) * screenWidth

		await drawImage(ctx, `${$baseUrl}homepage/Q3Res/xingmaLabPosterNickBg2.png`, nicknameBgX, nicknameBgY, nicknameBgW, nicknameBgH)

		// 绘制头像（带圆角）
		if (props.avatar) {
			// 头像位置：相对于昵称背景，top: 2rpx, left: 4rpx
			const avatarX = nicknameBgX + (8 / 750) * screenWidth
			const avatarY = nicknameBgY + (6 / 750) * screenWidth
			const avatarSize = (48 / 750) * screenWidth
			const avatarRadius = avatarSize / 2

			// 保存当前状态
			ctx.save()

			// 创建圆形裁剪路径
			ctx.beginPath()
			ctx.arc(avatarX + avatarRadius, avatarY + avatarRadius, avatarRadius, 0, 2 * Math.PI)
			ctx.clip()

			// 绘制头像图片
			await drawImage(ctx, props.avatar, avatarX, avatarY, avatarSize, avatarSize)

			// 恢复裁剪区域
			ctx.restore()
		}

		// 绘制昵称文字
		ctx.setFillStyle('#333333')
		ctx.setFontSize((28 / 750) * screenWidth)
		ctx.setTextAlign('left')
		const nicknameTextX = nicknameBgX + (props.avatar ? (48 + 20) / 750 * screenWidth : 30 / 750 * screenWidth)
		const nicknameTextY = nicknameBgY + nicknameBgH / 2 + (28 / 750) * screenWidth / 3
		// 计算昵称文字最大宽度（昵称背景宽度 - 左边距 - 右边距）
		const nicknameMaxWidth = nicknameBgW - (props.avatar ? (48 + 20) / 750 * screenWidth : 30 / 750 * screenWidth) - (30 / 750 * screenWidth)
		const truncatedNickname = truncateText(ctx, nickname.value || '', nicknameMaxWidth)
		ctx.fillText(truncatedNickname, nicknameTextX, nicknameTextY)

		// 绘制图片区域背景（居中）
		const imageBgW = (494 / 750) * screenWidth
		const imageBgH = (802 / 750) * screenWidth
		const imageBgX = (posterWidth - imageBgW) / 2
		const imageBgY = (120 / 750) * screenWidth

		await drawImage(ctx, `${$baseUrl}homepage/Q3Res/xingmaLabPosterImgBg2.png`, imageBgX, imageBgY, imageBgW, imageBgH)

		// 绘制主图片（自适应模式，保持宽高比）
		if (props.imageUrl) {
			const imageX = imageBgX + (26 / 750) * screenWidth
			const imageY = imageBgY + (26 / 750) * screenWidth
			const imageW = imageBgW - (52 / 750) * screenWidth
			const imageH = (586 / 750) * screenWidth
			await drawImage(ctx, props.imageUrl, imageX, imageY, imageW, imageH, true)
		}

		// 绘制文字内容
		ctx.setFillStyle('#000000')
		ctx.setFontSize((28 / 750) * screenWidth)
		ctx.setTextAlign('left')
		const contentX = imageBgX + (22 / 750) * screenWidth
		const contentY = imageBgY + imageBgH - (146 / 750) * screenWidth
		// 计算内容文字最大宽度（图片区域宽度 - 左右边距）
		const contentMaxWidth = imageBgW - (44 / 750) * screenWidth
		const truncatedContent = truncateText(ctx, props.content || '', contentMaxWidth)
		ctx.fillText(truncatedContent, contentX, contentY)

		// 绘制唯一藏品编号
		ctx.setFillStyle('#D3A458')
		ctx.setFontSize((20 / 750) * screenWidth)
		ctx.setTextAlign('left')
		const collectionX = imageBgX + (22 / 750) * screenWidth
		const collectionY = imageBgY + imageBgH - (116 / 750) * screenWidth
		ctx.fillText(`唯一藏品编号: ${props.collectionNumber || ''}`, collectionX, collectionY)

		// 绘制二维码（在图片区域右下角）
		if (qrcodeImageUrl.value) {
			const qrcodeSize = (114 / 750) * screenWidth
			// 二维码位置：图片区域右下角，距离右边 22rpx，距离底部 26rpx
			const qrcodeX = imageBgX + imageBgW - qrcodeSize - (22 / 750) * screenWidth
			const qrcodeY = imageBgY + imageBgH - qrcodeSize - (26 / 750) * screenWidth
			
			// 稍微缩小二维码尺寸以去除边框（缩小 8%，相当于去除 4% 的边框）
			const qrcodeDrawSize = qrcodeSize * 0.92
			const qrcodeDrawX = qrcodeX + (qrcodeSize - qrcodeDrawSize) / 2
			const qrcodeDrawY = qrcodeY + (qrcodeSize - qrcodeDrawSize) / 2
			
			console.log('开始绘制二维码:', {
				qrcodeX,
				qrcodeY,
				qrcodeSize,
				qrcodeDrawSize,
				imageBgX,
				imageBgY,
				imageBgW,
				imageBgH,
				qrcodeImageUrl: qrcodeImageUrl.value.substring(0, 50) + '...'
			})
			
			// 绘制二维码，使用稍微缩小的尺寸以去除边框
			await drawQRCodeImage(ctx, qrcodeImageUrl.value, qrcodeDrawX, qrcodeDrawY, qrcodeDrawSize, qrcodeDrawSize)
			console.log('二维码绘制完成')
		} else {
			console.warn('二维码图片 URL 为空，无法绘制')
		}

		// 等待所有绘制完成后再调用 draw
		await nextTick()

		// 绘制到 canvas
		ctx.draw(false, async () => {
			await nextTick()

			// 转换为临时文件（使用高分辨率）
			uni.canvasToTempFilePath({
				canvasId: 'posterCanvas',
				width: canvasWidth,
				height: canvasHeight,
				destWidth: canvasWidth,
				destHeight: canvasHeight,
				success: (res) => {
					// 保存到相册
					uni.saveImageToPhotosAlbum({
						filePath: res.tempFilePath,
						success: () => {
							uni.hideLoading()
							uni.showToast({
								title: '保存成功',
								icon: 'none'
							})
							isDownloading.value = false
						},
						fail: (err) => {
							uni.hideLoading()
							console.error('保存失败:', err)
							uni.showToast({
								title: '保存失败',
								icon: 'none'
							})
							isDownloading.value = false
						}
					})
				},
				fail: (err) => {
					uni.hideLoading()
					console.error('生成图片失败:', err)
					uni.showToast({
						title: '生成失败',
						icon: 'none'
					})
					isDownloading.value = false
				}
			}, proxy)
		})
	} catch (error) {
		uni.hideLoading()
		console.error('下载海报失败:', error)
		uni.showToast({
			title: '生成失败',
			icon: 'none'
		})
		isDownloading.value = false
	}
}

// 将 Base64 Data URI 转换为临时文件路径
const base64ToTempFilePath = (base64Data) => {
	return new Promise((resolve, reject) => {
		if (!base64Data || !base64Data.startsWith('data:image')) {
			reject(new Error('无效的 Base64 数据'))
			return
		}

		const fs = uni.getFileSystemManager()
		const base64String = base64Data.split(',')[1]
		const isJPEG = base64String.startsWith('/9j/')
		const fileExtension = isJPEG ? 'jpg' : 'png'
		const fileName = `qrcode_${Date.now()}_${Math.random().toString(36).substr(2, 9)}.${fileExtension}`

		// #ifdef MP-WEIXIN
		const userDataPath = wx.env.USER_DATA_PATH
		// #endif
		// #ifndef MP-WEIXIN
		const userDataPath = uni.env.USER_DATA_PATH || ''
		// #endif

		const filePath = `${userDataPath}/${fileName}`

		// 先尝试清理旧的临时文件（异步方式，避免阻塞）
		// #ifdef MP-WEIXIN
		if (userDataPath) {
			fs.readdir({
				dirPath: userDataPath,
				success: (res) => {
					const qrcodeFiles = res.files.filter(f => f.startsWith('qrcode_'))
					// 只保留最新的 2 个文件，删除其他旧文件
					if (qrcodeFiles.length > 2) {
						qrcodeFiles.sort().slice(0, qrcodeFiles.length - 2).forEach(oldFile => {
							fs.unlink({
								filePath: `${userDataPath}/${oldFile}`,
								success: () => { },
								fail: () => { }
							})
						})
					}
					// 清理完成后写入新文件
					writeBase64File()
				},
				fail: () => {
					// 如果读取目录失败，直接写入
					writeBase64File()
				}
			})
		} else {
			writeBase64File()
		}
		// #endif
		// #ifndef MP-WEIXIN
		writeBase64File()
		// #endif

		function writeBase64File() {
			fs.writeFile({
				filePath: filePath,
				data: base64String,
				encoding: 'base64',
				success: () => {
					resolve(filePath)
				},
				fail: (err) => {
					console.error('Base64 图片写入失败:', err)
					// 如果写入失败，尝试使用临时文件路径（uni.downloadFile 返回的路径）
					reject(err)
				}
			})
		}
	})
}

// 截断文字（canvas 中文字超出宽度时添加省略号）
const truncateText = (ctx, text, maxWidth) => {
	if (!text) return ''
	
	// 测量文字宽度
	const textWidth = ctx.measureText(text).width
	
	// 如果文字宽度小于等于最大宽度，直接返回
	if (textWidth <= maxWidth) {
		return text
	}
	
	// 如果超出，需要截断并添加省略号
	const ellipsis = '...'
	const ellipsisWidth = ctx.measureText(ellipsis).width
	const availableWidth = maxWidth - ellipsisWidth
	
	// 二分查找合适的截断位置
	let left = 0
	let right = text.length
	let mid = 0
	
	while (left < right) {
		mid = Math.floor((left + right) / 2)
		const testText = text.substring(0, mid)
		const testWidth = ctx.measureText(testText).width
		
		if (testWidth <= availableWidth) {
			left = mid + 1
		} else {
			right = mid
		}
	}
	
	// 确保至少保留一个字符
	const truncatePos = Math.max(1, left - 1)
	return text.substring(0, truncatePos) + ellipsis
}

// 获取图片信息（宽高）
const getImageInfo = (src) => {
	return new Promise((resolve, reject) => {
		uni.getImageInfo({
			src: src,
			success: (res) => {
				resolve({
					width: res.width,
					height: res.height
				})
			},
			fail: (err) => {
				reject(err)
			}
		})
	})
}

// 计算自适应尺寸（保持宽高比，根据超出比例决定适配方向）
const calculateFitSize = (imageWidth, imageHeight, containerWidth, containerHeight) => {
	const imageRatio = imageWidth / imageHeight
	
	// 计算超出比例
	const widthOverflowRatio = (imageWidth - containerWidth) / containerWidth
	const heightOverflowRatio = (imageHeight - containerHeight) / containerHeight
	
	let drawWidth, drawHeight, drawX, drawY
	
	// 如果高度超出的比例大，则高度适配（固定高度，宽度自适应）
	if (heightOverflowRatio > widthOverflowRatio) {
		drawHeight = containerHeight
		drawWidth = containerHeight * imageRatio
		drawX = (containerWidth - drawWidth) / 2
		drawY = 0
	} else {
		// 如果宽度超出的比例大，则宽度适配（固定宽度，高度自适应）
		drawWidth = containerWidth
		drawHeight = containerWidth / imageRatio
		drawX = 0
		drawY = (containerHeight - drawHeight) / 2
	}
	
	return { drawWidth, drawHeight, drawX, drawY }
}

// 绘制二维码图片（去除边框）
const drawQRCodeImage = (ctx, src, x, y, w, h) => {
	return new Promise((resolve) => {
		// 获取图片路径（Base64 需要转换）
		const getImagePath = () => {
			if (src.startsWith('data:image')) {
				return base64ToTempFilePath(src)
			} else {
				return Promise.resolve(src)
			}
		}
		
		getImagePath().then((imagePath) => {
			// 获取图片信息
			return getImageInfo(imagePath).then((info) => {
				// 二维码通常是正方形，如果图片有边框，计算裁剪区域
				// 假设二维码图片可能有边框，尝试裁剪掉边缘部分
				// 如果图片宽高比接近 1:1，可能是标准二维码，直接绘制
				// 如果图片明显不是正方形，可能需要裁剪
				
				const isSquare = Math.abs(info.width - info.height) < 10
				const minSize = Math.min(info.width, info.height)
				
				// 如果图片是正方形且尺寸合理，直接绘制
				if (isSquare && minSize > 200) {
					if (imagePath.startsWith('http')) {
						uni.downloadFile({
							url: imagePath,
							success: (res) => {
								if (res.statusCode === 200) {
									ctx.drawImage(res.tempFilePath, x, y, w, h)
									resolve()
								} else {
									console.warn('二维码图片下载失败')
									resolve()
								}
							},
							fail: () => {
								console.warn('二维码图片下载失败')
								resolve()
							}
						})
					} else {
						ctx.drawImage(imagePath, x, y, w, h)
						resolve()
					}
				} else {
					// 图片可能有边框，尝试裁剪掉 5% 的边缘
					// 注意：uni-app canvas 可能不支持 9 参数 drawImage
					// 这里先尝试直接绘制，如果仍有边框问题，可能需要后端处理
					if (imagePath.startsWith('http')) {
						uni.downloadFile({
							url: imagePath,
							success: (res) => {
								if (res.statusCode === 200) {
									// 直接绘制，让 canvas 自动处理
									ctx.drawImage(res.tempFilePath, x, y, w, h)
									resolve()
								} else {
									console.warn('二维码图片下载失败')
									resolve()
								}
							},
							fail: () => {
								console.warn('二维码图片下载失败')
								resolve()
							}
						})
					} else {
						ctx.drawImage(imagePath, x, y, w, h)
						resolve()
					}
				}
			}).catch(() => {
				// 如果获取图片信息失败，直接绘制
				if (imagePath.startsWith('http')) {
					uni.downloadFile({
						url: imagePath,
						success: (res) => {
							if (res.statusCode === 200) {
								ctx.drawImage(res.tempFilePath, x, y, w, h)
								resolve()
							} else {
								console.warn('二维码图片下载失败')
								resolve()
							}
						},
						fail: () => {
							console.warn('二维码图片下载失败')
							resolve()
						}
					})
				} else {
					ctx.drawImage(imagePath, x, y, w, h)
					resolve()
				}
			})
		}).catch((err) => {
			console.error('二维码图片处理失败:', err)
			resolve() // 即使失败也继续
		})
	})
}

// 绘制图片到 canvas（异步加载图片）
const drawImage = (ctx, src, x, y, w, h, fitMode = false) => {
	return new Promise((resolve) => {
		// 如果是自适应模式，需要先获取图片尺寸
		if (fitMode) {
			// 先获取图片路径（Base64 需要转换）
			if (src.startsWith('data:image')) {
				// Base64 图片：先转换为临时文件，再获取信息
				base64ToTempFilePath(src).then((filePath) => {
					// 获取图片信息
					return getImageInfo(filePath).then((info) => {
						const { drawWidth, drawHeight, drawX, drawY } = calculateFitSize(info.width, info.height, w, h)
						ctx.drawImage(filePath, x + drawX, y + drawY, drawWidth, drawHeight)
						resolve()
					}).catch(() => {
						// 如果获取图片信息失败，使用原始尺寸
						ctx.drawImage(filePath, x, y, w, h)
						resolve()
					})
				}).catch((err) => {
					console.error('Base64 图片处理失败:', err)
					// 如果转换失败，尝试直接使用（某些平台可能支持）
					try {
						ctx.drawImage(src, x, y, w, h)
						resolve()
					} catch (e) {
						console.warn('无法绘制 Base64 图片，跳过')
						resolve() // 即使失败也继续
					}
				})
				return
			} else {
				// 普通图片 URL
				getImageInfo(src).then((info) => {
					const { drawWidth, drawHeight, drawX, drawY } = calculateFitSize(info.width, info.height, w, h)
					// 先下载图片
					uni.downloadFile({
						url: src,
						success: (res) => {
							if (res.statusCode === 200) {
								ctx.drawImage(res.tempFilePath, x + drawX, y + drawY, drawWidth, drawHeight)
								resolve()
							} else {
								console.warn('图片下载失败:', src, 'statusCode:', res.statusCode)
								resolve() // 即使失败也继续
							}
						},
						fail: (err) => {
							console.warn('图片下载失败:', src, err)
							resolve() // 即使失败也继续
						}
					})
				}).catch(() => {
					// 如果获取图片信息失败，使用原始逻辑
					uni.downloadFile({
						url: src,
						success: (res) => {
							if (res.statusCode === 200) {
								ctx.drawImage(res.tempFilePath, x, y, w, h)
								resolve()
							} else {
								console.warn('图片下载失败:', src, 'statusCode:', res.statusCode)
								resolve() // 即使失败也继续
							}
						},
						fail: (err) => {
							console.warn('图片下载失败:', src, err)
							resolve() // 即使失败也继续
						}
					})
				})
				return
			}
		}
		
		// 非自适应模式，使用原始逻辑
		// 如果是 Base64 Data URI，先转换为临时文件
		if (src.startsWith('data:image')) {
			base64ToTempFilePath(src).then((filePath) => {
				ctx.drawImage(filePath, x, y, w, h)
				resolve()
			}).catch((err) => {
				console.error('Base64 图片处理失败:', err)
				// 尝试直接使用 Base64（某些平台可能支持）
				try {
					ctx.drawImage(src, x, y, w, h)
					resolve()
				} catch (e) {
					console.warn('无法绘制 Base64 图片，跳过')
					resolve() // 即使失败也继续
				}
			})
		} else {
			// 普通图片 URL，下载后绘制
			uni.downloadFile({
				url: src,
				success: (res) => {
					if (res.statusCode === 200) {
						ctx.drawImage(res.tempFilePath, x, y, w, h)
						resolve()
					} else {
						console.warn('图片下载失败:', src, 'statusCode:', res.statusCode)
						resolve() // 即使失败也继续
					}
				},
				fail: (err) => {
					console.warn('图片下载失败:', src, err)
					resolve() // 即使失败也继续
				}
			})
		}
	})
}
</script>

<style lang="less" scoped>
.poster-page-overlay {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	background-color: rgba(0, 0, 0, 0.8);
	display: flex;
	align-items: center;
	justify-content: center;
	z-index: 10000;
}

.poster-page-container {
	position: relative;
	width: 100%;
	height: 100%;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 40rpx;
}

.poster-wrapper {
	position: relative;
	width: 542rpx;
	height: 956rpx;
	display: flex;
	flex-direction: column;
	align-items: center;
}

.poster-bg {
	width: 542rpx;
	height: 956rpx;
	z-index: 0;
}

.poster-nickname-wrapper {
	position: absolute;
	top: 40rpx;
	left: 24rpx;
	display: flex;
	align-items: center;
	z-index: 1;
}

.poster-nickname-bg {
	position: relative;
	width: 256rpx;
	height: 58rpx;
	z-index: 0;
}

.poster-avatar {
	width: 48rpx;
	height: 48rpx;
	border-radius: 50%;
	flex-shrink: 0;
	z-index: 1;
	position: absolute;
	top: 6rpx;
	left: 8rpx;
}



.poster-nickname-text {
	position: absolute;
	left: 0;
	top: 0;
	width: 186rpx;
	height: 58rpx;
	padding: 5rpx 0 0 70rpx;
	font-size: 28rpx;
	color: #000000;
	text-align: center;
	z-index: 1;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.poster-image-wrapper {
	position: absolute;
	top: 120rpx;
	left: 50%;
	transform: translateX(-50%);
	width: 494rpx;
	height: 802rpx;
	display: flex;
	justify-content: center;
	z-index: 1;
}

.poster-image-bg {
	position: absolute;
	top: 0;
	left: 0;
	width: 494rpx;
	height: 802rpx;
	z-index: 0;
}

.poster-image {
	position: relative;
	height: 586rpx;
	z-index: 1;
	object-fit: contain;
	box-sizing: border-box;
}

.poster-content {
	position: absolute;
	bottom: 146rpx;
	left: 22rpx;
	width: 450rpx;
	height: 40rpx;
	z-index: 2;
}

.poster-content-text {
	font-size: 28rpx;
	font-weight: 500;
	color: #000000;
	width: 450rpx;
	height: 40rpx;
	line-height: 40rpx;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	position: absolute;
}

.poster-collection-number {
	position: absolute;
	bottom: 116rpx;
	left: 22rpx;
	width: calc(100% - 44rpx);
	text-align: left;
	z-index: 2;
}

.collection-number-text {
	font-size: 20rpx;
	color: #D3A458;
}

.poster-download-btn {
	position: absolute;
	bottom: 36rpx;
	left: 22rpx;
	width: 118rpx;
	height: 46rpx;
	display: flex;
	z-index: 2;
}

.download-icon {
	width: 100%;
	height: 100%;
}


.poster-qrcode-wrapper {
	position: absolute;
	bottom: 26rpx;
	right: 22rpx;
	width: 114rpx;
	height: 114rpx;
	z-index: 2;
}

.poster-qrcode-image {
	width: 114rpx;
	height: 114rpx;
}

.poster-close-btn {
	position: absolute;
	left: 50%;
	top: 1400rpx;
	transform: translateX(-50%);
	width: 56rpx;
	height: 56rpx;
	display: flex;
	align-items: center;
	justify-content: center;
	z-index: 2;
}

.close-icon {
	width: 56rpx;
	height: 56rpx;
}

.poster-canvas {
	position: fixed;
	left: -9999px;
	top: -9999px;
	width: 542rpx;
	height: 956rpx;
	z-index: -1;
	opacity: 0;
}
</style>
