diff --git a/serve/frontend/src/components/Layout.tsx b/serve/frontend/src/components/Layout.tsx index e154944..176b92a 100644 --- a/serve/frontend/src/components/Layout.tsx +++ b/serve/frontend/src/components/Layout.tsx @@ -1,4 +1,3 @@ -import { useEffect, useRef, useState } from 'react' import { NavLink, Outlet } from 'react-router-dom' import { useQuery } from '@tanstack/react-query' import { motion } from 'framer-motion' @@ -20,8 +19,6 @@ import { FileText, Settings, Key, - Database, - Loader2, LayoutDashboard, Tags, TrendingUp, @@ -30,14 +27,11 @@ import { Sparkles, Layers3, Landmark, - RadioTower, - CheckCircle2, BookOpenCheck, } from 'lucide-react' import { Logo } from './Logo' import { api } from '@/lib/api' import { cn } from '@/lib/cn' -import { setCurrentTotal as setAlertTotal, useUnreadAlerts } from '@/lib/monitorBadge' // 品牌色 — 只用于 logo / brand 区域,不影响功能语义色 const BRAND = '#8B5CF6' @@ -50,27 +44,10 @@ const nav = [ { to: '/concept-analysis', label: '概念分析', icon: Layers3 }, { to: '/industry-analysis', label: '行业分析', icon: Landmark }, { to: '/financials', label: '财务分析', icon: FileText }, - { to: '/monitor', label: '监控中心', icon: RadioTower }, { to: '/review', label: '复盘', icon: BookOpenCheck }, { to: '/indices', label: '指数', icon: BarChart3 }, - { to: '/data', label: '数据', icon: Database }, ] as const -/** 监控中心未读徽标 — 仅在非监控页且有未读时显示。 */ -function MonitorBadge({ active }: { active: boolean }) { - const unread = useUnreadAlerts() - // 尊重用户设置: 可在菜单设置里关闭数字提示 - const badgeEnabled = (() => { - try { return localStorage.getItem('monitor_badge_enabled') !== '0' } catch { return true } - })() - if (active || unread <= 0 || !badgeEnabled) return null - return ( - - {unread > 99 ? '99+' : unread} - - ) -} - // ===== 档位卡片 ===== function TierBadge({ label, hasKey }: { label: string; hasKey?: boolean }) { const base = label.split(' ')[0].split('+')[0].toLowerCase() @@ -196,46 +173,8 @@ export function Layout() { queryFn: api.analysisMenus, }) - // 数据同步状态轮询: 有活跃 job 时「数据」菜单项显示转圈 - const { data: pipelineJobs } = useQuery({ - queryKey: QK.pipelineJobs, - queryFn: () => api.pipelineJobs(1), - refetchInterval: (query) => (query.state.data?.active_id ? 2000 : 15000), - refetchIntervalInBackground: true, - }) - const isDataSyncing = !!pipelineJobs?.active_id - - // 数据同步完成的"瞬时反馈": isDataSyncing 从 true→false 时显示绿色对勾, - // 闪烁约 3 秒后自动消失。 - const [dataSyncJustDone, setDataSyncJustDone] = useState(false) - const prevSyncingRef = useRef(false) - useEffect(() => { - // 仅在"刚结束"(true→false)且非首次挂载时触发 - if (prevSyncingRef.current && !isDataSyncing) { - setDataSyncJustDone(true) - const t = setTimeout(() => setDataSyncJustDone(false), 3000) - prevSyncingRef.current = isDataSyncing - return () => clearTimeout(t) - } - prevSyncingRef.current = isDataSyncing - }, [isDataSyncing]) - const version = versionData?.version - // 轮询触发记录总数 → 更新监控中心徽标 (每 15 秒) - const alertsTotalQuery = useQuery({ - queryKey: ['alerts-total'], - queryFn: () => api.alertsList({ days: 7, limit: 1 }), - refetchInterval: 15000, - refetchIntervalInBackground: true, - select: (data) => data.total, - }) - // 只在拿到真实总数时同步徽标 (避免 data=undefined 时传 0 重置 lastSeen) - const alertsTotal = alertsTotalQuery.data - useEffect(() => { - if (alertsTotal != null) setAlertTotal(alertsTotal) - }, [alertsTotal]) - // 合并内置页面 + 可见的扩展分析菜单 const analysisNav = (analysisMenus?.items ?? []) .filter(m => m.visible) @@ -321,15 +260,6 @@ export function Layout() { Beta )} - {/* 数据同步状态: 同步中转圈, 刚完成显示绿色对勾闪烁 3 秒 */} - {to === '/data' && isDataSyncing && ( - - )} - {to === '/data' && !isDataSyncing && dataSyncJustDone && ( - - )} - {/* 监控中心徽标: 仅非监控页且有未读时显示 */} - {to === '/monitor' && } )} diff --git a/serve/frontend/src/pages/settings/MenuSettings.tsx b/serve/frontend/src/pages/settings/MenuSettings.tsx index f713a7a..947786e 100644 --- a/serve/frontend/src/pages/settings/MenuSettings.tsx +++ b/serve/frontend/src/pages/settings/MenuSettings.tsx @@ -17,7 +17,7 @@ import { verticalListSortingStrategy, } from '@dnd-kit/sortable' import { CSS } from '@dnd-kit/utilities' -import { Eye, EyeOff, ExternalLink, GripVertical, Settings, Bell } from 'lucide-react' +import { Eye, EyeOff, ExternalLink, GripVertical, Settings } from 'lucide-react' import { Link } from 'react-router-dom' import { api } from '@/lib/api' import { QK } from '@/lib/queryKeys' @@ -40,18 +40,14 @@ const BUILTIN_PAGES: NavEntry[] = [ { id: '/review', label: '复盘', type: 'builtin', visible: true }, { id: '/financials', label: '财务分析', type: 'builtin', visible: true }, { id: '/indices', label: '指数', type: 'builtin', visible: true }, - { id: '/monitor', label: '监控中心', type: 'builtin', visible: true }, - { id: '/data', label: '数据', type: 'builtin', visible: true }, ] // ── Sortable row ── -function SortableItem({ entry, hidden, onToggleHidden, badgeEnabled, onToggleBadge }: { +function SortableItem({ entry, hidden, onToggleHidden }: { entry: NavEntry hidden: boolean onToggleHidden: (id: string) => void - badgeEnabled?: boolean - onToggleBadge?: (id: string) => void }) { const { attributes, @@ -73,7 +69,7 @@ function SortableItem({ entry, hidden, onToggleHidden, badgeEnabled, onToggleBad
@@ -132,22 +128,6 @@ function SortableItem({ entry, hidden, onToggleHidden, badgeEnabled, onToggleBad )}
- {/* 第 6 列: 徽标开关 (仅监控中心) */} -
- {onToggleBadge && ( - - )} -
) } @@ -246,16 +226,6 @@ export function SettingsMenuSettingsPanel() { saveNavHidden.mutate([...next]) } - // 监控中心徽标开关 (localStorage) - const [badgeEnabled, setBadgeEnabled] = useState(() => { - try { return localStorage.getItem('monitor_badge_enabled') !== '0' } catch { return true } - }) - const toggleBadge = (id: string) => { - if (id !== '/monitor') return - const next = !badgeEnabled - setBadgeEnabled(next) - try { localStorage.setItem('monitor_badge_enabled', next ? '1' : '0') } catch { /* ignore */ } - } return (
@@ -268,13 +238,12 @@ export function SettingsMenuSettingsPanel() {
-
+
菜单
类型
显示
设置
-
数字