feat(导航): 替换 router-link 为 div 并添加点击事件处理
在 BottomNav.vue 中,将 router-link 替换为 div,并添加 handleNavClick 方法以处理导航点击事件。如果用户未登录且点击了“个人资料”项,则跳转到登录页面。同时,在 HomePage.vue 中,根据当前用户状态动态显示用户信息和头像。
Showing
2 changed files
with
35 additions
and
13 deletions
| 1 | +<!-- | ||
| 2 | + * @Date: 2025-03-20 20:36:36 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2025-03-21 10:20:44 | ||
| 5 | + * @FilePath: /mlaj/src/components/layout/BottomNav.vue | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | +--> | ||
| 1 | <template> | 8 | <template> |
| 2 | <nav class="fixed bottom-0 left-0 right-0 bg-white/70 backdrop-blur-lg border-t border-gray-100 z-50"> | 9 | <nav class="fixed bottom-0 left-0 right-0 bg-white/70 backdrop-blur-lg border-t border-gray-100 z-50"> |
| 3 | <div class="flex justify-around items-center h-16"> | 10 | <div class="flex justify-around items-center h-16"> |
| 4 | - <router-link | 11 | + <div |
| 5 | v-for="item in navItems" | 12 | v-for="item in navItems" |
| 6 | :key="item.name" | 13 | :key="item.name" |
| 7 | - :to="item.path" | 14 | + @click="handleNavClick(item)" |
| 8 | - class="flex flex-col items-center justify-center w-1/4 h-full" | 15 | + class="flex flex-col items-center justify-center w-1/4 h-full cursor-pointer" |
| 9 | :class="{ | 16 | :class="{ |
| 10 | 'text-green-500': isActive(item.path), | 17 | 'text-green-500': isActive(item.path), |
| 11 | 'text-gray-500': !isActive(item.path) | 18 | 'text-gray-500': !isActive(item.path) |
| ... | @@ -24,16 +31,19 @@ | ... | @@ -24,16 +31,19 @@ |
| 24 | v-html="item.icon" | 31 | v-html="item.icon" |
| 25 | /> | 32 | /> |
| 26 | <span class="text-xs">{{ item.name }}</span> | 33 | <span class="text-xs">{{ item.name }}</span> |
| 27 | - </router-link> | 34 | + </div> |
| 28 | </div> | 35 | </div> |
| 29 | </nav> | 36 | </nav> |
| 30 | </template> | 37 | </template> |
| 31 | 38 | ||
| 32 | <script setup> | 39 | <script setup> |
| 33 | import { computed } from 'vue' | 40 | import { computed } from 'vue' |
| 34 | -import { useRoute } from 'vue-router' | 41 | +import { useRoute, useRouter } from 'vue-router' |
| 42 | +import { useAuth } from '@/contexts/auth' | ||
| 35 | 43 | ||
| 36 | const route = useRoute() | 44 | const route = useRoute() |
| 45 | +const router = useRouter() | ||
| 46 | +const { currentUser } = useAuth() | ||
| 37 | 47 | ||
| 38 | const navItems = [ | 48 | const navItems = [ |
| 39 | { | 49 | { |
| ... | @@ -61,4 +71,12 @@ const navItems = [ | ... | @@ -61,4 +71,12 @@ const navItems = [ |
| 61 | const isActive = (path) => { | 71 | const isActive = (path) => { |
| 62 | return route.path === path || (path !== '/' && route.path.startsWith(path)) | 72 | return route.path === path || (path !== '/' && route.path.startsWith(path)) |
| 63 | } | 73 | } |
| 74 | + | ||
| 75 | +const handleNavClick = (item) => { | ||
| 76 | + if (item.path === '/profile' && !currentUser.value) { | ||
| 77 | + router.push('/login') | ||
| 78 | + return | ||
| 79 | + } | ||
| 80 | + router.push(item.path) | ||
| 81 | +} | ||
| 64 | </script> | 82 | </script> | ... | ... |
| ... | @@ -9,19 +9,19 @@ | ... | @@ -9,19 +9,19 @@ |
| 9 | <AppLayout title="亲子学院" :rightContent="rightContent"> | 9 | <AppLayout title="亲子学院" :rightContent="rightContent"> |
| 10 | <div class="pb-16 bg-gradient-to-b from-white via-green-50/10 to-blue-50/10"> | 10 | <div class="pb-16 bg-gradient-to-b from-white via-green-50/10 to-blue-50/10"> |
| 11 | <!-- Header Section with Welcome & Weather --> | 11 | <!-- Header Section with Welcome & Weather --> |
| 12 | - <div class="px-4 pt-3 pb-4"> | 12 | + <div v-if="currentUser" class="px-4 pt-3 pb-4"> |
| 13 | <FrostedGlass class="p-4 rounded-xl mb-4"> | 13 | <FrostedGlass class="p-4 rounded-xl mb-4"> |
| 14 | <div class="flex justify-between items-center mb-3"> | 14 | <div class="flex justify-between items-center mb-3"> |
| 15 | <div class="flex items-center"> | 15 | <div class="flex items-center"> |
| 16 | <div class="w-10 h-10 rounded-full overflow-hidden mr-3"> | 16 | <div class="w-10 h-10 rounded-full overflow-hidden mr-3"> |
| 17 | <img | 17 | <img |
| 18 | - src="https://cdn.ipadbiz.cn/mlaj/images/user-avatar-2.jpg" | 18 | + :src="currentUser.avatar" |
| 19 | - alt="王小明" | 19 | + :alt="currentUser.name" |
| 20 | class="w-full h-full object-cover" | 20 | class="w-full h-full object-cover" |
| 21 | @error="handleImageError" /> | 21 | @error="handleImageError" /> |
| 22 | </div> | 22 | </div> |
| 23 | <div> | 23 | <div> |
| 24 | - <h2 class="text-xl font-bold">欢迎回来,小明!</h2> | 24 | + <h2 class="text-xl font-bold">欢迎回来,{{ currentUser.name }}!</h2> |
| 25 | <p class="text-sm text-gray-500">{{ formatToday() }}</p> | 25 | <p class="text-sm text-gray-500">{{ formatToday() }}</p> |
| 26 | </div> | 26 | </div> |
| 27 | </div> | 27 | </div> |
| ... | @@ -489,11 +489,15 @@ import LiveStreamCard from '@/components/ui/LiveStreamCard.vue' | ... | @@ -489,11 +489,15 @@ import LiveStreamCard from '@/components/ui/LiveStreamCard.vue' |
| 489 | import ActivityCard from '@/components/ui/ActivityCard.vue' | 489 | import ActivityCard from '@/components/ui/ActivityCard.vue' |
| 490 | import SummerCampCard from '@/components/ui/SummerCampCard.vue' | 490 | import SummerCampCard from '@/components/ui/SummerCampCard.vue' |
| 491 | import { courses, liveStreams, activities, checkInTypes, userRecommendations } from '@/utils/mockData' | 491 | import { courses, liveStreams, activities, checkInTypes, userRecommendations } from '@/utils/mockData' |
| 492 | -import { useTitle } from '@vueuse/core'; | 492 | +import { useTitle } from '@vueuse/core' |
| 493 | +import { useAuth } from '@/contexts/auth' | ||
| 493 | 494 | ||
| 494 | -const $route = useRoute(); | 495 | +const $route = useRoute() |
| 495 | -const $router = useRouter(); | 496 | +const $router = useRouter() |
| 496 | -useTitle($route.meta.title); | 497 | +useTitle($route.meta.title) |
| 498 | + | ||
| 499 | +// 获取认证状态 | ||
| 500 | +const { currentUser } = useAuth() | ||
| 497 | 501 | ||
| 498 | // 响应式状态 | 502 | // 响应式状态 |
| 499 | const activeTab = ref('推荐') | 503 | const activeTab = ref('推荐') | ... | ... |
-
Please register or login to post a comment