From 2c9da6bf6d728fa330a3b05f3c04c9dfc8f7503c Mon Sep 17 00:00:00 2001 From: shijing Date: Wed, 15 Jul 2026 13:16:28 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E6=95=B0=E6=8D=AE=E5=88=86?= =?UTF-8?q?=E6=9E=90=E9=A1=B5=E9=9D=A2=E5=B1=95=E7=A4=BA=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=8A=A5=E8=A1=A8=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/analytics/RankBarList.vue | 114 +++++ .../src/components/analytics/StatCard.vue | 129 ++++++ .../src/components/analytics/TrendChart.vue | 281 ++++++++++++ frontend/src/composables/useAnalytics.js | 74 ++++ frontend/src/router/index.js | 2 +- frontend/src/views/AnalyticsView.vue | 403 ++++++++++++++++++ 6 files changed, 1002 insertions(+), 1 deletion(-) create mode 100644 frontend/src/components/analytics/RankBarList.vue create mode 100644 frontend/src/components/analytics/StatCard.vue create mode 100644 frontend/src/components/analytics/TrendChart.vue create mode 100644 frontend/src/composables/useAnalytics.js create mode 100644 frontend/src/views/AnalyticsView.vue diff --git a/frontend/src/components/analytics/RankBarList.vue b/frontend/src/components/analytics/RankBarList.vue new file mode 100644 index 0000000..b15b4e4 --- /dev/null +++ b/frontend/src/components/analytics/RankBarList.vue @@ -0,0 +1,114 @@ + + + + + diff --git a/frontend/src/components/analytics/StatCard.vue b/frontend/src/components/analytics/StatCard.vue new file mode 100644 index 0000000..6faf493 --- /dev/null +++ b/frontend/src/components/analytics/StatCard.vue @@ -0,0 +1,129 @@ + + + + + diff --git a/frontend/src/components/analytics/TrendChart.vue b/frontend/src/components/analytics/TrendChart.vue new file mode 100644 index 0000000..04f3ce8 --- /dev/null +++ b/frontend/src/components/analytics/TrendChart.vue @@ -0,0 +1,281 @@ + + + + + diff --git a/frontend/src/composables/useAnalytics.js b/frontend/src/composables/useAnalytics.js new file mode 100644 index 0000000..e2dd894 --- /dev/null +++ b/frontend/src/composables/useAnalytics.js @@ -0,0 +1,74 @@ +import { ref } from 'vue' +import { request } from '@/api/client' + +export const RANGE_OPTIONS = [ + { code: '1h', label: '近1小时' }, + { code: '12h', label: '近12小时' }, + { code: '24h', label: '近24小时' }, + { code: '7d', label: '近7天' }, +] + +function emptyBusiness() { + return { + range: null, + kpis: { + question_count: 0, + active_user_count: 0, + prev_active_user_count: 0, + user_delta_pct: null, + avg_questions_per_user: 0, + avg_latency_ms: 0, + success_count: 0, + success_ratio: 0, + fail_count: 0, + fail_ratio: 0, + }, + trend: [], + top_questions: [], + } +} + +function emptyResources() { + return { + range: null, + kpis: { + document_count: 0, + total_tokens: 0, + total_pu: 0, + api_call_count: 0, + api_success_ratio: 0, + avg_api_latency_ms: 0, + }, + token_trend: [], + top_documents: [], + } +} + +export function useAnalytics() { + const business = ref(emptyBusiness()) + const resources = ref(emptyResources()) + const loading = ref(false) + const error = ref('') + + async function loadBusiness(rangeCode) { + business.value = await request(`/api/stats/dashboard/business?range=${encodeURIComponent(rangeCode)}`) + } + + async function loadResources(rangeCode) { + resources.value = await request(`/api/stats/dashboard/resources?range=${encodeURIComponent(rangeCode)}`) + } + + async function loadAll(rangeCode) { + loading.value = true + error.value = '' + try { + await Promise.all([loadBusiness(rangeCode), loadResources(rangeCode)]) + } catch (err) { + error.value = err?.message || String(err) + } finally { + loading.value = false + } + } + + return { business, resources, loading, error, loadAll, loadBusiness, loadResources } +} diff --git a/frontend/src/router/index.js b/frontend/src/router/index.js index a1982c1..574b446 100644 --- a/frontend/src/router/index.js +++ b/frontend/src/router/index.js @@ -42,7 +42,7 @@ const routes = [ { path: '/analytics', name: 'analytics', - component: () => import('@/views/PlaceholderView.vue'), + component: () => import('@/views/AnalyticsView.vue'), meta: { title: '数据分析', subtitle: '使用量、热门问题、命中率等数据看板。', diff --git a/frontend/src/views/AnalyticsView.vue b/frontend/src/views/AnalyticsView.vue new file mode 100644 index 0000000..bd0842e --- /dev/null +++ b/frontend/src/views/AnalyticsView.vue @@ -0,0 +1,403 @@ + + + + +