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
+33
View File
@@ -220,6 +220,39 @@ const columns = computed<DataTableColumns<ParsedBillRow>>(() => [
return h('span', null, row.tradeStatus || '-')
},
},
{
title: t('import.column.matchedRule'),
key: 'matchedRule',
width: 220,
render: (row) => {
const ruleNames = row.matchedRuleNames || []
const suggestedTags = row.suggestedTags || []
if (ruleNames.length === 0 && !row.suggestedCategoryId && suggestedTags.length === 0) {
return h('span', { style: { color: '#ccc' } }, '—')
}
const nodes: any[] = []
// 命中规则名,多个时折叠为 +N
if (ruleNames.length) {
nodes.push(h(NTag, { size: 'small', type: 'warning' }, {
default: () => (ruleNames.length > 1 ? `${ruleNames[0]} +${ruleNames.length - 1}` : ruleNames[0]),
}))
}
// 建议分类
if (row.suggestedCategoryId) {
nodes.push(h(NTag, { size: 'small', type: 'info' }, {
default: () => `${row.suggestedCategoryIcon || ''}${row.suggestedCategoryName || ''}`,
}))
}
// 建议标签
for (const tag of suggestedTags) {
nodes.push(h(NTag, {
size: 'small',
color: tag.color ? { color: tag.color, textColor: '#fff' } : undefined,
}, { default: () => tag.name }))
}
return h('div', { style: { display: 'flex', flexWrap: 'wrap', gap: '4px' } }, nodes)
},
},
])
/** 加载分类选项 */