mirror of https://github.com/djteang/OrangeTV.git
fixed:自定义主题应用所有人
This commit is contained in:
parent
c462e1c2b5
commit
3457a7c565
|
|
@ -15,31 +15,21 @@
|
||||||
|
|
||||||
// 应用自定义CSS
|
// 应用自定义CSS
|
||||||
if (css) {
|
if (css) {
|
||||||
let customStyleEl = document.getElementById('init-theme-css');
|
let customStyleEl = document.getElementById('custom-theme-css');
|
||||||
if (!customStyleEl) {
|
if (!customStyleEl) {
|
||||||
customStyleEl = document.createElement('style');
|
customStyleEl = document.createElement('style');
|
||||||
customStyleEl.id = 'init-theme-css';
|
customStyleEl.id = 'custom-theme-css';
|
||||||
document.head.appendChild(customStyleEl);
|
document.head.appendChild(customStyleEl);
|
||||||
}
|
}
|
||||||
customStyleEl.textContent = css;
|
customStyleEl.textContent = css;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 从localStorage获取保存的主题
|
// 应用默认主题避免闪烁,等待GlobalThemeLoader加载全站配置
|
||||||
const savedTheme = localStorage.getItem('app-theme');
|
|
||||||
const savedCustomCSS = localStorage.getItem('app-custom-css') || '';
|
|
||||||
|
|
||||||
// 立即应用已保存的主题(如果有)
|
|
||||||
if (savedTheme) {
|
|
||||||
applyTheme(savedTheme, savedCustomCSS);
|
|
||||||
console.log('主题已初始化(本地设置):', savedTheme);
|
|
||||||
} else {
|
|
||||||
// 没有用户设置时,先应用默认主题
|
|
||||||
applyTheme('default', '');
|
applyTheme('default', '');
|
||||||
console.log('主题已初始化(默认)');
|
console.log('主题初始化完成,等待加载全站配置');
|
||||||
}
|
|
||||||
|
|
||||||
// 注意:GlobalThemeLoader会在React组件挂载后进一步处理全站配置
|
// 注意:GlobalThemeLoader会在React组件挂载后加载并应用全站主题配置
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('主题初始化失败:', error);
|
console.error('主题初始化失败:', error);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ import { DoubanItem } from '@/lib/types';
|
||||||
import CapsuleSwitch from '@/components/CapsuleSwitch';
|
import CapsuleSwitch from '@/components/CapsuleSwitch';
|
||||||
import ContinueWatching from '@/components/ContinueWatching';
|
import ContinueWatching from '@/components/ContinueWatching';
|
||||||
import PageLayout from '@/components/PageLayout';
|
import PageLayout from '@/components/PageLayout';
|
||||||
import { useThemeInit } from '@/hooks/useTheme';
|
|
||||||
import ScrollableRow from '@/components/ScrollableRow';
|
import ScrollableRow from '@/components/ScrollableRow';
|
||||||
import { useSite } from '@/components/SiteProvider';
|
import { useSite } from '@/components/SiteProvider';
|
||||||
import VideoCard from '@/components/VideoCard';
|
import VideoCard from '@/components/VideoCard';
|
||||||
|
|
@ -516,8 +515,6 @@ function HomeClient() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
// 初始化主题
|
|
||||||
useThemeInit();
|
|
||||||
return (
|
return (
|
||||||
<Suspense>
|
<Suspense>
|
||||||
<HomeClient />
|
<HomeClient />
|
||||||
|
|
|
||||||
|
|
@ -14,59 +14,19 @@ const GlobalThemeLoader = () => {
|
||||||
console.log('获取到全站主题配置:', result);
|
console.log('获取到全站主题配置:', result);
|
||||||
|
|
||||||
if (result.success && result.data) {
|
if (result.success && result.data) {
|
||||||
const { defaultTheme, customCSS, allowUserCustomization } = result.data;
|
const { defaultTheme, customCSS } = result.data;
|
||||||
|
|
||||||
// 检查用户是否有自定义设置
|
console.log('加载全站主题配置:', { defaultTheme, customCSS });
|
||||||
const userTheme = localStorage.getItem('app-theme');
|
|
||||||
const userCustomCSS = localStorage.getItem('app-custom-css') || '';
|
|
||||||
|
|
||||||
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);
|
applyTheme(defaultTheme, customCSS);
|
||||||
console.log('强制应用全站配置:', defaultTheme);
|
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);
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('加载全局主题配置失败:', error);
|
console.error('加载全站主题配置失败:', error);
|
||||||
// 失败时使用本地设置或默认设置
|
// 失败时使用默认设置
|
||||||
const savedTheme = localStorage.getItem('app-theme') || 'default';
|
applyTheme('default', '');
|
||||||
const savedCustomCSS = localStorage.getItem('app-custom-css') || '';
|
console.log('加载配置失败,使用默认主题');
|
||||||
applyTheme(savedTheme, savedCustomCSS);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -83,10 +43,10 @@ const GlobalThemeLoader = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 应用自定义CSS
|
// 应用自定义CSS
|
||||||
let customStyleEl = document.getElementById('global-theme-css');
|
let customStyleEl = document.getElementById('custom-theme-css');
|
||||||
if (!customStyleEl) {
|
if (!customStyleEl) {
|
||||||
customStyleEl = document.createElement('style');
|
customStyleEl = document.createElement('style');
|
||||||
customStyleEl.id = 'global-theme-css';
|
customStyleEl.id = 'custom-theme-css';
|
||||||
document.head.appendChild(customStyleEl);
|
document.head.appendChild(customStyleEl);
|
||||||
}
|
}
|
||||||
customStyleEl.textContent = css;
|
customStyleEl.textContent = css;
|
||||||
|
|
|
||||||
|
|
@ -274,7 +274,6 @@ const ThemeManager = ({ showAlert, role }: ThemeManagerProps) => {
|
||||||
customCSS: string;
|
customCSS: string;
|
||||||
allowUserCustomization: boolean;
|
allowUserCustomization: boolean;
|
||||||
} | null>(null);
|
} | null>(null);
|
||||||
const [isGlobalMode, setIsGlobalMode] = useState(false);
|
|
||||||
|
|
||||||
const isAdmin = role === 'admin' || role === 'owner';
|
const isAdmin = role === 'admin' || role === 'owner';
|
||||||
|
|
||||||
|
|
@ -338,23 +337,23 @@ const ThemeManager = ({ showAlert, role }: ThemeManagerProps) => {
|
||||||
// 加载全局配置
|
// 加载全局配置
|
||||||
const globalConfig = await loadGlobalThemeConfig();
|
const globalConfig = await loadGlobalThemeConfig();
|
||||||
|
|
||||||
if (isGlobalMode && globalConfig) {
|
if (globalConfig) {
|
||||||
// 使用全局配置
|
// 使用全局配置
|
||||||
setCurrentTheme(globalConfig.defaultTheme);
|
setCurrentTheme(globalConfig.defaultTheme);
|
||||||
setCustomCSS(globalConfig.customCSS);
|
setCustomCSS(globalConfig.customCSS);
|
||||||
applyTheme(globalConfig.defaultTheme, globalConfig.customCSS);
|
applyTheme(globalConfig.defaultTheme, globalConfig.customCSS);
|
||||||
} else {
|
} else {
|
||||||
// 使用本地配置
|
// 如果没有全局配置,使用默认值
|
||||||
const savedTheme = localStorage.getItem('app-theme') || globalConfig?.defaultTheme || 'default';
|
const defaultTheme = 'default';
|
||||||
const savedCustomCSS = localStorage.getItem('app-custom-css') || '';
|
const defaultCSS = '';
|
||||||
setCurrentTheme(savedTheme);
|
setCurrentTheme(defaultTheme);
|
||||||
setCustomCSS(savedCustomCSS);
|
setCustomCSS(defaultCSS);
|
||||||
applyTheme(savedTheme, savedCustomCSS);
|
applyTheme(defaultTheme, defaultCSS);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
initTheme();
|
initTheme();
|
||||||
}, [isGlobalMode]);
|
}, []);
|
||||||
|
|
||||||
// 应用主题
|
// 应用主题
|
||||||
const applyTheme = (themeId: string, css: string = '') => {
|
const applyTheme = (themeId: string, css: string = '') => {
|
||||||
|
|
@ -383,7 +382,7 @@ const ThemeManager = ({ showAlert, role }: ThemeManagerProps) => {
|
||||||
setCurrentTheme(themeId);
|
setCurrentTheme(themeId);
|
||||||
applyTheme(themeId, customCSS);
|
applyTheme(themeId, customCSS);
|
||||||
|
|
||||||
if (isGlobalMode && isAdmin) {
|
if (isAdmin) {
|
||||||
// 保存到全局配置
|
// 保存到全局配置
|
||||||
const success = await saveGlobalThemeConfig({
|
const success = await saveGlobalThemeConfig({
|
||||||
defaultTheme: themeId,
|
defaultTheme: themeId,
|
||||||
|
|
@ -399,15 +398,12 @@ const ThemeManager = ({ showAlert, role }: ThemeManagerProps) => {
|
||||||
allowUserCustomization: globalThemeConfig?.allowUserCustomization ?? true,
|
allowUserCustomization: globalThemeConfig?.allowUserCustomization ?? true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// 保存到本地
|
|
||||||
localStorage.setItem('app-theme', themeId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const theme = themes.find(t => t.id === themeId);
|
const theme = themes.find(t => t.id === themeId);
|
||||||
showAlert({
|
showAlert({
|
||||||
type: 'success',
|
type: 'success',
|
||||||
title: isGlobalMode ? '全局主题已设置' : '主题已切换',
|
title: '全站主题已设置',
|
||||||
message: `已切换到${theme?.name}`,
|
message: `已切换到${theme?.name}`,
|
||||||
timer: 2000
|
timer: 2000
|
||||||
});
|
});
|
||||||
|
|
@ -432,7 +428,7 @@ const ThemeManager = ({ showAlert, role }: ThemeManagerProps) => {
|
||||||
try {
|
try {
|
||||||
applyTheme(currentTheme, customCSS);
|
applyTheme(currentTheme, customCSS);
|
||||||
|
|
||||||
if (isGlobalMode && isAdmin) {
|
if (isAdmin) {
|
||||||
// 保存到全局配置
|
// 保存到全局配置
|
||||||
const success = await saveGlobalThemeConfig({
|
const success = await saveGlobalThemeConfig({
|
||||||
defaultTheme: currentTheme,
|
defaultTheme: currentTheme,
|
||||||
|
|
@ -449,12 +445,10 @@ const ThemeManager = ({ showAlert, role }: ThemeManagerProps) => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 保存到本地
|
|
||||||
localStorage.setItem('app-custom-css', customCSS);
|
|
||||||
showAlert({
|
showAlert({
|
||||||
type: 'success',
|
type: 'warning',
|
||||||
title: '自定义样式已应用',
|
title: '权限不足',
|
||||||
message: '您的自定义CSS已生效',
|
message: '仅管理员可以设置全站主题',
|
||||||
timer: 2000
|
timer: 2000
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -469,14 +463,28 @@ const ThemeManager = ({ showAlert, role }: ThemeManagerProps) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
// 重置自定义CSS
|
// 重置自定义CSS
|
||||||
const handleCustomCSSReset = () => {
|
const handleCustomCSSReset = async () => {
|
||||||
setCustomCSS('');
|
setCustomCSS('');
|
||||||
applyTheme(currentTheme, '');
|
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({
|
showAlert({
|
||||||
type: 'success',
|
type: 'success',
|
||||||
title: '自定义样式已重置',
|
title: '全站自定义样式已重置',
|
||||||
timer: 2000
|
timer: 2000
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
@ -495,46 +503,14 @@ const ThemeManager = ({ showAlert, role }: ThemeManagerProps) => {
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
{/* 管理员控制面板 */}
|
{/* 管理员控制面板 */}
|
||||||
{isAdmin && (
|
{isAdmin && globalThemeConfig && (
|
||||||
<div className="bg-theme-surface border border-theme-border rounded-lg p-4">
|
<div className="bg-theme-surface border border-theme-border rounded-lg p-4">
|
||||||
<h3 className="text-lg font-semibold text-theme-text mb-4 flex items-center gap-2">
|
<h3 className="text-lg font-semibold text-theme-text mb-4 flex items-center gap-2">
|
||||||
<Palette className="h-5 w-5" />
|
<Palette className="h-5 w-5" />
|
||||||
管理员主题设置
|
全站主题设置
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<div>
|
|
||||||
<label className="text-sm font-medium text-theme-text">配置模式</label>
|
|
||||||
<p className="text-xs text-theme-text-secondary mt-1">
|
|
||||||
选择设置个人主题还是全站默认主题
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center gap-3">
|
|
||||||
<label className="flex items-center gap-2 cursor-pointer">
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
name="configMode"
|
|
||||||
checked={!isGlobalMode}
|
|
||||||
onChange={() => setIsGlobalMode(false)}
|
|
||||||
className="w-4 h-4 text-theme-accent"
|
|
||||||
/>
|
|
||||||
<span className="text-sm text-theme-text">个人设置</span>
|
|
||||||
</label>
|
|
||||||
<label className="flex items-center gap-2 cursor-pointer">
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
name="configMode"
|
|
||||||
checked={isGlobalMode}
|
|
||||||
onChange={() => setIsGlobalMode(true)}
|
|
||||||
className="w-4 h-4 text-theme-accent"
|
|
||||||
/>
|
|
||||||
<span className="text-sm text-theme-text">全站默认</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{globalThemeConfig && (
|
|
||||||
<div className="p-3 bg-theme-accent/5 border border-theme-accent/20 rounded-lg">
|
<div className="p-3 bg-theme-accent/5 border border-theme-accent/20 rounded-lg">
|
||||||
<div className="text-sm text-theme-text">
|
<div className="text-sm text-theme-text">
|
||||||
<strong>当前全站配置:</strong>
|
<strong>当前全站配置:</strong>
|
||||||
|
|
@ -545,18 +521,15 @@ const ThemeManager = ({ showAlert, role }: ThemeManagerProps) => {
|
||||||
{!globalThemeConfig.allowUserCustomization && ' | 禁止用户自定义'}
|
{!globalThemeConfig.allowUserCustomization && ' | 禁止用户自定义'}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
|
|
||||||
{isGlobalMode && (
|
<div className="p-3 bg-blue-50 border border-blue-200 rounded-lg dark:bg-blue-900/20 dark:border-blue-700">
|
||||||
<div className="p-3 bg-yellow-50 border border-yellow-200 rounded-lg dark:bg-yellow-900/20 dark:border-yellow-700">
|
<div className="flex items-center gap-2 text-blue-800 dark:text-blue-200">
|
||||||
<div className="flex items-center gap-2 text-yellow-800 dark:text-yellow-200">
|
<span className="text-sm font-medium">ℹ️ 全站主题</span>
|
||||||
<span className="text-sm font-medium">⚠️ 全站模式</span>
|
|
||||||
</div>
|
</div>
|
||||||
<p className="text-xs text-yellow-700 dark:text-yellow-300 mt-1">
|
<p className="text-xs text-blue-700 dark:text-blue-300 mt-1">
|
||||||
在此模式下的更改将影响所有用户的默认主题配置
|
在此设置的主题配置将应用到整个网站,影响所有用户的默认体验
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
@ -565,18 +538,18 @@ const ThemeManager = ({ showAlert, role }: ThemeManagerProps) => {
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-lg font-semibold text-theme-text mb-4 flex items-center gap-2">
|
<h3 className="text-lg font-semibold text-theme-text mb-4 flex items-center gap-2">
|
||||||
<Palette className="h-5 w-5" />
|
<Palette className="h-5 w-5" />
|
||||||
{isGlobalMode && isAdmin ? '全站默认主题' : '主题选择'}
|
全站主题选择
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||||
{themes.map((theme) => (
|
{themes.map((theme) => (
|
||||||
<div
|
<div
|
||||||
key={theme.id}
|
key={theme.id}
|
||||||
className={`relative p-4 border-2 rounded-xl cursor-pointer transition-all ${currentTheme === theme.id
|
className={`relative p-4 border-2 rounded-xl transition-all ${currentTheme === theme.id
|
||||||
? 'border-theme-accent bg-theme-accent/5'
|
? 'border-theme-accent bg-theme-accent/5'
|
||||||
: 'border-theme-border bg-theme-surface hover:border-theme-accent/50'
|
: 'border-theme-border bg-theme-surface'
|
||||||
}`}
|
} ${isAdmin ? 'cursor-pointer hover:border-theme-accent/50' : 'cursor-not-allowed opacity-60'}`}
|
||||||
onClick={() => handleThemeChange(theme.id)}
|
onClick={() => isAdmin && handleThemeChange(theme.id)}
|
||||||
>
|
>
|
||||||
{/* 主题预览 */}
|
{/* 主题预览 */}
|
||||||
<div className="flex items-center justify-between mb-3">
|
<div className="flex items-center justify-between mb-3">
|
||||||
|
|
@ -589,11 +562,11 @@ const ThemeManager = ({ showAlert, role }: ThemeManagerProps) => {
|
||||||
<button
|
<button
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
handleThemePreview(theme.id);
|
if (isAdmin) handleThemePreview(theme.id);
|
||||||
}}
|
}}
|
||||||
className="p-1 text-theme-text-secondary hover:text-theme-accent transition-colors"
|
className={`p-1 transition-colors ${isAdmin ? 'text-theme-text-secondary hover:text-theme-accent' : 'text-theme-text-secondary opacity-50 cursor-not-allowed'}`}
|
||||||
title="预览主题"
|
title={isAdmin ? "预览主题" : "仅管理员可预览"}
|
||||||
disabled={previewMode}
|
disabled={previewMode || !isAdmin}
|
||||||
>
|
>
|
||||||
<Eye className="h-4 w-4" />
|
<Eye className="h-4 w-4" />
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -621,8 +594,9 @@ const ThemeManager = ({ showAlert, role }: ThemeManagerProps) => {
|
||||||
<div className="flex items-center justify-between mb-4">
|
<div className="flex items-center justify-between mb-4">
|
||||||
<h3 className="text-lg font-semibold text-theme-text flex items-center gap-2">
|
<h3 className="text-lg font-semibold text-theme-text flex items-center gap-2">
|
||||||
<Palette className="h-5 w-5" />
|
<Palette className="h-5 w-5" />
|
||||||
自定义样式
|
全站自定义样式
|
||||||
</h3>
|
</h3>
|
||||||
|
{isAdmin ? (
|
||||||
<button
|
<button
|
||||||
onClick={() => setShowCustomEditor(!showCustomEditor)}
|
onClick={() => setShowCustomEditor(!showCustomEditor)}
|
||||||
className="flex items-center gap-2 px-3 py-1.5 text-sm bg-theme-surface border border-theme-border rounded-lg hover:bg-theme-accent/5 transition-colors"
|
className="flex items-center gap-2 px-3 py-1.5 text-sm bg-theme-surface border border-theme-border rounded-lg hover:bg-theme-accent/5 transition-colors"
|
||||||
|
|
@ -630,9 +604,25 @@ const ThemeManager = ({ showAlert, role }: ThemeManagerProps) => {
|
||||||
{showCustomEditor ? <ChevronUp className="h-4 w-4" /> : <ChevronDown className="h-4 w-4" />}
|
{showCustomEditor ? <ChevronUp className="h-4 w-4" /> : <ChevronDown className="h-4 w-4" />}
|
||||||
{showCustomEditor ? '收起编辑器' : '展开编辑器'}
|
{showCustomEditor ? '收起编辑器' : '展开编辑器'}
|
||||||
</button>
|
</button>
|
||||||
|
) : (
|
||||||
|
<div className="text-sm text-theme-text-secondary">
|
||||||
|
仅管理员可编辑
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{showCustomEditor && (
|
{!isAdmin && (
|
||||||
|
<div className="p-4 bg-yellow-50 border border-yellow-200 rounded-lg dark:bg-yellow-900/20 dark:border-yellow-700 mb-4">
|
||||||
|
<div className="flex items-center gap-2 text-yellow-800 dark:text-yellow-200">
|
||||||
|
<span className="text-sm font-medium">⚠️ 权限限制</span>
|
||||||
|
</div>
|
||||||
|
<p className="text-xs text-yellow-700 dark:text-yellow-300 mt-1">
|
||||||
|
您当前没有权限修改全站主题设置,请联系管理员。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{isAdmin && showCustomEditor && (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="text-sm text-theme-text-secondary bg-theme-surface p-3 rounded-lg border border-theme-border">
|
<div className="text-sm text-theme-text-secondary bg-theme-surface p-3 rounded-lg border border-theme-border">
|
||||||
<p className="mb-2">💡 <strong>使用提示:</strong></p>
|
<p className="mb-2">💡 <strong>使用提示:</strong></p>
|
||||||
|
|
@ -685,12 +675,13 @@ const ThemeManager = ({ showAlert, role }: ThemeManagerProps) => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* CSS 模板库 */}
|
{/* CSS 模板库 */}
|
||||||
|
{isAdmin && (
|
||||||
<div className="bg-theme-surface border border-theme-border rounded-lg p-4">
|
<div className="bg-theme-surface border border-theme-border rounded-lg p-4">
|
||||||
<h4 className="font-medium text-theme-text mb-3 flex items-center gap-2">
|
<h4 className="font-medium text-theme-text mb-3 flex items-center gap-2">
|
||||||
<Palette className="h-4 w-4" />
|
<Palette className="h-4 w-4" />
|
||||||
🎨 样式模板库
|
🎨 全站样式模板库
|
||||||
</h4>
|
</h4>
|
||||||
<p className="text-sm text-theme-text-secondary mb-4">选择预设模板快速应用炫酷效果,也可以在此基础上进行自定义修改</p>
|
<p className="text-sm text-theme-text-secondary mb-4">选择预设模板快速应用炫酷效果到全站,也可以在此基础上进行自定义修改</p>
|
||||||
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3">
|
||||||
{cssTemplates.map((template) => (
|
{cssTemplates.map((template) => (
|
||||||
|
|
@ -718,14 +709,15 @@ const ThemeManager = ({ showAlert, role }: ThemeManagerProps) => {
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* 使用说明 */}
|
{/* 使用说明 */}
|
||||||
<div className="bg-theme-surface border border-theme-border rounded-lg p-4">
|
<div className="bg-theme-surface border border-theme-border rounded-lg p-4">
|
||||||
<h4 className="font-medium text-theme-text mb-2">📖 主题定制指南</h4>
|
<h4 className="font-medium text-theme-text mb-2">📖 全站主题定制指南</h4>
|
||||||
<div className="text-sm text-theme-text-secondary space-y-2">
|
<div className="text-sm text-theme-text-secondary space-y-2">
|
||||||
<p><strong>内置主题:</strong>选择预设主题即可一键切换整体风格</p>
|
<p><strong>内置主题:</strong>{isAdmin ? '选择预设主题即可一键切换全站整体风格' : '由管理员设置的全站预设主题'}</p>
|
||||||
<p><strong>自定义CSS:</strong>通过CSS变量或直接样式实现个性化定制</p>
|
{isAdmin && <p><strong>自定义CSS:</strong>通过CSS变量或直接样式实现全站个性化定制</p>}
|
||||||
<p><strong>样式模板:</strong>使用预设模板快速实现炫酷效果</p>
|
{isAdmin && <p><strong>样式模板:</strong>使用预设模板快速实现炫酷效果</p>}
|
||||||
<p><strong>主题变量:</strong></p>
|
<p><strong>主题变量:</strong></p>
|
||||||
<ul className="text-xs space-y-1 ml-4 mt-1">
|
<ul className="text-xs space-y-1 ml-4 mt-1">
|
||||||
<li>• <code className="bg-theme-bg px-1 rounded">--color-theme-bg</code> - 背景色</li>
|
<li>• <code className="bg-theme-bg px-1 rounded">--color-theme-bg</code> - 背景色</li>
|
||||||
|
|
@ -734,12 +726,16 @@ const ThemeManager = ({ showAlert, role }: ThemeManagerProps) => {
|
||||||
<li>• <code className="bg-theme-bg px-1 rounded">--color-theme-text</code> - 主文本色</li>
|
<li>• <code className="bg-theme-bg px-1 rounded">--color-theme-text</code> - 主文本色</li>
|
||||||
<li>• <code className="bg-theme-bg px-1 rounded">--color-theme-border</code> - 边框色</li>
|
<li>• <code className="bg-theme-bg px-1 rounded">--color-theme-border</code> - 边框色</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
{isAdmin && (
|
||||||
|
<>
|
||||||
<p><strong>常用技巧:</strong></p>
|
<p><strong>常用技巧:</strong></p>
|
||||||
<ul className="text-xs space-y-1 ml-4 mt-1">
|
<ul className="text-xs space-y-1 ml-4 mt-1">
|
||||||
<li>• 修改背景:<code className="bg-theme-bg px-1 rounded">{`body { background: linear-gradient(...); }`}</code></li>
|
<li>• 修改背景:<code className="bg-theme-bg px-1 rounded">{`body { background: linear-gradient(...); }`}</code></li>
|
||||||
<li>• 使用Tailwind:<code className="bg-theme-bg px-1 rounded">{`.my-class { @apply bg-red-500; }`}</code></li>
|
<li>• 使用Tailwind:<code className="bg-theme-bg px-1 rounded">{`.my-class { @apply bg-red-500; }`}</code></li>
|
||||||
<li>• 组合多个模板效果获得独特样式</li>
|
<li>• 组合多个模板效果获得独特样式</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,87 +1,19 @@
|
||||||
// 全局主题Hook - 用于在任何组件中初始化和使用主题
|
// 全局主题Hook - 已弃用,主题现在由 GlobalThemeLoader 统一管理
|
||||||
import { useEffect } from 'react';
|
// 保留此文件是为了向后兼容性,但不再使用
|
||||||
|
|
||||||
export const useThemeInit = () => {
|
export const useThemeInit = () => {
|
||||||
useEffect(() => {
|
// 不再执行任何操作,主题由 GlobalThemeLoader 处理
|
||||||
// 确保在客户端环境中执行
|
console.warn('useThemeInit is deprecated. Theme is now managed by GlobalThemeLoader.');
|
||||||
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);
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useTheme = () => {
|
export const useTheme = () => {
|
||||||
const applyTheme = (themeId: string, css: string = '') => {
|
// 已弃用:主题现在由 GlobalThemeLoader 和 ThemeManager 统一管理
|
||||||
if (typeof window === 'undefined') return;
|
console.warn('useTheme is deprecated. Use ThemeManager component for theme management.');
|
||||||
|
|
||||||
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') || '';
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
applyTheme,
|
applyTheme: () => console.warn('applyTheme is deprecated'),
|
||||||
getCurrentTheme,
|
getCurrentTheme: () => 'default',
|
||||||
getCurrentCustomCSS
|
getCurrentCustomCSS: () => ''
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue