interface UserInfo { _id: string; openid: string; unionid: string | null; nickName: string | null; avatarUrl: string | null; totalDownloads: number; createdAt: string; lastActiveAt: string; } const STORAGE_KEY = 'user_info'; const STORAGE_EXPIRE_KEY = 'user_info_expire'; const EXPIRE_DURATION = 7 * 24 * 60 * 60 * 1000; // 7 天 /** 内存中的用户数据(App 生命周期内有效) */ let currentUser: UserInfo | null = null; /** 登录进行中的 Promise(防止并发重复调用) */ let loginPromise: Promise | null = null; function syncAppGlobalUser(user: UserInfo | null): void { try { const app = getApp(); if (app?.globalData) { app.globalData.user = user; } } catch { // App 尚未初始化时忽略 } } function syncUserState(user: UserInfo, persist = true): UserInfo { currentUser = user; if (persist) { saveToStorage(user); } syncAppGlobalUser(user); return user; } /** * 获取当前用户,优先内存 → Storage → 云函数登录 */ export async function getUser(): Promise { // 1. 内存中有,直接返回 if (currentUser) { syncAppGlobalUser(currentUser); return currentUser; } // 2. 尝试从 Storage 读取 const cached = loadFromStorage(); if (cached) { return syncUserState(cached, false); } // 3. 静默登录(防止并发) if (!loginPromise) { loginPromise = silentLogin().finally(() => { loginPromise = null; }); } return loginPromise; } /** * 静默登录:调用云函数 */ async function silentLogin(): Promise { const res = await wx.cloud.callFunction({ name: 'userLogin', }); const result = (res?.result as any) || {}; if (result.code !== 0) { throw new Error('登录失败'); } const user = result.data as UserInfo; return syncUserState(user); } export function getCachedUser(): UserInfo | null { if (currentUser) { syncAppGlobalUser(currentUser); return currentUser; } const cached = loadFromStorage(); if (!cached) return null; return syncUserState(cached, false); } /** * 从 Storage 读取用户数据(检查过期) */ function loadFromStorage(): UserInfo | null { try { const expire = wx.getStorageSync(STORAGE_EXPIRE_KEY); if (!expire || Date.now() > expire) { wx.removeStorageSync(STORAGE_KEY); wx.removeStorageSync(STORAGE_EXPIRE_KEY); return null; } const user = wx.getStorageSync(STORAGE_KEY); return user || null; } catch { return null; } } /** * 写入 Storage */ function saveToStorage(user: UserInfo): void { try { wx.setStorageSync(STORAGE_KEY, user); wx.setStorageSync(STORAGE_EXPIRE_KEY, Date.now() + EXPIRE_DURATION); } catch { // Storage 写入失败不影响主流程 } } /** * 清除登录状态 */ export function clearUser(): void { currentUser = null; syncAppGlobalUser(null); wx.removeStorageSync(STORAGE_KEY); wx.removeStorageSync(STORAGE_EXPIRE_KEY); } /** * 强制刷新用户数据(跳过缓存) */ export async function refreshUser(): Promise { clearUser(); return await silentLogin(); } export async function updateUserProfile(payload: { nickName?: string | null; avatarUrl?: string | null; }): Promise { await getUser(); const res = await wx.cloud.callFunction({ name: 'userLogin', data: { action: 'updateProfile', ...payload, }, }); const result = (res?.result as any) || {}; if (result.code !== 0 || !result.data) { throw new Error(result.message || '更新用户资料失败'); } return syncUserState(result.data as UserInfo); } export type { UserInfo };