hookehuyr

refactor(router): 将路由配置和守卫逻辑拆分为独立模块

将路由配置从 `index.js` 拆分为 `routes.js`,并将路由守卫逻辑拆分为 `guards.js`,以提高代码的可维护性和可读性。
/*
* @Date: 2025-03-20 20:36:36
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-03-25 15:17:18
* @FilePath: /mlaj/src/router/guards.js
* @Description: 路由守卫逻辑
*/
import { getAuthInfoAPI } from '@/api/auth'
import { wxInfo } from "@/utils/tools"
// 需要登录才能访问的路由
export const authRequiredRoutes = [
{
path: '/profile',
exact: false,
},
{
path: '/checkout',
exact: true,
},
{
path: '/activities/[^/]+/signup',
regex: true,
},
]
// 微信授权检查
export const checkWxAuth = async (to) => {
if (!import.meta.env.DEV && wxInfo().isWeiXin && to.path !== '/auth') {
try {
const { code, data } = await getAuthInfoAPI();
if (code && !data.openid_has) {
return { path: '/auth', query: { href: location.hash } }
}
} catch (error) {
console.error('微信授权检查失败:', error)
}
}
return true
}
// 登录权限检查
export const checkAuth = (to) => {
const currentUser = JSON.parse(localStorage.getItem('currentUser'))
// 检查当前路由是否需要认证
const needAuth = authRequiredRoutes.some((route) => {
// 如果是正则匹配模式
if (route.regex) {
return new RegExp(`^${route.path}$`).test(to.path)
}
// 如果是精确匹配模式
if (route.exact) {
return to.path === route.path
}
// 默认前缀匹配模式
return to.path.startsWith(route.path)
})
if (needAuth && !currentUser) {
// 未登录时重定向到登录页面
return { path: '/login', query: { redirect: to.fullPath } }
}
return true
}
......@@ -3,194 +3,11 @@
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-03-25 15:17:18
* @FilePath: /mlaj/src/router/index.js
* @Description: 文件描述
* @Description: 路由实例创建和导出
*/
import { createRouter, createWebHashHistory } from 'vue-router'
import checkinRoutes from './checkin'
import { getAuthInfoAPI } from '@/api/auth'
import { wxInfo } from "@/utils/tools";
const routes = [
{
path: '/',
name: 'HomePage',
component: () => import('../views/HomePage.vue'),
meta: { title: '美乐爱觉' },
},
{
path: '/courses',
name: 'Courses',
component: () => import('../views/courses/CoursesPage.vue'),
meta: { title: '课程' },
},
{
path: '/courses/:id',
name: 'CourseDetail',
component: () => import('../views/courses/CourseDetailPage.vue'),
meta: { title: '课程详情' },
},
{
path: '/courses/:id/reviews',
name: 'CourseReviews',
component: () => import('../views/courses/CourseReviewsPage.vue'),
meta: { title: '课程评价' },
},
{
path: '/courses-list',
name: 'CourseList',
component: () => import('../views/courses/CourseListPage.vue'),
meta: { title: '课程列表' },
},
{
path: '/profile',
name: 'Profile',
component: () => import('../views/profile/ProfilePage.vue'),
meta: { title: '个人中心' },
},
{
path: '/login',
name: 'Login',
component: () => import('../views/auth/LoginPage.vue'),
meta: { title: '登录' },
},
{
path: '/register',
name: 'Register',
component: () => import('../views/auth/RegisterPage.vue'),
meta: { title: '注册' },
},
{
path: '/forgotPwd',
name: 'ForgotPassword',
component: () => import('../views/auth/ForgotPasswordPage.vue'),
meta: { title: '忘记密码' },
},
{
path: '/activities',
name: 'Activities',
component: () => import('../views/activities/ActivitiesPage.vue'),
meta: { title: '活动列表' },
},
{
path: '/activities/:id',
name: 'ActivityDetail',
component: () => import('../views/activities/ActivityDetailPage.vue'),
props: true,
meta: { title: '活动详情' },
},
{
path: '/activities/:id/signup',
name: 'ActivitySignup',
component: () => import('../views/activities/ActivitySignupPage.vue'),
meta: {
title: '活动报名',
},
},
{
path: '/profile/activities',
name: 'MyActivities',
component: () => import('../views/activities/MyActivitiesPage.vue'),
meta: { title: '我的活动' },
},
{
path: '/checkout',
name: 'CheckoutPage',
component: () => import('../views/checkout/CheckoutPage.vue'),
props: true,
meta: { title: '结账' },
},
{
path: '/profile/courses',
name: 'MyCourses',
component: () => import('../views/courses/MyCoursesPage.vue'),
meta: { title: '我的课程' },
},
{
path: '/profile/orders',
name: 'Orders',
component: () => import('../views/profile/OrdersPage.vue'),
meta: { title: '我的订单' },
},
{
path: '/profile/favorites',
name: 'MyFavorites',
component: () => import('../views/profile/MyFavoritesPage.vue'),
meta: { title: '我的收藏' },
},
{
path: '/profile/messages',
name: 'Messages',
component: () => import('../views/profile/MessagesPage.vue'),
meta: { title: '消息中心' },
},
{
path: '/profile/help',
name: 'Help',
component: () => import('../views/profile/HelpPage.vue'),
meta: { title: '帮助中心' },
},
{
path: '/profile/help/:id',
name: 'HelpDetail',
component: () => import('../views/profile/HelpDetailPage.vue'),
meta: { title: '帮助详情' },
},
{
path: '/profile/messages/:id',
name: 'MessageDetail',
component: () => import('../views/profile/MessageDetailPage.vue'),
meta: { title: '消息详情' },
},
{
path: '/profile/settings',
name: 'Settings',
component: () => import('../views/profile/SettingsPage.vue'),
meta: { title: '设置' },
},
{
path: '/profile/settings/avatar',
name: 'AvatarSetting',
component: () => import('../views/profile/settings/AvatarSettingPage.vue'),
meta: { title: '修改头像' },
},
{
path: '/profile/settings/username',
name: 'UsernameSetting',
component: () => import('../views/profile/settings/UsernameSettingPage.vue'),
meta: { title: '修改用户名' },
},
{
path: '/profile/settings/password',
name: 'PasswordSetting',
component: () => import('../views/profile/settings/PasswordSettingPage.vue'),
meta: { title: '修改密码' },
},
{
path: '/profile/learning-records',
name: 'LearningRecords',
component: () => import('../views/profile/LearningRecordsPage.vue'),
meta: { title: '学习记录' },
},
{
path: '/test',
name: 'test',
component: () => import('../views/test.vue'),
meta: { title: 'test' },
},
{
path: '/upload_video',
name: 'upload_video',
component: () => import('../views/upload_video.vue'),
meta: { title: 'upload_video' },
}, {
path: '/auth',
component: () => import('@/views/auth.vue'),
meta: {
title: '微信授权页面',
}
},
...checkinRoutes,
]
import { routes } from './routes'
import { checkWxAuth, checkAuth } from './guards'
const router = createRouter({
history: createWebHashHistory(import.meta.env.VITE_BASE || '/'),
......@@ -201,58 +18,19 @@ const router = createRouter({
},
})
// 需要登录才能访问的路由
const authRequiredRoutes = [
{
path: '/profile',
exact: false,
},
{
path: '/checkout',
exact: true,
},
{
path: '/activities/[^/]+/signup',
regex: true,
},
]
// 导航守卫
router.beforeEach(async (to, from, next) => {
// 微信授权检查
if (!import.meta.env.DEV && wxInfo().isWeiXin && to.path !== '/auth') {
try {
const { code, data } = await getAuthInfoAPI();
if (code && !data.openid_has) {
next({ path: '/auth', query: { href: location.hash } })
return
}
} catch (error) {
console.error('微信授权检查失败:', error)
}
const wxAuthResult = await checkWxAuth(to)
if (wxAuthResult !== true) {
next(wxAuthResult)
return
}
const currentUser = JSON.parse(localStorage.getItem('currentUser'))
// 检查当前路由是否需要认证
const needAuth = authRequiredRoutes.some((route) => {
// 如果是正则匹配模式
if (route.regex) {
return new RegExp(`^${route.path}$`).test(to.path)
}
// 如果是精确匹配模式
if (route.exact) {
return to.path === route.path
}
// 默认前缀匹配模式
// 判断路由路径是否以指定路径开头,用于匹配需要认证的路由及其子路由
// 例如: /profile/courses 应该匹配 /profile 规则
return to.path.startsWith(route.path)
})
if (needAuth && !currentUser) {
// 未登录时重定向到登录页面
next({ path: '/login', query: { redirect: to.fullPath } })
// 登录权限检查
const authResult = checkAuth(to)
if (authResult !== true) {
next(authResult)
return
}
......
/*
* @Date: 2025-03-20 20:36:36
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-03-25 15:17:18
* @FilePath: /mlaj/src/router/routes.js
* @Description: 路由地址映射配置
*/
import checkinRoutes from './checkin'
export const routes = [
{
path: '/',
name: 'HomePage',
component: () => import('../views/HomePage.vue'),
meta: { title: '美乐爱觉' },
},
{
path: '/courses',
name: 'Courses',
component: () => import('../views/courses/CoursesPage.vue'),
meta: { title: '课程' },
},
{
path: '/courses/:id',
name: 'CourseDetail',
component: () => import('../views/courses/CourseDetailPage.vue'),
meta: { title: '课程详情' },
},
{
path: '/courses/:id/reviews',
name: 'CourseReviews',
component: () => import('../views/courses/CourseReviewsPage.vue'),
meta: { title: '课程评价' },
},
{
path: '/courses-list',
name: 'CourseList',
component: () => import('../views/courses/CourseListPage.vue'),
meta: { title: '课程列表' },
},
{
path: '/profile',
name: 'Profile',
component: () => import('../views/profile/ProfilePage.vue'),
meta: { title: '个人中心' },
},
{
path: '/login',
name: 'Login',
component: () => import('../views/auth/LoginPage.vue'),
meta: { title: '登录' },
},
{
path: '/register',
name: 'Register',
component: () => import('../views/auth/RegisterPage.vue'),
meta: { title: '注册' },
},
{
path: '/forgotPwd',
name: 'ForgotPassword',
component: () => import('../views/auth/ForgotPasswordPage.vue'),
meta: { title: '忘记密码' },
},
{
path: '/activities',
name: 'Activities',
component: () => import('../views/activities/ActivitiesPage.vue'),
meta: { title: '活动列表' },
},
{
path: '/activities/:id',
name: 'ActivityDetail',
component: () => import('../views/activities/ActivityDetailPage.vue'),
props: true,
meta: { title: '活动详情' },
},
{
path: '/activities/:id/signup',
name: 'ActivitySignup',
component: () => import('../views/activities/ActivitySignupPage.vue'),
meta: {
title: '活动报名',
},
},
{
path: '/profile/activities',
name: 'MyActivities',
component: () => import('../views/activities/MyActivitiesPage.vue'),
meta: { title: '我的活动' },
},
{
path: '/checkout',
name: 'CheckoutPage',
component: () => import('../views/checkout/CheckoutPage.vue'),
props: true,
meta: { title: '结账' },
},
{
path: '/profile/courses',
name: 'MyCourses',
component: () => import('../views/courses/MyCoursesPage.vue'),
meta: { title: '我的课程' },
},
{
path: '/profile/orders',
name: 'Orders',
component: () => import('../views/profile/OrdersPage.vue'),
meta: { title: '我的订单' },
},
{
path: '/profile/favorites',
name: 'MyFavorites',
component: () => import('../views/profile/MyFavoritesPage.vue'),
meta: { title: '我的收藏' },
},
{
path: '/profile/messages',
name: 'Messages',
component: () => import('../views/profile/MessagesPage.vue'),
meta: { title: '消息中心' },
},
{
path: '/profile/help',
name: 'Help',
component: () => import('../views/profile/HelpPage.vue'),
meta: { title: '帮助中心' },
},
{
path: '/profile/help/:id',
name: 'HelpDetail',
component: () => import('../views/profile/HelpDetailPage.vue'),
meta: { title: '帮助详情' },
},
{
path: '/profile/messages/:id',
name: 'MessageDetail',
component: () => import('../views/profile/MessageDetailPage.vue'),
meta: { title: '消息详情' },
},
{
path: '/profile/settings',
name: 'Settings',
component: () => import('../views/profile/SettingsPage.vue'),
meta: { title: '设置' },
},
{
path: '/profile/settings/avatar',
name: 'AvatarSetting',
component: () => import('../views/profile/settings/AvatarSettingPage.vue'),
meta: { title: '修改头像' },
},
{
path: '/profile/settings/username',
name: 'UsernameSetting',
component: () => import('../views/profile/settings/UsernameSettingPage.vue'),
meta: { title: '修改用户名' },
},
{
path: '/profile/settings/password',
name: 'PasswordSetting',
component: () => import('../views/profile/settings/PasswordSettingPage.vue'),
meta: { title: '修改密码' },
},
{
path: '/profile/learning-records',
name: 'LearningRecords',
component: () => import('../views/profile/LearningRecordsPage.vue'),
meta: { title: '学习记录' },
},
{
path: '/test',
name: 'test',
component: () => import('../views/test.vue'),
meta: { title: 'test' },
},
{
path: '/upload_video',
name: 'upload_video',
component: () => import('../views/upload_video.vue'),
meta: { title: 'upload_video' },
}, {
path: '/auth',
component: () => import('@/views/auth.vue'),
meta: {
title: '微信授权页面',
}
},
...checkinRoutes,
]