From e9e397434f40a7094f7464ff1cb559859552da29 Mon Sep 17 00:00:00 2001 From: sb Date: Sun, 5 Jul 2026 15:29:16 +0900 Subject: [PATCH] =?UTF-8?q?feat(stats):=20=EC=98=88=EC=83=81=20=EC=A7=80?= =?UTF-8?q?=EC=B6=9C=EC=9D=84=20AI=20=EC=B6=94=EC=A0=95=EC=9C=BC=EB=A1=9C?= =?UTF-8?q?=20=EA=B5=90=EC=B2=B4=20=E2=80=94=20=EC=9D=BC=ED=9A=8C=EC=84=B1?= =?UTF-8?q?=20=ED=81=B0=20=EC=A7=80=EC=B6=9C=20=EC=99=9C=EA=B3=A1=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 선형 계산(expenseForecast) 제거, AI 코멘트의 forecast/근거 표시. 경과일·총일수 전달. Co-Authored-By: Claude Opus 4.8 --- src/views/account/AccountDashboardView.vue | 33 +++++++++++----------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/views/account/AccountDashboardView.vue b/src/views/account/AccountDashboardView.vue index d03c308..f6d62b4 100644 --- a/src/views/account/AccountDashboardView.vue +++ b/src/views/account/AccountDashboardView.vue @@ -26,6 +26,8 @@ const categoryList = ref([]) // 분류 목록(대/소분류 매핑용) const trendData = ref([]) // [{month, netWorth}] const aiBullets = ref([]) // AI 재무 코멘트(현황 관찰) const aiTips = ref([]) // AI 절약 가이드(실행 제안) +const aiForecast = ref(null) // AI 월말 예상 지출(일회성 큰 지출 제외 추정) +const aiForecastNote = ref('') // 예상 지출 근거 문장 const aiLoading = ref(false) const periodLabel = computed(() => `${year.value}년 ${String(month.value).padStart(2, '0')}월`) @@ -65,16 +67,8 @@ const expenseDelta = computed(() => { return { prev, diff, pct } }) -/* ===== 이번달 예상 지출 (실제 지출 추세로 월말 추정, run-rate) ===== - 경과일까지 실제 지출을 일평균으로 환산해 그 달 총일수로 추정. 이번 달에만 표시. */ -const expenseForecast = computed(() => { - const isCurrent = year.value === now.getFullYear() && month.value === now.getMonth() + 1 - if (!isCurrent) return null // 지난/미래 달은 추정 불필요(이미 확정 또는 데이터 없음) - const totalDays = daysInMonth(year.value, month.value) - const elapsed = now.getDate() - const projected = elapsed > 0 ? Math.round((monthExpense.value / elapsed) * totalDays) : monthExpense.value - return { projected, elapsed, totalDays } -}) +/* 월말 예상 지출은 단순 선형(run-rate) 대신 AI가 추정한다(aiForecast). + 일회성 큰 지출(노트북 등)을 일평균에서 제외해 현실적인 값을 준다. loadAiComment 참고. */ /* ===== 막대 차트 (기간별 예산 대비 지출) ===== */ const bars = computed(() => { @@ -280,7 +274,10 @@ async function loadAiComment() { aiLoading.value = true aiBullets.value = [] aiTips.value = [] + aiForecast.value = null + aiForecastNote.value = '' try { + const isCurrent = year.value === now.getFullYear() && month.value === now.getMonth() + 1 const res = await accountApi.aiComment({ year: year.value, month: month.value, @@ -289,13 +286,19 @@ async function loadAiComment() { prevExpense: prevMonthExpense.value, budget: budgetTotal.value, spent: spentTotal.value, + elapsedDays: isCurrent ? now.getDate() : 0, + totalDays: daysInMonth(year.value, month.value), categories: (catData.value || []).slice(0, 8).map((c) => ({ category: c.category, total: c.total })), }) aiBullets.value = res?.bullets || [] aiTips.value = res?.tips || [] + aiForecast.value = res?.forecast || null + aiForecastNote.value = res?.forecastNote || '' } catch { aiBullets.value = [] aiTips.value = [] + aiForecast.value = null + aiForecastNote.value = '' } finally { aiLoading.value = false } @@ -417,17 +420,15 @@ onMounted(async () => { {{ expenseDelta.diff >= 0 ? '+' : '' }}{{ won(expenseDelta.diff) }} -
- 예상 지출 월말 추정 - {{ won(expenseForecast.projected) }} +
+ 예상 지출 월말 추정 · AI + {{ won(aiForecast) }}
수지{{ won(monthIncome - monthExpense) }}
-

- 최근 추세 기준({{ expenseForecast.elapsed }}/{{ expenseForecast.totalDays }}일 · 현재 {{ won(monthExpense) }}) -

+

{{ aiForecastNote }}