From ba34019bde14b2b2d27a2ae7c70b5a662011358d Mon Sep 17 00:00:00 2001 From: mtvpls Date: Wed, 1 Jul 2026 10:21:51 +0800 Subject: [PATCH] =?UTF-8?q?=E9=80=9A=E7=9F=A5=E5=A2=9E=E5=8A=A0=E5=8C=BA?= =?UTF-8?q?=E5=9F=9Fswitch=EF=BC=8C=E5=A2=9E=E5=8A=A0=E5=85=8D=E8=B4=A3?= =?UTF-8?q?=E5=A3=B0=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/admin/page.tsx | 225 +++++++++++++++++- src/components/EmailSettingsPanel.tsx | 314 +++++++++++++++----------- 2 files changed, 410 insertions(+), 129 deletions(-) diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx index a098cfd..99e5253 100644 --- a/src/app/admin/page.tsx +++ b/src/app/admin/page.tsx @@ -12775,6 +12775,8 @@ const SuwayomiConfigComponent = ({ const [defaultLang, setDefaultLang] = useState('zh'); const [sourceIds, setSourceIds] = useState(''); const [maxSources, setMaxSources] = useState(10); + const [showMangaDisclaimer, setShowMangaDisclaimer] = useState(false); + const [mangaCountdown, setMangaCountdown] = useState(10); useEffect(() => { if (config?.SuwayomiConfig) { @@ -12789,6 +12791,14 @@ const SuwayomiConfigComponent = ({ } }, [config]); + useEffect(() => { + let timer: NodeJS.Timeout; + if (showMangaDisclaimer && mangaCountdown > 0) { + timer = setTimeout(() => setMangaCountdown(mangaCountdown - 1), 1000); + } + return () => clearTimeout(timer); + }, [showMangaDisclaimer, mangaCountdown]); + const buildConfig = () => ({ Enabled: enabled, ServerURL: serverURL, @@ -12896,7 +12906,14 @@ const SuwayomiConfigComponent = ({

+ {/* 漫画展馆免责声明弹窗 */} + {showMangaDisclaimer && + createPortal( +
+
+
+
+ +
+ +

+ 免责声明 +

+ +
+

+ 本功能仅供个人学习和技术研究使用,请勿将其部署在公网环境中,更不得用于任何违法违规行为。 + 使用本功能所产生的一切法律责任由使用者自行承担,与开发者无关。 + 启用此功能即表示您已充分理解并同意承担相应风险。 +

+
+ +
+ + +
+
+
+
, + document.body + )} +
+ {/* 电子书馆免责声明弹窗 */} + {showBooksDisclaimer && + createPortal( +
+
+
+
+ +
+ +

+ 免责声明 +

+ +
+

+ 本功能仅供个人学习和技术研究使用,请勿将其部署在公网环境中,更不得用于任何违法违规行为。 + 使用本功能所产生的一切法律责任由使用者自行承担,与开发者无关。 + 启用此功能即表示您已充分理解并同意承担相应风险。 +

+
+ +
+ + +
+
+
+
, + document.body + )} +
+ {/* 音乐免责声明弹窗 */} + {showMusicDisclaimer && + createPortal( +
+
+
+
+ +
+ +

+ 免责声明 +

+ +
+

+ 本功能仅供个人学习和技术研究使用,请勿将其部署在公网环境中,更不得用于任何违法违规行为。 + 使用本功能所产生的一切法律责任由使用者自行承担,与开发者无关。 + 启用此功能即表示您已充分理解并同意承担相应风险。 +

+
+ +
+ + +
+
+
+
, + document.body + )} +
diff --git a/src/components/EmailSettingsPanel.tsx b/src/components/EmailSettingsPanel.tsx index 34653f0..81ac0c9 100644 --- a/src/components/EmailSettingsPanel.tsx +++ b/src/components/EmailSettingsPanel.tsx @@ -2,6 +2,7 @@ import { Bell, Info, Mail, MonitorSmartphone, Send, X } from 'lucide-react'; import { createPortal } from 'react-dom'; +import { useState } from 'react'; interface EmailSettingsPanelProps { isOpen: boolean; @@ -30,6 +31,8 @@ interface EmailSettingsPanelProps { statusType?: 'success' | 'error' | null; } +type NotificationTab = 'email' | 'push' | 'telegram'; + function Toggle({ checked, disabled, @@ -96,11 +99,21 @@ export function EmailSettingsPanel({ }: EmailSettingsPanelProps) { if (!isOpen || !mounted) return null; + const [notificationTab, setNotificationTab] = useState('email'); + const pushDisabled = emailSettingsSaving || pushNotificationsBusy || (!pushNotifications && (!pushNotificationsConfigured || !pushNotificationsSupported)); + const telegramNotifyEnabled = Boolean(telegramEnabled); + + const tabs = [ + { key: 'email' as const, label: '邮件通知', icon: Mail }, + { key: 'push' as const, label: '浏览器通知', icon: MonitorSmartphone }, + { key: 'telegram' as const, label: 'Telegram', icon: Send }, + ]; + return createPortal( <>
+ {/* 三区域切换式导航 — 与电视访问一致 */} +
+ {tabs.map((item) => { + const Icon = item.icon; + const active = notificationTab === item.key; + return ( + + ); + })} +
+ {emailSettingsLoading ? (
@@ -154,147 +191,172 @@ export function EmailSettingsPanel({

) : ( -
-
-
-
- -
-
-

- 邮件通知 -

-

- 用于接收收藏影视更新等异步提醒,可独立于系统通知关闭。 -

-
-
- - - onUserEmailChange(e.target.value)} - placeholder='输入您的邮箱地址' - disabled={emailSettingsSaving} - className='mb-4 w-full rounded-xl border border-gray-300 bg-white px-3 py-2.5 text-sm text-gray-900 transition-colors placeholder:text-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-600 dark:bg-gray-900 dark:text-white' - /> - -
-
-
- 收藏更新邮件 -
-

- 当收藏的影片有更新时发送邮件通知。 -

-
- onEmailNotificationsChange(!emailNotifications)} - /> -
-
- -
-
-
- -
-
-

- 当前设备浏览器系统通知 -

-

- 当前设备收到站内通知时,通过浏览器推送到系统通知中心。 -

-
- onPushNotificationsChange(!pushNotifications)} - /> -
- -
-
- 当前设备 - - {pushNotificationsSupported ? '可用' : '需支持或授权'} - -
- {!pushNotificationsConfigured && ( -

- 系统正在初始化 Web Push 密钥,请稍后重试。 -

- )} - {pushNotificationsConfigured && !pushNotificationsSupported && ( -

- 当前浏览器、系统权限或登录模式暂不支持系统通知。 -

- )} -
-
- - {telegramEnabled && ( + <> + {/* 邮件通知 */} + {notificationTab === 'email' && (
- +
-

Telegram Bot 通知

+

+ 邮件通知 +

- 绑定 Telegram 后可接收站内通知,也可在登录页使用 Telegram 确认登录。 + 用于接收收藏影视更新等异步提醒,可独立于系统通知关闭。

-
+ + + onUserEmailChange(e.target.value)} + placeholder='输入您的邮箱地址' + disabled={emailSettingsSaving} + className='mb-4 w-full rounded-xl border border-gray-300 bg-white px-3 py-2.5 text-sm text-gray-900 transition-colors placeholder:text-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-600 dark:bg-gray-900 dark:text-white' + /> + +
+
+
+ 收藏更新邮件 +
+

+ 当收藏的影片有更新时发送邮件通知。 +

+
+ onEmailNotificationsChange(!emailNotifications)} + /> +
+
+ )} + + {/* 浏览器系统通知 */} + {notificationTab === 'push' && ( +
+
+
+ +
+
+

+ 当前设备浏览器系统通知 +

+

+ 当前设备收到站内通知时,通过浏览器推送到系统通知中心。 +

+
+ onPushNotificationsChange(!pushNotifications)} + /> +
+ +
- 绑定状态 - - {telegramBound ? `已绑定${telegramUsername ? ` @${telegramUsername}` : ''}` : '未绑定'} + 当前设备 + + {pushNotificationsSupported ? '可用' : '需支持或授权'}
- {!telegramBound && ( - <> - {telegramBindCode && ( -
- 绑定码:{telegramBindCode} -

在 Bot 中发送 /bind {telegramBindCode},或点击下方按钮打开 Telegram。

-
- )} -
- - {telegramDeepLink && ( - - )} -
- + {!pushNotificationsConfigured && ( +

+ 系统正在初始化 Web Push 密钥,请稍后重试。 +

+ )} + {pushNotificationsConfigured && !pushNotificationsSupported && ( +

+ 当前浏览器、系统权限或登录模式暂不支持系统通知。 +

)}
)} + {/* Telegram 通知 */} + {notificationTab === 'telegram' && ( + <> + {telegramNotifyEnabled ? ( +
+
+
+ +
+
+

Telegram Bot 通知

+

+ 绑定 Telegram 后可接收站内通知,也可在登录页使用 Telegram 确认登录。 +

+
+
+
+
+ 绑定状态 + + {telegramBound ? `已绑定${telegramUsername ? ` @${telegramUsername}` : ''}` : '未绑定'} + +
+ {!telegramBound && ( + <> + {telegramBindCode && ( +
+ 绑定码:{telegramBindCode} +

在 Bot 中发送 /bind {telegramBindCode},或点击下方按钮打开 Telegram。

+
+ )} +
+ + {telegramDeepLink && ( + + )} +
+ + )} +
+
+ ) : ( +
+
+
+ +
+
+

Telegram Bot 通知

+

+ 当前站点未启用 Telegram Bot 通知功能。 +

+
+
+
+ )} + + )} +
+ )}
@@ -336,4 +398,4 @@ export function EmailSettingsPanel({ , document.body ); -} +} \ No newline at end of file