mirror of
https://github.com/router-for-me/Cli-Proxy-API-Management-Center.git
synced 2026-06-16 21:03:58 +08:00
feat(ai-providers): add Vertex AI config toggle
This commit is contained in:
@@ -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}>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user