import 'package:flutter/material.dart'; import '../../../models/bill.dart'; import '../../../utils/amount_util.dart'; import '../../../utils/bill_grouping.dart'; import '../../../utils/date_util.dart'; import '../../../widgets/cute_icon.dart'; /// 单日分组卡:组头(日期 + 分开的支出/收入小计)+ 账单条目 class BillGroupCard extends StatelessWidget { const BillGroupCard({super.key, required this.group, required this.onTapBill}); final BillDayGroup group; final ValueChanged onTapBill; static const _expenseColor = Color(0xFFFA3534); static const _incomeColor = Color(0xFF19BE6B); @override Widget build(BuildContext context) { return Container( margin: const EdgeInsets.only(bottom: 12), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), ), child: Column( children: [ Padding( padding: const EdgeInsets.fromLTRB(14, 12, 14, 8), child: Row( children: [ Text( formatGroupDate(group.date), style: const TextStyle( fontSize: 13, fontWeight: FontWeight.bold, color: Color(0xFF5D4037), ), ), const Spacer(), // 原版把当日收入与支出直接相加(无意义),这里分开展示 if (group.expenseTotal > 0) Text( '支 ¥${formatAmount(group.expenseTotal)}', style: const TextStyle(fontSize: 12, color: _expenseColor), ), if (group.expenseTotal > 0 && group.incomeTotal > 0) const SizedBox(width: 10), if (group.incomeTotal > 0) Text( '收 ¥${formatAmount(group.incomeTotal)}', style: const TextStyle(fontSize: 12, color: _incomeColor), ), ], ), ), const Divider(height: 1, color: Color(0xFFF5EEE4)), for (var i = 0; i < group.bills.length; i++) ...[ _BillTile(bill: group.bills[i], onTap: () => onTapBill(group.bills[i])), if (i != group.bills.length - 1) const Divider(height: 1, indent: 56, color: Color(0xFFF5EEE4)), ], ], ), ); } } class _BillTile extends StatelessWidget { const _BillTile({required this.bill, required this.onTap}); final Bill bill; final VoidCallback onTap; @override Widget build(BuildContext context) { // 金额正负与颜色按 type 判断(后端 amount 恒为正数,不能用金额正负判色) final color = bill.isExpense ? BillGroupCard._expenseColor : BillGroupCard._incomeColor; return InkWell( onTap: onTap, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12), child: Row( children: [ Container( width: 38, height: 38, decoration: const BoxDecoration( shape: BoxShape.circle, color: Color(0xFFFBEEDD), ), alignment: Alignment.center, child: CuteIcon(bill.categoryIcon, size: 21), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( bill.categoryName, style: const TextStyle( fontSize: 14.5, fontWeight: FontWeight.w600, color: Color(0xFF5D4037), ), ), if (bill.description.isNotEmpty) Padding( padding: const EdgeInsets.only(top: 2), child: Text( bill.description, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle(fontSize: 12, color: Color(0xFFBCAAA4)), ), ), ], ), ), const SizedBox(width: 8), Text( formatSignedAmount(bill.absAmount, isExpense: bill.isExpense), style: TextStyle(fontSize: 15, fontWeight: FontWeight.bold, color: color), ), ], ), ), ); } }