From b850a5d7092f9c06ab5988c27a664d9bb0fe58c4 Mon Sep 17 00:00:00 2001 From: abingyyds Date: Sat, 25 Apr 2026 11:38:14 +0800 Subject: [PATCH] Separate distributor banner and notifications --- src/App.jsx | 2 + src/components/NotificationBell.jsx | 77 +++++++++++++++++++++++++++++ src/i18n/locales/en.json | 8 +-- src/i18n/locales/zh.json | 8 +-- src/pages/Dashboard.jsx | 30 ----------- 5 files changed, 89 insertions(+), 36 deletions(-) create mode 100644 src/components/NotificationBell.jsx diff --git a/src/App.jsx b/src/App.jsx index 64d032c..0f7d142 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,6 +1,7 @@ import React, { lazy, Suspense } from 'react'; import { Routes, Route, Navigate } from 'react-router-dom'; import AuthGuard from './components/AuthGuard'; +import NotificationBell from './components/NotificationBell'; import { ThemeProvider, useTheme } from './context/ThemeContext'; const Login = lazy(() => import('./pages/Login')); @@ -46,6 +47,7 @@ function ThemedRoutes() { } /> + ); } diff --git a/src/components/NotificationBell.jsx b/src/components/NotificationBell.jsx new file mode 100644 index 0000000..665197f --- /dev/null +++ b/src/components/NotificationBell.jsx @@ -0,0 +1,77 @@ +import React, { useMemo, useState } from 'react'; +import { Bell, X } from 'lucide-react'; +import { useTranslation } from 'react-i18next'; +import { useSite } from '../context/SiteContext'; + +export default function NotificationBell() { + const { t } = useTranslation(); + const { site } = useSite(); + const [open, setOpen] = useState(false); + + const notifications = useMemo(() => { + if (!Array.isArray(site?.notifications)) return []; + return site.notifications + .filter((item) => item?.content) + .slice(0, 20); + }, [site?.notifications]); + + if (notifications.length === 0) return null; + + return ( + <> + + + {open && ( +
setOpen(false)}> +
e.stopPropagation()} + > +
+
+
+ +
+
+

{t('notifications.title')}

+

{t('notifications.subtitle')}

+
+
+ +
+ +
+ {notifications.map((item, index) => ( +
+
+ {item.publish_date || t('notifications.notice')} +
+

+ {item.content} +

+
+ ))} +
+
+
+ )} + + ); +} diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index cdac093..d209f9d 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -9,6 +9,7 @@ "nav.signUp": "Sign Up", "nav.logout": "Logout", "nav.contact": "Contact", + "common.close": "Close", "home.heroSubtitle": "Access the world's most powerful AI models through a single API endpoint. Simple, affordable, reliable.", "home.getStarted": "Get Started Free", @@ -84,9 +85,10 @@ "dashboard.redeem": "Redeem", "dashboard.redeemSuccess": "Code redeemed successfully!", "dashboard.quickLinks": "Quick Links", - "dashboard.announcements": "Announcements", - "dashboard.announcementsDesc": "Latest updates from the site owner", - "dashboard.notice": "Notice", + "notifications.open": "Open announcements", + "notifications.title": "Announcements", + "notifications.subtitle": "Latest updates from the site owner", + "notifications.notice": "Notice", "dashboard.apiKeys": "API Keys", "dashboard.manageKeys": "Manage your keys", "dashboard.packages": "Packages", diff --git a/src/i18n/locales/zh.json b/src/i18n/locales/zh.json index e527f86..e90617d 100644 --- a/src/i18n/locales/zh.json +++ b/src/i18n/locales/zh.json @@ -9,6 +9,7 @@ "nav.signUp": "注册", "nav.logout": "退出", "nav.contact": "联系我们", + "common.close": "关闭", "home.heroSubtitle": "通过单一 API 端点访问全球最强大的 AI 模型。简单、实惠、可靠。", "home.getStarted": "免费开始", @@ -84,9 +85,10 @@ "dashboard.redeem": "兑换", "dashboard.redeemSuccess": "兑换码兑换成功!", "dashboard.quickLinks": "快捷入口", - "dashboard.announcements": "公告通知", - "dashboard.announcementsDesc": "站点管理员发布的最新消息", - "dashboard.notice": "通知", + "notifications.open": "打开公告通知", + "notifications.title": "公告通知", + "notifications.subtitle": "站点管理员发布的最新消息", + "notifications.notice": "通知", "dashboard.apiKeys": "API 密钥", "dashboard.manageKeys": "管理您的密钥", "dashboard.packages": "套餐", diff --git a/src/pages/Dashboard.jsx b/src/pages/Dashboard.jsx index affe88c..154d679 100644 --- a/src/pages/Dashboard.jsx +++ b/src/pages/Dashboard.jsx @@ -1,7 +1,6 @@ import React, { useState, useEffect, useCallback } from 'react'; import { Link } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; -import { Megaphone } from 'lucide-react'; import { useAuth } from '../context/AuthContext'; import { getUserUsage, @@ -175,9 +174,6 @@ export default function Dashboard() { ); const hasCustomCommissionRate = currentCommissionRate > defaultCommissionRate + 1e-8; - const announcements = Array.isArray(site?.announcements) - ? site.announcements.filter((item) => item?.content) - : (site?.announcement ? [{ content: site.announcement, publish_date: '' }] : []); const handleWithdraw = async () => { const amount = Number.parseFloat(withdrawAmount); @@ -315,32 +311,6 @@ export default function Dashboard() {

{t('dashboard.manageDesc')}

- {announcements.length > 0 && ( -
-
-
- -
-
-

{t('dashboard.announcements')}

-

{t('dashboard.announcementsDesc')}

-
-
-
- {announcements.slice(0, 10).map((item, index) => ( -
-
- {item.publish_date || t('dashboard.notice')} -
-

- {item.content} -

-
- ))} -
-
- )} -

{t('dashboard.balance')}