160 lines
4.2 KiB
JavaScript
160 lines
4.2 KiB
JavaScript
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 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()
|
||
if (response.success) {
|
||
user.value = response.data
|
||
sessionStorage.setItem('user', JSON.stringify(user.value))
|
||
} else {
|
||
// 会话无效,清除本地存储
|
||
clearUserData()
|
||
}
|
||
} 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,
|
||
// 方法
|
||
loginUser,
|
||
registerUser,
|
||
logoutUser,
|
||
fetchCurrentUser,
|
||
clearUserData,
|
||
init,
|
||
initialized
|
||
}
|
||
})
|