136 lines
3.5 KiB
TypeScript
136 lines
3.5 KiB
TypeScript
import { defineStore } from 'pinia'
|
||
import { ref } from 'vue'
|
||
import {
|
||
login as loginApi,
|
||
register as registerApi,
|
||
refresh as refreshApi,
|
||
type LoginRequest,
|
||
type RegisterRequest
|
||
} from '@/api/modules/account'
|
||
import { getUserInfo } from '@/api/modules/user'
|
||
|
||
/** 账户信息 */
|
||
export interface AccountState {
|
||
/** 用户昵称 */
|
||
nickName?: string
|
||
/** 头像 */
|
||
avatar?: string | null
|
||
/** 个性签名 */
|
||
signature?: string | null
|
||
/** 年龄 */
|
||
age?: number | null
|
||
/** 性别:1=男,2=女 */
|
||
sex?: number | null
|
||
/** 生日 */
|
||
birthday?: string | null
|
||
}
|
||
|
||
export const useAccountStore = defineStore(
|
||
'account',
|
||
() => {
|
||
/** 账户信息 */
|
||
const accountInfo = ref<AccountState | null>(null)
|
||
/** Access Token(30 分钟有效,每次请求通过 saToken 头携带) */
|
||
const accessToken = ref('')
|
||
/** Refresh Token(30 天有效,仅用于刷新 Access Token) */
|
||
const refreshToken = ref('')
|
||
/** token 是否已验证有效 */
|
||
const isTokenValid = ref(false)
|
||
/** 是否已完成初始验证(防止重复请求) */
|
||
const isInitialized = ref(false)
|
||
|
||
/**
|
||
* 用户登录
|
||
* 调用登录 API,成功后存储双 Token 并获取用户信息
|
||
* @param params - 登录请求参数(用户名、密码)
|
||
*/
|
||
const login = async (params: LoginRequest) => {
|
||
const res = await loginApi(params)
|
||
accessToken.value = res.data.accessToken
|
||
refreshToken.value = res.data.refreshToken
|
||
// await fetchUserInfo()
|
||
isTokenValid.value = true
|
||
}
|
||
|
||
/**
|
||
* 用户注册
|
||
* 调用注册 API,成功后自动登录(存储双 Token 并获取用户信息)
|
||
* @param params - 注册请求参数(用户名、密码)
|
||
*/
|
||
const register = async (params: RegisterRequest) => {
|
||
const res = await registerApi(params)
|
||
accessToken.value = res.data.accessToken
|
||
refreshToken.value = res.data.refreshToken
|
||
// await fetchUserInfo()
|
||
isTokenValid.value = true
|
||
}
|
||
|
||
/**
|
||
* 退出登录
|
||
* 清除令牌、账户信息和验证状态
|
||
*/
|
||
const logout = () => {
|
||
clearAuth()
|
||
}
|
||
|
||
/**
|
||
* 获取当前登录用户信息
|
||
* 需要先有 Access Token 才能调用
|
||
*/
|
||
const fetchUserInfo = async () => {
|
||
const res = await getUserInfo()
|
||
accountInfo.value = res.data
|
||
}
|
||
|
||
/**
|
||
* 刷新 Access Token
|
||
*
|
||
* 由刷新拦截器的 doRefreshToken 调用。
|
||
* 返回新的 Access Token 字符串,方便拦截器直接使用。
|
||
*
|
||
* @returns 新的 Access Token
|
||
*/
|
||
const refreshAccessToken = async (): Promise<string> => {
|
||
if (!refreshToken.value) {
|
||
throw new Error('无 Refresh Token,无法刷新')
|
||
}
|
||
|
||
const res = await refreshApi({ refreshToken: refreshToken.value })
|
||
accessToken.value = res.data.accessToken
|
||
if (res.data.refreshToken) {
|
||
refreshToken.value = res.data.refreshToken
|
||
}
|
||
isTokenValid.value = true
|
||
|
||
return accessToken.value
|
||
}
|
||
|
||
/** 清除所有认证状态 */
|
||
const clearAuth = () => {
|
||
accessToken.value = ''
|
||
refreshToken.value = ''
|
||
accountInfo.value = null
|
||
isTokenValid.value = false
|
||
isInitialized.value = false
|
||
}
|
||
|
||
console.log('useAccountStore', accessToken.value)
|
||
|
||
return {
|
||
accountInfo,
|
||
accessToken,
|
||
refreshToken,
|
||
login,
|
||
register,
|
||
logout,
|
||
refreshAccessToken,
|
||
fetchUserInfo
|
||
}
|
||
},
|
||
{
|
||
persist: {
|
||
pick: ['accessToken', 'refreshToken']
|
||
}
|
||
}
|
||
)
|