import { ref, computed, watch } from 'vue' import { defineStore } from 'pinia' import { getJSON, setJSON, remove } from '@/utils/storage' import { clearAllTokens } from '@gold/utils/token-manager' // 本地持久化的 key const STORAGE_KEY = 'user_store_v1' export const useUserStore = defineStore('user', () => { // 基本信息 const isLoggedIn = ref(false) const userId = ref('') const nickname = ref('') const avatar = ref('') // 微信相关 const wechatOpenId = ref('') const wechatUnionId = ref('') const wechatNickname = ref('') const wechatAvatar = ref('') // 资产与配额 const balance = ref(0) const vipLevel = ref(0) const credits = ref(0) const displayName = computed(() => nickname.value || wechatNickname.value || '未命名用户') const displayAvatar = computed(() => avatar.value || wechatAvatar.value || '') // 恢复本地 async function hydrateFromStorage() { const saved = await getJSON(STORAGE_KEY) if (!saved) return isLoggedIn.value = !!saved.isLoggedIn userId.value = saved.userId || '' nickname.value = saved.nickname || '' avatar.value = saved.avatar || '' wechatOpenId.value = saved.wechatOpenId || '' wechatUnionId.value = saved.wechatUnionId || '' wechatNickname.value = saved.wechatNickname || '' wechatAvatar.value = saved.wechatAvatar || '' balance.value = Number(saved.balance || 0) vipLevel.value = Number(saved.vipLevel || 0) credits.value = Number(saved.credits || 0) } // 持久化 async function persist() { const payload = { isLoggedIn: isLoggedIn.value, userId: userId.value, nickname: nickname.value, avatar: avatar.value, wechatOpenId: wechatOpenId.value, wechatUnionId: wechatUnionId.value, wechatNickname: wechatNickname.value, wechatAvatar: wechatAvatar.value, balance: balance.value, vipLevel: vipLevel.value, credits: credits.value, } await setJSON(STORAGE_KEY, payload) } // 监听关键字段做持久化 ;[ isLoggedIn, userId, nickname, avatar, wechatOpenId, wechatUnionId, wechatNickname, wechatAvatar, balance, vipLevel, credits, ].forEach((s) => watch(s, persist)) // 登录/登出动作(示例:具体接入后端可在此对接) async function loginWithPhone(payload) { // payload: { phone, code, profile? } isLoggedIn.value = true userId.value = payload?.profile?.userId || userId.value nickname.value = payload?.profile?.nickname || nickname.value avatar.value = payload?.profile?.avatar || avatar.value balance.value = payload?.profile?.balance ?? balance.value vipLevel.value = payload?.profile?.vipLevel ?? vipLevel.value credits.value = payload?.profile?.credits ?? credits.value await persist() } async function loginWithWeChat(profile) { // profile: { openId, unionId, nickname, avatar, balance, vipLevel, credits } isLoggedIn.value = true wechatOpenId.value = profile?.openId || '' wechatUnionId.value = profile?.unionId || '' wechatNickname.value = profile?.nickname || '' wechatAvatar.value = profile?.avatar || '' balance.value = profile?.balance ?? balance.value vipLevel.value = profile?.vipLevel ?? vipLevel.value credits.value = profile?.credits ?? credits.value await persist() } async function updateBalance(delta) { balance.value = Math.max(0, Number(balance.value) + Number(delta || 0)) await persist() } /** * 获取用户信息(从后端) * 登录成功后调用,更新用户信息 * 使用公共 hook @gold/hooks/web/useUserInfo */ async function fetchUserInfo() { try { // 使用公共 hook 获取用户信息 const { getUserInfo } = await import('@gold/hooks/web/useUserInfo') const { getToken } = await import('@gold/utils/token-manager') const userInfo = await getUserInfo({ getToken, }) if (userInfo) { // 更新用户信息 userId.value = String(userInfo.id || userInfo.userId || userId.value) nickname.value = userInfo.nickname || nickname.value avatar.value = userInfo.avatar || avatar.value // 如果有其他字段,也可以更新 if (userInfo.point !== undefined) credits.value = Number(userInfo.point || 0) if (userInfo.experience !== undefined) { // experience 可以映射到其他字段,根据实际需求 } await persist() } } catch (error) { console.error('获取用户信息失败:', error) // 不抛出错误,避免影响登录流程 } } async function logout() { // 1. 清空所有 token try { clearAllTokens() } catch (e) { console.error('清空 token 失败:', e) } // 2. 清空用户信息 isLoggedIn.value = false userId.value = '' nickname.value = '' avatar.value = '' wechatOpenId.value = '' wechatUnionId.value = '' wechatNickname.value = '' wechatAvatar.value = '' balance.value = 0 vipLevel.value = 0 credits.value = 0 // 3. 删除本地存储的用户数据 await remove(STORAGE_KEY) } // 初始化标志 const isHydrated = ref(false) // 初始化从本地恢复 hydrateFromStorage().then(() => { isHydrated.value = true }) return { // 状态 isHydrated, // state isLoggedIn, userId, nickname, avatar, wechatOpenId, wechatUnionId, wechatNickname, wechatAvatar, balance, vipLevel, credits, // getters displayName, displayAvatar, // actions loginWithPhone, loginWithWeChat, updateBalance, fetchUserInfo, logout, } }) export default useUserStore