Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
飞
飞鹤小程序
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
FH
飞鹤小程序
Commits
5fcd2fe2
Commit
5fcd2fe2
authored
Nov 14, 2025
by
spc
Browse files
Options
Browse Files
Download
Plain Diff
fixed
parents
d1e75afe
004fd931
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
474 additions
and
56 deletions
+474
-56
TaskPerson.vue
components/renwu/TaskPerson.vue
+21
-0
TaskPop.vue
components/renwu/TaskPop.vue
+3
-1
XingmaLabPosterPage.vue
components/xingmaLab/XingmaLabPosterPage.vue
+312
-27
manifest.json
manifest.json
+1
-4
XingmaLabDetailPage.vue
pages/XingmaLabDetailPage/XingmaLabDetailPage.vue
+84
-2
heliaixinTools.vue
pages/heliaixinTools/heliaixinTools.vue
+27
-3
index.vue
pages/index/index.vue
+10
-7
goodDetail.vue
v3/goodDetail/goodDetail.vue
+14
-10
Integral.vue
views/Integral.vue
+2
-2
No files found.
components/renwu/TaskPerson.vue
View file @
5fcd2fe2
...
...
@@ -718,6 +718,27 @@ onMounted(async() => {
initData
();
});
// 监听 visible 变化,设置页面滚动状态
watch
(()
=>
props
.
visible
,
(
newVal
)
=>
{
// #ifdef MP-WEIXIN
if
(
newVal
)
{
// 弹窗展示时,禁止页面滚动
wx
.
setPageStyle
({
style
:
{
overflow
:
'hidden'
}
});
}
else
{
// 弹窗关闭时,恢复页面滚动
wx
.
setPageStyle
({
style
:
{
overflow
:
'auto'
}
});
}
// #endif
},
{
immediate
:
true
});
// 监听 babyStage 和 dueDate
watch
(
()
=>
[
formData
.
value
.
babyStage
,
formData
.
value
.
babyBirthday
],
...
...
components/renwu/TaskPop.vue
View file @
5fcd2fe2
...
...
@@ -24,7 +24,9 @@
/>
</view>
<view
class=
"task_content"
>
<text
class=
"task_title"
>
{{
task
?.
taskTodoExtra
?.
title
}}
</text>
<text
class=
"task_title"
>
{{
task
?.
taskTodoExtra
?.
title
}}{{
(
task
?.
taskTodoExtra
?.
type
===
'BROWSE_PAGE'
||
task
?.
taskTodoExtra
?.
type
===
'EXCHANGE_GOODS'
)
?
`(${task?.taskTodoExtra?.completeCount || 0
}
/${task?.taskTodoExtra?.completeLimit || 0
}
)`
:
''
}}
<
/text
>
<
text
class
=
"task_points"
>
{{
task
?.
taskTodoExtra
?.
desc
}}
<
/text
>
<
/view
>
<
view
...
...
components/xingmaLab/XingmaLabPosterPage.vue
View file @
5fcd2fe2
...
...
@@ -19,7 +19,7 @@
<!-- 图片区域 -->
<view
class=
"poster-image-wrapper"
>
<image
class=
"poster-image-bg"
:src=
"`$
{$baseUrl}homepage/Q3Res/xingmaLabPosterImgBg.png`"
<image
class=
"poster-image-bg"
:src=
"`$
{$baseUrl}homepage/Q3Res/xingmaLabPosterImgBg
2
.png`"
mode="aspectFit">
</image>
<image
v-if=
"imageUrl"
class=
"poster-image"
:src=
"imageUrl"
mode=
"aspectFit"
></image>
<!-- 文字内容 -->
...
...
@@ -110,10 +110,14 @@ 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
canvasWidth
=
(
542
/
750
)
*
screenWidth
const
canvasHeight
=
(
956
/
750
)
*
screenWidth
const
baseCanvasWidth
=
(
542
/
750
)
*
screenWidth
const
baseCanvasHeight
=
(
956
/
750
)
*
screenWidth
const
canvasWidth
=
baseCanvasWidth
*
pixelRatio
const
canvasHeight
=
baseCanvasHeight
*
pixelRatio
// 监听 visible 变化,生成二维码
watch
(()
=>
props
.
visible
,
(
newVal
)
=>
{
...
...
@@ -130,12 +134,13 @@ const generateQrcodeFunc = async () => {
console
.
warn
(
'recordId 未传入,无法生成二维码'
)
return
}
console
.
warn
(
'recordId'
,
props
.
recordId
)
try
{
const
result
=
await
generateQRCode
({
scene
:
`id=
${
props
.
recordId
}
`
,
page
:
`pages/XingmaLabDetailPage/XingmaLabDetailPage`
,
envVersion
:
'
develop'
envVersion
:
'
trial'
//trial develop release
})
if
(
result
&&
result
.
ok
&&
result
.
data
&&
result
.
data
.
qrCodeBase64
)
{
...
...
@@ -221,9 +226,12 @@ const handleDownload = async () => {
// 保存初始状态
ctx
.
save
()
// 海报尺寸(rpx 转 px)
const
posterWidth
=
canvasWidth
const
posterHeight
=
canvasHeight
// 缩放 canvas 上下文以适应高分辨率
ctx
.
scale
(
pixelRatio
,
pixelRatio
)
// 海报尺寸(使用基础尺寸,因为已经缩放)
const
posterWidth
=
baseCanvasWidth
const
posterHeight
=
baseCanvasHeight
// 绘制背景
await
drawImage
(
ctx
,
`
${
$baseUrl
}
homepage/Q3Res/xingmaLabPosterBg.png`
,
0
,
0
,
posterWidth
,
posterHeight
)
...
...
@@ -265,7 +273,10 @@ const handleDownload = async () => {
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
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
...
...
@@ -275,13 +286,13 @@ const handleDownload = async () => {
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
)
await
drawImage
(
ctx
,
props
.
imageUrl
,
imageX
,
imageY
,
imageW
,
imageH
,
true
)
}
// 绘制文字内容
...
...
@@ -290,7 +301,10 @@ const handleDownload = async () => {
ctx
.
setTextAlign
(
'left'
)
const
contentX
=
imageBgX
+
(
22
/
750
)
*
screenWidth
const
contentY
=
imageBgY
+
imageBgH
-
(
146
/
750
)
*
screenWidth
ctx
.
fillText
(
props
.
content
||
''
,
contentX
,
contentY
)
// 计算内容文字最大宽度(图片区域宽度 - 左右边距)
const
contentMaxWidth
=
imageBgW
-
(
44
/
750
)
*
screenWidth
const
truncatedContent
=
truncateText
(
ctx
,
props
.
content
||
''
,
contentMaxWidth
)
ctx
.
fillText
(
truncatedContent
,
contentX
,
contentY
)
// 绘制唯一藏品编号
ctx
.
setFillStyle
(
'#D3A458'
)
...
...
@@ -306,17 +320,26 @@ const handleDownload = async () => {
// 二维码位置:图片区域右下角,距离右边 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
drawImage
(
ctx
,
qrcodeImageUrl
.
value
,
qrcodeX
,
qrcodeY
,
qrcodeSize
,
qrcodeSize
)
// 绘制二维码,使用稍微缩小的尺寸以去除边框
await
drawQRCodeImage
(
ctx
,
qrcodeImageUrl
.
value
,
qrcodeDrawX
,
qrcodeDrawY
,
qrcodeDrawSize
,
qrcodeDrawSize
)
console
.
log
(
'二维码绘制完成'
)
}
else
{
console
.
warn
(
'二维码图片 URL 为空,无法绘制'
)
...
...
@@ -329,13 +352,13 @@ const handleDownload = async () => {
ctx
.
draw
(
false
,
async
()
=>
{
await
nextTick
()
// 转换为临时文件
// 转换为临时文件
(使用高分辨率)
uni
.
canvasToTempFilePath
({
canvasId
:
'posterCanvas'
,
width
:
poster
Width
,
height
:
poster
Height
,
destWidth
:
poster
Width
,
destHeight
:
poster
Height
,
width
:
canvas
Width
,
height
:
canvas
Height
,
destWidth
:
canvas
Width
,
destHeight
:
canvas
Height
,
success
:
(
res
)
=>
{
// 保存到相册
uni
.
saveImageToPhotosAlbum
({
...
...
@@ -344,7 +367,7 @@ const handleDownload = async () => {
uni
.
hideLoading
()
uni
.
showToast
({
title
:
'保存成功'
,
icon
:
'
success
'
icon
:
'
none
'
})
isDownloading
.
value
=
false
},
...
...
@@ -455,9 +478,270 @@ const base64ToTempFilePath = (base64Data) => {
})
}
// 截断文字(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
)
=>
{
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
)
=>
{
...
...
@@ -569,16 +853,13 @@ const drawImage = (ctx, src, x, y, w, h) => {
position: absolute;
left: 0;
top: 0;
width:
25
6rpx;
width:
18
6rpx;
height: 58rpx;
padding:
0 3
0rpx;
padding:
5rpx 0 0 7
0rpx;
font-size: 28rpx;
color: #
333333
;
color: #
000000
;
text-align: center;
z-index: 1;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
...
...
@@ -610,7 +891,6 @@ const drawImage = (ctx, src, x, y, w, h) => {
height: 586rpx;
z-index: 1;
object-fit: contain;
margin: 26rpx;
box-sizing: border-box;
}
...
...
@@ -618,7 +898,8 @@ const drawImage = (ctx, src, x, y, w, h) => {
position: absolute;
bottom: 146rpx;
left: 22rpx;
width: calc(100% - 44rpx);
width: 450rpx;
height: 40rpx;
z-index: 2;
}
...
...
@@ -626,9 +907,13 @@ const drawImage = (ctx, src, x, y, w, h) => {
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 {
...
...
manifest.json
View file @
5fcd2fe2
...
...
@@ -66,10 +66,7 @@
}
},
"requiredBackgroundModes"
:
[
"share"
],
"embeddedAppIdList"
:
[
"wx4205ec55b793245e"
,
"wxab14ac8f684ad962"
],
"optimization"
:
{
"subpackages"
:
true
}
"embeddedAppIdList"
:
[
"wx4205ec55b793245e"
,
"wxab14ac8f684ad962"
]
},
"mp-alipay"
:
{
"usingComponents"
:
true
...
...
pages/XingmaLabDetailPage/XingmaLabDetailPage.vue
View file @
5fcd2fe2
...
...
@@ -358,6 +358,43 @@
}
}
// 从 scene 参数中解析 id
const
parseIdFromScene
=
(
scene
)
=>
{
if
(
!
scene
||
typeof
scene
!==
'string'
)
{
return
''
}
try
{
// 先对 scene 字符串进行 URL 解码
const
decodedScene
=
decodeURIComponent
(
scene
)
// scene 格式可能是 "id=xxx" 或 "id=xxx&other=yyy"
const
params
=
decodedScene
.
split
(
'&'
)
for
(
const
param
of
params
)
{
const
[
key
,
value
]
=
param
.
split
(
'='
)
if
(
key
===
'id'
&&
value
)
{
// value 可能也需要解码(如果 value 本身也被编码了)
return
decodeURIComponent
(
value
)
}
}
}
catch
(
error
)
{
console
.
warn
(
'解析 scene 参数失败:'
,
error
)
// 如果解码失败,尝试直接解析原始 scene
const
params
=
scene
.
split
(
'&'
)
for
(
const
param
of
params
)
{
const
[
key
,
value
]
=
param
.
split
(
'='
)
if
(
key
===
'id'
&&
value
)
{
try
{
return
decodeURIComponent
(
value
)
}
catch
(
e
)
{
return
value
}
}
}
}
return
''
}
// 页面初始化逻辑
const
initPage
=
async
()
=>
{
console
.
log
(
'🔍 initPage:页面初始化逻辑'
);
...
...
@@ -379,11 +416,56 @@
// 调用 home 接口获取登录状态
await
homeStore
.
loadHomeInfo
()
// 获取页面跳转参数中的 id
和 index
// 获取页面跳转参数中的 id
const
pages
=
getCurrentPages
()
const
currentPage
=
pages
[
pages
.
length
-
1
]
console
.
log
(
'🔍 currentPage:'
,
currentPage
);
const
id
=
currentPage
.
options
?.
id
||
''
// 优先从 options.id 获取
let
id
=
currentPage
.
options
?.
id
||
''
// 如果 options.id 不存在,尝试从 scene 参数中解析
if
(
!
id
)
{
// 尝试从 currentPage.options.scene 获取
const
scene
=
currentPage
.
options
?.
scene
||
''
if
(
scene
)
{
id
=
parseIdFromScene
(
scene
)
console
.
log
(
'🔍 从 currentPage.options.scene 解析到 id:'
,
id
)
}
// 如果还是没有,尝试从 wx.getLaunchOptionsSync() 获取(扫码进入场景)
if
(
!
id
)
{
try
{
const
launchOptions
=
wx
.
getLaunchOptionsSync
()
if
(
launchOptions
&&
launchOptions
.
scene
)
{
// 如果是扫码场景(scene 值为 1047 或 1048),从 query 中获取 scene 参数
if
(
launchOptions
.
scene
===
1047
||
launchOptions
.
scene
===
1048
)
{
const
sceneParam
=
launchOptions
.
query
?.
scene
||
''
if
(
sceneParam
)
{
id
=
parseIdFromScene
(
sceneParam
)
console
.
log
(
'🔍 从 launchOptions.query.scene 解析到 id:'
,
id
)
}
}
}
}
catch
(
error
)
{
console
.
warn
(
'获取 launchOptions 失败:'
,
error
)
}
}
// 如果还是没有,尝试从 wx.getEnterOptionsSync() 获取
if
(
!
id
)
{
try
{
const
enterOptions
=
wx
.
getEnterOptionsSync
()
if
(
enterOptions
&&
enterOptions
.
query
&&
enterOptions
.
query
.
scene
)
{
id
=
parseIdFromScene
(
enterOptions
.
query
.
scene
)
console
.
log
(
'🔍 从 enterOptions.query.scene 解析到 id:'
,
id
)
}
}
catch
(
error
)
{
console
.
warn
(
'获取 enterOptions 失败:'
,
error
)
}
}
}
if
(
id
)
{
console
.
log
(
'🔍 获取到页面参数 id:'
,
id
)
recordId
.
value
=
id
// 立即保存ID,确保分享时能获取到
...
...
pages/heliaixinTools/heliaixinTools.vue
View file @
5fcd2fe2
...
...
@@ -6,7 +6,7 @@
mode=
"aspectFill"
/>
<image
class=
"hlax_btn"
:src=
"$baseUrl + 'heliaixinTool/btn_go_see2.png'"
v-if=
"toolCfg.link?.go_see"
@
click=
"onTips"
/>
<!-- go_see=true,有按钮,否则没有按钮 -->
<!-- go_see=true,有按钮,否则没有按钮 -->
</view>
</
template
>
...
...
@@ -16,7 +16,8 @@
onMounted
,
getCurrentInstance
,
computed
}
from
"vue"
;
}
from
"vue"
;
import
md
from
'../../md.js'
;
import
{
usePageCfgStore
}
from
"@/stores/pageCfg"
;
...
...
@@ -30,11 +31,34 @@
pageCfgStore
?.
toolList
.
find
((
item
)
=>
item
.
title
==
"鹤礼爱心"
)
||
{}
);
onMounted
(()
=>
{})
onMounted
(()
=>
{
console
.
log
(
'啊啊啊啊啊啊'
)
if
(
toolCfg
.
value
.
link
&&
toolCfg
.
value
.
link
.
go_see
)
{
//已登录并且已报名
md
.
sensorComponentLogTake
({
xcxComponentExposure
:
'true'
,
pageName
:
'鹤礼2.0活动详情页'
,
componentName
:
'鹤礼2.0活动详情页-已报名用户'
,
componentContent
:
'去查看'
,
});
}
else
{
//未登录或者未报名
md
.
sensorComponentLogTake
({
xcxComponentExposure
:
'true'
,
pageName
:
'鹤礼2.0活动详情页'
,
componentName
:
'鹤礼2.0活动详情页-未报名用户'
,
componentContent
:
'未报名'
,
});
}
})
//点击去查看按钮提示
const
onTips
=
()
=>
{
console
.
log
(
"toolCfg:::"
,
toolCfg
);
md
.
sensorComponentLogTake
({
xcxComponentClick
:
'true'
,
pageName
:
'鹤礼2.0活动详情页'
,
componentName
:
'鹤礼2.0活动详情页-未报名用户'
,
componentContent
:
'未报名'
,
});
uni
.
showToast
({
title
:
'可去'
+
toolCfg
.
value
?.
link
?.
channelName
+
'渠道查看'
,
icon
:
"none"
...
...
pages/index/index.vue
View file @
5fcd2fe2
...
...
@@ -111,14 +111,14 @@ const shareOptions = {
imageUrl
:
$baseUrl
+
'share/share_home0901.jpg'
,
},
1
:
{
title
:
'星妈会 | 品牌页分享文案'
,
path
:
'/pages/index/index?pageType=brand'
,
imageUrl
:
$baseUrl
+
'common/shareImg.png'
,
title
:
"星妈会 | 陪伴成长每一步"
,
path
:
"/pages/index/index?pageType=brand"
,
imageUrl
:
$baseUrl
+
"common/shareImg.png"
,
},
2
:
{
title
:
'星妈会 | 解锁你的会员服务'
,
path
:
'/pages/index/index?pageType=integral'
,
imageUrl
:
$baseUrl
+
'common/shareImg.png'
,
title
:
"星妈会 | 解锁你的会员服务"
,
path
:
"/pages/index/index?pageType=integral"
,
imageUrl
:
$baseUrl
+
"common/shareImg.png"
,
},
};
...
...
@@ -251,6 +251,8 @@ const handleTaskComplete = async (taskIdParam) => {
}
else
{
console
.
info
(
'taskCompleteJSON res error:'
,
integralStore
.
queryTodoResult
);
}
await
integralStore
.
getSigninAndTaskInfo
();
//刷新任务接口
};
onShow
(
async
()
=>
{
...
...
@@ -554,9 +556,10 @@ const handleTaskClick = async (data) => {
const
extra3
=
JSON
.
parse
(
data
?.
task
?.
taskTodoExtra
?.
extra
);
if
(
extra3
.
length
>
0
)
{
const
idx
=
Math
.
floor
(
Math
.
random
()
*
extra3
.
length
);
let
url
=
'subPackages/shopMainProcess/product/index?productId={productId}&skuId={skuId}&entrySource=xmh_wechatmp_points_north'
;
url
=
url
.
replace
(
'{productId}'
,
extra3
[
0
].
itemId
).
replace
(
'{skuId}'
,
extra3
[
0
].
skuId
);
url
=
url
.
replace
(
'{productId}'
,
extra3
[
idx
].
itemId
).
replace
(
'{skuId}'
,
extra3
[
idx
].
skuId
);
jump
({
type
:
JumpType
.
MINI
,
url
:
url
,
...
...
v3/goodDetail/goodDetail.vue
View file @
5fcd2fe2
...
...
@@ -356,9 +356,12 @@ export default {
this
.
checkUserStatus
();
// 页面返回时刷新商品详情接口
// 根据 initOptions 中的参数判断使用哪个接口刷新
// 如果 initOptions 中有 activityId 和 sessionKey,使用秒杀接口;否则使用普通接口
if
(
this
.
initOptions
)
{
if
(
this
.
isSeckill
&&
this
.
initOptions
.
activityId
&&
this
.
initOptions
.
sessionKey
)
{
// 秒杀商品刷新
// 检查 initOptions 中是否有秒杀参数
if
(
this
.
initOptions
.
activityId
&&
this
.
initOptions
.
sessionKey
)
{
// 秒杀商品刷新:使用 initOptions 中的秒杀参数
const
seckillParams
=
{
gid
:
this
.
initOptions
.
appGoodsId
||
this
.
initOptions
.
gid
||
this
.
initOptions
.
id
||
this
.
initOptions
.
goodsId
||
''
,
activityId
:
this
.
initOptions
.
activityId
,
...
...
@@ -366,15 +369,16 @@ export default {
};
if
(
seckillParams
.
gid
&&
seckillParams
.
activityId
&&
seckillParams
.
sessionKey
)
{
this
.
fetchSeckillDetail
(
seckillParams
);
return
;
}
}
else
if
(
!
this
.
isSeckill
)
{
// 普通商品刷新
const
apiParams
=
{
gid
:
this
.
initOptions
.
gid
||
this
.
initOptions
.
id
||
this
.
initOptions
.
goodsId
||
''
};
if
(
apiParams
.
gid
)
{
this
.
fetchGoodsDetail
(
apiParams
);
}
}
// 普通商品刷新
const
apiParams
=
{
gid
:
this
.
initOptions
.
gid
||
this
.
initOptions
.
id
||
this
.
initOptions
.
goodsId
||
''
};
if
(
apiParams
.
gid
)
{
this
.
fetchGoodsDetail
(
apiParams
);
}
}
},
...
...
views/Integral.vue
View file @
5fcd2fe2
...
...
@@ -3071,13 +3071,13 @@ const handleViewBenefits = () => {
}
;
// 任务按钮点击事件
const handleTaskButtonClick = () => {
const handleTaskButtonClick =
async
() => {
// jump({
// type: JumpType.INNER,
// url: '/activities/1015/home'
//
}
)
// return
await integralStore.getSigninAndTaskInfo();//刷新任务接口
console.log('任务按钮点击');
console.log('taskTodo数据:', integralStore?.signinAndTaskInfo?.data?.taskTodo);
globalStore.showTaskPop(integralStore?.signinAndTaskInfo?.data?.taskTodo);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment