11 KiB
title, author, date, status, category
| title | author | date | status | category |
|---|---|---|---|---|
| TransactionStatistics 接口重构文档 | AI Assistant | 2026-02-10 | final | API重构 |
TransactionStatistics 接口重构文档
概述
本次重构针对 TransactionStatisticsController 中的接口进行了统一优化,采用方案一(激进重构),将原有 9 个接口精简为 4 个核心接口,同时保留旧接口用于向后兼容(标记为 [Obsolete])。
重构时间: 2026-02-10
影响范围: Backend (Service/Application/Controller) + Frontend (API/Views)
一、重构目标
问题分析
-
接口冗余: 存在多组功能重复的接口对
GetMonthlyStatisticsvsGetRangeStatisticsGetDailyStatisticsvsGetWeeklyStatisticsGetCategoryStatisticsvsGetCategoryStatisticsByDateRange
-
参数不统一: 部分接口使用
(year, month),部分使用(startDate, endDate) -
未使用接口:
GetReasonGroups在前端完全未被调用
重构原则
- ✅ 统一使用日期范围查询 (
startDate,endDate) - ✅ 保留旧接口用于向后兼容,标记为
[Obsolete] - ✅ 删除未使用的接口
- ✅ 前端优先迁移到新接口
二、接口变更对照表
新接口(推荐使用)
| 新接口名称 | 路径 | 参数 | 说明 | 替代的旧接口 |
|---|---|---|---|---|
GetDailyStatisticsByRange |
/TransactionStatistics/GetDailyStatisticsByRange |
startDate, endDate, savingClassify? | 按日期范围获取每日统计 | GetDailyStatisticsGetWeeklyStatistics |
GetSummaryByRange |
/TransactionStatistics/GetSummaryByRange |
startDate, endDate | 按日期范围获取汇总统计 | GetMonthlyStatisticsGetRangeStatistics |
GetCategoryStatisticsByRange |
/TransactionStatistics/GetCategoryStatisticsByRange |
startDate, endDate, type | 按日期范围获取分类统计 | GetCategoryStatisticsGetCategoryStatisticsByDateRange |
GetTrendStatistics |
/TransactionStatistics/GetTrendStatistics |
startYear, startMonth, monthCount | 多月趋势统计 | (保持不变) |
标记为 Obsolete 的接口(兼容性保留)
| 接口名称 | 状态 | 建议迁移方案 |
|---|---|---|
GetBalanceStatistics |
[Obsolete] |
使用 GetDailyStatisticsByRange 并在前端计算累积余额 |
GetDailyStatistics |
[Obsolete] |
使用 GetDailyStatisticsByRange |
GetWeeklyStatistics |
[Obsolete] |
使用 GetDailyStatisticsByRange |
GetMonthlyStatistics |
[Obsolete] |
使用 GetSummaryByRange |
GetRangeStatistics |
[Obsolete] |
使用 GetSummaryByRange |
GetCategoryStatistics |
[Obsolete] |
使用 GetCategoryStatisticsByRange |
GetCategoryStatisticsByDateRange |
[Obsolete] |
使用 GetCategoryStatisticsByRange (DateTime 参数版本) |
删除的接口
| 接口名称 | 删除原因 |
|---|---|
GetReasonGroups |
前端完全未使用 |
三、技术实现细节
1. Service 层变更
文件: Service/Transaction/TransactionStatisticsService.cs
新增方法:
/// <summary>
/// 按日期范围获取汇总统计数据(新统一接口)
/// </summary>
Task<MonthlyStatistics> GetSummaryByRangeAsync(DateTime startDate, DateTime endDate);
实现: 直接查询指定日期范围的交易记录并汇总统计。
2. Application 层变更
文件: Application/TransactionStatisticsApplication.cs
新增方法:
// 新统一接口
Task<List<DailyStatisticsDto>> GetDailyStatisticsByRangeAsync(DateTime startDate, DateTime endDate, string? savingClassify = null);
Task<MonthlyStatistics> GetSummaryByRangeAsync(DateTime startDate, DateTime endDate);
Task<List<CategoryStatistics>> GetCategoryStatisticsByRangeAsync(DateTime startDate, DateTime endDate, TransactionType type);
标记为过时的方法: 所有旧方法均添加 [Obsolete] 特性,指引开发者迁移到新接口。
3. Controller 层变更
文件: WebApi/Controllers/TransactionStatisticsController.cs
新增接口:
[HttpGet]
public async Task<BaseResponse<List<DailyStatisticsDto>>> GetDailyStatisticsByRangeAsync(
[FromQuery] DateTime startDate,
[FromQuery] DateTime endDate,
[FromQuery] string? savingClassify = null)
[HttpGet]
public async Task<BaseResponse<Service.Transaction.MonthlyStatistics>> GetSummaryByRangeAsync(
[FromQuery] DateTime startDate,
[FromQuery] DateTime endDate)
[HttpGet]
public async Task<BaseResponse<List<Service.Transaction.CategoryStatistics>>> GetCategoryStatisticsByRangeAsync(
[FromQuery] DateTime startDate,
[FromQuery] DateTime endDate,
[FromQuery] TransactionType type)
标记为过时的接口: 所有旧接口均添加 [Obsolete] 特性。
删除的接口: GetReasonGroupsAsync
4. 前端变更
API 定义文件
文件: Web/src/api/statistics.js
新增方法:
// 新统一接口
export const getDailyStatisticsByRange = (params) => { /* ... */ }
export const getSummaryByRange = (params) => { /* ... */ }
export const getCategoryStatisticsByRange = (params) => { /* ... */ }
标记为过时的方法: 添加 @deprecated JSDoc 注释。
视图文件
文件: Web/src/views/statisticsV2/Index.vue
迁移内容:
- 周度数据加载:
getRangeStatistics→getSummaryByRange - 周度每日统计:
getWeeklyStatistics→getDailyStatisticsByRange - 周度分类统计:
getCategoryStatisticsByDateRange→getCategoryStatisticsByRange
关键修改:
- 修改
endDate计算逻辑:+6天→+7天(因为新接口的 endDate 是不包含的) - 移除
weekEnd.setHours(23, 59, 59, 999)逻辑(不再需要)
四、迁移指南
后端开发者
场景 1: 获取月度统计
旧代码:
await statisticsService.GetMonthlyStatisticsAsync(2025, 2);
新代码:
var startDate = new DateTime(2025, 2, 1);
var endDate = new DateTime(2025, 3, 1); // 不包含3月1日
await statisticsService.GetSummaryByRangeAsync(startDate, endDate);
场景 2: 获取每日统计
旧代码:
await statisticsService.GetDailyStatisticsAsync(2025, 2, savingClassify);
新代码:
var startDate = new DateTime(2025, 2, 1);
var endDate = new DateTime(2025, 3, 1);
await statisticsService.GetDailyStatisticsByRangeAsync(startDate, endDate, savingClassify);
前端开发者
场景 1: 获取月度汇总
旧代码:
await getMonthlyStatistics({ year: 2025, month: 2 })
新代码:
await getSummaryByRange({
startDate: '2025-02-01',
endDate: '2025-03-01'
})
场景 2: 获取周度每日统计
旧代码:
await getWeeklyStatistics({
startDate: '2025-02-01',
endDate: '2025-02-07'
})
新代码:
await getDailyStatisticsByRange({
startDate: '2025-02-01',
endDate: '2025-02-08' // 注意:endDate 不包含
})
场景 3: 获取分类统计
旧代码:
await getCategoryStatistics({ year: 2025, month: 2, type: 0 })
// 或
await getCategoryStatisticsByDateRange({
startDate: '2025-02-01',
endDate: '2025-02-28',
type: 0
})
新代码:
await getCategoryStatisticsByRange({
startDate: '2025-02-01',
endDate: '2025-03-01', // 注意:endDate 不包含
type: 0
})
五、重要注意事项
⚠️ endDate 语义变更
新接口的 endDate 参数是不包含的(exclusive)。
- ❌ 错误:
startDate: '2025-02-01', endDate: '2025-02-28'→ 缺少2月28日数据 - ✅ 正确:
startDate: '2025-02-01', endDate: '2025-03-01'→ 包含整个2月
🔒 向后兼容策略
- 所有旧接口保持可用,仅标记为
[Obsolete] - 前端 V1 版本继续使用旧接口
- 前端 V2 版本已迁移到新接口
- 建议在后续版本中逐步废弃旧接口
📝 测试覆盖
- ✅ 后端单元测试:
TransactionStatisticsServiceTest全部通过(9个测试) - ⚠️ 前端测试: 建议手动测试以下场景
- 月度视图切换
- 年度视图切换
- 周度视图切换
- 分类统计数据展示
六、优化效果
接口精简
| 指标 | 重构前 | 重构后 | 优化 |
|---|---|---|---|
| 接口总数 | 9 | 4 | ⬇️ 55% |
| 推荐使用接口 | - | 4 | - |
| 兼容性接口 | - | 7 | - |
| 未使用接口 | 1 | 0 | ⬇️ 100% |
参数统一度
- 重构前: 3种参数模式(year+month, startDate+endDate, startYear+startMonth+monthCount)
- 重构后: 2种参数模式(startDate+endDate, startYear+startMonth+monthCount)
API 可维护性
- ✅ 接口语义更清晰
- ✅ 参数命名更统一
- ✅ 减少代码重复
- ✅ 降低学习成本
七、后续计划
-
V1 版本迁移 (优先级: 中)
- 将
statisticsV1/Index.vue迁移到新接口 - 移除对
getBalanceStatistics的依赖
- 将
-
旧接口废弃 (优先级: 低)
- 确认所有前端页面迁移完成
- 在下个大版本中彻底删除旧接口
-
性能优化 (优先级: 高)
- 考虑提供聚合接口,一次返回多种类型的分类统计
- 前端添加数据缓存机制
八、相关文件清单
后端文件
Service/Transaction/TransactionStatisticsService.csApplication/TransactionStatisticsApplication.csWebApi/Controllers/TransactionStatisticsController.cs
前端文件
Web/src/api/statistics.jsWeb/src/views/statisticsV2/Index.vue
测试文件
WebApi.Test/Transaction/TransactionStatisticsServiceTest.csWebApi.Test/Application/TransactionStatisticsApplicationTest.cs
九、常见问题 (FAQ)
Q1: 旧接口什么时候会被删除?
A: 目前旧接口仅标记为 [Obsolete],不会被立即删除。计划在确认所有前端页面迁移完成后,在下个大版本中删除。
Q2: 为什么 GetTrendStatistics 没有改为日期范围?
A: GetTrendStatistics 的业务场景是获取"连续N个月"的趋势数据,使用 (startYear, startMonth, monthCount) 更符合业务语义。如果改为日期范围,反而需要前端自行计算月份跨度。
Q3: 新接口的 endDate 为什么是不包含的?
A: 采用"左闭右开区间 [startDate, endDate)"是业界常见做法,优点包括:
- 方便表示连续时间段(如2月:
[2025-02-01, 2025-03-01)) - 避免时区和时间精度问题(不需要
23:59:59.999) - 与大多数编程语言的区间语义一致(如 Python 的
range())
Q4: 如何确认迁移是否成功?
A: 检查以下几点:
- 前端代码中没有引用旧的 API 方法
- 统计数据展示正常,与旧版本数据一致
- 控制台无 API 调用错误
文档版本: v1.0
最后更新: 2026-02-10