mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-09-22 06:40:21 +08:00
feat(frontend): 标明 OpenAI 认证模式
This commit is contained in:
@@ -276,7 +276,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Codex OAuth/session JSON batch import -->
|
||||
<!-- Codex auth.json / session credential batch import -->
|
||||
<div v-if="inputMethod === 'codex_session'" class="space-y-4">
|
||||
<div
|
||||
class="rounded-lg border border-blue-300 bg-white/80 p-4 dark:border-blue-600 dark:bg-gray-800/80"
|
||||
|
||||
@@ -77,6 +77,7 @@ const { t } = useI18n()
|
||||
interface Props {
|
||||
platform: AccountPlatform
|
||||
type: AccountType
|
||||
authMode?: string
|
||||
planType?: string
|
||||
privacyMode?: string
|
||||
subscriptionExpiresAt?: string
|
||||
@@ -92,7 +93,15 @@ const platformLabel = computed(() => {
|
||||
return 'Gemini'
|
||||
})
|
||||
|
||||
const normalizedAuthMode = computed(() =>
|
||||
(props.authMode || '').trim().toLowerCase().replace(/[\s_-]+/g, '')
|
||||
)
|
||||
|
||||
const typeLabel = computed(() => {
|
||||
if (props.platform === 'openai' && props.type === 'oauth') {
|
||||
if (normalizedAuthMode.value === 'agentidentity') return 'Agent Identity'
|
||||
if (normalizedAuthMode.value === 'personalaccesstoken') return 'PAT'
|
||||
}
|
||||
switch (props.type) {
|
||||
case 'oauth':
|
||||
return 'OAuth'
|
||||
|
||||
@@ -62,3 +62,24 @@ describe('PlatformTypeBadge Grok plans', () => {
|
||||
expect(wrapper.findAll('path')).toHaveLength(2)
|
||||
})
|
||||
})
|
||||
|
||||
describe('PlatformTypeBadge OpenAI authentication modes', () => {
|
||||
it('distinguishes Agent Identity, PAT, and OAuth accounts', async () => {
|
||||
const wrapper = mount(PlatformTypeBadge, {
|
||||
props: {
|
||||
platform: 'openai',
|
||||
type: 'oauth',
|
||||
authMode: 'agentIdentity',
|
||||
},
|
||||
})
|
||||
|
||||
expect(wrapper.text()).toContain('Agent Identity')
|
||||
|
||||
await wrapper.setProps({ authMode: 'personalAccessToken' })
|
||||
expect(wrapper.text()).toContain('PAT')
|
||||
expect(wrapper.text()).not.toContain('Agent Identity')
|
||||
|
||||
await wrapper.setProps({ authMode: undefined })
|
||||
expect(wrapper.text()).toContain('OAuth')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -822,13 +822,13 @@ export default {
|
||||
refreshTokenAuth: 'Manual RT Input',
|
||||
refreshTokenDesc: 'Enter your existing OpenAI Refresh Token(s). Supports batch input (one per line). The system will automatically validate and create accounts.',
|
||||
refreshTokenPlaceholder: 'Paste your OpenAI Refresh Token...\nSupports multiple, one per line',
|
||||
codexSessionAuth: 'Codex JSON / AT Batch Input',
|
||||
codexSessionDesc: 'Paste Codex JSON or an accessToken. Accounts use the step 1 settings.',
|
||||
codexSessionInputLabel: 'Codex JSON or accessToken',
|
||||
codexSessionPlaceholder: 'Multiple lines supported, one token or JSON per line',
|
||||
codexSessionHint: 'sessionToken will not be saved as refresh_token. Without refresh_token, the account expires with the accessToken expiry; import is rejected if the expiry cannot be parsed and step 1 has no expiration.',
|
||||
codexSessionAuth: 'Codex auth.json / AT Import',
|
||||
codexSessionDesc: 'Paste a Codex auth.json (OAuth or Agent Identity) or an accessToken. Accounts use the step 1 settings.',
|
||||
codexSessionInputLabel: 'Codex auth.json or accessToken',
|
||||
codexSessionPlaceholder: 'Multiple lines supported, one token or auth.json object per line',
|
||||
codexSessionHint: 'Agent Identity keeps no OAuth token and signs each upstream request dynamically. Session/access-token imports retain their existing expiration behavior.',
|
||||
codexSessionImportAndCreate: 'Import & Create Account',
|
||||
codexSessionEmpty: 'Please enter Codex JSON or accessToken',
|
||||
codexSessionEmpty: 'Please enter a Codex auth.json or accessToken',
|
||||
codexSessionImportFailed: 'Failed to import Codex account',
|
||||
codexSessionImportSuccess: 'Import completed: created {created}, updated {updated}, skipped {skipped}',
|
||||
codexSessionImportPartial: 'Partial success: created {created}, updated {updated}, skipped {skipped}, failed {failed}',
|
||||
|
||||
@@ -909,13 +909,13 @@ export default {
|
||||
refreshTokenAuth: '手动输入 RT',
|
||||
refreshTokenDesc: '输入您已有的 OpenAI Refresh Token,支持批量输入(每行一个),系统将自动验证并创建账号。',
|
||||
refreshTokenPlaceholder: '粘贴您的 OpenAI Refresh Token...\n支持多个,每行一个',
|
||||
codexSessionAuth: 'Codex JSON / AT 批量输入',
|
||||
codexSessionDesc: '粘贴 Codex JSON 或 accessToken,按第一步配置创建账号。',
|
||||
codexSessionInputLabel: 'Codex JSON 或 accessToken',
|
||||
codexSessionPlaceholder: '支持多行,每行一个 token 或 JSON',
|
||||
codexSessionHint: 'sessionToken 不会作为 refresh_token 保存;未包含 refresh_token 时会按 accessToken 过期时间设置账号过期,无法解析且第一步未设置过期时间时会拒绝导入。',
|
||||
codexSessionAuth: 'Codex auth.json / AT 导入',
|
||||
codexSessionDesc: '粘贴 Codex auth.json(OAuth 或 Agent Identity)或 accessToken,按第一步配置创建账号。',
|
||||
codexSessionInputLabel: 'Codex auth.json 或 accessToken',
|
||||
codexSessionPlaceholder: '支持多行,每行一个 token 或 auth.json 对象',
|
||||
codexSessionHint: 'Agent Identity 不保存 OAuth token,并为每次上游请求动态签名;session/accessToken 导入继续沿用原有过期规则。',
|
||||
codexSessionImportAndCreate: '导入并创建账号',
|
||||
codexSessionEmpty: '请输入 Codex JSON 或 accessToken',
|
||||
codexSessionEmpty: '请输入 Codex auth.json 或 accessToken',
|
||||
codexSessionImportFailed: 'Codex 账号导入失败',
|
||||
codexSessionImportSuccess: '导入完成:新增 {created},更新 {updated},跳过 {skipped}',
|
||||
codexSessionImportPartial: '部分成功:新增 {created},更新 {updated},跳过 {skipped},失败 {failed}',
|
||||
|
||||
@@ -234,6 +234,7 @@
|
||||
<div class="flex min-w-0 flex-col gap-1">
|
||||
<div class="flex flex-wrap items-center gap-1">
|
||||
<PlatformTypeBadge :platform="row.platform" :type="row.type"
|
||||
:auth-mode="getOpenAIAuthMode(row)"
|
||||
:plan-type="getAccountPlanType(row)"
|
||||
:privacy-mode="row.extra?.privacy_mode || row.parent_privacy_mode"
|
||||
:subscription-expires-at="row.credentials?.subscription_expires_at || row.parent_subscription_expires_at" />
|
||||
@@ -1167,6 +1168,12 @@ function getAccountPlanType(row: any): string | undefined {
|
||||
return row.credentials?.plan_type || row.parent_plan_type || undefined
|
||||
}
|
||||
|
||||
function getOpenAIAuthMode(row: any): string | undefined {
|
||||
if (!row || row.platform !== 'openai' || row.type !== 'oauth') return undefined
|
||||
const authMode = row.credentials?.auth_mode
|
||||
return typeof authMode === 'string' && authMode.trim() ? authMode : undefined
|
||||
}
|
||||
|
||||
// Antigravity 订阅等级辅助函数
|
||||
function getAntigravityTierFromRow(row: any): string | null {
|
||||
if (row.platform !== 'antigravity') return null
|
||||
|
||||
Reference in New Issue
Block a user