/** * 用户状态管理 * 使用Zustand进行状态管理 * 对接真实后端API */ import { create } from 'zustand'; import { User, Post, Notification, NotificationBadge } from '../types'; import { PaginatedData } from '../services/api'; import { authService, postService, commentService, notificationService, } from '../services'; import { userManager } from './userManager'; import { messageManager } from './messageManager'; import { createOptimisticUpdaterFactory } from '../utils/optimisticUpdate'; interface UserState { // 状态 users: User[]; userCache: Record; // 用户缓存 posts: Post[]; notifications: Notification[]; notificationBadge: NotificationBadge; messageUnreadCount: number; // 加载状态 isLoadingPosts: boolean; isLoadingNotifications: boolean; // 搜索历史 searchHistory: string[]; // 操作 fetchUser: (userId: string) => Promise; fetchUserPosts: (userId: string, page?: number) => Promise; fetchPosts: (type: 'recommend' | 'follow' | 'hot' | 'latest', page?: number) => Promise>; fetchNotifications: (type?: string, page?: number) => Promise; markNotificationAsRead: (notificationId: string) => Promise; markAllNotificationsAsRead: () => Promise; fetchNotificationBadge: () => Promise; setMessageUnreadCount: (count: number) => void; fetchMessageUnreadCount: () => Promise; addSearchHistory: (keyword: string) => void; clearSearchHistory: () => void; // 互动操作 likePost: (postId: string) => Promise; unlikePost: (postId: string) => Promise; favoritePost: (postId: string) => Promise; unfavoritePost: (postId: string) => Promise; likeComment: (commentId: string) => Promise; unlikeComment: (commentId: string) => Promise; followUser: (userId: string) => Promise; unfollowUser: (userId: string) => Promise; // 刷新数据 refreshAll: () => Promise; } export const useUserStore = create((set, get) => { // 创建乐观更新器 const optimisticUpdater = createOptimisticUpdaterFactory(set, get); return { // 初始状态 users: [], userCache: {}, posts: [], notifications: [], notificationBadge: { total: 0, likes: 0, comments: 0, follows: 0, system: 0, }, messageUnreadCount: 0, searchHistory: [], isLoadingPosts: false, isLoadingNotifications: false, // 获取用户信息 fetchUser: async (userId: string) => { // 先检查缓存 const cached = get().userCache[userId]; if (cached) return cached; try { const user = await userManager.getUserById(userId); if (user) { set(state => ({ userCache: { ...state.userCache, [userId]: user } })); return user; } } catch (error) { console.error('获取用户信息失败:', error); } return undefined; }, // 获取用户帖子 fetchUserPosts: async (userId: string, page = 1) => { try { const response = await postService.getUserPosts(userId, page); const newPosts = response.list; set(state => ({ posts: page === 1 ? newPosts : [...state.posts, ...newPosts] })); return newPosts; } catch (error) { console.error('获取用户帖子失败:', error); return []; } }, // 获取帖子列表(首页) fetchPosts: async (type: 'recommend' | 'follow' | 'hot' | 'latest', page = 1) => { set({ isLoadingPosts: true }); try { let response; switch (type) { case 'recommend': response = await postService.getRecommendedPosts(page); break; case 'follow': response = await postService.getFollowingPosts(page); break; case 'hot': response = await postService.getHotPosts(page); break; case 'latest': default: response = await postService.getLatestPosts(page); break; } const newPosts = response.list; set(state => ({ posts: page === 1 ? newPosts : [...state.posts, ...newPosts], isLoadingPosts: false })); return response; } catch (error) { console.error('获取帖子列表失败:', error); set({ isLoadingPosts: false }); return { list: [], total: 0, page, page_size: 20, total_pages: 0, }; } }, // 获取通知列表 fetchNotifications: async (type?: string, page = 1) => { set({ isLoadingNotifications: true }); try { const response = await notificationService.getNotifications( page, 20, type as any ); const newNotifications = response.list; set(state => ({ notifications: page === 1 ? newNotifications : [...state.notifications, ...newNotifications], isLoadingNotifications: false })); return newNotifications; } catch (error) { console.error('获取通知列表失败:', error); set({ isLoadingNotifications: false }); return []; } }, // 标记通知为已读 markNotificationAsRead: async (notificationId: string) => { try { await notificationService.markAsRead(notificationId); set(state => { const notifications = state.notifications.map(n => n.id === notificationId ? { ...n, isRead: true } : n ); return { notifications, notificationBadge: { total: notifications.filter(n => !n.isRead).length, likes: notifications.filter(n => n.type === 'like_post' && !n.isRead).length, comments: notifications.filter(n => n.type === 'comment' && !n.isRead).length, follows: notifications.filter(n => n.type === 'follow' && !n.isRead).length, system: notifications.filter(n => n.type === 'system' && !n.isRead).length, } }; }); } catch (error) { console.error('标记通知为已读失败:', error); } }, // 标记所有通知为已读 markAllNotificationsAsRead: async () => { try { await notificationService.markAllAsRead(); set(state => ({ notifications: state.notifications.map(n => ({ ...n, isRead: true })), notificationBadge: { total: 0, likes: 0, comments: 0, follows: 0, system: 0, } })); } catch (error) { console.error('标记所有通知为已读失败:', error); } }, // 获取通知角标 fetchNotificationBadge: async () => { try { const badge = await notificationService.getNotificationBadge(); set({ notificationBadge: badge }); } catch (error) { console.error('获取通知角标失败:', error); } }, // 设置消息未读数 // 注意:未读数现在由 MessageManager 统一管理 // 此方法保留用于 TabBar 角标显示,从 MessageManager 同步 setMessageUnreadCount: (count: number) => { set({ messageUnreadCount: count }); }, // 从后端拉取最新消息未读数 // @deprecated 请使用 messageManager.fetchUnreadCount() 代替 // 此方法保留用于向后兼容 fetchMessageUnreadCount: async () => { try { await messageManager.fetchUnreadCount(); const unread = messageManager.getUnreadCount(); set({ messageUnreadCount: unread.total + unread.system }); } catch (error) { console.error('获取消息未读数失败:', error); } }, // 添加搜索历史 addSearchHistory: (keyword: string) => { set(state => { const history = [keyword, ...state.searchHistory.filter(k => k !== keyword)].slice(0, 20); return { searchHistory: history }; }); }, // 清除搜索历史 clearSearchHistory: () => { set({ searchHistory: [] }); }, // 点赞帖子 - 使用乐观更新工具 likePost: async (postId: string) => { const originalPosts = get().posts; // 乐观更新 set(state => ({ posts: state.posts.map(p => p.id === postId ? { ...p, is_liked: true, likes_count: p.likes_count + 1 } : p ) })); try { const updatedPost = await postService.likePost(postId); if (updatedPost) { // 使用服务器返回的数据更新 set(state => ({ posts: state.posts.map(p => p.id === postId ? updatedPost : p ) })); } } catch (error) { console.error('点赞帖子失败:', error); // 回滚 set({ posts: originalPosts }); } }, // 取消点赞 - 使用乐观更新工具 unlikePost: async (postId: string) => { const originalPosts = get().posts; // 乐观更新 set(state => ({ posts: state.posts.map(p => p.id === postId ? { ...p, is_liked: false, likes_count: Math.max(0, p.likes_count - 1) } : p ) })); try { const updatedPost = await postService.unlikePost(postId); if (updatedPost) { // 使用服务器返回的数据更新 set(state => ({ posts: state.posts.map(p => p.id === postId ? updatedPost : p ) })); } } catch (error) { console.error('取消点赞帖子失败:', error); // 回滚 set({ posts: originalPosts }); } }, // 收藏帖子 - 使用乐观更新工具 favoritePost: async (postId: string) => { const originalPosts = get().posts; // 乐观更新 set(state => ({ posts: state.posts.map(p => p.id === postId ? { ...p, is_favorited: true, favorites_count: p.favorites_count + 1 } : p ) })); try { const updatedPost = await postService.favoritePost(postId); if (updatedPost) { // 使用服务器返回的数据更新 set(state => ({ posts: state.posts.map(p => p.id === postId ? updatedPost : p ) })); } } catch (error) { console.error('收藏帖子失败:', error); // 回滚 set({ posts: originalPosts }); } }, // 取消收藏 - 使用乐观更新工具 unfavoritePost: async (postId: string) => { const originalPosts = get().posts; // 乐观更新 set(state => ({ posts: state.posts.map(p => p.id === postId ? { ...p, is_favorited: false, favorites_count: Math.max(0, p.favorites_count - 1) } : p ) })); try { const updatedPost = await postService.unfavoritePost(postId); if (updatedPost) { // 使用服务器返回的数据更新 set(state => ({ posts: state.posts.map(p => p.id === postId ? updatedPost : p ) })); } } catch (error) { console.error('取消收藏帖子失败:', error); // 回滚 set({ posts: originalPosts }); } }, // 点赞评论 - 使用乐观更新工具 likeComment: async (commentId: string) => { await optimisticUpdater({ key: 'posts', optimisticUpdate: (posts) => posts.map(p => ({ ...p, top_comment: p.top_comment && p.top_comment.id === commentId ? { ...p.top_comment, is_liked: true, likes_count: p.top_comment.likes_count + 1 } : p.top_comment })), rollbackState: (original) => original, apiCall: () => commentService.likeComment(commentId), errorMessage: '点赞评论失败', }); }, // 取消点赞评论 - 使用乐观更新工具 unlikeComment: async (commentId: string) => { await optimisticUpdater({ key: 'posts', optimisticUpdate: (posts) => posts.map(p => ({ ...p, top_comment: p.top_comment && p.top_comment.id === commentId ? { ...p.top_comment, is_liked: false, likes_count: Math.max(0, p.top_comment.likes_count - 1) } : p.top_comment })), rollbackState: (original) => original, apiCall: () => commentService.unlikeComment(commentId), errorMessage: '取消点赞评论失败', }); }, // 关注用户 - 使用乐观更新工具 followUser: async (userId: string) => { const originalUsers = get().users; const originalUserCache = get().userCache; // 乐观更新 users set(state => ({ users: state.users.map(u => u.id === userId ? { ...u, isFollowing: true, followersCount: u.followers_count + 1 } : u ), })); // 乐观更新 userCache set(state => ({ userCache: Object.fromEntries( Object.entries(state.userCache).map(([id, user]) => [ id, id === userId ? { ...user, isFollowing: true, followersCount: user.followers_count + 1 } : user ]) ) })); try { await authService.followUser(userId); } catch (error) { console.error('关注用户失败:', error); // 回滚 set({ users: originalUsers, userCache: originalUserCache }); } }, // 取消关注 - 使用乐观更新工具 unfollowUser: async (userId: string) => { const originalUsers = get().users; const originalUserCache = get().userCache; // 乐观更新 users set(state => ({ users: state.users.map(u => u.id === userId ? { ...u, isFollowing: false, followersCount: Math.max(0, u.followers_count - 1) } : u ), })); // 乐观更新 userCache set(state => ({ userCache: Object.fromEntries( Object.entries(state.userCache).map(([id, user]) => [ id, id === userId ? { ...user, isFollowing: false, followersCount: Math.max(0, user.followers_count - 1) } : user ]) ) })); try { await authService.unfollowUser(userId); } catch (error) { console.error('取消关注用户失败:', error); // 回滚 set({ users: originalUsers, userCache: originalUserCache }); } }, // 刷新所有数据 refreshAll: async () => { await Promise.all([ get().fetchPosts('recommend', 1), get().fetchNotificationBadge(), ]); }, }; }); // 导出selector hooks以优化性能 export const usePosts = () => useUserStore((state) => state.posts); export const useNotifications = () => useUserStore((state) => state.notifications); export const useNotificationBadge = () => useUserStore((state) => state.notificationBadge); export const useMessageUnreadCount = () => useUserStore((state) => state.messageUnreadCount); export const useSearchHistory = () => useUserStore((state) => state.searchHistory); export const useIsLoadingPosts = () => useUserStore((state) => state.isLoadingPosts);