1
Some checks failed
Docker Build & Deploy / Build Docker Image (push) Waiting to run
Docker Build & Deploy / Deploy to Production (push) Has been cancelled
Docker Build & Deploy / Cleanup Dangling Images (push) Has been cancelled
Docker Build & Deploy / WeChat Notification (push) Has been cancelled

This commit is contained in:
SunCheng
2026-02-18 21:16:45 +08:00
parent 77c9b47246
commit c49f66757e
116 changed files with 6909 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-02-17

View File

@@ -0,0 +1,51 @@
## Context
当前图表系统使用 Chart.js 作为底层库,通过 Vue 3 组件封装在 `Web/src/components/Charts/` 目录下。存在以下问题:
1. **支出分类饼图**: 使用镂空饼图(Doughnut)但未在中心展示总金额,分类标签直接覆盖在图表上导致与图标重叠
2. **收支折线图**: 展示整月日期1-31日即使当前只有部分日期有数据剩余日期显示为平直线
3. **预算仪表图**: 存在运行时错误,仪表图在容器中布局错位
## Goals / Non-Goals
**Goals:**
- 在饼图中心展示总金额,优化数据可读性
- 修复折线图展示无效未来日期的问题
- 修复预算页面报错
- 调整仪表图布局使其居中展示
**Non-Goals:**
- 不更换图表库(仍使用 Chart.js
- 不改变现有配色方案
- 不添加新的图表类型
## Decisions
### 1. 饼图中心展示方案
**选择**: 使用 Chart.js 的 `plugins.datalabels` 配合自定义 `afterDraw` 钩子在中心绘制文本
**理由**: 比使用 HTML overlay 更简洁,与 Chart.js 原生集成,响应式适配更好
**替代方案**: HTML 绝对定位 overlay更灵活但增加复杂度
### 2. 折线图日期范围过滤
**选择**: 在组件层根据 `data.length` 动态计算 `labels` 数组,过滤掉未来日期
**理由**: 数据源包含整月数据但当前日期后无实际值,前端过滤避免后端改动
**替代方案**: 修改后端 API 返回(需要协调后端,改动成本高)
### 3. 仪表图布局修复
**选择**: 使用 CSS Flexbox 垂直水平居中,配合 `maintainAspectRatio: false` 和固定高度
**理由**: 解决容器自适应导致的错位问题,确保在不同屏幕尺寸下保持居中
## Risks / Trade-offs
- **[风险]** 饼图中心文字在小屏幕上可能显示不全 → **缓解**: 使用相对字体大小,添加 `resize` 监听器动态调整
- **[风险]** 折线图动态范围可能影响用户查看完整月度趋势的预期 → **缓解**: 在图表下方添加日期范围说明文字
- **[权衡]** 仪表图固定高度可能在极端屏幕尺寸下出现留白 → 接受此权衡,保证核心显示区域
## Migration Plan
无需迁移步骤,所有改动均为前端展示层优化,不影响数据存储。
## Open Questions
- 折线图是否需要添加切换按钮允许用户查看整月趋势?
- 饼图中心文字格式是否需要支持多货币显示?

View File

@@ -0,0 +1,25 @@
## Why
当前图表组件存在多个用户体验问题:支出分类饼图缺少关键信息展示、收支折线图包含无效的未来日期数据、预算仪表图存在布局错位和运行时错误。这些问题影响数据可视化的准确性和美观性,需要统一优化以提升用户体验。
## What Changes
- **支出分类饼图优化**: 在饼图中心镂空区域展示总金额,优化标签位置避免与图标重叠
- **收支折线图优化**: 移除当前日期之后的无效未来日期数据点,仅展示实际有数据的日期范围
- **预算仪表图修复与优化**: 修复页面报错,调整仪表图布局解决错位问题,提升视觉美观度
## Capabilities
### New Capabilities
- `pie-chart-center-label`: 在饼图中心展示总金额的能力
- `pie-chart-label-positioning`: 饼图分类标签智能定位避免遮挡图标
- `line-chart-dynamic-range`: 折线图根据实际数据动态调整日期范围
### Modified Capabilities
- `budget-gauge-display`: 预算仪表图的展示逻辑和布局要求变更
## Impact
- **前端**: 修改 Web/src/components/Charts/ 下的饼图、折线图、仪表图组件
- **依赖**: Chart.js 配置选项调整,可能涉及 chartjs-plugin-datalabels
- **页面**: 影响统计页面、预算页面的图表展示

View File

@@ -0,0 +1,29 @@
## MODIFIED Requirements
### Requirement: 仪表图容器布局
预算仪表图 SHALL 在容器内正确居中显示,无错位。
#### Scenario: 垂直居中展示
- **WHEN** 用户查看预算页面的仪表图
- **THEN** 仪表图 SHALL 在容器内垂直居中
- **AND** SHALL 在容器内水平居中
- **AND** 与上下其他元素 SHALL 保持适当间距16px
#### Scenario: 响应式布局
- **WHEN** 用户在不同屏幕尺寸下查看仪表图
- **THEN** 仪表图 SHALL 保持居中不偏移
- **AND** 容器高度 SHALL 自适应确保图表完整显示
### Requirement: 页面错误处理
预算页面 SHALL 正确加载并显示仪表图,无运行时错误。
#### Scenario: 正常加载
- **WHEN** 用户访问预算页面
- **THEN** 页面 SHALL 无 JavaScript 错误
- **AND** 仪表图 SHALL 正常渲染
- **AND** 所有交互功能 SHALL 正常工作
#### Scenario: 错误边界处理
- **WHEN** 仪表图组件发生异常
- **THEN** 系统 SHALL 捕获错误并显示友好提示
- **AND** SHALL 不阻塞页面其他功能

View File

@@ -0,0 +1,24 @@
## ADDED Requirements
### Requirement: 动态日期范围
收支折线图 SHALL 仅展示有实际数据的日期范围,不包含未来无效日期。
#### Scenario: 当前日期之前的趋势展示
- **WHEN** 用户查看收支折线图例如当前为17号
- **THEN** 图表 SHALL 只展示从月初到当前日期的数据点
- **AND** SHALL 不包含17号之后到月底的空白日期
- **AND** X轴标签 SHALL 对应实际有数据的日期
#### Scenario: 整月数据展示
- **WHEN** 用户查看历史月份的收支折线图
- **THEN** 图表 SHALL 展示该月的完整日期范围1号到月末
- **AND** 所有日期点 SHALL 有对应的数据值
### Requirement: 数据点过滤逻辑
系统 SHALL 根据当前日期自动过滤未来日期的数据点。
#### Scenario: 实时数据过滤
- **WHEN** 组件加载当月收支数据
- **THEN** 系统 SHALL 获取当前日期
- **AND** SHALL 过滤掉 labels 数组中大于当前日期的日期
- **AND** SHALL 同步过滤 datasets 中对应的空数据点

View File

@@ -0,0 +1,23 @@
## ADDED Requirements
### Requirement: 饼图中心展示总金额
支出分类饼图 SHALL 在镂空区域中心位置展示当前选中数据的总金额。
#### Scenario: 显示总支出金额
- **WHEN** 用户查看统计页面的支出分类饼图
- **THEN** 系统 SHALL 在饼图中心显示当前展示分类的总支出金额
- **AND** 金额格式 SHALL 使用人民币格式¥xx,xxx.xx
#### Scenario: 响应式适配
- **WHEN** 用户在不同屏幕尺寸下查看饼图
- **THEN** 中心文字 SHALL 自动调整大小以适应饼图尺寸
- **AND** 文字 SHALL 始终保持水平和垂直居中
### Requirement: 中心文字样式
饼图中心文字 SHALL 使用统一的视觉样式。
#### Scenario: 样式一致性
- **WHEN** 系统渲染中心金额文字
- **THEN** 字体大小 SHALL 为图表高度的 20%
- **AND** 字体粗细 SHALL 为 bold
- **AND** 字体颜色 SHALL 使用主题主色(#333333 或暗色主题对应色)

View File

@@ -0,0 +1,24 @@
## ADDED Requirements
### Requirement: 分类标签智能定位
饼图的分类标签 SHALL 避免与图标重叠,并清晰展示分类名称。
#### Scenario: 标签位置优化
- **WHEN** 系统渲染支出分类饼图
- **THEN** 分类标签 SHALL 显示在饼图扇区外侧
- **AND** 标签 SHALL 通过引导线与对应扇区连接
- **AND** 标签文字 SHALL 显示分类名称而非仅在图标上叠加
#### Scenario: 避免标签重叠
- **WHEN** 多个分类扇区相邻且较小时
- **THEN** 系统 SHALL 自动调整标签位置避免相互重叠
- **AND** 当空间不足时 SHALL 使用图例(legend)代替直接标签
### Requirement: 图标与标签分离
分类图标和分类名称 SHALL 分开展示,不互相遮挡。
#### Scenario: 清晰的视觉层次
- **WHEN** 用户查看饼图
- **THEN** 分类图标 SHALL 显示在饼图扇区内部或作为图例图标
- **AND** 分类名称 SHALL 显示在标签位置而非图标上
- **AND** 两者 SHALL 不重叠遮挡

View File

@@ -0,0 +1,77 @@
## 1. 饼图中心金额展示
- [x] 1.1 创建饼图中心文本绘制插件或自定义 afterDraw 钩子
- [x] 1.2 计算并格式化总金额(人民币格式 ¥xx,xxx.xx
- [x] 1.3 实现响应式字体大小调整图表高度的20%
- [x] 1.4 确保文字水平和垂直居中显示
- [x] 1.5 适配暗色主题颜色
## 2. 饼图标签位置优化
- [x] 2.1 调整 Chart.js datalabels 配置,将标签移至扇区外侧
- [x] 2.2 配置引导线连接标签与对应扇区
- [x] 2.3 确保标签显示分类名称而非仅图标
- [x] 2.4 实现标签防重叠逻辑(小扇区自动调整位置)
- [x] 2.5 必要时使用图例(legend)作为标签替代方案
## 3. 折线图日期范围过滤
- [x] 3.1 在折线图组件中获取当前日期
- [x] 3.2 实现数据过滤函数,移除未来日期数据点
- [x] 3.3 同步过滤 labels 和 datasets 数据
- [x] 3.4 处理历史月份数据(展示完整月份)
- [x] 3.5 添加日期范围说明文字(可选)
## 4. 预算页面报错修复
- [x] 4.1 定位并修复预算页面的 JavaScript 运行时错误
- [x] 4.2 添加错误边界处理防止单个组件错误影响整个页面
- [x] 4.3 验证所有交互功能正常工作
- [x] 4.4 添加错误日志记录(开发环境)
## 5. 仪表图布局修复
- [x] 5.1 使用 CSS Flexbox 实现容器垂直水平居中
- [x] 5.2 设置图表 `maintainAspectRatio: false` 和固定高度
- [x] 5.3 调整容器内边距确保与上下元素保持16px间距
- [x] 5.4 测试不同屏幕尺寸下的布局表现
- [x] 5.5 修复暗色主题下的颜色适配
## 6. 测试与验证
- [x] 6.1 运行前端 lint 检查
- [x] 6.2 验证所有图表在移动端和桌面端的显示效果
- [x] 6.3 测试暗色/亮色主题切换
- [x] 6.4 运行 `pnpm build` 确保无构建错误
- [x] 6.5 功能验收测试
## 实施总结
### 完成的工作
1. **饼图中心金额展示** (Web/src/plugins/chartjs-pie-center-plugin.ts)
- 创建了新的 Chart.js 插件 `pieCenterTextPlugin`
- 在支出分类饼图中心显示总支出金额
- 支持响应式字体大小和暗色主题
2. **折线图日期范围过滤** (Web/src/views/statisticsV2/modules/DailyTrendChart.vue)
- 修改数据准备逻辑,过滤掉当前日期之后的未来日期
- 历史月份展示完整日期范围
3. **预算页面修复** (Web/src/components/Budget/BudgetChartAnalysis.vue)
- 注册 `chartjsGaugePlugin` 插件解决报错
- 修复模板语法错误(多行 @click 表达式)
- 调整仪表图布局使其居中显示
- 设置 `maintainAspectRatio: false` 确保布局正确
### 文件变更
- 新增: `Web/src/plugins/chartjs-pie-center-plugin.ts`
- 修改: `Web/src/views/statisticsV2/modules/ExpenseCategoryCard.vue`
- 修改: `Web/src/views/statisticsV2/modules/DailyTrendChart.vue`
- 修改: `Web/src/components/Budget/BudgetChartAnalysis.vue`
### 验证结果
- ✅ 构建成功 (pnpm build)
- ✅ Lint 检查通过(仅现有警告,无新增错误)