105 lines
2.6 KiB
TypeScript
105 lines
2.6 KiB
TypeScript
import { defineStore } from 'pinia'
|
||
import { ref, computed } from 'vue'
|
||
import { login as loginApi, logout as logoutApi } from '@/api/auth'
|
||
import type { LoginRequest } from '@/types'
|
||
|
||
export const useUserStore = defineStore('user', () => {
|
||
const token = ref(localStorage.getItem('token') || '')
|
||
const userInfo = ref<{ username: string; realName: string } | null>(null)
|
||
const roles = ref<string[]>([])
|
||
|
||
const hasRole = (role: string) => {
|
||
return roles.value.includes(role)
|
||
}
|
||
|
||
const hasAnyRole = (checkRoles: string[]) => {
|
||
return checkRoles.some(role => roles.value.includes(role))
|
||
}
|
||
|
||
const isAdmin = computed(() => {
|
||
return roles.value.includes('SYS_ADMIN')
|
||
})
|
||
|
||
const login = async (data: LoginRequest) => {
|
||
const res = await loginApi(data)
|
||
const loginData = res.data.data
|
||
if (!loginData?.token) {
|
||
throw new Error('登录失败:未获取到token')
|
||
}
|
||
const newToken = loginData.token
|
||
token.value = newToken
|
||
userInfo.value = {
|
||
username: loginData.username,
|
||
realName: loginData.realName
|
||
}
|
||
roles.value = loginData.roles || []
|
||
localStorage.setItem('token', newToken)
|
||
localStorage.setItem('userInfo', JSON.stringify(userInfo.value))
|
||
localStorage.setItem('roles', JSON.stringify(roles.value))
|
||
}
|
||
|
||
const logout = async () => {
|
||
await logoutApi()
|
||
token.value = ''
|
||
userInfo.value = null
|
||
roles.value = []
|
||
localStorage.removeItem('token')
|
||
localStorage.removeItem('userInfo')
|
||
localStorage.removeItem('roles')
|
||
}
|
||
|
||
const isLoggedIn = () => {
|
||
const storedToken = localStorage.getItem('token')
|
||
if (!storedToken || storedToken === 'null' || storedToken === 'undefined') {
|
||
return false
|
||
}
|
||
const parts = storedToken.split('.')
|
||
if (parts.length !== 3) {
|
||
return false
|
||
}
|
||
try {
|
||
const payload = JSON.parse(atob(parts[1]))
|
||
if (payload.exp && payload.exp * 1000 < Date.now()) {
|
||
logout()
|
||
return false
|
||
}
|
||
} catch {
|
||
return false
|
||
}
|
||
return true
|
||
}
|
||
|
||
const initFromStorage = () => {
|
||
const storedRoles = localStorage.getItem('roles')
|
||
if (storedRoles) {
|
||
try {
|
||
roles.value = JSON.parse(storedRoles)
|
||
} catch {
|
||
roles.value = []
|
||
}
|
||
}
|
||
const storedUserInfo = localStorage.getItem('userInfo')
|
||
if (storedUserInfo) {
|
||
try {
|
||
userInfo.value = JSON.parse(storedUserInfo)
|
||
} catch {
|
||
userInfo.value = null
|
||
}
|
||
}
|
||
}
|
||
|
||
initFromStorage()
|
||
|
||
return {
|
||
token,
|
||
userInfo,
|
||
roles,
|
||
hasRole,
|
||
hasAnyRole,
|
||
isAdmin,
|
||
login,
|
||
logout,
|
||
isLoggedIn
|
||
}
|
||
})
|