hookehuyr

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

将路由配置从 `index.js` 拆分为 `routes.js`,并将路由守卫逻辑拆分为 `guards.js`,以提高代码的可维护性和可读性。
1 +/*
2 + * @Date: 2025-03-20 20:36:36
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2025-03-25 15:17:18
5 + * @FilePath: /mlaj/src/router/guards.js
6 + * @Description: 路由守卫逻辑
7 + */
8 +import { getAuthInfoAPI } from '@/api/auth'
9 +import { wxInfo } from "@/utils/tools"
10 +
11 +// 需要登录才能访问的路由
12 +export const authRequiredRoutes = [
13 + {
14 + path: '/profile',
15 + exact: false,
16 + },
17 + {
18 + path: '/checkout',
19 + exact: true,
20 + },
21 + {
22 + path: '/activities/[^/]+/signup',
23 + regex: true,
24 + },
25 +]
26 +
27 +// 微信授权检查
28 +export const checkWxAuth = async (to) => {
29 + if (!import.meta.env.DEV && wxInfo().isWeiXin && to.path !== '/auth') {
30 + try {
31 + const { code, data } = await getAuthInfoAPI();
32 + if (code && !data.openid_has) {
33 + return { path: '/auth', query: { href: location.hash } }
34 + }
35 + } catch (error) {
36 + console.error('微信授权检查失败:', error)
37 + }
38 + }
39 + return true
40 +}
41 +
42 +// 登录权限检查
43 +export const checkAuth = (to) => {
44 + const currentUser = JSON.parse(localStorage.getItem('currentUser'))
45 +
46 + // 检查当前路由是否需要认证
47 + const needAuth = authRequiredRoutes.some((route) => {
48 + // 如果是正则匹配模式
49 + if (route.regex) {
50 + return new RegExp(`^${route.path}$`).test(to.path)
51 + }
52 + // 如果是精确匹配模式
53 + if (route.exact) {
54 + return to.path === route.path
55 + }
56 + // 默认前缀匹配模式
57 + return to.path.startsWith(route.path)
58 + })
59 +
60 + if (needAuth && !currentUser) {
61 + // 未登录时重定向到登录页面
62 + return { path: '/login', query: { redirect: to.fullPath } }
63 + }
64 +
65 + return true
66 +}
...@@ -3,194 +3,11 @@ ...@@ -3,194 +3,11 @@
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 * @LastEditTime: 2025-03-25 15:17:18 4 * @LastEditTime: 2025-03-25 15:17:18
5 * @FilePath: /mlaj/src/router/index.js 5 * @FilePath: /mlaj/src/router/index.js
6 - * @Description: 文件描述 6 + * @Description: 路由实例创建和导出
7 */ 7 */
8 import { createRouter, createWebHashHistory } from 'vue-router' 8 import { createRouter, createWebHashHistory } from 'vue-router'
9 -import checkinRoutes from './checkin' 9 +import { routes } from './routes'
10 -import { getAuthInfoAPI } from '@/api/auth' 10 +import { checkWxAuth, checkAuth } from './guards'
11 -import { wxInfo } from "@/utils/tools";
12 -
13 -const routes = [
14 - {
15 - path: '/',
16 - name: 'HomePage',
17 - component: () => import('../views/HomePage.vue'),
18 - meta: { title: '美乐爱觉' },
19 - },
20 - {
21 - path: '/courses',
22 - name: 'Courses',
23 - component: () => import('../views/courses/CoursesPage.vue'),
24 - meta: { title: '课程' },
25 - },
26 - {
27 - path: '/courses/:id',
28 - name: 'CourseDetail',
29 - component: () => import('../views/courses/CourseDetailPage.vue'),
30 - meta: { title: '课程详情' },
31 - },
32 - {
33 - path: '/courses/:id/reviews',
34 - name: 'CourseReviews',
35 - component: () => import('../views/courses/CourseReviewsPage.vue'),
36 - meta: { title: '课程评价' },
37 - },
38 - {
39 - path: '/courses-list',
40 - name: 'CourseList',
41 - component: () => import('../views/courses/CourseListPage.vue'),
42 - meta: { title: '课程列表' },
43 - },
44 - {
45 - path: '/profile',
46 - name: 'Profile',
47 - component: () => import('../views/profile/ProfilePage.vue'),
48 - meta: { title: '个人中心' },
49 - },
50 - {
51 - path: '/login',
52 - name: 'Login',
53 - component: () => import('../views/auth/LoginPage.vue'),
54 - meta: { title: '登录' },
55 - },
56 - {
57 - path: '/register',
58 - name: 'Register',
59 - component: () => import('../views/auth/RegisterPage.vue'),
60 - meta: { title: '注册' },
61 - },
62 - {
63 - path: '/forgotPwd',
64 - name: 'ForgotPassword',
65 - component: () => import('../views/auth/ForgotPasswordPage.vue'),
66 - meta: { title: '忘记密码' },
67 - },
68 - {
69 - path: '/activities',
70 - name: 'Activities',
71 - component: () => import('../views/activities/ActivitiesPage.vue'),
72 - meta: { title: '活动列表' },
73 - },
74 - {
75 - path: '/activities/:id',
76 - name: 'ActivityDetail',
77 - component: () => import('../views/activities/ActivityDetailPage.vue'),
78 - props: true,
79 - meta: { title: '活动详情' },
80 - },
81 - {
82 - path: '/activities/:id/signup',
83 - name: 'ActivitySignup',
84 - component: () => import('../views/activities/ActivitySignupPage.vue'),
85 - meta: {
86 - title: '活动报名',
87 - },
88 - },
89 - {
90 - path: '/profile/activities',
91 - name: 'MyActivities',
92 - component: () => import('../views/activities/MyActivitiesPage.vue'),
93 - meta: { title: '我的活动' },
94 - },
95 - {
96 - path: '/checkout',
97 - name: 'CheckoutPage',
98 - component: () => import('../views/checkout/CheckoutPage.vue'),
99 - props: true,
100 - meta: { title: '结账' },
101 - },
102 - {
103 - path: '/profile/courses',
104 - name: 'MyCourses',
105 - component: () => import('../views/courses/MyCoursesPage.vue'),
106 - meta: { title: '我的课程' },
107 - },
108 - {
109 - path: '/profile/orders',
110 - name: 'Orders',
111 - component: () => import('../views/profile/OrdersPage.vue'),
112 - meta: { title: '我的订单' },
113 - },
114 - {
115 - path: '/profile/favorites',
116 - name: 'MyFavorites',
117 - component: () => import('../views/profile/MyFavoritesPage.vue'),
118 - meta: { title: '我的收藏' },
119 - },
120 - {
121 - path: '/profile/messages',
122 - name: 'Messages',
123 - component: () => import('../views/profile/MessagesPage.vue'),
124 - meta: { title: '消息中心' },
125 - },
126 - {
127 - path: '/profile/help',
128 - name: 'Help',
129 - component: () => import('../views/profile/HelpPage.vue'),
130 - meta: { title: '帮助中心' },
131 - },
132 - {
133 - path: '/profile/help/:id',
134 - name: 'HelpDetail',
135 - component: () => import('../views/profile/HelpDetailPage.vue'),
136 - meta: { title: '帮助详情' },
137 - },
138 - {
139 - path: '/profile/messages/:id',
140 - name: 'MessageDetail',
141 - component: () => import('../views/profile/MessageDetailPage.vue'),
142 - meta: { title: '消息详情' },
143 - },
144 - {
145 - path: '/profile/settings',
146 - name: 'Settings',
147 - component: () => import('../views/profile/SettingsPage.vue'),
148 - meta: { title: '设置' },
149 - },
150 - {
151 - path: '/profile/settings/avatar',
152 - name: 'AvatarSetting',
153 - component: () => import('../views/profile/settings/AvatarSettingPage.vue'),
154 - meta: { title: '修改头像' },
155 - },
156 - {
157 - path: '/profile/settings/username',
158 - name: 'UsernameSetting',
159 - component: () => import('../views/profile/settings/UsernameSettingPage.vue'),
160 - meta: { title: '修改用户名' },
161 - },
162 - {
163 - path: '/profile/settings/password',
164 - name: 'PasswordSetting',
165 - component: () => import('../views/profile/settings/PasswordSettingPage.vue'),
166 - meta: { title: '修改密码' },
167 - },
168 - {
169 - path: '/profile/learning-records',
170 - name: 'LearningRecords',
171 - component: () => import('../views/profile/LearningRecordsPage.vue'),
172 - meta: { title: '学习记录' },
173 - },
174 - {
175 - path: '/test',
176 - name: 'test',
177 - component: () => import('../views/test.vue'),
178 - meta: { title: 'test' },
179 - },
180 - {
181 - path: '/upload_video',
182 - name: 'upload_video',
183 - component: () => import('../views/upload_video.vue'),
184 - meta: { title: 'upload_video' },
185 - }, {
186 - path: '/auth',
187 - component: () => import('@/views/auth.vue'),
188 - meta: {
189 - title: '微信授权页面',
190 - }
191 - },
192 - ...checkinRoutes,
193 -]
194 11
195 const router = createRouter({ 12 const router = createRouter({
196 history: createWebHashHistory(import.meta.env.VITE_BASE || '/'), 13 history: createWebHashHistory(import.meta.env.VITE_BASE || '/'),
...@@ -201,58 +18,19 @@ const router = createRouter({ ...@@ -201,58 +18,19 @@ const router = createRouter({
201 }, 18 },
202 }) 19 })
203 20
204 -// 需要登录才能访问的路由
205 -const authRequiredRoutes = [
206 - {
207 - path: '/profile',
208 - exact: false,
209 - },
210 - {
211 - path: '/checkout',
212 - exact: true,
213 - },
214 - {
215 - path: '/activities/[^/]+/signup',
216 - regex: true,
217 - },
218 -]
219 -
220 // 导航守卫 21 // 导航守卫
221 router.beforeEach(async (to, from, next) => { 22 router.beforeEach(async (to, from, next) => {
222 // 微信授权检查 23 // 微信授权检查
223 - if (!import.meta.env.DEV && wxInfo().isWeiXin && to.path !== '/auth') { 24 + const wxAuthResult = await checkWxAuth(to)
224 - try { 25 + if (wxAuthResult !== true) {
225 - const { code, data } = await getAuthInfoAPI(); 26 + next(wxAuthResult)
226 - if (code && !data.openid_has) { 27 + return
227 - next({ path: '/auth', query: { href: location.hash } })
228 - return
229 - }
230 - } catch (error) {
231 - console.error('微信授权检查失败:', error)
232 - }
233 } 28 }
234 29
235 - const currentUser = JSON.parse(localStorage.getItem('currentUser')) 30 + // 登录权限检查
236 - 31 + const authResult = checkAuth(to)
237 - // 检查当前路由是否需要认证 32 + if (authResult !== true) {
238 - const needAuth = authRequiredRoutes.some((route) => { 33 + next(authResult)
239 - // 如果是正则匹配模式
240 - if (route.regex) {
241 - return new RegExp(`^${route.path}$`).test(to.path)
242 - }
243 - // 如果是精确匹配模式
244 - if (route.exact) {
245 - return to.path === route.path
246 - }
247 - // 默认前缀匹配模式
248 - // 判断路由路径是否以指定路径开头,用于匹配需要认证的路由及其子路由
249 - // 例如: /profile/courses 应该匹配 /profile 规则
250 - return to.path.startsWith(route.path)
251 - })
252 -
253 - if (needAuth && !currentUser) {
254 - // 未登录时重定向到登录页面
255 - next({ path: '/login', query: { redirect: to.fullPath } })
256 return 34 return
257 } 35 }
258 36
......
1 +/*
2 + * @Date: 2025-03-20 20:36:36
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2025-03-25 15:17:18
5 + * @FilePath: /mlaj/src/router/routes.js
6 + * @Description: 路由地址映射配置
7 + */
8 +import checkinRoutes from './checkin'
9 +
10 +export const routes = [
11 + {
12 + path: '/',
13 + name: 'HomePage',
14 + component: () => import('../views/HomePage.vue'),
15 + meta: { title: '美乐爱觉' },
16 + },
17 + {
18 + path: '/courses',
19 + name: 'Courses',
20 + component: () => import('../views/courses/CoursesPage.vue'),
21 + meta: { title: '课程' },
22 + },
23 + {
24 + path: '/courses/:id',
25 + name: 'CourseDetail',
26 + component: () => import('../views/courses/CourseDetailPage.vue'),
27 + meta: { title: '课程详情' },
28 + },
29 + {
30 + path: '/courses/:id/reviews',
31 + name: 'CourseReviews',
32 + component: () => import('../views/courses/CourseReviewsPage.vue'),
33 + meta: { title: '课程评价' },
34 + },
35 + {
36 + path: '/courses-list',
37 + name: 'CourseList',
38 + component: () => import('../views/courses/CourseListPage.vue'),
39 + meta: { title: '课程列表' },
40 + },
41 + {
42 + path: '/profile',
43 + name: 'Profile',
44 + component: () => import('../views/profile/ProfilePage.vue'),
45 + meta: { title: '个人中心' },
46 + },
47 + {
48 + path: '/login',
49 + name: 'Login',
50 + component: () => import('../views/auth/LoginPage.vue'),
51 + meta: { title: '登录' },
52 + },
53 + {
54 + path: '/register',
55 + name: 'Register',
56 + component: () => import('../views/auth/RegisterPage.vue'),
57 + meta: { title: '注册' },
58 + },
59 + {
60 + path: '/forgotPwd',
61 + name: 'ForgotPassword',
62 + component: () => import('../views/auth/ForgotPasswordPage.vue'),
63 + meta: { title: '忘记密码' },
64 + },
65 + {
66 + path: '/activities',
67 + name: 'Activities',
68 + component: () => import('../views/activities/ActivitiesPage.vue'),
69 + meta: { title: '活动列表' },
70 + },
71 + {
72 + path: '/activities/:id',
73 + name: 'ActivityDetail',
74 + component: () => import('../views/activities/ActivityDetailPage.vue'),
75 + props: true,
76 + meta: { title: '活动详情' },
77 + },
78 + {
79 + path: '/activities/:id/signup',
80 + name: 'ActivitySignup',
81 + component: () => import('../views/activities/ActivitySignupPage.vue'),
82 + meta: {
83 + title: '活动报名',
84 + },
85 + },
86 + {
87 + path: '/profile/activities',
88 + name: 'MyActivities',
89 + component: () => import('../views/activities/MyActivitiesPage.vue'),
90 + meta: { title: '我的活动' },
91 + },
92 + {
93 + path: '/checkout',
94 + name: 'CheckoutPage',
95 + component: () => import('../views/checkout/CheckoutPage.vue'),
96 + props: true,
97 + meta: { title: '结账' },
98 + },
99 + {
100 + path: '/profile/courses',
101 + name: 'MyCourses',
102 + component: () => import('../views/courses/MyCoursesPage.vue'),
103 + meta: { title: '我的课程' },
104 + },
105 + {
106 + path: '/profile/orders',
107 + name: 'Orders',
108 + component: () => import('../views/profile/OrdersPage.vue'),
109 + meta: { title: '我的订单' },
110 + },
111 + {
112 + path: '/profile/favorites',
113 + name: 'MyFavorites',
114 + component: () => import('../views/profile/MyFavoritesPage.vue'),
115 + meta: { title: '我的收藏' },
116 + },
117 + {
118 + path: '/profile/messages',
119 + name: 'Messages',
120 + component: () => import('../views/profile/MessagesPage.vue'),
121 + meta: { title: '消息中心' },
122 + },
123 + {
124 + path: '/profile/help',
125 + name: 'Help',
126 + component: () => import('../views/profile/HelpPage.vue'),
127 + meta: { title: '帮助中心' },
128 + },
129 + {
130 + path: '/profile/help/:id',
131 + name: 'HelpDetail',
132 + component: () => import('../views/profile/HelpDetailPage.vue'),
133 + meta: { title: '帮助详情' },
134 + },
135 + {
136 + path: '/profile/messages/:id',
137 + name: 'MessageDetail',
138 + component: () => import('../views/profile/MessageDetailPage.vue'),
139 + meta: { title: '消息详情' },
140 + },
141 + {
142 + path: '/profile/settings',
143 + name: 'Settings',
144 + component: () => import('../views/profile/SettingsPage.vue'),
145 + meta: { title: '设置' },
146 + },
147 + {
148 + path: '/profile/settings/avatar',
149 + name: 'AvatarSetting',
150 + component: () => import('../views/profile/settings/AvatarSettingPage.vue'),
151 + meta: { title: '修改头像' },
152 + },
153 + {
154 + path: '/profile/settings/username',
155 + name: 'UsernameSetting',
156 + component: () => import('../views/profile/settings/UsernameSettingPage.vue'),
157 + meta: { title: '修改用户名' },
158 + },
159 + {
160 + path: '/profile/settings/password',
161 + name: 'PasswordSetting',
162 + component: () => import('../views/profile/settings/PasswordSettingPage.vue'),
163 + meta: { title: '修改密码' },
164 + },
165 + {
166 + path: '/profile/learning-records',
167 + name: 'LearningRecords',
168 + component: () => import('../views/profile/LearningRecordsPage.vue'),
169 + meta: { title: '学习记录' },
170 + },
171 + {
172 + path: '/test',
173 + name: 'test',
174 + component: () => import('../views/test.vue'),
175 + meta: { title: 'test' },
176 + },
177 + {
178 + path: '/upload_video',
179 + name: 'upload_video',
180 + component: () => import('../views/upload_video.vue'),
181 + meta: { title: 'upload_video' },
182 + }, {
183 + path: '/auth',
184 + component: () => import('@/views/auth.vue'),
185 + meta: {
186 + title: '微信授权页面',
187 + }
188 + },
189 + ...checkinRoutes,
190 +]