mirror of
https://github.com/router-for-me/Cli-Proxy-API-Management-Center.git
synced 2026-06-16 21:03:58 +08:00
feat(AiProviders): integrate OpenAI providers fetching and update config handling
This commit is contained in:
@@ -148,6 +148,7 @@ export function AiProvidersOpenAIEditLayout() {
|
||||
|
||||
const config = useConfigStore((state) => state.config);
|
||||
const fetchConfig = useConfigStore((state) => state.fetchConfig);
|
||||
const updateConfigValue = useConfigStore((state) => state.updateConfigValue);
|
||||
const isCacheValid = useConfigStore((state) => state.isCacheValid);
|
||||
|
||||
const [providers, setProviders] = useState<OpenAIProviderConfig[]>(
|
||||
@@ -258,15 +259,25 @@ export function AiProvidersOpenAIEditLayout() {
|
||||
setLoading(true);
|
||||
}
|
||||
|
||||
fetchConfig('openai-compatibility')
|
||||
providersApi
|
||||
.getOpenAIProviders()
|
||||
.then((value) => {
|
||||
if (cancelled) return;
|
||||
setProviders(Array.isArray(value) ? (value as OpenAIProviderConfig[]) : []);
|
||||
const nextProviders = value || [];
|
||||
setProviders(nextProviders);
|
||||
updateConfigValue('openai-compatibility', nextProviders);
|
||||
})
|
||||
.catch((err: unknown) => {
|
||||
.catch(async (err: unknown) => {
|
||||
if (cancelled) return;
|
||||
const message = getErrorMessage(err) || t('notification.refresh_failed');
|
||||
showNotification(`${t('notification.load_failed')}: ${message}`, 'error');
|
||||
try {
|
||||
const fallback = await fetchConfig('openai-compatibility');
|
||||
if (cancelled) return;
|
||||
setProviders(Array.isArray(fallback) ? (fallback as OpenAIProviderConfig[]) : []);
|
||||
} catch {
|
||||
if (cancelled) return;
|
||||
const message = getErrorMessage(err) || t('notification.refresh_failed');
|
||||
showNotification(`${t('notification.load_failed')}: ${message}`, 'error');
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
if (cancelled) return;
|
||||
@@ -276,7 +287,7 @@ export function AiProvidersOpenAIEditLayout() {
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [fetchConfig, isCacheValid, showNotification, t]);
|
||||
}, [fetchConfig, isCacheValid, showNotification, t, updateConfigValue]);
|
||||
|
||||
useEffect(() => {
|
||||
if (loading) return;
|
||||
@@ -481,15 +492,13 @@ export function AiProvidersOpenAIEditLayout() {
|
||||
|
||||
let syncedProviders = nextList;
|
||||
try {
|
||||
const latest = await fetchConfig('openai-compatibility', true);
|
||||
if (Array.isArray(latest)) {
|
||||
syncedProviders = latest as OpenAIProviderConfig[];
|
||||
}
|
||||
syncedProviders = await providersApi.getOpenAIProviders();
|
||||
} catch {
|
||||
// 保存成功后刷新失败时,回退到本地计算结果,避免页面数据为空或回退
|
||||
}
|
||||
|
||||
setProviders(syncedProviders);
|
||||
updateConfigValue('openai-compatibility', syncedProviders);
|
||||
showNotification(
|
||||
editIndex !== null
|
||||
? t('notification.openai_provider_updated')
|
||||
@@ -508,7 +517,6 @@ export function AiProvidersOpenAIEditLayout() {
|
||||
allowNextNavigation,
|
||||
draftKey,
|
||||
editIndex,
|
||||
fetchConfig,
|
||||
form,
|
||||
handleBack,
|
||||
providers,
|
||||
@@ -516,6 +524,7 @@ export function AiProvidersOpenAIEditLayout() {
|
||||
showNotification,
|
||||
t,
|
||||
testModel,
|
||||
updateConfigValue,
|
||||
]);
|
||||
|
||||
return (
|
||||
|
||||
@@ -89,10 +89,11 @@ export function AiProvidersPage() {
|
||||
}
|
||||
setError('');
|
||||
try {
|
||||
const [configResult, vertexResult, ampcodeResult] = await Promise.allSettled([
|
||||
const [configResult, vertexResult, ampcodeResult, openaiResult] = await Promise.allSettled([
|
||||
fetchConfig(),
|
||||
providersApi.getVertexConfigs(),
|
||||
ampcodeApi.getAmpcode(),
|
||||
providersApi.getOpenAIProviders(),
|
||||
]);
|
||||
|
||||
if (configResult.status !== 'fulfilled') {
|
||||
@@ -116,6 +117,12 @@ export function AiProvidersPage() {
|
||||
updateConfigValue('ampcode', ampcodeResult.value);
|
||||
clearCache('ampcode');
|
||||
}
|
||||
|
||||
if (openaiResult.status === 'fulfilled') {
|
||||
setOpenaiProviders(openaiResult.value || []);
|
||||
updateConfigValue('openai-compatibility', openaiResult.value || []);
|
||||
clearCache('openai-compatibility');
|
||||
}
|
||||
} catch (err: unknown) {
|
||||
const message = getErrorMessage(err) || t('notification.refresh_failed');
|
||||
setError(message);
|
||||
|
||||
+35
-2
@@ -16,7 +16,9 @@ import { LoadingSpinner } from '@/components/ui/LoadingSpinner';
|
||||
import { Select } from '@/components/ui/Select';
|
||||
import { useMediaQuery } from '@/hooks/useMediaQuery';
|
||||
import { useHeaderRefresh } from '@/hooks/useHeaderRefresh';
|
||||
import { providersApi } from '@/services/api';
|
||||
import { useThemeStore, useConfigStore } from '@/stores';
|
||||
import type { OpenAIProviderConfig } from '@/types';
|
||||
import {
|
||||
StatCards,
|
||||
UsageChart,
|
||||
@@ -121,6 +123,11 @@ export function UsagePage() {
|
||||
const resolvedTheme = useThemeStore((state) => state.resolvedTheme);
|
||||
const isDark = resolvedTheme === 'dark';
|
||||
const config = useConfigStore((state) => state.config);
|
||||
const openaiCompatibilityConfig = config?.openaiCompatibility;
|
||||
const [openaiProvidersWithAuthIndex, setOpenaiProvidersWithAuthIndex] = useState<{
|
||||
source: OpenAIProviderConfig[] | undefined;
|
||||
providers: OpenAIProviderConfig[];
|
||||
} | null>(null);
|
||||
|
||||
// Data hook
|
||||
const {
|
||||
@@ -145,6 +152,32 @@ export function UsagePage() {
|
||||
const [chartLines, setChartLines] = useState<string[]>(loadChartLines);
|
||||
const [timeRange, setTimeRange] = useState<UsageTimeRange>(loadTimeRange);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
const source = openaiCompatibilityConfig;
|
||||
|
||||
providersApi
|
||||
.getOpenAIProviders()
|
||||
.then((providers) => {
|
||||
if (cancelled) return;
|
||||
setOpenaiProvidersWithAuthIndex({ source, providers: providers || [] });
|
||||
})
|
||||
.catch(() => {
|
||||
if (cancelled) return;
|
||||
setOpenaiProvidersWithAuthIndex(null);
|
||||
});
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [openaiCompatibilityConfig]);
|
||||
|
||||
const openaiProviderState = openaiProvidersWithAuthIndex;
|
||||
const openaiProvidersForUsage =
|
||||
openaiProviderState && openaiProviderState.source === openaiCompatibilityConfig
|
||||
? openaiProviderState.providers
|
||||
: openaiCompatibilityConfig ?? [];
|
||||
|
||||
const timeRangeOptions = useMemo(
|
||||
() =>
|
||||
TIME_RANGE_OPTIONS.map((opt) => ({
|
||||
@@ -372,7 +405,7 @@ export function UsagePage() {
|
||||
claudeConfigs={config?.claudeApiKeys || []}
|
||||
codexConfigs={config?.codexApiKeys || []}
|
||||
vertexConfigs={config?.vertexApiKeys || []}
|
||||
openaiProviders={config?.openaiCompatibility || []}
|
||||
openaiProviders={openaiProvidersForUsage}
|
||||
/>
|
||||
|
||||
{/* Credential Stats */}
|
||||
@@ -383,7 +416,7 @@ export function UsagePage() {
|
||||
claudeConfigs={config?.claudeApiKeys || []}
|
||||
codexConfigs={config?.codexApiKeys || []}
|
||||
vertexConfigs={config?.vertexApiKeys || []}
|
||||
openaiProviders={config?.openaiCompatibility || []}
|
||||
openaiProviders={openaiProvidersForUsage}
|
||||
/>
|
||||
|
||||
{/* Price Settings */}
|
||||
|
||||
Reference in New Issue
Block a user