# mycash

个人记账。电脑和手机打开的是同一份账，全部跑在 Cloudflare 上：页面是 Vite + Vue 3，接口是 Pages Functions 里的 Hono，数据在 D1。不需要阿里云、不需要 MySQL。

金额在库里用「分」保存。时区按东八区。

## 账是怎么记的

注册登录之后，每个人一份账。第一个注册的账号会接手库里还没归属的旧数据，之后注册的是空账本。

日常记账：

- 正数是收入，负数是支出
- 分类两级。一级是固定的：收入分「工资类 / 非工资类 / 活动收入」，支出分「生活支出 / 套现支出」
- 记一笔只选二级。可以拖动二级分类改变顺序
- 「活动收入」不出现在记一笔里，到「总览 · 活动」按月填写，保存后记在该月最后一天
- 某月结余 = 收入 − 支出。活动收入算进收入，但不按天列在流水里

信用卡：

- 不做账单日。欠款由流水算出来，不单独改余额
- 添加银行时填的当前欠款，会记成一笔「期初欠款」（负数）
- 之后记账：正数是还款，欠款减少；负数是新增欠款，欠款增加
- 某银行欠款 = 该行全部流水金额之和的相反数
- 总欠款 = 各银行欠款相加。还多了会显示成负数，表示溢缴

例如期初欠 10000，还款 2000，再新增 500，当前欠款是 8500。

总览、工资、非工资都按这一年的流水汇总，不再使用写死的年度表格。

## 目录

```
web/                 Vue 页面，构建结果在 web/dist
functions/api/       Pages Functions 入口（Cloudflare 只认项目根目录的 functions）
api/                 Hono 路由和记账逻辑，其中 api/db.ts 是 D1 访问
migrations/          D1 建表
wrangler.toml        绑定 D1，pages_build_output_dir = web/dist
```

## 本地运行

需要 Node.js 20 以上。

```bash
npm install
npm run icons
npm run dev
```

`npm run dev` 会同时做两件事：

1. Vite 开发页：http://127.0.0.1:5173 （改页面用这个，接口会代理到下面的 wrangler）
2. `wrangler pages dev`：http://127.0.0.1:8788 （和线上一样，页面和 `/api` 在同一个地址）

第一次会把迁移应用到本地 D1。数据在 `.wrangler/`，不要提交。

只重建本地表：

```bash
npm run db:migrate
```

金额和月份的小测试：

```bash
npm test
```

## 部署到 Cloudflare Pages

域名已经在 Cloudflare 账号里时，不需要再做证书。Pages 绑自定义域名会自动写 DNS。

1. 登录：

```bash
npx wrangler login
```

2. 创建 D1，把返回的 `database_id` 填进 [wrangler.toml](wrangler.toml)，替换现在的占位 id：

```bash
npx wrangler d1 create mycash
```

3. 在远端建表：

```bash
npm run db:migrate:remote
```

4. 发布页面和接口：

```bash
npm run deploy
```

5. 绑定域名。在 Cloudflare 控制台打开 **Workers & Pages → mycash → Custom domains**，添加你的域名，例如 `cash.example.com`。账号里已经托管这个域名时，保存后等一两分钟即可用 HTTPS 打开。

也可以用命令：

```bash
npx wrangler pages project create mycash
npx wrangler pages deployment tail
```

更新时重新执行 `npm run deploy`。浏览器下次打开会拿到新页面。

安装到桌面：安卓 Chrome、电脑 Chrome / Edge 可以安装。iPhone 用 Safari 的分享菜单，选「添加到主屏幕」。

## 备份

导出整库（需要先装好 wrangler 并登录）：

```bash
npx wrangler d1 export mycash --remote --output mycash.sql
```

恢复到一个空库时，把 SQL 再导回去。导出文件以后如果要放到对象存储，再绑 R2，这一版先只放在 D1。

## 以后加菜单

页面菜单在 [web/src/menus.ts](web/src/menus.ts)。加一项，并配上对应页面即可。
