/** * 全局通知/Toast 状态 Store (Zustand) * * 管理应用全局的 toast / 通知队列: * - 添加通知(支持 success / error / warning / info) * - 自动过期清除 * - 手动移除 */ import { create } from "zustand"; // ── 类型定义 ──────────────────────────────────────────────────────────── export type NotificationType = "success" | "error" | "warning" | "info"; export interface Notification { /** 通知唯一 ID */ id: string; /** 通知类型 */ type: NotificationType; /** 通知消息 */ message: string; /** 通知标题(可选) */ title?: string; /** 创建时间戳 */ createdAt: number; /** 自动过期时间(毫秒),null 表示不自动过期 */ duration: number | null; } export interface NotificationState { /** 当前通知队列 */ notifications: Notification[]; } export interface NotificationActions { /** 添加一条通知 */ addNotification: (payload: { type: NotificationType; message: string; title?: string; /** 自定义过期时间(毫秒),默认按 type 自动设置 */ duration?: number | null; }) => string; /** 移除一条通知 */ removeNotification: (id: string) => void; /** 清空所有通知 */ clearAll: () => void; } // ── 默认过期时间 ──────────────────────────────────────────────────────── const DEFAULT_DURATION_BY_TYPE: Record = { success: 3000, error: 5000, warning: 4000, info: 3000, }; // ── 辅助 ──────────────────────────────────────────────────────────────────── /** 生成通知 ID */ function generateNotificationId(): string { return `notif-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`; } /** 定时器映射,避免重复 */ const timers = new Map>(); // ── 默认值 ────────────────────────────────────────────────────────────────── const INITIAL_STATE: NotificationState = { notifications: [], }; // ── Store ─────────────────────────────────────────────────────────────────── export const useNotificationStore = create()( (set, get) => ({ ...INITIAL_STATE, addNotification: ({ type, message, title, duration }) => { const id = generateNotificationId(); const effectiveDuration = duration ?? DEFAULT_DURATION_BY_TYPE[type]; const notification: Notification = { id, type, message, title, createdAt: Date.now(), duration: effectiveDuration, }; set((state) => ({ notifications: [...state.notifications, notification], })); // 设置自动过期 if (effectiveDuration !== null) { const timer = setTimeout(() => { get().removeNotification(id); timers.delete(id); }, effectiveDuration); timers.set(id, timer); } return id; }, removeNotification: (id) => { // 清除定时器 const timer = timers.get(id); if (timer) { clearTimeout(timer); timers.delete(id); } set((state) => ({ notifications: state.notifications.filter((n) => n.id !== id), })); }, clearAll: () => { // 清除所有定时器 timers.forEach((timer) => clearTimeout(timer)); timers.clear(); set({ notifications: [] }); }, }) );