fix: 分站加载动画跟随主题色
- 添加 --page-bg/--page-spinner CSS 变量,各主题定义自己的颜色 - body 背景改用 CSS 变量,不再硬编码黑色 - SiteContext 获取站点信息后立即应用主题类到 body - localStorage 缓存主题类,刷新时在 React 加载前恢复,防止闪烁 - 浅色主题(clean/corporate/claude)加载时显示白色/米色背景+对应色 spinner Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
16c42412bc
commit
91e673aabd
36 files changed
+419
-12
No files matched your search
+3
-2
@@ -13,8 +13,9 @@ const Topup = lazy(() => import('./pages/Topup'));
|
||||
const Logs = lazy(() => import('./pages/Logs'));
|
||||
|
||||
const Loading = () => (
|
||||
<div className="flex items-center justify-center min-h-screen">
|
||||
<div className="w-8 h-8 border-2 border-brand-500/30 border-t-brand-500 rounded-full animate-spin" />
|
||||
<div className="flex items-center justify-center min-h-screen" style={{ background: 'var(--page-bg)' }}>
|
||||
<div className="w-8 h-8 rounded-full animate-spin"
|
||||
style={{ border: '2px solid var(--page-spinner-track)', borderTopColor: 'var(--page-spinner)' }} />
|
||||
</div>
|
||||
);
|
||||
|
||||
|
||||
@@ -3,6 +3,23 @@ import { getSiteInfo } from '../api';
|
||||
|
||||
const SiteContext = createContext(null);
|
||||
|
||||
// Map theme template name → CSS class(es) to apply on <body>
|
||||
const themeClassMap = {
|
||||
starter: '',
|
||||
default: 'theme-default',
|
||||
dark: 'theme-dark',
|
||||
minimal: 'theme-minimal',
|
||||
clean: 'theme-light',
|
||||
corporate: 'theme-light',
|
||||
claude: 'theme-light theme-claude',
|
||||
};
|
||||
|
||||
function applyThemeClass(themeName) {
|
||||
const cls = themeClassMap[themeName] || '';
|
||||
document.body.className = cls + (cls ? ' ' : '') + 'antialiased';
|
||||
try { localStorage.setItem('dist-theme-class', cls); } catch(e) {}
|
||||
}
|
||||
|
||||
export function SiteProvider({ children }) {
|
||||
const [site, setSite] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
@@ -12,6 +29,8 @@ export function SiteProvider({ children }) {
|
||||
.then((res) => {
|
||||
if (res.data.success) {
|
||||
setSite(res.data.data);
|
||||
// Apply theme class to body immediately
|
||||
applyThemeClass(res.data.data?.theme_template);
|
||||
// Update page title
|
||||
if (res.data.data?.name) {
|
||||
document.title = res.data.data.name;
|
||||
|
||||
@@ -39,8 +39,9 @@ const themeRegistry = {
|
||||
// Prevents theme flash (rendering default theme before API returns the real one)
|
||||
function ThemeLoading() {
|
||||
return (
|
||||
<div className="flex items-center justify-center min-h-screen bg-gray-950">
|
||||
<div className="w-8 h-8 border-2 border-white/20 border-t-white/70 rounded-full animate-spin" />
|
||||
<div className="flex items-center justify-center min-h-screen" style={{ background: 'var(--page-bg)' }}>
|
||||
<div className="w-8 h-8 rounded-full animate-spin"
|
||||
style={{ border: '2px solid var(--page-spinner-track)', borderTopColor: 'var(--page-spinner)' }} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
+17
-1
@@ -5,6 +5,10 @@
|
||||
@layer base {
|
||||
:root {
|
||||
--brand: 99 102 241;
|
||||
/* Page background */
|
||||
--page-bg: #000000;
|
||||
--page-spinner: rgba(255,255,255,0.7);
|
||||
--page-spinner-track: rgba(255,255,255,0.2);
|
||||
/* Text colors */
|
||||
--page-text: 255 255 255;
|
||||
--page-text-secondary: 163 163 163;
|
||||
@@ -32,7 +36,8 @@
|
||||
}
|
||||
|
||||
body {
|
||||
@apply bg-black text-white;
|
||||
background: var(--page-bg);
|
||||
color: rgb(var(--page-text));
|
||||
font-feature-settings: 'cv02', 'cv03', 'cv04', 'cv11';
|
||||
}
|
||||
|
||||
@@ -56,6 +61,9 @@
|
||||
|
||||
/* Light theme variable overrides */
|
||||
.theme-light {
|
||||
--page-bg: #ffffff;
|
||||
--page-spinner: rgba(99,102,241,0.8);
|
||||
--page-spinner-track: rgba(99,102,241,0.2);
|
||||
--page-text: 17 24 39;
|
||||
--page-text-secondary: 107 114 128;
|
||||
--page-text-muted: 156 163 175;
|
||||
@@ -80,6 +88,9 @@
|
||||
}
|
||||
|
||||
.theme-claude {
|
||||
--page-bg: #FAF6F1;
|
||||
--page-spinner: rgba(217,119,87,0.8);
|
||||
--page-spinner-track: rgba(217,119,87,0.2);
|
||||
--page-link: 217 119 87;
|
||||
--page-card-bg: rgba(255,255,255,0.7);
|
||||
--page-card-border: #E8DDD0;
|
||||
@@ -88,6 +99,11 @@
|
||||
--page-divider: #E8DDD0;
|
||||
--page-inset: rgba(61,48,36,0.06);
|
||||
}
|
||||
|
||||
/* Per-dark-theme background overrides */
|
||||
.theme-default { --page-bg: #09090b; }
|
||||
.theme-dark { --page-bg: #030712; }
|
||||
.theme-minimal { --page-bg: #0a0a0a; }
|
||||
}
|
||||
|
||||
@layer components {
|
||||
|
||||
Reference in new issue
Block a user