import { defineStore } from 'pinia' import { ref, computed } from 'vue' import authService from '@/api/authService' import { checkUserVip } from '@/utils/appUtils' export const useUserStore = defineStore('user', () => { const username = ref('') const isVip = ref(false) const avatarUrl = ref('') const membershipExpireAt = ref(null) const userInfoRaw = ref(null) // 响应式保存最新完整的用户原始数据 const tokenChecked = ref(false) // 是否已完成 Token 校验 const tokenValid = ref(false) // Token 是否真实有效 // 严谨的全局登录状态判定:必须 Token 有效、用户名存在且本地有 token 凭证 const isLoggedIn = computed(() => { return tokenValid.value && !!username.value && !!localStorage.getItem('token') }) // 设置/保存用户信息 function setUser(data, fallbackPhone = '') { if (!data) return const userObj = data.user || data userInfoRaw.value = userObj // 写入本地缓存,供快照加载与 checkUserVip 自动使用 try { localStorage.setItem('user_info', JSON.stringify(userObj)) } catch (e) { } // 游客账号特征判断:temp 为 true,或角色 role 为 '8',或名称包含 '游客' const isGuest = userObj.temp === true || userObj.role === '8' || userObj.name === '游客' || userObj.nickname === '游客' if (isGuest) { username.value = '' isVip.value = false avatarUrl.value = '' tokenChecked.value = true tokenValid.value = false return } username.value = userObj.name || '已登录用户' isVip.value = checkUserVip(userObj) avatarUrl.value = userObj.avater || userObj.avatar || '' membershipExpireAt.value = userObj.vip_expire || null tokenChecked.value = true tokenValid.value = true } let fetchPromise = null async function fetchProfile() { const token = localStorage.getItem('token') if (!token) { reset() return null } // 1. 本地快照秒开:瞬间解析 user_info 填充响应式数据,0毫秒延迟 const localUserInfo = localStorage.getItem('user_info') if (localUserInfo) { try { const parsed = JSON.parse(localUserInfo) setUser(parsed) } catch (e) { } } // 2. 防并发防阻塞:如果后台已有进行中的网络校验,直接复用 Promise if (fetchPromise) { return fetchPromise } // 3. 实时后台接口校验:精准兼容多种 Api 返回数据结构并更新 store 与缓存 fetchPromise = (async () => { try { const res = await authService.getUserInfo() // 兼容 res.data 结构以及直接返回用户对象的结构 const userData = (res && res.data) ? res.data : (res && (res.vip !== undefined || res.user_id || res.name) ? res : null) if (userData) { setUser(userData) console.log("最新后台用户信息已同步:", userData) return userData } else if (res && res.code && res.code !== 0) { reset() } } catch (e) { console.error("同步后台用户信息异常:", e) } finally { fetchPromise = null } })() return fetchPromise } function reset() { username.value = '' isVip.value = false avatarUrl.value = '' membershipExpireAt.value = null userInfoRaw.value = null tokenChecked.value = true tokenValid.value = false localStorage.removeItem('token') localStorage.removeItem('user_info') } return { username, isVip, avatarUrl, membershipExpireAt, userInfoRaw, tokenChecked, tokenValid, isLoggedIn, setUser, fetchProfile, reset, checkVip: checkUserVip } })