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(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) /** * 判断当前是否已登录 * token 存在且已验证有效才算已登录 */ const isLoggedIn = () => isTokenValid.value /** * 初始化认证状态 * * 用持久化的 Access Token 向服务端验证是否仍然有效。 * 只会在首次调用时真正发请求,后续调用直接跳过。 * * - 无 token → 无操作 * - token 有效 → 拉取用户信息,标记已登录 * - token 过期 → 尝试用 Refresh Token 刷新,刷新失败则清除 */ const initAuth = async () => { // 已验证过,跳过 if (isInitialized.value) return isInitialized.value = true // 没有持久化的 Access Token if (!accessToken.value) return try { await fetchUserInfo() // 成功获取用户信息,token 有效 isTokenValid.value = true } catch { // Access Token 可能过期,尝试用 Refresh Token 刷新 if (refreshToken.value) { try { await doRefresh() isTokenValid.value = true } catch { // 刷新也失败,清除 clearAuth() } } else { clearAuth() } } } /** * 用户登录 * 调用登录 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 } /** * 使用 Refresh Token 刷新 Access Token * 成功后更新 accessToken,Refresh Token 不变(由服务端行为决定) */ const doRefresh = async () => { const res = await refreshApi({ refreshToken: refreshToken.value }) accessToken.value = res.data.accessToken // 如果服务端返回了新的 refreshToken 则更新 if (res.data.refreshToken) { refreshToken.value = res.data.refreshToken } await fetchUserInfo() } /** 清除所有认证状态 */ const clearAuth = () => { accessToken.value = '' refreshToken.value = '' accountInfo.value = null isTokenValid.value = false isInitialized.value = false } return { accountInfo, accessToken, refreshToken, isLoggedIn, initAuth, login, register, logout, fetchUserInfo } }, { persist: { pick: ['accessToken', 'refreshToken'] } } )