import 'package:flutter/material.dart'; import '../models/record.dart'; import '../data/categories.dart'; import 'package:uuid/uuid.dart'; class RecordPage extends StatefulWidget { final Record? record; final Function(Record) onSave; // 添加保存回调 const RecordPage({ Key? key, this.record, required this.onSave, }) : super(key: key); @override State createState() => _RecordPageState(); } class _RecordPageState extends State with SingleTickerProviderStateMixin { late TabController _tabController; String? _selectedCategoryId; String _note = ''; double _amount = 0.0; DateTime _selectedDate = DateTime.now(); final _uuid = const Uuid(); @override void initState() { super.initState(); // 如果是编辑模式,初始化现有记录的数据 if (widget.record != null) { _selectedCategoryId = widget.record!.categoryId; _note = widget.record!.note ?? ''; _amount = widget.record!.amount; _selectedDate = widget.record!.createTime; } _tabController = TabController( length: 2, vsync: this, initialIndex: widget.record?.type == RecordType.income ? 1 : 0, ); _tabController.addListener(_onTabChanged); } /// 标签切换监听 void _onTabChanged() { setState(() { _selectedCategoryId = null; // 切换类型时重置选中的分类 }); } /// 获取当前记录类型 RecordType get _currentType => _tabController.index == 0 ? RecordType.expense : RecordType.income; /// 获取当前分类列表 List get _currentCategories => _currentType == RecordType.expense ? expenseCategories : incomeCategories; /// 保存记录 void _saveRecord() { if (_selectedCategoryId == null) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('请选择分类')), ); return; } if (_amount <= 0) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('请输入金额')), ); return; } final record = Record( id: widget.record?.id ?? _uuid.v4(), type: _currentType, categoryId: _selectedCategoryId!, note: _note.isEmpty ? null : _note, amount: _amount, createTime: _selectedDate, ); widget.onSave(record); Navigator.of(context).pop(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: TabBar( controller: _tabController, tabs: const [ Tab(text: '支出'), Tab(text: '收入'), ], ), ), body: Column( children: [ // 分类网格 Expanded( child: GridView.builder( padding: const EdgeInsets.all(16), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 4, mainAxisSpacing: 16, crossAxisSpacing: 16, ), itemCount: _currentCategories.length, itemBuilder: (context, index) { final category = _currentCategories[index]; final isSelected = category.id == _selectedCategoryId; return _buildCategoryItem(category, isSelected); }, ), ), // 底部编辑区域 _buildBottomEditor(), ], ), ); } /// 构建分类项 Widget _buildCategoryItem(Category category, bool isSelected) { return InkWell( onTap: () => setState(() => _selectedCategoryId = category.id), child: Container( decoration: BoxDecoration( color: isSelected ? Theme.of(context).primaryColor.withOpacity(0.1) : null, border: Border.all( color: isSelected ? Theme.of(context).primaryColor : Colors.grey, ), borderRadius: BorderRadius.circular(8), ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( category.icon, color: isSelected ? Theme.of(context).primaryColor : Colors.grey, ), const SizedBox(height: 4), Text( category.name, style: TextStyle( color: isSelected ? Theme.of(context).primaryColor : Colors.grey, ), ), ], ), ), ); } /// 构建底部编辑区域 Widget _buildBottomEditor() { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 8, offset: const Offset(0, -2), ), ], ), child: Column( mainAxisSize: MainAxisSize.min, children: [ // 备注和金额 Row( children: [ Expanded( child: TextField( decoration: const InputDecoration( hintText: '添加备注', border: InputBorder.none, ), onChanged: (value) => setState(() => _note = value), ), ), Text( '¥${_amount.toStringAsFixed(2)}', style: const TextStyle( fontSize: 24, fontWeight: FontWeight.bold, ), ), ], ), // 配置按钮 Row( children: [ TextButton.icon( onPressed: () { // TODO: 实现账户选择 }, icon: const Icon(Icons.account_balance_wallet), label: const Text('默认账户'), ), TextButton.icon( onPressed: () async { final date = await showDatePicker( context: context, initialDate: _selectedDate, firstDate: DateTime(2000), lastDate: DateTime.now(), ); if (date != null) { setState(() => _selectedDate = date); } }, icon: const Icon(Icons.calendar_today), label: Text(_selectedDate == DateTime.now() ? '今天' : '${_selectedDate.month}月${_selectedDate.day}日'), ), TextButton.icon( onPressed: () { // TODO: 实现图片选择 }, icon: const Icon(Icons.photo), label: const Text('图片'), ), ], ), // 数字键盘 _buildNumberKeyboard(), ], ), ); } /// 构建数字键盘 Widget _buildNumberKeyboard() { return GridView.count( shrinkWrap: true, crossAxisCount: 4, childAspectRatio: 2, children: [ _buildKeyboardButton('7'), _buildKeyboardButton('8'), _buildKeyboardButton('9'), _buildKeyboardButton('删除', isFunction: true), _buildKeyboardButton('4'), _buildKeyboardButton('5'), _buildKeyboardButton('6'), _buildKeyboardButton('+'), _buildKeyboardButton('1'), _buildKeyboardButton('2'), _buildKeyboardButton('3'), _buildKeyboardButton('-'), _buildKeyboardButton('again'), _buildKeyboardButton('0'), _buildKeyboardButton('.'), _buildKeyboardButton('保存', isFunction: true), ], ); } /// 构建键盘按钮 Widget _buildKeyboardButton(String text, {bool isFunction = false}) { return TextButton( onPressed: () => _onKeyboardButtonPressed(text), child: Text( text, style: TextStyle( fontSize: 20, color: isFunction ? Theme.of(context).primaryColor : Colors.black, ), ), ); } /// 处理键盘按钮点击 void _onKeyboardButtonPressed(String value) { switch (value) { case '删除': setState(() { final amountStr = _amount.toStringAsFixed(2); if (amountStr.length > 1) { _amount = double.parse(amountStr.substring(0, amountStr.length - 1)); } else { _amount = 0; } }); break; case '保存': _saveRecord(); break; case 'again': // TODO: 实现again功能 break; case '+': case '-': // TODO: 实现加减功能 break; case '.': // TODO: 实现小数点功能 break; default: if (_amount == 0) { setState(() => _amount = double.parse(value)); } else { setState(() => _amount = double.parse('$_amount$value')); } } } @override void dispose() { _tabController.dispose(); super.dispose(); } }