322 lines
9.0 KiB
Dart
322 lines
9.0 KiB
Dart
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<RecordPage> createState() => _RecordPageState();
|
|
}
|
|
|
|
class _RecordPageState extends State<RecordPage> 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<Category> 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();
|
|
}
|
|
} |