Files
EmailBill/openspec/changes/archive/2026-02-17-fix-chart-garbled-text/design.md

88 lines
3.3 KiB
Markdown
Raw Normal View History

2026-02-18 21:16:45 +08:00
## Context
EmailBill 项目已从 ECharts 迁移到 Chart.js 作为图表库。在迁移过程中图表文本显示出现了乱码问题特别是在显示中文标签、Tooltip 和中心文本时。这可能是由于:
1. Chart.js 默认字体配置不支持中文
2. Tooltip 回调函数返回的字符串编码问题
3. 主题切换时字体颜色对比度不足
当前图表组件位于 `Web/src/components/Charts/`,使用 `BaseChart.vue` 作为统一包装组件。
## Goals / Non-Goals
**Goals:**
- 修复所有图表(饼图、折线图、仪表盘)的中文乱码问题
- 确保图表文本在明/暗主题下都清晰可读
- 统一字体配置,支持跨平台中文显示
- 修复 Tooltip 和 Label 的文本格式化问题
**Non-Goals:**
- 不修改图表的数据结构或业务逻辑
- 不添加新的图表类型
- 不进行 UI 样式的大幅度调整(仅修复文本显示问题)
## Decisions
### Decision 1: 字体配置方案
**选择**: 在 `useChartTheme.ts` 中统一配置 Chart.js 字体选项
**理由**:
- Chart.js 支持全局字体配置,通过 `defaults.font.family` 可以一次性设置所有图表的字体
- 使用系统字体栈确保跨平台兼容性:`'PingFang SC', 'Microsoft YaHei', 'Helvetica Neue', Arial, sans-serif`
- 避免在每个组件中重复配置
**替代方案考虑**:
- 在每个图表组件中单独配置字体 → 重复代码,维护困难
- 使用 WebFont 加载自定义字体 → 增加外部依赖,加载时间不可控
### Decision 2: Tooltip 格式化修复方案
**选择**: 修复 `callbacks.label``callbacks.title` 回调函数,确保返回正确的字符串
**理由**:
- Chart.js 的 Tooltip 回调函数必须返回字符串,不能返回对象或其他类型
- 使用模板字符串确保正确的字符串拼接
- 添加空值检查防止 undefined 导致的乱码
**代码示例**:
```typescript
tooltip: {
callbacks: {
label: (context) => {
const value = context.parsed.y || context.parsed
return `¥${value.toFixed(2)}`
}
}
}
```
### Decision 3: 中心文本显示方案
**选择**: 继续使用 CSS 绝对定位的覆盖层显示中心文本
**理由**:
- Chart.js 本身不支持在 Doughnut 图表中心直接渲染文本
- CSS 覆盖层方式简单可靠,易于控制字体样式
- 确保覆盖层使用正确的字体族和颜色
**实现要点**:
- 覆盖层容器设置 `font-family` 继承自主题配置
- 使用 `var(--van-text-color)` 确保主题适配
- 添加 `white-space: nowrap` 防止文本换行导致错位
## Risks / Trade-offs
| Risk | Mitigation |
|------|------------|
| 某些旧版浏览器可能不支持系统字体栈 | 提供后备字体Arial, sans-serif确保基本可读性 |
| 暗色模式下文本颜色对比度不足 | 使用 Vant 主题变量确保颜色适配 |
| 字体文件过大影响加载性能 | 使用系统字体,不加载外部字体文件 |
| 修改全局配置可能影响其他组件 | 在 `useChartTheme` 中集中管理,便于回滚 |
## Migration Plan
1. **阶段 1**: 修改 `useChartTheme.ts` 添加全局字体配置
2. **阶段 2**: 检查并修复各图表组件的 Tooltip 回调函数
3. **阶段 3**: 验证所有图表页面的文本显示
4. **阶段 4**: 在明/暗主题下分别测试
**Rollback Strategy**: 所有修改都是配置层面的,可以通过回滚 Git 提交快速恢复。