// ========================================================= // FBIF 资讯订阅 · Overlays // Toaster (success/info/warn), Placeholder // ========================================================= const Toaster = ({ toasts }) => { useLucide(); const iconFor = { success: 'check-circle-2', info: 'info', warning: 'alert-triangle', error: 'x-circle' }; const colorFor = { success: '#00A870', info: '#1456F0', warning: '#FF8800', error: '#F54A45' }; return (
{toasts.map(t => (
{t.msg} {t.action && ( )}
))}
); }; const Placeholder = ({ icon, title, hint }) => { useLucide(); return (
{title}
{hint}
V1 / V2 路线图
); }; // Generic centered modal (scrim + card). Esc / scrim / ✕ to close. const Modal = ({ title, subtitle, icon, width = 520, onClose, children, footer }) => { useLucide(); React.useEffect(() => { const onKey = (e) => { if (e.key === 'Escape') onClose && onClose(); }; window.addEventListener('keydown', onKey); return () => window.removeEventListener('keydown', onKey); }, []); const modal = (
{icon && }
{title}
{subtitle &&
{subtitle}
}
{children}
{footer &&
{footer}
}
); return ReactDOM.createPortal(modal, document.body); }; // 数据看板 — coming soon, previews planned modules so it isn't a dead icon const DashboardComingSoon = ({ onClose }) => { useLucide(); const bars = [62, 78, 45, 88, 70, 53]; return (

数据看板

即将上线

验证「精选时间线」的核心假设:精选流点击率是否高于全量流。以下为规划中的看板模块预览。

{/* 点击率对比 */}
精选 vs 全量 点击率
核心假设验证指标
精选流 全量流
{/* 来源质量分布 */}
来源质量分布
各来源平均质量分
{bars.map((b, i) => (
))}
{/* 标签热度 */}
标签热度
近 7 天各标签资讯量
{[['新茶饮', 22], ['无糖代糖', 18], ['咖啡', 15], ['植物基', 12], ['并购融资', 9], ['功能性', 7]].map(([n, v]) => ( {n}{v} ))}
数据看板将在 V1 接入真实埋点后开放(精选/全量点击率、来源质量分布、标签热度)。
); }; Object.assign(window, { Toaster, Placeholder, Modal, DashboardComingSoon });