auth.ts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. import { defineStore } from 'pinia'
  2. import { ApiCode } from '@/config'
  3. import { fetchUserInfo, login, logoutRequest, type LoginBody } from '@/service/auth'
  4. // import { loginValid } from '@/service/auth' // 恢复二步登录时取消注释
  5. import { syncTokenToHttpDefaults } from '@/service/http'
  6. import type { UserInfo } from '@/types/user'
  7. import { loggedIn } from '@/utils/auth'
  8. import { session } from '@/utils/session'
  9. import { usePermissionStore } from './permission'
  10. import { useVaultStore } from './vault'
  11. export const useAuthStore = defineStore('auth', {
  12. state: () => ({
  13. token: null as string | null,
  14. user: null as UserInfo | null,
  15. expire: false,
  16. /** 防止多处同时触发 info 请求 */
  17. userInfoRefreshInFlight: false,
  18. }),
  19. getters: {
  20. isLoggedIn: (s) => !!s.user && session.IsExist('user'),
  21. },
  22. actions: {
  23. hydrateFromSession(): void {
  24. this.token = sessionStorage.getItem('access_token')
  25. const raw = session.Get('user', true)
  26. if (raw) {
  27. try {
  28. this.user = JSON.parse(raw) as UserInfo
  29. } catch {
  30. this.user = null
  31. }
  32. } else {
  33. this.user = null
  34. }
  35. // 动态侧栏:由后端 user.display 写入 permission store(恢复时取消注释)
  36. // if (this.user?.display) {
  37. // usePermissionStore().initFromUserDisplay(this.user.display)
  38. // }
  39. syncTokenToHttpDefaults()
  40. },
  41. setAccessToken(token: string): void {
  42. this.token = token
  43. sessionStorage.setItem('access_token', token)
  44. syncTokenToHttpDefaults()
  45. },
  46. setUserInfo(user: UserInfo): void {
  47. this.user = user
  48. session.Set('user', JSON.stringify(user), true)
  49. // if (user.display) {
  50. // usePermissionStore().initFromUserDisplay(user.display)
  51. // }
  52. },
  53. setExpire(v: boolean): void {
  54. this.expire = v
  55. },
  56. async fetchAndStoreUser(): Promise<boolean> {
  57. try {
  58. const res = await fetchUserInfo()
  59. if (res.code === ApiCode.StatusOK && res.data) {
  60. this.setUserInfo(res.data as UserInfo)
  61. this.setExpire(false)
  62. return true
  63. }
  64. return false
  65. } catch {
  66. return false
  67. }
  68. },
  69. /**
  70. * 全局静默同步用户信息。
  71. * (恢复 display 驱动菜单时,setUserInfo 内 initFromUserDisplay 一并恢复。)
  72. */
  73. async refreshUserInfoFromServer(): Promise<void> {
  74. if (!sessionStorage.getItem('access_token')) return
  75. if (!loggedIn()) return
  76. if (this.userInfoRefreshInFlight) return
  77. this.userInfoRefreshInFlight = true
  78. try {
  79. await this.fetchAndStoreUser()
  80. } finally {
  81. this.userInfoRefreshInFlight = false
  82. }
  83. },
  84. async doPasswordLogin(body: LoginBody): Promise<boolean> {
  85. try {
  86. const res = await login(body)
  87. if (res.code === ApiCode.StatusOK && res.data) {
  88. this.setAccessToken(res.data as string)
  89. return await this.fetchAndStoreUser()
  90. }
  91. return false
  92. } catch {
  93. return false
  94. }
  95. },
  96. /** 暂不使用:先 /user/login/valid 再弹二步;恢复时与 LoginView 二步流程一起启用 */
  97. // async validateThenOpenSecondStep(loginName: string, password: string): Promise<1 | 0 | null> {
  98. // const res = await loginValid({ loginName, password })
  99. // if (res.code === ApiCode.StatusOK && res.data !== undefined && res.data !== null) {
  100. // return res.data === 1 ? 1 : 0
  101. // }
  102. // return null
  103. // },
  104. async logout(): Promise<boolean> {
  105. const res = await logoutRequest()
  106. if (res.code === ApiCode.StatusOK) {
  107. this.clearSession()
  108. return true
  109. }
  110. return false
  111. },
  112. clearSession(): void {
  113. sessionStorage.clear()
  114. this.token = null
  115. this.user = null
  116. this.expire = false
  117. usePermissionStore().clear()
  118. useVaultStore().clear()
  119. syncTokenToHttpDefaults()
  120. },
  121. },
  122. })