feat: 添加 AI 分类功能,支持交易自动分类与标签生成
This commit is contained in:
@@ -4,6 +4,7 @@ import NotificationBridge, { isNativeNotificationBridgeAvailable } from '../lib/
|
||||
import { useSettingsStore } from '../stores/settings'
|
||||
import EchoInput from '../components/EchoInput.vue'
|
||||
import { BUDGET_CATEGORY_OPTIONS } from '../config/transactionCategories.js'
|
||||
import { AI_MODEL_OPTIONS, AI_PROVIDER_OPTIONS } from '../config/transactionTags.js'
|
||||
|
||||
// 从 Vite 注入的版本号(来源于 package.json),用于在设置页展示
|
||||
// eslint-disable-next-line no-undef
|
||||
@@ -23,6 +24,24 @@ const aiAutoCategoryEnabled = computed({
|
||||
set: (value) => settingsStore.setAiAutoCategoryEnabled(value),
|
||||
})
|
||||
|
||||
const aiApiKey = computed({
|
||||
get: () => settingsStore.aiApiKey,
|
||||
set: (value) => settingsStore.setAiApiKey(value),
|
||||
})
|
||||
|
||||
const aiAutoApplyThreshold = computed({
|
||||
get: () => String(settingsStore.aiAutoApplyThreshold ?? 0.9),
|
||||
set: (value) => settingsStore.setAiAutoApplyThreshold(value),
|
||||
})
|
||||
|
||||
const currentAiProviderLabel = computed(
|
||||
() => AI_PROVIDER_OPTIONS.find((item) => item.value === settingsStore.aiProvider)?.label || 'DeepSeek',
|
||||
)
|
||||
|
||||
const currentAiModelLabel = computed(
|
||||
() => AI_MODEL_OPTIONS.find((item) => item.value === settingsStore.aiModel)?.label || 'deepseek-chat',
|
||||
)
|
||||
|
||||
const nativeBridgeReady = isNativeNotificationBridgeAvailable()
|
||||
const notificationPermissionGranted = ref(true)
|
||||
const checkingPermission = ref(false)
|
||||
@@ -373,7 +392,7 @@ onMounted(() => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AI 自动分类开关(预留) -->
|
||||
<!-- AI 自动分类与标签 -->
|
||||
<div class="flex flex-col gap-1 p-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-3">
|
||||
@@ -383,9 +402,9 @@ onMounted(() => {
|
||||
<i class="ph-fill ph-magic-wand" />
|
||||
</div>
|
||||
<div>
|
||||
<p class="font-bold text-stone-700 text-sm">AI 自动分类与标签(预留)</p>
|
||||
<p class="font-bold text-stone-700 text-sm">AI 自动分类与标签</p>
|
||||
<p class="text-[11px] text-stone-400 mt-0.5">
|
||||
开启后,未来会自动补全分类、标签,并生成可复用的商户画像。
|
||||
使用本地 DeepSeek API Key 为新交易补全分类、标签,并记录商户画像。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -397,9 +416,42 @@ onMounted(() => {
|
||||
<div class="w-4 h-4 bg-white rounded-full shadow-sm" />
|
||||
</button>
|
||||
</div>
|
||||
<p v-if="aiAutoCategoryEnabled" class="px-4 pb-1 text-[11px] text-purple-600">
|
||||
当前版本仅记录偏好,后续接入 AI 能力后会自动生效。
|
||||
</p>
|
||||
|
||||
<div v-if="aiAutoCategoryEnabled" class="px-4 pt-3 pb-1 space-y-3">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<span class="px-3 py-1 rounded-full bg-stone-100 text-[11px] font-bold text-stone-600">
|
||||
Provider · {{ currentAiProviderLabel }}
|
||||
</span>
|
||||
<span class="px-3 py-1 rounded-full bg-stone-100 text-[11px] font-bold text-stone-600">
|
||||
Model · {{ currentAiModelLabel }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<EchoInput
|
||||
v-model="aiApiKey"
|
||||
label="DeepSeek API Key"
|
||||
type="password"
|
||||
placeholder="sk-..."
|
||||
hint="仅保存在当前设备,本阶段用于本地直连 DeepSeek。"
|
||||
/>
|
||||
|
||||
<EchoInput
|
||||
v-model="aiAutoApplyThreshold"
|
||||
label="自动应用阈值(0-1)"
|
||||
type="number"
|
||||
inputmode="decimal"
|
||||
step="0.05"
|
||||
placeholder="例如 0.9"
|
||||
hint="高于该阈值的 AI 分类会自动写入交易分类,低于阈值仅作为建议保留。"
|
||||
/>
|
||||
|
||||
<p
|
||||
v-if="!settingsStore.aiApiKey"
|
||||
class="text-[11px] text-amber-600 bg-amber-50 border border-amber-200 rounded-2xl px-3 py-2"
|
||||
>
|
||||
当前已开启 AI,但还没有填写 DeepSeek API Key,保存交易时不会发起 AI 分类请求。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
Reference in New Issue
Block a user