// 顶层 App — 把 design 的 3 视图(DR/告警/总览)和 broadcast tab 串起来。 const { useState, useEffect } = React; const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "view": "roster", "density": "regular", "theme": "dark", "aiOn": true, "accent": "blue" }/*EDITMODE-END*/; const ACCENT_HUES = { blue: { h: 220, h2: 145 }, purple: { h: 285, h2: 195 }, green: { h: 165, h2: 220 }, amber: { h: 65, h2: 200 }, }; function App() { const [t, setTweak] = useTweaks(TWEAK_DEFAULTS); // 顶层 tab:监控看板 / 群发消息 const [activeTab, setActiveTab] = useState(() => localStorage.getItem("cm.activeTab") || "dashboard" ); useEffect(() => { localStorage.setItem("cm.activeTab", activeTab); }, [activeTab]); // 时钟(用于 TopBar 实时同步显示) const [now, setNow] = useState(new Date()); useEffect(() => { const id = setInterval(() => setNow(new Date()), 30000); return () => clearInterval(id); }, []); // 主题 useEffect(() => { document.documentElement.setAttribute("data-theme", t.theme || "dark"); }, [t.theme]); // 强调色 useEffect(() => { const a = ACCENT_HUES[t.accent] || ACCENT_HUES.blue; document.documentElement.style.setProperty("--accent", `oklch(0.78 0.14 ${a.h})`); document.documentElement.style.setProperty("--accent-2", `oklch(0.82 0.14 ${a.h2})`); }, [t.accent]); // dashboard 内部状态 const [drFilter, setDrFilter] = useState("all"); const [timeRange, setTimeRange] = useState("today"); const [statusFilter, setStatusFilter] = useState("all"); const [openDr, setOpenDr] = useState(null); const [openGroup, setOpenGroup] = useState(null); // broadcast modal 状态 const [broadcastOpen, setBroadcastOpen] = useState(false); const [broadcastPrefill, setBroadcastPrefill] = useState(null); const openBroadcastWizard = (prefill = null) => { setBroadcastPrefill(prefill); setBroadcastOpen(true); }; const broadcasts = (window.AppData && window.AppData.BROADCASTS) || []; const groups = (window.AppData && window.AppData.GROUPS) || []; return (
{this.state.err && this.state.err.stack}
{this.state.info && (
{this.state.info.componentStack}
)}