@@ -195,7 +212,7 @@
- 原始值除以该数得到实际余额。New-API 填 500000,Sub2API 填 1
+ 原始值除以该数得到实际余额。New-API / Nox-API 填 500000,Sub2API 填 1
@@ -462,6 +479,7 @@ const authCaptureInitialUrl = computed(() => {
const authCapturePreferredTypes = computed(() => {
if (quickPlatform.value === 'sub2api') return ['bearer_token', 'api_key', 'cookie_bundle', 'cookie']
if (quickPlatform.value === 'new-api-user') return ['cookie_bundle', 'cookie', 'bearer_token', 'api_key']
+ if (quickPlatform.value === 'nox-api') return ['cookie_bundle', 'cookie', 'bearer_token', 'api_key']
return ['bearer_token', 'api_key', 'cookie_bundle', 'cookie']
})
@@ -477,28 +495,45 @@ function handleAuthCaptureSelect(candidate: {
cookie_count?: number
cookie_names?: string[]
new_api_user?: string
+ user_id?: string
}) {
if (candidate.type === 'bearer_token') {
- form.value.auth_type = 'bearer'
- form.value.auth_config.token = candidate.value
- ElMessage.success('已填入 Bearer Token')
+ if (quickPlatform.value === 'nox-api') {
+ form.value.auth_type = 'nox_token'
+ form.value.auth_config.token = candidate.value
+ form.value.auth_config.provider = 'nox-api'
+ if (candidate.user_id || candidate.new_api_user) {
+ form.value.auth_config.user_id = candidate.user_id || candidate.new_api_user
+ }
+ ElMessage.success('已填入 Nox Access Token')
+ } else {
+ form.value.auth_type = 'bearer'
+ form.value.auth_config.token = candidate.value
+ ElMessage.success('已填入 Bearer Token')
+ }
} else if (candidate.type === 'cookie_bundle') {
// 完整 cookie 组:value 已是完整 "name1=v1; name2=v2" 字符串
form.value.auth_type = 'cookie'
form.value.auth_config.cookie_string = candidate.value
+ if (quickPlatform.value === 'nox-api' || quickPlatform.value === 'new-api-user') {
+ form.value.auth_config.provider = quickPlatform.value
+ }
if (quickPlatform.value === 'sub2api') {
ElMessage.warning('Sub2API 通常需要 Bearer Token;Cookie 只能在确认上游支持 Cookie 鉴权时使用')
}
if (candidate.new_api_user) {
form.value.auth_config.new_api_user = candidate.new_api_user
+ form.value.auth_config.user_id = candidate.user_id || candidate.new_api_user
form.value.api_prefix = ''
form.value.groups_endpoint = '/api/user/self/groups'
form.value.rate_endpoint = '/api/user/self/groups'
- } else if (quickPlatform.value === 'new-api-user') {
+ } else if (quickPlatform.value === 'new-api-user' || quickPlatform.value === 'nox-api') {
form.value.api_prefix = ''
form.value.groups_endpoint = '/api/user/self/groups'
form.value.rate_endpoint = '/api/user/self/groups'
- ElMessage.warning('已填入完整 Cookie 组,但未提取到 New-Api-User,请重新登录后再提取')
+ if (quickPlatform.value === 'new-api-user' || quickPlatform.value === 'nox-api') {
+ ElMessage.warning(`已填入完整 Cookie 组,但未提取到 ${quickPlatform.value === 'nox-api' ? 'Nox-Api-User' : 'New-Api-User'},请重新登录后再提取`)
+ }
}
const countLabel = candidate.cookie_count ? `(${candidate.cookie_count} 个 cookie)` : ''
ElMessage.success(`已填入完整 Cookie 组${countLabel}`)
@@ -507,19 +542,25 @@ function handleAuthCaptureSelect(candidate: {
form.value.auth_config.cookie_string = candidate.cookie_name && candidate.cookie_value
? `${candidate.cookie_name}=${candidate.cookie_value}`
: candidate.value
+ if (quickPlatform.value === 'nox-api' || quickPlatform.value === 'new-api-user') {
+ form.value.auth_config.provider = quickPlatform.value
+ }
if (quickPlatform.value === 'sub2api') {
ElMessage.warning('Sub2API 通常需要 Bearer Token;Cookie 只能在确认上游支持 Cookie 鉴权时使用')
}
if (candidate.new_api_user) {
form.value.auth_config.new_api_user = candidate.new_api_user
+ form.value.auth_config.user_id = candidate.user_id || candidate.new_api_user
form.value.api_prefix = ''
form.value.groups_endpoint = '/api/user/self/groups'
form.value.rate_endpoint = '/api/user/self/groups'
- } else if (quickPlatform.value === 'new-api-user') {
+ } else if (quickPlatform.value === 'new-api-user' || quickPlatform.value === 'nox-api') {
form.value.api_prefix = ''
form.value.groups_endpoint = '/api/user/self/groups'
form.value.rate_endpoint = '/api/user/self/groups'
- ElMessage.warning('已填入 Cookie,但未提取到 New-Api-User,请重新登录后再提取')
+ if (quickPlatform.value === 'new-api-user' || quickPlatform.value === 'nox-api') {
+ ElMessage.warning(`已填入 Cookie,但未提取到 ${quickPlatform.value === 'nox-api' ? 'Nox-Api-User' : 'New-Api-User'},请重新登录后再提取`)
+ }
}
ElMessage.success('已填入 Cookie')
} else if (candidate.type === 'api_key') {
@@ -530,12 +571,20 @@ function handleAuthCaptureSelect(candidate: {
} else if (candidate.type === 'credential') {
// Try to guess — if value starts with 'sk-', treat as bearer
if (candidate.value.startsWith('sk-')) {
- form.value.auth_type = 'bearer'
+ form.value.auth_type = quickPlatform.value === 'nox-api' ? 'nox_token' : 'bearer'
form.value.auth_config.token = candidate.value
+ if (quickPlatform.value === 'nox-api') form.value.auth_config.provider = 'nox-api'
+ if (quickPlatform.value === 'nox-api' && (candidate.user_id || candidate.new_api_user)) {
+ form.value.auth_config.user_id = candidate.user_id || candidate.new_api_user
+ }
ElMessage.success('已填入 Bearer Token (sk-key)')
} else {
- form.value.auth_type = 'bearer'
+ form.value.auth_type = quickPlatform.value === 'nox-api' ? 'nox_token' : 'bearer'
form.value.auth_config.token = candidate.value
+ if (quickPlatform.value === 'nox-api') form.value.auth_config.provider = 'nox-api'
+ if (quickPlatform.value === 'nox-api' && (candidate.user_id || candidate.new_api_user)) {
+ form.value.auth_config.user_id = candidate.user_id || candidate.new_api_user
+ }
ElMessage.success('已填入认证信息')
}
}
@@ -543,6 +592,15 @@ function handleAuthCaptureSelect(candidate: {
const quickPlatform = ref('sub2api')
+function inferPlatform(row: Pick): string {
+ if (row.api_prefix?.replace(/^\/|\/$/g, '') === 'api/v1') return 'sub2api'
+ if (row.api_prefix === '' && row.groups_endpoint === '/api/user/self/groups') {
+ if (row.auth_type === 'nox_token' || row.auth_config_masked?.provider === 'nox-api') return 'nox-api'
+ return 'new-api-user'
+ }
+ return 'custom'
+}
+
function handlePlatformChange(val: string) {
if (val === 'sub2api') {
form.value.api_prefix = '/api/v1'
@@ -559,11 +617,21 @@ function handlePlatformChange(val: string) {
form.value.groups_endpoint = '/api/user/self/groups'
form.value.rate_endpoint = '/api/user/self/groups'
form.value.auth_type = 'login_password'
+ form.value.auth_config.provider = 'new-api-user'
form.value.auth_config.login_path = '/api/user/login'
form.value.auth_config.username_field = 'username'
form.value.balance_endpoint = '/api/user/self'
form.value.balance_response_path = 'data.quota'
form.value.balance_divisor = 500000
+ } else if (val === 'nox-api') {
+ form.value.api_prefix = ''
+ form.value.groups_endpoint = '/api/user/self/groups'
+ form.value.rate_endpoint = '/api/user/self/groups'
+ form.value.auth_type = 'nox_token'
+ form.value.auth_config = { token: '', user_id: '', provider: 'nox-api' }
+ form.value.balance_endpoint = '/api/user/self'
+ form.value.balance_response_path = 'data.quota'
+ form.value.balance_divisor = 500000
} else {
form.value.balance_endpoint = ''
form.value.balance_response_path = ''
@@ -613,13 +681,14 @@ const healthyRate = computed(() => {
const pendingChecks = computed(() => list.value.filter((item) => !item.last_checked_at).length)
-function isNewApiUserUpstream(row: UpstreamData | null) {
+function usesTokenEndpointUpstream(row: UpstreamData | null) {
if (!row) return false
return row.api_prefix === ''
&& (
row.groups_endpoint === '/api/user/self/groups'
|| row.auth_config_masked?.login_path === '/api/user/login'
|| Boolean(row.auth_config_masked?.new_api_user)
+ || row.auth_type === 'nox_token'
)
}
@@ -645,7 +714,7 @@ const recentChecks = computed(() =>
)
const statusLabel = (s: string) => ({ healthy: '健康', unhealthy: '异常', unknown: '未知' }[s] || s)
-const authLabel = (s: string) => ({ none: '无认证', bearer: 'Bearer', cookie: 'Cookie', api_key: 'API Key', login_password: '邮箱密码' }[s] || s)
+const authLabel = (s: string) => ({ none: '无认证', bearer: 'Bearer', nox_token: 'Nox Token', cookie: 'Cookie', api_key: 'API Key', login_password: '邮箱密码' }[s] || s)
function formatBalance(value: number | null | undefined): string {
if (value === null || value === undefined) return '—'
@@ -691,6 +760,7 @@ function openCreate() {
function openEdit(row: UpstreamData) {
editingId.value = row.id
+ quickPlatform.value = inferPlatform(row)
form.value = {
name: row.name,
base_url: row.base_url,
@@ -813,7 +883,7 @@ async function openKeyGenerate(row: UpstreamData) {
rate_limit_5h: 0,
rate_limit_1d: 0,
rate_limit_7d: 0,
- endpoint: isNewApiUserUpstream(row) ? '/api/token' : '/keys',
+ endpoint: usesTokenEndpointUpstream(row) ? '/api/token' : '/keys',
}
useKeyExpiry.value = false
keyExpiresDays.value = 30