import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:intl/intl.dart'; import '../providers/expense_provider.dart'; import 'add_transaction_screen.dart'; import 'stats_screen.dart'; import 'category_management_screen.dart'; class HomeScreen extends StatelessWidget { const HomeScreen({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('我的记账本'), actions: [ IconButton( icon: const Icon(Icons.bar_chart), tooltip: '统计', onPressed: () { Navigator.of(context).push( MaterialPageRoute(builder: (context) => const StatsScreen()), ); }, ), ], ), drawer: Drawer( child: ListView( padding: EdgeInsets.zero, children: [ const UserAccountsDrawerHeader( accountName: Text('用户'), accountEmail: Text('本地用户'), currentAccountPicture: CircleAvatar( backgroundColor: Colors.white, child: Icon(Icons.person, color: Colors.deepPurple), ), decoration: BoxDecoration( color: Colors.deepPurple, ), ), ListTile( leading: const Icon(Icons.category), title: const Text('分类管理'), onTap: () { Navigator.pop(context); // Close drawer Navigator.of(context).push( MaterialPageRoute(builder: (context) => const CategoryManagementScreen()), ); }, ), ListTile( leading: const Icon(Icons.settings), title: const Text('设置'), onTap: () { Navigator.pop(context); ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('设置功能开发中...'))); }, ), ], ), ), body: Consumer( builder: (context, provider, child) { if (provider.isLoading) { return const Center(child: CircularProgressIndicator()); } if (provider.transactions.isEmpty) { return const Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.receipt_long, size: 64, color: Colors.grey), SizedBox(height: 16), Text('暂无账单,快去记一笔吧!', style: TextStyle(color: Colors.grey)), ], ), ); } return Column( children: [ _buildSummaryCard(provider), Expanded( child: ListView.builder( itemCount: provider.transactions.length, itemBuilder: (context, index) { final transaction = provider.transactions[index]; final category = provider.getCategoryById(transaction.categoryId); return Dismissible( key: Key(transaction.id), background: Container( color: Colors.red, alignment: Alignment.centerRight, padding: const EdgeInsets.only(right: 20), child: const Icon(Icons.delete, color: Colors.white), ), direction: DismissDirection.endToStart, confirmDismiss: (direction) async { return await showDialog( context: context, builder: (ctx) => AlertDialog( title: const Text('确认删除'), content: const Text('确定要删除这条记录吗?'), actions: [ TextButton(onPressed: () => Navigator.of(ctx).pop(false), child: const Text('取消')), TextButton(onPressed: () => Navigator.of(ctx).pop(true), child: const Text('删除', style: TextStyle(color: Colors.red))), ], ), ); }, onDismissed: (direction) { provider.deleteTransaction(transaction.id); ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('已删除'))); }, child: Card( margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 4), child: ListTile( leading: CircleAvatar( backgroundColor: Color(category.color), child: Icon(_getIconData(category.icon), color: Colors.white), ), title: Text(category.name, style: const TextStyle(fontWeight: FontWeight.bold)), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(DateFormat('yyyy-MM-dd HH:mm').format(transaction.date)), if (transaction.note != null && transaction.note!.isNotEmpty) Text(transaction.note!, style: const TextStyle(fontSize: 12, color: Colors.grey)), ], ), trailing: Text( '${transaction.type == 'income' ? '+' : '-'}${transaction.amount.toStringAsFixed(2)}', style: TextStyle( color: transaction.type == 'income' ? Colors.green : Colors.red, fontWeight: FontWeight.bold, fontSize: 16, ), ), ), ), ); }, ), ), ], ); }, ), floatingActionButton: FloatingActionButton( onPressed: () { Navigator.of(context).push( MaterialPageRoute(builder: (context) => const AddTransactionScreen()), ); }, child: const Icon(Icons.add), ), ); } Widget _buildSummaryCard(ExpenseProvider provider) { return Card( margin: const EdgeInsets.all(16), elevation: 4, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(16), gradient: LinearGradient( colors: [Colors.deepPurple.shade400, Colors.deepPurple.shade700], begin: Alignment.topLeft, end: Alignment.bottomRight, ), ), padding: const EdgeInsets.all(20), child: Column( children: [ const Text('本月结余', style: TextStyle(color: Colors.white70, fontSize: 14)), const SizedBox(height: 8), Text( '¥${(provider.totalIncome - provider.totalExpense).toStringAsFixed(2)}', style: const TextStyle(color: Colors.white, fontSize: 32, fontWeight: FontWeight.bold), ), const SizedBox(height: 20), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ const Icon(Icons.arrow_downward, color: Colors.greenAccent, size: 16), const SizedBox(width: 4), const Text('收入', style: TextStyle(color: Colors.white70)), ], ), Text('¥${provider.totalIncome.toStringAsFixed(2)}', style: const TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold)), ], ), Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Row( children: [ const Icon(Icons.arrow_upward, color: Colors.redAccent, size: 16), const SizedBox(width: 4), const Text('支出', style: TextStyle(color: Colors.white70)), ], ), Text('¥${provider.totalExpense.toStringAsFixed(2)}', style: const TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold)), ], ), ], ), ], ), ), ); } IconData _getIconData(String iconName) { switch (iconName) { case 'restaurant': return Icons.restaurant; case 'directions_bus': return Icons.directions_bus; case 'shopping_cart': return Icons.shopping_cart; case 'movie': return Icons.movie; case 'local_hospital': return Icons.local_hospital; case 'attach_money': return Icons.attach_money; case 'trending_up': return Icons.trending_up; case 'breakfast_dining': return Icons.breakfast_dining; case 'lunch_dining': return Icons.lunch_dining; case 'dinner_dining': return Icons.dinner_dining; case 'subway': return Icons.subway; case 'local_taxi': return Icons.local_taxi; default: return Icons.category; } } }