/** * 帖子状态 Zustand Store */ import { create } from 'zustand'; import type { Post } from '../../types'; import { CacheEntry, createCacheEntry, isCacheExpired, DEFAULT_TTL } from '../utils/cache'; // ==================== 状态接口 ==================== export interface PostManagerState { // 帖子列表缓存 (key: list:type:page:pageSize) listsMap: Map>; // 帖子详情缓存 detailsMap: Map>; // 加载状态 loadingListKeys: Set; loadingDetailIds: Set; // 待处理请求(去重) pendingRequests: Map>; } export interface PostManagerActions { // 获取状态 getPostsList: (type: string, page: number, pageSize: number) => Post[] | null; getPostDetail: (postId: string) => Post | null; isListExpired: (type: string, page: number, pageSize: number) => boolean; isDetailExpired: (postId: string) => boolean; isLoadingList: (type: string, page: number, pageSize: number) => boolean; isLoadingDetail: (postId: string) => boolean; // 设置状态 setPostsList: (type: string, page: number, pageSize: number, posts: Post[]) => void; setPostDetail: (postId: string, post: Post | null) => void; setLoadingList: (type: string, page: number, pageSize: number, loading: boolean) => void; setLoadingDetail: (postId: string, loading: boolean) => void; // 缓存管理 invalidateList: (type?: string, page?: number, pageSize?: number) => void; invalidateDetail: (postId: string) => void; invalidateAll: () => void; // 请求去重 getPendingRequest: (key: string) => Promise | undefined; setPendingRequest: (key: string, request: Promise) => void; deletePendingRequest: (key: string) => void; clearPendingRequests: () => void; // 重置 reset: () => void; } // ==================== 辅助函数 ==================== function buildListKey(type: string, page: number, pageSize: number): string { return `list:${type}:${page}:${pageSize}`; } // ==================== 初始状态 ==================== const initialState: PostManagerState = { listsMap: new Map(), detailsMap: new Map(), loadingListKeys: new Set(), loadingDetailIds: new Set(), pendingRequests: new Map(), }; // ==================== Store 创建 ==================== export type PostManagerStore = PostManagerState & PostManagerActions; export const usePostManagerStore = create((set, get) => ({ // ==================== 初始状态 ==================== ...initialState, // ==================== 获取状态 ==================== getPostsList: (type: string, page: number, pageSize: number) => { const key = buildListKey(type, page, pageSize); const entry = get().listsMap.get(key); if (!entry) return null; if (isCacheExpired(entry)) return null; return entry.data; }, getPostDetail: (postId: string) => { const entry = get().detailsMap.get(postId); if (!entry) return null; if (isCacheExpired(entry)) return null; return entry.data; }, isListExpired: (type: string, page: number, pageSize: number) => { const key = buildListKey(type, page, pageSize); const entry = get().listsMap.get(key); if (!entry) return true; return isCacheExpired(entry); }, isDetailExpired: (postId: string) => { const entry = get().detailsMap.get(postId); if (!entry) return true; return isCacheExpired(entry); }, isLoadingList: (type: string, page: number, pageSize: number) => { const key = buildListKey(type, page, pageSize); return get().loadingListKeys.has(key); }, isLoadingDetail: (postId: string) => { return get().loadingDetailIds.has(postId); }, // ==================== 设置状态 ==================== setPostsList: (type: string, page: number, pageSize: number, posts: Post[]) => { const key = buildListKey(type, page, pageSize); set(state => { const newListsMap = new Map(state.listsMap); newListsMap.set(key, createCacheEntry(posts, DEFAULT_TTL.POST_LIST)); return { listsMap: newListsMap }; }); }, setPostDetail: (postId: string, post: Post | null) => { set(state => { const newDetailsMap = new Map(state.detailsMap); newDetailsMap.set(postId, createCacheEntry(post, DEFAULT_TTL.POST_DETAIL)); return { detailsMap: newDetailsMap }; }); }, setLoadingList: (type: string, page: number, pageSize: number, loading: boolean) => { const key = buildListKey(type, page, pageSize); set(state => { const newLoadingListKeys = new Set(state.loadingListKeys); if (loading) { newLoadingListKeys.add(key); } else { newLoadingListKeys.delete(key); } return { loadingListKeys: newLoadingListKeys }; }); }, setLoadingDetail: (postId: string, loading: boolean) => { set(state => { const newLoadingDetailIds = new Set(state.loadingDetailIds); if (loading) { newLoadingDetailIds.add(postId); } else { newLoadingDetailIds.delete(postId); } return { loadingDetailIds: newLoadingDetailIds }; }); }, // ==================== 缓存管理 ==================== invalidateList: (type?: string, page?: number, pageSize?: number) => { if (type !== undefined && page !== undefined && pageSize !== undefined) { const key = buildListKey(type, page, pageSize); set(state => { const newListsMap = new Map(state.listsMap); newListsMap.delete(key); return { listsMap: newListsMap }; }); } else { set({ listsMap: new Map() }); } }, invalidateDetail: (postId: string) => { set(state => { const newDetailsMap = new Map(state.detailsMap); newDetailsMap.delete(postId); return { detailsMap: newDetailsMap }; }); }, invalidateAll: () => { set({ listsMap: new Map(), detailsMap: new Map(), pendingRequests: new Map(), }); }, // ==================== 请求去重 ==================== getPendingRequest: (key: string) => { return get().pendingRequests.get(key) as Promise | undefined; }, setPendingRequest: (key: string, request: Promise) => { set(state => { const newPendingRequests = new Map(state.pendingRequests); newPendingRequests.set(key, request); return { pendingRequests: newPendingRequests }; }); }, deletePendingRequest: (key: string) => { set(state => { const newPendingRequests = new Map(state.pendingRequests); newPendingRequests.delete(key); return { pendingRequests: newPendingRequests }; }); }, clearPendingRequests: () => { set({ pendingRequests: new Map() }); }, // ==================== 重置 ==================== reset: () => { set({ ...initialState, listsMap: new Map(), detailsMap: new Map(), loadingListKeys: new Set(), loadingDetailIds: new Set(), pendingRequests: new Map(), }); }, }));