记账本应用


欢迎加入开源鸿蒙跨平台社区:
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

一、项目概述

运行效果图

image-20260412105326390

image-20260412105638476

image-20260412105643039

image-20260412105647809

image-20260412105658096

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 整体架构图

Data Layer

Business Layer

Presentation Layer

主页面
HomePage

首页账单

统计分析

账户管理

设置中心

账单列表

快速操作

添加交易

收支概览

支出分布

支出排行

账户列表

总资产

安全设置

提醒设置

数据管理

数据库管理器
DatabaseHelper

交易管理
TransactionManager

账户管理
AccountManager

设置管理
SettingsManager

SQLite数据库

SharedPreferences

Transaction模型

Account模型

2.2 类图设计

has

has

has

manages

AccountBookApp

+Widget build()

AuthWrapper

-bool _isAuthenticated

-bool _isAuthEnabled

+Widget build()

+void _authenticate()

«enumeration»

TransactionType

expense

income

«enumeration»

ExpenseCategory

+String label

+String emoji

+Color color

+food()

+transport()

+shopping()

+entertainment()

+housing()

+medical()

+education()

+other()

«enumeration»

IncomeCategory

+String label

+String emoji

+Color color

+salary()

+bonus()

+investment()

+partTime()

+gift()

+other()

Transaction

+String id

+TransactionType type

+double amount

+ExpenseCategory expenseCategory

+IncomeCategory incomeCategory

+String description

+DateTime date

+String note

+String account

+toMap()

+fromMap()

Account

+String id

+String name

+double balance

+String icon

+Color color

DatabaseHelper

-Database _database

+get database

+insertTransaction()

+getTransactions()

+deleteTransaction()

+clearAllTransactions()

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 消费分布示例
35% 20% 15% 12% 10% 8% 月度支出分布示例 餐饮 交通 购物 娱乐 住房 其他

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 主页面布局

HomePage

IndexedStack

首页账单

统计分析

账户管理

设置中心

NavigationBar

首页 Tab

统计 Tab

账户 Tab

设置 Tab

3.3.2 首页账单结构

首页账单

SliverAppBar

收支概览卡片

快速操作区

账单明细列表

本月结余

预算进度

收入/支出

记支出

记收入

报表

预算

日期分组

交易卡片

3.3.3 统计分析结构

统计分析

SliverAppBar

收支概览卡片

支出分布饼图

支出排行列表

收入统计

支出统计

结余统计

CustomPaint绘制

图例说明

分类图标

金额进度条

百分比显示

3.4 报表导出逻辑

微信

QQ

复制

其他

点击导出报表

获取当前月份数据

计算收支统计

生成报表文本

调用Share.share

选择分享方式

分享到微信

分享到QQ

复制到剪贴板

其他应用

3.5 指纹解锁逻辑

成功

失败

应用启动

指纹解锁开启?

直接进入首页

显示验证页面

点击验证身份

调用local_auth

验证结果

提示验证失败

点击跳过验证

使用应用

应用进入后台

指纹解锁开启?


四、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 后续版本规划

2024-01-07 2024-01-14 2024-01-21 2024-01-28 2024-02-04 2024-02-11 2024-02-18 2024-02-25 2024-03-03 2024-03-10 基础UI框架 数据库存储 分类统计 报表导出 指纹解锁 记账提醒 预算管理 数据备份恢复 云端同步 V1.0 基础版本 V1.1 增强版本 V1.2 进阶版本 记账本开发计划

7.2 功能扩展建议

7.2.1 高级统计功能

统计功能:

  • 年度收支趋势图
  • 分类对比分析
  • 预算达成率分析
  • 消费习惯洞察
7.2.2 账户管理功能

账户管理:

  • 账户转账记录
  • 信用卡账单管理
  • 账户余额变动趋势
  • 多币种支持
7.2.3 云端同步功能

云端功能:

  • 多设备数据同步
  • 数据云端备份
  • 家庭账本共享
  • 数据加密存储

八、注意事项

8.1 开发注意事项

  1. 数据库操作:使用异步操作,避免阻塞UI线程

  2. 数据精度:金额使用double类型,注意精度问题

  3. 分类扩展:预留自定义分类接口

  4. 隐私保护:敏感数据需要加密存储

  5. 性能优化:大量数据时使用分页加载

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数据库持久化存储,支持报表分享和指纹解锁保护隐私。通过本应用,希望能够帮助用户养成良好的记账习惯,实现财务自由的目标。

记账本——轻松掌控个人财务


Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐