Skyroc Admin React
主题与资源

主题系统

理解 apps/admin 如何通过 @skyroc/web-admin-theme 初始化主题、接入 Ant Design、持久化用户配置和同步全局副作用

这一页解决一个问题:修改后台主题、暗色模式、圆角、字号、布局模式或 Ant Design token 时,应该改应用配置、主题包,还是页面组件。

当前主题链路由 apps/admin 编排,@skyroc/web-admin-theme 提供运行时状态、默认配置、Ant Design 适配和全局副作用。

apps/admin/src/bootstrap.tsx
  -> setupTheme()
  -> render App
  -> AppAntdProvider
  -> @skyroc/web-admin-theme/AntdProvider
  -> GlobalEffect
  -> ThemeEffect

主题不是页面局部状态。启动阶段先初始化主题 atom,Provider 再把主题转成 Ant Design 配置,全局 effect 最后把暗色模式、滤镜、水印和缓存同步到 DOM 与 localStorage。

适用场景

你要做什么先看哪里
改默认主色、圆角、字号或布局模式packages/web/admin-theme/src/config/default.tssetupTheme({ overrides })
改当前应用读取主题缓存的方式apps/admin/src/bootstrap.tsx@skyroc/web-admin-theme/setupTheme
改 Ant Design token 生成packages/web/admin-theme/src/antd/shared.ts@skyroc/adapter-antd-theme
在页面读取或更新主题@skyroc/web-admin-theme/useTheme()
同步暗色 class、色弱、灰阶、水印@skyroc/web-admin-theme/ThemeEffectapps/admin/src/features/effects/GlobalEffect.tsx

当前实现位置

文件职责
apps/admin/src/bootstrap.tsx在组件渲染前调用 setupTheme({ buildTime: BUILD_TIME })
apps/admin/src/config.ts暴露 defaultThemeColordefaultDarkMode,并 re-export antd message/modal helpers。
apps/admin/src/features/antd/AntdProvider.tsx把当前语言和用户信息传给主题包的 AntdProvider
apps/admin/src/features/effects/GlobalEffect.tsx挂载 ThemeEffect,同步 DOM class、缓存、滤镜和水印。
packages/web/admin-theme/src/config/default.ts当前默认主题配置,包括颜色、圆角、字号、布局、header、tab、sider、footer 和 watermark。
packages/web/admin-theme/src/setup.ts初始化主题 atom,处理生产缓存和版本覆盖。

核心概念

setupTheme 是启动前置步骤

bootstrap.tsx 当前先执行:

setupTheme({
  buildTime: BUILD_TIME
});

这个调用必须发生在 App 渲染之前。否则 AntdProviderThemeEffect、登录页主题切换按钮和后台布局读取主题 atom 时,拿到的可能不是应用预期的初始主题。

setupTheme() 的行为分两类:

环境行为
开发环境直接使用 defaultThemeSettings 初始化主题。
生产环境从 storage 读取 themeSettings,再用 BUILD_TIME 判断是否应用 overrides。

生产环境的版本覆盖标记是 overrideThemeFlag。当构建时间变化且传入了 overrides,主题包可以在不清空全部用户缓存的前提下覆盖指定主题字段。

默认配置来自主题包

默认主题集中在 packages/web/admin-theme/src/config/default.ts

export const defaultThemeSettings: Theme.ThemeSetting = {
  themeScheme: 'light',
  themeColor: '#6366F1',
  themeRadius: 6,
  themeTextSize: 14,
  layout: {
    mode: 'vertical',
    scrollMode: 'content'
  }
};

这里是共享默认值。只有当默认值适用于所有消费 @skyroc/web-admin-theme 的后台应用时,才直接改这个文件。只想让 apps/admin 有自己的默认主题时,优先通过应用侧 setupTheme overrides 或 storage 初始化策略处理。

Ant Design 主题由 Provider 转换

apps/admin/src/features/antd/AntdProvider.tsx 当前做两件事:

  1. useLang() 读取当前语言,选择 antdLocales[locale]
  2. useUserInfoQuery() 读取用户信息,把 userName 交给主题包。
return (
  <AntdProvider locale={antdLocales[locale]} userName={userInfo?.userName}>
    {children}
  </AntdProvider>
);

真正的 Ant Design token、算法、暗色模式和组件 token 转换在 @skyroc/web-admin-theme 里完成。页面不应该自己嵌套新的 ConfigProvider 来覆盖全局主题,否则会和布局、弹窗、通知、message 的主题状态割裂。

ThemeEffect 负责外部系统同步

主题状态改变后,需要同步到 React 之外的系统:

同步对象目的
HTML dark class让全局 CSS、UnoCSS 和主题 token 感知暗色模式。
localStorage持久化用户主题选择。
灰阶 / 色弱滤镜应用全局视觉辅助模式。
watermark按主题状态和用户信息更新水印。

这些副作用集中在 ThemeEffect,由 GlobalEffect 挂载。页面里不需要再写 effect 去手动改 document.documentElement

最小可用示例

修改共享默认主色

如果你确认所有使用主题包的后台应用都应该更换默认主色,改:

// packages/web/admin-theme/src/config/default.ts
export const defaultThemeSettings: Theme.ThemeSetting = {
  themeScheme: 'light',
  themeColor: '#2563EB',
  themeRadius: 6
  // ...
};

改共享默认值后,需要检查 docs/web-kit-docs 里主题包文档是否也要同步。

只给 apps/admin 覆盖默认主题

如果只是当前应用需要覆盖默认值,优先把覆盖留在 apps/admin/src/bootstrap.tsx

setupTheme({
  buildTime: BUILD_TIME,
  overrides: {
    themeColor: '#2563EB',
    themeScheme: 'light'
  }
});

这会保持共享包默认值稳定,同时让当前应用在新构建版本中应用自己的覆盖项。

在页面里读取主题

页面需要根据当前主题做业务 UI 适配时,读取主题状态即可:

import { useTheme } from '@skyroc/web-admin-theme';

const ThemeAwarePanel = () => {
  const { darkMode, themeColor } = useTheme();

  return <div data-dark={darkMode} style={{ borderColor: themeColor }} />;
};

不要为了读取主题去访问 localStorage。缓存只是持久化手段,运行时数据源是主题 atom。

排查顺序

  1. 确认 bootstrap.tsx 是否在渲染 App 前调用了 setupTheme()
  2. 确认当前是开发环境还是生产环境,开发环境不会读取生产缓存覆盖逻辑。
  3. 检查 localStorage 中是否有旧的 themeSettingsthemeColordarkMode
  4. 如果 Ant Design 组件样式不对,先看 AppAntdProvider 是否包住了页面。
  5. 如果暗色模式 class 没变,确认 GlobalEffect 是否挂载了 ThemeEffect
  6. 如果默认值改了但用户无感,检查 BUILD_TIMEoverrideThemeFlag 是否导致缓存未覆盖。

常见误区

误区正确做法
在业务页面里新建 ConfigProvider 改全局主题全局主题走 AppAntdProvider@skyroc/web-admin-theme
直接改 localStorage 当作主题状态源运行时以主题 atom 为准,localStorage 只负责持久化。
把应用专属默认值写进共享主题包只影响 apps/admin 的默认值应放在应用侧 overrides。
改暗色模式时手动操作 DOM class暗色、灰阶、色弱和水印同步由 ThemeEffect 负责。
认为 .env 控制主题默认值当前主题默认值来自代码配置和 storage,不来自 .env

相关链接

主题继续查看
主题初始化、缓存和版本覆盖主题运行时与缓存
Ant Design token、CSS 变量和 loading 主题色主题 Token 与 Ant Design
启动时为什么先初始化主题启动流程
布局模式如何影响菜单和 tabs布局系统菜单与标签页
语言切换和 Ant Design locale国际化与图标
共享主题包完整 APIdocs/web-kit-docs/content/docs/theme/overview.mdxdocs/web-kit-docs/content/docs/theme/admin-theme.mdx

On this page