1
0

feat: Header 倒计时数字滚动动画 — @number-flow/react 替换静态文本

This commit is contained in:
2026-05-16 00:14:35 +08:00
parent 88f4119a4e
commit f8d563c668
9 changed files with 212 additions and 41 deletions

View File

@@ -105,6 +105,25 @@ styles.css SHALL 定义前端组件复用的工具类,包含页面布局相关
- **WHEN** Drawer 概览统计区渲染
- **THEN** 统计卡片 SHALL 使用 `.overview-stat-card`background: var(--td-bg-color-container-hover)),并使用 TDesign Statistic 组件自带的上下布局title 在上、value 在下),通过 `.summary-stat-col`text-align: center实现内容居中。系统 SHALL NOT 使用已移除的 `.overview-stat-item``.overview-stat-value` 类。
### Requirement: NumberFlow 倒计时样式类
styles.css SHALL 定义 NumberFlow 倒计时相关样式类,供 Header 倒计时组件使用。样式 SHALL 继承 TDesign 文本颜色或使用 TDesign CSS tokens不得使用组件内联 `style`、硬编码色值、`!important` 或覆盖 TDesign 内部类名。
#### Scenario: 倒计时滚动容器类
- **WHEN** Header 自动刷新倒计时以 NumberFlow 形式渲染
- **THEN** 倒计时 SHALL 使用集中定义的滚动容器类,保持 inline-flex、baseline 对齐、nowrap 和 tabular-nums
#### Scenario: 倒计时数字类
- **WHEN** NumberFlow 数字渲染
- **THEN** 数字 SHALL 使用集中定义的数字类配置 line-height 和 NumberFlow mask CSS 变量,减少滚动边缘突兀感
#### Scenario: 倒计时单位类
- **WHEN** 分钟或秒单位文本渲染
- **THEN** 单位 SHALL 使用集中定义的单位类与数字保持基线对齐,并继承当前 TDesign 文本色
#### Scenario: 不使用内联样式
- **WHEN** RefreshCountdown 组件渲染 NumberFlow 倒计时
- **THEN** 组件 SHALL 通过 `className` 引用 styles.css 中的样式类,不得通过 React `style` prop 设置 NumberFlow 展示样式
### Requirement: 异常行背景类
styles.css SHALL 定义 DOWN 行的背景色和左侧竖线,使用安全选择器且不使用 `!important`

View File

@@ -20,7 +20,7 @@ HeadMenu operations 区域 SHALL 提供 RadioGroup 组件供用户选择刷新
- **THEN** 系统 SHALL 立即触发一次数据刷新,然后应用新的刷新间隔
### Requirement: 倒计时显示
RadioGroup 右侧 SHALL 显示距下次自动刷新的倒计时文本。倒计时逻辑 SHALL 封装在独立的 `RefreshCountdown` 组件中App 组件 SHALL NOT 持有每秒更新的 `now` state。
RadioGroup 右侧 SHALL 显示距下次自动刷新的倒计时。倒计时逻辑 SHALL 封装在独立的 `RefreshCountdown` 组件中App 组件 SHALL NOT 持有每秒更新的 `now` state。自动倒计时数字 SHALL 使用 `@number-flow/react` 提供滚动过渡,非倒计时状态 SHALL 保持普通文本或按钮语义。
#### Scenario: RefreshCountdown 组件封装
- **WHEN** Dashboard 页面渲染
@@ -30,22 +30,38 @@ RadioGroup 右侧 SHALL 显示距下次自动刷新的倒计时文本。倒计
- **WHEN** RefreshCountdown 组件渲染
- **THEN** 组件 SHALL 接收 `dashboardUpdatedAt: number``refreshInterval: number``isFetching: boolean``isManualRefresh: boolean``onRefresh: () => void` 作为 props
#### Scenario: 短时间格式
- **WHEN** 距下次刷新剩余时间小于 60 秒
#### Scenario: NumberFlow 数字滚动
- **WHEN** 自动刷新模式下已完成首次刷新且当前未处于刷新中状态
- **THEN** 倒计时数字 SHALL 使用 `@number-flow/react``NumberFlow` 渲染,并使用向下滚动趋势表达倒计时递减
#### Scenario: 秒级间隔格式
- **WHEN** 自动刷新间隔小于 60 秒
- **THEN** 倒计时 SHALL 显示为"xx秒"格式(如"26秒"
#### Scenario: 长时间格式
- **WHEN** 距下次刷新剩余时间大于等于 60 秒
- **THEN** 倒计时 SHALL 显示为"x分x秒"格式(如"4分30秒"
#### Scenario: 分钟级稳定格式
- **WHEN** 自动刷新间隔大于等于 60 秒
- **THEN** 倒计时 SHALL 显示为"x分xx秒"格式,秒数 SHALL 固定为两位(如"4分30秒"、"0分09秒"
#### Scenario: 时间数字边界
- **WHEN** 分钟级倒计时中的秒数在 59 到 00 边界变化
- **THEN** 秒数十位 SHALL 按时间显示规则限制在 0 到 5 之间滚动
#### Scenario: 无前缀
- **WHEN** 倒计时显示
- **THEN** 倒计时文本 SHALL 不包含任何前缀(如"下一次刷新:"),直接显示时间
- **THEN** 可见倒计时文本 SHALL 不包含任何前缀(如"下一次刷新:"),直接显示时间
#### Scenario: 可访问文本
- **WHEN** NumberFlow 倒计时渲染
- **THEN** 倒计时容器 SHALL 暴露与当前倒计时等价的可访问文本,供测试和辅助技术读取
#### Scenario: 刷新中状态
- **WHEN** 数据正在刷新isFetching=true 且 isLoading=false
- **THEN** 倒计时文本 SHALL 显示为"刷新中..."
#### Scenario: 等待首次刷新状态
- **WHEN** 自动刷新模式下尚未完成首次刷新
- **THEN** 倒计时文本 SHALL 显示为"等待首次刷新"
### Requirement: App 组件渲染隔离
App 组件 SHALL NOT 持有任何高频更新的 state如每秒更新的时钟确保 App 的重渲染频率与数据刷新频率一致(默认 30 秒一次)。
@@ -73,12 +89,16 @@ App 组件 SHALL NOT 持有任何高频更新的 state如每秒更新的时
- **THEN** 刷新按钮 SHALL 显示 loading 状态且 disabled防止连续点击
### Requirement: 布局稳定性
倒计时/按钮容器 SHALL 保持布局稳定,避免内容变化导致的抖动。
倒计时/按钮容器 SHALL 保持布局稳定,避免内容变化导致的抖动。NumberFlow 倒计时 SHALL 通过分组同步和等宽数字样式降低位数、单位和动画变化带来的布局偏移。
#### Scenario: 数字等宽
- **WHEN** 倒计时数字变化
- **THEN** 容器 SHALL 使用 tabular-nums 字体特性,确保数字等宽不抖动
- **THEN** 容器和 NumberFlow 倒计时 SHALL 使用 tabular-nums 字体特性,确保数字等宽不抖动
#### Scenario: NumberFlow 分组同步
- **WHEN** 分钟级倒计时同时渲染分钟和秒数
- **THEN** 分钟和秒数 SHALL 使用 `NumberFlowGroup` 同步布局变化
#### Scenario: 格式切换不抖动
- **WHEN** 倒计时在"秒"和"分秒"格式间切换
- **WHEN** 倒计时在按钮、秒级文本和分钟级文本之间切换
- **THEN** 容器 SHALL 使用 min-width 确保最小宽度,避免 RadioGroup 位移