permission.ts 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. import router from './router'
  2. import type { RouteRecordRaw } from 'vue-router'
  3. import { isRelogin } from '@/config/axios/service'
  4. import { getAccessToken } from '@/utils/auth'
  5. import { useTitle } from '@/hooks/web/useTitle'
  6. import { useNProgress } from '@/hooks/web/useNProgress'
  7. import { usePageLoading } from '@/hooks/web/usePageLoading'
  8. import { useDictStoreWithOut } from '@/store/modules/dict'
  9. import { useUserStoreWithOut } from '@/store/modules/user'
  10. import { usePermissionStoreWithOut } from '@/store/modules/permission'
  11. import * as authUtil from '@/utils/auth'
  12. const { start, done } = useNProgress()
  13. const { loadStart, loadDone } = usePageLoading()
  14. const loading = ref() // ElLoading.service 返回的实例
  15. const parseURL = (
  16. url: string | null | undefined
  17. ): { basePath: string; paramsObject: { [key: string]: string } } => {
  18. // 如果输入为 null 或 undefined,返回空字符串和空对象
  19. if (url == null) {
  20. return { basePath: '', paramsObject: {} }
  21. }
  22. // 找到问号 (?) 的位置,它之前是基础路径,之后是查询参数
  23. const questionMarkIndex = url.indexOf('?')
  24. let basePath = url
  25. const paramsObject: { [key: string]: string } = {}
  26. // 如果找到了问号,说明有查询参数
  27. if (questionMarkIndex !== -1) {
  28. // 获取 basePath
  29. basePath = url.substring(0, questionMarkIndex)
  30. // 从 URL 中获取查询字符串部分
  31. const queryString = url.substring(questionMarkIndex + 1)
  32. // 使用 URLSearchParams 遍历参数
  33. const searchParams = new URLSearchParams(queryString)
  34. searchParams.forEach((value, key) => {
  35. // 封装进 paramsObject 对象
  36. paramsObject[key] = value
  37. })
  38. }
  39. // 返回 basePath 和 paramsObject
  40. return { basePath, paramsObject }
  41. }
  42. // 单点登录token验证函数
  43. const validateAndLogin = async () => {
  44. try {
  45. const userStore = useUserStoreWithOut()
  46. // 调用单点登录接口,传入外部token
  47. // 这里根据你的实际接口调整
  48. const response = await userStore.ssoLogin()
  49. // const response = {
  50. // accessToken: "41f636cc7ff247129e4d4f205bc3a096",
  51. // expiresTime: 1767094239442,
  52. // loginType: "cas",
  53. // refreshToken: "d86a7e71e34b464a898fe2a2e838e572",
  54. // userId: "140"
  55. // }
  56. if (response && response.accessToken) {
  57. loading.value = ElLoading.service({
  58. lock: true,
  59. text: '正在加载系统中...',
  60. background: 'rgba(0, 0, 0, 0.7)'
  61. })
  62. authUtil.setToken(response)
  63. }
  64. console.log(response, 'response的数据啊')
  65. // 或者直接调用API
  66. // import { ssoLoginApi } from '@/api/login'
  67. // const response = await ssoLoginApi({ token, loginType })
  68. // 保存本系统的token
  69. // if (response && response.token) {
  70. // setToken(response.token)
  71. // return true
  72. // }
  73. return true
  74. } catch (error) {
  75. console.error('SSO登录失败:', error)
  76. return false
  77. }
  78. }
  79. // 路由不重定向白名单
  80. const whiteList = [
  81. '/login',
  82. '/social-login',
  83. '/auth-redirect',
  84. '/bind',
  85. '/register',
  86. '/oauthLogin/gitee'
  87. ]
  88. // 路由加载前
  89. // 路由加载前
  90. router.beforeEach(async (to, from, next) => {
  91. start()
  92. loadStart()
  93. const loginType = to.query.loginType as string
  94. // 处理单点登录
  95. if (loginType == 'cas') {
  96. console.log('检测到SSO登录参数:', loginType )
  97. try {
  98. // 验证token并登录
  99. const loginSuccess = await validateAndLogin()
  100. console.log('SSO登录结果:', loginSuccess)
  101. if (loginSuccess) {
  102. // 登录成功,清除URL中的token参数
  103. const targetPath = to.path === '/' ? '/index' : to.path
  104. console.log('登录成功,跳转到:', targetPath)
  105. // 获取用户信息和权限
  106. const userStore = useUserStoreWithOut()
  107. const permissionStore = usePermissionStoreWithOut()
  108. const dictStore = useDictStoreWithOut()
  109. isRelogin.show = true
  110. // 加载字典
  111. if (!dictStore.getIsSetDict) {
  112. await dictStore.setDictMap()
  113. }
  114. // 加载用户信息
  115. await userStore.setUserInfoAction()
  116. // 加载菜单权限
  117. await permissionStore.generateRoutes()
  118. permissionStore.getAddRouters.forEach((route) => {
  119. router.addRoute(route as unknown as RouteRecordRaw)
  120. })
  121. loading.value.close()
  122. isRelogin.show = false
  123. // 跳转到目标页面,移除token参数
  124. next({
  125. path: targetPath,
  126. query: {},
  127. replace: true
  128. })
  129. } else {
  130. // token验证失败
  131. console.log('SSO token验证失败')
  132. loading.value.close()
  133. next('/login')
  134. }
  135. } catch (error) {
  136. console.error('SSO登录异常:', error)
  137. isRelogin.show = false
  138. next('/login')
  139. }
  140. return
  141. }
  142. // 正常的登录验证逻辑
  143. if (getAccessToken()) {
  144. if (to.path === '/login') {
  145. next({ path: '/' })
  146. } else {
  147. const dictStore = useDictStoreWithOut()
  148. const userStore = useUserStoreWithOut()
  149. const permissionStore = usePermissionStoreWithOut()
  150. if (!dictStore.getIsSetDict) {
  151. await dictStore.setDictMap()
  152. }
  153. if (!userStore.getIsSetUser) {
  154. isRelogin.show = true
  155. await userStore.setUserInfoAction()
  156. isRelogin.show = false
  157. await permissionStore.generateRoutes()
  158. permissionStore.getAddRouters.forEach((route) => {
  159. router.addRoute(route as unknown as RouteRecordRaw)
  160. })
  161. const redirectPath = from.query.redirect || to.path
  162. const redirect = decodeURIComponent(redirectPath as string)
  163. const { paramsObject: query } = parseURL(redirect)
  164. const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect, query }
  165. next(nextData)
  166. } else {
  167. next()
  168. }
  169. }
  170. } else {
  171. if (whiteList.indexOf(to.path) !== -1) {
  172. next()
  173. } else {
  174. next(`/login?redirect=${encodeURIComponent(to.fullPath)}`)
  175. }
  176. }
  177. })
  178. router.afterEach((to) => {
  179. useTitle(to?.meta?.title as string)
  180. done() // 结束Progress
  181. loadDone()
  182. })