1
0

refactor: 迁移 UI 组件库从 Ant Design 至 TDesign

- 替换 antd 为 tdesign-react 作为主要 UI 组件库
- 引入 Recharts 替代 @ant-design/charts 实现图表功能
- 移除主题系统相关代码(ThemeContext、themes 目录)
- 更新所有组件以适配 TDesign 组件 API
- 更新测试用例以匹配新的组件实现
- 新增 TDesign 和 Recharts 集成规范文档
This commit is contained in:
2026-04-17 18:22:13 +08:00
parent 6eeb38c15e
commit 2b1c5e96c3
55 changed files with 1622 additions and 2541 deletions

View File

@@ -8,16 +8,15 @@ TBD - 提供供应商、模型配置和用量统计的前端管理界面
### Requirement: 提供供应商管理页面
前端 SHALL 使用 Ant Design 组件提供供应商管理页面,所有组件 SHALL 遵循 antd v6 API 规范
前端 SHALL 使用 TDesign 组件提供供应商管理页面。
#### Scenario: 显示供应商列表
- **WHEN** 加载供应商管理页面
- **THEN** 前端 SHALL 使用 Ant Design Table 显示所有已配置供应商
- **THEN** 前端 SHALL 使用 TDesign Table 显示所有已配置供应商
- **THEN** 每个供应商 SHALL 显示 name、base_url 和 enabled 状态(使用 Tag 组件)
- **THEN** API Key SHALL 被脱敏显示(掩码处理)
- **THEN** 表格 SHALL 支持展开行以显示关联模型
- **THEN** 表格 SHALL 设置 `scroll={{ x: 'max-content' }}` 防止窄屏溢出
#### Scenario: 表格列宽约束
@@ -36,32 +35,32 @@ TBD - 提供供应商、模型配置和用量统计的前端管理界面
#### Scenario: 添加新供应商
- **WHEN** 用户点击"添加供应商"按钮
- **THEN** 前端 SHALL 使用 Ant Design Modal + Form 显示输入表单
- **THEN** 前端 SHALL 使用 TDesign Dialog + Form 显示输入表单
- **THEN** 表单 SHALL 包含 id、name、api_key、base_url 字段,带校验规则
- **WHEN** 用户提交包含有效数据的表单
- **THEN** 前端 SHALL 通过 useMutation 调用创建 API
- **THEN** 成功后 SHALL 关闭 Modal 并刷新供应商列表
- **THEN** 失败 SHALL 使用 `App.useApp()` 提供的 `message` 实例显示错误提示
- **THEN** 成功后 SHALL 关闭 Dialog 并刷新供应商列表
- **THEN** 失败 SHALL 显示错误提示
#### Scenario: 编辑现有供应商
- **WHEN** 用户点击供应商的"编辑"按钮
- **THEN** 前端 SHALL 使用 Ant Design Modal + Form 显示预填充数据的表单
- **THEN** 前端 SHALL 使用 TDesign Dialog + Form 显示预填充数据的表单
- **WHEN** 用户提交包含更新数据的表单
- **THEN** 前端 SHALL 通过 useMutation 调用更新 API
- **THEN** 成功后 SHALL 关闭 Modal 并刷新供应商列表
- **THEN** 成功后 SHALL 关闭 Dialog 并刷新供应商列表
#### Scenario: 删除供应商
- **WHEN** 用户点击供应商的"删除"按钮
- **THEN** 前端 SHALL 使用 Ant Design Popconfirm 弹出确认
- **THEN** 前端 SHALL 使用 TDesign Popconfirm 弹出确认
- **WHEN** 用户确认删除
- **THEN** 前端 SHALL 通过 useMutation 调用删除 API
- **THEN** 成功后 SHALL 刷新供应商列表
### Requirement: 提供模型管理界面
前端 SHALL 在供应商页面展开行中提供模型管理,所有组件 SHALL 遵循 antd v6 API 规范
前端 SHALL 在供应商页面展开行中提供模型管理。
#### Scenario: 显示供应商的模型
@@ -78,9 +77,9 @@ TBD - 提供供应商、模型配置和用量统计的前端管理界面
#### Scenario: 为供应商添加模型
- **WHEN** 用户在展开行中点击"添加模型"
- **THEN** 前端 SHALL 显示 Ant Design Modal + Form
- **THEN** 前端 SHALL 显示 TDesign Dialog + Form
- **THEN** provider_id SHALL 自动关联当前供应商
- **THEN** 供应商选择 SHALL 使用 `options` 属性而非 `Select.Option` 子组件
- **THEN** 供应商选择 SHALL 使用 `options` 属性
- **WHEN** 用户提交表单
- **THEN** 前端 SHALL 通过 useMutation 调用创建 API
- **THEN** 成功后 SHALL 刷新模型列表
@@ -103,7 +102,7 @@ TBD - 提供供应商、模型配置和用量统计的前端管理界面
### Requirement: 提供统计查看页面
前端 SHALL 使用 Ant Design 组件提供统计仪表盘页面。
前端 SHALL 使用 TDesign 组件提供统计仪表盘页面。
#### Scenario: 显示统计概览
@@ -111,9 +110,8 @@ TBD - 提供供应商、模型配置和用量统计的前端管理界面
- **THEN** 前端 SHALL 在顶部显示统计摘要卡片(总请求量、活跃模型数、活跃供应商数、今日请求量)
- **THEN** 统计摘要数据 SHALL 从 stats API 返回数据中前端聚合
- **THEN** 前端 SHALL 显示请求趋势折线图
- **THEN** 前端 SHALL 使用 Ant Design Table 显示统计数据
- **THEN** 前端 SHALL 使用 TDesign Table 显示统计数据
- **THEN** 统计数据 SHALL 按供应商和模型显示请求计数
- **THEN** 统计表格 SHALL 设置 `scroll={{ x: 'max-content' }}` 防止窄屏溢出
#### Scenario: 统计表格列宽约束
@@ -130,24 +128,24 @@ TBD - 提供供应商、模型配置和用量统计的前端管理界面
#### Scenario: 按供应商过滤统计
- **WHEN** 用户从 Ant Design Select 选择供应商
- **WHEN** 用户从 TDesign Select 选择供应商
- **THEN** 前端 SHALL 自动查询并过滤统计
- **THEN** 统计摘要卡片和趋势图表 SHALL 同步更新
#### Scenario: 按日期范围过滤统计
- **WHEN** 用户使用 Ant Design DatePicker.RangePicker 选择日期范围
- **WHEN** 用户使用 TDesign DateRangePicker 选择日期范围
- **THEN** 前端 SHALL 自动查询并过滤统计
- **THEN** 统计摘要卡片和趋势图表 SHALL 同步更新
### Requirement: 优雅处理 API 错误
前端 SHALL 处理 API 错误并显示用户友好的消息message 组件 SHALL 通过 `App.useApp()` 获取
前端 SHALL 处理 API 错误并显示用户友好的消息。
#### Scenario: API 请求失败
- **WHEN** API 请求失败网络错误、4xx、5xx
- **THEN** 前端 SHALL 使用 `App.useApp()` 提供的 `message` 实例显示全局错误提示
- **THEN** 前端 SHALL 显示全局错误提示
- **THEN** 错误消息 SHALL 具有描述性
#### Scenario: 验证错误
@@ -158,21 +156,14 @@ TBD - 提供供应商、模型配置和用量统计的前端管理界面
### Requirement: 提供响应式布局
前端 SHALL 使用 Ant Design Layout 提供侧边栏导航布局。
前端 SHALL 使用 TDesign Layout 提供侧边栏导航布局。
#### Scenario: 桌面布局
- **WHEN** 在桌面屏幕上查看前端(宽度 >= 992px
- **THEN** 布局 SHALL 使用 Ant Design `Layout.Sider` + `Menu`inline 模式)
- **WHEN** 在桌面屏幕上查看前端
- **THEN** 布局 SHALL 使用 TDesign `Layout.Aside` + `Menu`
- **THEN** 侧边栏 SHALL 显示导航菜单,包含图标和文字标签
- **THEN** 侧边栏 SHALL 可通过折叠按钮折叠为仅图标模式
#### Scenario: 响应式折叠
- **WHEN** 屏幕宽度小于 992px
- **THEN** 侧边栏 SHALL 自动折叠为图标模式
- **THEN** 折叠后侧边栏宽度 SHALL 为 80px
- **THEN** 菜单项 SHALL 仅显示图标
- **THEN** 侧边栏 SHALL 使用固定宽度 232px
#### Scenario: 页面内容区域
@@ -186,70 +177,52 @@ TBD - 提供供应商、模型配置和用量统计的前端管理界面
- **THEN** Header SHALL 仅显示当前页面标题
- **THEN** Header SHALL 不包含导航菜单
### Requirement: 使用无组件库的最小 UI
### Requirement: 使用 TDesign UI 组件库
前端 SHALL 使用 Ant Design 6 作为 UI 组件库,所有组件 SHALL 使用 antd v6 推荐的 API
#### Scenario: Ant Design 组件使用
- **WHEN** 实现前端
- **THEN** Button 组件 SHALL 使用 `variant``color` 属性替代已废弃的 `type`link/text/dashed`danger` 属性
- **THEN** Button `type="link"` SHALL 替换为 `variant="link"`
- **THEN** Button `danger` 属性 SHALL 替换为 `color="danger"`
- **THEN** Space 组件 SHALL 使用 `vertical` 布尔属性替代已废弃的 `direction` 属性
- **THEN** Select 组件 SHALL 使用 `options` 属性替代 `Select.Option` 子组件
- **THEN** 图标 SHALL 优先使用图标库中已有的图标
#### Scenario: App 组件包裹
- **WHEN** 应用初始化
- **THEN** `App.tsx` SHALL 在 `ConfigProvider` 内部使用 Ant Design `<App>` 组件包裹应用
- **THEN** hooks 中 SHALL 使用 `App.useApp()` 获取 `message` 实例
- **THEN** `message` 实例 SHALL NOT 通过静态 `import { message } from 'antd'` 获取
前端 SHALL 使用 TDesign 作为 UI 组件库。
### Requirement: 样式体系
前端样式 SHALL 优先使用 Ant Design 样式体系SCSS 作为补充工具。
前端样式 SHALL 优先使用 TDesign 样式体系SCSS 作为补充工具。
#### Scenario: Ant Design 样式优先
#### Scenario: TDesign 样式优先
- **WHEN** 实现组件样式
- **THEN** 前端 SHALL 优先使用 Ant Design 组件的 style prop
- **THEN** 前端 SHALL 优先使用 Ant Design v6 的语义化样式classNames 和 styles props
- **THEN** 前端 SHALL 使用 Ant Design Layout 组件处理布局
- **THEN** 前端 SHALL 优先使用 TDesign 组件的 style prop
- **THEN** 前端 SHALL 使用 TDesign Layout 组件处理布局
#### Scenario: SCSS 补充使用
- **WHEN** Ant Design 样式体系无法满足需求
- **WHEN** TDesign 样式体系无法满足需求
- **THEN** 前端 MAY 使用 SCSS 作为补充
- **THEN** SCSS 文件 SHALL 使用 *.module.scssSCSS Modules
- **THEN** 前端 SHALL NOT 使用纯 CSS 文件(*.css
#### Scenario: 移除冗余 SCSS
- **WHEN** SCSS 文件仅实现 Ant Design 已有的功能
- **WHEN** SCSS 文件仅实现 TDesign 已有的功能
- **THEN** 前端 SHALL 移除该 SCSS 文件
- **THEN** 前端 SHALL 使用 Ant Design 内置功能替代
- **THEN** 前端 SHALL 使用 TDesign 内置功能替代
### Requirement: 提供侧边栏导航
前端 SHALL 使用 Ant Design `Layout.Sider` 提供侧边栏导航。
前端 SHALL 使用 TDesign `Layout.Aside` 提供侧边栏导航。
#### Scenario: 侧边栏内容
- **WHEN** 渲染侧边栏
- **THEN** 侧边栏顶部 SHALL 显示应用名称/Logo
- **THEN** 侧边栏 SHALL 包含 inline 模式的导航菜单
- **THEN** 导航菜单项 SHALL 包含:供应商管理(CloudServerOutlined 图标)、用量统计(BarChartOutlined 图标)
- **THEN** 侧边栏底部 SHALL 放置主题切换按钮
- **THEN** 侧边栏 SHALL 包含导航菜单
- **THEN** 导航菜单项 SHALL 包含供应商管理ServerIcon 图标、用量统计ChartLineIcon 图标、设置SettingIcon 图标)
#### Scenario: 侧边栏折叠
#### Scenario: 导航菜单交互
- **WHEN** 用户点击侧边栏折叠按钮
- **THEN** 侧边栏 SHALL 切换折叠/展开状态
- **THEN** 折叠状态下菜单项 SHALL 仅显示图标
- **THEN** 折叠状态下应用名称/Logo SHALL 隐藏或缩小
- **THEN** 折叠状态下主题切换按钮 SHALL 保持可见可点击
- **WHEN** 用户点击导航中的"供应商管理"
- **THEN** 前端 SHALL 导航到 `/providers` 并高亮当前菜单项
- **WHEN** 用户点击导航中的"用量统计"
- **THEN** 前端 SHALL 导航到 `/stats` 并高亮当前菜单项
- **WHEN** 用户点击导航中的"设置"
- **THEN** 前端 SHALL 导航到 `/settings` 并高亮当前菜单项
#### Scenario: 导航菜单交互
@@ -355,10 +328,10 @@ TBD - 提供供应商、模型配置和用量统计的前端管理界面
- **WHEN** 用户执行创建、更新或删除操作
- **THEN** 前端 SHALL 使用 TanStack Query 的 useMutation hook
- **THEN** 操作成功后 SHALL 自动失效相关查询缓存
- **THEN** 操作失败 SHALL 使用 `App.useApp()` 提供的 `message` 实例显示错误提示
- **THEN** 操作失败 SHALL 显示错误提示
#### Scenario: 错误提示
- **WHEN** API 请求失败网络错误、4xx、5xx
- **THEN** 前端 SHALL 使用 `App.useApp()` 提供的 `message` 实例显示全局错误提示
- **THEN** 前端 SHALL 显示全局错误提示
- **THEN** 错误消息 SHALL 具有描述性

View File

@@ -0,0 +1,114 @@
# Recharts Integration
## Purpose
TBD - 集成Recharts图表库实现数据可视化功能替代@ant-design/charts。
## Requirements
### Requirement: Recharts依赖集成
系统SHALL正确集成Recharts图表库作为数据可视化的基础依赖。
#### Scenario: 安装Recharts依赖
- **WHEN** 依赖安装完成
- **THEN** package.json中SHALL存在recharts依赖
- **AND** recharts版本SHALL为2.x最新稳定版
- **AND** Recharts组件SHALL可正常导入使用
### Requirement: UsageChart图表重写
系统SHALL使用Recharts重新实现UsageChart组件保持原有功能。
#### Scenario: 折线图渲染
- **WHEN** UsageChart组件接收统计数据
- **THEN** SHALL使用Recharts的LineChart组件渲染
- **AND** X轴SHALL显示日期数据
- **AND** Y轴SHALL显示请求数据
- **AND** 图表SHALL支持鼠标悬停显示详情Tooltip
- **AND** 图表SHALL包含网格线CartesianGrid
#### Scenario: 响应式图表容器
- **WHEN** 图表渲染
- **THEN** SHALL使用ResponsiveContainer包裹
- **AND** 图表宽度SHALL自适应容器宽度
- **AND** 图表高度SHALL为固定300px
#### Scenario: 空数据状态处理
- **WHEN** 统计数据为空数组
- **THEN** SHALL显示"暂无数据"提示
- **AND** 不SHALL渲染图表组件
#### Scenario: 数据格式转换
- **WHEN** 接收UsageStats数组数据
- **THEN** SHALL按日期聚合计数
- **AND** 数据SHALL按日期升序排序
- **AND** 数据格式SHALL适配Recharts要求
### Requirement: 图表样式配置
系统SHALL配置Recharts图表样式确保视觉一致性。
#### Scenario: 图表颜色配置
- **WHEN** 图表渲染
- **THEN** 折线颜色SHALL为TDesign主色#0052D9
- **AND** 线条宽度SHALL为2px
- **AND** 数据点样式SHALL正常显示
#### Scenario: 网格线配置
- **WHEN** 图表渲染
- **THEN** 网格线SHALL使用虚线样式strokeDasharray="3 3"
- **AND** 网格线SHALL不遮挡数据线
### Requirement: 移除Ant Design Charts
系统SHALL完全移除@ant-design/charts的使用。
#### Scenario: 移除Line组件
- **WHEN** 迁移完成
- **THEN** UsageChart中SHALL不存在@ant-design/charts的Line组件
- **AND** UsageChart中SHALL不存在任何@ant-design/charts导入
#### Scenario: 移除配置对象模式
- **WHEN** 图表实现
- **THEN** SHALL使用Recharts声明式组件模式
- **AND** 不SHALL使用Ant Design Charts的配置对象模式xField、yField等
### Requirement: 图表交互功能
系统SHALL保持图表的基本交互功能。
#### Scenario: 鼠标悬停提示
- **WHEN** 用户鼠标悬停在数据点上
- **THEN** SHALL显示Tooltip提示框
- **AND** 提示框SHALL显示日期和请求数
- **AND** 提示框SHALL不遮挡图表内容
#### Scenario: 平滑曲线效果
- **WHEN** 折线渲染
- **THEN** SHALL使用monotone类型平滑曲线
- **AND** 曲线SHALL自然流畅
- **AND** 数据点SHALL准确对应
### Requirement: 图表性能
系统SHALL确保图表渲染性能满足要求。
#### Scenario: 大数据量渲染
- **WHEN** 统计数据包含大量数据点(>100
- **THEN** 图表SHALL在1秒内完成渲染
- **AND** 交互响应SHALL流畅无卡顿
#### Scenario: 组件重渲染优化
- **WHEN** 父组件重新渲染
- **THEN** 图表组件SHALL避免不必要的重渲染
- **AND** 数据未变化时SHALL保持稳定
### Requirement: 图表测试覆盖
系统SHALL为Recharts图表组件提供完整的测试覆盖。
#### Scenario: 组件渲染测试
- **WHEN** 运行单元测试
- **THEN** UsageChart测试SHALL验证正常渲染
- **AND** UsageChart测试SHALL验证空数据状态
- **AND** UsageChart测试SHALL验证数据格式转换
#### Scenario: 数据处理测试
- **WHEN** 运行单元测试
- **THEN** 测试SHALL覆盖日期聚合逻辑
- **AND** 测试SHALL覆盖数据排序逻辑
- **AND** 测试SHALL验证边界情况

View File

@@ -0,0 +1,122 @@
# TDesign Integration
## Purpose
TBD - 集成TDesign React组件库提供统一的UI设计系统和组件支持替代Ant Design。
## Requirements
### Requirement: TDesign全局配置
系统SHALL正确配置TDesign ConfigProvider作为全局配置容器确保所有TDesign组件使用统一的配置。
#### Scenario: 应用启动时加载TDesign配置
- **WHEN** 应用初始化启动
- **THEN** ConfigProvider组件SHALL包裹整个应用
- **AND** TDesign全局样式SHALL被正确引入
- **AND** 所有TDesign组件SHALL使用统一配置
#### Scenario: 移除Ant Design配置
- **WHEN** 迁移完成
- **THEN** 应用中SHALL不存在Ant Design的ConfigProvider
- **AND** 应用中SHALL不存在ThemeProvider
- **AND** 应用中SHALL不存在任何Ant Design全局配置
### Requirement: TDesign组件替换
系统SHALL将所有Ant Design组件替换为对应的TDesign组件保持功能完整性。
#### Scenario: 布局组件替换
- **WHEN** 使用Layout组件
- **THEN** SHALL使用TDesign的Layout组件
- **AND** Layout.Sider SHALL替换为Layout.Aside
- **AND** Layout.Header SHALL保持不变
- **AND** Layout.Content SHALL保持不变
#### Scenario: 表单组件替换
- **WHEN** 使用表单相关组件
- **THEN** Modal SHALL替换为Dialog
- **AND** Form.Item SHALL替换为Form.FormItem
- **AND** Input、Select、Switch SHALL使用TDesign版本
- **AND** 表单验证功能SHALL保持完整
#### Scenario: 数据展示组件替换
- **WHEN** 使用数据展示组件
- **THEN** Table、Card、Statistic、Tag SHALL使用TDesign版本
- **AND** 组件功能SHALL保持不变
- **AND** 组件API SHALL兼容原有使用方式
#### Scenario: 导航组件替换
- **WHEN** 使用导航组件
- **THEN** Menu SHALL使用TDesign版本
- **AND** 菜单项配置SHALL正确映射
- **AND** 路由导航功能SHALL保持正常
### Requirement: TDesign图标系统
系统SHALL使用tdesign-icons-react作为图标库替换@ant-design/icons。
#### Scenario: 图标导入替换
- **WHEN** 使用图标组件
- **THEN** SHALL从tdesign-icons-react导入
- **AND** SHALL不从@ant-design/icons导入任何图标
- **AND** 图标显示SHALL正常
#### Scenario: 图标语义匹配
- **WHEN** 替换图标
- **THEN** 新图标SHALL与原图标语义相近
- **AND** CloudServerOutlined SHALL替换为语义相近的TDesign图标
- **AND** BarChartOutlined SHALL替换为语义相近的TDesign图标
- **AND** SettingOutlined SHALL替换为语义相近的TDesign图标
### Requirement: 栅格系统兼容
系统SHALL保持Row/Col栅格系统的使用确保响应式布局功能正常。
#### Scenario: 栅格组件替换
- **WHEN** 使用Row和Col组件
- **THEN** SHALL使用TDesign的Row和Col组件
- **AND** 响应式配置xs、sm、md、lg、xlSHALL保持有效
- **AND** gutter配置SHALL正常工作
- **AND** 布局效果SHALL与迁移前一致
### Requirement: 主题系统移除
系统SHALL完全移除多主题系统使用TDesign默认主题。
#### Scenario: 删除主题相关代码
- **WHEN** 迁移完成
- **THEN** ThemeContext SHALL被删除
- **AND** themes目录 SHALL被删除
- **AND** 所有主题相关导入SHALL被移除
#### Scenario: 使用TDesign默认主题
- **WHEN** 应用运行
- **THEN** SHALL使用TDesign默认视觉风格
- **AND** 不SHALL提供主题切换功能
- **AND** UI风格SHALL统一一致
### Requirement: 依赖管理
系统SHALL正确管理npm依赖确保无冗余依赖。
#### Scenario: 移除Ant Design依赖
- **WHEN** 依赖安装完成
- **THEN** package.json中SHALL不存在antd
- **AND** package.json中SHALL不存在@ant-design/icons
- **AND** package.json中SHALL不存在@ant-design/charts
- **AND** package.json中SHALL不存在antd-style
#### Scenario: 添加TDesign依赖
- **WHEN** 依赖安装完成
- **THEN** package.json中SHALL存在tdesign-react
- **AND** package.json中SHALL存在tdesign-icons-react
- **AND** 依赖版本SHALL为最新稳定版
### Requirement: Settings页面简化
系统SHALL保留Settings页面路由但简化页面内容为空状态。
#### Scenario: Settings页面访问
- **WHEN** 用户访问/settings路由
- **THEN** 页面SHALL正常加载
- **AND** 页面SHALL显示空状态提示
- **AND** 不SHALL显示主题设置相关内容
#### Scenario: Settings路由保留
- **WHEN** 应用路由配置
- **THEN** /settings路由SHALL存在
- **AND** Settings页面组件SHALL存在

View File

@@ -1,178 +0,0 @@
# 主题系统
## 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** `useThemeConfig` SHALL 优化加载策略,避免不必要的主题初始化开销
#### Scenario: 主题文件组织
- **THEN** 主题文件 SHALL 位于 `src/themes/` 目录
- **THEN** 每套主题 SHALL 有独立的配置文件
- **THEN** `src/themes/index.ts` SHALL 导出注册表和类型定义

View File

@@ -1,84 +0,0 @@
# 主题切换
## Purpose
管理主题状态与应用,使用 React Context 提供全局主题配置,支持多主题切换和持久化。
## Requirements
### Requirement: 持久化主题偏好
前端 SHALL 使用 localStorage 持久化用户的主题偏好。
#### Scenario: 保存主题偏好
- **WHEN** 用户选择主题或切换跟随系统开关
- **THEN** 前端 SHALL 将主题 ID 保存到 localStorage 键 `nex-theme-id`
- **THEN** 前端 SHALL 将跟随系统偏好保存到 localStorage 键 `nex-follow-system`
#### Scenario: 恢复主题偏好
- **WHEN** 用户重新访问前端应用
- **THEN** 前端 SHALL 从 localStorage 读取 `nex-theme-id`
- **THEN** 前端 SHALL 从 localStorage 读取 `nex-follow-system`
- **THEN** 如果 `nex-theme-id` 不存在或无效SHALL 使用 `'default'`
- **THEN** 如果 `nex-follow-system` 不存在SHALL 使用 `false`
#### Scenario: 刷新页面保持设置
- **WHEN** 用户在任意主题和跟随系统设置下刷新浏览器
- **THEN** 前端 SHALL 保持用户的选择
### Requirement: 使用 React Context 管理主题状态
前端 SHALL 使用 React Context 提供全局主题状态。
#### Scenario: 主题 Context 提供
- **WHEN** 应用初始化
- **THEN** ThemeContext SHALL 提供 `themeId`(当前选择的主题 ID
- **THEN** ThemeContext SHALL 提供 `followSystem`(跟随系统开关状态)
- **THEN** ThemeContext SHALL 提供 `systemIsDark`OS 暗色模式状态)
- **THEN** ThemeContext SHALL 提供 `effectiveThemeId`(计算后的实际主题 ID
- **THEN** ThemeContext SHALL 提供 `setThemeId`(设置主题方法)
- **THEN** ThemeContext SHALL 提供 `setFollowSystem`(设置跟随系统方法)
#### Scenario: 主题 Context 使用
- **WHEN** 组件需要访问或修改主题
- **THEN** 组件 SHALL 使用 `useTheme` hook
- **THEN** `useTheme` SHALL 返回当前主题状态和操作方法
- **THEN** 在 ThemeProvider 外使用 `useTheme` SHALL 抛出错误
#### Scenario: 计算有效主题
- **WHEN** `followSystem``true``systemIsDark``true`
- **THEN** `effectiveThemeId` SHALL 为 `'dark'`
- **WHEN** `followSystem``true``systemIsDark``false`
- **THEN** `effectiveThemeId` SHALL 为 `themeId`
- **WHEN** `followSystem``false`
- **THEN** `effectiveThemeId` SHALL 为 `themeId`
### Requirement: 集成 Ant Design ConfigProvider
前端 SHALL 使用 ConfigProvider 应用主题到 Ant Design 组件,包括侧边栏。
#### Scenario: ConfigProvider 主题配置
- **WHEN** 渲染应用
- **THEN** 前端 SHALL 使用 ConfigProvider 包裹应用
- **THEN** ConfigProvider 的 theme 属性 SHALL 由当前 `effectiveThemeId` 对应的主题配置决定
- **THEN** 配置 SHALL 包含完整的 `algorithm``token` 和组件样式覆盖
#### Scenario: 组件自动应用主题
- **WHEN** 主题切换
- **THEN** 所有 Ant Design 组件 SHALL 自动应用新主题
- **THEN** 主题切换 SHALL 平滑过渡,无闪烁
#### Scenario: 侧边栏响应主题切换
- **WHEN** `effectiveThemeId` 发生变化
- **THEN** 侧边栏的 `Menu theme` SHALL 同步切换为 `'light'``'dark'`
- **THEN** 侧边栏 Sider 背景颜色 SHALL 同步切换为对应的亮色或暗色
- **THEN** Logo 文字颜色 SHALL 同步适配侧边栏主题