index.ts 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. import { createRouter, createWebHistory } from 'vue-router'
  2. import type { RouteRecordRaw } from 'vue-router'
  3. import { useAuthStore } from '@/stores/auth'
  4. import MainLayout from '@/layouts/MainLayout.vue'
  5. const routes: RouteRecordRaw[] = [
  6. {
  7. path: '/',
  8. redirect: '/dashboard'
  9. },
  10. {
  11. path: '/login',
  12. name: 'Login',
  13. component: () => import('@/views/auth/Login.vue'),
  14. meta: { requiresGuest: true }
  15. },
  16. {
  17. path: '/register',
  18. name: 'Register',
  19. component: () => import('@/views/auth/Register.vue'),
  20. meta: { requiresGuest: true }
  21. },
  22. {
  23. path: '/oauth/callback',
  24. name: 'OAuthCallback',
  25. component: () => import('@/views/auth/OAuthCallback.vue')
  26. },
  27. {
  28. path: '/',
  29. component: MainLayout,
  30. meta: { requiresAuth: true },
  31. children: [
  32. {
  33. path: 'admin/basic-info',
  34. name: 'BasicInfo',
  35. redirect: '/admin/basic-info/standard',
  36. meta: { requiresAdmin: true }
  37. },
  38. {
  39. path: 'admin/basic-info/standard',
  40. name: 'BasicInfoStandard',
  41. component: () => import('@/views/basic-info/Index.vue'),
  42. props: { infoType: 'standard' },
  43. meta: { requiresAdmin: true }
  44. },
  45. {
  46. path: 'admin/basic-info/construction_plan',
  47. name: 'BasicInfoConstructionPlan',
  48. component: () => import('@/views/basic-info/Index.vue'),
  49. props: { infoType: 'construction_plan' },
  50. meta: { requiresAdmin: true }
  51. },
  52. {
  53. path: 'admin/basic-info/regulation',
  54. name: 'BasicInfoRegulation',
  55. component: () => import('@/views/basic-info/Index.vue'),
  56. props: { infoType: 'regulation' },
  57. meta: { requiresAdmin: true }
  58. },
  59. {
  60. path: 'dashboard',
  61. name: 'Dashboard',
  62. component: () => import('@/views/dashboard/Index.vue')
  63. },
  64. {
  65. path: 'profile',
  66. name: 'Profile',
  67. component: () => import('@/views/user/Profile.vue')
  68. },
  69. {
  70. path: 'admin',
  71. redirect: '/admin/dashboard'
  72. },
  73. {
  74. path: 'admin/dashboard',
  75. name: 'AdminDashboard',
  76. component: () => import('@/views/admin/Dashboard.vue'),
  77. meta: { requiresAdmin: true }
  78. },
  79. {
  80. path: 'admin/users',
  81. name: 'AdminUsers',
  82. component: () => import('@/views/admin/Users.vue'),
  83. meta: { requiresAdmin: true }
  84. },
  85. {
  86. path: 'admin/roles',
  87. name: 'AdminRoles',
  88. component: () => import('@/views/admin/Roles.vue'),
  89. meta: { requiresAdmin: true }
  90. },
  91. {
  92. path: 'admin/menus',
  93. name: 'AdminMenus',
  94. component: () => import('@/views/admin/Menus.vue'),
  95. meta: { requiresAdmin: true }
  96. },
  97. {
  98. path: 'admin/tasks',
  99. name: 'AdminTasks',
  100. component: () => import('@/views/admin/TaskManagement.vue'),
  101. meta: { requiresAdmin: true }
  102. },
  103. {
  104. path: 'admin/permissions',
  105. name: 'AdminPermissions',
  106. component: () => import('@/views/admin/Permissions.vue'),
  107. meta: { requiresAdmin: true }
  108. },
  109. {
  110. path: 'admin/apps',
  111. name: 'AdminApps',
  112. component: () => import('@/views/admin/Apps.vue'),
  113. meta: { requiresAdmin: true }
  114. },
  115. {
  116. path: 'admin/logs',
  117. name: 'AdminLogs',
  118. component: () => import('@/views/admin/Logs.vue'),
  119. meta: { requiresAdmin: true }
  120. },
  121. {
  122. path: 'admin/settings',
  123. name: 'AdminSettings',
  124. component: () => import('@/views/admin/Settings.vue'),
  125. meta: { requiresAdmin: true }
  126. },
  127. {
  128. path: 'admin/tags',
  129. name: 'AdminTags',
  130. component: () => import('@/views/admin/Tag.vue'),
  131. meta: { requiresAdmin: true }
  132. },
  133. {
  134. path: 'admin/documents',
  135. name: 'Documents',
  136. component: () => import('@/views/documents/Index.vue'),
  137. meta: { requiresAdmin: true }
  138. },
  139. {
  140. path: 'admin/images',
  141. name: 'Images',
  142. component: () => import('@/views/images/Index.vue'),
  143. meta: { requiresAdmin: true }
  144. },
  145. {
  146. path: 'admin/documents/kb',
  147. name: 'KnowledgeBase',
  148. component: () => import('@/views/documents/KnowledgeBase.vue'),
  149. meta: { requiresAdmin: true }
  150. },
  151. {
  152. path: 'admin/documents/snippet',
  153. name: 'KnowledgeSnippet',
  154. component: () => import('@/views/documents/KnowledgeSnippet.vue'),
  155. meta: { requiresAdmin: true }
  156. },
  157. {
  158. path: 'admin/documents/search-engine',
  159. name: 'SearchEngine',
  160. component: () => import('@/views/documents/SearchEngine.vue'),
  161. meta: { requiresAdmin: true }
  162. }
  163. ]
  164. },
  165. {
  166. path: '/unauthorized',
  167. name: 'Unauthorized',
  168. component: () => import('@/views/error/403.vue')
  169. },
  170. {
  171. path: '/:pathMatch(.*)*',
  172. name: 'NotFound',
  173. component: () => import('@/views/error/404.vue')
  174. }
  175. ]
  176. const router = createRouter({
  177. history: createWebHistory(),
  178. routes
  179. })
  180. // 路由守卫
  181. router.beforeEach(async (to, from, next) => {
  182. const authStore = useAuthStore()
  183. // 如果有token但没有用户信息,先尝试获取用户信息
  184. if (authStore.token && !authStore.user && !authStore.loading) {
  185. try {
  186. await authStore.checkAuth()
  187. } catch (error) {
  188. console.error('路由守卫检查认证状态失败:', error)
  189. }
  190. }
  191. // 检查是否需要认证
  192. if (to.meta.requiresAuth) {
  193. if (!authStore.isAuthenticated) {
  194. // 未登录,重定向到登录页
  195. next({
  196. name: 'Login',
  197. query: { redirect: to.fullPath }
  198. })
  199. return
  200. }
  201. // 检查是否需要管理员权限
  202. if (to.meta.requiresAdmin) {
  203. // For admin routes, check permissions
  204. if (authStore.isAdmin) {
  205. // Super admin or admin users can access all admin routes
  206. next()
  207. return
  208. } else {
  209. // For non-admin users, check if they have menu access to this specific path
  210. if (authStore.hasPathAccess(to.path)) {
  211. next()
  212. return
  213. } else {
  214. next({ name: 'Unauthorized' })
  215. return
  216. }
  217. }
  218. }
  219. }
  220. // 检查是否需要访客权限(已登录用户不能访问登录/注册页)
  221. if (to.meta.requiresGuest && authStore.isAuthenticated) {
  222. next({ name: 'Dashboard' })
  223. return
  224. }
  225. next()
  226. })
  227. export default router