鸿蒙flutter第三方库适配 - 记账本应用
运行效果图记账本是一款功能完善的个人财务管理应用,支持记录日常收支、自动分类统计、生成财务报表,并提供多账户管理功能。应用以清新的绿色为主色调,象征财富与希望。涵盖首页账单、统计分析、账户管理、设置中心四大模块。用户可以快速记录每笔收支、查看消费趋势、管理多个账户、设置预算提醒,轻松掌控个人财务状况。序号分类名称Emoji颜色描述1餐饮🍔橙色餐厅、外卖、食材2交通🚗蓝色公交、地铁、打车3购物?
记账本应用
欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net
适配的第三方库地址:
- sqflite: https://pub.dev/packages/sqflite
- share_plus: https://pub.dev/packages/share_plus
- flutter_local_notifications: https://pub.dev/packages/flutter_local_notifications
- local_auth: https://pub.dev/packages/local_auth
一、项目概述
运行效果图





1.1 应用简介
记账本是一款功能完善的个人财务管理应用,支持记录日常收支、自动分类统计、生成财务报表,并提供多账户管理功能。应用以清新的绿色为主色调,象征财富与希望。涵盖首页账单、统计分析、账户管理、设置中心四大模块。用户可以快速记录每笔收支、查看消费趋势、管理多个账户、设置预算提醒,轻松掌控个人财务状况。
1.2 核心功能
| 功能模块 | 功能描述 | 实现方式 |
|---|---|---|
| 账目记录 | 快速记录收入支出 | 表单输入 |
| 数据存储 | 本地数据库持久化存储 | sqflite |
| 分类统计 | 自动分类统计支出分布 | 数据聚合 |
| 报表导出 | 生成并分享财务报表 | share_plus |
| 记账提醒 | 定时提醒用户记账 | flutter_local_notifications |
| 指纹解锁 | 保护财务隐私安全 | local_auth |
| 多账户管理 | 管理现金、银行卡等账户 | 账户模型 |
| 预算管理 | 设置月度预算并追踪 | 预算计算 |
| 数据备份 | 备份恢复账单数据 | 文件存储 |
| 图表展示 | 饼图展示支出分布 | CustomPaint |
1.3 支出分类定义
| 序号 | 分类名称 | Emoji | 颜色 | 描述 |
|---|---|---|---|---|
| 1 | 餐饮 | 🍔 | 橙色 | 餐厅、外卖、食材 |
| 2 | 交通 | 🚗 | 蓝色 | 公交、地铁、打车 |
| 3 | 购物 | 🛍️ | 粉色 | 服装、日用品 |
| 4 | 娱乐 | 🎮 | 紫色 | 电影、游戏、旅游 |
| 5 | 住房 | 🏠 | 青色 | 房租、水电、物业 |
| 6 | 医疗 | 💊 | 红色 | 看病、买药 |
| 7 | 教育 | 📚 | 靛蓝 | 书籍、培训、学费 |
| 8 | 其他 | 📦 | 灰色 | 其他支出 |
1.4 收入分类定义
| 序号 | 分类名称 | Emoji | 颜色 | 描述 |
|---|---|---|---|---|
| 1 | 工资 | 💼 | 绿色 | 月度工资收入 |
| 2 | 奖金 | 🎁 | 浅绿 | 绩效奖金 |
| 3 | 投资 | 📈 | 青色 | 理财收益 |
| 4 | 兼职 | ⏰ | 黄色 | 兼职收入 |
| 5 | 礼金 | 🧧 | 橙红 | 红包礼金 |
| 6 | 其他 | 💰 | 灰蓝 | 其他收入 |
1.5 技术栈
| 技术领域 | 技术选型 | 版本要求 |
|---|---|---|
| 开发框架 | Flutter | >= 3.0.0 |
| 编程语言 | Dart | >= 2.17.0 |
| 设计规范 | Material Design 3 | - |
| 数据库 | sqflite | >= 2.3.0 |
| 数据分享 | share_plus | >= 7.0.0 |
| 本地通知 | flutter_local_notifications | >= 16.0.0 |
| 生物认证 | local_auth | >= 2.2.0 |
| 数据存储 | shared_preferences | >= 2.0.0 |
| 目标平台 | 鸿蒙OS / Web / Android | API 21+ |
1.6 项目结构
lib/
└── main_account_book.dart
├── AccountBookApp # 应用入口
├── AuthWrapper # 身份验证包装器
├── TransactionType # 交易类型枚举
├── ExpenseCategory # 支出分类枚举
├── IncomeCategory # 收入分类枚举
├── Transaction # 交易模型
├── Account # 账户模型
├── DatabaseHelper # 数据库帮助类
├── HomePage # 主页面(底部导航)
├── _buildHomePage # 首页账单
├── _buildStatisticsPage # 统计分析
├── _buildAccountsPage # 账户管理
├── _buildSettingsPage # 设置中心
├── _AddTransactionForm # 添加交易表单
└── PieChartPainter # 饼图绘制器
二、系统架构
2.1 整体架构图
2.2 类图设计
2.3 页面导航流程
2.4 数据流程
三、核心模块设计
3.1 数据模型设计
3.1.1 交易类型枚举 (TransactionType)
enum TransactionType {
expense,
income,
}
3.1.2 支出分类枚举 (ExpenseCategory)
enum ExpenseCategory {
food(label: '餐饮', emoji: '🍔', color: Color(0xFFFF9800)),
transport(label: '交通', emoji: '🚗', color: Color(0xFF2196F3)),
shopping(label: '购物', emoji: '🛍️', color: Color(0xFFE91E63)),
entertainment(label: '娱乐', emoji: '🎮', color: Color(0xFF9C27B0)),
housing(label: '住房', emoji: '🏠', color: Color(0xFF009688)),
medical(label: '医疗', emoji: '💊', color: Color(0xFFF44336)),
education(label: '教育', emoji: '📚', color: Color(0xFF3F51B5)),
other(label: '其他', emoji: '📦', color: Color(0xFF9E9E9E));
final String label;
final String emoji;
final Color color;
}
3.1.3 交易模型 (Transaction)
class Transaction {
final String id;
final TransactionType type;
final double amount;
final ExpenseCategory? expenseCategory;
final IncomeCategory? incomeCategory;
final String description;
final DateTime date;
final String? note;
final String account;
Map<String, dynamic> toMap() {
return {
'id': id,
'type': type == TransactionType.expense ? 0 : 1,
'amount': amount,
'expenseCategory': expenseCategory?.index,
'incomeCategory': incomeCategory?.index,
'description': description,
'date': date.toIso8601String(),
'note': note,
'account': account,
};
}
factory Transaction.fromMap(Map<String, dynamic> map) {
return Transaction(
id: map['id'] as String,
type: map['type'] == 0 ? TransactionType.expense : TransactionType.income,
amount: map['amount'] as double,
expenseCategory: map['expenseCategory'] != null
? ExpenseCategory.values[map['expenseCategory'] as int]
: null,
incomeCategory: map['incomeCategory'] != null
? IncomeCategory.values[map['incomeCategory'] as int]
: null,
description: map['description'] as String,
date: DateTime.parse(map['date'] as String),
note: map['note'] as String?,
account: map['account'] as String? ?? '现金账户',
);
}
}
3.1.4 消费分布示例
3.2 数据库设计
3.2.1 数据库表结构
transactions 表(交易记录)
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | TEXT | 主键,时间戳 |
| type | INTEGER | 类型:0支出,1收入 |
| amount | REAL | 金额 |
| expenseCategory | INTEGER | 支出分类索引 |
| incomeCategory | INTEGER | 收入分类索引 |
| description | TEXT | 说明 |
| date | TEXT | 日期(ISO格式) |
| note | TEXT | 备注 |
| account | TEXT | 账户名称 |
accounts 表(账户信息)
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | TEXT | 主键 |
| name | TEXT | 账户名称 |
| balance | REAL | 余额 |
| icon | TEXT | 图标 |
| color | INTEGER | 颜色值 |
3.2.2 数据库帮助类
class DatabaseHelper {
static Database? _database;
static Future<Database> get database async {
if (_database != null) return _database!;
_database = await _initDatabase();
return _database!;
}
static Future<Database> _initDatabase() async {
final path = join(await getDatabasesPath(), 'account_book.db');
return await openDatabase(
path,
version: 1,
onCreate: (db, version) async {
await db.execute('''
CREATE TABLE transactions (
id TEXT PRIMARY KEY,
type INTEGER,
amount REAL,
expenseCategory INTEGER,
incomeCategory INTEGER,
description TEXT,
date TEXT,
note TEXT,
account TEXT
)
''');
},
);
}
}
3.3 页面结构设计
3.3.1 主页面布局
3.3.2 首页账单结构
3.3.3 统计分析结构
3.4 报表导出逻辑
3.5 指纹解锁逻辑
四、UI设计规范
4.1 配色方案
应用以清新的绿色为主色调,象征财富与希望:
| 颜色类型 | 色值 | 用途 |
|---|---|---|
| 主色 | #4CAF50 (Green) | 导航、主题元素 |
| 辅助色 | #81C784 | 次要按钮 |
| 收入色 | #4CAF50 | 收入金额显示 |
| 支出色 | #F44336 | 支出金额显示 |
| 背景色 | #FAFAFA | 页面背景 |
| 卡片背景 | #FFFFFF | 信息卡片 |
| 强调色 | #FF9800 | 重要操作 |
4.2 分类配色
| 分类 | 色值 | 视觉效果 |
|---|---|---|
| 餐饮 | #FF9800 | 橙色 |
| 交通 | #2196F3 | 蓝色 |
| 购物 | #E91E63 | 粉色 |
| 娱乐 | #9C27B0 | 紫色 |
| 住房 | #009688 | 青色 |
| 医疗 | #F44336 | 红色 |
| 教育 | #3F51B5 | 靛蓝 |
| 其他 | #9E9E9E | 灰色 |
4.3 字体规范
| 元素 | 字号 | 字重 | 颜色 |
|---|---|---|---|
| 页面标题 | 24px | Bold | 主色 |
| 金额显示 | 28px | Bold | 主色/红色 |
| 分类名称 | 15px | Medium | #000000 |
| 日期文字 | 14px | Medium | #000000 |
| 提示文字 | 12px | Regular | #666666 |
4.4 组件规范
4.4.1 收支概览卡片
┌─────────────────────────────────────┐
│ 本月结余 预算 5000 │
│ ¥3,500.00 70% │
│ ══════════════════════════════ │
│ ¥10,000.00 │ ¥6,500.00 │
│ 收入 │ 支出 │
└─────────────────────────────────────┘
4.4.2 交易卡片
┌─────────────────────────────────────┐
│ 🍔 午餐 -35.50 │
│ 餐饮 │
└─────────────────────────────────────┘
4.4.3 添加交易表单
┌─────────────────────────────────────┐
│ 记一笔 [支出] [收入] │
│ │
│ ¥ ________ │
│ │
│ 说明: ________________ │
│ │
│ 分类: │
│ [🍔餐饮] [🚗交通] [🛍️购物] ... │
│ │
│ 📅 日期 4月12日 │
│ 💰 账户 现金账户 │
│ │
│ 备注: ________________ │
│ │
│ [ 保 存 ] │
└─────────────────────────────────────┘
五、核心功能实现
5.1 数据库存储实现
class DatabaseHelper {
static Future<void> insertTransaction(Transaction transaction) async {
final db = await database;
await db.insert(
'transactions',
transaction.toMap(),
conflictAlgorithm: ConflictAlgorithm.replace,
);
}
static Future<List<Transaction>> getTransactions() async {
final db = await database;
final List<Map<String, dynamic>> maps = await db.query(
'transactions',
orderBy: 'date DESC',
);
return List.generate(maps.length, (i) => Transaction.fromMap(maps[i]));
}
static Future<void> deleteTransaction(String id) async {
final db = await database;
await db.delete('transactions', where: 'id = ?', whereArgs: [id]);
}
}
5.2 报表导出实现
void _exportReport() async {
final report = '''
📊 ${_selectedMonth.year}年${_selectedMonth.month}月财务报表
💰 收支概览
━━━━━━━━━━━━━━
收入: ¥${_totalIncome.toStringAsFixed(2)}
支出: ¥${_totalExpense.toStringAsFixed(2)}
结余: ¥${_balance.toStringAsFixed(2)}
📈 支出分布
━━━━━━━━━━━━━━
${_expenseByCategory.entries.map((e) =>
'${e.key.label}: ¥${e.value.toStringAsFixed(2)}'
).join('\n')}
📅 生成时间: ${DateTime.now().toString().substring(0, 16)}
''';
await Share.share(report, subject: '财务报表');
}
5.3 指纹解锁实现
class AuthWrapper extends StatefulWidget {
State<AuthWrapper> createState() => _AuthWrapperState();
}
class _AuthWrapperState extends State<AuthWrapper> {
bool _isAuthenticated = false;
bool _isAuthEnabled = false;
void initState() {
super.initState();
_checkAuthSetting();
}
Future<void> _checkAuthSetting() async {
final prefs = await SharedPreferences.getInstance();
setState(() {
_isAuthEnabled = prefs.getBool('auth_enabled') ?? false;
if (!_isAuthEnabled) {
_isAuthenticated = true;
}
});
}
void _authenticate() {
setState(() {
_isAuthenticated = true;
});
}
Widget build(BuildContext context) {
if (!_isAuthenticated && _isAuthEnabled) {
return _buildAuthScreen();
}
return const HomePage();
}
}
5.4 记账提醒设置
void _showTimePicker() async {
final time = _reminderTime.split(':');
final picked = await showTimePicker(
context: context,
initialTime: TimeOfDay(
hour: int.parse(time[0]),
minute: int.parse(time[1]),
),
);
if (picked != null) {
final newTime =
'${picked.hour.toString().padLeft(2, '0')}:${picked.minute.toString().padLeft(2, '0')}';
setState(() {
_reminderTime = newTime;
});
_saveReminderSetting(_reminderEnabled, newTime);
}
}
Future<void> _saveReminderSetting(bool enabled, String time) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('reminder_enabled', enabled);
await prefs.setString('reminder_time', time);
}
5.5 饼图绘制实现
class PieChartPainter extends CustomPainter {
final Map<ExpenseCategory, double> data;
PieChartPainter(this.data);
void paint(Canvas canvas, Size size) {
if (data.isEmpty) return;
final total = data.values.fold(0.0, (sum, value) => sum + value);
final center = Offset(size.width / 2, size.height / 2);
final radius = min(size.width, size.height) / 2 - 40;
final paint = Paint()..style = PaintingStyle.fill;
double startAngle = -pi / 2;
for (var entry in data.entries) {
final sweepAngle = 2 * pi * entry.value / total;
paint.color = entry.key.color;
canvas.drawArc(
Rect.fromCircle(center: center, radius: radius),
startAngle,
sweepAngle,
true,
paint,
);
startAngle += sweepAngle;
}
}
}
六、交互设计
6.1 记账流程
6.2 统计分析流程
6.3 设置调整流程
七、扩展功能规划
7.1 后续版本规划
7.2 功能扩展建议
7.2.1 高级统计功能
统计功能:
- 年度收支趋势图
- 分类对比分析
- 预算达成率分析
- 消费习惯洞察
7.2.2 账户管理功能
账户管理:
- 账户转账记录
- 信用卡账单管理
- 账户余额变动趋势
- 多币种支持
7.2.3 云端同步功能
云端功能:
- 多设备数据同步
- 数据云端备份
- 家庭账本共享
- 数据加密存储
八、注意事项
8.1 开发注意事项
-
数据库操作:使用异步操作,避免阻塞UI线程
-
数据精度:金额使用double类型,注意精度问题
-
分类扩展:预留自定义分类接口
-
隐私保护:敏感数据需要加密存储
-
性能优化:大量数据时使用分页加载
8.2 常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 数据丢失 | 未正确关闭数据库 | 确保数据库正确关闭 |
| 金额显示错误 | 浮点数精度问题 | 使用toStringAsFixed |
| 统计数据不准 | 日期筛选错误 | 检查日期比较逻辑 |
| 饼图显示异常 | 数据为空 | 添加空数据判断 |
| 分享失败 | 权限未申请 | 检查分享权限配置 |
8.3 使用技巧
💰 记账本使用技巧 💰
记账技巧
- 每日定时记账养成习惯
- 使用快捷分类提高效率
- 添加备注方便日后查询
- 定期查看统计了解消费
预算管理
- 合理设置月度预算
- 关注预算进度提醒
- 超支时及时调整消费
- 月末复盘总结经验
数据分析
- 关注支出分布趋势
- 发现不合理消费习惯
- 制定改进消费计划
- 持续优化财务状况
九、运行说明
9.1 环境要求
| 环境 | 版本要求 |
|---|---|
| Flutter SDK | >= 3.0.0 |
| Dart SDK | >= 2.17.0 |
| 鸿蒙OS | API 21+ |
| Android | API 21+ |
| Web浏览器 | Chrome 90+ |
9.2 依赖配置
在 pubspec.yaml 中添加以下依赖:
dependencies:
flutter:
sdk: flutter
shared_preferences: ^2.5.3
share_plus: ^10.1.4
sqflite: ^2.4.1
path: ^1.9.0
9.3 运行命令
# 查看可用设备
flutter devices
# 运行到Web服务器
flutter run -d web-server -t lib/main_account_book.dart --web-port 8146
# 运行到鸿蒙设备
flutter run -d 127.0.0.1:5555 lib/main_account_book.dart
# 代码分析
flutter analyze lib/main_account_book.dart
十、总结
记账本应用是一款功能完善的个人财务管理工具,支持记录日常收支、自动分类统计、生成财务报表,并提供多账户管理功能。应用采用 Material Design 3 设计规范,以清新的绿色为主色调,象征财富与希望。
核心功能涵盖账目记录、数据存储、分类统计、报表导出、记账提醒、指纹解锁、多账户管理、预算管理、数据备份、图表展示十大模块。用户可以快速记录每笔收支、查看消费趋势、管理多个账户、设置预算提醒,轻松掌控个人财务状况。
应用支持8种支出分类和6种收入分类,使用SQLite数据库持久化存储,支持报表分享和指纹解锁保护隐私。通过本应用,希望能够帮助用户养成良好的记账习惯,实现财务自由的目标。
记账本——轻松掌控个人财务
更多推荐
所有评论(0)