feat(ai-providers): add Vertex AI config toggle

This commit is contained in:
Supra4E8C
2026-03-14 15:25:29 +08:00
parent e833c03c68
commit df96297c68
2 changed files with 41 additions and 6 deletions
@@ -2,6 +2,7 @@ import { Fragment, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { Button } from '@/components/ui/Button';
import { Card } from '@/components/ui/Card';
import { ToggleSwitch } from '@/components/ui/ToggleSwitch';
import iconVertex from '@/assets/icons/vertex.svg';
import type { ProviderKeyConfig } from '@/types';
import { maskApiKey } from '@/utils/format';
@@ -14,7 +15,7 @@ import {
import styles from '@/pages/AiProvidersPage.module.scss';
import { ProviderList } from '../ProviderList';
import { ProviderStatusBar } from '../ProviderStatusBar';
import { getStatsBySource } from '../utils';
import { getStatsBySource, hasDisableAllModelsRule } from '../utils';
interface VertexSectionProps {
configs: ProviderKeyConfig[];
@@ -26,6 +27,7 @@ interface VertexSectionProps {
onAdd: () => void;
onEdit: (index: number) => void;
onDelete: (index: number) => void;
onToggle: (index: number, enabled: boolean) => void;
}
export function VertexSection({
@@ -38,9 +40,11 @@ export function VertexSection({
onAdd,
onEdit,
onDelete,
onToggle,
}: VertexSectionProps) {
const { t } = useTranslation();
const actionsDisabled = disableControls || loading || isSwitching;
const toggleDisabled = disableControls || loading || isSwitching;
const statusBarCache = useMemo(() => {
const cache = new Map<string, ReturnType<typeof calculateStatusBarData>>();
@@ -84,9 +88,19 @@ export function VertexSection({
onEdit={onEdit}
onDelete={onDelete}
actionsDisabled={actionsDisabled}
getRowDisabled={(item) => hasDisableAllModelsRule(item.excludedModels)}
renderExtraActions={(item, index) => (
<ToggleSwitch
label={t('ai_providers.config_toggle_label')}
checked={!hasDisableAllModelsRule(item.excludedModels)}
disabled={toggleDisabled}
onChange={(value) => void onToggle(index, value)}
/>
)}
renderContent={(item, index) => {
const stats = getStatsBySource(item.apiKey, keyStats, item.prefix);
const headerEntries = Object.entries(item.headers || {});
const configDisabled = hasDisableAllModelsRule(item.excludedModels);
const excludedModels = item.excludedModels ?? [];
const statusData = statusBarCache.get(item.apiKey) || calculateStatusBarData([]);
@@ -126,6 +140,11 @@ export function VertexSection({
))}
</div>
)}
{configDisabled && (
<div className="status-badge warning" style={{ marginTop: 8, marginBottom: 0 }}>
{t('ai_providers.config_disabled_badge')}
</div>
)}
{item.models?.length ? (
<div className={styles.modelTagList}>
<span className={styles.modelCountLabel}>
+21 -5
View File
@@ -164,7 +164,7 @@ export function AiProvidersPage() {
};
const setConfigEnabled = async (
provider: 'gemini' | 'codex' | 'claude',
provider: 'gemini' | 'codex' | 'claude' | 'vertex',
index: number,
enabled: boolean
) => {
@@ -204,7 +204,12 @@ export function AiProvidersPage() {
return;
}
const source = provider === 'codex' ? codexConfigs : claudeConfigs;
const source =
provider === 'codex'
? codexConfigs
: provider === 'claude'
? claudeConfigs
: vertexConfigs;
const current = source[index];
if (!current) return;
@@ -222,17 +227,23 @@ export function AiProvidersPage() {
setCodexConfigs(nextList);
updateConfigValue('codex-api-key', nextList);
clearCache('codex-api-key');
} else {
} else if (provider === 'claude') {
setClaudeConfigs(nextList);
updateConfigValue('claude-api-key', nextList);
clearCache('claude-api-key');
} else {
setVertexConfigs(nextList);
updateConfigValue('vertex-api-key', nextList);
clearCache('vertex-api-key');
}
try {
if (provider === 'codex') {
await providersApi.saveCodexConfigs(nextList);
} else {
} else if (provider === 'claude') {
await providersApi.saveClaudeConfigs(nextList);
} else {
await providersApi.saveVertexConfigs(nextList);
}
showNotification(
enabled ? t('notification.config_enabled') : t('notification.config_disabled'),
@@ -244,10 +255,14 @@ export function AiProvidersPage() {
setCodexConfigs(previousList);
updateConfigValue('codex-api-key', previousList);
clearCache('codex-api-key');
} else {
} else if (provider === 'claude') {
setClaudeConfigs(previousList);
updateConfigValue('claude-api-key', previousList);
clearCache('claude-api-key');
} else {
setVertexConfigs(previousList);
updateConfigValue('vertex-api-key', previousList);
clearCache('vertex-api-key');
}
showNotification(`${t('notification.update_failed')}: ${message}`, 'error');
} finally {
@@ -400,6 +415,7 @@ export function AiProvidersPage() {
onAdd={() => openEditor('/ai-providers/vertex/new')}
onEdit={(index) => openEditor(`/ai-providers/vertex/${index}`)}
onDelete={deleteVertex}
onToggle={(index, enabled) => void setConfigEnabled('vertex', index, enabled)}
/>
</div>