feat: 支持自定义分类与标签规则并优化 AI 查询交互

- 新增 t_rule、t_rule_tag 表(MySQL/SQLite 双脚本)与规则引擎,支持关键词(备注/交易对方/商品名称)、收支类型、金额区间组合匹配
- 新增 /api/rule 增删改查与启用停用接口,侧边栏新增「规则管理」页,支持排序与启停
- 账单导入解析阶段批量匹配,返回命中规则与建议分类/标签,预览表格新增「匹配规则/建议」列
- 确认导入时按行重新匹配:规则建议分类优先于面板默认分类,规则标签与默认标签合并去重
- 删除标签时同步清理规则标签关联
- AI 自然语言查询解析后直接应用筛选并搜索,移除二次确认弹窗,成功提示展示识别意图
- 修正登录日志筛选 success 参数类型为 'true'/'false'
This commit is contained in:
2026-09-18 17:42:59 +08:00
parent e82e0a4ef9
commit c69e76ed4c
26 changed files with 1622 additions and 78 deletions
+65
View File
@@ -0,0 +1,65 @@
// 规则相关 API 接口:自定义分类与标签规则的增删改查与启用切换
import request from './request'
/** 规则关联的标签 */
export interface RuleTag {
id: number
name: string
color?: string
}
/** 规则数据结构 */
export interface RuleItem {
id: number
name: string
enabled: boolean
sortOrder: number
type: string | null
keyword: string | null
minAmount: number | null
maxAmount: number | null
categoryId: number | null
categoryName: string | null
categoryIcon: string | null
tags: RuleTag[] | null
createdAt: string
updatedAt: string
}
/** 创建/更新规则的请求体 */
export interface RulePayload {
name: string
enabled?: boolean
sortOrder?: number
type?: string | null
keyword?: string | null
minAmount?: number | null
maxAmount?: number | null
categoryId?: number | null
tagIds?: number[]
}
/** 获取规则列表 */
export function getRuleList() {
return request.get('/rule/list')
}
/** 创建规则 */
export function createRule(data: RulePayload) {
return request.post('/rule', data)
}
/** 更新指定规则 */
export function updateRule(id: number, data: RulePayload) {
return request.put(`/rule/${id}`, data)
}
/** 删除指定规则 */
export function deleteRule(id: number) {
return request.delete(`/rule/${id}`)
}
/** 启用/停用指定规则 */
export function toggleRuleEnabled(id: number, enabled: boolean) {
return request.put(`/rule/${id}/enabled`, { enabled })
}
+5
View File
@@ -85,6 +85,11 @@ export interface ParsedBillRow {
importable: boolean
selected: boolean
duplicate: boolean
matchedRuleNames: string[] | null
suggestedCategoryId: number | null
suggestedCategoryName: string | null
suggestedCategoryIcon: string | null
suggestedTags: { id: number; name: string; color?: string }[] | null
rawData: string | null
error: string | null
}