Commit e6cb8b18 authored by spc's avatar spc

fixed

parent 3b91e3a1
import requestModule from './request.js' import requestModule from './request.js'
const {api} = requestModule const { api } = requestModule
/** /**
* 星妈会藏馆 * 星妈会藏馆
...@@ -38,3 +38,5 @@ export const fetchRecordDetail = (data) => api.get('/c/lab/record/detail', data) ...@@ -38,3 +38,5 @@ export const fetchRecordDetail = (data) => api.get('/c/lab/record/detail', data)
export const fetchFavoriteAdd = (data) => api.get('/c/lab/favorite/add', data) export const fetchFavoriteAdd = (data) => api.get('/c/lab/favorite/add', data)
export const fetchFavoriteRemove = (data) => api.get('/c/lab/favorite/remove', data) export const fetchFavoriteRemove = (data) => api.get('/c/lab/favorite/remove', data)
export const generateQRCode = (data) => api.post('/c/wechat/generateQRCode', data)
\ No newline at end of file
<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/xingmaLabPosterImgBg.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)
const systemInfo = uni.getSystemInfoSync()
const screenWidth = systemInfo.windowWidth || 375
const canvasWidth = (542 / 750) * screenWidth
const canvasHeight = (956 / 750) * screenWidth
// 监听 visible 变化,生成二维码
watch(() => props.visible, (newVal) => {
if (newVal) {
nextTick(() => {
generateQrcodeFunc()
})
}
})
// 生成二维码
const generateQrcodeFunc = async () => {
if (!props.recordId) {
console.warn('recordId 未传入,无法生成二维码')
return
}
try {
const result = await generateQRCode({
scene: `id=${props.recordId}`,
page: `pages/XingmaLabDetailPage/XingmaLabDetailPage`,
envVersion: 'develop'
})
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()
// 海报尺寸(rpx 转 px)
const posterWidth = canvasWidth
const posterHeight = canvasHeight
// 绘制背景
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
ctx.fillText(nickname.value || '', 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/xingmaLabPosterImgBg.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)
}
// 绘制文字内容
ctx.setFillStyle('#000000')
ctx.setFontSize((28 / 750) * screenWidth)
ctx.setTextAlign('left')
const contentX = imageBgX + (22 / 750) * screenWidth
const contentY = imageBgY + imageBgH - (146 / 750) * screenWidth
ctx.fillText(props.content || '', 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
console.log('开始绘制二维码:', {
qrcodeX,
qrcodeY,
qrcodeSize,
imageBgX,
imageBgY,
imageBgW,
imageBgH,
qrcodeImageUrl: qrcodeImageUrl.value.substring(0, 50) + '...'
})
await drawImage(ctx, qrcodeImageUrl.value, qrcodeX, qrcodeY, qrcodeSize, qrcodeSize)
console.log('二维码绘制完成')
} else {
console.warn('二维码图片 URL 为空,无法绘制')
}
// 等待所有绘制完成后再调用 draw
await nextTick()
// 绘制到 canvas
ctx.draw(false, async () => {
await nextTick()
// 转换为临时文件
uni.canvasToTempFilePath({
canvasId: 'posterCanvas',
width: posterWidth,
height: posterHeight,
destWidth: posterWidth,
destHeight: posterHeight,
success: (res) => {
// 保存到相册
uni.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success: () => {
uni.hideLoading()
uni.showToast({
title: '保存成功',
icon: 'success'
})
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 drawImage = (ctx, src, x, y, w, h) => {
return new Promise((resolve) => {
// 如果是 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: 256rpx;
height: 58rpx;
padding: 0 30rpx;
font-size: 28rpx;
color: #333333;
text-align: center;
z-index: 1;
display: flex;
align-items: center;
justify-content: center;
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;
margin: 26rpx;
box-sizing: border-box;
}
.poster-content {
position: absolute;
bottom: 146rpx;
left: 22rpx;
width: calc(100% - 44rpx);
z-index: 2;
}
.poster-content-text {
font-size: 28rpx;
font-weight: 500;
color: #000000;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.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>
<template>
<view v-if="visible" class="share-popup-overlay" @tap="handleOverlayClick">
<view class="share-popup-container" @tap.stop>
<!-- 背景 -->
<image class="share-popup-bg" :src="`${$baseUrl}homepage/Q3Res/xingmaLabPosterBtnConBg.png`"
mode="aspectFit"></image>
<!-- 标题 -->
<view class="share-popup-title">
<view class="close-btn" @tap="handleClose">
<image class="close-icon" :src="`${$baseUrl}homepage/Q3Res/xingmaLabPosterBtnConCloseBtn.png`"
mode="aspectFit"></image>
</view>
</view>
<!-- 按钮区域 -->
<view class="share-popup-buttons">
<!-- 分享给好友 -->
<view class="share-button-item">
<button open-type="share" class="share-button-trigger" @tap="handleShareToFriend">
<view class="button-icon button-icon-share">
<image class="icon-image"
:src="`${$baseUrl}homepage/Q3Res/xingmaLabPosterBtnConShareBtn.png`" mode="aspectFit">
</image>
</view>
</button>
</view>
<!-- 生成分享海报 -->
<view class="share-button-item" @tap="handleGeneratePoster">
<view class="button-icon button-icon-poster">
<image class="icon-image"
:src="`${$baseUrl}homepage/Q3Res/xingmaLabPosterBtnConShowPosterBtn.png`" mode="aspectFit">
</image>
</view>
</view>
</view>
</view>
</view>
</template>
<script setup>
import { getCurrentInstance } from 'vue'
const { proxy } = getCurrentInstance()
const $baseUrl = proxy.$baseUrl
const props = defineProps({
visible: {
type: Boolean,
default: false
}
})
const emit = defineEmits(['close', 'shareToFriend', 'generatePoster'])
// 关闭弹窗
const handleClose = () => {
emit('close')
}
// 点击遮罩关闭
const handleOverlayClick = () => {
handleClose()
}
// 分享给好友
const handleShareToFriend = () => {
emit('shareToFriend')
handleClose()
}
// 生成分享海报
const handleGeneratePoster = () => {
emit('generatePoster')
handleClose()
}
</script>
<style lang="less" scoped>
.share-popup-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
align-items: flex-end;
justify-content: center;
z-index: 9999;
}
.share-popup-container {
position: relative;
width: 750rpx;
height: 432rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.share-popup-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 0;
}
.share-popup-title {
position: relative;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
padding-top: 60rpx;
z-index: 1;
}
.title-text {
font-size: 36rpx;
font-weight: 500;
color: #333333;
}
.close-btn {
position: absolute;
right: 40rpx;
top: 50%;
transform: translateY(-50%);
width: 48rpx;
height: 48rpx;
display: flex;
align-items: center;
justify-content: center;
}
.close-icon {
width: 48rpx;
height: 48rpx;
}
.share-popup-buttons {
position: relative;
width: 100%;
display: flex;
align-items: center;
justify-content: space-around;
padding: 80rpx 60rpx 0;
z-index: 1;
}
.share-button-item {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
position: relative;
}
.share-button-trigger {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: transparent;
border: none;
padding: 0;
margin: 0;
line-height: normal;
}
.share-button-trigger::after {
border: none;
}
.button-icon {
margin-bottom: 20rpx;
display: flex;
align-items: center;
justify-content: center;
}
.button-icon-share {
width: 148rpx;
height: 202rpx;
}
.button-icon-poster {
width: 170rpx;
height: 202rpx;
}
.icon-image {
width: 100%;
height: 100%;
}
.button-text {
font-size: 28rpx;
color: #333333;
}
</style>
...@@ -42,9 +42,9 @@ ...@@ -42,9 +42,9 @@
@click="handleLikeClick"></span> @click="handleLikeClick"></span>
<!-- 分享按钮 --> <!-- 分享按钮 -->
<button open-type="share" class="xingmalabdetailpagebottomconsharebtn" <view class="xingmalabdetailpagebottomconsharebtn"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.bottomConShareBtn)})` }" :style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.bottomConShareBtn)})` }"
@click="handleShareClick"></button> @click="handleShareClick"></view>
<!-- 未登录时覆盖的授权按钮层 --> <!-- 未登录时覆盖的授权按钮层 -->
<div v-if="homeStore && !homeStore.isLogin" class="auth-overlay"> <div v-if="homeStore && !homeStore.isLogin" class="auth-overlay">
...@@ -57,6 +57,25 @@ ...@@ -57,6 +57,25 @@
class="auth-share-btn phone-auth-btn-cover"></button> class="auth-share-btn phone-auth-btn-cover"></button>
</div> </div>
</div> </div>
<!-- 分享弹窗 -->
<XingmaLabSharePopup
:visible="showSharePopup"
@close="handleCloseSharePopup"
@shareToFriend="handleShareToFriend"
@generatePoster="handleGeneratePoster" />
<!-- 海报页面 -->
<XingmaLabPosterPage
:visible="showPosterPage"
:imageUrl="detailData.imgUrl"
:content="detailData.content || '可爱'"
:collectionNumber="detailData.bizNo || collectionNumber"
:defaultNickname="detailData.nickname || '星妈用户'"
:avatar="detailData.avatar || ''"
:recordId="recordId || detailData.id || ''"
@close="handleClosePosterPage"
@download="handleDownloadPoster" />
</view> </view>
</template> </template>
...@@ -83,6 +102,8 @@ ...@@ -83,6 +102,8 @@
useUserStore useUserStore
} from '@/stores/user.js' } from '@/stores/user.js'
import md from '../../md'; import md from '../../md';
import XingmaLabSharePopup from '@/components/xingmaLab/XingmaLabSharePopup.vue'
import XingmaLabPosterPage from '@/components/xingmaLab/XingmaLabPosterPage.vue'
// 组件名称 // 组件名称
defineOptions({ defineOptions({
...@@ -104,6 +125,10 @@ ...@@ -104,6 +125,10 @@
state: null state: null
}) })
// 分享弹窗和海报页面状态
const showSharePopup = ref(false)
const showPosterPage = ref(false)
// 配置对象 // 配置对象
const config = xingmaLabDetailConfig const config = xingmaLabDetailConfig
...@@ -259,22 +284,58 @@ ...@@ -259,22 +284,58 @@
} }
const handleShareClick = () => { const handleShareClick = () => {
// 使用 open-type="share" 时,点击事件可以为空 // 显示分享弹窗
// 分享内容通过页面配置自动设置 showSharePopup.value = true
console.log('分享按钮被点击')
//TODO:埋点 // 埋点
md.sensorComponentLogTake({ md.sensorComponentLogTake({
xcxComponentClick: "true", xcxComponentClick: "true",
pageName: "星妈lab-藏品详情页", pageName: "星妈lab-藏品详情页",
componentName: "藏品详情", componentName: "藏品详情",
componentContent: "分享" componentContent: "分享"
}); });
}
// 手动触发分享(如果需要的话) // 关闭分享弹窗
// uni.showShareMenu({ const handleCloseSharePopup = () => {
// withShareTicket: true, showSharePopup.value = false
// menus: ['shareAppMessage'] // 仅分享给好友,禁用朋友圈 }
// })
// 分享给好友
const handleShareToFriend = () => {
// 埋点
md.sensorComponentLogTake({
xcxComponentClick: "true",
pageName: "星妈lab-藏品详情页",
componentName: "分享弹窗",
componentContent: "分享给好友"
});
// 分享功能由 button 的 open-type="share" 自动触发
}
// 生成分享海报
const handleGeneratePoster = () => {
showPosterPage.value = true
// 埋点
md.sensorComponentLogTake({
xcxComponentClick: "true",
pageName: "星妈lab-藏品详情页",
componentName: "分享弹窗",
componentContent: "生成分享海报"
});
}
// 关闭海报页面
const handleClosePosterPage = () => {
showPosterPage.value = false
}
// 下载海报
const handleDownloadPoster = (data) => {
// TODO: 实现海报下载逻辑
// 可以使用 canvas 将海报内容绘制成图片,然后保存到相册
console.log('下载海报', data)
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment