From 523d8fa76bd3b6e932685d3677eae55963cef378 Mon Sep 17 00:00:00 2001 From: 12975 <1297598740@qq.com> Date: Wed, 28 Jan 2026 22:13:38 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=20AI=20=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E6=A8=A1=E5=9D=97=EF=BC=8C=E6=94=AF=E6=8C=81=E6=99=BA?= =?UTF-8?q?=E8=83=BD=E8=81=8A=E5=A4=A9=E3=80=81=E8=AF=AD=E9=9F=B3=E8=BD=AC?= =?UTF-8?q?=E6=96=87=E5=AD=97=E3=80=81=E4=BA=A4=E6=98=93=E7=A1=AE=E8=AE=A4?= =?UTF-8?q?=E5=8F=8A=E8=B4=A2=E5=8A=A1=E5=BB=BA=E8=AE=AE=E7=AD=89=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/services/aiService.ts | 84 ++++++++++++++------------------------- 1 file changed, 30 insertions(+), 54 deletions(-) diff --git a/src/services/aiService.ts b/src/services/aiService.ts index affd832..e4e0e37 100644 --- a/src/services/aiService.ts +++ b/src/services/aiService.ts @@ -313,6 +313,9 @@ export interface DailyInsightContext { /** * Get AI-powered daily insight */ +/** + * Get AI-powered daily insight via dedicated endpoint + */ export async function getDailyInsight(context: DailyInsightContext): Promise<{ spending: string; budget: string }> { // Hash needs to include new fields const currentHash = JSON.stringify(context); @@ -326,64 +329,32 @@ export async function getDailyInsight(context: DailyInsightContext): Promise<{ s return dailyInsightCache.data; } + // 2. Prepare Context Data const weekday = new Date().toLocaleDateString('zh-CN', { weekday: 'long' }); const weekDiff = context.lastWeekSpend !== undefined ? (context.todaySpend - context.lastWeekSpend) : 0; - const prompt = `System: 你是 Novault 首席财务AI,也是用户的贴身管家。你的点评需要非常有温度、有依据。 -Context: -- 今天是: ${weekday} -- 连续记账: ${context.streakDays || 0} 天 -- 今日支出: ${context.todaySpend} - - 对比昨日: ${context.yesterdaySpend} - - 对比上周同日: ${context.lastWeekSpend || '无数据'} (差额: ${weekDiff}) -- 月预算: ${context.monthlyBudget} (已用: ${context.monthlySpent}, 进度: ${(context.monthlySpent / (context.monthlyBudget || 1) * 100).toFixed(0)}%) -- 月时间进度: ${(context.monthProgress * 100).toFixed(0)}% -- 今日支出之王: ${context.topCategory ? `【${context.topCategory.name}】 ¥${context.topCategory.amount}` : '无'} -- 今日最大一笔: ${context.maxTransaction ? `${context.maxTransaction.note || '未备注'} (¥${context.maxTransaction.amount})` : '无'} - -Task: -请输出 JSON 对象(无 markdown 标记): -1. "spending": 针对今日支出的点评(40字内)。 - - 必须结合【${weekday}】的场景(如周五可以放松,周一要收心)。 - - 如果有【连续记账】成就(>3天),请顺带夸奖。 - - 如果对比上周同日波动大,请指出。 - - 结合最大支出进行调侃。 - -2. "budget": 针对预算状况的建议(40字内)。 - - 结合月度进度,给出具体行动指南。 -`; + const contextData = { + weekday, + streakDays: context.streakDays || 0, + todaySpend: context.todaySpend, + yesterdaySpend: context.yesterdaySpend, + lastWeekSpend: context.lastWeekSpend || 0, + weekSpendDiff: weekDiff, + monthlyBudget: context.monthlyBudget, + monthlySpent: context.monthlySpent, + monthProgress: context.monthProgress, + topCategory: context.topCategory ? `${context.topCategory.name} (¥${context.topCategory.amount})` : '无', + maxTransaction: context.maxTransaction ? `${context.maxTransaction.note || '未备注'} (¥${context.maxTransaction.amount})` : '无', + }; try { - const response = await sendChatMessage(prompt); + // 3. Call Dedicated Backend Endpoint + const response = await api.post>('/ai/insight', { + context_data: contextData + }); - if (response.message) { - let content = response.message.trim(); - - // Extract JSON object using regex to handle potential markdown or extra text - const jsonMatch = content.match(/\{[\s\S]*\}/); - if (jsonMatch) { - content = jsonMatch[0]; - } else { - // Fallback cleanup if regex fails but it might still be JSON-ish - content = content.replace(/^```json\s*/, '').replace(/\s*```$/, ''); - } - - let parsed; - try { - parsed = JSON.parse(content); - } catch (e) { - console.warn('AI returned invalid JSON, falling back to raw text split or default', content); - // Fallback: simple split if possible or default - parsed = { - spending: content.slice(0, 50) + '...', - budget: 'AI 分析数据格式异常,请稍后再试。' - }; - } - - const result = { - spending: parsed.spending || '暂无点评', - budget: parsed.budget || '暂无建议' - }; + if (response.success && response.data) { + const result = response.data; // Update Cache dailyInsightCache = { @@ -394,10 +365,15 @@ Task: return result; } - throw new Error('No insight received'); + + throw new Error(response.error || 'Failed to generate insight'); } catch (error) { console.error('Failed to get AI insight:', error); - throw error; + // Return fallback instead of throwing to prevent UI crash + return { + spending: '今日消费情况暂未分析完成', + budget: '暂无预算建议' + }; } }