// ============================================================ // PageDispatcher — 页面事件调度器 // // 监听 EVENTS.OPEN_PAGE,根据 modalType 渲染对应容器: // - modal → antd Modal(居中模态,有遮罩阻断交互) // - drawer → antd Drawer(侧滑抽屉) // - floating → FloatingPanel(非模态浮动面板,可拖拽,不阻断交互) // // 支持多面板共存(floating 类型可同时打开多个) // ============================================================ import {useState, useEffect, useCallback, useRef, type ComponentType} from 'react'; import {Modal, Drawer} from 'antd'; import {on, off, EVENTS} from '@/utils/event-bus'; import {FloatingPanel} from '@/components/ui/FloatingPanel'; import {ComplianceAssetsPage} from '@/pages/compliance-assets/ComplianceAssetsPage'; import {AccountPage} from '@/pages/account/AccountPage'; import {VipPage} from '@/pages/vip/VipPage'; import {RechargePage} from '@/pages/recharge/RechargePage'; import {BillingPage} from '@/pages/billing/BillingPage'; import {OrdersPage} from '@/pages/orders/OrdersPage'; import {ProjectsPage} from '@/pages/projects/ProjectsPage'; import {QuotaPage} from '@/pages/quota/QuotaPage'; import {WechatWorkPage} from '@/pages/wechat-work/WechatWorkPage'; // ---------- 类型 ---------- type ModalType = 'modal' | 'drawer' | 'floating'; interface PageEventPayload { target: string; modalType: ModalType; label: string; } interface ActivePanel { id: string; target: string; label: string; } // ---------- target → 页面组件映射 ---------- const PAGE_MAP: Record = { '/compliance-assets': ComplianceAssetsPage, '/account': AccountPage, '/vip': VipPage, '/recharge': RechargePage, '/billing': BillingPage, '/orders': OrdersPage, '/projects': ProjectsPage, '/quota': QuotaPage, '/wechat-work': WechatWorkPage, }; // ---------- 组件 ---------- export function PageDispatcher() { // 单实例(modal / drawer)—— 同一时间只有一个 const [singleton, setSingleton] = useState(null); // 浮动面板列表(支持多个同时打开) const [floatingPanels, setFloatingPanels] = useState([]); const nextIdRef = useRef(0); // 监听 OPEN_PAGE 事件 useEffect(() => { const handler = (payload: unknown) => { const {target, modalType, label} = payload as PageEventPayload; if (!target || !PAGE_MAP[target]) { console.warn(`[PageDispatcher] 未找到页面组件: ${target}`); return; } if (modalType === 'floating') { // 浮动面板:追加到列表 const id = `fp-${nextIdRef.current++}`; setFloatingPanels((prev) => [...prev, {id, target, label}]); } else { // modal / drawer:单实例,覆盖之前的 setSingleton({target, modalType, label}); } }; on(EVENTS.OPEN_PAGE, handler); return () => off(EVENTS.OPEN_PAGE, handler); }, []); // 关闭单实例 const closeSingleton = useCallback(() => { setSingleton(null); }, []); // 关闭指定浮动面板 const closeFloating = useCallback((id: string) => { setFloatingPanels((prev) => prev.filter((p) => p.id !== id)); }, []); // 单实例对应的页面组件 const SingletonPage = singleton ? PAGE_MAP[singleton.target] : null; return ( <> {/* ======== Modal ======== */} {singleton?.modalType === 'modal' && SingletonPage && ( )} {/* ======== Drawer ======== */} {singleton?.modalType === 'drawer' && SingletonPage && ( )} {/* ======== Floating Panels ======== */} {floatingPanels.map((panel) => { const PageContent = PAGE_MAP[panel.target]; if (!PageContent) return null; return ( closeFloating(panel.id)} > ); })} ); }