first commit

This commit is contained in:
2026-09-21 17:37:53 +08:00
commit 67d4dd5b7c
141 changed files with 8558 additions and 0 deletions
+56
View File
@@ -0,0 +1,56 @@
import 'package:dio/dio.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../core/network/api_exception.dart';
import '../core/network/dio_client.dart';
import '../models/statistics_response.dart';
final statisticsApiProvider =
Provider<StatisticsApi>((ref) => StatisticsApi(ref.watch(dioProvider)));
/// 统计接口。
///
/// 注意后端三个接口实际都委托给同一段按日聚合逻辑,区别只在参数:
/// daily 传日期区间,weekly 传周一,monthly 传年月。
class StatisticsApi {
final Dio _dio;
StatisticsApi(this._dio);
/// 按日期区间统计(yyyy-MM-dd)
Future<StatisticsResponse> getDaily({
required String startDate,
required String endDate,
}) async {
return _request('/statistics/daily', {
'startDate': startDate,
'endDate': endDate,
});
}
/// 按周统计,weekStart 为本周一(后端自行算到周内其余日期)
Future<StatisticsResponse> getWeekly({required String weekStart}) async {
return _request('/statistics/weekly', {'weekStart': weekStart});
}
/// 按月统计
Future<StatisticsResponse> getMonthly({required int year, required int month}) async {
return _request('/statistics/monthly', {'year': year, 'month': month});
}
Future<StatisticsResponse> _request(String path, Map<String, dynamic> params) async {
try {
final res = await _dio.get(path, queryParameters: params);
final data = res.data;
if (data is Map<String, dynamic>) return StatisticsResponse.fromJson(data);
if (data is Map && data['data'] is Map) {
return StatisticsResponse.fromJson(Map<String, dynamic>.from(data['data'] as Map));
}
// 空响应(无数据)按空统计处理,不视为错误
return StatisticsResponse.empty;
} on DioException catch (e) {
final err = e.error;
throw err is ApiException ? err : ApiException(-1, '统计加载失败');
}
}
}