You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中按月份聚合Map列表收支总额并展示到fl_charts的问题

实现思路与代码示例

核心逻辑

先按「月份+交易类型」对数据分组,再在每个分组内累加金额得到月度总额,最后将分组数据转换为折线图所需的FlSpot集合。

步骤1:处理日期解析(关键注意点)

你的日期格式是dd-MM-yyyy,直接用DateTime.parse可能会解析失败(默认ISO格式是yyyy-MM-dd),建议手动拆分或用intl包的DateFormat处理:

// 手动拆分日期获取月份
int getMonthFromDate(String dateStr) {
  final parts = dateStr.split('-');
  return int.parse(parts[1]); // 取MM部分
}

// 或者用intl包(需在pubspec.yaml添加依赖)
// import 'package:intl/intl.dart';
// int getMonthFromDate(String dateStr) {
//   return DateFormat('dd-MM-yyyy').parse(dateStr).month;
// }

步骤2:分组聚合月度总额

可以用forEach或fold遍历数据,以"月份-类型"为键存入Map,累加对应金额:

// 初始化空Map存储月度收支总额
final Map<String, double> monthlyTotals = {};

currentScenario?.transactions.forEach((trans) {
  final String type = trans['type'];
  final double amount = (trans['amount'] as num).toDouble();
  final int month = getMonthFromDate(trans['paymentDate']);
  
  final String key = '$month-$type';
  // 累加金额:存在则加,不存在则初始化
  monthlyTotals[key] = (monthlyTotals[key] ?? 0.0) + amount;
});

// 用fold实现的版本(逻辑和forEach一致)
// final monthlyTotals = currentScenario?.transactions.fold<Map<String, double>>({}, (acc, trans) {
//   final String type = trans['type'];
//   final double amount = (trans['amount'] as num).toDouble();
//   final int month = getMonthFromDate(trans['paymentDate']);
//   final String key = '$month-$type';
//   acc[key] = (acc[key] ?? 0.0) + amount;
//   return acc;
// });

步骤3:转换为折线图所需的FlSpot集合

先提取所有涉及的月份并排序,再分别生成收入、支出的FlSpot(缺失数据的月份补0,保证折线连续):

// 提取所有月份并排序,确保x轴顺序正确
final List<int> allMonths = monthlyTotals.keys
    .map((key) => int.parse(key.split('-')[0]))
    .toSet() // 去重
    .toList()
    ..sort();

// 生成收入折线的spots
final List<FlSpot> incomeSpots = allMonths.map((month) {
  final double total = monthlyTotals['$month-income'] ?? 0.0;
  return FlSpot(month.toDouble(), total);
}).toList();

// 生成支出折线的spots
final List<FlSpot> expenseSpots = allMonths.map((month) {
  final double total = monthlyTotals['$month-expense'] ?? 0.0;
  return FlSpot(month.toDouble(), total);
}).toList();

步骤4:更新折线图配置

将生成的incomeSpots和expenseSpots替换原代码中的spots即可:

LineChartBarData(
  spots: incomeSpots,
  // 其他配置:颜色、宽度、圆点等
),
LineChartBarData(
  spots: expenseSpots,
  // 其他配置:颜色、宽度、圆点等
)

为什么之前的fold无效?

你之前的fold没有按月份分组,直接对所有同类型的交易金额求和,自然得到的是全量总额而非月度总额。必须先按月份+类型分组,再在组内累加才能得到目标数据。

内容的提问来源于stack exchange,提问作者user3352042

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 08:45:21