web-base-h5/components/share/DefaultSharePage.vue

312 lines
6.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="default-share-page">
<!-- 背景图片替代CSS background -->
<img
class="share-bg-image"
src="/static/images/share-bg.jpg"
crossorigin="anonymous"
@load="onBackgroundImageLoad"
@error="onBackgroundImageError"
/>
<view class="qr-code-outer">
<image
class="qr-code"
:src="qrCodeImage"
mode="aspectFit"
v-if="qrCodeImage"
></image>
<view v-else class="qr-code-placeholder">
<view class="loader"></view>
</view>
</view>
<view class="member-code-outer">
<text
class="member-code-text"
style="
font-size: 30rpx;
color: #fff;
font-weight: bold;
margin-top: 20rpx;
"
>{{ desensitization(userInfo.memberCode) }}</text
>
</view>
</view>
</template>
<script>
import html2canvas from 'html2canvas'
import { snapdom } from '@zumer/snapdom'
export default {
name: 'DefaultSharePage',
props: {
qrCodeImage: {
type: String,
default: '',
},
userInfo: {
type: Object,
default: () => ({}),
},
isWechat: {
type: Boolean,
default: false,
},
isLoaded: {
type: Boolean,
default: false,
},
},
data() {
return {
backgroundImageLoaded: false,
shareButtonShow: true,
}
},
methods: {
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)
},
// 背景图片加载成功
onBackgroundImageLoad() {
this.backgroundImageLoaded = true
console.log('默认场景背景图片加载成功')
},
// 背景图片加载失败
onBackgroundImageError(e) {
console.error('默认场景背景图片加载失败:', e)
},
async sharePage() {
if (!this.qrCodeImage) {
uni.showToast({
title: '二维码尚未生成',
icon: 'none',
})
return
}
uni.showLoading({ title: '加载中...' })
try {
this.shareButtonShow = false
await this.$nextTick()
await this.capturePageWithHtml2Canvas()
} catch (error) {
uni.hideLoading()
uni.showToast({ title: '图片生成失败,请稍后重试', icon: 'none' })
console.error('sharePage error:', error)
} finally {
// 恢复按钮显示
this.shareButtonShow = true
}
},
// 使用html2canvas截取整个页面
async capturePageWithHtml2Canvas() {
console.log('开始使用html2canvas截取页面')
return new Promise((resolve, reject) => {
// 确保所有图片都已加载完成
const waitForImages = () => {
if (!this.backgroundImageLoaded || !this.qrCodeImage) {
setTimeout(waitForImages, 100)
return
}
// 额外等待确保渲染完成
setTimeout(() => {
const element = this.$el
if (!element) {
reject(new Error('找不到组件容器'))
return
}
const scale = 3
html2canvas(element, {
useCORS: true,
// allowTaint: true,
backgroundColor: null,
scale,
// canvas,
width: element.offsetWidth,
height: element.offsetHeight,
})
.then(canvas => {
const context = canvas.getContext('2d')
// context.scale(2, 2)
context.mozImageSmoothingEnabled = false
context.webkitImageSmoothingEnabled = false
context.msImageSmoothingEnabled = false
context.imageSmoothingEnabled = false
const dataUrl = canvas.toDataURL('image/jpeg', 1)
this.$emit('share-generated', dataUrl)
resolve()
})
.catch(err => {
console.error('html2canvas截取失败:', err)
reject(err)
})
}, 1000)
}
// 开始等待图片加载
waitForImages()
})
},
},
}
</script>
<style lang="scss" scoped>
.default-share-page {
position: relative;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
}
/* 背景图片样式 */
.share-bg-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
}
.share-wrapper {
position: absolute;
z-index: 2;
bottom: 22%;
display: flex;
flex-direction: column;
align-items: center;
}
.portal-frame {
padding: 32rpx;
width: 520rpx;
border-radius: 40rpx;
display: flex;
box-sizing: border-box;
flex-direction: column;
align-items: center;
margin: 0 auto;
opacity: 0;
transform: translateY(20rpx);
transition: all 0.3s ease;
}
.portal-frame.is-loaded {
opacity: 1;
transform: translateY(0);
}
/* 二维码样式区域 - 用户自定义样式位置 */
.qr-code-outer {
width: 140rpx;
height: 140rpx;
background: rgba(255, 255, 255, 0.98);
border-radius: 20rpx;
box-shadow: 0px 8rpx 20rpx rgba(50, 50, 90, 0.06);
border: 1px solid #f0f0f0;
display: flex;
align-items: center;
justify-content: center;
padding: 12rpx;
box-sizing: border-box;
position: absolute;
bottom: 460rpx;
right: 130rpx;
z-index: 10;
}
.qr-code,
.qr-code-placeholder {
width: 100%;
height: 100%;
}
.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);
}
}
/* 会员编号样式区域 - 用户自定义样式位置 */
.member-code-text {
/* 用户可以在这里自定义会员编号的样式 */
}
.member-code-outer {
position: absolute;
bottom: 160rpx;
width: 300rpx;
text-align: center;
background: rgb(217, 24, 25);
border-radius: 20rpx;
z-index: 10;
}
/* 下载按钮样式 */
.share-button {
margin-top: 28rpx;
width: 280rpx;
height: 72rpx;
line-height: 72rpx;
color: #fff;
border-radius: 36rpx;
font-size: 26rpx;
font-weight: 500;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
box-shadow: 0 5rpx 12rpx 0 rgba(102, 126, 234, 0.2);
border: none;
padding: 0;
text-align: center;
transition: all 0.3s ease;
letter-spacing: 1rpx;
}
button.share-button {
padding: 0;
line-height: 72rpx;
border: none;
}
.share-button:active {
transform: translateY(1rpx);
box-shadow: 0 4rpx 10rpx rgba(102, 126, 234, 0.4);
background: linear-gradient(135deg, #5a67d8 0%, #6b46c1 100%);
}
</style>