/** * 全局 Toast/通知 UI 组件 * * 从 notification-store 读取通知队列,渲染为浮动通知列表。 * 放置在 layout 层级,自动显示/消失。 */ "use client"; import { X, CheckCircle, AlertTriangle, Info, AlertCircle } from "lucide-react"; import { useNotificationStore } from "@/lib/stores/notification-store"; import type { Notification, NotificationType } from "@/lib/stores/notification-store"; import { cn } from "@/lib/utils"; // ── 图标映射 ──────────────────────────────────────────────────────────── const ICON_BY_TYPE: Record = { success: , error: , warning: , info: , }; // ── 样式映射 ──────────────────────────────────────────────────────────── const STYLE_BY_TYPE: Record = { success: "border-emerald-200 bg-emerald-50 text-emerald-800", error: "border-red-200 bg-red-50 text-red-800", warning: "border-amber-200 bg-amber-50 text-amber-800", info: "border-blue-200 bg-blue-50 text-blue-800", }; // ── 单条通知 ──────────────────────────────────────────────────────────── function NotificationItem({ notification, onRemove, }: { notification: Notification; onRemove: (id: string) => void; }) { return (
{ICON_BY_TYPE[notification.type]}
{notification.title && (

{notification.title}

)}

{notification.message}

); } // ── 通知容器 ──────────────────────────────────────────────────────────── export function NotificationContainer() { const notifications = useNotificationStore((s) => s.notifications); const removeNotification = useNotificationStore((s) => s.removeNotification); if (notifications.length === 0) return null; return (
{notifications.map((notification) => (
))}
); }