Actual 24.11.0 版本深度解析:规则模板引擎、Upcoming 计划长度与 Dashboards 实验特性
【免费下载链接】actualA local-first personal finance app项目地址: https://gitcode.com/GitHub_Trending/ac/actual
Actual 是一个本地优先(local-first)的个人财务管理应用,其 24.11.0 版本围绕「自动化与可定制性」带来了一批显著改进。本文以该版本的官方发布文档为骨架,结合仓库源码,深入拆解规则模板(Handlebars 模板与公式)、Upcoming 计划显示长度、Dashboards 仪表盘增强、账户管理迁移与文件迁移等核心特性,帮助读者理解每个改进背后的实现机制与实际使用方法。
版本概览与升级方式
Actual 24.11.0 于 2024 年 11 月发布,官方发布文档(packages/docs/blog/2024-11-03-release-24.11.0.md)给出的 Docker 镜像标签为24.11.0,可直接用于自托管部署。
本版本的核心改进集中在四条主线:
- SimpleFIN 银行同步 API 调用优化(针对 Actual Server);
- 实验性支持设置 Upcoming 计划显示时长(即未来多远距离的周期性交易显示在账户视图);
- 实验性 Dashboards 功能的多项改进;
- 实验性的规则模板化支持(规则「设置」动作中引入 Handlebars 模板语法)。
此外还包含大量对移动端、CSV 导入、规则引擎、报表的 Bug 修复与维护性重构(详见下文各节)。
规则模板引擎:在「设置」动作中使用 Handlebars
功能来源
本次发布的规则模板功能来自两个 PR:
- #3305:为 set 动作引入基于 Handlebars 语法的规则动作模板;
- #3619:将模板能力扩展到
payee_name字段。
这意味着用户可以把规则动作写成{{ ... }}形式的模板表达式,由引擎在规则匹配时动态求值,而不是使用固定值。
底层实现原理
规则动作的核心实现在 packages/loot-core/src/server/rules/action.ts。其中Action类支持的操作类型(ACTION_OPS)包括:
set:设置字段值(支持固定值、公式、模板三种模式);set-split-amount:设置拆分金额(支持固定金额、百分比、公式等分配方式);link-schedule:关联到计划交易;prepend-notes/append-notes:在备注前/后追加文本;delete-transaction:删除交易(置 tombstone 标记)。
当set动作携带options.template时,构造函数会调用Handlebars.compile(options.template, { noEscape: true })预编译模板,并在exec()阶段执行:
// 源码节选:packages/loot-core/src/server/rules/action.ts if (options?.template) { this.handlebarsTemplate = Handlebars.compile(options.template, { noEscape: true, }); }执行模板时,传入的上下文包含交易对象的所有字段,并额外注入today(当前日期)变量:
object[this.field] = this.handlebarsTemplate({ ...object, today: currentDay(), });Handlebars 总是返回字符串,因此引擎按目标字段类型做转换(见exec()中的 switch):
- number 字段:
parseFloat转换,结果为 NaN 时回退为 0,避免数据库写入失败; - date 字段:
parseDate后校验合法性,非法时写入9999-12-31作为显眼占位,并输出错误日志; - boolean 字段:字符串
'true'判定为真。
内置模板 Helper
模板之所以强大,是因为项目注册了大量内置 Helper。它们在 packages/loot-core/src/server/rules/handlebars-helpers.ts 中定义,并在 packages/loot-core/src/server/rules/index.ts 中通过registerHandlebarsHelpers()统一注册,按类别可分为:
字符串处理:
| Helper | 说明 |
|---|---|
regex | 正则替换,支持/regex/flags语法(如{{regex value "/\d+/" "X"}}) |
replace | 普通替换(支持正则字面量/.../flags) |
replaceAll | 全局替换 |
concat | 拼接多个参数 |
数学运算:
| Helper | 说明 |
|---|---|
add/sub/div/mul/mod | 算术运算,支持多参数(如{{add a b c}}) |
floor/ceil/round/abs | 取整与绝对值 |
min/max | 最小值/最大值 |
fixed | 保留指定位小数(如{{fixed amount 2}}) |
日期运算:
| Helper | 说明 |
|---|---|
day/month/year | 提取日期分量 |
format | 按自定义格式输出日期 |
addDays/subDays/addMonths/subMonths/addWeeks/subWeeks/addYears/subYears | 日期加减 |
setDay | 将日期调整到指定「星期几」(以本周为基准) |
debug | 输出日志用于调试 |
日期 Helper 底层基于date-fns与项目封装的#shared/months工具实现,所有日期函数输入输出统一为yyyy-MM-dd格式。
实际应用示例
利用这些 Helper,可以构建出非常灵活的规则动作,例如:
# 给商家名补全:把 "COFFEE" 统一改为 "COFFEE SHOP" set payee_name to template {{replaceAll payee_name "COFFEE" "COFFEE SHOP"}} # 备注前追加当前日期 prepend-notes {{format today "yyyy-MM-dd"}}: # 将金额四舍五入到整数 set amount to template {{round amount}}注意set动作在payee_name字段上执行模板后,源码会将object['payee'] = 'new'(action.ts),即创建新的收款人实体,这正是 #3619 将模板扩展到payee_name的核心逻辑。
相关 Bug 修复
本次发布同时修复了模板功能初期的问题:
- #3632:修复 action 规则模板中的转义(escaping)问题;
- #3749:修复规则模板中使用日期函数的问题;
- #3704:修复无法通过规则修改 Payee 的问题;
- #3705:修复 off-budget 账户被错误设置分类的问题。
这些修复说明模板引擎在发布前经历了密集的实战打磨,也提醒使用者在升级后重新验证已有规则行为。
实验性特性:设置 Upcoming 计划显示长度
功能来源
Upcoming Length 控制来自 PR#3310("Add option to set how far out the upcoming scheduled transactions are shown in the account view")与#3639("Add info text to Upcoming Length control"),并配套#3651为其添加了功能开关(feature flag)。
功能说明
在账户视图中,「Upcoming」区域会显示未来一段时间内即将发生的周期性计划交易。旧版本这个时间窗是固定的,而 24.11.0 允许用户自定义「提前多少天」显示这些计划交易。
配置项与预设值
UI 组件实现在 packages/desktop-client/src/components/schedules/UpcomingLength.tsx,底层偏好值为同步偏好upcomingScheduledTransactionLength,通过useSyncedPref读写。预设选项集中在 packages/loot-core/src/shared/schedules.ts:
- 默认值:
DEFAULT_UPCOMING_SCHEDULE_DAYS = '7'(7 天); - 预设选项(
UPCOMING_LENGTH_PRESET_VALUES):1(1 天)、7(1 周)、14(2 周)、oneMonth(1 个月)、currentMonth(当月月底); - 自定义值:任意非预设字符串都会被识别为自定义长度(
isCustomUpcomingLength),界面提供 Custom length 输入框(CustomUpcomingLength组件)。
设置界面包含说明文字,明确两点:
- 该设置只影响计划交易的显示(距离计划日期多少天开始出现在账户账本中),不改变预算数据的存储方式;
- 该设置可以随时更改。
由于是同步偏好(SyncedPref),该设置会随预算文件同步,多端保持一致。
使用方式
进入 Schedules(计划)设置或账户视图的相关入口,打开名为schedules-upcoming-length的弹窗(见 UpcomingLength.tsx),选择预设值或输入自定义天数,点击 Save 保存即可。修改会立即影响账户视图中 upcoming 交易的显示范围。
实验性 Dashboards 的多项改进
Dashboards(仪表盘)作为实验功能,在本版本中得到集中打磨:
- #3587:支持在内部报表页面快速重命名 widget(组件名称);
- #3588:让「add widgets」按钮始终可见,降低操作成本;
- #3626:修复(实验性)报表页导入非自定义报表 widget 的问题;
- #3633:修复自定义报表的「show uncategorized」与「show off budget」选项。
这些改进主要落在 packages/desktop-client/src/components/reports 目录下,配合#3611(移除 Spending Report 的功能开关,正式开放)与#3615(即使账户开启了银行同步,也始终显示「import transactions」按钮)一起,提升了报表与数据导入的整体可用性。
账户管理与文件迁移:管理页的整合
功能来源
PR#3584("Moving file settings to the management page and enabling budget file relocation")是本版本在文件管理上的重要变化:
- 将文件设置迁移到管理页面(management page)统一管理;
- 支持预算文件的重新定位(relocation)。
配套修复
- #3600:当迁移(migrations)不同步时弹出引导弹窗,避免用户在状态不一致时操作;
- #3717:修复下载预算时的竞态条件(race condition);
- #3736:服务器 URL 配置错误时增加额外错误处理;
- #3697:支持使用 ngrok 隧道接入 actual-sync 服务器,方便远程联调。
这些改动涉及 packages/desktop-client 与 packages/sync-server 两个包,体现了 24.11.0 对自托管部署体验的持续优化。
Actual Server 侧改进
发布文档的 Server 部分同样包含值得关注的变化:
银行同步优化
- #482:请求账户列表时不再从 SimpleFIN 拉取交易,减少不必要的 API 调用;
- #483:SimpleFIN 同步单个账户时只拉取该账户的交易;
- #470:银行交易排序扩展,存在
bookingDateTime时按时间排序; - #473 / #481:将 N26、Fineco(意大利/英国)加入历史数据受限银行列表;
- #486:调整 EASYBANK(BAWAATWW)的
access_valid_for_days为 179 天。
配置与部署
- #480:允许通过环境变量覆盖数据目录,为容器化部署提供更大灵活性;
- #487:修复初始设置时迁移未正确运行的问题。
维护
- #432:为
app-sync.js集成 FileService; - #478:为银行集成消息设置正确的日志级别。
以上改动集中在 packages/sync-server/src 下(如app-sync.ts、app-gocardless、app-simplefin等目录),实际部署时可参考 packages/sync-server/README.md 与 docker-compose.yml。
其他值得关注的变化
界面与交互
- #3549:[Mobile] 允许更新已有交易的账户;
- #3554:侧边栏仅滚动账户列表,按钮保持固定;
- #3622:[Mobile] Cleared 标记改为开关(toggle)交互;
- #3684:账户页新增 Reconcile(对账)按钮;
- #3648:帮助相关条目整合到单一菜单;
- #3691:帮助菜单中加入 goal template 参考指南。
CSV 导入
- #3543:在多次 CSV 导入之间保存 in/out 模式设置;
- #3605:修复 CSV 仅含 3 列时的导入问题;
- #3613:导入按钮显示将要导入的准确交易数量;
- #3499(维护):为 CSV 导入对话框补充 E2E 测试。
预算与目标
- #3617:新增目标模板:从 N 个月前的预算复制;
- #3695:修复 tracking budget 中预算复制失效的问题;
- #3721:修复模板通知不显示的问题;
- #3511:修复年度计划模板在提前于交易日期做预算时行为不正确的问题。
移动端与报表修复
- #3343:修复移动端模态框滚动缓慢;
- #3602:确保移动端预算视图金额为正;
- #3679:修复 Spending Report 第 28 天起的累计总额错误;
- #3723:修复 Monthly Spending Report 前三月的平均值计算;
- #3725:修复标签名含正则特殊字符时标签过滤导致崩溃的问题。
维护与工程化
- #3471:用
@emotion/css替换 glamor CSS-in-JS 库; - #3553:减小桌面应用包体积;
- #3580:移除
electron-is-dev依赖; - #3365:为
account/rules.ts添加更严格的类型; - 大量组件完成 TypeScript 迁移(
ManagePayees、LoadBackupModal、NetWorth、ImportTransactionsModal 子组件、账户 header 等)。
总结
Actual 24.11.0 是一个「自动化能力」与「使用体验」并重的版本:
- 规则模板引擎(#3305、#3619)把规则从「固定值替换」升级为「可编程表达式」,配合内置的字符串、数学、日期 Helper,可以实现高度自动化的交易分类与清洗,核心实现位于 packages/loot-core/src/server/rules/action.ts 与 handlebars-helpers.ts;
- Upcoming Length(#3310)让用户按天/周/月自由控制计划交易的显示窗口,配置保存在同步偏好
upcomingScheduledTransactionLength中; - Dashboards 与报表获得多项实验性增强,Spending Report 正式开放;
- 管理页整合与文件迁移(#3584)、SimpleFIN API 优化(#482、#483)分别提升了文件管理与银行同步的效率。
如需深入源码,推荐从以下入口继续阅读:规则动作实现 action.ts、规则测试快照 transaction-rules.test.ts.snap、计划配置常量 shared/schedules.ts、Upcoming Length 界面 UpcomingLength.tsx。
【免费下载链接】actualA local-first personal finance app项目地址: https://gitcode.com/GitHub_Trending/ac/actual
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考