feat: 扩展 AI 记账能力并优化收支记录交互

- AI 能力:新增分类 Emoji 推荐、标签颜色推荐、自然语言生成分类/标签、单条记录分类推荐

- AI 批量建议:按类型+支付方式+备注去重聚合后分批调用,支持分类/标签/两者范围并记忆偏好,结果可勾选应用

- 分类/标签管理:新增 EmojiPicker 与预设色板,支持 AI 一键推荐并在列表可视化

- 收支记录:新增序号列,标签筛选支持无标签,编辑记录时允许不设置分类

- 修复:账单导入未选择默认标签时生成空 IN 列表导致的 SQL 语法错误

- AI 未启用时隐藏所有 AI 入口与弹窗
This commit is contained in:
2026-09-18 09:57:53 +08:00
parent 49c70a732d
commit a8ef91ed3d
30 changed files with 2009 additions and 132 deletions
+51 -2
View File
@@ -150,6 +150,7 @@ export default {
pageIncome: { zh: '本页收入', en: 'Page Income' },
pageBalance: { zh: '本页结余', en: 'Page Balance' },
column: {
index: { zh: '序号', en: 'No.' },
transactionTime: { zh: '交易时间', en: 'Time' },
type: { zh: '类型', en: 'Type' },
category: { zh: '分类', en: 'Category' },
@@ -162,6 +163,7 @@ export default {
},
notIncluded: { zh: '不计入', en: 'Excluded' },
uncategorized: { zh: '未分类', en: 'Uncategorized' },
untagged: { zh: '无标签', en: 'Untagged' },
remarkHidden: { zh: '备注已隐藏', en: 'Remark hidden' },
remarkView: { zh: '查看', en: 'View' },
remarkHide: { zh: '隐藏', en: 'Hide' },
@@ -228,7 +230,9 @@ export default {
namePlaceholder: { zh: '请输入分类名称', en: 'Enter category name' },
type: { zh: '类型', en: 'Type' },
icon: { zh: '图标', en: 'Icon' },
iconPlaceholder: { zh: '可选,如 emoji', en: 'Optional, e.g. emoji' },
iconPlaceholder: { zh: '点击选择 Emoji', en: 'Click to pick an emoji' },
emojiInputPlaceholder: { zh: '自定义输入 Emoji 或文字', en: 'Custom emoji or text' },
clearIcon: { zh: '清除图标', en: 'Clear icon' },
sort: { zh: '排序', en: 'Order' },
nameRequired: { zh: '请输入分类名称', en: 'Please enter a category name' },
deleteConfirm: { zh: '确定要删除这个分类吗?', en: 'Are you sure you want to delete this category?' },
@@ -326,15 +330,57 @@ export default {
testSuccess: { zh: '连接成功', en: 'Connection succeeded' },
testFailed: { zh: '连接失败', en: 'Connection failed' },
suggestButton: { zh: 'AI 智能建议', en: 'AI suggestions' },
pickButton: { zh: 'AI 推荐', en: 'AI Pick' },
scope: {
label: { zh: '建议内容', en: 'Scope' },
both: { zh: '分类与标签', en: 'Category & Tags' },
category: { zh: '仅分类', en: 'Category only' },
tag: { zh: '仅标签', en: 'Tags only' },
},
suggestTitle: { zh: 'AI 分类与标签建议', en: 'AI category & tag suggestions' },
suggesting: { zh: '正在分析,请稍候…', en: 'Analyzing, please wait…' },
suggestFailed: { zh: 'AI 建议生成失败', en: 'Failed to generate AI suggestions' },
noSuggestion: { zh: 'AI 未返回有效建议', en: 'AI returned no valid suggestions' },
applyAll: { zh: '全部应用({count})', en: 'Apply all ({count})' },
applyAll: { zh: '应用勾选({count})', en: 'Apply selected ({count})' },
applyNone: { zh: '请至少勾选一条建议', en: 'Please select at least one suggestion' },
aggregated: { zh: '已聚合为 {groups} 类、共 {count} 条记录', en: 'Aggregated into {groups} groups, {count} records in total' },
applySuccess: { zh: '已应用 {count} 条建议', en: 'Applied {count} suggestions' },
oneApplied: { zh: '已应用 AI 推荐分类', en: 'AI category applied' },
tagApplied: { zh: '已应用 AI 推荐标签', en: 'AI tags applied' },
applyFailed: { zh: '应用建议失败', en: 'Failed to apply suggestions' },
applyHint: { zh: '将覆盖分类并追加标签,确认后立即写入', en: 'Categories will be overwritten and tags appended; changes are written immediately.' },
needConfig: { zh: 'AI 未启用,请先在「AI 设置」中配置', en: 'AI is not enabled. Please configure it in AI Settings first.' },
decorate: {
emojiButton: { zh: 'AI 推荐', en: 'AI Pick' },
colorButton: { zh: 'AI 推荐', en: 'AI Pick' },
nameRequired: { zh: '请先输入名称', en: 'Please enter a name first' },
failed: { zh: 'AI 推荐失败', en: 'AI recommendation failed' },
},
category: {
label: { zh: 'AI 生成分类', en: 'AI Category' },
placeholder: { zh: '描述用途,如:日常通勤打车地铁', en: 'Describe it, e.g. daily commute by taxi and metro' },
button: { zh: 'AI 生成', en: 'Generate' },
textRequired: { zh: '请输入分类描述', en: 'Please enter a description' },
applied: { zh: '已生成分类,请确认后保存', en: 'Category generated, please confirm and save' },
failed: { zh: 'AI 生成分类失败', en: 'Failed to generate category' },
},
newCategory: {
button: { zh: 'AI 新建', en: 'AI New' },
hint: { zh: 'AI 建议新分类:', en: 'AI suggests:' },
save: { zh: '保存并选用', en: 'Save & Select' },
saved: { zh: '已创建并选用新分类', en: 'Category created and selected' },
exists: { zh: '已存在同名分类,已为你选中', en: 'A same-name category exists and has been selected' },
needInfo: { zh: '请先填写备注或金额,便于生成分类', en: 'Please fill in a remark or amount first' },
},
newTag: {
button: { zh: 'AI 新建', en: 'AI New' },
hint: { zh: 'AI 建议新标签:', en: 'AI suggests tag:' },
save: { zh: '保存并选用', en: 'Save & Select' },
saved: { zh: '已创建并选用新标签', en: 'Tag created and selected' },
exists: { zh: '已存在同名标签,已为你选中', en: 'A same-name tag exists and has been selected' },
needInfo: { zh: '请先填写备注或金额,便于生成标签', en: 'Please fill in a remark or amount first' },
failed: { zh: 'AI 生成标签失败', en: 'Failed to generate tag' },
},
query: {
placeholder: { zh: '用自然语言查询,如:上个月餐饮花了多少', en: 'Ask in natural language, e.g. dining expenses last month' },
examples: { zh: '上个月餐饮|超过500的支出|待报销的支出|微信支付', en: 'Dining last month|Expenses over 500|Pending reimbursement|Paid by WeChat' },
@@ -369,6 +415,7 @@ export default {
},
column: {
record: { zh: '记录', en: 'Record' },
count: { zh: '命中条数', en: 'Matched' },
category: { zh: '建议分类', en: 'Suggested category' },
tags: { zh: '建议标签', en: 'Suggested tags' },
reason: { zh: '理由', en: 'Reason' },
@@ -390,6 +437,8 @@ export default {
empty: { zh: '暂无调用记录', en: 'No usage records yet' },
type: {
suggest: { zh: '生成建议', en: 'Suggest' },
decorate: { zh: '图标配色', en: 'Icon & Color' },
category: { zh: '生成分类', en: 'Category' },
test: { zh: '测试连接', en: 'Test' },
},
column: {