419 lines
14 KiB
Vue
419 lines
14 KiB
Vue
<template>
|
|
<!-- 滚动内容区域 -->
|
|
<scroll-view scroll-y class="scroll-container theme-light">
|
|
<view class="member-page">
|
|
<MemberInfoHeader
|
|
:user-info="userInfo"
|
|
:stats="stats"
|
|
:isLogin="isLogin"
|
|
@user-info="goUserInfo"
|
|
@guest-login="handleGuestLogin"
|
|
/>
|
|
<view class="member-page__body">
|
|
<view class="member-page__sections">
|
|
<MemberInfoMemberCard
|
|
:card-info="cardInfo"
|
|
@view-all="goMemberCard"
|
|
@renew="onRenewCard"
|
|
@purchase="goPurchaseCard"
|
|
/>
|
|
<MemberInfoQuickActions @action="onQuickAction" />
|
|
<MemberInfoBookingList
|
|
v-if="isLogin"
|
|
:items="bookingPreview"
|
|
@view-all="goBooking"
|
|
@item-tap="goBooking"
|
|
/>
|
|
<MemberInfoCheckInList
|
|
v-if="isLogin"
|
|
:items="checkIns"
|
|
@view-all="onCheckInViewAll"
|
|
@item-tap="onCheckInTap"
|
|
/>
|
|
<MemberInfoBodyReport
|
|
v-if="isLogin"
|
|
:report="bodyReport"
|
|
@view-history="onBodyReportHistory"
|
|
@view-report="onBodyReportView"
|
|
/>
|
|
<MemberInfoCouponPoints
|
|
v-if="isLogin"
|
|
:data="couponPoints"
|
|
@view-all="onCouponViewAll"
|
|
@use-coupon="onUseCoupon"
|
|
@redeem-points="onRedeemPoints"
|
|
/>
|
|
<MemberInfoReferral
|
|
v-if="isLogin"
|
|
:data="referral"
|
|
@view-rules="onReferralRules"
|
|
/>
|
|
<MemberInfoSettings v-if="isLogin" @setting="onSetting" />
|
|
<MemberInfoLogout v-if="isLogin" @logout="handleLogout" />
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</scroll-view>
|
|
|
|
<!-- 固定 TabBar -->
|
|
<view class="tabbar-fixed">
|
|
<TabBar />
|
|
</view>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, onMounted } from 'vue'
|
|
import { onShow } from '@dcloudio/uni-app'
|
|
import { PAGE, navigateToPage } from '@/common/constants/routes.js'
|
|
import {
|
|
loadMemberStore,
|
|
getCenterPageData,
|
|
renewMemberCard,
|
|
saveMemberStore,
|
|
getDefaultStore
|
|
} from '@/common/memberInfo/store.js'
|
|
import { login as miniappLogin, getUserInfo, getMemberDetail, getCheckInStats, updateUserInfo } from '@/api/main.js'
|
|
import { setToken, getToken, clearToken } from '@/utils/request.js'
|
|
import MemberInfoHeader from '@/components/memberInfo/MemberInfoHeader.vue'
|
|
import MemberInfoMemberCard from '@/components/memberInfo/MemberInfoMemberCard.vue'
|
|
import MemberInfoQuickActions from '@/components/memberInfo/MemberInfoQuickActions.vue'
|
|
import MemberInfoBookingList from '@/components/memberInfo/MemberInfoBookingList.vue'
|
|
import MemberInfoCheckInList from '@/components/memberInfo/MemberInfoCheckInList.vue'
|
|
import MemberInfoBodyReport from '@/components/memberInfo/MemberInfoBodyReport.vue'
|
|
import MemberInfoCouponPoints from '@/components/memberInfo/MemberInfoCouponPoints.vue'
|
|
import MemberInfoReferral from '@/components/memberInfo/MemberInfoReferral.vue'
|
|
import MemberInfoSettings from '@/components/memberInfo/MemberInfoSettings.vue'
|
|
import MemberInfoLogout from '@/components/memberInfo/MemberInfoLogout.vue'
|
|
import TabBar from '@/components/TabBar.vue'
|
|
|
|
const userInfo = ref({})
|
|
const stats = ref({})
|
|
const cardInfo = ref({})
|
|
const bookingPreview = ref([])
|
|
const checkIns = ref([])
|
|
const bodyReport = ref({})
|
|
const couponPoints = ref({})
|
|
const referral = ref({})
|
|
const loading = ref(false)
|
|
const hasActiveCard = ref(false)
|
|
const isLogin = ref(false)
|
|
|
|
// 页面加载时检查token
|
|
onMounted(() => {
|
|
const token = getToken()
|
|
const isLoginStorage = uni.getStorageSync('isLogin')
|
|
if (token || isLoginStorage) {
|
|
isLogin.value = true
|
|
}
|
|
})
|
|
|
|
async function fetchMemberInfo() {
|
|
if (loading.value) return
|
|
loading.value = true
|
|
console.log('[memberInfo] fetchMemberInfo 开始执行')
|
|
try {
|
|
const res = await getUserInfo({ cache: false })
|
|
console.log('[memberInfo] API返回,res =', res)
|
|
const apiData = res.data || res
|
|
console.log('[memberInfo] apiData =', apiData)
|
|
|
|
if (apiData && (apiData.nickname !== undefined || apiData.phone !== undefined || apiData.id !== undefined)) {
|
|
console.log('[memberInfo] 收到有效数据,更新store')
|
|
const store = loadMemberStore()
|
|
// 更新memberProfile
|
|
store.memberProfile = {
|
|
...store.memberProfile,
|
|
id: apiData.id,
|
|
name: apiData.nickname || apiData.name,
|
|
phone: apiData.phone,
|
|
avatar: apiData.avatar,
|
|
memberLevel: apiData.memberLevel || '普通会员'
|
|
}
|
|
// 更新profile
|
|
store.profile = {
|
|
...store.profile,
|
|
id: apiData.id,
|
|
name: apiData.nickname || apiData.name,
|
|
phone: apiData.phone,
|
|
avatar: apiData.avatar,
|
|
gender: apiData.gender,
|
|
genderDesc: apiData.genderDesc,
|
|
birthday: apiData.birthday,
|
|
height: apiData.height,
|
|
weight: apiData.weight,
|
|
hasPhone: apiData.hasPhone,
|
|
isSubscribed: apiData.isSubscribed,
|
|
memberLevel: apiData.memberLevel || '普通会员'
|
|
}
|
|
// 获取会员详细信息(会员卡、积分)
|
|
try {
|
|
const detailRes = await getMemberDetail()
|
|
console.log('[memberInfo] getMemberDetail 返回:', JSON.stringify(detailRes, null, 2))
|
|
const detailData = detailRes.data || {}
|
|
store.card = detailData.memberCards ? detailData.memberCards[0] || {} : {}
|
|
store.cardInfo = {
|
|
name: detailData.memberCards?.[0]?.memberCardName || '暂无会员卡',
|
|
type: detailData.memberCards?.[0]?.memberCardTypeDesc || '',
|
|
remainingTimes: detailData.memberCards?.[0]?.memberCardTotalTimes || 0,
|
|
status: detailData.memberCards?.[0]?.memberCardStatusDesc || ''
|
|
}
|
|
hasActiveCard.value = (detailData.activeCardCount || 0) > 0
|
|
store.stats = {
|
|
...store.stats,
|
|
pointsBalance: detailData.pointsBalance || 0
|
|
}
|
|
} catch (e) {
|
|
console.error('[memberInfo] 获取会员详情失败:', e)
|
|
}
|
|
// 获取签到统计
|
|
try {
|
|
const statsRes = await getCheckInStats()
|
|
console.log('[memberInfo] getCheckInStats 返回:', JSON.stringify(statsRes, null, 2))
|
|
const statsData = statsRes.data || {}
|
|
store.stats.checkInCount = statsData.totalCount || 0
|
|
} catch (e) {
|
|
console.error('[memberInfo] 获取签到统计失败:', e)
|
|
store.stats.checkInCount = 0
|
|
}
|
|
saveMemberStore(store)
|
|
refreshFromStore()
|
|
console.log('[memberInfo] store已更新')
|
|
} else {
|
|
console.log('[memberInfo] 未登录或数据无效,使用默认空数据')
|
|
const store = loadMemberStore()
|
|
store.memberProfile = {}
|
|
store.profile = {}
|
|
store.stats.checkInCount = 0
|
|
hasActiveCard.value = false
|
|
saveMemberStore(store)
|
|
refreshFromStore()
|
|
}
|
|
} catch (err) {
|
|
console.error('[memberInfo] 获取会员信息失败:', err)
|
|
// 失败时使用默认空数据
|
|
const store = loadMemberStore()
|
|
store.memberProfile = {}
|
|
store.profile = {}
|
|
store.stats.checkInCount = 0
|
|
hasActiveCard.value = false
|
|
saveMemberStore(store)
|
|
refreshFromStore()
|
|
} finally {
|
|
loading.value = false
|
|
console.log('[memberInfo] fetchMemberInfo 执行完成')
|
|
}
|
|
}
|
|
|
|
function refreshFromStore() {
|
|
const store = loadMemberStore()
|
|
const pageData = getCenterPageData(store)
|
|
console.log('[memberInfo] refreshFromStore - pageData.userInfo:', JSON.stringify(pageData.userInfo))
|
|
userInfo.value = pageData.userInfo
|
|
stats.value = pageData.stats
|
|
cardInfo.value = pageData.cardInfo
|
|
bookingPreview.value = pageData.bookingPreview
|
|
checkIns.value = pageData.checkIns
|
|
bodyReport.value = pageData.bodyReport
|
|
couponPoints.value = pageData.couponPoints
|
|
referral.value = pageData.referral
|
|
console.log('[memberInfo] refreshFromStore - userInfo.value:', JSON.stringify(userInfo.value))
|
|
}
|
|
|
|
function goMemberCard() {
|
|
navigateToPage(PAGE.MEMBER_CARD)
|
|
}
|
|
|
|
function goPurchaseCard() {
|
|
navigateToPage(PAGE.PURCHASE_CARD)
|
|
}
|
|
|
|
function goBooking() {
|
|
navigateToPage(PAGE.BOOKING)
|
|
}
|
|
|
|
function goUserInfo() {
|
|
navigateToPage(PAGE.USER_INFO)
|
|
}
|
|
|
|
function handleGuestLogin() {
|
|
console.log('[memberInfo] 用户点击登录区域')
|
|
uni.navigateTo({
|
|
url: '/pages/memberInfo/login'
|
|
})
|
|
}
|
|
|
|
function onRenewCard() {
|
|
uni.showModal({
|
|
title: '续费会员卡',
|
|
content: '确认续费 90 天?',
|
|
success: (res) => {
|
|
if (!res.confirm) return
|
|
const store = loadMemberStore()
|
|
renewMemberCard(store, 90)
|
|
refreshFromStore()
|
|
uni.showToast({ title: '续费成功', icon: 'success' })
|
|
}
|
|
})
|
|
}
|
|
|
|
function onQuickAction(type) {
|
|
const routes = {
|
|
booking: PAGE.COURSE_LIST,
|
|
bodyTest: PAGE.BODY_TEST_HOME,
|
|
bodyReport: PAGE.BODY_TEST_HISTORY,
|
|
trainReport: PAGE.TRAIN_REPORT,
|
|
coupon: PAGE.COUPONS,
|
|
points: PAGE.POINTS,
|
|
referral: PAGE.REFERRAL,
|
|
course: PAGE.MY_COURSES
|
|
}
|
|
if (routes[type]) {
|
|
navigateToPage(routes[type])
|
|
}
|
|
}
|
|
|
|
function onCheckInViewAll() {
|
|
navigateToPage(PAGE.CHECK_IN_HISTORY)
|
|
}
|
|
|
|
function onCheckInTap(item) {
|
|
uni.showModal({
|
|
title: item.title,
|
|
content: item.time,
|
|
showCancel: false
|
|
})
|
|
}
|
|
|
|
function onBodyReportHistory() {
|
|
navigateToPage(PAGE.BODY_TEST_HISTORY)
|
|
}
|
|
|
|
function onBodyReportView() {
|
|
const id = bodyReport.value?.recordId
|
|
const url = id
|
|
? `${PAGE.BODY_TEST_REPORT}?id=${id}`
|
|
: PAGE.BODY_TEST_HISTORY
|
|
navigateToPage(url)
|
|
}
|
|
|
|
function onCouponViewAll() {
|
|
navigateToPage(PAGE.COUPONS)
|
|
}
|
|
|
|
function onUseCoupon() {
|
|
navigateToPage(PAGE.COUPONS)
|
|
}
|
|
|
|
function onRedeemPoints() {
|
|
navigateToPage(PAGE.POINTS)
|
|
}
|
|
|
|
function onReferralRules() {
|
|
navigateToPage(PAGE.REFERRAL)
|
|
}
|
|
|
|
function onSetting(key) {
|
|
const labels = {
|
|
notify: '通知设置',
|
|
password: '修改密码',
|
|
privacy: '隐私政策',
|
|
nfc: 'NFC 门禁卡',
|
|
delete: '注销账户'
|
|
}
|
|
if (key === 'delete') {
|
|
uni.showModal({
|
|
title: '注销账户',
|
|
content: '注销后数据将无法恢复,确定继续吗?',
|
|
confirmColor: '#E74C3C'
|
|
})
|
|
return
|
|
}
|
|
if (key === 'privacy') {
|
|
uni.showModal({
|
|
title: '隐私政策',
|
|
content: '我们重视您的隐私,详细政策请前往官网查看。',
|
|
showCancel: false
|
|
})
|
|
return
|
|
}
|
|
uni.showToast({
|
|
title: `${labels[key] || '设置'}开发中`,
|
|
icon: 'none'
|
|
})
|
|
}
|
|
|
|
function handleLogout() {
|
|
uni.showModal({
|
|
title: '退出登录',
|
|
content: '确定要退出登录吗?',
|
|
success: (res) => {
|
|
if (res.confirm) {
|
|
// 清除token
|
|
clearToken()
|
|
// 重置登录状态
|
|
isLogin.value = false
|
|
// 重置store为默认状态
|
|
const defaultStore = getDefaultStore()
|
|
saveMemberStore(defaultStore)
|
|
// 重置页面数据
|
|
userInfo.value = {}
|
|
stats.value = {}
|
|
cardInfo.value = {}
|
|
bookingPreview.value = []
|
|
checkIns.value = []
|
|
bodyReport.value = {}
|
|
couponPoints.value = {}
|
|
referral.value = {}
|
|
hasActiveCard.value = false
|
|
refreshFromStore()
|
|
uni.showToast({ title: '已退出', icon: 'success' })
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
refreshFromStore()
|
|
|
|
onShow(() => {
|
|
console.log('[memberInfo] onShow 被调用')
|
|
|
|
// 检查登录状态
|
|
const token = getToken()
|
|
const isLoginStorage = uni.getStorageSync('isLogin')
|
|
if (token || isLoginStorage) {
|
|
isLogin.value = true
|
|
} else {
|
|
isLogin.value = false
|
|
}
|
|
|
|
fetchMemberInfo()
|
|
})
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
@import '@/common/style/base.css';
|
|
@import '@/common/style/memberInfo/member-info-component-reset.css';
|
|
@import '@/common/style/memberInfo/member-info-tap.css';
|
|
@import '@/common/style/memberInfo/member-info-page.css';
|
|
@import '@/common/style/memberInfo/member-info-header.css';
|
|
@import '@/common/style/memberInfo/member-info-member-card.css';
|
|
@import '@/common/style/memberInfo/member-info-quick-actions.css';
|
|
@import '@/common/style/memberInfo/member-info-booking-list.css';
|
|
@import '@/common/style/memberInfo/member-info-check-in-list.css';
|
|
@import '@/common/style/memberInfo/member-info-body-report.css';
|
|
@import '@/common/style/memberInfo/member-info-coupon-points.css';
|
|
@import '@/common/style/memberInfo/member-info-referral.css';
|
|
@import '@/common/style/memberInfo/member-info-settings.css';
|
|
@import '@/common/style/memberInfo/member-info-logout.css';
|
|
|
|
/* 固定 TabBar */
|
|
.tabbar-fixed {
|
|
position: fixed;
|
|
bottom: 0;
|
|
left: 0;
|
|
right: 0;
|
|
z-index: 1000;
|
|
background-color: transparent;
|
|
}
|
|
</style>
|