285 lines
7.4 KiB
TypeScript
285 lines
7.4 KiB
TypeScript
/**
|
|
* 认证状态管理
|
|
*/
|
|
|
|
import { defineStore } from 'pinia'
|
|
import { ref, computed } from 'vue'
|
|
import { ElMessage } from 'element-plus'
|
|
import AuthService from '@/services/auth'
|
|
import { handleApiError } from '@/utils/errorHandler'
|
|
import type {
|
|
LoginRequest,
|
|
RegisterRequest,
|
|
AuthResponse,
|
|
UserInfo
|
|
} from '@/types/auth'
|
|
|
|
export const useAuthStore = defineStore('auth', () => {
|
|
// 状态
|
|
const accessToken = ref<string>('')
|
|
const refreshToken = ref<string>('')
|
|
const userInfo = ref<UserInfo | null>(null)
|
|
// 移除权限状态,该功能不存在
|
|
const isLoading = ref(false)
|
|
|
|
// 计算属性
|
|
const isLoggedIn = computed(() => !!accessToken.value && !!userInfo.value)
|
|
const userId = computed(() => userInfo.value?.id || '')
|
|
const username = computed(() => userInfo.value?.username || '')
|
|
const nickname = computed(() => userInfo.value?.nickname || '')
|
|
const avatar = computed(() => userInfo.value?.avatar || '')
|
|
const email = computed(() => userInfo.value?.email || '')
|
|
const phone = computed(() => userInfo.value?.phone || '')
|
|
|
|
// 移除权限检查方法,该功能不存在
|
|
|
|
/**
|
|
* 初始化认证状态
|
|
*/
|
|
const initAuth = async () => {
|
|
try {
|
|
console.log('🔄 初始化认证状态...')
|
|
|
|
// 从本地存储恢复token
|
|
const storedAccessToken = localStorage.getItem('access_token')
|
|
const storedRefreshToken = localStorage.getItem('refresh_token')
|
|
const storedUserInfo = localStorage.getItem('user_info')
|
|
|
|
console.log('🔄 本地存储状态:', {
|
|
hasToken: !!storedAccessToken,
|
|
hasRefreshToken: !!storedRefreshToken,
|
|
hasUserInfo: !!storedUserInfo
|
|
})
|
|
|
|
if (storedAccessToken && storedUserInfo) {
|
|
// 恢复认证状态
|
|
accessToken.value = storedAccessToken
|
|
refreshToken.value = storedRefreshToken || ''
|
|
userInfo.value = JSON.parse(storedUserInfo)
|
|
|
|
console.log('🔄 认证状态已恢复')
|
|
|
|
// 简单验证:尝试获取用户信息来验证token是否有效
|
|
try {
|
|
await getCurrentUserInfo()
|
|
console.log('🔄 Token验证成功')
|
|
} catch (error) {
|
|
console.warn('🔄 Token可能已过期,但不强制登出:', error)
|
|
// 不强制登出,让用户在下次API调用时处理
|
|
}
|
|
} else {
|
|
console.log('🔄 无有效的本地认证信息')
|
|
}
|
|
} catch (error) {
|
|
console.error('🔄 初始化认证状态失败:', error)
|
|
// 不自动登出,避免清除用户刚登录的状态
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 用户登录
|
|
*/
|
|
const login = async (loginData: LoginRequest): Promise<boolean> => {
|
|
try {
|
|
isLoading.value = true
|
|
|
|
console.log('🔐 开始登录流程...')
|
|
const response = await AuthService.login(loginData)
|
|
console.log('🔐 登录响应数据:', response)
|
|
|
|
// 保存认证信息
|
|
setAuthData(response)
|
|
console.log('🔐 认证信息已保存')
|
|
|
|
// 验证token是否正确保存
|
|
const savedToken = localStorage.getItem('access_token')
|
|
console.log('🔐 保存的token:', savedToken ? '已保存' : '未保存')
|
|
|
|
// 获取最新的用户信息
|
|
await getCurrentUserInfo()
|
|
|
|
ElMessage.success('登录成功')
|
|
return true
|
|
} catch (error: any) {
|
|
console.error('🔐 登录失败:', error)
|
|
handleApiError(error, '用户登录')
|
|
return false
|
|
} finally {
|
|
isLoading.value = false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 用户注册
|
|
*/
|
|
const register = async (registerData: RegisterRequest): Promise<boolean> => {
|
|
try {
|
|
isLoading.value = true
|
|
|
|
const response = await AuthService.register(registerData)
|
|
|
|
// 保存认证信息
|
|
setAuthData(response)
|
|
|
|
// 移除权限获取,该接口不存在
|
|
|
|
ElMessage.success('注册成功')
|
|
return true
|
|
} catch (error: any) {
|
|
handleApiError(error, '用户注册')
|
|
return false
|
|
} finally {
|
|
isLoading.value = false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 用户登出
|
|
*/
|
|
const logout = async (): Promise<void> => {
|
|
try {
|
|
// 调用登出接口
|
|
if (accessToken.value) {
|
|
await AuthService.logout()
|
|
}
|
|
} catch (error) {
|
|
console.error('登出接口调用失败:', error)
|
|
} finally {
|
|
// 清除本地状态
|
|
clearAuthData()
|
|
ElMessage.success('已退出登录')
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 刷新Token
|
|
*/
|
|
const refreshAccessToken = async (): Promise<boolean> => {
|
|
try {
|
|
if (!refreshToken.value) {
|
|
throw new Error('没有刷新令牌')
|
|
}
|
|
|
|
const response = await AuthService.refreshToken({
|
|
refreshToken: refreshToken.value
|
|
})
|
|
|
|
// 更新认证信息
|
|
setAuthData(response)
|
|
|
|
return true
|
|
} catch (error) {
|
|
console.error('刷新Token失败:', error)
|
|
// 刷新失败,清除认证状态
|
|
await logout()
|
|
return false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取当前用户信息
|
|
*/
|
|
const getCurrentUserInfo = async (): Promise<void> => {
|
|
try {
|
|
const response = await AuthService.getCurrentUserInfo()
|
|
// 后端直接返回用户信息,不是嵌套在userInfo字段中
|
|
userInfo.value = response
|
|
|
|
// 更新本地存储
|
|
localStorage.setItem('user_info', JSON.stringify(response))
|
|
} catch (error) {
|
|
console.error('获取用户信息失败:', error)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 静默恢复本地认证状态(不进行API调用)
|
|
*/
|
|
const restoreLocalAuth = () => {
|
|
try {
|
|
const storedAccessToken = localStorage.getItem('access_token')
|
|
const storedRefreshToken = localStorage.getItem('refresh_token')
|
|
const storedUserInfo = localStorage.getItem('user_info')
|
|
|
|
if (storedAccessToken && storedUserInfo) {
|
|
accessToken.value = storedAccessToken
|
|
refreshToken.value = storedRefreshToken || ''
|
|
userInfo.value = JSON.parse(storedUserInfo)
|
|
console.log('🔄 本地认证状态已恢复')
|
|
return true
|
|
}
|
|
return false
|
|
} catch (error) {
|
|
console.error('🔄 恢复本地认证状态失败:', error)
|
|
return false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 设置认证数据
|
|
*/
|
|
const setAuthData = (authData: AuthResponse): void => {
|
|
accessToken.value = authData.accessToken
|
|
refreshToken.value = authData.refreshToken
|
|
userInfo.value = authData.userInfo
|
|
|
|
// 保存到本地存储
|
|
localStorage.setItem('access_token', authData.accessToken)
|
|
localStorage.setItem('refresh_token', authData.refreshToken)
|
|
localStorage.setItem('user_info', JSON.stringify(authData.userInfo))
|
|
}
|
|
|
|
/**
|
|
* 清除认证数据
|
|
*/
|
|
const clearAuthData = (): void => {
|
|
accessToken.value = ''
|
|
refreshToken.value = ''
|
|
userInfo.value = null
|
|
|
|
// 清除本地存储
|
|
localStorage.removeItem('access_token')
|
|
localStorage.removeItem('refresh_token')
|
|
localStorage.removeItem('user_info')
|
|
}
|
|
|
|
/**
|
|
* 更新用户信息
|
|
*/
|
|
const updateUserInfo = (newUserInfo: Partial<UserInfo>): void => {
|
|
if (userInfo.value) {
|
|
userInfo.value = { ...userInfo.value, ...newUserInfo }
|
|
localStorage.setItem('user_info', JSON.stringify(userInfo.value))
|
|
}
|
|
}
|
|
|
|
return {
|
|
// 状态
|
|
accessToken,
|
|
refreshToken,
|
|
userInfo,
|
|
isLoading,
|
|
|
|
// 计算属性
|
|
isLoggedIn,
|
|
userId,
|
|
username,
|
|
nickname,
|
|
avatar,
|
|
email,
|
|
phone,
|
|
|
|
// 方法
|
|
initAuth,
|
|
restoreLocalAuth,
|
|
login,
|
|
register,
|
|
logout,
|
|
refreshAccessToken,
|
|
getCurrentUserInfo,
|
|
setAuthData,
|
|
clearAuthData,
|
|
updateUserInfo
|
|
}
|
|
})
|