## MODIFIED Requirements ### Requirement: 仪表盘图表迁移模式 组件 SHALL 使用 Chart.js Doughnut 图表实现仪表盘(Gauge)效果,替代 ECharts Gauge 图表。 #### Scenario: 半圆仪表盘渲染 - **WHEN** 组件接收预算统计数据(current, limit) - **THEN** 系统使用 Doughnut 图表渲染半圆进度条,配置 `rotation: -90` 和 `circumference: 180` - **AND** 图表字体配置 SHALL 包含中文字体支持 #### Scenario: 中心文本叠加显示 - **WHEN** 仪表盘图表渲染完成 - **THEN** 系统在图表中心显示余额/超支文本,使用 CSS 绝对定位的覆盖层 - **AND** 中心文本 SHALL 正确显示中文,无乱码 #### Scenario: 动态颜色切换 - **WHEN** 实际值超过预算限额 - **THEN** 进度条颜色切换为危险色(`var(--van-danger-color)`),中心文本显示"超支" - **AND** "超支"文字 SHALL 清晰可读 #### Scenario: 暗色模式适配 - **WHEN** 用户切换到暗色主题 - **THEN** 图表颜色自动适配,使用 `useChartTheme` composable 获取主题色 - **AND** 文本颜色 SHALL 与背景有足够对比度 ### Requirement: 折线图迁移模式 组件 SHALL 使用 Chart.js Line 图表实现趋势折线图,替代 ECharts Line 图表。 #### Scenario: 单系列折线图渲染 - **WHEN** 组件接收月度支出数据(日期 + 金额数组) - **THEN** 系统渲染折线图,X 轴为日期标签,Y 轴为金额,使用渐变填充 - **AND** X 轴日期标签 SHALL 正确显示,无乱码 #### Scenario: 双系列折线图渲染 - **WHEN** 组件接收收支数据(包含收入和支出两个系列) - **THEN** 系统渲染两条折线,支出为红色,收入为绿色,支持独立的 hover 交互 - **AND** 图例 SHALL 正确显示"收入"和"支出"中文标签 #### Scenario: 空数据处理 - **WHEN** 图表数据为空或所有数据点为 0 - **THEN** 系统显示 `` 空状态组件,而非空白图表 #### Scenario: Tooltip 格式化 - **WHEN** 用户 hover 到数据点 - **THEN** Tooltip 显示"¥XXX.XX"格式的金额,使用 `callbacks.label` 自定义 - **AND** Tooltip 内容 SHALL 正确编码,无乱码 ### Requirement: 饼图/环形图迁移模式 组件 SHALL 使用 Chart.js Doughnut 图表实现分类统计环形图,替代 ECharts Pie 图表。 #### Scenario: 环形图渲染 - **WHEN** 组件接收分类统计数据(分类名称 + 金额数组) - **THEN** 系统渲染环形图,每个分类使用不同颜色,配置 `cutout: '50%'` - **AND** 分类标签 SHALL 正确显示中文名称 #### Scenario: 分类颜色映射 - **WHEN** 分类数据包含预定义颜色 - **THEN** 图表使用 props 传入的颜色数组,确保与列表中的分类色块一致 #### Scenario: 小分类合并 - **WHEN** 分类数量超过 10 个 - **THEN** 系统使用 `mergeSmallCategories()` 工具函数,将占比小于 5% 的分类合并为"其他" - **AND** "其他"标签 SHALL 正确显示 #### Scenario: 点击分类跳转 - **WHEN** 用户点击环形图扇区 - **THEN** 系统触发 `@category-click` 事件,传递分类名称和类型 ### Requirement: BaseChart 组件统一使用 所有图表组件 SHALL 使用 `BaseChart.vue` 包装组件,而非直接使用 vue-chartjs 组件。 #### Scenario: BaseChart 组件使用 - **WHEN** 组件需要渲染图表 - **THEN** 使用 `` - **AND** 通过 options 传入正确的字体配置 #### Scenario: Loading 状态处理 - **WHEN** 图表数据加载中 - **THEN** BaseChart 显示 `` 组件 #### Scenario: 图表渲染回调 - **WHEN** 图表渲染完成 - **THEN** BaseChart 触发 `@chart:render` 事件,传递 Chart.js 实例引用 ### Requirement: ECharts 代码完全移除 组件 SHALL 移除所有 ECharts 相关代码,包括导入语句、实例变量、环境变量判断。 #### Scenario: 移除 ECharts 导入 - **WHEN** 迁移组件 - **THEN** 删除 `import * as echarts from 'echarts'` 语句 #### Scenario: 移除环境变量开关 - **WHEN** 迁移组件 - **THEN** 删除 `const useChartJS = import.meta.env.VITE_USE_CHARTJS === 'true'` 和相关的 `v-if`/`v-else` 条件渲染 #### Scenario: 移除 ECharts 实例管理 - **WHEN** 迁移组件 - **THEN** 删除 `let chartInstance = null`、`echarts.init()`、`chartInstance.setOption()` 等代码 #### Scenario: 移除生命周期清理 - **WHEN** 迁移组件 - **THEN** 删除 `onBeforeUnmount()` 中的 `chartInstance.dispose()` 调用 ### Requirement: 测试覆盖 迁移后的组件 SHALL 通过白盒和黑盒测试验证功能正确性。 #### Scenario: 单元测试 - 组件挂载 - **WHEN** 运行 Jest 单元测试 - **THEN** 组件能够成功挂载,不抛出错误 #### Scenario: 单元测试 - Props 传递 - **WHEN** 传入测试数据 props - **THEN** 计算属性 `chartData` 和 `chartOptions` 返回正确的 Chart.js 配置对象 - **AND** options 中 SHALL 包含正确的字体配置 #### Scenario: E2E 测试 - 图表渲染 - **WHEN** 运行 Playwright E2E 测试 - **THEN** 浏览器中能看到图表元素(Canvas),且无控制台错误 - **AND** 图表文本 SHALL 正确显示,无乱码 #### Scenario: E2E 测试 - 用户交互 - **WHEN** 用户 hover 到图表数据点 - **THEN** Tooltip 正确显示,格式化后的金额信息可见 - **AND** Tooltip 内容 SHALL 无乱码 #### Scenario: 视觉回归测试 - **WHEN** 截图对比迁移前后的图表 - **THEN** 颜色、布局、字体大小差异在可接受范围内(像素差异 < 5%) - **AND** 中文文本 SHALL 清晰可读