feat(AiProviders): integrate OpenAI providers fetching and update config handling

This commit is contained in:
Supra4E8C
2026-04-25 01:34:12 +08:00
Unverified
parent 60790b946c
commit 03186e447d
3 changed files with 63 additions and 14 deletions
+20 -11
View File
@@ -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 (
+8 -1
View File
@@ -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
View File
@@ -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 */}