diff --git a/src/components/quota/quotaConfigs.ts b/src/components/quota/quotaConfigs.ts index 5be4331..096bc1f 100644 --- a/src/components/quota/quotaConfigs.ts +++ b/src/components/quota/quotaConfigs.ts @@ -45,6 +45,7 @@ import { getStatusFromError, isAntigravityFile, isCodexFile, + isDisabledAuthFile, isGeminiCliFile, isRuntimeOnlyAuthFile } from '@/utils/quota'; @@ -519,7 +520,7 @@ const renderGeminiCliItems = ( export const ANTIGRAVITY_CONFIG: QuotaConfig = { type: 'antigravity', i18nPrefix: 'antigravity_quota', - filterFn: (file) => isAntigravityFile(file), + filterFn: (file) => isAntigravityFile(file) && !isDisabledAuthFile(file), fetchQuota: fetchAntigravityQuota, storeSelector: (state) => state.antigravityQuota, storeSetter: 'setAntigravityQuota', @@ -544,7 +545,7 @@ export const CODEX_CONFIG: QuotaConfig< > = { type: 'codex', i18nPrefix: 'codex_quota', - filterFn: (file) => isCodexFile(file), + filterFn: (file) => isCodexFile(file) && !isDisabledAuthFile(file), fetchQuota: fetchCodexQuota, storeSelector: (state) => state.codexQuota, storeSetter: 'setCodexQuota', @@ -570,7 +571,8 @@ export const CODEX_CONFIG: QuotaConfig< export const GEMINI_CLI_CONFIG: QuotaConfig = { type: 'gemini-cli', i18nPrefix: 'gemini_cli_quota', - filterFn: (file) => isGeminiCliFile(file) && !isRuntimeOnlyAuthFile(file), + filterFn: (file) => + isGeminiCliFile(file) && !isRuntimeOnlyAuthFile(file) && !isDisabledAuthFile(file), fetchQuota: fetchGeminiCliQuota, storeSelector: (state) => state.geminiCliQuota, storeSetter: 'setGeminiCliQuota', diff --git a/src/pages/AuthFilesPage.module.scss b/src/pages/AuthFilesPage.module.scss index 0230d0d..7ce60d2 100644 --- a/src/pages/AuthFilesPage.module.scss +++ b/src/pages/AuthFilesPage.module.scss @@ -79,6 +79,9 @@ } .filterTag { + display: inline-flex; + align-items: center; + gap: 8px; padding: 6px 14px; border-radius: 20px; font-size: 13px; @@ -97,6 +100,16 @@ font-weight: 600; } +.filterTagLabel { + white-space: nowrap; +} + +.filterTagCount { + font-size: 12px; + font-weight: 600; + opacity: 0.85; +} + .filterControls { display: flex; gap: $spacing-md; diff --git a/src/pages/AuthFilesPage.tsx b/src/pages/AuthFilesPage.tsx index b1328a8..abe76d1 100644 --- a/src/pages/AuthFilesPage.tsx +++ b/src/pages/AuthFilesPage.tsx @@ -453,6 +453,15 @@ export function AuthFilesPage() { return Array.from(types); }, [files]); + const typeCounts = useMemo(() => { + const counts: Record = { all: files.length }; + files.forEach((file) => { + if (!file.type) return; + counts[file.type] = (counts[file.type] || 0) + 1; + }); + return counts; + }, [files]); + // 过滤和搜索 const filtered = useMemo(() => { return files.filter((item) => { @@ -1006,7 +1015,8 @@ export function AuthFilesPage() { setPage(1); }} > - {getTypeLabel(type)} + {getTypeLabel(type)} + {typeCounts[type] ?? 0} ); })} diff --git a/src/utils/quota/validators.ts b/src/utils/quota/validators.ts index 61ac41d..ba90c3c 100644 --- a/src/utils/quota/validators.ts +++ b/src/utils/quota/validators.ts @@ -29,6 +29,14 @@ export function isRuntimeOnlyAuthFile(file: AuthFileItem): boolean { return false; } +export function isDisabledAuthFile(file: AuthFileItem): boolean { + const raw = (file as { disabled?: unknown }).disabled; + if (typeof raw === 'boolean') return raw; + if (typeof raw === 'number') return raw !== 0; + if (typeof raw === 'string') return raw.trim().toLowerCase() === 'true'; + return false; +} + export function isIgnoredGeminiCliModel(modelId: string): boolean { return GEMINI_CLI_IGNORED_MODEL_PREFIXES.some( (prefix) => modelId === prefix || modelId.startsWith(`${prefix}-`)