/** * UserManager - 用户管理核心模块(重构版) * * 使用 Zustand store 进行状态管理 * 保持与旧 API 的向后兼容 */ import type { UserDTO } from '../../types/dto'; import { authService } from '@/services/auth'; import { userCacheRepository } from '@/database'; import { useUserManagerStore } from './userStore'; import { createCacheEntry, isCacheExpired, DEFAULT_TTL } from '../utils/cache'; import { createDedupe } from '../utils/requestDedupe'; const dedupe = createDedupe(() => useUserManagerStore); // 将 fetchCurrentUserFromAPI 的判别结果转为 User | null。 // 网络故障/认证失败时返回 null,由上层缓存兜底(避免空数据覆盖缓存)。 // 注意:UserManager 只负责缓存,不触发登出,登出由 authStore 统一处理。 async function fetchCurrentUserOrNull(): Promise { const result = await authService.fetchCurrentUserFromAPI(); return result.kind === 'user' ? result.user : null; } // ==================== UserManager 类 ==================== class UserManager { async getCurrentUser(forceRefresh = false): Promise { const store = useUserManagerStore.getState(); const entry = store.currentUserEntry; if (!forceRefresh && entry && !isCacheExpired(entry)) { return entry.data; } if (!forceRefresh && entry && isCacheExpired(entry)) { this.refreshCurrentUserInBackground(); return entry.data; } if (!forceRefresh) { const cachedFromDb = await userCacheRepository.getCurrent(); if (cachedFromDb) { const newEntry = createCacheEntry(cachedFromDb, DEFAULT_TTL.USER); store.setCurrentUserEntry(newEntry); this.refreshCurrentUserInBackground(); return cachedFromDb; } } return dedupe('users:current', async () => { const user = await fetchCurrentUserOrNull(); // 仅在拿到真实用户时刷新缓存;网络/认证失败时保留旧缓存,避免误清空 if (user) { const newEntry = createCacheEntry(user, DEFAULT_TTL.USER); store.setCurrentUserEntry(newEntry); userCacheRepository.saveCurrent(user).catch(() => {}); userCacheRepository.save(user).catch(() => {}); } return user; }); } private refreshCurrentUserInBackground(): void { dedupe('users:current:bg', async () => { const store = useUserManagerStore.getState(); const user = await fetchCurrentUserOrNull(); if (user) { const newEntry = createCacheEntry(user, DEFAULT_TTL.USER); store.setCurrentUserEntry(newEntry); userCacheRepository.saveCurrent(user).catch(() => {}); userCacheRepository.save(user).catch(() => {}); } return user; }).catch((error) => { console.error('[UserManager] refreshCurrentUserInBackground error:', error); }); } async getUserById(userId: string, forceRefresh = false): Promise { const store = useUserManagerStore.getState(); const entry = store.usersMap.get(userId); if (!forceRefresh && entry && !isCacheExpired(entry)) { return entry.data; } if (!forceRefresh && entry && isCacheExpired(entry)) { this.refreshUserByIdInBackground(userId); return entry.data; } if (!forceRefresh) { const cachedFromDb = await userCacheRepository.get(userId); if (cachedFromDb) { const newEntry = createCacheEntry(cachedFromDb, DEFAULT_TTL.USER); store.setUser(userId, cachedFromDb); this.refreshUserByIdInBackground(userId); return cachedFromDb; } } return dedupe(`users:detail:${userId}`, async () => { const store = useUserManagerStore.getState(); const user = await authService.fetchUserByIdFromAPI(userId); const newEntry = createCacheEntry(user, DEFAULT_TTL.USER); store.setUser(userId, user); if (user) { userCacheRepository.save(user).catch(() => {}); } return user; }); } private refreshUserByIdInBackground(userId: string): void { dedupe(`users:detail:bg:${userId}`, async () => { const store = useUserManagerStore.getState(); const user = await authService.fetchUserByIdFromAPI(userId); const newEntry = createCacheEntry(user, DEFAULT_TTL.USER); store.setUser(userId, user); if (user) { userCacheRepository.save(user).catch(() => {}); } return user; }).catch((error) => { console.error('[UserManager] refreshUserByIdInBackground error:', error); }); } invalidateUsers(): void { useUserManagerStore.getState().invalidateAll(); } } export const userManager = new UserManager(); export { UserManager }; export default userManager;