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
742d7083
Commit
742d7083
authored
Nov 11, 2025
by
spc
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fixed
parent
78cd0752
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
214 additions
and
172 deletions
+214
-172
ActivitySelectedPopup.vue
components/ActivitySelectedPopup.vue
+127
-68
main.js
main.js
+2
-2
index.vue
pages/index/index.vue
+85
-102
No files found.
components/ActivitySelectedPopup.vue
View file @
742d7083
...
...
@@ -17,26 +17,28 @@
<view
v-if=
"activityList.length >= 3"
class=
"activity-scroll-wrapper"
>
<scroll-view
class=
"activity-scroll"
scroll-y
:scroll-top=
"scrollTop"
>
<view
v-for=
"(activity, index) in activityList"
:key=
"index"
class=
"activity-item"
>
<text
class=
"activity-text"
>
已入选
{{
activity
.
name
||
''
}}
</text>
<view
class=
"activity-btn"
:class=
"
{ disabled: activity.disabled }"
@tap="handleViewActivity(activity, index)">
查看活动
</view>
<text
class=
"activity-text"
:class=
"
{ 'faded': index >= 2 }">已入选
{{
activity
.
name
||
''
}}
</text>
</view>
</scroll-view>
<!-- 底部渐变蒙层 -->
<view
class=
"scroll-fade-mask"
>
<image
class=
"mask-image"
:src=
"`$
{$baseUrl}homepage/Q3Res/actSelectMask.png`" mode="aspectFit">
</image>
</view>
</view>
<view
v-else
class=
"activity-list"
>
<view
v-for=
"(activity, index) in activityList"
:key=
"index"
class=
"activity-item"
>
<text
class=
"activity-text"
>
已入选
{{
activity
.
name
||
''
}}
</text>
<view
class=
"activity-btn"
:class=
"
{ disabled: activity.disabled }"
@tap="handleViewActivity(activity, index)">
查看活动
</view>
</view>
</view>
<!-- 底部渐变蒙层 -->
<view
v-if=
"activityList.length >= 3"
class=
"scroll-fade-mask"
>
<image
class=
"mask-image"
:src=
"`$
{$baseUrl}homepage/Q3Res/actSelectMask.png`" mode="aspectFit">
</image>
</view>
<!-- 底部统一按钮 -->
<view
class=
"bottom-btn-wrapper"
>
<view
class=
"activity-btn"
@
tap=
"handleBottomButtonClick"
>
<image
class=
"activity-btn-image"
:src=
"`$
{$baseUrl}homepage/Q3Res/actSelectLookBtn.png`"
mode="aspectFit">
</image>
</view>
</view>
</view>
...
...
@@ -89,22 +91,28 @@ const popupStyle = computed(() => {
// 查看活动
const
handleViewActivity
=
async
(
activity
,
index
)
=>
{
if
(
activity
.
disabled
)
{
return
}
emit
(
'viewActivity'
,
activity
,
index
)
}
// 底部按钮点击
const
handleBottomButtonClick
=
()
=>
{
// 调用接口,传所有 activityIds
const
activityIds
=
props
.
activityList
.
filter
(
activity
=>
activity
.
id
)
.
map
(
activity
=>
activity
.
id
)
// 调用接口,传单个 activityId
if
(
activity
.
id
)
{
try
{
await
fetchUserClickActivity
({
activityIds
:
[
activity
.
id
]
})
}
catch
(
error
)
{
console
.
error
(
'点击活动接口调用失败:'
,
error
)
}
if
(
activityIds
.
length
>
0
)
{
try
{
await
fetchUserClickActivity
({
activityIds
:
activityIds
})
}
catch
(
error
)
{
console
.
error
(
'关闭弹窗接口调用失败:'
,
error
)
}
}
emit
(
'viewActivity'
,
activity
,
index
)
handleViewActivity
(
props
.
activityList
[
0
],
0
)
}
// 关闭弹窗
...
...
@@ -169,6 +177,7 @@ const handleMaskClick = (e) => {
flex-shrink: 0;
border-radius: 38rpx;
z-index: 1;
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.15);
}
/* 背景底 */
...
...
@@ -187,109 +196,159 @@ const handleMaskClick = (e) => {
position: relative;
width: 100%;
height: 100%;
padding: 60rpx 40rpx 40rpx 40rpx;
box-sizing: border-box;
z-index: 1;
}
.popup-title {
position: absolute;
top: 48rpx;
left: 0;
right: 0;
font-size: 36rpx;
font-weight: bold;
color: #D3A458;
text-align: center;
margin-bottom: 40rpx;
letter-spacing: 1rpx;
line-height: 1.2;
z-index: 2;
}
.activity-scroll-wrapper {
position: relative;
position: absolute;
top: 120rpx;
left: 40rpx;
right: 40rpx;
bottom: 120rpx;
max-height: 360rpx;
height:
360rpx
;
height:
auto
;
}
.activity-scroll {
width: 100%;
max-height: 250rpx;
height: 250rpx;
}
/* 底部渐变蒙层 */
.scroll-fade-mask {
.activity-scroll .activity-item {
position: relative;
width: 100%;
min-height: 56rpx;
margin-bottom: 20rpx;
}
.activity-scroll .activity-text {
position: absolute;
bottom: 0;
left: 0;
right: 0;
top: 0;
font-size: 28rpx;
color: #333333;
text-align: center;
font-weight: 400;
line-height: 1.6;
width: 100%;
}
/* 底部渐变蒙层 */
.scroll-fade-mask {
position: absolute;
bottom: 0rpx;
left: 50%;
transform: translateX(-50%);
width: 546rpx;
height: 85rpx;
pointer-events: none;
z-index: 10;
display: flex;
align-items: flex-end;
justify-content: center;
z-index: 2;
}
.mask-image {
position: absolute;
bottom: 0;
left: 0;
width: 546rpx;
height: 170rpx;
flex-shrink: 0;
object-fit: cover;
}
.activity-list {
display: flex;
flex-direction: column;
gap: 35rpx;
position: absolute;
top: 120rpx;
left: 40rpx;
right: 40rpx;
bottom: 120rpx;
width: calc(100% - 80rpx);
}
.activity-item {
display: flex
;
align-items: center
;
justify-content: space-between
;
padding: 20rpx 0
;
position: relative
;
width: 100%
;
min-height: 56rpx
;
margin-bottom: 20rpx
;
}
.activity-text {
position: absolute;
left: 0;
right: 0;
top: 0;
font-size: 28rpx;
color: #333333;
flex: 1;
text-align: center;
font-weight: 400;
line-height: 1.6;
width: 100%;
}
.activity-text.faded {
color: #333333;
}
.bottom-btn-wrapper {
position: absolute;
bottom: 40rpx;
left: 50%;
transform: translateX(-50%);
width: 396rpx;
height: 78rpx;
z-index: 3;
}
.activity-btn {
display: flex;
width: 160rpx;
height: 60rpx;
padding: 24rpx 160rpx;
justify-content: center;
align-items: center;
gap: 20rpx;
flex-shrink: 0;
border-radius: 44rpx;
background: #D3A358;
color: #FFFFFF;
font-size: 24rpx;
text-align: center;
box-sizing: border-box;
position: absolute;
top: 0;
left: 0;
width: 396rpx;
height: 78rpx;
transition: all 0.3s ease;
background: transparent;
border: none;
}
.activity-btn.disabled {
background: #E0E0E0;
color: #999999;
.activity-btn-image {
position: absolute;
top: 0;
left: 0;
width: 396rpx;
height: 78rpx;
}
.close-btn {
position: absolute;
bottom: -80rpx;
left: 50%;
transform: translateX(-50%);
top: 1100rpx;
width: 56rpx;
height: 56rpx;
background-color: rgba(255, 255, 255, 0.5);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
z-index: 2;
}
.close-icon {
position: absolute;
top: 0;
left: 0;
width: 56rpx;
height: 56rpx;
}
...
...
main.js
View file @
742d7083
...
...
@@ -6,8 +6,8 @@ import md from "./md";
const
SENSORS_URL
=
"https://sensors.feihe.com/sa?project=XMH_Content"
;
// const BASE_URL = 'https://duiba.oss-cn-hangzhou.aliyuncs.com/fh/';
const
BASE_URL
=
'https://firmus-member-test-1253290912.cos.ap-beijing.myqcloud.com/xmh-mini-program/'
;
//
const BASE_URL = "https://course.feihe.com/momclub-picture/";
//
const BASE_URL = 'https://firmus-member-test-1253290912.cos.ap-beijing.myqcloud.com/xmh-mini-program/';
const
BASE_URL
=
"https://course.feihe.com/momclub-picture/"
;
md
.
init
(
SENSORS_URL
);
...
...
pages/index/index.vue
View file @
742d7083
...
...
@@ -51,8 +51,23 @@
}">
<!--
<text
class=
"back-text"
>
返回app
</text>
-->
</button>
<!-- 悬浮授权手机号模块 -->
<view
class=
"auth-phone-module"
v-if=
"!userStore.memberInfo?.mobile"
>
<image
class=
"auth-phone-bg"
:src=
"$baseUrl + 'homepage/Q3Res/accessBg3.png'"
></image>
<view
class=
"auth-phone-btn-container"
>
<image
class=
"auth-phone-btn"
:src=
"$baseUrl + 'homepage/Q3Res/accessBtn3.png'"
@
tap=
"handleAuthPhoneClick"
>
</image>
</view>
</view>
<!-- 活动入选弹窗 - 移到容器外部,确保 fixed 定位正确 -->
<ActivitySelectedPopup
v-show=
"showActivitySelectedPopup && selectedActivityList.length > 0"
:visible=
"showActivitySelectedPopup"
:activityList=
"selectedActivityList"
@
close=
"handleCloseActivityPopup"
@
viewActivity=
"handleViewActivity"
/>
</view>
</
template
>
<
script
setup
>
...
...
@@ -71,13 +86,12 @@ import TaskPop from '@/components/renwu/TaskPop.vue';
import
TaskPerson
from
'@/components/renwu/TaskPerson.vue'
;
import
TaskCompleteTips
from
'@/components/renwu/TaskCompleteTips.vue'
;
import
ActivitySelectedPopup
from
'@/components/ActivitySelectedPopup.vue'
;
import
GongzhonghaoPop
from
'@/components/renwu/GongzhonghaoPop.vue'
;
import
{
useGlobalStore
}
from
'@/stores/global.js'
;
import
{
useUserStore
}
from
'@/stores/user.js'
;
import
{
useIntegralStore
}
from
'@/stores/integral'
;
import
{
jump
,
JumpType
}
from
'../../utils'
;
import
{
taskCompleteJSON
}
from
'../../api/integral'
;
import
{
fetchUserClickActivity
}
from
'../../api/home'
;
import
{
useIntegralStore
}
from
'@/stores/integral'
;
import
GongzhonghaoPop
from
'@/components/renwu/GongzhonghaoPop.vue'
;
const
globalStore
=
useGlobalStore
();
const
userStore
=
useUserStore
();
...
...
@@ -243,105 +257,21 @@ onShow(async () => {
if
(
taskId
.
value
>
0
)
{
await
handleTaskComplete
(
taskId
.
value
);
}
});
onLoad
((
options
)
=>
{
const
optionsSync
=
wx
.
getEnterOptionsSync
();
if
(
optionsSync
.
scene
==
'1154'
)
{
globalStore
.
setIsWxFriendCircle
(
true
);
}
// 加载会员信息,确保能正确判断手机号授权状态
// 页面显示时,如果已登录,刷新会员信息并检查活动入选
if
(
userStore
.
isLogin
)
{
userStore
.
loadMemberInfo
();
// 查看活动
const
handleViewActivity
=
(
activity
,
index
)
=>
{
console
.
log
(
'查看活动:'
,
activity
,
index
)
// 接口调用已在组件内部完成,这里只需要处理跳转逻辑
// 根据 activityUri 跳转到对应页面
const
uri
=
activity
.
uri
||
activity
.
activityUri
if
(
!
uri
)
{
console
.
warn
(
'活动没有跳转地址'
)
return
}
console
.
log
(
'跳转到活动页面:'
,
uri
)
// 判断跳转类型
// H5 链接
jump
({
type
:
JumpType
.
H5
,
url
:
uri
})
}
}
})
// 显示活动入选弹窗
const
showActivitySelectedPopupFunc
=
(
activityList
)
=>
{
selectedActivityList
.
value
=
activityList
||
[]
showActivitySelectedPopup
.
value
=
true
}
// 检查并显示活动入选弹窗
const
checkAndShowActivityPopup
=
()
=>
{
// 如果已经显示过弹窗,不再重复显示
if
(
hasShownActivityPopup
.
value
)
{
console
.
log
(
'活动入选弹窗已显示过,跳过'
)
return
}
const
memberInfo
=
userStore
.
memberInfo
console
.
log
(
'检查活动入选弹窗 - memberInfo:'
,
memberInfo
)
console
.
log
(
'检查活动入选弹窗 - passedActivityList:'
,
memberInfo
?.
passedActivityList
)
if
(
memberInfo
&&
memberInfo
.
passedActivityList
&&
memberInfo
.
passedActivityList
.
length
>
0
)
{
// 将 passedActivityList 转换为组件需要的格式
const
activityList
=
memberInfo
.
passedActivityList
.
map
(
item
=>
({
id
:
item
.
activityId
,
name
:
item
.
activityName
,
uri
:
item
.
activityUri
,
disabled
:
false
}))
console
.
log
(
'转换后的活动列表:'
,
activityList
)
selectedActivityList
.
value
=
activityList
showActivitySelectedPopup
.
value
=
true
hasShownActivityPopup
.
value
=
true
// 标记已显示
console
.
log
(
'显示活动入选弹窗:'
,
activityList
)
}
else
{
console
.
log
(
'没有活动入选数据,不显示弹窗'
)
}
}
// 监听 memberInfo 变化,检查是否有 passedActivityList
watch
(()
=>
userStore
.
memberInfo
,
(
newVal
,
oldVal
)
=>
{
if
(
newVal
&&
newVal
.
passedActivityList
&&
newVal
.
passedActivityList
.
length
>
0
)
{
// 检查是否是新的活动列表(通过比较 activityId 来判断)
const
oldActivityIds
=
oldVal
?.
passedActivityList
?.
map
(
item
=>
item
.
activityId
)
||
[]
const
newActivityIds
=
newVal
.
passedActivityList
.
map
(
item
=>
item
.
activityId
)
// 如果有新的活动,重置标记并显示弹窗
const
hasNewActivity
=
newActivityIds
.
some
(
id
=>
!
oldActivityIds
.
includes
(
id
))
if
(
hasNewActivity
)
{
hasShownActivityPopup
.
value
=
false
}
// 延迟一下,确保页面已经渲染完成
setTimeout
(()
=>
{
checkAndShowActivityPopup
()
},
300
)
await
userStore
.
loadMemberInfo
()
await
nextTick
()
checkAndShowActivityPopup
()
}
}
,
{
deep
:
true
})
}
);
onLoad
(
async
(
options
)
=>
{
const
optionsSync
=
wx
.
getEnterOptionsSync
()
const
optionsSync
=
wx
.
getEnterOptionsSync
()
;
if
(
optionsSync
.
scene
==
'1154'
)
{
globalStore
.
setIsWxFriendCircle
(
true
)
globalStore
.
setIsWxFriendCircle
(
true
);
}
if
(
optionsSync
.
scene
==
'1069'
)
{
isBackApp
.
value
=
true
;
}
else
{
...
...
@@ -382,17 +312,11 @@ onLoad(async (options) => {
// 加载会员信息,检查是否有活动入选
if
(
userStore
.
isLogin
)
{
await
userStore
.
loadMemberInfo
()
await
nextTick
()
checkAndShowActivityPopup
()
}
});
onShow
(
async
()
=>
{
// 页面显示时,如果已登录,刷新会员信息(但不强制显示弹窗,由 watch 监听处理)
if
(
userStore
.
isLogin
)
{
await
userStore
.
loadMemberInfo
()
}
});
onShareAppMessage
(()
=>
{
const
pageType
=
globalStore
.
curTabIndex
;
return
shareOptions
[
pageType
]
||
shareOptions
[
0
];
...
...
@@ -407,6 +331,65 @@ onPageScroll((e) => {
scrollTop
.
value
=
e
.
scrollTop
;
});
// 处理活动点击
const
handleViewActivity
=
(
activity
,
index
)
=>
{
// 接口调用已在组件内部完成,这里只需要处理跳转逻辑
const
activityCount
=
selectedActivityList
.
value
.
length
if
(
activityCount
===
1
)
{
// 1个活动:跳转到详情页(使用接口返回的 activityUri)
const
uri
=
activity
.
activityUri
if
(
!
uri
)
{
console
.
warn
(
'活动没有跳转地址'
)
return
}
jump
({
type
:
JumpType
.
H5
,
url
:
uri
})
}
else
{
jump
({
type
:
JumpType
.
INNER
,
url
:
'subPackages/momclub/actList?type=2'
})
}
}
// 处理关闭活动弹窗
const
handleCloseActivityPopup
=
()
=>
{
showActivitySelectedPopup
.
value
=
false
}
// 检查并显示活动入选弹窗
const
checkAndShowActivityPopup
=
()
=>
{
const
memberInfo
=
userStore
.
memberInfo
if
(
memberInfo
&&
memberInfo
.
passedActivityList
&&
Array
.
isArray
(
memberInfo
.
passedActivityList
)
&&
memberInfo
.
passedActivityList
.
length
>
0
)
{
// 将 passedActivityList 转换为组件需要的格式
const
activityList
=
memberInfo
.
passedActivityList
.
map
(
item
=>
({
id
:
item
.
activityId
,
name
:
item
.
activityName
,
uri
:
item
.
activityUri
,
disabled
:
false
}))
selectedActivityList
.
value
=
activityList
showActivitySelectedPopup
.
value
=
true
}
else
{
// 没有数据时隐藏弹窗
showActivitySelectedPopup
.
value
=
false
selectedActivityList
.
value
=
[]
}
}
// 监听 memberInfo 变化,检查是否有 passedActivityList
watch
(()
=>
userStore
.
memberInfo
,
()
=>
{
nextTick
(()
=>
{
checkAndShowActivityPopup
()
})
},
{
deep
:
true
})
// 页面显示时检查会员信息
// onShow(() => {
// if (userStore.isLogin) {
...
...
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