import { defineStore } from 'pinia' import { ref, computed } from 'vue' import { login, register, logout, getCurrentUser } from '@/api/auth' export const useUserStore = defineStore('user', () => { // 状态 - 从 sessionStorage 尝试恢复用户信息 const user = ref(null) const token = ref(null) const loading = ref(false) const initialized = ref(false) try { const cachedUser = sessionStorage.getItem('user') const cachedToken = sessionStorage.getItem('token') if (cachedUser && cachedToken) { user.value = JSON.parse(cachedUser) token.value = cachedToken } } catch (_) { // ignore sessionStorage parse errors } // 计算属性 const isAuthenticated = computed(() => !!user.value) const isAdmin = computed(() => user.value?.role === 'ROLE_ADMIN') const username = computed(() => user.value?.username || '') // 可用积分(总积分 - 冻结积分) const availablePoints = computed(() => { if (!user.value) return 0 const total = user.value.points || 0 const frozen = user.value.frozenPoints || 0 return Math.max(0, total - frozen) }) // 登录 const loginUser = async (credentials) => { try { loading.value = true const response = await login(credentials) if (response.success) { // 使用JWT认证,保存token和用户信息 user.value = response.data.user token.value = response.data.token // 保存到sessionStorage,关闭页面时自动清除 sessionStorage.setItem('token', response.data.token) sessionStorage.setItem('user', JSON.stringify(user.value)) return { success: true } } else { return { success: false, message: response.message } } } catch (error) { console.error('Login error:', error) return { success: false, message: '登录失败,请检查网络连接' } } finally { loading.value = false } } // 注册 const registerUser = async (userData) => { try { loading.value = true const response = await register(userData) if (response.success) { return { success: true, message: '注册成功,请登录' } } else { return { success: false, message: response.message } } } catch (error) { console.error('Register error:', error) return { success: false, message: '注册失败,请检查网络连接' } } finally { loading.value = false } } // 登出 const logoutUser = async () => { try { // JWT无状态,直接清除sessionStorage即可 token.value = null user.value = null sessionStorage.removeItem('token') sessionStorage.removeItem('user') } catch (error) { console.error('Logout error:', error) } } // 获取当前用户信息 const fetchCurrentUser = async () => { try { const response = await getCurrentUser() // 统一使用 response.data 格式 const data = response.data || response if (data.success) { user.value = data.data sessionStorage.setItem('user', JSON.stringify(user.value)) } else { console.warn('获取用户信息失败:', data.message) // 不要立即清除用户数据,保持当前登录状态 // 只在明确的401/认证失败时才由axios拦截器处理登出 } } catch (error) { console.error('Fetch user error:', error) // 请求失败时不强制清除,保持现有本地态 } } // 清除用户数据 const clearUserData = () => { token.value = null user.value = null // 清除 sessionStorage 中的用户数据 sessionStorage.removeItem('token') sessionStorage.removeItem('user') } // 初始化 const init = async () => { if (initialized.value) { return } // 从sessionStorage恢复用户状态 const savedToken = sessionStorage.getItem('token') const savedUser = sessionStorage.getItem('user') if (savedToken && savedUser) { try { token.value = savedToken user.value = JSON.parse(savedUser) // 只在开发环境输出详细日志 if (process.env.NODE_ENV === 'development') { console.log('恢复用户状态:', user.value?.username, '角色:', user.value?.role) } } catch (error) { console.error('Failed to restore user state:', error) clearUserData() } } initialized.value = true } return { // 状态 user, token, loading, // 计算属性 isAuthenticated, isAdmin, username, availablePoints, // 方法 loginUser, registerUser, logoutUser, fetchCurrentUser, clearUserData, init, initialized } })