3
0
Fork 0
web-store-retail-h5/components/DefaultSharePage.vue

308 lines
6.9 KiB
Vue
Raw Normal View History

<template>
<view class="default-share-page">
<!-- 背景图片替代CSS background -->
<img
class="share-bg-image"
src="/static/images/share-bg.jpg"
mode="scaleToFill"
crossorigin="anonymous"
@load="onBackgroundImageLoad"
@error="onBackgroundImageError"
/>
<view class="share-wrapper">
<view class="portal-frame" :class="{ 'is-loaded': isLoaded }">
<!-- 二维码样式区域 - 用户自定义样式位置 -->
<view class="qr-code-outer">
<img
class="qr-code"
:src="qrCodeImage"
mode="aspectFit"
v-if="qrCodeImage"
/>
<view v-else class="qr-code-placeholder">
<view class="loader"></view>
</view>
</view>
<!-- 会员编号样式区域 - 用户自定义样式位置 -->
<text
class="member-code-text"
style="font-size: 30rpx; color: #fff; font-weight: bold"
>{{ desensitization(userInfo.memberCode) }}</text
>
</view>
</view>
</view>
</template>
<script>
import html2canvas from 'html2canvas'
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
}
console.log(
'开始html2canvas截取容器尺寸:',
element.offsetWidth,
'x',
element.offsetHeight
)
html2canvas(element, {
useCORS: true,
allowTaint: true,
backgroundColor: null,
scale: 2,
dpi: 400,
logging: true,
width: element.offsetWidth,
height: element.offsetHeight,
windowWidth: element.offsetWidth,
windowHeight: element.offsetHeight,
scrollX: 0,
scrollY: 0,
x: 0,
y: 0,
})
.then(canvas => {
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;
justify-content: center;
}
/* 背景图片样式 */
.share-bg-image {
height: 100%;
width: 100%;
// height: 100%;
z-index: 1;
// object-fit: cover;
}
.share-wrapper {
position: absolute;
z-index: 2;
top: 25%;
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;
justify-content: center;
margin: 0 auto;
opacity: 0;
text-align: center;
}
.portal-frame.is-loaded {
opacity: 1;
}
/* 二维码样式区域 - 用户自定义样式位置 */
.qr-code-outer {
width: 280rpx;
height: 280rpx;
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;
}
.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 {
display: block;
text-align: center;
/* 用户可以在这里自定义会员编号的样式 */
}
/* 下载按钮样式 */
.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>