From 3457a7c565125ea476a20556bb57071e1aee84e2 Mon Sep 17 00:00:00 2001 From: djteang <935037887@qq.com> Date: Mon, 22 Sep 2025 17:20:02 +0800 Subject: [PATCH] =?UTF-8?q?fixed:=E8=87=AA=E5=AE=9A=E4=B9=89=E4=B8=BB?= =?UTF-8?q?=E9=A2=98=E5=BA=94=E7=94=A8=E6=89=80=E6=9C=89=E4=BA=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/theme-init.js | 22 +-- src/app/page.tsx | 3 - src/components/GlobalThemeLoader.tsx | 62 ++----- src/components/ThemeManager.tsx | 258 +++++++++++++-------------- src/hooks/useTheme.ts | 86 +-------- 5 files changed, 153 insertions(+), 278 deletions(-) diff --git a/public/theme-init.js b/public/theme-init.js index 3a8a1c9..d4dedbe 100644 --- a/public/theme-init.js +++ b/public/theme-init.js @@ -15,31 +15,21 @@ // 应用自定义CSS if (css) { - let customStyleEl = document.getElementById('init-theme-css'); + let customStyleEl = document.getElementById('custom-theme-css'); if (!customStyleEl) { customStyleEl = document.createElement('style'); - customStyleEl.id = 'init-theme-css'; + customStyleEl.id = 'custom-theme-css'; document.head.appendChild(customStyleEl); } customStyleEl.textContent = css; } } - // 从localStorage获取保存的主题 - const savedTheme = localStorage.getItem('app-theme'); - const savedCustomCSS = localStorage.getItem('app-custom-css') || ''; + // 应用默认主题避免闪烁,等待GlobalThemeLoader加载全站配置 + applyTheme('default', ''); + console.log('主题初始化完成,等待加载全站配置'); - // 立即应用已保存的主题(如果有) - if (savedTheme) { - applyTheme(savedTheme, savedCustomCSS); - console.log('主题已初始化(本地设置):', savedTheme); - } else { - // 没有用户设置时,先应用默认主题 - applyTheme('default', ''); - console.log('主题已初始化(默认)'); - } - - // 注意:GlobalThemeLoader会在React组件挂载后进一步处理全站配置 + // 注意:GlobalThemeLoader会在React组件挂载后加载并应用全站主题配置 } catch (error) { console.error('主题初始化失败:', error); } diff --git a/src/app/page.tsx b/src/app/page.tsx index 3ec3cbf..9caac96 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -23,7 +23,6 @@ import { DoubanItem } from '@/lib/types'; import CapsuleSwitch from '@/components/CapsuleSwitch'; import ContinueWatching from '@/components/ContinueWatching'; import PageLayout from '@/components/PageLayout'; -import { useThemeInit } from '@/hooks/useTheme'; import ScrollableRow from '@/components/ScrollableRow'; import { useSite } from '@/components/SiteProvider'; import VideoCard from '@/components/VideoCard'; @@ -516,8 +515,6 @@ function HomeClient() { } export default function Home() { - // 初始化主题 - useThemeInit(); return ( diff --git a/src/components/GlobalThemeLoader.tsx b/src/components/GlobalThemeLoader.tsx index 3e7b12a..a055c9f 100644 --- a/src/components/GlobalThemeLoader.tsx +++ b/src/components/GlobalThemeLoader.tsx @@ -14,59 +14,19 @@ const GlobalThemeLoader = () => { console.log('获取到全站主题配置:', result); if (result.success && result.data) { - const { defaultTheme, customCSS, allowUserCustomization } = result.data; + const { defaultTheme, customCSS } = result.data; - // 检查用户是否有自定义设置 - const userTheme = localStorage.getItem('app-theme'); - const userCustomCSS = localStorage.getItem('app-custom-css') || ''; + console.log('加载全站主题配置:', { defaultTheme, customCSS }); - console.log('当前用户设置:', { userTheme, userCustomCSS }); - console.log('全站配置:', { defaultTheme, customCSS, allowUserCustomization }); - - // 如果不允许用户自定义,强制应用全局配置 - if (!allowUserCustomization) { - localStorage.setItem('app-theme', defaultTheme); - localStorage.setItem('app-custom-css', customCSS); - applyTheme(defaultTheme, customCSS); - console.log('强制应用全站配置:', defaultTheme); - return; - } - - // 智能决定使用哪个主题 - let finalTheme = defaultTheme; - let finalCSS = customCSS; - - // 检查是否需要强制应用全站主题 - // 如果localStorage中存储的主题与全站默认不同,说明可能是过期的设置,需要更新 - const shouldForceGlobalTheme = !userTheme || userTheme !== defaultTheme; - - if (shouldForceGlobalTheme) { - // 强制应用全站默认配置 - finalTheme = defaultTheme; - finalCSS = customCSS; - localStorage.setItem('app-theme', defaultTheme); - if (customCSS) { - localStorage.setItem('app-custom-css', customCSS); - } else { - localStorage.removeItem('app-custom-css'); - } - console.log('强制应用全站默认主题:', defaultTheme, '(替换过期设置:', userTheme, ')'); - } else { - // 用户设置与全站默认一致,使用现有设置 - finalTheme = userTheme; - finalCSS = userCustomCSS || customCSS; - console.log('保持一致的主题设置:', userTheme); - } - - // 应用最终主题 - applyTheme(finalTheme, finalCSS); + // 直接应用全站配置 + applyTheme(defaultTheme, customCSS); + console.log('已应用全站主题:', defaultTheme); } } catch (error) { - console.error('加载全局主题配置失败:', error); - // 失败时使用本地设置或默认设置 - const savedTheme = localStorage.getItem('app-theme') || 'default'; - const savedCustomCSS = localStorage.getItem('app-custom-css') || ''; - applyTheme(savedTheme, savedCustomCSS); + console.error('加载全站主题配置失败:', error); + // 失败时使用默认设置 + applyTheme('default', ''); + console.log('加载配置失败,使用默认主题'); } }; @@ -83,10 +43,10 @@ const GlobalThemeLoader = () => { } // 应用自定义CSS - let customStyleEl = document.getElementById('global-theme-css'); + let customStyleEl = document.getElementById('custom-theme-css'); if (!customStyleEl) { customStyleEl = document.createElement('style'); - customStyleEl.id = 'global-theme-css'; + customStyleEl.id = 'custom-theme-css'; document.head.appendChild(customStyleEl); } customStyleEl.textContent = css; diff --git a/src/components/ThemeManager.tsx b/src/components/ThemeManager.tsx index eeebe3c..7f300ab 100644 --- a/src/components/ThemeManager.tsx +++ b/src/components/ThemeManager.tsx @@ -274,7 +274,6 @@ const ThemeManager = ({ showAlert, role }: ThemeManagerProps) => { customCSS: string; allowUserCustomization: boolean; } | null>(null); - const [isGlobalMode, setIsGlobalMode] = useState(false); const isAdmin = role === 'admin' || role === 'owner'; @@ -338,23 +337,23 @@ const ThemeManager = ({ showAlert, role }: ThemeManagerProps) => { // 加载全局配置 const globalConfig = await loadGlobalThemeConfig(); - if (isGlobalMode && globalConfig) { + if (globalConfig) { // 使用全局配置 setCurrentTheme(globalConfig.defaultTheme); setCustomCSS(globalConfig.customCSS); applyTheme(globalConfig.defaultTheme, globalConfig.customCSS); } else { - // 使用本地配置 - const savedTheme = localStorage.getItem('app-theme') || globalConfig?.defaultTheme || 'default'; - const savedCustomCSS = localStorage.getItem('app-custom-css') || ''; - setCurrentTheme(savedTheme); - setCustomCSS(savedCustomCSS); - applyTheme(savedTheme, savedCustomCSS); + // 如果没有全局配置,使用默认值 + const defaultTheme = 'default'; + const defaultCSS = ''; + setCurrentTheme(defaultTheme); + setCustomCSS(defaultCSS); + applyTheme(defaultTheme, defaultCSS); } }; initTheme(); - }, [isGlobalMode]); + }, []); // 应用主题 const applyTheme = (themeId: string, css: string = '') => { @@ -383,7 +382,7 @@ const ThemeManager = ({ showAlert, role }: ThemeManagerProps) => { setCurrentTheme(themeId); applyTheme(themeId, customCSS); - if (isGlobalMode && isAdmin) { + if (isAdmin) { // 保存到全局配置 const success = await saveGlobalThemeConfig({ defaultTheme: themeId, @@ -399,15 +398,12 @@ const ThemeManager = ({ showAlert, role }: ThemeManagerProps) => { allowUserCustomization: globalThemeConfig?.allowUserCustomization ?? true, }); } - } else { - // 保存到本地 - localStorage.setItem('app-theme', themeId); } const theme = themes.find(t => t.id === themeId); showAlert({ type: 'success', - title: isGlobalMode ? '全局主题已设置' : '主题已切换', + title: '全站主题已设置', message: `已切换到${theme?.name}`, timer: 2000 }); @@ -432,7 +428,7 @@ const ThemeManager = ({ showAlert, role }: ThemeManagerProps) => { try { applyTheme(currentTheme, customCSS); - if (isGlobalMode && isAdmin) { + if (isAdmin) { // 保存到全局配置 const success = await saveGlobalThemeConfig({ defaultTheme: currentTheme, @@ -449,12 +445,10 @@ const ThemeManager = ({ showAlert, role }: ThemeManagerProps) => { }); } } else { - // 保存到本地 - localStorage.setItem('app-custom-css', customCSS); showAlert({ - type: 'success', - title: '自定义样式已应用', - message: '您的自定义CSS已生效', + type: 'warning', + title: '权限不足', + message: '仅管理员可以设置全站主题', timer: 2000 }); } @@ -469,14 +463,28 @@ const ThemeManager = ({ showAlert, role }: ThemeManagerProps) => { }; // 重置自定义CSS - const handleCustomCSSReset = () => { + const handleCustomCSSReset = async () => { setCustomCSS(''); applyTheme(currentTheme, ''); - localStorage.removeItem('app-custom-css'); + + if (isAdmin) { + // 保存到全局配置 + await saveGlobalThemeConfig({ + defaultTheme: currentTheme, + customCSS: '', + allowUserCustomization: globalThemeConfig?.allowUserCustomization ?? true, + }); + + setGlobalThemeConfig({ + defaultTheme: currentTheme, + customCSS: '', + allowUserCustomization: globalThemeConfig?.allowUserCustomization ?? true, + }); + } showAlert({ type: 'success', - title: '自定义样式已重置', + title: '全站自定义样式已重置', timer: 2000 }); }; @@ -495,68 +503,33 @@ const ThemeManager = ({ showAlert, role }: ThemeManagerProps) => { return (
{/* 管理员控制面板 */} - {isAdmin && ( + {isAdmin && globalThemeConfig && (

- 管理员主题设置 + 全站主题设置

-
-
- -

- 选择设置个人主题还是全站默认主题 -

+
+
+ 当前全站配置:
-
- - +
+ 默认主题: {themes.find(t => t.id === globalThemeConfig.defaultTheme)?.name || globalThemeConfig.defaultTheme} + {globalThemeConfig.customCSS && ' | 包含自定义CSS'} + {!globalThemeConfig.allowUserCustomization && ' | 禁止用户自定义'}
- {globalThemeConfig && ( -
-
- 当前全站配置: -
-
- 默认主题: {themes.find(t => t.id === globalThemeConfig.defaultTheme)?.name || globalThemeConfig.defaultTheme} - {globalThemeConfig.customCSS && ' | 包含自定义CSS'} - {!globalThemeConfig.allowUserCustomization && ' | 禁止用户自定义'} -
+
+
+ ℹ️ 全站主题
- )} - - {isGlobalMode && ( -
-
- ⚠️ 全站模式 -
-

- 在此模式下的更改将影响所有用户的默认主题配置 -

-
- )} +

+ 在此设置的主题配置将应用到整个网站,影响所有用户的默认体验 +

+
)} @@ -565,18 +538,18 @@ const ThemeManager = ({ showAlert, role }: ThemeManagerProps) => {

- {isGlobalMode && isAdmin ? '全站默认主题' : '主题选择'} + 全站主题选择

{themes.map((theme) => (
handleThemeChange(theme.id)} + : 'border-theme-border bg-theme-surface' + } ${isAdmin ? 'cursor-pointer hover:border-theme-accent/50' : 'cursor-not-allowed opacity-60'}`} + onClick={() => isAdmin && handleThemeChange(theme.id)} > {/* 主题预览 */}
@@ -589,11 +562,11 @@ const ThemeManager = ({ showAlert, role }: ThemeManagerProps) => { @@ -621,18 +594,35 @@ const ThemeManager = ({ showAlert, role }: ThemeManagerProps) => {

- 自定义样式 + 全站自定义样式

- + {isAdmin ? ( + + ) : ( +
+ 仅管理员可编辑 +
+ )}
- {showCustomEditor && ( + {!isAdmin && ( +
+
+ ⚠️ 权限限制 +
+

+ 您当前没有权限修改全站主题设置,请联系管理员。 +

+
+ )} + + {isAdmin && showCustomEditor && (

💡 使用提示:

@@ -685,47 +675,49 @@ const ThemeManager = ({ showAlert, role }: ThemeManagerProps) => {
{/* CSS 模板库 */} -
-

- - 🎨 样式模板库 -

-

选择预设模板快速应用炫酷效果,也可以在此基础上进行自定义修改

+ {isAdmin && ( +
+

+ + 🎨 全站样式模板库 +

+

选择预设模板快速应用炫酷效果到全站,也可以在此基础上进行自定义修改

-
- {cssTemplates.map((template) => ( -
-
-
{template.name}
- +
+ {cssTemplates.map((template) => ( +
+
+
{template.name}
+ +
+

{template.description}

+
+ {template.preview} +
-

{template.description}

-
- {template.preview} -
-
- ))} -
+ ))} +
-
-

- 💡 使用提示: 点击模板的"应用"按钮将代码复制到自定义CSS编辑器,然后可以在此基础上进行修改。记得点击"应用样式"按钮生效。 -

+
+

+ 💡 使用提示: 点击模板的"应用"按钮将代码复制到自定义CSS编辑器,然后可以在此基础上进行修改。记得点击"应用样式"按钮生效。 +

+
-
+ )} {/* 使用说明 */}
-

📖 主题定制指南

+

📖 全站主题定制指南

-

内置主题:选择预设主题即可一键切换整体风格

-

自定义CSS:通过CSS变量或直接样式实现个性化定制

-

样式模板:使用预设模板快速实现炫酷效果

+

内置主题:{isAdmin ? '选择预设主题即可一键切换全站整体风格' : '由管理员设置的全站预设主题'}

+ {isAdmin &&

自定义CSS:通过CSS变量或直接样式实现全站个性化定制

} + {isAdmin &&

样式模板:使用预设模板快速实现炫酷效果

}

主题变量:

  • --color-theme-bg - 背景色
  • @@ -734,12 +726,16 @@ const ThemeManager = ({ showAlert, role }: ThemeManagerProps) => {
  • --color-theme-text - 主文本色
  • --color-theme-border - 边框色
-

常用技巧:

-
    -
  • • 修改背景:{`body { background: linear-gradient(...); }`}
  • -
  • • 使用Tailwind:{`.my-class { @apply bg-red-500; }`}
  • -
  • • 组合多个模板效果获得独特样式
  • -
+ {isAdmin && ( + <> +

常用技巧:

+
    +
  • • 修改背景:{`body { background: linear-gradient(...); }`}
  • +
  • • 使用Tailwind:{`.my-class { @apply bg-red-500; }`}
  • +
  • • 组合多个模板效果获得独特样式
  • +
+ + )}
diff --git a/src/hooks/useTheme.ts b/src/hooks/useTheme.ts index e775ecd..b47747f 100644 --- a/src/hooks/useTheme.ts +++ b/src/hooks/useTheme.ts @@ -1,87 +1,19 @@ -// 全局主题Hook - 用于在任何组件中初始化和使用主题 -import { useEffect } from 'react'; +// 全局主题Hook - 已弃用,主题现在由 GlobalThemeLoader 统一管理 +// 保留此文件是为了向后兼容性,但不再使用 export const useThemeInit = () => { - useEffect(() => { - // 确保在客户端环境中执行 - if (typeof window === 'undefined') return; - - try { - // 从localStorage获取保存的主题 - const savedTheme = localStorage.getItem('app-theme') || 'default'; - const savedCustomCSS = localStorage.getItem('app-custom-css') || ''; - - // 立即应用主题到HTML元素 - const html = document.documentElement; - - // 移除所有主题属性 - html.removeAttribute('data-theme'); - - // 应用保存的主题 - if (savedTheme !== 'default') { - html.setAttribute('data-theme', savedTheme); - } - - // 应用自定义CSS - if (savedCustomCSS) { - let customStyleEl = document.getElementById('custom-theme-css'); - if (!customStyleEl) { - customStyleEl = document.createElement('style'); - customStyleEl.id = 'custom-theme-css'; - document.head.appendChild(customStyleEl); - } - customStyleEl.textContent = savedCustomCSS; - } - - console.log(`主题已初始化: ${savedTheme}`); - } catch (error) { - console.error('主题初始化失败:', error); - } - }, []); + // 不再执行任何操作,主题由 GlobalThemeLoader 处理 + console.warn('useThemeInit is deprecated. Theme is now managed by GlobalThemeLoader.'); }; export const useTheme = () => { - const applyTheme = (themeId: string, css: string = '') => { - if (typeof window === 'undefined') return; - - const html = document.documentElement; - - // 移除所有主题class - html.removeAttribute('data-theme'); - - // 应用新主题 - if (themeId !== 'default') { - html.setAttribute('data-theme', themeId); - } - - // 应用自定义CSS - let customStyleEl = document.getElementById('custom-theme-css'); - if (!customStyleEl) { - customStyleEl = document.createElement('style'); - customStyleEl.id = 'custom-theme-css'; - document.head.appendChild(customStyleEl); - } - customStyleEl.textContent = css; - - // 保存到localStorage - localStorage.setItem('app-theme', themeId); - localStorage.setItem('app-custom-css', css); - }; - - const getCurrentTheme = () => { - if (typeof window === 'undefined') return 'default'; - return localStorage.getItem('app-theme') || 'default'; - }; - - const getCurrentCustomCSS = () => { - if (typeof window === 'undefined') return ''; - return localStorage.getItem('app-custom-css') || ''; - }; + // 已弃用:主题现在由 GlobalThemeLoader 和 ThemeManager 统一管理 + console.warn('useTheme is deprecated. Use ThemeManager component for theme management.'); return { - applyTheme, - getCurrentTheme, - getCurrentCustomCSS + applyTheme: () => console.warn('applyTheme is deprecated'), + getCurrentTheme: () => 'default', + getCurrentCustomCSS: () => '' }; };