Files
EmailBill/openspec/changes/archive/2026-02-17-fix-stats-chart-bugs/design.md
SunCheng c49f66757e
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
1
2026-02-18 21:16:45 +08:00

57 lines
2.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## Context
当前统计页面使用 Chart.js 渲染折线图和饼图,但存在以下技术问题:
1. **折线图溢出**: 图表 canvas 尺寸计算未考虑容器边界,导致图表绘制超出卡片范围
2. **时间范围显示**: 折线图 X 轴显示整个自然周期(如整月),但数据仅到当前日期,导致后半段为平直线
3. **饼图标签**: 当前饼图使用图例(legend)展示分类,用户需要在图例和图表间来回查看
项目使用 Vue 3 + Chart.js + vue-chartjs 技术栈,图表配置通过 `useChartTheme` composable 统一管理。
## Goals / Non-Goals
**Goals:**
- 实现图表在容器内的自适应布局,无溢出
- 折线图动态计算数据截止时间,仅显示有效数据范围
- 饼图扇区直接渲染分类名称标签
- 保持现有主题配置和响应式行为
**Non-Goals:**
- 不更换图表库(保持 Chart.js
- 不修改数据 API 或数据结构
- 不添加新的图表类型
- 不影响其他页面的图表显示
## Decisions
### 1. 布局约束方案: CSS 容器 + Chart.js responsive 配置
- **选择**: 结合 CSS `overflow: hidden` 和 Chart.js `maintainAspectRatio: false` + `responsive: true`
- **理由**: 利用 Chart.js 内置的响应式机制,同时通过 CSS 确保容器边界约束
- **替代方案**: 手动计算 canvas 尺寸(复杂,需监听 resize
### 2. 折线图数据过滤: 前端日期截断
- **选择**: 在组件内根据当前日期过滤数据数组,仅传递有效数据给 Chart.js
- **理由**: 最小化改动,不修改 API保持数据完整性以备他用
- **替代方案**: 后端 API 支持日期参数(需后端改动,过度设计)
### 3. 饼图标签方案: Chart.js datalabels 插件
- **选择**: 使用 `chartjs-plugin-datalabels` 插件在扇区上渲染标签
- **理由**: 官方推荐方案,支持自动位置计算和碰撞检测
- **替代方案**: 自定义绘制(复杂,需处理重叠)
## Risks / Trade-offs
| Risk | Mitigation |
|------|------------|
| 饼图标签在扇区过小时显示不全 | 设置最小扇区角度阈值,小分类合并为"其他" |
| 暗色模式切换时标签颜色适配 | 通过 `useChartTheme` 动态计算对比色 |
| 性能影响datalabels 插件) | 仅在饼图启用,监控渲染耗时 |
## Migration Plan
无需迁移,纯视觉修复,向后兼容。
## Open Questions
- 饼图标签在移动端小屏幕上的显示策略(待实现时验证)