我做了一个不会偷看你账单的记账 App

前言

你有没有遇到过这样的困扰?

  • 打开记账 App,首页推荐的不是记账功能,而是贷款广告
  • 刚在 App 里记录了一笔大额消费,第二天就收到理财产品推送
  • 想导出自己的账单数据,却发现只能导出 PDF,无法进一步分析
  • 担心记账软件倒闭,多年的财务数据付之东流

作为一个程序员,我对这些问题深感不安。于是,我决定自己动手,做一个真正把数据所有权还给用户的记账应用。

这就是**蜜蜂记账(BeeCount)**的由来。

为什么要自己做记账 App?

市面上记账软件的问题

我调研了市面上主流的记账软件,发现它们普遍存在以下问题:

1. 隐私问题

大多数记账 App 会将你的数据上传到他们的服务器。表面上是为了"云同步",但你的消费习惯、收入水平、资产状况等敏感信息,都被完整地存储在第三方服务器上。

更糟糕的是,很多 App 的隐私政策中明确写着"可能会将数据用于商业分析"或"与合作伙伴共享"。你的财务隐私,实际上已经不再属于你。

2. 广告和推销

免费的记账 App 需要盈利,最常见的方式就是广告和金融产品推销:

  • 开屏广告、横幅广告
  • 贷款产品推荐
  • 理财产品推销
  • 信用卡办理引导

有些 App 甚至会根据你的消费数据,"精准推送"贷款广告。这不仅影响使用体验,更让人担心数据被滥用。

3. 功能锁定

很多记账 App 采用"免费增值"模式,核心功能需要付费订阅:

  • 多账本管理需要会员
  • 数据导出需要会员
  • 云同步需要会员
  • 图表分析需要会员

一旦停止订阅,功能立刻降级,甚至无法导出历史数据。

4. 数据不可控

当你把数据托管给第三方服务时,你就失去了对数据的完全控制:

  • 无法自由选择存储位置
  • 无法自由迁移到其他服务
  • 服务商倒闭后数据可能丢失
  • 无法审计数据的使用情况

理想的记账软件应该是什么样的?

基于这些问题,我列出了理想记账软件的特征:

数据主权:数据完全由用户掌控,可以选择存储位置 ✅ 隐私保护:开发者无法访问用户数据 ✅ 完全免费:所有功能免费使用,无广告 ✅ 开源透明:代码公开,可审计 ✅ 功能完整:不阉割核心功能 ✅ 自由迁移:支持标准格式导入导出

市面上没有同时满足这些条件的产品,所以我决定自己做一个。

技术选型和架构设计

为什么选择 Flutter?

跨平台是必须的。我希望这个 App 能同时支持 iOS 和 Android,而不是分别开发两个版本。

在对比了 React Native、Flutter、Kotlin Multiplatform 后,我选择了 Flutter:

  • 性能优秀:编译为原生代码,接近原生性能
  • UI 一致性:自绘引擎保证跨平台 UI 完全一致
  • 开发效率:热重载极大提升开发效率
  • 生态成熟:包管理、状态管理等工具链完善

数据存储:本地优先 + 可选云同步

本地存储使用 SQLite(通过 Drift ORM):

  • 离线优先,无需网络即可使用
  • 数据完全存储在设备本地
  • 查询性能优秀
  • 支持事务和完整性约束

云同步是可选的,而且是自建云服务

我支持了两种方案:

方案 1:Supabase(推荐新手)

Supabase 是开源的 Firebase 替代品,提供:

  • 数据库(PostgreSQL)
  • 身份认证
  • 对象存储
  • 实时订阅

关键是,用户可以使用自己的 Supabase 项目,数据存储在用户自己的 Supabase 实例中,而不是我的服务器。

Supabase 提供免费套餐,对于个人记账完全够用。

方案 2:WebDAV(推荐 NAS 用户)

WebDAV 是一个开放的文件共享协议,支持:

  • Synology、QNAP、UGREEN 等 NAS
  • Nextcloud、ownCloud 等私有云
  • 坚果云等支持 WebDAV 的网盘

用户可以将数据同步到自己的 NAS 或私有云,数据完全本地化

这两种方案的共同点是:数据存储在用户自己控制的服务器或云平台上,我作为开发者无法访问。

状态管理:Riverpod

Flutter 的状态管理方案很多,我选择了 Riverpod:

  • 类型安全,编译时检查
  • 依赖注入简洁优雅
  • 支持异步状态管理
  • 可测试性强

数据导入导出:CSV + 智能识别

为了让用户能够自由迁移数据,我实现了完整的 CSV 导入导出功能。

特别是导入功能,我做了很多优化:

  • 智能列映射:自动识别"日期""金额""分类"等常见列名
  • 支持多语言:识别中文、英文等不同语言的列名
  • 支持支付宝/微信账单:可以直接导入支付宝和微信导出的账单(CSV/XLSX 格式)
  • 预览和确认:导入前可以预览数据,调整映射关系

核心功能实现

多账本管理

很多人有多个账本的需求:

  • 个人账本
  • 家庭账本
  • 工作账本
  • 投资账本

蜜蜂记账支持创建多个账本,每个账本独立记录,互不干扰。

在底部导航栏有一个专门的"账本"标签,可以快速切换账本。

分类管理

内置了常用的收入和支出分类,同时支持:

  • 自定义分类
  • 自定义分类图标(Emoji)
  • 分类排序
  • 分类隐藏/显示

特别地,我实现了分类迁移功能:当你想删除一个分类时,可以选择将该分类下的所有记录迁移到另一个分类,避免数据丢失。

图表分析

实现了多维度的数据分析:

  • 月度报表:收入、支出、结余的月度趋势
  • 分类统计:各分类的支出占比
  • 排行榜:支出金额最多的分类
  • 时间筛选:按年、月、全部时间查看

图表使用 fl_chart 库实现,支持交互和动画。

搜索功能

支持全文搜索,可以按:

  • 交易描述
  • 金额
  • 分类
  • 日期范围

搜索结果按时间倒序排列。

主题定制

内置了多种主题颜色,用户可以根据喜好选择。

主题系统基于 Material Design 3,自动适配亮色和暗色模式。

国际化支持

为了让更多人使用,我实现了完整的国际化(i18n)支持。

目前支持 9 种语言:

  • 简体中文
  • 繁体中文
  • English
  • 日本語
  • 한국어
  • Español
  • Français
  • Deutsch
  • Português

国际化不仅包括 UI 文本翻译,还包括:

  • 日期格式本地化:不同地区的日期格式不同
  • 数字格式本地化:千分位分隔符、小数点符号
  • 分类名称映射:导入 CSV 时自动识别不同语言的分类名

如果你想贡献新的语言翻译,欢迎提交 Pull Request!

云同步实现细节

云同步是最复杂的部分,我采用了以下设计:

数据模型

每条记录都有以下元数据:

  • id:唯一标识符(UUID)
  • createdAt:创建时间
  • updatedAt:最后修改时间
  • deletedAt:删除时间(软删除)

同步策略

采用时间戳为基础的增量同步

  1. 上传:将本地 updatedAt 晚于上次同步时间的记录上传到云端
  2. 下载:将云端 updatedAt 晚于本地记录的数据下载到本地
  3. 冲突解决:如果同一条记录本地和云端都被修改,以 updatedAt 较新的为准

软删除

为了支持多设备同步,删除操作不会真正删除数据,而是:

  • 设置 deletedAt 字段
  • 同步到其他设备
  • 其他设备收到后也标记为删除

这样可以避免"在 A 设备删除,同步后又从 B 设备恢复"的问题。

真正的物理删除由用户手动触发("清理已删除数据"功能)。

Supabase 实现

Supabase 提供了完整的后端能力:

  • Realtime:实时数据订阅,一个设备修改后其他设备立即更新
  • Row Level Security:行级安全策略,确保用户只能访问自己的数据
  • Auth:内置身份认证,支持邮箱、OAuth 等多种方式

WebDAV 实现

WebDAV 相对简单:

  • 数据以 JSON 格式存储为文件
  • 定期轮询检查文件是否有更新
  • 使用文件锁避免并发冲突

隐私和安全

数据加密

  • 本地数据:存储在 SQLite 数据库中,受操作系统保护
  • 传输加密:使用 HTTPS/TLS 加密传输
  • 云端存储:由用户自己的 Supabase 或 WebDAV 服务负责

如果用户需要更高的安全性,可以:

  • 启用设备的全盘加密
  • 使用加密的 WebDAV 服务
  • 设置 App 密码锁(计划中)

权限最小化

App 只请求必要的权限:

  • 存储权限:用于导入/导出 CSV 文件
  • 网络权限:用于云同步(可选)

不需要:

  • ❌ 通讯录权限
  • ❌ 相机权限
  • ❌ 位置权限
  • ❌ 电话权限

开源可审计

代码完全开源在 GitHub 上,任何人都可以审计:

  • 检查是否有隐藏的数据上传
  • 检查是否有安全漏洞
  • 贡献代码改进

开发过程中的挑战

1. CSV 解析和智能识别

CSV 格式看似简单,实际上有很多坑:

  • 字符编码问题(UTF-8、GBK、GB2312)
  • 引号和转义处理
  • 多行字段
  • 不同的分隔符(逗号、制表符)

支付宝和微信导出的 CSV 格式也各不相同:

支付宝

  • 前 25 行是元信息,第 25 行才是表头
  • 列名:交易时间商品说明收/支金额

微信

  • 前 16 行是元信息
  • 列名:交易时间交易类型收/支金额
  • 支持 XLSX 格式

为了支持这些格式,我实现了:

  • 智能检测表头位置(扫描前 30 行)
  • 灵活的列名匹配(支持多个同义词)
  • 用户手动选择账单类型(通用/支付宝/微信)

2. 跨平台 UI 一致性

Flutter 的自绘引擎保证了基本的 UI 一致性,但仍有一些平台差异需要处理:

  • 状态栏和导航栏:iOS 和 Android 的高度和样式不同
  • 日期选择器:iOS 和 Android 的原生选择器样式完全不同
  • 权限请求:iOS 和 Android 的权限模型不同

最终我使用了 SafeArea 和条件编译来处理这些差异。

3. 数据库迁移

随着功能迭代,数据库 schema 需要升级。我使用 Drift 的 migration 功能:

@DriftDatabase
(...)

class
 
AppDatabase
 
extends
 
_
$
AppDatabase
 
{
  
@override

  
int
 
get
 schemaVersion => 
3
;

  
@override

  MigrationStrategy 
get
 migration => MigrationStrategy(
        onUpgrade: (m, from, to) 
async
 {
          
if
 (from == 
1
) {
            
await
 m.addColumn(transactions, transactions.cloudId);
          }
          
if
 (from <= 
2
) {
            
await
 m.addColumn(transactions, transactions.deletedAt);
          }
        },
      );
}

每次升级都要确保旧版本用户的数据能够平滑迁移。

4. iOS 发布

Android 可以直接分发 APK,但 iOS 必须通过 App Store 或 TestFlight。

这需要:

  • Apple Developer 账号($99/年)
  • 代码签名:证书、Provisioning Profile
  • 自动化构建:GitHub Actions 自动签名和上传

为了让社区用户能用上 iOS 版本,我在 V2EX 发起了筹款,目标 $99(Apple 开发者账号年费)。

令人感动的是,不到一天时间,目标就达成了(实际筹集 ¥732)。感谢所有支持者!

iOS 版本预计 5-7 天后通过 TestFlight 发布。

开源和社区

为什么选择开源?

  1. 透明性:用户可以审计代码,确认没有隐私问题
  2. 可持续性:即使我不再维护,社区也可以 fork 继续开发
  3. 协作:接受社区贡献,功能迭代更快
  4. 学习:其他开发者可以学习和参考代码

开源协议:MIT

我选择了 MIT 协议,这是最宽松的开源协议之一:

  • ✅ 可以商业使用
  • ✅ 可以修改和分发
  • ✅ 可以私有使用
  • ✅ 可以闭源修改版本

唯一的要求是保留原始的版权声明。

社区参与

项目在 GitHub 上开源:https://github.com/TNT-Likely/BeeCount

目前已有 140+ Stars,欢迎:

  • 🐛 提交 Bug 报告
  • ✨ 提交功能建议
  • 💻 贡献代码
  • 🌍 贡献翻译
  • 📖 改进文档

未来计划

短期计划(1-2 个月)

  • ✅ iOS 版本发布(TestFlight 和 App Store)
  • ⏳ iPad 适配优化
  • ⏳ 桌面小组件(iOS/Android)
  • ⏳ 预算功能
  • ⏳ 定期交易(重复记账)

中期计划(3-6 个月)

  • 📊 更多图表类型(饼图、趋势图)
  • 🔔 提醒功能(账单提醒、预算超支提醒)
  • 📸 发票扫描(OCR 识别金额)
  • 🎨 更多主题和自定义选项
  • 🍎 Apple Watch 版本
  • 💬 Siri 快捷指令

长期计划(6 个月以上)

  • 🌐 Web 版本(使用 Flutter Web)
  • 💻 桌面版本(Windows、macOS、Linux)
  • 🤝 家庭账本共享
  • 📈 投资组合管理
  • 🔄 更多云服务支持(AWS S3、Google Drive、Dropbox)

总结

做蜜蜂记账的初衷很简单:我想要一个不会偷看我账单的记账软件。

在这个数据即金钱的时代,隐私变得越来越珍贵。大多数免费软件都在用你的数据变现,而我希望做一个例外。

蜜蜂记账的核心理念是:

  • 🔒 数据主权:你的数据,你做主
  • 🆓 完全免费:所有功能永久免费
  • 🔓 开源透明:代码公开,可审计
  • 🛡️ 隐私优先:开发者无法访问你的数据

如果你也在寻找这样一款记账软件,不妨试试蜜蜂记账。

如果你是开发者,欢迎阅读源码,参与贡献。

让我们一起,把数据所有权还给用户。


相关链接

关于作者

一名关注隐私和开源的独立开发者,相信技术应该服务于人,而不是控制人。

如果你喜欢这个项目,欢迎在 GitHub 给个 Star ⭐️

3
0