docs: 补充收支记录页 AI 生成规则、CORS/反向代理与邮箱检查进度时间戳

同步近期 ledgerly 功能与配置变更到文档站:新增收支记录页「AI 生成规则」入口的用户与开发说明、补充新接口与规则应用逻辑、修正 CORS/反向代理与运行环境编码说明,并更新邮箱检查进度时间戳描述。

变更内容:
- guide/transactions.md 批量操作区新增「AI 生成规则」按钮与「AI 生成规则(从勾选账单)」小节(含「同时应用到勾选账单」),引用新截图。
- guide/ai.md、guide/rules.md、guide/pages.md 补充两处生成入口与「同时应用」说明。
- dev/api.md 新增 POST /api/ai/rule/apply-transactions;dev/rule-engine.md、dev/ai.md 补充 applyToTransactions 与两个生成入口。
- dev/build-deploy.md 将 CORS 更新为放开全部来源并信任反向代理转发头,新增运行环境 UTF-8 locale 说明。
- guide/email-bills.md 补充「立即检查」进度每行带 HH:mm:ss 时间戳。
- scripts/ts/capture-elements.ts 新增 captureAiRuleFromTransactions 截图场景(交易页 AI 生成规则弹窗)。

说明:
- 新截图 elements/ai-rule-transactions.png 已上传 OSS,正文以 OSS 长期地址引用。
This commit is contained in:
2026-10-13 22:39:40 +08:00
parent 5eb1d331f9
commit d94d4e1ed5
10 changed files with 72 additions and 10 deletions
+3 -2
View File
@@ -89,11 +89,12 @@
## 规则生成
`AiRuleServiceImpl` 由用户勾选的**已打标签记录**反推分类/标签规则:
`AiRuleServiceImpl` 由用户勾选的记录反推分类/标签规则,有两个入口:规则管理页(依据**已打标签记录**)与收支记录页批量操作(依据**任意勾选账单**):
- 仅加载属于当前用户且被勾选的记录(单次 ≤ 500 条),附带其标签名称与分类名;提示词字段为 `type / remark / channel / category / tags`(不含金额与 `rawData`),并对相同组合去重。
- 仅加载属于当前用户且被勾选的记录(单次 ≤ 500 条),附带其标签名称与分类名;提示词字段为 `type / remark / channel / category / tags`(不含金额与 `rawData`),并对相同「类型 + 备注 + 渠道 + 标签」组合去重。
- 解析并校验模型输出(分类 ID 归属与类型、标签归属、名称长度、颜色格式等)。
- **去重**:按「类型 + 归一化关键词 + 分类 + 排序标签集合」计算签名;与已有规则或本次建议内部重复的条目标记 `duplicate=true`(前端默认不勾选且禁止导入),`apply` 时后端再次校验并跳过。
- **应用到交易**:`POST /api/ai/rule/apply-transactions`(`applyToTransactions`)按传入规则对指定交易做**本地匹配**(不调用大模型、不外发数据),命中时覆盖分类、追加标签,必要时新建分类/标签;用于收支记录页勾选「同时应用到账单」的场景。
## 统计搜索
+1
View File
@@ -79,6 +79,7 @@
| DELETE | `/api/rule/batch` | 批量删除规则(body `{ ids }`,返回实际删除数) |
| POST | `/api/ai/rule/suggest` | 依据所选已打标签记录生成规则建议(含 `duplicate` 标记) |
| POST | `/api/ai/rule/apply` | 批量创建规则(自动去重、按需新建分类/标签) |
| POST | `/api/ai/rule/apply-transactions` | 按传入规则对指定交易做本地匹配并应用(命中则覆盖分类、追加标签,必要时新建;纯本地匹配,不外发数据) |
| POST | `/api/ai/statistics` | 自然语言解析为统计面板参数 |
| GET / PUT | `/api/setting/excluded-display-style` | 查询 / 更新「不计入统计」记录展示样式 |
| GET / PUT | `/api/setting/show-hidden-data` | 查询 / 更新是否显示已隐藏备注的记录 |
+3 -1
View File
@@ -122,7 +122,9 @@ jar 内置的前端为生产构建,访问时与后端同源,无需额外的
### 安全配置
- **JWT 签名密钥**:默认使用内置密钥签发 Token(有效期 24 小时);生产环境可通过环境变量 `JWT_SECRET` 覆盖,未配置时回退内置默认值,避免个人自托管场景重启后登录态失效。
- **CORS 放行来源**:仅放行本机与局域网来源——`localhost`、`127.0.0.1`、`[::1]`、`192.168.*`、`10.*`、`172.*`(任意端口),并允许携带凭证;生产环境前后端同源,无需额外的跨域配置。
- **CORS 放行来源**:放开全部来源(`allowedOriginPatterns("*")` 并允许携带凭证)。因 `allowCredentials(true)` 不允许 `allowedOrigins("*")`,需使用 origin pattern 通配;接口认证基于 JWT(`Authorization` 头存于 `localStorage`,跨站脚本无法自动携带),风险可控。
- **反向代理转发头**:`application.yml` 配置 `server.forward-headers-strategy: framework`,信任 `X-Forwarded-Proto`/`Host`;经 nginx/frp 反代时使 HTTPS 同源请求被正确识别为同源,避免被误判为跨域(否则带 `Origin` 的请求会返回 `403 Invalid CORS request`)。
- **运行环境编码**:容器或直接运行 jar 的 JVM 需为 UTF-8 locale(`LANG`/`LC_ALL=C.UTF-8`);否则 `sun.jnu.encoding` 退化为 ASCII,含中文的文件名(如邮箱账单附件名)落盘会抛 `InvalidPathException`。
### 发布流程
+4 -3
View File
@@ -38,10 +38,11 @@
## AI 生成规则
`AiRuleServiceImpl` 依据用户勾选的**已打标签记录**生成规则建议:
`AiRuleServiceImpl` 提供两个入口:规则管理页(生成 + 创建)与收支记录页批量操作(生成 + 可选应用到账单)。
- 输入字段为记录的类型、备注、交易渠道、已有分类与标签(不含金额与原始账单数据)。
- 输出规则经 `RuleService.create` 落库,必要时新建分类/标签,规则默认启用。
- 生成建议(`suggest`,`POST /api/ai/rule/suggest`):依据用户勾选的记录生成规则建议;规则管理页限定**已打标签记录**,收支记录页为**任意勾选账单**。输入字段为记录的类型、备注、交易渠道、已有分类与标签(不含金额与原始账单数据),并按「类型 + 备注 + 渠道 + 标签」组合去重。
- 创建规则(`apply`,`POST /api/ai/rule/apply`):输出规则经 `RuleService.create` 落库,必要时新建分类/标签,规则默认启用。
- 应用到交易(`applyToTransactions`,`POST /api/ai/rule/apply-transactions`):**纯本地匹配、不调用大模型**,按规则的类型/关键词/金额条件匹配指定交易,命中则聚合分类与标签,委托 `AiSuggestionService.apply` 落库(覆盖分类、追加标签,必要时新建)。
- **去重**:以「类型 + 归一化关键词 + 分类 + 排序标签集合」为签名;与已有规则或同批已创建规则重复时跳过(`apply` 返回实际创建数),建议阶段则标记 `duplicate` 供前端禁止勾选。
## 校验
+7 -2
View File
@@ -51,7 +51,7 @@ API Key 仅保存在本地数据库中,仅用于向你配置的接口地址发
| 生成渠道 | 新增/编辑记录 → 交易渠道 → AI 新建 | 由账单描述生成渠道名称并创建 |
| 推荐 Emoji | 分类管理 → AI 推荐 | 为分类推荐 Emoji 图标 |
| 推荐颜色 | 标签管理 → AI 推荐 | 为标签推荐颜色 |
| 生成规则 | 规则管理 → AI 生成规则 | 由已打标签的记录归纳分类与标签规则 |
| 生成规则 | 规则管理 → AI 生成规则(已打标签记录)/收支记录 → 批量操作 → AI 生成规则(勾选账单) | 由所选记录归纳分类与标签规则,可同时应用到勾选账单 |
| 统计搜索 | 统计面板 → AI 搜索 | 自然语言解析为统计筛选条件与维度 |
| 生成关系名称 | 收支记录 → 账单关系 → AI 生成 | 依据关联账单的类型、渠道、分类与备注生成关系名称与备注 |
| 智能查数 | 左侧菜单 → 智能查数 | 自然语言转只读 SQL 查询并展示结果 |
@@ -114,7 +114,12 @@ API Key 仅保存在本地数据库中,仅用于向你配置的接口地址发
## AI 生成规则
在规则管理页点「AI 生成规则」,选择用于归纳的**已打标签记录**(默认全选当前页,支持搜索、筛选与分页),AI 会依据这些记录的**类型、备注、交易渠道、已有分类与标签**生成规则建议,预览编辑后批量创建。与已有规则重复的建议会标记「已存在」并禁止导入。详见[规则管理](/guide/rules)。
有两种生成方式:
- **规则管理页**:点「AI 生成规则」,选择用于归纳的**已打标签记录**(默认全选当前页,支持搜索、筛选与分页),AI 依据这些记录的**类型、备注、交易渠道、已有分类与标签**生成规则建议,预览编辑后批量创建。
- **收支记录页**:在**批量操作**区勾选若干账单后点「AI 生成规则」,直接以**勾选的账单**为依据归纳规则(不要求已打标签);弹窗中还可勾选「**同时应用到当前勾选的账单**」,命中时覆盖这些账单的分类并追加标签。
两种方式都会对与已有规则重复的建议标记「已存在」并禁止导入。详见[规则管理](/guide/rules#ai-生成规则)与[收支记录](/guide/transactions#ai-生成规则从勾选账单)。
## 用量统计
+1 -1
View File
@@ -32,7 +32,7 @@
行操作:
- **测试连接**:验证 IMAP 配置。
- **立即检查**:实时展示检查进度,完成后提示新增待处理账单数量。
- **立即检查**:实时展示检查进度(每行带 `HH:mm:ss` 时间戳),完成后提示新增待处理账单数量。
- **编辑 / 删除**。
## 发件人规则
+1 -1
View File
@@ -57,7 +57,7 @@
- **智能查数**:左侧菜单「智能查数」→ 输入自然语言 → 查看结果、生成的 SQL 与历史提问
- **自动归类**:规则管理配置规则 → 账单导入预览时命中并给出建议
- **邮箱账单**:邮箱配置 → 发件人规则 → 待处理账单 → 解析 → 导入到收支记录
- **AI 辅助**:设置启用 AI → 统计面板「AI 搜索」、收支记录「一键设置 / 文字·图片记账 / AI 查询」、编辑记录「分类·标签·渠道 AI 推荐与新建」、分类与标签「AI 推荐」、规则管理「AI 生成规则」、账单关系「AI 生成」、左侧「智能查数」
- **AI 辅助**:设置启用 AI → 统计面板「AI 搜索」、收支记录「一键设置 / 文字·图片记账 / AI 查询」、编辑记录「分类·标签·渠道 AI 推荐与新建」、分类与标签「AI 推荐」、规则管理「AI 生成规则」、收支记录批量操作「AI 生成规则」、账单关系「AI 生成」、左侧「智能查数」
- **系统维护**:顶部菜单 → 设置 / 日志
## 页面关系说明
+2
View File
@@ -75,6 +75,8 @@
![AI 生成规则 · 预览规则](https://adcarac.oss-cn-beijing.aliyuncs.com/finance-app-docs/screenshots/elements/ai-rule-preview.png)
> 此外,也可在[收支记录页的批量操作区](/guide/transactions#ai-生成规则从勾选账单)勾选账单后直接生成规则(不要求已打标签),并可选「同时应用到勾选账单」。
::: tip 与已有规则去重
AI 建议若与**数据库中已有规则重复**(按「类型 + 关键词 + 分类 + 标签集合」判定),会标注「**已存在**」,**默认不勾选且不可勾选**,无法导入,避免产生重复规则。
:::
+11
View File
@@ -27,9 +27,20 @@
| 一键设置 | 批量设置分类、计入统计与标签;**有勾选时作用于勾选记录,未勾选时作用于当前页全部记录**,详见[一键设置(批量设置)](#一键设置-批量设置) |
| 批量删除 | 勾选至少一条后出现,确认后删除所选记录 |
| 建立关系 | 勾选至少两条后出现,为所选记录[建立账单关系](/guide/relations) |
| AI 生成规则 | 启用 AI 后出现;勾选至少一条账单,由 AI 归纳分类/标签规则,可在弹窗中勾选「同时应用到当前勾选的账单」,详见 [AI 生成规则](#ai-生成规则从勾选账单) |
> 翻页、刷新或退出批量模式都会清空已勾选记录。**批量删除**与**建立关系**只作用于勾选记录;**一键设置**在未勾选时才作用于当前页全部记录,且当次勾选范围以打开弹窗时的选择为准。
## AI 生成规则(从勾选账单)
启用 AI 后,批量操作区会出现「**AI 生成规则**」按钮。勾选若干账单后点击,AI 会依据这些账单的**类型、备注、交易渠道、已有分类与标签**归纳出「关键词 → 分类/标签」规则;在弹窗中预览、勾选要创建的规则后点击「创建勾选规则」批量创建,系统会自动创建建议中不存在的新分类与标签。
弹窗底部可勾选「**同时应用到当前勾选的 N 条账单**」——命中规则时会**覆盖这些账单的分类并追加标签**(不改动备注与金额)。生成与「同时应用」全程不发送金额、原始账单数据等敏感字段。
![AI 生成规则(收支记录)](https://adcarac.oss-cn-beijing.aliyuncs.com/finance-app-docs/screenshots/elements/ai-rule-transactions.png)
> 与[规则管理](/guide/rules#ai-生成规则)页的「AI 生成规则」(依据**已打标签记录**归纳)不同,此入口直接以**勾选的账单**为依据,不要求已打标签;两处都会对与已有规则重复的建议标记「已存在」并禁止导入。
## 账单导入
「收支记录」页支持把支付宝、微信、美团、淘宝、京东、招商银行、交通银行的账单文件解析并导入为收支记录。
+39
View File
@@ -442,6 +442,44 @@ export async function captureAiRule(page: Page): Promise<void> {
}
}
/**
* 截取「收支记录 → 批量操作 → AI 生成规则」弹窗(基于勾选账单生成规则)。
*
* <p>仅触发规则建议生成(只读),不点击「创建勾选规则」,不修改数据。
* 需目标环境已启用 AI 且存在可勾选账单。</p>
*
* @param page Page 实例
*/
export async function captureAiRuleFromTransactions(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('未找到「批量操作」按钮')
await page.waitForTimeout(500)
const checkboxes = page.locator('.n-data-table-tbody .n-checkbox')
const count = Math.min(await checkboxes.count(), 5)
for (let i = 0; i < count; i++) {
await checkboxes.nth(i).click({ force: true }).catch(() => undefined)
}
await page.waitForTimeout(300)
// 点击「AI 生成规则」,等待弹窗与规则建议表(真实 AI 调用)
if (!(await clickText(page, 'AI 生成规则'))) throw new Error('未找到「AI 生成规则」按钮')
const modal = page.locator('.n-modal').first()
await modal.waitFor({ state: 'visible', timeout: 30000 })
await modal.locator('.n-data-table-tbody tr').first().waitFor({ state: 'visible', timeout: 90000 })
await page.waitForLoadState('networkidle', { timeout: 90000 }).catch(() => undefined)
await page.waitForTimeout(1000)
await modal.screenshot({ path: resolve(ELEM_DIR, 'ai-rule-transactions.png') })
console.log('[OK] modal/ai-rule-transactions')
} catch (err) {
console.log(`[FAIL] modal/ai-rule-transactions: ${err}`)
}
}
/**
* 截取系统设置的配置面板。
*
@@ -641,6 +679,7 @@ async function main(): Promise<void> {
await captureEditRecord(page)
await captureInlineCreate(page)
await captureAiRule(page)
await captureAiRuleFromTransactions(page)
await captureAiRecordImage(page)
await captureBillDetail(page)
await captureChannelAi(page)