docs: 新增日历页文档并补充记账直接新建分类/标签/渠道说明

补上此前已完成但未提交的文档更新:新增「日历」页面使用文档,并把登录后默认落地页由统计面板调整为日历,同步页面流程与偏好说明;同时补充记账弹窗内可直接新建分类/标签/渠道的说明,并登记相应截图场景。

变更内容:
- 新增 guide/calendar.md,并在 .vitepress/config.mts 侧边栏与 guide/pages.md、guide/index.md 登记日历页
- index.md、guide/getting-started.md、guide/dashboard.md、guide/pages.md 同步日历为登录后默认落地页与页面流程
- dev/preferences.md 新增日历偏好 ledgerly.calendar.view/year/month/statsScope 说明
- guide/transactions.md 补充记账弹窗内直接新建分类/标签/渠道的说明,guide/ai.md、guide/categories-tags.md、guide/channels.md 同步相关描述
- scripts/ts/capture-all.ts、capture-pages.ts、capture-elements.ts 增加日历与新建分类等截图场景,captureModals 支持按场景过滤
This commit is contained in:
2026-10-13 12:52:08 +08:00
parent 4425a6ba04
commit b1fb2c68a9
16 changed files with 263 additions and 21 deletions
+2 -1
View File
@@ -9,7 +9,7 @@ export default defineConfig({
cleanUrls: true, cleanUrls: true,
ignoreDeadLinks: true, ignoreDeadLinks: true,
// 维护类文档不参与站点构建 // 维护类文档不参与站点构建
srcExclude: ['AGENTS.md'], srcExclude: ['AGENTS.md', 'todo.md'],
// 文档站默认端口从 5173 调整为 5175,把 5173 让给 ledgerly 前端 // 文档站默认端口从 5173 调整为 5175,把 5173 让给 ledgerly 前端
vite: { vite: {
server: { server: {
@@ -31,6 +31,7 @@ export default defineConfig({
{ text: '项目简介', link: '/guide/introduction' }, { text: '项目简介', link: '/guide/introduction' },
{ text: '快速开始', link: '/guide/getting-started' }, { text: '快速开始', link: '/guide/getting-started' },
{ text: '下载与安装', link: '/guide/download' }, { text: '下载与安装', link: '/guide/download' },
{ text: '日历', link: '/guide/calendar' },
{ text: '统计面板', link: '/guide/dashboard' }, { text: '统计面板', link: '/guide/dashboard' },
{ text: '页面总览', link: '/guide/pages' }, { text: '页面总览', link: '/guide/pages' },
], ],
+16
View File
@@ -33,6 +33,10 @@
| 键名 | 偏好内容 | 文件 | 保存时机 | 读取时机 | | 键名 | 偏好内容 | 文件 | 保存时机 | 读取时机 |
|---|---|---|---|---| |---|---|---|---|---|
| `ledgerly.locale` | 界面语言 `zh-CN`/`en-US`/`ja-JP` | `locales/index.ts` | 切换语言 | 模块初始化 | | `ledgerly.locale` | 界面语言 `zh-CN`/`en-US`/`ja-JP` | `locales/index.ts` | 切换语言 | 模块初始化 |
| `ledgerly.calendar.view` | 日历视图 `month`/`year` | `views/Calendar.vue` | `useStringPreference` 自动 | 组件初始化 |
| `ledgerly.calendar.year` | 日历最近浏览年份(四位数字符串) | `views/Calendar.vue` | 变量 `watch` 自动 | 组件初始化 |
| `ledgerly.calendar.month` | 日历月视图最近浏览月份(`1`-`12`) | `views/Calendar.vue` | 变量 `watch` 自动 | 组件初始化 |
| `ledgerly.calendar.statsScope` | 日历统计口径 `INCLUDED`/`ALL`/`EXCLUDED` | `views/Calendar.vue` | `useStringPreference` 自动 | 组件初始化 |
| `ledgerly.dashboard.prefs` | 统计面板时间范围、粒度与多项筛选 | `views/Dashboard.vue` | 变量 `watch` 自动 | `onMounted` | | `ledgerly.dashboard.prefs` | 统计面板时间范围、粒度与多项筛选 | `views/Dashboard.vue` | 变量 `watch` 自动 | `onMounted` |
| `ledgerly.transaction.filterPrefs` | 收支列表筛选、分页、排序 | `views/TransactionList.vue` | 变量 `watch` 自动 | `onMounted` | | `ledgerly.transaction.filterPrefs` | 收支列表筛选、分页、排序 | `views/TransactionList.vue` | 变量 `watch` 自动 | `onMounted` |
| `ledgerly.transaction.aiScope` | 批量 AI 建议范围 | `views/TransactionList.vue` | 变量 `watch` 自动 | ref 初始化 | | `ledgerly.transaction.aiScope` | 批量 AI 建议范围 | `views/TransactionList.vue` | 变量 `watch` 自动 | ref 初始化 |
@@ -79,6 +83,18 @@
- **目的**:记住用户语言选择,应用启动与切换即时生效。 - **目的**:记住用户语言选择,应用启动与切换即时生效。
- **入口**:`components/LocaleSwitch.vue`。 - **入口**:`components/LocaleSwitch.vue`。
### 日历偏好 `ledgerly.calendar.view` / `ledgerly.calendar.year` / `ledgerly.calendar.month` / `ledgerly.calendar.statsScope`
- **文件**:`frontend/src/views/Calendar.vue`
- **取值**:
- `ledgerly.calendar.view`:`month`(月视图,默认)/ `year`(年视图);非法值回退 `month`。
- `ledgerly.calendar.year`:最近浏览的年份(四位数字符串),月视图面板年份与年视图年份共用;非法值回退当前年。
- `ledgerly.calendar.month`:月视图最近浏览的月份(`1`-`12`);非法值回退当前月。
- `ledgerly.calendar.statsScope`:`INCLUDED`(仅计入统计,默认)/ `ALL`(全部记录)/ `EXCLUDED`(仅不计入);非法值回退 `INCLUDED`。
- **读取**:组件初始化时经 `useStringPreference` 读取;URL 中的 `view`/`y`/`m`(如 `?view=year&y=2026`)优先于偏好,无参数时按偏好恢复上次视图、年月与统计口径。
- **保存**:`view`/`statsScope` 由 `useStringPreference` 内部 `watch` 自动写入;`year`/`month` 由组件内 `watch(panelYear/panelMonth)`(月视图)与 `watch(yearViewYear)`(年视图)写入。
- **目的**:下次进入日历自动还原上次的月/年视图、年月与统计口径。
### 统计面板偏好 `ledgerly.dashboard.prefs` ### 统计面板偏好 `ledgerly.dashboard.prefs`
- **文件**:`frontend/src/views/Dashboard.vue`(键名第 470 行) - **文件**:`frontend/src/views/Dashboard.vue`(键名第 470 行)
+2 -1
View File
@@ -55,6 +55,7 @@ API Key 仅保存在本地数据库中,仅用于向你配置的接口地址发
| 统计搜索 | 统计面板 → AI 搜索 | 自然语言解析为统计筛选条件与维度 | | 统计搜索 | 统计面板 → AI 搜索 | 自然语言解析为统计筛选条件与维度 |
| 生成关系名称 | 收支记录 → 账单关系 → AI 生成 | 依据关联账单的类型、渠道、分类与备注生成关系名称与备注 | | 生成关系名称 | 收支记录 → 账单关系 → AI 生成 | 依据关联账单的类型、渠道、分类与备注生成关系名称与备注 |
| 智能查数 | 左侧菜单 → 智能查数 | 自然语言转只读 SQL 查询并展示结果 | | 智能查数 | 左侧菜单 → 智能查数 | 自然语言转只读 SQL 查询并展示结果 |
| 手动新建分类/标签/渠道 | 新增/编辑记录 → 新建分类 / 新建标签 / 新建渠道 | 不依赖 AI,直接创建并选中(始终可用) |
## 分类与标签建议 ## 分类与标签建议
@@ -128,5 +129,5 @@ API Key 仅保存在本地数据库中,仅用于向你配置的接口地址发
## 说明 ## 说明
- AI 建议结果仅供参考,应用前可逐条取消勾选。 - AI 建议结果仅供参考,应用前可逐条取消勾选。
- 关闭「启用 AI 建议」后,系统不会发起任何 AI 请求,相关入口也会隐藏。 - 关闭「启用 AI 建议」后,系统不会发起任何 AI 请求,相关入口也会隐藏(分类/标签/渠道的**手动新建**入口不受影响,始终可用)。
- 账单类型识别(邮箱账单)使用的是**发件人规则**而非 AI,结果更确定、可预期。 - 账单类型识别(邮箱账单)使用的是**发件人规则**而非 AI,结果更确定、可预期。
+66
View File
@@ -0,0 +1,66 @@
# 日历
「日历」是登录后的默认首页,用月视图与年视图直观查看每天的收支情况。左侧菜单默认置于首项,访问 `/` 也会自动进入本页。
![日历(月视图)](https://adcarac.oss-cn-beijing.aliyuncs.com/finance-app-docs/screenshots/calendar.png)
## 月视图
- 每天展示当天**收入**(绿色,`+`)、**支出**(红色,`-`)与**结余**;同一天既有收入又有支出时显示三行,否则只显示对应的一侧。
- **今天**以高亮标记;点击网格中相邻月份的灰色日期会自动切换到该月。
- 顶部四张卡片显示**当月合计**:总收入、总支出、结余、交易笔数。
## 切换月份与视图
表头提供:
- 「‹」「›」:切换上一月 / 下一月(年视图下为上一年 / 下一年);
- **年份 / 月份下拉**:直接跳转到任意年月;
- **今天**:回到当前月并选中今天;
- **月视图 / 年视图**:切换视图。
## 年视图
年视图以 12 个月的卡片展示每月收入、支出与结余,无数据的月份显示「无数据」,当前月高亮。点击任意月份卡片即可进入该月的月视图。
![日历年视图](https://adcarac.oss-cn-beijing.aliyuncs.com/finance-app-docs/screenshots/elements/calendar-year.png)
某一年完全没有数据时,会显示「本年暂无交易数据」的空状态提示。
## 统计口径
表头的「**统计口径**」下拉控制参与汇总的记录范围:
| 选项 | 含义 |
|---|---|
| 仅计入统计(默认) | 只统计「计入统计」的记录 |
| 全部记录 | 计入与不计入的记录都统计 |
| 仅不计入 | 只统计「不计入统计」的记录 |
切换后日历中的金额、顶部合计与点击日期弹出的**当日明细**都会随之变化:明细只列出符合当前口径的记录,与汇总口径保持一致。
## 查看某天的明细
点击日历中的某一天,会弹出当天的**交易明细浮窗**:
- 顶部显示**当日合计**(收入 / 支出 / 结余);
- 下方逐条列出当天交易,每条在主行显示时间、分类、渠道与**金额**(收绿支红);
- 点击任意条目可打开该笔账单的**完整详情**(标签、账单关系、来源图片、原始数据等,为只读);
- 底部「**在收支记录中查看**」会携带当天日期与当前统计口径跳转到[收支记录](/guide/transactions),便于继续编辑整理。
![当日明细浮窗](https://adcarac.oss-cn-beijing.aliyuncs.com/finance-app-docs/screenshots/elements/calendar-day-detail.png)
> 当日明细(按当前统计口径)最多展示前 50 条,超出时浮窗内会提示总数,可点「在收支记录中查看」查看全部。
## 链接分享与偏好
- 当前视图与年月会同步到地址栏(形如 `?view=month&y=2026&m=9`),刷新页面或把链接分享给他人,都能还原到对应月份与视图。
- **视图**(月 / 年)、**统计口径**与**最近浏览的年月**会被记住,下次进入自动还原;地址栏带参数时以参数为准。
## 小技巧
- 想知道某一天具体花在哪,直接点该日期,先看当日合计,再逐条核对明细。
- 想看全年的分布,切到「年视图」浏览各月汇总,再点开支出最高的月份查看当天明细。
- 不计入统计的记录(如借款、账户间转账)默认不参与汇总,当日明细也不会列出;如需一并查看,把统计口径切换为「全部记录」。
> 想从更大的时间跨度看趋势与占比,可使用[统计面板](/guide/dashboard)的图表与筛选。
+1
View File
@@ -53,3 +53,4 @@
- 建议为以下场景建立标签:报销/待报销、旅行、大额消费、订阅、礼物、家庭、工作等。 - 建议为以下场景建立标签:报销/待报销、旅行、大额消费、订阅、礼物、家庭、工作等。
- 需要按规则自动归类时,配合[规则管理](/guide/rules)使用:规则命中后会自动应用分类与标签。 - 需要按规则自动归类时,配合[规则管理](/guide/rules)使用:规则命中后会自动应用分类与标签。
- 分类与标签都支持在[账单导入](/guide/transactions)预览阶段批量指定为默认值。 - 分类与标签都支持在[账单导入](/guide/transactions)预览阶段批量指定为默认值。
- 在[新增/编辑记录](/guide/transactions#手动添加记录)弹窗中,可直接点分类/标签行右侧的「新建分类」「新建标签」创建并选用,无需先到本页维护。
+1 -1
View File
@@ -55,7 +55,7 @@
自定义渠道创建后,可在以下场景直接选用: 自定义渠道创建后,可在以下场景直接选用:
- **新增 / 编辑记录**:交易渠道下拉中出现在内置渠道之后。 - **新增 / 编辑记录**:交易渠道下拉中出现在内置渠道之后;也可点右侧「新建渠道」直接创建并选用(不受 AI 状态影响)。
- **筛选与统计**:收支记录页筛选、统计面板的渠道维度与筛选均可选择自定义渠道,图表与分组会展示其名称。 - **筛选与统计**:收支记录页筛选、统计面板的渠道维度与筛选均可选择自定义渠道,图表与分组会展示其名称。
- **AI 能力**:智能查询、统计搜索与智能记账会把当前账号的自定义渠道一并作为可选渠道;新增/编辑记录时还可用「渠道 · AI 推荐」选择已有渠道,或「渠道 · AI 新建」由描述生成并创建渠道。 - **AI 能力**:智能查询、统计搜索与智能记账会把当前账号的自定义渠道一并作为可选渠道;新增/编辑记录时还可用「渠道 · AI 推荐」选择已有渠道,或「渠道 · AI 新建」由描述生成并创建渠道。
- **导出**:Excel 导出时渠道列展示自定义渠道名称。 - **导出**:Excel 导出时渠道列展示自定义渠道名称。
+3 -1
View File
@@ -1,6 +1,6 @@
# 统计面板 # 统计面板
「统计面板」是登录后的默认首页,用于查看指定时间范围内的收支汇总与图表。 「统计面板」用于查看指定时间范围内的收支汇总与图表,可从左侧菜单进入(登录后的默认首页为[日历](/guide/calendar))。
![统计面板](https://adcarac.oss-cn-beijing.aliyuncs.com/finance-app-docs/screenshots/dashboard.png) ![统计面板](https://adcarac.oss-cn-beijing.aliyuncs.com/finance-app-docs/screenshots/dashboard.png)
@@ -77,6 +77,8 @@
无论从哪张图下钻,都会同时保留面板当前的统计口径、标签、金额区间与备注关键字等筛选。 无论从哪张图下钻,都会同时保留面板当前的统计口径、标签、金额区间与备注关键字等筛选。
> 触屏设备上,点击趋势柱或饼图扇区会先弹出确认气泡(「查看明细」/「取消」),确认后才跳转,避免滑动或误触直接跳走;趋势图的**「整列可点」在触屏端禁用**,只能点击柱子本体。桌面端行为不变。
![点击趋势柱状图跳转收支记录](https://adcarac.oss-cn-beijing.aliyuncs.com/finance-app-docs/screenshots/elements/dashboard-trend-jump.png) ![点击趋势柱状图跳转收支记录](https://adcarac.oss-cn-beijing.aliyuncs.com/finance-app-docs/screenshots/elements/dashboard-trend-jump.png)
页面底部的「**查看收支记录**」按钮则会携带**当前全部筛选条件**跳转,便于核对整体明细。 页面底部的「**查看收支记录**」按钮则会携带**当前全部筛选条件**跳转,便于核对整体明细。
+2 -1
View File
@@ -52,7 +52,7 @@
## 首次使用建议 ## 首次使用建议
1. 完成数据库配置并注册登录。 1. 完成数据库配置并注册登录。登录后默认进入[日历](/guide/calendar),可先熟悉按天查看收支的用法。
2. 进入「分类管理」「标签管理」按自己的习惯调整分类与标签。 2. 进入「分类管理」「标签管理」按自己的习惯调整分类与标签。
3. 在「规则管理」配置常用自动归类规则(如「星巴克 → 餐饮」)。 3. 在「规则管理」配置常用自动归类规则(如「星巴克 → 餐饮」)。
4. 导出并导入历史账单(见[账单类型与获取](/guide/bills/overview))。 4. 导出并导入历史账单(见[账单类型与获取](/guide/bills/overview))。
@@ -61,6 +61,7 @@
## 下一步 ## 下一步
- [日历](/guide/calendar):登录后的默认首页,按天查看每日收支
- [统计面板](/guide/dashboard) - [统计面板](/guide/dashboard)
- [收支记录](/guide/transactions) - [收支记录](/guide/transactions)
- [账单导入](/guide/transactions) - [账单导入](/guide/transactions)
+1
View File
@@ -7,6 +7,7 @@
- [项目简介](/guide/introduction):系统定位、核心功能与技术栈 - [项目简介](/guide/introduction):系统定位、核心功能与技术栈
- [快速开始](/guide/getting-started):数据库配置、注册登录、界面语言与首次使用建议 - [快速开始](/guide/getting-started):数据库配置、注册登录、界面语言与首次使用建议
- [下载与安装](/guide/download):Windows / Linux 安装包与可执行 jar 的下载、运行与校验 - [下载与安装](/guide/download):Windows / Linux 安装包与可执行 jar 的下载、运行与校验
- [日历](/guide/calendar):按天查看每日收支、月视图与年视图、当日明细
- [统计面板](/guide/dashboard):时间范围、筛选条件与图表说明 - [统计面板](/guide/dashboard):时间范围、筛选条件与图表说明
## 记账与整理 ## 记账与整理
+1
View File
@@ -18,6 +18,7 @@
| 收支记录 | 增删改查、分页与多条件筛选、批量设置分类/标签、批量删除、计入统计开关、备注隐藏、导出 Excel | | 收支记录 | 增删改查、分页与多条件筛选、批量设置分类/标签、批量删除、计入统计开关、备注隐藏、导出 Excel |
| 分类与标签 | 收入/支出分类与标签的增删改查,新用户自动获得默认数据,AI 推荐 Emoji 与颜色 | | 分类与标签 | 收入/支出分类与标签的增删改查,新用户自动获得默认数据,AI 推荐 Emoji 与颜色 |
| 交易渠道 | 内置渠道 + 自定义渠道的新建/改名/删除,改名不影响历史账单 | | 交易渠道 | 内置渠道 + 自定义渠道的新建/改名/删除,改名不影响历史账单 |
| 日历 | 默认首页,月视图按天展示每日收支与当月合计,年视图一览全年各月,支持统计口径过滤与当日明细下钻 |
| 统计图表 | 月度收支、分类占比、收支趋势、交易渠道占比,支持按日/周/月/季/年粒度,图表可点击下钻对应明细 | | 统计图表 | 月度收支、分类占比、收支趋势、交易渠道占比,支持按日/周/月/季/年粒度,图表可点击下钻对应明细 |
| 账单关系 | 父子/同级多笔账单关联、自动绘制关系图,AI 生成关系名称与备注 | | 账单关系 | 父子/同级多笔账单关联、自动绘制关系图,AI 生成关系名称与备注 |
| 账单导入 | 七类账单解析、zip 解密、解析预览、按交易号去重、规则建议 | | 账单导入 | 七类账单解析、zip 解密、解析预览、按交易号去重、规则建议 |
+6 -3
View File
@@ -9,7 +9,8 @@
| 登录 | `/login` | 用户名密码登录 | 未登录访问受保护页面时自动跳转 | | 登录 | `/login` | 用户名密码登录 | 未登录访问受保护页面时自动跳转 |
| 注册 | `/register` | 创建账号 | 登录页「没有账号?去注册」(注册开启时) | | 注册 | `/register` | 创建账号 | 登录页「没有账号?去注册」(注册开启时) |
| 数据库初始化 | `/database-setup` | 首次配置数据库 | 数据库未配置时自动引导 | | 数据库初始化 | `/database-setup` | 首次配置数据库 | 数据库未配置时自动引导 |
| 统计面板 | `/dashboard` | 收支汇总与图表 | 登录后默认页;左侧菜单 | | 日历 | `/calendar` | 每日收支日历、月/年视图与当日明细 | **登录后默认页**;左侧菜单(默认置顶) |
| 统计面板 | `/dashboard` | 收支汇总与图表 | 左侧菜单 |
| 智能查数 | `/smart-query` | 自然语言转只读 SQL 查询 | 左侧菜单(**AI 启用时**) | | 智能查数 | `/smart-query` | 自然语言转只读 SQL 查询 | 左侧菜单(**AI 启用时**) |
| 收支记录 | `/transactions` | 记录管理与**账单导入** | 左侧菜单 | | 收支记录 | `/transactions` | 记录管理与**账单导入** | 左侧菜单 |
| 分类管理 | `/categories` | 收入/支出分类维护 | 左侧菜单 | | 分类管理 | `/categories` | 收入/支出分类维护 | 左侧菜单 |
@@ -28,7 +29,7 @@
### 左侧菜单 ### 左侧菜单
统计面板 → 智能查数(AI 启用时)→ 收支记录 → 分类管理 → 标签管理 → 规则管理 → 邮箱账单 日历 → 统计面板 → 智能查数(AI 启用时)→ 收支记录 → 分类管理 → 标签管理 → 规则管理 → 邮箱账单
左侧菜单的**顺序与显隐可自定义**(设置 → 导航设置),并在下次进入时还原。 左侧菜单的**顺序与显隐可自定义**(设置 → 导航设置),并在下次进入时还原。
@@ -44,7 +45,8 @@
## 典型跳转路径 ## 典型跳转路径
- **首次使用**:`/database-setup` → `/register` → `/login` → `/dashboard` - **首次使用**:`/database-setup` → `/register` → `/login` → `/calendar`
- **日历看某天**:日历 → 点击某天 → 当日明细浮窗(按当前统计口径)→ 点条目查看账单详情 / 点「在收支记录中查看」跳转收支记录(按当日筛选并沿用统计口径)
- **手动记账**:收支记录 → 点击「新增记录」→ 表单弹窗 → 保存 - **手动记账**:收支记录 → 点击「新增记录」→ 表单弹窗 → 保存
- **查看趋势明细**:统计面板 → 点击趋势柱、分类/渠道饼图或「查看收支记录」→ 收支记录(自动带入对应筛选条件) - **查看趋势明细**:统计面板 → 点击趋势柱、分类/渠道饼图或「查看收支记录」→ 收支记录(自动带入对应筛选条件)
- **反向跳转**:收支记录 → 点击「查看统计」→ 统计面板(还原当前筛选条件) - **反向跳转**:收支记录 → 点击「查看统计」→ 统计面板(还原当前筛选条件)
@@ -60,6 +62,7 @@
## 页面关系说明 ## 页面关系说明
- **日历**是登录后的默认落地页:按天查看每日收支、切换月/年视图与统计口径,并可点击某天下钻到当日明细与账单详情。
- **收支记录**是核心页面:手动记账、账单导入、批量操作、账单关系与 AI 能力都从这里进入,导入完成后也回到该页查看。 - **收支记录**是核心页面:手动记账、账单导入、批量操作、账单关系与 AI 能力都从这里进入,导入完成后也回到该页查看。
- **账单导入**有两条独立路径: - **账单导入**有两条独立路径:
- 收支记录页的「导入账单」**弹窗**(桌面端常用); - 收支记录页的「导入账单」**弹窗**(桌面端常用);
+15 -3
View File
@@ -178,18 +178,28 @@
| 字段 | 说明 | | 字段 | 说明 |
|---|---| |---|---|
| 类型 | 支出 / 收入 | | 类型 | 支出 / 收入 |
| 分类 | 新增时必填 | | 分类 | 新增时必填;可点右侧「新建分类」直接创建 |
| 金额 | 大于 0 | | 金额 | 大于 0 |
| 交易渠道 | 可选,含内置渠道与[自定义渠道](/guide/channels);启用 AI 时可一键推荐或新建 | | 交易渠道 | 可选,含内置渠道与[自定义渠道](/guide/channels);可点右侧「新建渠道」直接创建;启用 AI 时可一键推荐或新建 |
| 交易时间 | 默认当前时间 | | 交易时间 | 默认当前时间 |
| 备注 | 可选 | | 备注 | 可选 |
| 标签 | 可选,可多选 | | 标签 | 可选,可多选;可点右侧「新建标签」直接创建 |
| 计入统计 | 默认开启;关闭后不纳入统计 | | 计入统计 | 默认开启;关闭后不纳入统计 |
3. 点击「确定」保存。 3. 点击「确定」保存。
![新增记录弹窗](https://adcarac.oss-cn-beijing.aliyuncs.com/finance-app-docs/screenshots/elements/add-record.png) ![新增记录弹窗](https://adcarac.oss-cn-beijing.aliyuncs.com/finance-app-docs/screenshots/elements/add-record.png)
::: tip 记账时直接新建分类 / 标签 / 渠道
新增与编辑弹窗中,**分类**、**标签**、**交易渠道** 三行在选择框右侧各有一个「**新建分类 / 新建标签 / 新建渠道**」按钮,**不受 AI 启用状态影响**,随时可用。点击后弹出精简表单,创建完成即自动填入当前账单:
- **新建分类**:填写名称、类型(默认跟随当前账单类型)与图标;创建后自动选中,并把账单类型同步为该分类的类型。
- **新建标签**:填写名称与颜色;创建后自动追加到已选标签。
- **新建渠道**:填写名称;创建后自动选中。
![记账弹窗内新建分类](https://adcarac.oss-cn-beijing.aliyuncs.com/finance-app-docs/screenshots/elements/record-new-category.png)
:::
## 编辑记录 ## 编辑记录
在记录行点击「编辑」即可修改记录,弹窗字段与新增一致;编辑时允许不设置分类。 在记录行点击「编辑」即可修改记录,弹窗字段与新增一致;编辑时允许不设置分类。
@@ -212,6 +222,8 @@
![编辑记录中的渠道 AI 辅助](https://adcarac.oss-cn-beijing.aliyuncs.com/finance-app-docs/screenshots/elements/ai-channel-suggest.png) ![编辑记录中的渠道 AI 辅助](https://adcarac.oss-cn-beijing.aliyuncs.com/finance-app-docs/screenshots/elements/ai-channel-suggest.png)
> 「AI 新建」需先填写备注或金额,便于模型理解;生成结果会显示确认条,点击「保存并选用」才真正创建。 > 「AI 新建」需先填写备注或金额,便于模型理解;生成结果会显示确认条,点击「保存并选用」才真正创建。
>
> 上述 AI 辅助按钮仅在[启用 AI](/guide/ai)后出现;**分类、标签、交易渠道三行始终各有一个手动「新建」按钮**(不受 AI 状态影响),可直接填写并创建,详见[手动添加记录](#手动添加记录)中的说明。
编辑完成后点击「确定」保存。其他 AI 能力(批量建议、智能记账、智能查询)见 [AI 能力](/guide/ai)。 编辑完成后点击「确定」保存。其他 AI 能力(批量建议、智能记账、智能查询)见 [AI 能力](/guide/ai)。
+5 -3
View File
@@ -6,8 +6,8 @@ hero:
text: 个人收支管理 · 多来源账单导入 · AI 智能记账 text: 个人收支管理 · 多来源账单导入 · AI 智能记账
tagline: 支持支付宝、微信、美团、淘宝、京东、招商银行、交通银行账单导入,提供分类标签与交易渠道管理、自定义规则、账单关系、AI 建议(含多图图片记账与智能查数)与定时提醒 tagline: 支持支付宝、微信、美团、淘宝、京东、招商银行、交通银行账单导入,提供分类标签与交易渠道管理、自定义规则、账单关系、AI 建议(含多图图片记账与智能查数)与定时提醒
image: image:
src: https://adcarac.oss-cn-beijing.aliyuncs.com/finance-app-docs/screenshots/dashboard.png src: https://adcarac.oss-cn-beijing.aliyuncs.com/finance-app-docs/screenshots/calendar.png
alt: 统计面板 alt: 日历
actions: actions:
- theme: brand - theme: brand
text: 使用文档 text: 使用文档
@@ -32,6 +32,8 @@ features:
details: 按关键词、收支类型、金额区间组合条件,命中后自动应用分类与标签,导入预览即展示建议。 details: 按关键词、收支类型、金额区间组合条件,命中后自动应用分类与标签,导入预览即展示建议。
- title: AI 智能能力 - title: AI 智能能力
details: 基于 DeepSeek 的分类/标签/渠道建议、自然语言查询与查数(智能查数)、文字与多图图片记账(实时进度)、分类标签渠道生成、关系命名,并统计 token 用量。 details: 基于 DeepSeek 的分类/标签/渠道建议、自然语言查询与查数(智能查数)、文字与多图图片记账(实时进度)、分类标签渠道生成、关系命名,并统计 token 用量。
- title: 日历视图
details: 默认首页,月视图按天展示每日收支与当月合计,年视图一览全年各月;点击某天查看当日明细并直达账单详情,支持统计口径过滤。
- title: 统计与图表 - title: 统计与图表
details: 月度收支汇总、分类占比、收支趋势、交易渠道占比,支持多维度筛选与自定义时间范围,图表可点击下钻明细。 details: 月度收支汇总、分类占比、收支趋势、交易渠道占比,支持多维度筛选与自定义时间范围,图表可点击下钻明细。
- title: 定时提醒与通知 - title: 定时提醒与通知
@@ -59,7 +61,7 @@ features:
- 想开始使用:[快速开始](/guide/getting-started) - 想开始使用:[快速开始](/guide/getting-started)
- 想知道各类账单怎么导出:[账单类型与获取](/guide/bills/overview) - 想知道各类账单怎么导出:[账单类型与获取](/guide/bills/overview)
- 想了解各功能怎么用:[统计面板](/guide/dashboard) 起逐页阅读 - 想了解各功能怎么用:[日历](/guide/calendar) 起逐页阅读
- 遇到问题:[常见问题](/guide/faq) - 遇到问题:[常见问题](/guide/faq)
### 开发文档 ### 开发文档
+6 -1
View File
@@ -5,7 +5,7 @@
// - scripts/samples/alipay_sample.zip 样例账单存在。 // - scripts/samples/alipay_sample.zip 样例账单存在。
import { mkdir } from 'node:fs/promises' import { mkdir } from 'node:fs/promises'
import { injectSession, launchBrowser, login, newContext } from './browser.js' import { injectSession, launchBrowser, login, newContext } from './browser.js'
import { captureAiRule, captureBillParse, captureCards, captureEditRecord, captureModals, captureSettingsPanels, captureTrendJump } from './capture-elements.js' import { captureAddRecord, captureAiRule, captureBillParse, captureCalendarDetail, captureCalendarMonth, captureCalendarYear, captureCards, captureEditRecord, captureInlineCreate, captureModals, captureSettingsPanels, captureTrendJump } from './capture-elements.js'
import { capturePages } from './capture-pages.js' import { capturePages } from './capture-pages.js'
import { ELEM_DIR } from './config.js' import { ELEM_DIR } from './config.js'
@@ -25,8 +25,13 @@ async function main(): Promise<void> {
await injectSession(context, token) await injectSession(context, token)
const page = await context.newPage() const page = await context.newPage()
await capturePages(page) await capturePages(page)
await captureCalendarMonth(page)
await captureCalendarYear(page)
await captureCalendarDetail(page)
await captureAddRecord(page)
await captureModals(page) await captureModals(page)
await captureEditRecord(page) await captureEditRecord(page)
await captureInlineCreate(page)
await captureAiRule(page) await captureAiRule(page)
await captureSettingsPanels(page) await captureSettingsPanels(page)
await captureBillParse(page) await captureBillParse(page)
+130 -3
View File
@@ -16,7 +16,6 @@ const CARD_SCENES: Array<[string, string, string]> = [
/** 弹窗截图:文件名、路由、触发按钮文本 */ /** 弹窗截图:文件名、路由、触发按钮文本 */
const MODAL_SCENES: Array<[string, string, string]> = [ const MODAL_SCENES: Array<[string, string, string]> = [
['add-record', '/transactions', '新增记录'],
['batch-set', '/transactions', '一键设置'], ['batch-set', '/transactions', '一键设置'],
['import-bill', '/transactions', '导入账单'], ['import-bill', '/transactions', '导入账单'],
['ai-record', '/transactions', '智能记账'], ['ai-record', '/transactions', '智能记账'],
@@ -58,9 +57,11 @@ export async function captureCards(page: Page): Promise<void> {
* 截取各功能弹窗。 * 截取各功能弹窗。
* *
* @param page Page 实例 * @param page Page 实例
* @param only 仅截取指定场景名(可选,缺省截取全部)
*/ */
export async function captureModals(page: Page): Promise<void> { export async function captureModals(page: Page, only?: string[]): Promise<void> {
for (const [name, path, button] of MODAL_SCENES) { const scenes = only ? MODAL_SCENES.filter(([name]) => only.includes(name)) : MODAL_SCENES
for (const [name, path, button] of scenes) {
try { try {
await page.setViewportSize({ width: 1440, height: 1000 }) await page.setViewportSize({ width: 1440, height: 1000 })
await page.goto(BASE_URL + path) await page.goto(BASE_URL + path)
@@ -85,6 +86,32 @@ export async function captureModals(page: Page): Promise<void> {
} }
} }
/**
* 截取新增记录弹窗(elements/add-record.png)。
*
* 先二次加载页面,确保模块级 AI 启用状态已就绪,使弹窗完整展示 AI 辅助按钮。
*
* @param page Page 实例
*/
export async function captureAddRecord(page: Page): Promise<void> {
try {
await page.setViewportSize({ width: 1440, height: 1000 })
await page.goto(BASE_URL + '/transactions')
await waitPage(page, { selector: PAGE_READY })
await page.reload()
await waitPage(page, { selector: PAGE_READY })
await page.waitForTimeout(1500)
if (!(await clickText(page, '新增记录'))) throw new Error('未找到「新增记录」按钮')
const modal = page.locator('.n-modal').first()
await modal.waitFor({ state: 'visible', timeout: 20000 })
await page.waitForTimeout(900)
await modal.screenshot({ path: resolve(ELEM_DIR, 'add-record.png') })
console.log('[OK] modal/add-record')
} catch (err) {
console.log(`[FAIL] modal/add-record: ${err}`)
}
}
/** /**
* 截取账单解析预览:上传样例账单后解析。 * 截取账单解析预览:上传样例账单后解析。
* *
@@ -321,6 +348,31 @@ export async function captureEditRecord(page: Page): Promise<void> {
} }
} }
/**
* 截取记账弹窗内「新建分类」子弹窗(体现新增/编辑记录时可直接新建分类)。
*
* @param page Page 实例
*/
export async function captureInlineCreate(page: Page): Promise<void> {
try {
await page.setViewportSize({ width: 1440, height: 1000 })
await page.goto(BASE_URL + '/transactions')
await waitPage(page, { selector: PAGE_READY })
if (!(await clickText(page, '新增记录'))) throw new Error('未找到「新增记录」按钮')
const modal = page.locator('.n-modal').first()
await modal.waitFor({ state: 'visible', timeout: 20000 })
if (!(await clickText(page, '新建分类'))) throw new Error('未找到「新建分类」按钮')
await page.waitForTimeout(800)
// 子弹窗为后打开的最后一层弹窗
const sub = page.locator('.n-modal').last()
await sub.waitFor({ state: 'visible', timeout: 8000 })
await sub.screenshot({ path: resolve(ELEM_DIR, 'record-new-category.png') })
console.log('[OK] modal/record-new-category')
} catch (err) {
console.log(`[FAIL] modal/record-new-category: ${err}`)
}
}
/** /**
* 截取「AI 生成规则」的两步弹窗:步骤一选择记录、步骤二预览规则建议。 * 截取「AI 生成规则」的两步弹窗:步骤一选择记录、步骤二预览规则建议。
* *
@@ -466,6 +518,76 @@ export async function captureSqlQuery(page: Page): Promise<void> {
} }
} }
/**
* 截取日历「月视图」整页:写入 screenshots/calendar.png。
*
* @param page Page 实例
*/
export async function captureCalendarMonth(page: Page): Promise<void> {
try {
await page.setViewportSize({ width: 1440, height: 1280 })
await page.goto(BASE_URL + '/calendar?view=month')
await waitPage(page, { selector: '.n-calendar' })
await page.locator('.day-cell__row').first().waitFor({ state: 'visible', timeout: 20000 }).catch(() => undefined)
await page.waitForTimeout(600)
await page.screenshot({ path: resolve(OUT_DIR, 'calendar.png') })
console.log('[OK] calendar')
} catch (err) {
console.log(`[FAIL] calendar: ${err}`)
}
}
/**
* 截取日历「年视图」:切换到年视图后截取。
*
* @param page Page 实例
*/
export async function captureCalendarYear(page: Page): Promise<void> {
try {
await page.setViewportSize({ width: 1440, height: 1000 })
await page.goto(BASE_URL + '/calendar?view=month')
await waitPage(page, { selector: '.n-calendar' })
const viewBtn = page.locator('.cal-toolbar__view').first()
await viewBtn.waitFor({ state: 'visible', timeout: 15000 })
await viewBtn.evaluate((el) => (el as HTMLElement).click())
await page.locator('.year-cell').first().waitFor({ state: 'visible', timeout: 15000 })
await page.waitForLoadState('networkidle', { timeout: 8000 }).catch(() => undefined)
await page.waitForTimeout(800)
await page.screenshot({ path: resolve(ELEM_DIR, 'calendar-year.png') })
console.log('[OK] calendar-year')
} catch (err) {
console.log(`[FAIL] calendar-year: ${err}`)
}
}
/**
* 截取日历「当日明细浮窗」:点击某天有数据的日期后截取浮窗。
*
* @param page Page 实例
*/
export async function captureCalendarDetail(page: Page): Promise<void> {
try {
await page.setViewportSize({ width: 1440, height: 1100 })
await page.goto(BASE_URL + '/calendar?view=month')
await waitPage(page, { selector: '.n-calendar' })
await page.locator('.day-cell__row').first().waitFor({ state: 'visible', timeout: 20000 })
const cell = page
.locator('.n-calendar-cell')
.filter({ has: page.locator('.day-cell__row') })
.first()
await cell.evaluate((el) => (el as HTMLElement).click())
const modal = page.locator('.n-modal', { hasText: '交易明细' }).first()
await modal.waitFor({ state: 'visible', timeout: 20000 })
// 等待明细列表加载完成(出现条目后再截图,避免截到加载中状态)
await modal.locator('.detail-item').first().waitFor({ state: 'visible', timeout: 20000 })
await page.waitForTimeout(600)
await modal.screenshot({ path: resolve(ELEM_DIR, 'calendar-day-detail.png') })
console.log('[OK] calendar-day-detail')
} catch (err) {
console.log(`[FAIL] calendar-day-detail: ${err}`)
}
}
async function main(): Promise<void> { async function main(): Promise<void> {
const browser = await launchBrowser() const browser = await launchBrowser()
try { try {
@@ -478,8 +600,13 @@ async function main(): Promise<void> {
const context = await newContext(browser) const context = await newContext(browser)
await injectSession(context, token) await injectSession(context, token)
const page = await context.newPage() const page = await context.newPage()
await captureCalendarMonth(page)
await captureCalendarYear(page)
await captureCalendarDetail(page)
await captureAddRecord(page)
await captureModals(page) await captureModals(page)
await captureEditRecord(page) await captureEditRecord(page)
await captureInlineCreate(page)
await captureAiRule(page) await captureAiRule(page)
await captureAiRecordImage(page) await captureAiRecordImage(page)
await captureBillDetail(page) await captureBillDetail(page)
+6 -3
View File
@@ -9,6 +9,7 @@ import { BASE_URL, OUT_DIR } from './config.js'
const PAGES: Array<[string, string, number, number, string]> = [ const PAGES: Array<[string, string, number, number, string]> = [
['login', '/login', 1440, 900, '.n-card'], ['login', '/login', 1440, 900, '.n-card'],
['register', '/register', 1440, 900, '.n-card'], ['register', '/register', 1440, 900, '.n-card'],
['calendar', '/calendar', 1440, 1280, '.n-calendar'],
['dashboard', '/dashboard', 1440, 1280, 'canvas'], ['dashboard', '/dashboard', 1440, 1280, 'canvas'],
['sql-query', '/smart-query', 1440, 1180, '.n-card'], ['sql-query', '/smart-query', 1440, 1180, '.n-card'],
['transactions', '/transactions', 1720, 1200, '.n-data-table-tbody tr'], ['transactions', '/transactions', 1720, 1200, '.n-data-table-tbody tr'],
@@ -28,12 +29,14 @@ const PAGES: Array<[string, string, number, number, string]> = [
] ]
/** /**
* 截取全部整页。 * 截取整页。
* *
* @param page Page 实例 * @param page Page 实例
* @param only 仅截取指定页面名(可选,缺省截取全部)
*/ */
export async function capturePages(page: Page): Promise<void> { export async function capturePages(page: Page, only?: string[]): Promise<void> {
for (const [name, path, width, height, selector] of PAGES) { const pages = only ? PAGES.filter(([name]) => only.includes(name)) : PAGES
for (const [name, path, width, height, selector] of pages) {
try { try {
await page.setViewportSize({ width, height }) await page.setViewportSize({ width, height })
await page.goto(BASE_URL + path) await page.goto(BASE_URL + path)