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:
@@ -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; }
|
||||||
|
|||||||
@@ -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": "用于获取工作室位置导航"
|
||||||
|
|||||||
@@ -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": "普拉提约课",
|
||||||
|
|||||||
@@ -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'
|
||||||
|
|||||||
@@ -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'
|
||||||
|
|
||||||
|
|||||||
@@ -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'
|
||||||
|
|||||||
@@ -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'
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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'
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|
||||||
|
|||||||
@@ -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'
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
@@ -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 = {
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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' })
|
||||||
|
|||||||
Reference in New Issue
Block a user