merge: 合并 main 分支到 test,解决 config 和 modelWhitelist 冲突

- config.go: 保留 Sora 配置,合入 SubscriptionCache 配置
- useModelWhitelist.ts: 同时保留 soraModels 和 antigravityModels

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
yangjianbo
2026-02-07 20:18:07 +08:00
156 changed files with 14550 additions and 2206 deletions

View File

@@ -10,25 +10,88 @@ export default {
login: 'Login',
getStarted: 'Get Started',
goToDashboard: 'Go to Dashboard',
// User-focused value proposition
heroSubtitle: 'One Key, All AI Models',
heroDescription: 'No need to manage multiple subscriptions. Access Claude, GPT, Gemini and more with a single API key',
tags: {
subscriptionToApi: 'Subscription to API',
stickySession: 'Sticky Session',
realtimeBilling: 'Real-time Billing'
stickySession: 'Session Persistence',
realtimeBilling: 'Pay As You Go'
},
// Pain points section
painPoints: {
title: 'Sound Familiar?',
items: {
expensive: {
title: 'High Subscription Costs',
desc: 'Paying for multiple AI subscriptions that add up every month'
},
complex: {
title: 'Account Chaos',
desc: 'Managing scattered accounts and API keys across different platforms'
},
unstable: {
title: 'Service Interruptions',
desc: 'Single accounts hitting rate limits and disrupting your workflow'
},
noControl: {
title: 'No Usage Control',
desc: "Can't track where your money goes or limit team member usage"
}
}
},
// Solutions section
solutions: {
title: 'We Solve These Problems',
subtitle: 'Three simple steps to stress-free AI access'
},
features: {
unifiedGateway: 'Unified API Gateway',
unifiedGatewayDesc:
'Convert Claude subscriptions to API endpoints. Access AI capabilities through standard /v1/messages interface.',
multiAccount: 'Multi-Account Pool',
multiAccountDesc:
'Manage multiple upstream accounts with smart load balancing. Support OAuth and API Key authentication.',
balanceQuota: 'Balance & Quota',
balanceQuotaDesc:
'Token-based billing with precise usage tracking. Manage quotas and recharge with redeem codes.'
unifiedGateway: 'One-Click Access',
unifiedGatewayDesc: 'Get a single API key to call all connected AI models. No separate applications needed.',
multiAccount: 'Always Reliable',
multiAccountDesc: 'Smart routing across multiple upstream accounts with automatic failover. Say goodbye to errors.',
balanceQuota: 'Pay What You Use',
balanceQuotaDesc: 'Usage-based billing with quota limits. Full visibility into team consumption.'
},
// Comparison section
comparison: {
title: 'Why Choose Us?',
headers: {
feature: 'Comparison',
official: 'Official Subscriptions',
us: 'Our Platform'
},
items: {
pricing: {
feature: 'Pricing',
official: 'Fixed monthly fee, pay even if unused',
us: 'Pay only for what you use'
},
models: {
feature: 'Model Selection',
official: 'Single provider only',
us: 'Switch between models freely'
},
management: {
feature: 'Account Management',
official: 'Manage each service separately',
us: 'Unified key, one dashboard'
},
stability: {
feature: 'Stability',
official: 'Single account rate limits',
us: 'Multi-account pool, auto-failover'
},
control: {
feature: 'Usage Control',
official: 'Not available',
us: 'Quotas & detailed analytics'
}
}
},
providers: {
title: 'Supported Providers',
description: 'Unified API interface for AI services',
title: 'Supported AI Models',
description: 'One API, Multiple Choices',
supported: 'Supported',
soon: 'Soon',
claude: 'Claude',
@@ -36,6 +99,12 @@ export default {
antigravity: 'Antigravity',
more: 'More'
},
// CTA section
cta: {
title: 'Ready to Get Started?',
description: 'Sign up now and get free trial credits to experience seamless AI access',
button: 'Sign Up Free'
},
footer: {
allRightsReserved: 'All rights reserved.'
}
@@ -165,6 +234,7 @@ export default {
selectedCount: '({count} selected)',
refresh: 'Refresh',
settings: 'Settings',
chooseFile: 'Choose File',
notAvailable: 'N/A',
now: 'Now',
unknown: 'Unknown',
@@ -1207,6 +1277,28 @@ export default {
refreshInterval30s: '30 seconds',
autoRefreshCountdown: 'Auto refresh: {seconds}s',
syncFromCrs: 'Sync from CRS',
dataExport: 'Export',
dataExportSelected: 'Export Selected',
dataExportIncludeProxies: 'Include proxies linked to the exported accounts',
dataImport: 'Import',
dataExportConfirmMessage: 'The exported data contains sensitive account and proxy information. Store it securely.',
dataExportConfirm: 'Confirm Export',
dataExported: 'Data exported successfully',
dataExportFailed: 'Failed to export data',
dataImportTitle: 'Import Data',
dataImportHint: 'Upload the exported JSON file to import accounts and proxies.',
dataImportWarning: 'Import will create new accounts/proxies; groups must be bound manually. Ensure existing data does not conflict.',
dataImportFile: 'Data file',
dataImportButton: 'Start Import',
dataImporting: 'Importing...',
dataImportSelectFile: 'Please select a data file',
dataImportParseFailed: 'Failed to parse data file',
dataImportFailed: 'Data import failed',
dataImportResult: 'Import Result',
dataImportResultSummary: 'Proxies created {proxy_created}, reused {proxy_reused}, failed {proxy_failed}; Accounts created {account_created}, failed {account_failed}',
dataImportErrors: 'Error Details',
dataImportSuccess: 'Import completed: accounts {account_created}, failed {account_failed}',
dataImportCompletedWithErrors: 'Import completed with errors: account failed {account_failed}, proxy failed {proxy_failed}',
syncFromCrsTitle: 'Sync Accounts from CRS',
syncFromCrsDesc:
'Sync accounts from claude-relay-service (CRS) into this system (CRS is called server-to-server).',
@@ -1275,6 +1367,7 @@ export default {
tempUnschedulable: 'Temp Unschedulable',
rateLimitedUntil: 'Rate limited until {time}',
scopeRateLimitedUntil: '{scope} rate limited until {time}',
modelRateLimitedUntil: '{model} rate limited until {time}',
overloadedUntil: 'Overloaded until {time}',
viewTempUnschedDetails: 'View temp unschedulable details'
},
@@ -1439,6 +1532,8 @@ export default {
actualModel: 'Actual model',
addMapping: 'Add Mapping',
mappingExists: 'Mapping for {model} already exists',
wildcardOnlyAtEnd: 'Wildcard * can only be at the end',
targetNoWildcard: 'Target model cannot contain wildcard *',
searchModels: 'Search models...',
noMatchingModels: 'No matching models',
fillRelatedModels: 'Fill related models',
@@ -1906,6 +2001,27 @@ export default {
createProxy: 'Create Proxy',
editProxy: 'Edit Proxy',
deleteProxy: 'Delete Proxy',
dataImport: 'Import',
dataExportSelected: 'Export Selected',
dataImportTitle: 'Import Proxies',
dataImportHint: 'Upload the exported proxy JSON file to import proxies in bulk.',
dataImportWarning: 'Import will create or reuse proxies, keep their status, and trigger latency checks after completion.',
dataImportFile: 'Data File',
dataImportButton: 'Start Import',
dataImporting: 'Importing...',
dataImportSelectFile: 'Please select a data file',
dataImportParseFailed: 'Failed to parse data',
dataImportFailed: 'Failed to import data',
dataImportResult: 'Import Result',
dataImportResultSummary: 'Created {proxy_created}, reused {proxy_reused}, failed {proxy_failed}',
dataImportErrors: 'Failure Details',
dataImportSuccess: 'Import completed: created {proxy_created}, reused {proxy_reused}',
dataImportCompletedWithErrors: 'Import completed with errors: failed {proxy_failed}',
dataExport: 'Export',
dataExportConfirmMessage: 'The exported data contains sensitive proxy information. Store it securely.',
dataExportConfirm: 'Confirm Export',
dataExported: 'Data exported successfully',
dataExportFailed: 'Failed to export data',
searchProxies: 'Search proxies...',
allProtocols: 'All Protocols',
allStatus: 'All Status',
@@ -2941,6 +3057,10 @@ export default {
byPlatform: 'By Platform',
byGroup: 'By Group',
byAccount: 'By Account',
byUser: 'By User',
showByUserTooltip: 'Switch to user view to see concurrency usage per user',
switchToUser: 'Switch to user view',
switchToPlatform: 'Switch to platform view',
totalRows: '{count} rows',
disabledHint: 'Realtime monitoring is disabled in settings.',
empty: 'No data',

View File

@@ -8,24 +8,90 @@ export default {
switchToDark: '切换到深色模式',
dashboard: '控制台',
login: '登录',
getStarted: '开始使用',
getStarted: '立即开始',
goToDashboard: '进入控制台',
// 新增:面向用户的价值主张
heroSubtitle: '一个密钥,畅用多个 AI 模型',
heroDescription: '无需管理多个订阅账号,一站式接入 Claude、GPT、Gemini 等主流 AI 服务',
tags: {
subscriptionToApi: '订阅转 API',
stickySession: '粘性会话',
realtimeBilling: '实时计费'
stickySession: '会话保持',
realtimeBilling: '按量计费'
},
// 用户痛点区块
painPoints: {
title: '你是否也遇到这些问题?',
items: {
expensive: {
title: '订阅费用高',
desc: '每个 AI 服务都要单独订阅,每月支出越来越多'
},
complex: {
title: '多账号难管理',
desc: '不同平台的账号、密钥分散各处,管理起来很麻烦'
},
unstable: {
title: '服务不稳定',
desc: '单一账号容易触发限制,影响正常使用'
},
noControl: {
title: '用量无法控制',
desc: '不知道钱花在哪了,也无法限制团队成员的使用'
}
}
},
// 解决方案区块
solutions: {
title: '我们帮你解决',
subtitle: '简单三步,开始省心使用 AI'
},
features: {
unifiedGateway: '统一 API 网关',
unifiedGatewayDesc: '将 Claude 订阅转换为 API 接口,通过标准 /v1/messages 接口访问 AI 能力。',
multiAccount: '多账号池',
multiAccountDesc: '智能负载均衡管理多个上游账号,支持 OAuth 和 API Key 认证。',
balanceQuota: '余额与配额',
balanceQuotaDesc: '基于 Token 的精确计费和用量追踪,支持配额管理和兑换码充值。'
unifiedGateway: '一键接入',
unifiedGatewayDesc: '获取一个 API 密钥,即可调用所有已接入的 AI 模型,无需分别申请。',
multiAccount: '稳定可靠',
multiAccountDesc: '智能调度多个上游账号,自动切换和负载均衡,告别频繁报错。',
balanceQuota: '用多少付多少',
balanceQuotaDesc: '按实际使用量计费,支持设置配额上限,团队用量一目了然。'
},
// 优势对比
comparison: {
title: '为什么选择我们?',
headers: {
feature: '对比项',
official: '官方订阅',
us: '本平台'
},
items: {
pricing: {
feature: '付费方式',
official: '固定月费,用不完也付',
us: '按量付费,用多少付多少'
},
models: {
feature: '模型选择',
official: '单一服务商',
us: '多模型随意切换'
},
management: {
feature: '账号管理',
official: '每个服务单独管理',
us: '统一密钥,一站管理'
},
stability: {
feature: '服务稳定性',
official: '单账号易触发限制',
us: '多账号池,自动切换'
},
control: {
feature: '用量控制',
official: '无法限制',
us: '可设配额、查明细'
}
}
},
providers: {
title: '支持的服务商',
description: 'AI 服务的统一 API 接口',
title: '支持的 AI 模型',
description: '一个 API多种选择',
supported: '已支持',
soon: '即将推出',
claude: 'Claude',
@@ -33,6 +99,12 @@ export default {
antigravity: 'Antigravity',
more: '更多'
},
// CTA 区块
cta: {
title: '准备好开始了吗?',
description: '注册即可获得免费试用额度,体验一站式 AI 服务',
button: '免费注册'
},
footer: {
allRightsReserved: '保留所有权利。'
}
@@ -162,6 +234,7 @@ export default {
selectedCount: '(已选 {count} 个)',
refresh: '刷新',
settings: '设置',
chooseFile: '选择文件',
notAvailable: '不可用',
now: '现在',
unknown: '未知',
@@ -1292,6 +1365,28 @@ export default {
refreshInterval30s: '30 秒',
autoRefreshCountdown: '自动刷新:{seconds}s',
syncFromCrs: '从 CRS 同步',
dataExport: '导出',
dataExportSelected: '导出选中',
dataExportIncludeProxies: '导出代理(导出账号关联的代理)',
dataImport: '导入',
dataExportConfirmMessage: '导出的数据包含账号与代理的敏感信息,请妥善保存。',
dataExportConfirm: '确认导出',
dataExported: '数据导出成功',
dataExportFailed: '数据导出失败',
dataImportTitle: '导入数据',
dataImportHint: '上传导出的 JSON 文件以批量导入账号与代理。',
dataImportWarning: '导入将创建新账号与代理,分组需手工绑定;请确认已有数据不会冲突。',
dataImportFile: '数据文件',
dataImportButton: '开始导入',
dataImporting: '导入中...',
dataImportSelectFile: '请选择数据文件',
dataImportParseFailed: '数据解析失败',
dataImportFailed: '数据导入失败',
dataImportResult: '导入结果',
dataImportResultSummary: '代理创建 {proxy_created},复用 {proxy_reused},失败 {proxy_failed};账号创建 {account_created},失败 {account_failed}',
dataImportErrors: '失败详情',
dataImportSuccess: '导入完成:账号 {account_created},失败 {account_failed}',
dataImportCompletedWithErrors: '导入完成但有错误:账号失败 {account_failed},代理失败 {proxy_failed}',
syncFromCrsTitle: '从 CRS 同步账号',
syncFromCrsDesc:
'将 claude-relay-serviceCRS中的账号同步到当前系统不会在浏览器侧直接请求 CRS。',
@@ -1408,6 +1503,7 @@ export default {
tempUnschedulable: '临时不可调度',
rateLimitedUntil: '限流中,重置时间:{time}',
scopeRateLimitedUntil: '{scope} 限流中,重置时间:{time}',
modelRateLimitedUntil: '{model} 限流至 {time}',
overloadedUntil: '负载过重,重置时间:{time}',
viewTempUnschedDetails: '查看临时不可调度详情'
},
@@ -1584,6 +1680,8 @@ export default {
actualModel: '实际模型',
addMapping: '添加映射',
mappingExists: '模型 {model} 的映射已存在',
wildcardOnlyAtEnd: '通配符 * 只能放在末尾',
targetNoWildcard: '目标模型不能包含通配符 *',
searchModels: '搜索模型...',
noMatchingModels: '没有匹配的模型',
fillRelatedModels: '填入相关模型',
@@ -2015,6 +2113,27 @@ export default {
deleteProxy: '删除代理',
deleteConfirmMessage: "确定要删除代理 '{name}' 吗?",
testProxy: '测试代理',
dataImport: '导入',
dataExportSelected: '导出选中',
dataImportTitle: '导入代理',
dataImportHint: '上传代理导出的 JSON 文件以批量导入代理。',
dataImportWarning: '导入将创建或复用代理,保留状态并在完成后自动触发延迟检测。',
dataImportFile: '数据文件',
dataImportButton: '开始导入',
dataImporting: '导入中...',
dataImportSelectFile: '请选择数据文件',
dataImportParseFailed: '数据解析失败',
dataImportFailed: '数据导入失败',
dataImportResult: '导入结果',
dataImportResultSummary: '创建 {proxy_created},复用 {proxy_reused},失败 {proxy_failed}',
dataImportErrors: '失败详情',
dataImportSuccess: '导入完成:创建 {proxy_created},复用 {proxy_reused}',
dataImportCompletedWithErrors: '导入完成但有错误:失败 {proxy_failed}',
dataExport: '导出',
dataExportConfirmMessage: '导出的数据包含代理的敏感信息,请妥善保存。',
dataExportConfirm: '确认导出',
dataExported: '数据导出成功',
dataExportFailed: '数据导出失败',
columns: {
name: '名称',
protocol: '协议',
@@ -3111,6 +3230,10 @@ export default {
byPlatform: '按平台',
byGroup: '按分组',
byAccount: '按账号',
byUser: '按用户',
showByUserTooltip: '切换用户视图,显示每个用户的并发使用情况',
switchToUser: '切换到用户视图',
switchToPlatform: '切换回平台视图',
totalRows: '共 {count} 项',
disabledHint: '已在设置中关闭实时监控。',
empty: '暂无数据',