| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  | <template> | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |   <view | 
					
						
							|  |  |  |  |     class="share-page" | 
					
						
							|  |  |  |  |     style="display: flex; flex-direction: column; height: 100vh" | 
					
						
							|  |  |  |  |   > | 
					
						
							|  |  |  |  |     <view id="shareContainer" class="share-container"> | 
					
						
							|  |  |  |  |       <!-- 微信环境:只有在未生成分享图时才显示原始内容 --> | 
					
						
							|  |  |  |  |       <template v-if="!isWechat || (isWechat && !generatedImageUrl)"> | 
					
						
							|  |  |  |  |         <!-- 背景图片,替代CSS background --> | 
					
						
							| 
									
										
										
										
											2025-08-01 18:10:01 +08:00
										 |  |  |  |         <img | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |           class="share-bg-image" | 
					
						
							|  |  |  |  |           src="/static/images/share-bg.jpg" | 
					
						
							|  |  |  |  |           mode="scaleToFill" | 
					
						
							|  |  |  |  |           crossorigin="anonymous" | 
					
						
							|  |  |  |  |           @load="onBackgroundImageLoad" | 
					
						
							|  |  |  |  |           @error="onBackgroundImageError" | 
					
						
							| 
									
										
										
										
											2025-08-01 18:10:01 +08:00
										 |  |  |  |         /> | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |         <view class="share-wrapper"> | 
					
						
							|  |  |  |  |           <view class="portal-frame" :class="{ 'is-loaded': isLoaded }"> | 
					
						
							|  |  |  |  |             <view class="qr-code-outer"> | 
					
						
							| 
									
										
										
										
											2025-08-01 18:10:01 +08:00
										 |  |  |  |               <img | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |                 class="qr-code" | 
					
						
							|  |  |  |  |                 :src="qrCodeImage" | 
					
						
							|  |  |  |  |                 mode="aspectFit" | 
					
						
							|  |  |  |  |                 v-if="qrCodeImage" | 
					
						
							| 
									
										
										
										
											2025-08-01 18:10:01 +08:00
										 |  |  |  |               /> | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |               <view v-else class="qr-code-placeholder"> | 
					
						
							|  |  |  |  |                 <view class="loader"></view> | 
					
						
							|  |  |  |  |               </view> | 
					
						
							|  |  |  |  |             </view> | 
					
						
							| 
									
										
										
										
											2025-08-01 18:10:01 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |             <div | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |               style=" | 
					
						
							| 
									
										
										
										
											2025-08-19 13:55:40 +08:00
										 |  |  |  |                 font-size: 18rpx; | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |                 color: #fff; | 
					
						
							|  |  |  |  |                 font-weight: bold; | 
					
						
							| 
									
										
										
										
											2025-08-01 18:10:01 +08:00
										 |  |  |  |                 margin-top: 10rpx; | 
					
						
							|  |  |  |  |                 text-align: center; | 
					
						
							|  |  |  |  |                 display: flex; | 
					
						
							|  |  |  |  |                 align-items: center; | 
					
						
							|  |  |  |  |                 justify-content: center; | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |               " | 
					
						
							|  |  |  |  |             > | 
					
						
							| 
									
										
										
										
											2025-08-01 18:10:01 +08:00
										 |  |  |  |               {{ desensitization(userInfo.memberCode) }} | 
					
						
							|  |  |  |  |             </div> | 
					
						
							|  |  |  |  |             <div v-if="!isWechat" class="share-button" @click="sharePage"> | 
					
						
							|  |  |  |  |               保存图片并分享 | 
					
						
							|  |  |  |  |             </div> | 
					
						
							|  |  |  |  |             <img | 
					
						
							|  |  |  |  |               v-if="isWechat" | 
					
						
							|  |  |  |  |               class="share-btn" | 
					
						
							| 
									
										
										
										
											2025-08-19 13:55:40 +08:00
										 |  |  |  |               style="margin-top: 30rpx" | 
					
						
							| 
									
										
										
										
											2025-08-01 18:10:01 +08:00
										 |  |  |  |               src="/static/images/share-btn.svg" | 
					
						
							|  |  |  |  |               mode="scaleToFill" | 
					
						
							|  |  |  |  |             /> | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |           </view> | 
					
						
							|  |  |  |  |           <!-- <image | 
					
						
							|  |  |  |  |             class="share-bg-logo" | 
					
						
							|  |  |  |  |             src="/static/images/share-logo.png" | 
					
						
							|  |  |  |  |             mode="scaleToFill" | 
					
						
							|  |  |  |  |           ></image> --> | 
					
						
							| 
									
										
										
										
											2025-06-13 17:16:37 +08:00
										 |  |  |  |         </view> | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |       </template> | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |       <view | 
					
						
							|  |  |  |  |         class="wechat-fullscreen-overlay" | 
					
						
							|  |  |  |  |         v-show="isWechat && generatedImageUrl" | 
					
						
							|  |  |  |  |         @click="closeFullscreenImage" | 
					
						
							|  |  |  |  |       > | 
					
						
							|  |  |  |  |         <image | 
					
						
							|  |  |  |  |           class="fullscreen-image" | 
					
						
							|  |  |  |  |           :src="generatedImageUrl" | 
					
						
							|  |  |  |  |           mode="scaleToFill" | 
					
						
							|  |  |  |  |           @load="onGeneratedImageLoad" | 
					
						
							|  |  |  |  |           @error="onGeneratedImageError" | 
					
						
							|  |  |  |  |           @click.stop="" | 
					
						
							|  |  |  |  |         ></image> | 
					
						
							|  |  |  |  |       </view> | 
					
						
							| 
									
										
										
										
											2025-06-13 17:16:37 +08:00
										 |  |  |  |     </view> | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |     <cl-tabbar class="tabbar" :current="2" /> | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  |   </view> | 
					
						
							|  |  |  |  | </template> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | <script> | 
					
						
							| 
									
										
										
										
											2025-06-13 17:16:37 +08:00
										 |  |  |  | import html2canvas from 'html2canvas' | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  | import { getShareCode } from '@/config/share' | 
					
						
							| 
									
										
										
										
											2025-06-19 09:39:59 +08:00
										 |  |  |  | import clTabbar from '@/components/cl-tabbar.vue' | 
					
						
							| 
									
										
										
										
											2025-06-19 16:28:16 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  | export default { | 
					
						
							|  |  |  |  |   name: 'ShareQRCode', | 
					
						
							| 
									
										
										
										
											2025-06-19 09:39:59 +08:00
										 |  |  |  |   components: { | 
					
						
							|  |  |  |  |     'cl-tabbar': clTabbar, | 
					
						
							|  |  |  |  |   }, | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  |   data() { | 
					
						
							|  |  |  |  |     return { | 
					
						
							|  |  |  |  |       qrCodeImage: '', | 
					
						
							|  |  |  |  |       // Set canvas dimensions. It's better to get device screen width for this.
 | 
					
						
							|  |  |  |  |       canvasWidth: 375, | 
					
						
							| 
									
										
										
										
											2025-06-13 17:16:37 +08:00
										 |  |  |  |       canvasHeight: 800, | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  |       isLoaded: false, | 
					
						
							| 
									
										
										
										
											2025-06-13 17:16:37 +08:00
										 |  |  |  |       shareButtonShow: true, | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |       isWechat: false, // 是否微信环境
 | 
					
						
							|  |  |  |  |       generatedImageUrl: '', // 生成的图片URL,用于微信长按保存
 | 
					
						
							|  |  |  |  |       backgroundImageLoaded: false, // 背景图片是否加载完成
 | 
					
						
							|  |  |  |  |       userInfo: uni.getStorageSync('User'), | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  |     } | 
					
						
							|  |  |  |  |   }, | 
					
						
							|  |  |  |  |   onLoad() { | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |     this.checkWechatEnvironment() | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  |     this.handleGetShareCode() | 
					
						
							|  |  |  |  |     // Get screen width to set canvas width dynamically
 | 
					
						
							|  |  |  |  |     uni.getSystemInfo({ | 
					
						
							|  |  |  |  |       success: res => { | 
					
						
							|  |  |  |  |         this.canvasWidth = res.windowWidth | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |         this.canvasHeight = res.windowHeight | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  |       }, | 
					
						
							|  |  |  |  |     }) | 
					
						
							|  |  |  |  |   }, | 
					
						
							|  |  |  |  |   onReady() { | 
					
						
							|  |  |  |  |     // Use a short timeout to ensure the initial render is complete before animation
 | 
					
						
							|  |  |  |  |     setTimeout(() => { | 
					
						
							|  |  |  |  |       this.isLoaded = true | 
					
						
							|  |  |  |  |     }, 100) | 
					
						
							|  |  |  |  |   }, | 
					
						
							|  |  |  |  |   methods: { | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |     desensitization(str) { | 
					
						
							|  |  |  |  |       if (!str) return '' | 
					
						
							|  |  |  |  |       if (str.length <= 8) return str.slice(0, 4) + '****' | 
					
						
							|  |  |  |  |       const len = str.length - 6 | 
					
						
							|  |  |  |  |       const placeholder = '*'.repeat(len) | 
					
						
							|  |  |  |  |       return str.slice(0, 4) + placeholder + str.slice(-2) | 
					
						
							|  |  |  |  |     }, | 
					
						
							|  |  |  |  |     // 检测微信环境
 | 
					
						
							|  |  |  |  |     checkWechatEnvironment() { | 
					
						
							|  |  |  |  |       const ua = navigator.userAgent.toLowerCase() | 
					
						
							|  |  |  |  |       this.isWechat = ua.includes('micromessenger') | 
					
						
							|  |  |  |  |       console.log('微信环境检测:', this.isWechat) | 
					
						
							|  |  |  |  |     }, | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  |     handleGetShareCode() { | 
					
						
							|  |  |  |  |       // Don't show loading toast, use the placeholder loader instead
 | 
					
						
							|  |  |  |  |       // uni.showLoading({ title: '加载中...' })
 | 
					
						
							|  |  |  |  |       getShareCode() | 
					
						
							|  |  |  |  |         .then(res => { | 
					
						
							|  |  |  |  |           // The screenshot shows the base64 string is in data.datStr
 | 
					
						
							|  |  |  |  |           if (res.code === 200 && res.data && res.data.dataStr) { | 
					
						
							|  |  |  |  |             this.qrCodeImage = 'data:image/png;base64,' + res.data.dataStr | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |             this.$nextTick(() => { | 
					
						
							|  |  |  |  |               if (this.isWechat) { | 
					
						
							|  |  |  |  |                 this.sharePage() | 
					
						
							|  |  |  |  |               } | 
					
						
							|  |  |  |  |             }) | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  |           } else { | 
					
						
							|  |  |  |  |             uni.showToast({ | 
					
						
							|  |  |  |  |               title: '获取分享码失败', | 
					
						
							|  |  |  |  |               icon: 'none', | 
					
						
							|  |  |  |  |             }) | 
					
						
							|  |  |  |  |           } | 
					
						
							|  |  |  |  |         }) | 
					
						
							|  |  |  |  |         .catch(err => { | 
					
						
							|  |  |  |  |           console.error('getShareCode error:', err) | 
					
						
							|  |  |  |  |           uni.showToast({ | 
					
						
							|  |  |  |  |             title: '网络错误,请稍后再试', | 
					
						
							|  |  |  |  |             icon: 'none', | 
					
						
							|  |  |  |  |           }) | 
					
						
							|  |  |  |  |         }) | 
					
						
							|  |  |  |  |     }, | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     async sharePage() { | 
					
						
							|  |  |  |  |       if (!this.qrCodeImage) { | 
					
						
							|  |  |  |  |         uni.showToast({ | 
					
						
							|  |  |  |  |           title: '二维码尚未生成', | 
					
						
							|  |  |  |  |           icon: 'none', | 
					
						
							|  |  |  |  |         }) | 
					
						
							|  |  |  |  |         return | 
					
						
							|  |  |  |  |       } | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |       // 统一使用html2canvas生成图片
 | 
					
						
							|  |  |  |  |       uni.showLoading({ title: '加载中...' }) | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |       try { | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |         // 隐藏按钮,等待DOM更新
 | 
					
						
							| 
									
										
										
										
											2025-06-13 17:16:37 +08:00
										 |  |  |  |         this.shareButtonShow = false | 
					
						
							|  |  |  |  |         await this.$nextTick() | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |         // 使用html2canvas截取页面
 | 
					
						
							|  |  |  |  |         await this.capturePageWithHtml2Canvas() | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  |       } catch (error) { | 
					
						
							|  |  |  |  |         uni.hideLoading() | 
					
						
							| 
									
										
										
										
											2025-06-13 17:16:37 +08:00
										 |  |  |  |         uni.showToast({ title: '图片生成失败,请稍后重试', icon: 'none' }) | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  |         console.error('sharePage error:', error) | 
					
						
							| 
									
										
										
										
											2025-06-13 17:16:37 +08:00
										 |  |  |  |       } finally { | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |         // 恢复按钮显示
 | 
					
						
							| 
									
										
										
										
											2025-06-13 17:16:37 +08:00
										 |  |  |  |         this.shareButtonShow = true | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  |       } | 
					
						
							|  |  |  |  |     }, | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |     // 生成的图片加载成功
 | 
					
						
							|  |  |  |  |     onGeneratedImageLoad() { | 
					
						
							|  |  |  |  |       console.log('生成的图片加载成功') | 
					
						
							|  |  |  |  |     }, | 
					
						
							| 
									
										
										
										
											2025-06-13 17:16:37 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |     // 生成的图片加载失败
 | 
					
						
							|  |  |  |  |     onGeneratedImageError(e) { | 
					
						
							|  |  |  |  |       console.error('生成的图片加载失败:', e) | 
					
						
							|  |  |  |  |       uni.showToast({ | 
					
						
							|  |  |  |  |         title: '图片显示失败', | 
					
						
							|  |  |  |  |         icon: 'none', | 
					
						
							| 
									
										
										
										
											2025-06-13 17:16:37 +08:00
										 |  |  |  |       }) | 
					
						
							|  |  |  |  |     }, | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |     // 关闭全屏图片
 | 
					
						
							|  |  |  |  |     closeFullscreenImage() { | 
					
						
							|  |  |  |  |       this.generatedImageUrl = '' | 
					
						
							|  |  |  |  |       console.log('关闭全屏图片') | 
					
						
							| 
									
										
										
										
											2025-06-13 17:16:37 +08:00
										 |  |  |  |     }, | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |     // 背景图片加载成功
 | 
					
						
							|  |  |  |  |     onBackgroundImageLoad() { | 
					
						
							|  |  |  |  |       this.backgroundImageLoaded = true | 
					
						
							|  |  |  |  |       console.log('背景图片加载成功') | 
					
						
							| 
									
										
										
										
											2025-06-13 17:16:37 +08:00
										 |  |  |  |     }, | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |     // 背景图片加载失败
 | 
					
						
							|  |  |  |  |     onBackgroundImageError(e) { | 
					
						
							|  |  |  |  |       console.error('背景图片加载失败:', e) | 
					
						
							| 
									
										
										
										
											2025-06-13 17:16:37 +08:00
										 |  |  |  |     }, | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |     // 使用html2canvas截取整个页面
 | 
					
						
							|  |  |  |  |     async capturePageWithHtml2Canvas() { | 
					
						
							|  |  |  |  |       console.log('开始使用html2canvas截取页面') | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |       return new Promise((resolve, reject) => { | 
					
						
							|  |  |  |  |         // 确保所有图片都已加载完成
 | 
					
						
							|  |  |  |  |         const waitForImages = () => { | 
					
						
							|  |  |  |  |           if (!this.backgroundImageLoaded || !this.qrCodeImage) { | 
					
						
							|  |  |  |  |             setTimeout(waitForImages, 100) | 
					
						
							|  |  |  |  |             return | 
					
						
							|  |  |  |  |           } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |           // 额外等待确保渲染完成
 | 
					
						
							|  |  |  |  |           setTimeout(() => { | 
					
						
							|  |  |  |  |             const element = document.getElementById('shareContainer') | 
					
						
							|  |  |  |  |             if (!element) { | 
					
						
							|  |  |  |  |               reject(new Error('找不到页面容器')) | 
					
						
							|  |  |  |  |               return | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             console.log( | 
					
						
							|  |  |  |  |               '开始html2canvas截取,容器尺寸:', | 
					
						
							|  |  |  |  |               element.offsetWidth, | 
					
						
							|  |  |  |  |               'x', | 
					
						
							|  |  |  |  |               element.offsetHeight | 
					
						
							|  |  |  |  |             ) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             html2canvas(element, { | 
					
						
							|  |  |  |  |               useCORS: true, | 
					
						
							|  |  |  |  |               allowTaint: true, | 
					
						
							|  |  |  |  |               backgroundColor: null, | 
					
						
							| 
									
										
										
										
											2025-06-19 16:28:16 +08:00
										 |  |  |  |               scale: 2, | 
					
						
							|  |  |  |  |               dpi: 400, | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |               logging: true, // 开启日志便于调试
 | 
					
						
							|  |  |  |  |               width: element.offsetWidth, | 
					
						
							|  |  |  |  |               height: element.offsetHeight, | 
					
						
							|  |  |  |  |               windowWidth: element.offsetWidth, | 
					
						
							|  |  |  |  |               windowHeight: element.offsetHeight, | 
					
						
							|  |  |  |  |               scrollX: 0, | 
					
						
							|  |  |  |  |               scrollY: 0, | 
					
						
							|  |  |  |  |               x: 0, | 
					
						
							|  |  |  |  |               y: 0, | 
					
						
							|  |  |  |  |             }) | 
					
						
							|  |  |  |  |               .then(canvas => { | 
					
						
							| 
									
										
										
										
											2025-06-19 16:28:16 +08:00
										 |  |  |  |                 const dataUrl = canvas.toDataURL('image/jpeg', 1) | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |                 // 根据环境处理结果
 | 
					
						
							|  |  |  |  |                 if (this.isWechat) { | 
					
						
							|  |  |  |  |                   // 微信环境:设置图片供长按保存
 | 
					
						
							|  |  |  |  |                   this.generatedImageUrl = dataUrl | 
					
						
							|  |  |  |  |                   uni.hideLoading() | 
					
						
							|  |  |  |  |                 } else { | 
					
						
							|  |  |  |  |                   // 普通浏览器:直接下载图片
 | 
					
						
							|  |  |  |  |                   this.downloadImage(dataUrl) | 
					
						
							|  |  |  |  |                   uni.hideLoading() | 
					
						
							|  |  |  |  |                   uni.showToast({ | 
					
						
							|  |  |  |  |                     title: '图片已开始下载', | 
					
						
							|  |  |  |  |                     icon: 'success', | 
					
						
							|  |  |  |  |                   }) | 
					
						
							|  |  |  |  |                 } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                 resolve() | 
					
						
							|  |  |  |  |               }) | 
					
						
							|  |  |  |  |               .catch(err => { | 
					
						
							|  |  |  |  |                 console.error('html2canvas截取失败:', err) | 
					
						
							|  |  |  |  |                 reject(err) | 
					
						
							|  |  |  |  |               }) | 
					
						
							|  |  |  |  |           }, 1000) // 增加等待时间到1000ms
 | 
					
						
							|  |  |  |  |         } | 
					
						
							| 
									
										
										
										
											2025-06-13 17:16:37 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |         // 开始等待图片加载
 | 
					
						
							|  |  |  |  |         waitForImages() | 
					
						
							|  |  |  |  |       }) | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  |     }, | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |     // 原生图片加载器
 | 
					
						
							|  |  |  |  |     loadImage(src) { | 
					
						
							|  |  |  |  |       return new Promise((resolve, reject) => { | 
					
						
							|  |  |  |  |         const img = new Image() | 
					
						
							|  |  |  |  |         img.crossOrigin = 'anonymous' | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         img.onload = () => { | 
					
						
							|  |  |  |  |           console.log( | 
					
						
							|  |  |  |  |             `图片加载成功: ${src.substring(0, 50)}...`, | 
					
						
							|  |  |  |  |             `${img.width}x${img.height}` | 
					
						
							|  |  |  |  |           ) | 
					
						
							|  |  |  |  |           resolve(img) | 
					
						
							| 
									
										
										
										
											2025-06-13 17:16:37 +08:00
										 |  |  |  |         } | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |         img.onerror = error => { | 
					
						
							|  |  |  |  |           console.error(`图片加载失败: ${src}`, error) | 
					
						
							|  |  |  |  |           reject(new Error(`图片加载失败: ${src}`)) | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         img.src = src | 
					
						
							|  |  |  |  |       }) | 
					
						
							| 
									
										
										
										
											2025-06-13 17:16:37 +08:00
										 |  |  |  |     }, | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |     // 下载图片
 | 
					
						
							|  |  |  |  |     downloadImage(dataUrl) { | 
					
						
							| 
									
										
										
										
											2025-06-13 17:16:37 +08:00
										 |  |  |  |       const link = document.createElement('a') | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |       link.href = dataUrl | 
					
						
							| 
									
										
										
										
											2025-06-13 17:16:37 +08:00
										 |  |  |  |       link.download = `share_page_${Date.now()}.png` | 
					
						
							|  |  |  |  |       document.body.appendChild(link) | 
					
						
							|  |  |  |  |       link.click() | 
					
						
							|  |  |  |  |       document.body.removeChild(link) | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  |     }, | 
					
						
							|  |  |  |  |   }, | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | </script> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | <style lang="scss" scoped> | 
					
						
							|  |  |  |  | .share-container { | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |   flex: 1; | 
					
						
							|  |  |  |  |   height: 0; | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  |   box-sizing: border-box; | 
					
						
							|  |  |  |  |   position: relative; | 
					
						
							|  |  |  |  |   overflow: hidden; | 
					
						
							| 
									
										
										
										
											2025-06-13 17:16:37 +08:00
										 |  |  |  |   display: flex; | 
					
						
							|  |  |  |  |   flex-direction: column; | 
					
						
							|  |  |  |  |   align-items: center; | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  | } | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | /* 背景图片样式 */ | 
					
						
							|  |  |  |  | .share-bg-image { | 
					
						
							|  |  |  |  |   position: absolute; | 
					
						
							|  |  |  |  |   top: 0; | 
					
						
							|  |  |  |  |   left: 0; | 
					
						
							|  |  |  |  |   width: 100%; | 
					
						
							|  |  |  |  |   height: 100%; | 
					
						
							|  |  |  |  |   z-index: 1; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-13 14:57:26 +08:00
										 |  |  |  | .share-bg { | 
					
						
							|  |  |  |  |   width: 100%; | 
					
						
							|  |  |  |  |   height: 100%; | 
					
						
							|  |  |  |  |   img { | 
					
						
							|  |  |  |  |     width: 100%; | 
					
						
							|  |  |  |  |     height: 100%; | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  |   } | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  | .share-wrapper { | 
					
						
							|  |  |  |  |   position: absolute; | 
					
						
							|  |  |  |  |   z-index: 2; | 
					
						
							| 
									
										
										
										
											2025-08-19 13:55:40 +08:00
										 |  |  |  |   top: 370rpx; | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |   display: flex; | 
					
						
							|  |  |  |  |   flex-direction: column; | 
					
						
							|  |  |  |  |   align-items: center; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | .share-bg-logo { | 
					
						
							|  |  |  |  |   width: 100%; | 
					
						
							|  |  |  |  |   height: 360rpx; | 
					
						
							|  |  |  |  |   // margin-top: -60rpx;
 | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-13 17:16:37 +08:00
										 |  |  |  | .portal-frame { | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |   padding: 32rpx; | 
					
						
							|  |  |  |  |   width: 520rpx; | 
					
						
							|  |  |  |  |   border-radius: 40rpx; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  |   display: flex; | 
					
						
							| 
									
										
										
										
											2025-06-13 17:16:37 +08:00
										 |  |  |  |   box-sizing: border-box; | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  |   flex-direction: column; | 
					
						
							|  |  |  |  |   align-items: center; | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |   margin: 0 auto; | 
					
						
							| 
									
										
										
										
											2025-08-01 18:10:01 +08:00
										 |  |  |  |   text-align: center; | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-13 17:16:37 +08:00
										 |  |  |  | .portal-frame.is-loaded { | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  |   opacity: 1; | 
					
						
							|  |  |  |  |   transform: translateY(0); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-13 17:16:37 +08:00
										 |  |  |  | /* The single white card for the QR code */ | 
					
						
							|  |  |  |  | .qr-code-outer { | 
					
						
							| 
									
										
										
										
											2025-08-19 13:55:40 +08:00
										 |  |  |  |   width: 300rpx; /* 从400rpx缩小到320rpx */ | 
					
						
							|  |  |  |  |   height: 300rpx; /* 从400rpx缩小到320rpx */ | 
					
						
							| 
									
										
										
										
											2025-06-13 17:16:37 +08:00
										 |  |  |  |   background: rgba(255, 255, 255, 0.98); | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |   border-radius: 20rpx; /* 从24rpx减小到20rpx */ | 
					
						
							|  |  |  |  |   box-shadow: 0px 8rpx 20rpx rgba(50, 50, 90, 0.06); | 
					
						
							| 
									
										
										
										
											2025-06-13 17:16:37 +08:00
										 |  |  |  |   border: 1px solid #f0f0f0; | 
					
						
							|  |  |  |  |   display: flex; | 
					
						
							|  |  |  |  |   align-items: center; | 
					
						
							|  |  |  |  |   justify-content: center; | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |   padding: 12rpx; /* 从16rpx减小到12rpx */ | 
					
						
							| 
									
										
										
										
											2025-06-13 17:16:37 +08:00
										 |  |  |  |   box-sizing: border-box; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* The image and the placeholder both live inside the outer card */ | 
					
						
							|  |  |  |  | .qr-code, | 
					
						
							|  |  |  |  | .qr-code-placeholder { | 
					
						
							|  |  |  |  |   width: 100%; | 
					
						
							|  |  |  |  |   height: 100%; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  | .qr-code { | 
					
						
							|  |  |  |  |   border-radius: 16rpx; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | .qr-code-placeholder { | 
					
						
							|  |  |  |  |   display: flex; | 
					
						
							|  |  |  |  |   align-items: center; | 
					
						
							|  |  |  |  |   justify-content: center; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | .loader { | 
					
						
							|  |  |  |  |   width: 100rpx; | 
					
						
							|  |  |  |  |   height: 100rpx; | 
					
						
							|  |  |  |  |   border: 8rpx solid rgba(0, 0, 0, 0.1); | 
					
						
							|  |  |  |  |   border-left-color: #0072ff; | 
					
						
							|  |  |  |  |   border-radius: 50%; | 
					
						
							|  |  |  |  |   animation: spin 1s linear infinite; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | @keyframes spin { | 
					
						
							|  |  |  |  |   to { | 
					
						
							|  |  |  |  |     transform: rotate(360deg); | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | .tip { | 
					
						
							|  |  |  |  |   font-size: 30rpx; | 
					
						
							|  |  |  |  |   color: #888; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | .share-button { | 
					
						
							| 
									
										
										
										
											2025-08-01 18:10:01 +08:00
										 |  |  |  |   margin-top: 58rpx; /* 从32rpx减小到28rpx */ | 
					
						
							|  |  |  |  |   width: 380rpx; /* 设置固定宽度 */ | 
					
						
							| 
									
										
										
										
											2025-06-13 17:16:37 +08:00
										 |  |  |  |   color: #fff; | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |   border-radius: 36rpx; /* 从44rpx减小到36rpx */ | 
					
						
							| 
									
										
										
										
											2025-08-01 18:10:01 +08:00
										 |  |  |  |   font-size: 16rpx; /* 从30rpx减小到26rpx */ | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |   font-weight: 500; | 
					
						
							| 
									
										
										
										
											2025-08-01 18:10:01 +08:00
										 |  |  |  |   padding: 12rpx 0; | 
					
						
							|  |  |  |  |   display: flex; | 
					
						
							|  |  |  |  |   align-items: flex-start; | 
					
						
							|  |  |  |  |   justify-content: center; | 
					
						
							| 
									
										
										
										
											2025-08-19 13:56:53 +08:00
										 |  |  |  |   background: linear-gradient( | 
					
						
							|  |  |  |  |     135deg, | 
					
						
							|  |  |  |  |     #d4af37 0%, | 
					
						
							|  |  |  |  |     #ffd700 30%, | 
					
						
							|  |  |  |  |     #b8860b 70%, | 
					
						
							|  |  |  |  |     #8b7355 100% | 
					
						
							|  |  |  |  |   ); | 
					
						
							| 
									
										
										
										
											2025-08-01 18:10:01 +08:00
										 |  |  |  |   // box-shadow: 0 5rpx 12rpx 0 rgba(102, 126, 234, 0.2);
 | 
					
						
							| 
									
										
										
										
											2025-06-13 17:16:37 +08:00
										 |  |  |  |   border: none; | 
					
						
							| 
									
										
										
										
											2025-08-01 18:10:01 +08:00
										 |  |  |  |   border-radius: 70rpx; | 
					
						
							| 
									
										
										
										
											2025-06-13 17:16:37 +08:00
										 |  |  |  |   text-align: center; | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  |   letter-spacing: 1rpx; | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-19 16:09:33 +08:00
										 |  |  |  | /* 微信环境全屏覆盖样式 */ | 
					
						
							|  |  |  |  | .wechat-fullscreen-overlay { | 
					
						
							|  |  |  |  |   position: absolute; | 
					
						
							|  |  |  |  |   top: 0; | 
					
						
							|  |  |  |  |   left: 0; | 
					
						
							|  |  |  |  |   width: 100vw; | 
					
						
							|  |  |  |  |   height: 100%; /* 减去tab栏高度 */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   background-color: transparent; /* 移除背景色 */ | 
					
						
							|  |  |  |  |   z-index: 999; | 
					
						
							|  |  |  |  |   display: flex; | 
					
						
							|  |  |  |  |   flex-direction: column; | 
					
						
							|  |  |  |  |   align-items: stretch; /* 拉伸对齐 */ | 
					
						
							|  |  |  |  |   justify-content: stretch; /* 拉伸对齐 */ | 
					
						
							|  |  |  |  |   padding: 0; | 
					
						
							|  |  |  |  |   margin: 0; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | .fullscreen-image { | 
					
						
							|  |  |  |  |   width: 100vw; | 
					
						
							|  |  |  |  |   height: 100%; /* 减去tab栏高度 */ | 
					
						
							|  |  |  |  |   object-fit: cover; /* 覆盖整个容器,可能会裁剪 */ | 
					
						
							|  |  |  |  |   margin: 0; | 
					
						
							|  |  |  |  |   padding: 0; | 
					
						
							|  |  |  |  |   border: none; | 
					
						
							|  |  |  |  |   display: block; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | @media screen and (max-height: 667px) { | 
					
						
							|  |  |  |  |   .tabbar { | 
					
						
							|  |  |  |  |     height: 70px !important; | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | @media screen and (min-height: 812px) { | 
					
						
							|  |  |  |  |   /* iPhone X及以上机型 */ | 
					
						
							|  |  |  |  |   .tabbar { | 
					
						
							|  |  |  |  |     height: 80px !important; | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | .tabbar { | 
					
						
							|  |  |  |  |   position: static; | 
					
						
							|  |  |  |  |   bottom: 0; | 
					
						
							|  |  |  |  |   z-index: 1000; | 
					
						
							|  |  |  |  |   width: 100%; | 
					
						
							|  |  |  |  |   height: 50px; | 
					
						
							|  |  |  |  |   :v-deep .u-tabbar--fixed { | 
					
						
							|  |  |  |  |     height: 100px !important; | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  |   // ::v-deep .u-safe-area-inset-bottom {
 | 
					
						
							|  |  |  |  |   //   display: none !important;
 | 
					
						
							|  |  |  |  |   // }
 | 
					
						
							| 
									
										
										
										
											2025-06-10 14:06:32 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | </style> |