一个自建的个人记账 Web 应用:飞书多维表格当账本,本地 SQLite 当镜子,网页当门面。
手机、电脑都能用;记账、看报表、月度对账全在一个页面里完成。零构建工具链——Python + Flask + 标准库,git clone 完填个配置就能跑。
适合谁:已经在飞书多维表格里记账、但受够了在手机上戳表格的人。 不适合谁:想要一个开箱即用云服务的人(这是自托管项目,你得有自己的飞书表格)。
多维表格是很好的账本(公式强大、数据在自己手里),但是很糟糕的录入界面和看板——手机上放大缩小找单元格,谁都受不了。
MoneyMirror 的做法:
写入(唯一入口)
网页 / 手机捷径 / 机器人 ──→ 飞书多维表格(唯一真相)
│
│ sync.py 单向全量重照
↓
SQLite 镜像(只读副本)
↓
网页所有页面读这份副本
三条规矩撑起整个系统:
- 写永远写飞书。App 与任何其他录入方(机器人、手工)平级,都只是飞书的前端。
- 读永远读本地镜像。页面秒开,不用每次问云端。
- 镜像随时可以扔掉重建。删掉
.db文件跑一次sync.py就回来了。
这条铁律的价值:永远不会出现两本对不上的账。
| 页面 | 能干什么 |
|---|---|
| 首页 | 净资产大数字 + 趋势曲线 + 关键指标卡 + 决策事件标记 |
| 流水 | 按日分组的交易列表,月/类型/分类/账户四维筛选 + 全文搜索 + 分页;点开可编辑/删除 |
| 记一笔 | 手机数字键盘录入(支出/收入/转账/余额校准),写入飞书后即时刷新镜像 |
| 报表 | 预算执行三色预警 + 分类支出 + 月度收支对比 + 单分类跨月趋势 |
| 账户 | 账户分组管理,点开看近期流水与余额曲线,可改名、可单户校准 |
| 对账 | 填各账户真实余额 → 差额自动生成「余额变更」补平 |
Money Mirror(本项目独有):在净资产曲线上标记决策事件——冲动买入、校准、里程碑,点开能看到当时的决策理由。账本记「钱发生了什么」,这里记「你对钱做了什么决定」。
可选的第三块面:每次记账同时往一份 Markdown 月度笔记里追加一行并重算月度汇总,适合 Obsidian / Logseq 用户(config.MD_LEDGER_DIR 设为 None 即关闭)。
git clone https://github.com/<your-name>/MoneyMirror.git
cd MoneyMirror
python3 -m pip install --user flask
cp config.example.py config.py # 填你的 Base token、表 ID、字段名
cp .env.example .env # 填网页登录账密 + 飞书应用凭证
chmod 600 .env
python3 sync.py # 首次把飞书数据照进本地镜像
python3 app.py # 打开 http://127.0.0.1:5001- 飞书自建应用凭证(推荐):在 飞书开放平台 创建自建应用 → 开通
bitable:app权限 → 发布 → 把 App ID / Secret 填进.env→ 在你的多维表格里把这个应用加为协作者。 - lark-cli 用户身份:
.env里凭证留空即可,代码自动回退到调用本机 lark-cli(适合本地开发,不适合无人值守服务器)。
你的多维表格需要这些表(字段名可以随你叫什么,在 config.py 里映射即可)。最小可用只需 accounts + transactions,其余表在 config.TABLES 里删掉或留占位符即可。
accounts(科目账户):账户名、类型、当前余额、归属
当前余额建议做成公式:期初 + 收入 − 支出 + 转入 − 转出 + 余额变更——负债账户天然为负,无需任何特判归属建议做成公式,把账户分成 资产 / 负债 / 受限(如企业福利账户这类不计入净资产的受限资金)
transactions(交易流水):日期、类型、金额、账户(关联)、转入账户(关联)、分类、备注
- 类型四选一:支出 / 收入 / 转账 / 余额变更
- 金额恒为正数,方向由类型决定(余额变更例外,可为负)
- 转账 = 一条记录带两个关联字段(转出腿 + 转入腿),比全复式记账轻量得多
其余表(预算、持仓、快照、指标、对账记录、决策事件、缴费计划)字段见 config.example.py 注释。
金额一律以整数分存储,比对四舍五入到分(ROUND_HALF_UP,不用银行家舍入)——浮点数不配管钱。
macOS 机器上一条命令(launchd 常驻,开机自启 + 崩溃自动拉起):
MM_HOST=user@server.local MM_DEST=/Users/user/MoneyMirror bash deploy/deploy.sh脚本会检查凭证完整性、清理端口占用、注册服务、建立镜像并做健康检查——任何一步不对就中止,不会假装部署成功。
iOS 捷径「获取 URL 内容」直接 POST 记账:
- URL
http://<服务器>:5001/add,方法 POST,请求体选「表单」 - 字段:
type/amount/account(可直接写账户名)/category/note - 头部:
Authorization: Basic <base64(用户名:密码)>
已经有别的记账机器人?让它记完后 POST 一下 /sync 即可让网页立刻跟上(不加也行,后台每 10 分钟自动同步)。
这个项目默认只在局域网里跑,不要暴露到公网。
已实现:全站 Basic Auth(含静态文件;未配置凭证时直接 503 拒绝服务而非裸奔)、CSRF 防护(Origin 校验 + 表单令牌,非浏览器客户端如捷径不受影响)、SQL 全参数化、数据库只读打开、record_id 白名单校验、Markdown 写入消毒。
已知取舍:明文 HTTP,Basic Auth 防误入不防嗅探。要外网访问请自行加 TLS 或用 Tailscale 这类方案。
界面用 Fraunces(SIL Open Font License)。仓库里不含字体文件,请自行下载放到 static/fonts/fraunces.woff2——不放也能跑,会回退到系统衬线体。
Python 3.9+ / Flask / sqlite3(标准库)/ Jinja2 / ECharts。无 npm、无构建步骤、无前端框架。
MIT