215 lines
5.5 KiB
JavaScript
215 lines
5.5 KiB
JavaScript
|
|
import { defineStore } from 'pinia'
|
|||
|
|
import { ref, computed } from 'vue'
|
|||
|
|
import api from '@/utils/api'
|
|||
|
|
import { ElMessage } from 'element-plus'
|
|||
|
|
|
|||
|
|
export const useUserStore = defineStore('user', () => {
|
|||
|
|
// 状态
|
|||
|
|
const user = ref(null)
|
|||
|
|
const token = ref(localStorage.getItem('token') || '')
|
|||
|
|
const loading = ref(false)
|
|||
|
|
|
|||
|
|
// 计算属性
|
|||
|
|
const isAuthenticated = computed(() => {
|
|||
|
|
return !!token.value && !!user.value
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
const isAdmin = computed(() => {
|
|||
|
|
return user.value?.role === 'admin'
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
// 设置token
|
|||
|
|
const setToken = (newToken) => {
|
|||
|
|
token.value = newToken
|
|||
|
|
if (newToken) {
|
|||
|
|
localStorage.setItem('token', newToken)
|
|||
|
|
api.defaults.headers.common['Authorization'] = `Bearer ${newToken}`
|
|||
|
|
} else {
|
|||
|
|
localStorage.removeItem('token')
|
|||
|
|
delete api.defaults.headers.common['Authorization']
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 设置用户信息
|
|||
|
|
const setUser = (userData) => {
|
|||
|
|
user.value = userData
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 登录
|
|||
|
|
const login = async (credentials) => {
|
|||
|
|
try {
|
|||
|
|
loading.value = true
|
|||
|
|
const response = await api.post('/auth/login', credentials)
|
|||
|
|
|
|||
|
|
if (response.data.token) {
|
|||
|
|
setToken(response.data.token)
|
|||
|
|
setUser(response.data.user)
|
|||
|
|
startStatusCheck() // 登录成功后开始状态检查
|
|||
|
|
ElMessage.success(response.data.message || '登录成功')
|
|||
|
|
return { success: true, data: response.data }
|
|||
|
|
}
|
|||
|
|
} catch (error) {
|
|||
|
|
const message = error.response?.data?.message || '登录失败'
|
|||
|
|
ElMessage.error(message)
|
|||
|
|
return { success: false, message }
|
|||
|
|
} finally {
|
|||
|
|
loading.value = false
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 注册
|
|||
|
|
const register = async (userData) => {
|
|||
|
|
try {
|
|||
|
|
loading.value = true
|
|||
|
|
const response = await api.post('/auth/register', userData)
|
|||
|
|
|
|||
|
|
if (response.data.token) {
|
|||
|
|
setToken(response.data.token)
|
|||
|
|
setUser(response.data.user)
|
|||
|
|
ElMessage.success(response.data.message || '注册成功')
|
|||
|
|
return { success: true, data: response.data }
|
|||
|
|
}
|
|||
|
|
} catch (error) {
|
|||
|
|
const message = error.response?.data?.message || '注册失败'
|
|||
|
|
ElMessage.error(message)
|
|||
|
|
return { success: false, message }
|
|||
|
|
} finally {
|
|||
|
|
loading.value = false
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 登出
|
|||
|
|
const logout = () => {
|
|||
|
|
stopStatusCheck() // 登出时停止状态检查
|
|||
|
|
setToken('')
|
|||
|
|
setUser(null)
|
|||
|
|
ElMessage.success('已退出登录')
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 检查认证状态
|
|||
|
|
const checkAuth = async () => {
|
|||
|
|
if (!token.value) {
|
|||
|
|
return false
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
// 确保请求头已设置
|
|||
|
|
if (token.value && !api.defaults.headers.common['Authorization']) {
|
|||
|
|
api.defaults.headers.common['Authorization'] = `Bearer ${token.value}`
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const response = await api.get('/auth/me')
|
|||
|
|
setUser(response.data.user)
|
|||
|
|
return true
|
|||
|
|
} catch (error) {
|
|||
|
|
// token无效,清除本地存储
|
|||
|
|
setToken('')
|
|||
|
|
setUser(null)
|
|||
|
|
return false
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 更新用户信息
|
|||
|
|
const updateProfile = async (userData) => {
|
|||
|
|
try {
|
|||
|
|
loading.value = true
|
|||
|
|
const response = await api.put(`/users/${user.value.id}`, userData)
|
|||
|
|
|
|||
|
|
setUser(response.data.user)
|
|||
|
|
ElMessage.success(response.data.message || '更新成功')
|
|||
|
|
return { success: true, data: response.data }
|
|||
|
|
} catch (error) {
|
|||
|
|
const message = error.response?.data?.message || '更新失败'
|
|||
|
|
ElMessage.error(message)
|
|||
|
|
return { success: false, message }
|
|||
|
|
} finally {
|
|||
|
|
loading.value = false
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 修改密码
|
|||
|
|
const changePassword = async (passwordData) => {
|
|||
|
|
try {
|
|||
|
|
loading.value = true
|
|||
|
|
const response = await api.put('/auth/change-password', passwordData)
|
|||
|
|
|
|||
|
|
ElMessage.success(response.data.message || '密码修改成功')
|
|||
|
|
return { success: true, data: response.data }
|
|||
|
|
} catch (error) {
|
|||
|
|
const message = error.response?.data?.message || '密码修改失败'
|
|||
|
|
ElMessage.error(message)
|
|||
|
|
return { success: false, message }
|
|||
|
|
} finally {
|
|||
|
|
loading.value = false
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取用户详情
|
|||
|
|
const getUserInfo = async (userId) => {
|
|||
|
|
try {
|
|||
|
|
const response = await api.get(`/users/${userId}`)
|
|||
|
|
return { success: true, data: response.data.user }
|
|||
|
|
} catch (error) {
|
|||
|
|
const message = error.response?.data?.message || '获取用户信息失败'
|
|||
|
|
return { success: false, message }
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 定期检查用户状态(用于检测拉黑等状态变化)
|
|||
|
|
let statusCheckInterval = null
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 开始定期检查用户状态
|
|||
|
|
* 每5分钟检查一次用户状态,确保及时发现被拉黑等情况
|
|||
|
|
*/
|
|||
|
|
const startStatusCheck = () => {
|
|||
|
|
if (statusCheckInterval) {
|
|||
|
|
clearInterval(statusCheckInterval)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
statusCheckInterval = setInterval(async () => {
|
|||
|
|
if (isAuthenticated.value) {
|
|||
|
|
try {
|
|||
|
|
await api.get('/auth/me')
|
|||
|
|
} catch (error) {
|
|||
|
|
// 如果是拉黑错误,API拦截器会自动处理
|
|||
|
|
// 这里不需要额外处理
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}, 5 * 60 * 1000) // 5分钟检查一次
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 停止定期检查用户状态
|
|||
|
|
*/
|
|||
|
|
const stopStatusCheck = () => {
|
|||
|
|
if (statusCheckInterval) {
|
|||
|
|
clearInterval(statusCheckInterval)
|
|||
|
|
statusCheckInterval = null
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
// 状态
|
|||
|
|
user,
|
|||
|
|
token,
|
|||
|
|
loading,
|
|||
|
|
|
|||
|
|
// 计算属性
|
|||
|
|
isAuthenticated,
|
|||
|
|
isAdmin,
|
|||
|
|
|
|||
|
|
// 方法
|
|||
|
|
setToken,
|
|||
|
|
setUser,
|
|||
|
|
login,
|
|||
|
|
register,
|
|||
|
|
logout,
|
|||
|
|
checkAuth,
|
|||
|
|
updateProfile,
|
|||
|
|
changePassword,
|
|||
|
|
getUserInfo,
|
|||
|
|
startStatusCheck,
|
|||
|
|
stopStatusCheck
|
|||
|
|
}
|
|||
|
|
})
|