Cashew腰果记账
Cashew腰果记账是一款功能齐全、特性丰富的应用程序,旨在帮助用户有效管理他们的财务。该应用使用Flutter构建 - 配合Drift的SQL包和Firebase,为各种设备提供流畅直观的用户体验。开发始于2021年9月。
功能特性
Cashew腰果记账在YouTube上被评为"2024年最佳免费开源应用"(并出现在缩略图中!)
Cashew腰果记账在YouTube上被评为"2023年最佳应用"
Cashew腰果记账在YouTube上被评为"顶级Android应用!(2023年11月)"
Cashew腰果记账被Google Play的编辑推荐为"我们喜爱的新应用"(2023年11月)!
Cashew腰果记账被收录在Material You应用列表中!
发布
查看官方网站!
本应用程序可在App Store、Google Play、GitHub和Web应用(PWA)上获取。
更新日志
开发过程中的变更和进展都在GitHub的提交记录和更新日志中有详细记录。
主要功能
💸 预算管理
- 自定义预算和时间周期:设置个性化预算,灵活选择时间周期,如月度、周度、每日或任何符合您财务规划需求的自定义时间周期。自定义时间周期对于设置一次性旅行预算等特殊情况非常有用!
- 添加预算:有选择地将交易添加到特定预算中,让您专注于特定的支出类别。
- 每个预算的类别支出限额:为预算内的每个类别设置限额,确保合理支出。
- 查看过往预算历史:通过访问过去的预算历史分析您的支出习惯,实现财务进展的比较和跟踪。
- 目标:创建支出和储蓄目标,将交易分配到不同的购买或储蓄项目。跟踪您实现财务目标的进度。
💰 交易管理
- 支持不同交易类型:根据即将到来、订阅、重复、债务(借入)和信用(借出)等类型有效分类交易。每种类型在界面中都有特定的表现方式。您可以在准备好时支付即将到来的交易,或将借出的交易标记为已收回。
- 自定义类别:创建个性化类别,根据您独特的支出习惯组织交易。搜索多个图标并在添加交易时选择默认选项为支出或收入。
- 自定义标题:自动将相同名称的交易分配到特定类别,节省时间并确保一致性。这些标题会存储在内存中,当您添加另一个类似名称的交易时会弹出。
- 搜索和筛选:轻松根据日期、类别、金额或自定义标签等各种条件搜索和筛选交易,快速获取信息。
- 轻松编辑:长按和滑动选择多个预算,根据需要进行相应编辑或一次性删除多个。
💱 财务灵活性
- 多种货币和账户:管理不同货币和账户的财务,提供最新汇率以进行准确计算和轻松货币转换。界面显示原始添加金额和转换后的账户金额。
- 轻松切换账户和货币:在主页上,轻松选择不同的账户和货币,所有内容都会立即自动转换。
🔒 增强安全性和可访问性
- 生物识别锁:使用生物识别认证保护预算数据,增加额外的隐私保护层。
- Google登录:使用Google账户方便登录应用,确保简化且无障碍的认证过程。
🎨 用户体验和设计
- Material You设计:享受视觉吸引力强、现代化的界面,遵循Material You设计原则,提供愉悦的用户体验。
- 自定义强调色:通过选择适合您风格的自定义强调色个性化应用,或跟随系统主题。
- 明暗模式:无缝切换明暗主题,优化可视性并减少眼睛疲劳。
- 可定制主屏幕:定制主屏幕布局和小部件,展示对您最重要的财务信息,提供个性化和高效的仪表板。
- 详细图表可视化:通过详细的交互式图表深入了解支出模式,一目了然地可视化财务数据。
- 美观的自适应UI:响应式用户界面,完美适应网页和移动平台,在各种设备上提供沉浸式且一致的用户体验。
☁ 备份和同步
- 跨设备同步:在所有设备上保持预算数据同步,确保随时随地都能访问财务信息。
- Google Drive备份:利用Google Drive的备份功能保护预算数据,允许在需要时轻松恢复数据。
💿 智能自动化
- 通知:及时了解重要财务事件,并收到预算目标、交易和即将到期日期的及时提醒。
- 导入CSV文件:通过上传CSV文件无缝导入财务数据,实现从其他应用程序或平台的平稳过渡。
- 导入Google表格:无缝导入Google表格,快速从电子表格中导入大量交易记录。
- 应用链接:使用应用链接自动创建预填数据的交易(详细文档见下文)
应用链接
关于应用链接(示例用法和如何利用应用链接的强大功能)的讨论/线程可以在以下问题中找到:https://github.com/jameskokoska/Cashew/issues/127#issuecomment-1975096357。 应用链接允许使用应用程序URL直接导航和自动化操作。一些示例如下。
更新日志
- 引入iOS支持(Cashew v5.3.5+400及以上版本)
- 重大变更: 移除不受支持的应用链接域名 -
cashew://budget.app
(Cashew v5.3.4+396及以上版本) - 支持更多参数,详见
详细参数
(Cashew v5.2.9+358及以上版本) - 引入Android和网页支持(Cashew v5.2.3+328及以上版本)
示例(适用于Android和iOS)
确保在启动这些URL的设备上已安装Cashew。
示例1:创建一个金额为100的购物类别支出交易,时间为当前时间
https://cashewapp.web.app/addTransaction?amount=-100&title=所有购物&category=购物¬es=去购物了
示例2:创建一个缺少类别的收入交易,时间为当前时间
https://cashewapp.web.app/addTransaction?amount=100&title=收入¬es=收到钱了
示例3:打开添加交易页面,使用自定义日期和预填详细信息
https://cashewapp.web.app/addTransactionRoute?amount=-50&title=所有购物¬es=去购物了&date=2024-03-02
示例4:使用JSON通过一个链接创建多个交易
查看下方的JSON交易列表
了解链接的格式。
路由
Android和iOS的路由 | 网页应用的路由 |
---|---|
https://cashewapp.web.app/[此处为端点] | https://budget-track.web.app/[此处为端点] |
端点
端点 | 描述 |
---|---|
/addTransaction | 添加新交易,无需UI提示(除非缺少类别)。 |
/addTransactionRoute | 打开添加新交易路由,并填入信息。 |
参数
参数 | 描述 | 必需 | 默认值 |
---|---|---|---|
amount | 交易金额。如果为负数,表示支出;如果为正数,表示收入。 | 否 | 0 |
title | 交易标题。如果找到关联标题且未设置类别,将使用关联标题的类别。 | 否 | 空字符串 |
notes | 与交易相关的备注。 | 否 | 空字符串 |
date | 交易日期。支持的字符串格式可在此处的getCommonDateFormats() 方法中找到。 | 否 | 当前时间 |
category | 要添加交易的类别名称。执行名称搜索,取第一个结果,不区分大小写。 | 否 | 提示用户 |
subcategory | 要添加交易的子类别名称。如果提供,将覆盖主类别下找到的子类别。执行名称搜索,取第一个结果,不区分大小写。 | 否 | 无 |
account | 账户名称。执行名称搜索,取第一个结果,不区分大小写。 | 否 | 主要账户 |
JSON | 交易的JSON对象列表。如果提供,Cashew将一次导入多个交易。列表中的每个JSON对象可以使用上述任何参数。JSON对象应以transactions 为键,后跟对象列表。请参阅下面的示例。 | 否 | 无 |
详细参数
以下是所有可传递参数的列表,包括额外的(尚未完全支持的)参数。它们按优先级排序,顶部的参数将在下面的参数之前解析。因此,重叠的字段将由第一个参数处理。
类别: 相关参数将具有相同的类别。
独立参数: 只使用此参数,忽略所有其他参数。
应用链接解析可在此处找到。
类别 | 参数 | 描述 | 必需 | 默认值 | 独立 |
---|---|---|---|---|---|
a | messageToParse | 使用扫描模板解析传入的消息。只有date 或dateCreated 可以与此独立参数一起传递。所有其他字段将由扫描模板构建。默认情况下,Cashew中未启用扫描模板。要启用此功能,请开启通知交易 调试功能。 | 无 | 无 | 是 |
b | JSON | 描述见上表。 | 否 | 无 | 是 |
c | subcategoryPk | 数据库中子类别条目的主键。 | 否 | 无 | |
c | subcategory | 描述见上表。 | 否 | 无 | |
c | categoryPk | 数据库中类别条目的主键。 | 否 | 提示用户 | |
c | category | 描述见上表。 | 否 | 提示用户 | |
d | walletPk | 数据库中钱包条目的主键。 | 否 | 主要账户 | |
d | account | 描述见上表。 | 否 | 主要账户 | |
d | wallet | 与account 相同。 | 否 | 主要账户 | |
e | date | 描述见上表。 | 否 | 当前时间 | |
e | dateCreated | 与date 相同。 | 否 | 当前时间 | |
f | amount | 描述见上表。 | 否 | 0 | |
g | title | 描述见上表。 | 否 | 空字符串 | |
g | name | 与title 相同。 | 否 | 空字符串 | |
h | notes | 描述见上表。 | 否 | 空字符串 | |
h | note | 与notes 相同。 | 否 | 空字符串 |
JSON交易列表
addTransaction
和addTransactionRoute
的输入JSON应遵循以下格式:
{
"transactions":[
{ ... },
{ ... },
{ ... }
]
}
示例:
{
"transactions": [
{
"amount": "-100",
"notes": "这是一条备注",
"category": "购物"
},
{
"amount": "-150",
"notes": "这是第二条备注"
}
]
}
别忘了在URL中对JSON进行编码,因为JSON使用了无效的URI字符。编码后,输出链接看起来会像这样:
故障排除
Android
如果您被重定向到网站而不是Cashew应用程序,您的设备可能未正确设置以打开应用链接。确保Cashew可以打开其相应的应用链接。在您的Android设备上,转到设备设置,"默认应用程序","打开链接",并确保Cashew有权限从域名cashewapp.web.app
下的"支持的网址"打开。如果您没有安装Google Play签名的Cashew副本(例如从GitHub下载),这可能默认被禁用。这是因为Cashew现在使用应用链接,根据Android 12+的要求,需要使用应用程序的签名公钥进行验证。或者,您可以使用像LinkSheet这样的重定向应用程序,它可以管理在激活某些链接时打开哪些应用程序。
测试
使用ADB进行Android测试
您可以使用ADB测试应用链接。例如
adb shell am start -a android.intent.action.VIEW -d "https://cashewapp.web.app/addTransaction?amount=-70\&title=Grocery%20Shopping\&date=2024-03-02\&category=Food\&subcategory=Groceries\¬es=Bought%20fruits%20and%20vegetables\&account=test"
使用链接
你可以点击链接并用Cashew打开它们。请查看上面的示例部分进行测试。
捆绑包
此仓库包含了以下已停止维护的包的修改版本。它们可以在/budget/packages
文件夹中找到。
- https://pub.dev/packages/implicitly_animated_reorderable_list
- https://pub.dev/packages/sliding_sheet
翻译
更新翻译
- 运行
budget\assets\translations\generate-translations.py
- 重启应用程序
开发者注意事项
拉取请求和贡献
很遗憾,由于许可和署名问题,我目前不接受贡献。由于这个应用程序产生一些利润,我想避免在贡献补偿方面出现任何模糊不清的情况。你可以提交一个问题,我会考虑的!
Android发布
- 要构建Android应用包发布版本,运行
flutter build appbundle --release
注意:需要Android SDK。
iOS发布
- 要构建iOS IPA发布版本,运行
flutter build ipa
注意:需要MacOS。
Firebase部署
- 要部署到Firebase,运行
firebase deploy
注意:需要Firebase。
GitHub发布
- 为
pubspec.yaml
中指定的当前版本创建一个标签 git tag <version>
- 推送标签
git push origin <version>
- 创建发布并上传二进制文件
- https://github.com/jameskokoska/Cashew/releases/new
脚本
deploy_and_build_windows.bat
- 部署到Firebase并构建apk和appbundle
open_release_builds.bat
- 打开构建的apk和appbundle的位置
update_translations.bat
- 下载最新版本的Cashew翻译。运行
budget\assets\translations\generate-translations.py
在Android上无线开发
adb tcpip 5555
adb connect <IP>
- 通过进入
关于手机
>状态信息
>IP地址
获取手机的IP
数据库迁移
- 对数据库的架构和表进行任何更改
- 提升架构版本
- 在
tables.dart
中更改int schemaVersionGlobal = ...+1
- 在
- 确保你在应用程序根目录下
cd .\budget\
- 生成数据库代码
- 运行
dart run build_runner build
- 运行
- 导出新架构
- 为新创建的架构生成架构转储
- 将下面命令中的
[schemaVersion]
替换为schemaVersionGlobal
的值 - 运行
dart run drift_dev schema dump lib\database\tables.dart drift_schemas//drift_schema_v[schemaVersion].json
- 了解更多:https://drift.simonbinder.eu/docs/advanced-features/migrations/#exporting-the-schema
- 生成逐步迁移
- 运行
dart run drift_dev schema steps drift_schemas/ lib\database\schema_versions.dart
- 运行
- 实现迁移策略
- 编辑
tables.dart
中的await stepByStep(...)
函数,并为新版本迁移添加迁移策略
- 编辑
获取平台
- 使用
functions.dart
中的getPlatform()
- 由于
Platform
在网页上不支持,我们必须创建一个封装器,并始终使用它来确定当前平台
推送路由
- 如果我们想导航到新页面,请坚持使用
functions.dart
中的pushRoute(context, page)
函数 - 它处理平台路由和
PageRouteBuilder
钱包 vs. 账户
钱包
在前端已被重命名为账户
,但在内部,名称钱包
仍在使用。
目标 vs. 目标
目标
在前端已被重命名为目标
,但在内部,名称目标
仍在使用。
长期贷款
- 长期贷款会创建一个目标。然而,目标的总额并未被使用。相反,目标的总额是通过计算相反类型交易的适当极性来计算的。例如,如果是借出100美元的贷款,初始交易将是100美元的负极性(支出),这将是目标的总额。当进行还款时,它以相反(正)极性(收入)进行,并添加到"已偿还"的总额中。我们可以通过取差额(或包括极性的加法)轻松找出剩余金额。