refactor: 调整 admin 目录结构并精简个人中心快捷区

- 将 admin 相关的 store/utils 移入对应子目录(pages/admin/stores、pages/admin/utils)
- 更新 manifest.json、pages.json 路由与配置
- 个人中心 ProfileMenu 移除顶部「我的会员卡 / 我的预约」快捷卡片,与 UserCard 会员卡入口合并
- 「我的预约」下移至菜单列表,紧邻「个人信息」
- 清理 profile/index.vue 中不再使用的 bookingStore / 计算属性 / 透传
This commit is contained in:
richarjiang
2026-09-09 14:36:34 +08:00
parent 57107c02dc
commit 75ef5e94a6
22 changed files with 138 additions and 183 deletions

View File

@@ -1,21 +1,9 @@
<template> <template>
<view class="profile-menu"> <view class="profile-menu">
<view class="profile-menu__shortcuts">
<view v-for="item in primaryItems" :key="item.key" class="profile-menu__shortcut"
hover-class="profile-menu__item--hover" @tap="handleTap(item)">
<view class="profile-menu__shortcut-head">
<view class="profile-menu__icon" :class="'profile-menu__icon--' + item.key" />
<text class="profile-menu__arrow"></text>
</view>
<text class="profile-menu__shortcut-title">{{ item.title }}</text>
<text class="profile-menu__shortcut-note">{{ !requireAuth ? '登录后查看' : item.key === 'membership' ? `${activeMembershipCount || 0} 张可用` : `${upcomingBookingCount || 0} 节待上` }}</text>
</view>
</view>
<slot /> <slot />
<view class="profile-menu__links"> <view class="profile-menu__links">
<template v-for="item in secondaryItems" :key="item.key"> <template v-for="item in menuItems" :key="item.key">
<view v-if="item.type === 'separator'" class="profile-menu__separator" /> <view v-if="item.type === 'separator'" class="profile-menu__separator" />
<view v-else class="profile-menu__item" :class="{ 'profile-menu__item--admin': item.isAdmin }" <view v-else class="profile-menu__item" :class="{ 'profile-menu__item--admin': item.isAdmin }"
hover-class="profile-menu__item--hover" hover-stay-time="150" @tap="handleTap(item)"> hover-class="profile-menu__item--hover" hover-stay-time="150" @tap="handleTap(item)">
@@ -36,7 +24,6 @@ interface MenuItem {
title?: string title?: string
path?: string path?: string
isAdmin?: boolean isAdmin?: boolean
badge?: string
action?: 'clear' action?: 'clear'
requireAuth?: boolean requireAuth?: boolean
} }
@@ -44,9 +31,6 @@ interface MenuItem {
const props = defineProps<{ const props = defineProps<{
isAdmin: boolean isAdmin: boolean
requireAuth?: boolean requireAuth?: boolean
activeMembershipCount?: number
upcomingBookingCount?: number
inviteShareEligible?: boolean
}>() }>()
const emit = defineEmits<{ const emit = defineEmits<{
@@ -55,30 +39,7 @@ const emit = defineEmits<{
}>() }>()
const menuItems = computed<MenuItem[]>(() => { const menuItems = computed<MenuItem[]>(() => {
const membershipBadge = props.activeMembershipCount && props.activeMembershipCount > 0
? `${props.activeMembershipCount}`
: undefined
const bookingBadge = props.upcomingBookingCount && props.upcomingBookingCount > 0
? `${props.upcomingBookingCount}`
: undefined
const items: MenuItem[] = [ const items: MenuItem[] = [
{
key: 'membership',
type: 'item',
title: '我的会员卡',
path: '/pages/profile/membership',
badge: membershipBadge,
requireAuth: true,
},
{
key: 'bookings',
type: 'item',
title: '我的预约',
path: '/pages/profile/bookings',
badge: bookingBadge,
requireAuth: true,
},
...(props.isAdmin ...(props.isAdmin
? [{ ? [{
key: 'teaching-schedule', key: 'teaching-schedule',
@@ -88,16 +49,13 @@ const menuItems = computed<MenuItem[]>(() => {
requireAuth: true, requireAuth: true,
}] }]
: []), : []),
// 临时隐藏邀请好友入口,后续恢复时直接取消这段注释即可。 {
// ...(props.inviteShareEligible key: 'bookings',
// ? [{ type: 'item',
// key: 'invite', title: '我的预约',
// type: 'item' as const, path: '/pages/profile/bookings',
// title: '邀请好友', requireAuth: true,
// path: '/pages/profile/invite', },
// requireAuth: true,
// }]
// : []),
{ {
key: 'info', key: 'info',
type: 'item', type: 'item',
@@ -132,9 +90,6 @@ const menuItems = computed<MenuItem[]>(() => {
return items return items
}) })
const primaryItems = computed(() => menuItems.value.filter(item => item.key === 'membership' || item.key === 'bookings'))
const secondaryItems = computed(() => menuItems.value.filter(item => item.key !== 'membership' && item.key !== 'bookings'))
function handleTap(item: MenuItem) { function handleTap(item: MenuItem) {
if (item.requireAuth && !props.requireAuth) { if (item.requireAuth && !props.requireAuth) {
emit('require-login') emit('require-login')
@@ -150,14 +105,6 @@ function handleTap(item: MenuItem) {
<style lang="scss" scoped> <style lang="scss" scoped>
.profile-menu { .profile-menu {
&__shortcuts { display: flex; gap: 20rpx; margin: 24rpx 32rpx 0; }
&__shortcut { flex: 1; min-width: 0; padding: 24rpx; box-sizing: border-box; border-radius: 26rpx; background: #fff; border: 1rpx solid #eee8e3; }
&__shortcut-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 16rpx; }
&__shortcut-title { display: block; font-size: 27rpx; font-weight: 500; color: #514943; }
&__shortcut-note { display: block; font-size: 22rpx; color: #8b817b; margin-top: 8rpx; }
&__icon { width: 36rpx; height: 30rpx; position: relative; box-sizing: border-box; border: 2rpx solid #9b8878; border-radius: 6rpx; }
&__icon--membership::after { content: ''; position: absolute; top: 8rpx; left: 0; right: 0; border-top: 2rpx solid #9b8878; }
&__icon--bookings { border-color: #829a8b; border-top-width: 7rpx; &::after { content: ''; position: absolute; left: 8rpx; top: 8rpx; width: 12rpx; border-top: 2rpx solid #829a8b; } }
&__links { margin: 24rpx 32rpx 0; border-radius: 26rpx; background: #fff; overflow: hidden; } &__links { margin: 24rpx 32rpx 0; border-radius: 26rpx; background: #fff; overflow: hidden; }
&__item { display: flex; align-items: center; gap: 20rpx; min-height: 96rpx; padding: 0 28rpx; box-sizing: border-box; border-bottom: 1rpx solid #f2ede8; &:last-child { border-bottom: none; } } &__item { display: flex; align-items: center; gap: 20rpx; min-height: 96rpx; padding: 0 28rpx; box-sizing: border-box; border-bottom: 1rpx solid #f2ede8; &:last-child { border-bottom: none; } }
&__item--hover { background: #f4f1ec; } &__item--hover { background: #f4f1ec; }

View File

@@ -13,6 +13,10 @@
"minified": true "minified": true
}, },
"usingComponents": true, "usingComponents": true,
"lazyCodeLoading": "requiredComponents",
"optimization": {
"subPackages": true
},
"permission": { "permission": {
"scope.userLocation": { "scope.userLocation": {
"desc": "用于获取工作室位置导航" "desc": "用于获取工作室位置导航"

View File

@@ -12,13 +12,19 @@
{ {
"path": "pages/booking/index", "path": "pages/booking/index",
"style": { "style": {
"navigationStyle": "custom" "navigationStyle": "custom",
"componentPlaceholder": {
"booking-confirm-popup": "view"
}
} }
}, },
{ {
"path": "pages/booking/detail", "path": "pages/booking/detail",
"style": { "style": {
"navigationStyle": "custom" "navigationStyle": "custom",
"componentPlaceholder": {
"booking-confirm-popup": "view"
}
} }
}, },
{ {
@@ -69,83 +75,6 @@
"navigationStyle": "custom" "navigationStyle": "custom"
} }
}, },
{
"path": "pages/admin/index",
"style": {
"navigationStyle": "custom"
}
},
{ "path": "pages/admin/analytics", "style": { "navigationStyle": "custom", "enablePullDownRefresh": true } },
{
"path": "pages/admin/bookings",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/admin/schedule",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/admin/slot-adjust",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/admin/members",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/admin/member-detail",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/admin/member-edit",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/admin/member-supplement",
"style": { "navigationStyle": "custom" }
},
{
"path": "pages/admin/member-arrange",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/admin/orders",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/admin/card-types",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/admin/studio",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/admin/flash-sales",
"style": {
"navigationStyle": "custom"
}
},
{ {
"path": "pages/flash-sale/detail", "path": "pages/flash-sale/detail",
"style": { "style": {
@@ -153,6 +82,98 @@
} }
} }
], ],
"subPackages": [
{
"root": "pages/admin",
"pages": [
{
"path": "index",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "analytics",
"style": {
"navigationStyle": "custom",
"enablePullDownRefresh": true
}
},
{
"path": "bookings",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "schedule",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "slot-adjust",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "members",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "member-detail",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "member-edit",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "member-supplement",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "member-arrange",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "orders",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "card-types",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "studio",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "flash-sales",
"style": {
"navigationStyle": "custom"
}
}
]
}
],
"globalStyle": { "globalStyle": {
"navigationBarTextStyle": "black", "navigationBarTextStyle": "black",
"navigationBarTitleText": "普拉提约课", "navigationBarTitleText": "普拉提约课",

View File

@@ -103,7 +103,7 @@ import { onShow, onPullDownRefresh } from '@dcloudio/uni-app'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import type { TeachingAnalytics } from '@mp-pilates/shared' import type { TeachingAnalytics } from '@mp-pilates/shared'
import CustomNavBar from '../../components/CustomNavBar.vue' import CustomNavBar from '../../components/CustomNavBar.vue'
import { useAdminStore } from '../../stores/admin' import { useAdminStore } from './stores/admin'
import { useUserStore } from '../../stores/user' import { useUserStore } from '../../stores/user'
import { getSystemLayout } from '../../utils/system' import { getSystemLayout } from '../../utils/system'
import { getErrorMessage } from '../../utils/auth' import { getErrorMessage } from '../../utils/auth'

View File

@@ -239,9 +239,9 @@
import { ref, onMounted } from 'vue' import { ref, onMounted } from 'vue'
import CustomNavBar from '../../components/CustomNavBar.vue' import CustomNavBar from '../../components/CustomNavBar.vue'
import { getSystemLayout } from '../../utils/system' import { getSystemLayout } from '../../utils/system'
import { useAdminStore } from '../../stores/admin' import { useAdminStore } from './stores/admin'
import { formatPrice } from '../../utils/format' import { formatPrice } from '../../utils/format'
import { uploadStudioAsset } from '../../utils/studio-upload' import { uploadStudioAsset } from './utils/studio-upload'
import { CardTypeCategory } from '@mp-pilates/shared' import { CardTypeCategory } from '@mp-pilates/shared'
import type { CardType } from '@mp-pilates/shared' import type { CardType } from '@mp-pilates/shared'

View File

@@ -264,7 +264,7 @@
import { ref, onMounted, computed } from 'vue' import { ref, onMounted, computed } from 'vue'
import CustomNavBar from '../../components/CustomNavBar.vue' import CustomNavBar from '../../components/CustomNavBar.vue'
import { getSystemLayout } from '../../utils/system' import { getSystemLayout } from '../../utils/system'
import { useAdminStore } from '../../stores/admin' import { useAdminStore } from './stores/admin'
import { formatPrice, formatDateTime, getFlashSalePhaseLabel, getStockPercent, formatDateLocal, formatTimeLocal } from '../../utils/format' import { formatPrice, formatDateTime, getFlashSalePhaseLabel, getStockPercent, formatDateLocal, formatTimeLocal } from '../../utils/format'
import { FlashSaleStatus, FlashSalePhase } from '@mp-pilates/shared' import { FlashSaleStatus, FlashSalePhase } from '@mp-pilates/shared'
import type { FlashSaleAdminItem, CardType } from '@mp-pilates/shared' import type { FlashSaleAdminItem, CardType } from '@mp-pilates/shared'

View File

@@ -190,9 +190,9 @@ import { ref, onMounted } from 'vue'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import CustomNavBar from '../../components/CustomNavBar.vue' import CustomNavBar from '../../components/CustomNavBar.vue'
import { getSystemLayout } from '../../utils/system' import { getSystemLayout } from '../../utils/system'
import { useAdminStore } from '../../stores/admin' import { useAdminStore } from './stores/admin'
import { useUserStore } from '../../stores/user' import { useUserStore } from '../../stores/user'
import type { AdminStats } from '../../stores/admin' import type { AdminStats } from './stores/admin'
import { requestAdminBookingSubscriptionCount } from '../../utils/wechat-subscription' import { requestAdminBookingSubscriptionCount } from '../../utils/wechat-subscription'
import { getErrorMessage } from '../../utils/auth' import { getErrorMessage } from '../../utils/auth'

View File

@@ -115,7 +115,7 @@ import TimePeriodFilter from '../../components/TimePeriodFilter.vue'
import { getSystemLayout } from '../../utils/system' import { getSystemLayout } from '../../utils/system'
import { formatDate, isSlotPast } from '../../utils/format' import { formatDate, isSlotPast } from '../../utils/format'
import { getErrorMessage } from '../../utils/auth' import { getErrorMessage } from '../../utils/auth'
import { useAdminStore } from '../../stores/admin' import { useAdminStore } from './stores/admin'
type PeriodKey = keyof typeof TIME_PERIODS | null type PeriodKey = keyof typeof TIME_PERIODS | null

View File

@@ -170,7 +170,7 @@ import {
} from '../../utils/format' } from '../../utils/format'
import { BOOKING_STATUS_LABELS } from '../../utils/booking-helpers' import { BOOKING_STATUS_LABELS } from '../../utils/booking-helpers'
import { getErrorMessage } from '../../utils/auth' import { getErrorMessage } from '../../utils/auth'
import { useAdminStore } from '../../stores/admin' import { useAdminStore } from './stores/admin'
const adminStore = useAdminStore() const adminStore = useAdminStore()
const navBarHeight = ref('64px') const navBarHeight = ref('64px')

View File

@@ -111,7 +111,7 @@ import CustomNavBar from '../../components/CustomNavBar.vue'
import { getSystemLayout } from '../../utils/system' import { getSystemLayout } from '../../utils/system'
import { formatDateLocal } from '../../utils/format' import { formatDateLocal } from '../../utils/format'
import { getErrorMessage } from '../../utils/auth' import { getErrorMessage } from '../../utils/auth'
import { useAdminStore } from '../../stores/admin' import { useAdminStore } from './stores/admin'
const adminStore = useAdminStore() const adminStore = useAdminStore()
const navBarHeight = ref('64px') const navBarHeight = ref('64px')

View File

@@ -60,7 +60,7 @@ import { onLoad } from '@dcloudio/uni-app'
import type { AdminMemberDetail, CreateLessonSupplementDto, LessonSupplementRecord } from '@mp-pilates/shared' import type { AdminMemberDetail, CreateLessonSupplementDto, LessonSupplementRecord } from '@mp-pilates/shared'
import CustomNavBar from '../../components/CustomNavBar.vue' import CustomNavBar from '../../components/CustomNavBar.vue'
import LessonSupplementList from '../../components/LessonSupplementList.vue' import LessonSupplementList from '../../components/LessonSupplementList.vue'
import { useAdminStore } from '../../stores/admin' import { useAdminStore } from './stores/admin'
import { getSystemLayout } from '../../utils/system' import { getSystemLayout } from '../../utils/system'
import { HttpRequestError } from '../../utils/request' import { HttpRequestError } from '../../utils/request'
import { getErrorMessage } from '../../utils/auth' import { getErrorMessage } from '../../utils/auth'

View File

@@ -103,8 +103,8 @@ import { onReachBottom, onShow } from '@dcloudio/uni-app'
import CustomNavBar from '../../components/CustomNavBar.vue' import CustomNavBar from '../../components/CustomNavBar.vue'
import { getSystemLayout } from '../../utils/system' import { getSystemLayout } from '../../utils/system'
import { getCardTypeLabel } from '../../utils/format' import { getCardTypeLabel } from '../../utils/format'
import { useAdminStore } from '../../stores/admin' import { useAdminStore } from './stores/admin'
import type { MemberSummary } from '../../stores/admin' import type { MemberSummary } from './stores/admin'
const adminStore = useAdminStore() const adminStore = useAdminStore()

View File

@@ -137,7 +137,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, computed, onMounted } from 'vue' import { ref, computed, onMounted } from 'vue'
import CustomNavBar from '../../components/CustomNavBar.vue' import CustomNavBar from '../../components/CustomNavBar.vue'
import { useAdminStore } from '../../stores/admin' import { useAdminStore } from './stores/admin'
import { formatPrice, formatDateTime } from '../../utils/format' import { formatPrice, formatDateTime } from '../../utils/format'
import { OrderStatus } from '@mp-pilates/shared' import { OrderStatus } from '@mp-pilates/shared'
import type { OrderWithDetails } from '@mp-pilates/shared' import type { OrderWithDetails } from '@mp-pilates/shared'

View File

@@ -162,7 +162,7 @@ import { ref, computed, onMounted } from 'vue'
import type { ScheduleSlotPreview } from '@mp-pilates/shared' import type { ScheduleSlotPreview } from '@mp-pilates/shared'
import CustomNavBar from '../../components/CustomNavBar.vue' import CustomNavBar from '../../components/CustomNavBar.vue'
import { getSystemLayout } from '../../utils/system' import { getSystemLayout } from '../../utils/system'
import { useAdminStore } from '../../stores/admin' import { useAdminStore } from './stores/admin'
import { formatDate } from '../../utils/format' import { formatDate } from '../../utils/format'
import DateSelector from '../../components/DateSelector.vue' import DateSelector from '../../components/DateSelector.vue'
import { import {
@@ -170,7 +170,7 @@ import {
timeToPickerIndex, timeToPickerIndex,
pickerIndexToTime, pickerIndexToTime,
addOneHourCapped, addOneHourCapped,
} from '../../utils/schedule-time' } from './utils/schedule-time'
const timePickerRange = SCHEDULE_TIME_PICKER_RANGE const timePickerRange = SCHEDULE_TIME_PICKER_RANGE

View File

@@ -152,14 +152,14 @@
import { ref, onMounted } from 'vue' import { ref, onMounted } from 'vue'
import CustomNavBar from '../../components/CustomNavBar.vue' import CustomNavBar from '../../components/CustomNavBar.vue'
import { getSystemLayout } from '../../utils/system' import { getSystemLayout } from '../../utils/system'
import { useAdminStore } from '../../stores/admin' import { useAdminStore } from './stores/admin'
import { formatDate } from '../../utils/format' import { formatDate } from '../../utils/format'
import type { TimeSlot } from '@mp-pilates/shared' import type { TimeSlot } from '@mp-pilates/shared'
import { import {
SCHEDULE_TIME_PICKER_RANGE, SCHEDULE_TIME_PICKER_RANGE,
timeToPickerIndex, timeToPickerIndex,
pickerIndexToTime, pickerIndexToTime,
} from '../../utils/schedule-time' } from './utils/schedule-time'
const timePickerRange = SCHEDULE_TIME_PICKER_RANGE const timePickerRange = SCHEDULE_TIME_PICKER_RANGE

View File

@@ -1,6 +1,6 @@
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { ref } from 'vue' import { ref } from 'vue'
import { get, post, put, del } from '../utils/request' import { get, post, put, del } from '../../../utils/request'
import type { import type {
TeachingAnalytics, TeachingAnalytics,
CardType, CardType,

View File

@@ -197,9 +197,9 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, onMounted, ref } from 'vue' import { computed, onMounted, ref } from 'vue'
import CustomNavBar from '../../components/CustomNavBar.vue' import CustomNavBar from '../../components/CustomNavBar.vue'
import { useAdminStore } from '../../stores/admin' import { useAdminStore } from './stores/admin'
import { getErrorMessage } from '../../utils/auth' import { getErrorMessage } from '../../utils/auth'
import { uploadStudioAsset } from '../../utils/studio-upload' import { uploadStudioAsset } from './utils/studio-upload'
import { getSystemLayout } from '../../utils/system' import { getSystemLayout } from '../../utils/system'
type FormState = { type FormState = {

View File

@@ -179,8 +179,8 @@
</view> </view>
<BookingConfirmPopup <BookingConfirmPopup
v-if="isSlotMode" v-if="showConfirmPopup"
:visible="showConfirmPopup" :visible="true"
:time-slot="slotData" :time-slot="slotData"
:memberships="userStore.activeMemberships as MembershipWithCardType[]" :memberships="userStore.activeMemberships as MembershipWithCardType[]"
@confirm="onConfirmBooking" @confirm="onConfirmBooking"

View File

@@ -68,7 +68,8 @@
<!-- Confirm popup --> <!-- Confirm popup -->
<BookingConfirmPopup <BookingConfirmPopup
:visible="showConfirmPopup" v-if="showConfirmPopup"
:visible="true"
:time-slot="pendingSlot" :time-slot="pendingSlot"
:memberships="userStore.activeMemberships as MembershipWithCardType[]" :memberships="userStore.activeMemberships as MembershipWithCardType[]"
@confirm="onConfirmBooking" @confirm="onConfirmBooking"

View File

@@ -15,9 +15,6 @@
<ProfileMenu <ProfileMenu
:is-admin="isAdmin" :is-admin="isAdmin"
:require-auth="loggedIn" :require-auth="loggedIn"
:active-membership-count="activeMembershipCount"
:upcoming-booking-count="upcomingBookingCount"
:invite-share-eligible="!!user?.inviteShareEligible"
@clear-cache="handleClearCache" @clear-cache="handleClearCache"
@require-login="handleLogin" @require-login="handleLogin"
> >
@@ -34,11 +31,10 @@
<script setup lang="ts"> <script setup lang="ts">
import InviteCard from '../../components/InviteCard.vue' import InviteCard from '../../components/InviteCard.vue'
import { useInviteStore } from '../../stores/invite' import { useInviteStore } from '../../stores/invite'
import { ref, computed, onMounted } from 'vue' import { ref, onMounted } from 'vue'
import { onShow, onShareAppMessage, onShareTimeline } from '@dcloudio/uni-app' import { onShow, onShareAppMessage, onShareTimeline } from '@dcloudio/uni-app'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { useUserStore } from '../../stores/user' import { useUserStore } from '../../stores/user'
import { useBookingStore } from '../../stores/booking'
import { getSystemLayout } from '../../utils/system' import { getSystemLayout } from '../../utils/system'
import { getErrorMessage } from '../../utils/auth' import { getErrorMessage } from '../../utils/auth'
import PracticeActivityCard from '../../components/PracticeActivityCard.vue' import PracticeActivityCard from '../../components/PracticeActivityCard.vue'
@@ -47,9 +43,7 @@ import ProfileMenu from '../../components/ProfileMenu.vue'
const invite = useInviteStore() const invite = useInviteStore()
const userStore = useUserStore() const userStore = useUserStore()
const bookingStore = useBookingStore()
const { loggedIn, hasProfile, user, memberships, membershipsLoading, membershipsLoaded, membershipsError, isAdmin } = storeToRefs(userStore) const { loggedIn, hasProfile, user, memberships, membershipsLoading, membershipsLoaded, membershipsError, isAdmin } = storeToRefs(userStore)
const { upcomingBookings } = storeToRefs(bookingStore)
const activityRefreshKey = ref(0) const activityRefreshKey = ref(0)
const membershipNow = ref(Date.now()) const membershipNow = ref(Date.now())
@@ -57,14 +51,6 @@ const loginLoading = ref(false)
const navBarHeight = ref(getSystemLayout().navBarHeight) const navBarHeight = ref(getSystemLayout().navBarHeight)
const statusBarHeight = getSystemLayout().statusBarHeight const statusBarHeight = getSystemLayout().statusBarHeight
const activeMembershipCount = computed(
() => user.value?.activeMembershipCount ?? userStore.activeMemberships.length,
)
const upcomingBookingCount = computed(
() => (loggedIn.value ? upcomingBookings.value.length : 0),
)
// ─── 微信分享 ─────────────────────────────────────────────── // ─── 微信分享 ───────────────────────────────────────────────
onShareAppMessage(() => { onShareAppMessage(() => {
return { return {
@@ -94,7 +80,6 @@ onShow(async () => {
invite.refreshActivity().catch(() => {}), invite.refreshActivity().catch(() => {}),
userStore.fetchProfile(), userStore.fetchProfile(),
userStore.fetchMemberships(), userStore.fetchMemberships(),
bookingStore.fetchUpcomingBookings(),
]) ])
} }
}) })
@@ -105,10 +90,7 @@ async function handleLogin() {
try { try {
const { isNewUser } = await userStore.loginWithSetup() const { isNewUser } = await userStore.loginWithSetup()
if (!isNewUser) { if (!isNewUser) {
await Promise.all([ await invite.refreshActivity().catch(() => {})
invite.refreshActivity().catch(() => {}),
bookingStore.fetchUpcomingBookings(),
])
} }
} catch (err: unknown) { } catch (err: unknown) {
uni.showToast({ title: getErrorMessage(err, '登录失败,请重试'), icon: 'none' }) uni.showToast({ title: getErrorMessage(err, '登录失败,请重试'), icon: 'none' })