Files
happy-life-star/web/src/stores/auth.ts
T

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
}
})