auth.ts 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import { defineStore } from 'pinia'
  2. import { ref, computed } from 'vue'
  3. import type { User } from '@/types/auth'
  4. import { UserRole } from '@/types/auth'
  5. import { authAPI, permissionAPI, STORAGE_KEYS } from '@/services/api'
  6. import type { PagePermission } from '@/types/auth'
  7. export const useAuthStore = defineStore('auth', () => {
  8. const user = ref<User | null>(null)
  9. const isLoading = ref(true)
  10. const userPermissions = ref<PagePermission[]>([])
  11. const isAuthenticated = computed(() => !!user.value)
  12. const loadUserPermissions = async (userId?: string) => {
  13. const targetUserId = userId || user.value?.id
  14. if (!targetUserId) return
  15. try {
  16. const response = await permissionAPI.getUserPermissions(targetUserId)
  17. if (response.success) {
  18. userPermissions.value = response.data || []
  19. }
  20. } catch {
  21. userPermissions.value = []
  22. }
  23. }
  24. const checkAuthStatus = async () => {
  25. try {
  26. const storedUser = localStorage.getItem(STORAGE_KEYS.USER)
  27. const token = localStorage.getItem(STORAGE_KEYS.TOKEN)
  28. if (storedUser && token) {
  29. const userData = JSON.parse(storedUser)
  30. user.value = userData
  31. try {
  32. const response = await authAPI.getCurrentUser()
  33. if (response.success) {
  34. user.value = response.data
  35. await loadUserPermissions()
  36. } else {
  37. try {
  38. const refreshResponse = await authAPI.refreshToken()
  39. if (refreshResponse.success && refreshResponse.data?.token) {
  40. localStorage.setItem(STORAGE_KEYS.TOKEN, refreshResponse.data.token)
  41. const userResponse = await authAPI.getCurrentUser()
  42. if (userResponse.success) {
  43. user.value = userResponse.data
  44. await loadUserPermissions()
  45. }
  46. }
  47. } catch {
  48. localStorage.removeItem(STORAGE_KEYS.USER)
  49. localStorage.removeItem(STORAGE_KEYS.TOKEN)
  50. user.value = null
  51. userPermissions.value = []
  52. }
  53. }
  54. } catch {
  55. localStorage.removeItem(STORAGE_KEYS.USER)
  56. localStorage.removeItem(STORAGE_KEYS.TOKEN)
  57. user.value = null
  58. userPermissions.value = []
  59. }
  60. } else {
  61. user.value = null
  62. userPermissions.value = []
  63. }
  64. } catch {
  65. localStorage.removeItem(STORAGE_KEYS.USER)
  66. localStorage.removeItem(STORAGE_KEYS.TOKEN)
  67. user.value = null
  68. userPermissions.value = []
  69. } finally {
  70. isLoading.value = false
  71. }
  72. }
  73. const login = async (credentials: { username: string; password: string }) => {
  74. isLoading.value = true
  75. try {
  76. const response = await authAPI.login(credentials)
  77. if (response.success && response.data) {
  78. const { user: userData, token } = response.data
  79. localStorage.setItem(STORAGE_KEYS.USER, JSON.stringify(userData))
  80. localStorage.setItem(STORAGE_KEYS.TOKEN, token)
  81. user.value = userData
  82. await loadUserPermissions(userData.id)
  83. } else {
  84. throw new Error(response.message || '登录失败')
  85. }
  86. } finally {
  87. isLoading.value = false
  88. }
  89. }
  90. const logout = () => {
  91. localStorage.removeItem(STORAGE_KEYS.USER)
  92. localStorage.removeItem(STORAGE_KEYS.TOKEN)
  93. user.value = null
  94. userPermissions.value = []
  95. }
  96. const hasPermission = (requiredRole: UserRole | string): boolean => {
  97. if (!user.value) return false
  98. if (typeof requiredRole === 'string') {
  99. if (Object.values(UserRole).includes(requiredRole as UserRole)) {
  100. const roleHierarchy: Record<string, number> = {
  101. [UserRole.ADMIN]: 3,
  102. [UserRole.USER]: 2,
  103. [UserRole.VIEWER]: 1
  104. }
  105. return (roleHierarchy[user.value.role] || 0) >= (roleHierarchy[requiredRole as UserRole] || 0)
  106. } else {
  107. return checkPagePermission(requiredRole)
  108. }
  109. }
  110. const roleHierarchy: Record<string, number> = {
  111. [UserRole.ADMIN]: 3,
  112. [UserRole.USER]: 2,
  113. [UserRole.VIEWER]: 1
  114. }
  115. return (roleHierarchy[user.value.role] || 0) >= (roleHierarchy[requiredRole] || 0)
  116. }
  117. const checkPagePermission = (pagePath: string): boolean => {
  118. if (!user.value) return false
  119. if (user.value.role === UserRole.ADMIN) return true
  120. return userPermissions.value.some(permission => pagePath.startsWith(permission.path))
  121. }
  122. return {
  123. user,
  124. isLoading,
  125. isAuthenticated,
  126. userPermissions,
  127. checkAuthStatus,
  128. login,
  129. logout,
  130. hasPermission,
  131. checkPagePermission,
  132. loadUserPermissions
  133. }
  134. })