- 迁移静态 message 到 App.useApp() 模式,使 message 感知 ConfigProvider 上下文 - Button type/danger 迁移为 variant/color 新 API - Space direction 迁移为 vertical 布尔属性 - Select.Option 子组件迁移为 options 属性 - AppLayout 硬编码颜色替换为 antd design token - 优化 useThemeConfig:default/dark 改为静态导出,减少不必要的 hook 调用 - 同步更新 openspec 主规范文档
6.3 KiB
6.3 KiB
主题系统
Purpose
提供多主题选择功能,支持 6 套主题切换、跟随系统暗色模式、主题注册表管理和设置页面。
Requirements
Requirement: 提供多主题选择功能
前端 SHALL 提供 6 套主题供用户选择:默认、暗黑、MUI、shadcn、Bootstrap、玻璃。
Scenario: 默认主题
- WHEN 用户首次访问应用且无持久化偏好
- THEN 前端 SHALL 使用"默认"主题
- THEN ConfigProvider SHALL 应用
theme.defaultAlgorithm
Scenario: 切换到暗黑主题
- WHEN 用户在设置页面选择"暗黑"主题
- THEN 前端 SHALL 应用"暗黑"主题
- THEN ConfigProvider SHALL 应用
theme.darkAlgorithm
Scenario: 切换到 MUI 主题
- WHEN 用户在设置页面选择"MUI"主题
- THEN 前端 SHALL 应用 MUI 主题的完整配置(algorithm + token + 组件样式)
Scenario: 切换到 shadcn 主题
- WHEN 用户在设置页面选择"shadcn"主题
- THEN 前端 SHALL 应用 shadcn 主题的完整配置
Scenario: 切换到 Bootstrap 主题
- WHEN 用户在设置页面选择"Bootstrap"主题
- THEN 前端 SHALL 应用 Bootstrap 主题的完整配置
Scenario: 切换到玻璃主题
- WHEN 用户在设置页面选择"玻璃"主题
- THEN 前端 SHALL 应用玻璃主题的完整配置
Requirement: 提供跟随系统功能
前端 SHALL 提供跟随系统开关,开启后自动检测 OS 暗色模式状态。
Scenario: 开启跟随系统且 OS 处于暗色模式
- WHEN 用户开启"跟随系统"开关
- AND OS 当前处于暗色模式
- THEN 前端 SHALL 强制使用"暗黑"主题
- AND 忽略用户在下拉栏选择的主题
Scenario: 开启跟随系统且 OS 处于亮色模式
- WHEN 用户开启"跟随系统"开关
- AND OS 当前处于亮色模式
- THEN 前端 SHALL 使用用户在下拉栏选择的主题
Scenario: 关闭跟随系统
- WHEN 用户关闭"跟随系统"开关
- THEN 前端 SHALL 始终使用用户在下拉栏选择的主题
- AND 忽略 OS 暗色模式状态
Scenario: OS 暗色模式实时变化
- WHEN "跟随系统"开关处于开启状态
- AND OS 从亮色模式切换到暗色模式
- THEN 前端 SHALL 自动切换到"暗黑"主题
- WHEN OS 从暗色模式切换到亮色模式
- THEN 前端 SHALL 自动恢复为用户选择的主题
Requirement: 持久化主题偏好
前端 SHALL 使用 localStorage 持久化用户的主题偏好。
Scenario: 保存主题选择
- WHEN 用户选择主题
- THEN 前端 SHALL 将主题 ID 保存到 localStorage 键
nex-theme-id - THEN 值 SHALL 为有效的主题标识符(
default、dark、mui、shadcn、bootstrap、glass)
Scenario: 保存跟随系统偏好
- WHEN 用户切换跟随系统开关
- THEN 前端 SHALL 将偏好保存到 localStorage 键
nex-follow-system - THEN 值 SHALL 为
'true'或'false'
Scenario: 恢复偏好
- WHEN 用户重新访问应用
- THEN 前端 SHALL 从 localStorage 读取
nex-theme-id和nex-follow-system - THEN 如果
nex-theme-id无效或不存在,SHALL 使用'default' - THEN 如果
nex-follow-system不存在,SHALL 使用false
Scenario: 忽略旧键名
- WHEN localStorage 中存在旧键
theme-mode - THEN 前端 SHALL 忽略该值
- THEN 前端 SHALL NOT 读取或迁移该键
Requirement: 提供设置页面
前端 SHALL 提供设置页面,使用卡片布局组织设置内容,所有布局组件 SHALL 遵循 antd v6 API 规范。
Scenario: 主题卡片
- WHEN 用户访问设置页面
- THEN 前端 SHALL 显示主题设置卡片
- THEN 卡片内 SHALL 包含主题下拉栏和跟随系统开关
- THEN 卡片内布局 SHALL 使用
Space的vertical布尔属性替代已废弃的direction属性
Scenario: 主题下拉栏
- WHEN 用户展开主题下拉栏
- THEN 下拉栏 SHALL 列出所有 6 套主题:默认、暗黑、MUI、shadcn、Bootstrap、玻璃
- THEN 当前选中的主题 SHALL 被高亮显示
- WHEN 用户选择一个主题
- THEN 前端 SHALL 立即切换到该主题
Scenario: 跟随系统开关
- WHEN 用户切换跟随系统开关
- THEN 前端 SHALL 立即应用新的跟随系统设置
- THEN 开关状态 SHALL 反映当前设置
Scenario: 侧边栏设置入口
- WHEN 渲染侧边栏菜单
- THEN 菜单 SHALL 包含"设置"菜单项
- THEN 菜单项 SHALL 使用
SettingOutlined图标 - WHEN 用户点击"设置"菜单项
- THEN 前端 SHALL 导航到
/settings路由
Requirement: 侧边栏跟随应用主题
侧边栏 SHALL 根据 effectiveThemeId 动态切换亮色或暗色外观,使用 antd token 获取颜色值。
Scenario: 亮色主题下的侧边栏
- WHEN
effectiveThemeId不为'dark' - THEN 侧边栏 Sider 背景 SHALL 使用 antd token 的
colorBgContainer而非硬编码颜色值 - THEN Logo 文字颜色 SHALL 使用 antd token 的
colorText而非硬编码颜色值 - THEN Menu 组件 SHALL 使用
theme="light" - THEN Header 背景和边框 SHALL 使用 antd token 获取颜色值
Scenario: 暗色主题下的侧边栏
- WHEN
effectiveThemeId为'dark' - THEN 侧边栏 Sider 背景 SHALL 为深色
- THEN Logo 文字颜色 SHALL 为白色
- THEN Menu 组件 SHALL 使用
theme="dark"
Scenario: 主题切换时侧边栏平滑过渡
- WHEN 用户从亮色主题切换到暗色主题(或反向切换)
- THEN 侧边栏 SHALL 平滑过渡到新主题外观
- THEN 过渡过程 SHALL 无闪烁
Requirement: 使用主题注册表管理主题
前端 SHALL 使用主题注册表统一管理所有主题配置。
Scenario: 主题注册表结构
- WHEN 应用初始化
- THEN 主题注册表 SHALL 包含 6 套主题的完整配置
- THEN 每套主题 SHALL 通过
useConfig()hook 返回ConfigProviderProps - THEN
useThemeConfigSHALL 优化加载策略,避免不必要的主题初始化开销
Scenario: 主题文件组织
- THEN 主题文件 SHALL 位于
src/themes/目录 - THEN 每套主题 SHALL 有独立的配置文件
- THEN
src/themes/index.tsSHALL 导出注册表和类型定义