From d4f6ad72251ba3f364d8271d773c11244f1e232c Mon Sep 17 00:00:00 2001 From: shaw Date: Thu, 5 Mar 2026 10:45:51 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9Eapikey=E7=9A=84usage?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/i18n/locales/en.ts | 59 ++ frontend/src/i18n/locales/zh.ts | 59 ++ frontend/src/router/index.ts | 9 + frontend/src/views/KeyUsageView.vue | 858 ++++++++++++++++++++++++++++ frontend/vite.config.ts | 4 + 5 files changed, 989 insertions(+) create mode 100644 frontend/src/views/KeyUsageView.vue diff --git a/frontend/src/i18n/locales/en.ts b/frontend/src/i18n/locales/en.ts index 3963ad01..0fad270d 100644 --- a/frontend/src/i18n/locales/en.ts +++ b/frontend/src/i18n/locales/en.ts @@ -110,6 +110,65 @@ export default { } }, + // Key Usage Query Page + keyUsage: { + title: 'API Key Usage', + subtitle: 'Enter your API Key to view real-time spending and usage status', + placeholder: 'sk-ant-mirror-xxxxxxxxxxxx', + query: 'Query', + querying: 'Querying...', + privacyNote: 'Your Key is processed locally in the browser and will not be stored', + dateRange: 'Date Range:', + dateRangeToday: 'Today', + dateRange7d: '7 Days', + dateRange30d: '30 Days', + dateRangeCustom: 'Custom', + apply: 'Apply', + used: 'Used', + detailInfo: 'Detail Information', + tokenStats: 'Token Statistics', + modelStats: 'Model Usage Statistics', + // Table headers + model: 'Model', + requests: 'Requests', + inputTokens: 'Input Tokens', + outputTokens: 'Output Tokens', + totalTokens: 'Total Tokens', + cost: 'Cost', + // Status + quotaMode: 'Key Quota Mode', + walletBalance: 'Wallet Balance', + // Ring card titles + totalQuota: 'Total Quota', + limit5h: '5-Hour Limit', + limitDaily: 'Daily Limit', + limit7d: '7-Day Limit', + limitWeekly: 'Weekly Limit', + limitMonthly: 'Monthly Limit', + // Detail rows + remainingQuota: 'Remaining Quota', + expiresAt: 'Expires At', + todayExpires: '(expires today)', + daysLeft: '({days} days)', + usedQuota: 'Used Quota', + subscriptionType: 'Subscription Type', + subscriptionExpires: 'Subscription Expires', + // Usage stat cells + todayRequests: 'Today Requests', + todayTokens: 'Today Tokens', + todayCost: 'Today Cost', + rpmTpm: 'RPM / TPM', + totalRequests: 'Total Requests', + totalTokensLabel: 'Total Tokens', + totalCost: 'Total Cost', + avgDuration: 'Avg Duration', + // Messages + enterApiKey: 'Please enter an API Key', + querySuccess: 'Query successful', + queryFailed: 'Query failed', + queryFailedRetry: 'Query failed, please try again later', + }, + // Setup Wizard setup: { title: 'Sub2API Setup', diff --git a/frontend/src/i18n/locales/zh.ts b/frontend/src/i18n/locales/zh.ts index a692b7f6..a9619b9d 100644 --- a/frontend/src/i18n/locales/zh.ts +++ b/frontend/src/i18n/locales/zh.ts @@ -110,6 +110,65 @@ export default { } }, + // Key Usage Query Page + keyUsage: { + title: 'API Key 用量查询', + subtitle: '输入您的 API Key 以查看实时消费金额与使用状态', + placeholder: 'sk-ant-mirror-xxxxxxxxxxxx', + query: '查询', + querying: '查询中...', + privacyNote: '您的 Key 仅在浏览器本地处理,不会被存储', + dateRange: '统计范围:', + dateRangeToday: '今日', + dateRange7d: '7 天', + dateRange30d: '30 天', + dateRangeCustom: '自定义', + apply: '应用', + used: '已使用', + detailInfo: '详细信息', + tokenStats: 'Token 统计', + modelStats: '模型用量统计', + // Table headers + model: '模型', + requests: '请求数', + inputTokens: '输入 Tokens', + outputTokens: '输出 Tokens', + totalTokens: '总 Tokens', + cost: '费用', + // Status + quotaMode: 'Key 限额模式', + walletBalance: '钱包余额', + // Ring card titles + totalQuota: '总额度', + limit5h: '5 小时限额', + limitDaily: '日限额', + limit7d: '7 天限额', + limitWeekly: '周限额', + limitMonthly: '月限额', + // Detail rows + remainingQuota: '剩余额度', + expiresAt: '过期时间', + todayExpires: '(今日到期)', + daysLeft: '({days} 天)', + usedQuota: '已用额度', + subscriptionType: '订阅类型', + subscriptionExpires: '订阅到期', + // Usage stat cells + todayRequests: '今日请求', + todayTokens: '今日 Tokens', + todayCost: '今日费用', + rpmTpm: 'RPM / TPM', + totalRequests: '累计请求', + totalTokensLabel: '累计 Tokens', + totalCost: '累计费用', + avgDuration: '平均耗时', + // Messages + enterApiKey: '请输入 API Key', + querySuccess: '查询成功', + queryFailed: '查询失败', + queryFailedRetry: '查询失败,请稍后重试', + }, + // Setup Wizard setup: { title: 'Sub2API 安装向导', diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts index 8aa9cfff..d235de51 100644 --- a/frontend/src/router/index.ts +++ b/frontend/src/router/index.ts @@ -102,6 +102,15 @@ const routes: RouteRecordRaw[] = [ title: 'Reset Password' } }, + { + path: '/key-usage', + name: 'KeyUsage', + component: () => import('@/views/KeyUsageView.vue'), + meta: { + requiresAuth: false, + title: 'Key Usage', + } + }, // ==================== User Routes ==================== { diff --git a/frontend/src/views/KeyUsageView.vue b/frontend/src/views/KeyUsageView.vue new file mode 100644 index 00000000..a061ad9f --- /dev/null +++ b/frontend/src/views/KeyUsageView.vue @@ -0,0 +1,858 @@ + + + + + diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index d6487b5b..b71f9d58 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -115,6 +115,10 @@ export default defineConfig(({ mode }) => { target: backendUrl, changeOrigin: true }, + '/v1': { + target: backendUrl, + changeOrigin: true + }, '/setup': { target: backendUrl, changeOrigin: true