150 lines
5.1 KiB
Vue
150 lines
5.1 KiB
Vue
<template>
|
|
<view class="profile-page" :style="{ paddingTop: navBarHeight + 'px' }">
|
|
<view class="profile-page__nav" :style="{ paddingTop: statusBarHeight + 'px' }">
|
|
<view class="profile-page__nav-title">我的</view>
|
|
</view>
|
|
|
|
<!-- User card -->
|
|
<UserCard :logged-in="loggedIn" :has-profile="hasProfile" :user="user" :memberships="memberships" :now="membershipNow"
|
|
:memberships-loading="membershipsLoading" :memberships-loaded="membershipsLoaded" :memberships-error="membershipsError"
|
|
:loading="loginLoading" @login="handleLogin" @edit="goToInfo" @refresh-memberships="userStore.fetchMemberships()" />
|
|
|
|
<InviteCard />
|
|
|
|
<!-- Menu section: always visible -->
|
|
<ProfileMenu
|
|
:is-admin="isAdmin"
|
|
:require-auth="loggedIn"
|
|
@clear-cache="handleClearCache"
|
|
@require-login="handleLogin"
|
|
@open-notifications="showNotificationsModal = true"
|
|
>
|
|
<PracticeActivityCard v-if="loggedIn" :key="userStore.token" :refresh-key="activityRefreshKey" />
|
|
</ProfileMenu>
|
|
|
|
<!-- Logout button: only when logged in -->
|
|
<view v-if="loggedIn" class="profile-page__logout-wrap">
|
|
<button class="profile-page__logout-btn" @tap="handleLogout">退出登录</button>
|
|
</view>
|
|
|
|
<!-- Notification Settings Modal -->
|
|
<SubscriptionSettingsModal v-model:visible="showNotificationsModal" />
|
|
</view>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import InviteCard from '../../components/InviteCard.vue'
|
|
import { useInviteStore } from '../../stores/invite'
|
|
import { ref, onMounted } from 'vue'
|
|
import { onShow, onShareAppMessage, onShareTimeline } from '@dcloudio/uni-app'
|
|
import { storeToRefs } from 'pinia'
|
|
import { useUserStore } from '../../stores/user'
|
|
import { getSystemLayout } from '../../utils/system'
|
|
import { getErrorMessage } from '../../utils/auth'
|
|
import PracticeActivityCard from '../../components/PracticeActivityCard.vue'
|
|
import UserCard from '../../components/UserCard.vue'
|
|
import ProfileMenu from '../../components/ProfileMenu.vue'
|
|
import SubscriptionSettingsModal from '../../components/SubscriptionSettingsModal.vue'
|
|
|
|
const invite = useInviteStore()
|
|
const userStore = useUserStore()
|
|
const { loggedIn, hasProfile, user, memberships, membershipsLoading, membershipsLoaded, membershipsError, isAdmin } = storeToRefs(userStore)
|
|
|
|
const showNotificationsModal = ref(false)
|
|
const activityRefreshKey = ref(0)
|
|
const membershipNow = ref(Date.now())
|
|
const loginLoading = ref(false)
|
|
const navBarHeight = ref(getSystemLayout().navBarHeight)
|
|
const statusBarHeight = getSystemLayout().statusBarHeight
|
|
|
|
// ─── 微信分享 ───────────────────────────────────────────────
|
|
onShareAppMessage(() => {
|
|
return {
|
|
title: invite.code ? '送你 95 折购卡礼,一起练普拉提' : '一起练普拉提',
|
|
path: invite.code ? `/pages/card/detail?showAll=1&inviteCode=${invite.code}` : '/pages/home/index',
|
|
imageUrl: '',
|
|
}
|
|
})
|
|
|
|
onShareTimeline(() => {
|
|
return {
|
|
title: '我的普拉提会所,记录每一次进步',
|
|
query: '',
|
|
}
|
|
})
|
|
|
|
onMounted(() => {
|
|
navBarHeight.value = getSystemLayout().navBarHeight
|
|
})
|
|
|
|
onShow(async () => {
|
|
membershipNow.value = Date.now()
|
|
activityRefreshKey.value += 1
|
|
if (loggedIn.value) {
|
|
await Promise.all([
|
|
invite.refresh().catch(() => {}),
|
|
invite.refreshActivity().catch(() => {}),
|
|
userStore.fetchProfile(),
|
|
userStore.fetchMemberships(),
|
|
])
|
|
}
|
|
})
|
|
|
|
async function handleLogin() {
|
|
if (loginLoading.value) return
|
|
loginLoading.value = true
|
|
try {
|
|
const { isNewUser } = await userStore.loginWithSetup()
|
|
if (!isNewUser) {
|
|
await invite.refreshActivity().catch(() => {})
|
|
}
|
|
} catch (err: unknown) {
|
|
uni.showToast({ title: getErrorMessage(err, '登录失败,请重试'), icon: 'none' })
|
|
} finally {
|
|
loginLoading.value = false
|
|
}
|
|
}
|
|
|
|
function goToInfo() {
|
|
uni.navigateTo({ url: '/pages/profile/info' })
|
|
}
|
|
|
|
function handleLogout() {
|
|
uni.showModal({
|
|
title: '退出登录',
|
|
content: '确定要退出登录吗?',
|
|
confirmText: '退出',
|
|
confirmColor: '#9c7a6e',
|
|
success(res) {
|
|
if (res.confirm) {
|
|
userStore.logout()
|
|
}
|
|
},
|
|
})
|
|
}
|
|
|
|
function handleClearCache() {
|
|
uni.showModal({
|
|
title: '清除缓存',
|
|
content: '确定要清除本地缓存数据吗?',
|
|
success(res) {
|
|
if (res.confirm) {
|
|
uni.clearStorageSync()
|
|
uni.showToast({ title: '缓存已清除', icon: 'success' })
|
|
}
|
|
},
|
|
})
|
|
}
|
|
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.profile-page {
|
|
min-height: 100vh; box-sizing: border-box; background: #fbf9f6; padding-bottom: 36rpx;
|
|
&__nav { position: fixed; top: 0; left: 0; right: 0; z-index: 101; background: #fbf9f6; }
|
|
&__nav-title { height: 88rpx; display: flex; align-items: center; justify-content: center; font-size: 34rpx; font-weight: 500; color: #514943; }
|
|
&__logout-wrap { margin: 28rpx 32rpx 0; }
|
|
&__logout-btn { width: 100%; height: 80rpx; line-height: 80rpx; padding: 0; margin: 0; border: none; border-radius: 24rpx; background: #f2ede7; color: #91766a; font-size: 25rpx; font-weight: 400; &::after { border: none; } }
|
|
}
|
|
</style>
|