131 lines
3.6 KiB
Vue
131 lines
3.6 KiB
Vue
<template>
|
||
<view class="profile-menu">
|
||
<slot />
|
||
|
||
<view class="profile-menu__links">
|
||
<template v-for="item in menuItems" :key="item.key">
|
||
<view v-if="item.type === 'separator'" class="profile-menu__separator" />
|
||
<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)">
|
||
<text class="profile-menu__title">{{ item.title }}</text>
|
||
<text class="profile-menu__arrow">›</text>
|
||
</view>
|
||
</template>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { computed } from 'vue'
|
||
|
||
interface MenuItem {
|
||
key: string
|
||
type: 'item' | 'separator'
|
||
title?: string
|
||
path?: string
|
||
isAdmin?: boolean
|
||
action?: 'clear' | 'notifications'
|
||
requireAuth?: boolean
|
||
}
|
||
|
||
const props = defineProps<{
|
||
isAdmin: boolean
|
||
requireAuth?: boolean
|
||
}>()
|
||
|
||
const emit = defineEmits<{
|
||
(e: 'clear-cache'): void
|
||
(e: 'require-login'): void
|
||
(e: 'open-notifications'): void
|
||
}>()
|
||
|
||
const menuItems = computed<MenuItem[]>(() => {
|
||
const items: MenuItem[] = [
|
||
{ key: 'shop-orders', type: 'item', title: '我的商品订单', path: '/pages/shop/orders', requireAuth: true },
|
||
{ key: 'progress', type: 'item', title: '我的成长档案', path: '/pages/profile/progress', requireAuth: true },
|
||
{ key: 'portrait', type: 'item', title: '身体状态评估', path: '/pages/portrait/index' },
|
||
{ key: 'plan', type: 'item', title: '我的改善计划', path: '/pages/portrait/plan', requireAuth: true },
|
||
...(props.isAdmin
|
||
? [{
|
||
key: 'teaching-schedule',
|
||
type: 'item' as const,
|
||
title: '我的课表',
|
||
path: '/pages/profile/teaching-schedule',
|
||
requireAuth: true,
|
||
}]
|
||
: []),
|
||
{
|
||
key: 'bookings',
|
||
type: 'item',
|
||
title: '我的预约',
|
||
path: '/pages/profile/bookings',
|
||
requireAuth: true,
|
||
},
|
||
{
|
||
key: 'info',
|
||
type: 'item',
|
||
title: '个人信息',
|
||
path: '/pages/profile/info',
|
||
requireAuth: true,
|
||
},
|
||
{
|
||
key: 'notifications',
|
||
type: 'item',
|
||
title: '消息提醒设置',
|
||
action: 'notifications',
|
||
requireAuth: true,
|
||
},
|
||
{
|
||
key: 'sep1',
|
||
type: 'separator',
|
||
},
|
||
{
|
||
key: 'clear',
|
||
type: 'item',
|
||
title: '清除缓存',
|
||
action: 'clear',
|
||
},
|
||
]
|
||
|
||
if (props.isAdmin) {
|
||
items.push({ key: 'sep2', type: 'separator' })
|
||
items.push({
|
||
key: 'admin',
|
||
type: 'item',
|
||
title: '管理中心',
|
||
path: '/pages/admin/index',
|
||
isAdmin: true,
|
||
requireAuth: true,
|
||
})
|
||
}
|
||
|
||
return items
|
||
})
|
||
|
||
function handleTap(item: MenuItem) {
|
||
if (item.requireAuth && !props.requireAuth) {
|
||
emit('require-login')
|
||
return
|
||
}
|
||
if (item.action === 'clear') {
|
||
emit('clear-cache')
|
||
} else if (item.action === 'notifications') {
|
||
emit('open-notifications')
|
||
} else if (item.path) {
|
||
uni.navigateTo({ url: item.path })
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.profile-menu {
|
||
&__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--hover { background: #f4f1ec; }
|
||
&__item--admin { background: #eff3ed; .profile-menu__title { color: #617d73; } }
|
||
&__title { flex: 1; font-size: 27rpx; font-weight: 400; color: #6f655e; }
|
||
&__arrow { font-size: 30rpx; color: #b2a79e; line-height: 1; }
|
||
&__separator { height: 12rpx; background: #fbf9f6; }
|
||
}
|
||
</style>
|