permission.ts 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  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 (code) => {
  44. try {
  45. const userStore = useUserStoreWithOut()
  46. // 调用单点登录接口,传入外部token
  47. // 这里根据你的实际接口调整
  48. const response = await userStore.ssoLogin(code)
  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. '/pressure2/qr-report/boiler',
  88. '/pressure2/qr-report/pipe'
  89. ]
  90. // 路由加载前
  91. // 路由加载前
  92. router.beforeEach(async (to, from, next) => {
  93. start()
  94. loadStart()
  95. const loginType = to.query.loginType as string
  96. const code = to.query.code as string
  97. // 处理单点登录
  98. if (loginType == 'cas' && code) {
  99. console.log('检测到SSO登录参数:', loginType )
  100. try {
  101. // 验证token并登录
  102. const loginSuccess = await validateAndLogin(code)
  103. console.log('SSO登录结果:', loginSuccess)
  104. if (loginSuccess) {
  105. // 登录成功,清除URL中的token参数
  106. const targetPath = to.path === '/' ? '/index' : to.path
  107. console.log('登录成功,跳转到:', targetPath)
  108. // 获取用户信息和权限
  109. const userStore = useUserStoreWithOut()
  110. const permissionStore = usePermissionStoreWithOut()
  111. const dictStore = useDictStoreWithOut()
  112. isRelogin.show = true
  113. // 加载字典
  114. if (!dictStore.getIsSetDict) {
  115. await dictStore.setDictMap()
  116. }
  117. // 加载用户信息
  118. await userStore.setUserInfoAction()
  119. // 加载菜单权限
  120. await permissionStore.generateRoutes()
  121. permissionStore.getAddRouters.forEach((route) => {
  122. router.addRoute(route as unknown as RouteRecordRaw)
  123. })
  124. loading.value.close()
  125. isRelogin.show = false
  126. // 跳转到目标页面,移除token参数
  127. next({
  128. path: targetPath,
  129. query: {},
  130. replace: true
  131. })
  132. } else {
  133. // token验证失败
  134. console.log('SSO token验证失败')
  135. loading.value.close()
  136. next('/login')
  137. }
  138. } catch (error) {
  139. console.error('SSO登录异常:', error)
  140. isRelogin.show = false
  141. next('/login')
  142. }
  143. return
  144. }
  145. // 正常的登录验证逻辑
  146. if (getAccessToken()) {
  147. if (to.path === '/login') {
  148. next({ path: '/' })
  149. } else {
  150. const dictStore = useDictStoreWithOut()
  151. const userStore = useUserStoreWithOut()
  152. const permissionStore = usePermissionStoreWithOut()
  153. if (!dictStore.getIsSetDict) {
  154. await dictStore.setDictMap()
  155. }
  156. if (!userStore.getIsSetUser) {
  157. isRelogin.show = true
  158. await userStore.setUserInfoAction()
  159. isRelogin.show = false
  160. await permissionStore.generateRoutes()
  161. permissionStore.getAddRouters.forEach((route) => {
  162. router.addRoute(route as unknown as RouteRecordRaw)
  163. })
  164. const redirectPath = from.query.redirect || to.path
  165. const redirect = decodeURIComponent(redirectPath as string)
  166. const { paramsObject: query } = parseURL(redirect)
  167. const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect, query }
  168. next(nextData)
  169. } else {
  170. next()
  171. }
  172. }
  173. } else {
  174. if (whiteList.indexOf(to.path) !== -1) {
  175. next()
  176. } else {
  177. next(`/login?redirect=${encodeURIComponent(to.fullPath)}`)
  178. }
  179. }
  180. })
  181. router.afterEach((to) => {
  182. useTitle(to?.meta?.title as string)
  183. done() // 结束Progress
  184. loadDone()
  185. })