feat: add models cache store and fix search placeholder truncation

- Add useModelsStore with 30s cache for model list to reduce API calls
  - Refactor SystemPage to use cached models from store
  - Shorten ConfigPage search placeholder to prevent text truncation
This commit is contained in:
Supra4E8C
2025-12-13 01:35:08 +08:00
parent a7b77ffa25
commit da9469c5aa
6 changed files with 93 additions and 23 deletions

View File

@@ -7,3 +7,4 @@ export { useThemeStore } from './useThemeStore';
export { useLanguageStore } from './useLanguageStore';
export { useAuthStore } from './useAuthStore';
export { useConfigStore } from './useConfigStore';
export { useModelsStore } from './useModelsStore';

View File

@@ -0,0 +1,76 @@
/**
* 模型列表状态管理(带缓存)
*/
import { create } from 'zustand';
import { modelsApi } from '@/services/api/models';
import { CACHE_EXPIRY_MS } from '@/utils/constants';
import type { ModelInfo } from '@/utils/models';
interface ModelsCache {
data: ModelInfo[];
timestamp: number;
apiBase: string;
}
interface ModelsState {
models: ModelInfo[];
loading: boolean;
error: string | null;
cache: ModelsCache | null;
fetchModels: (apiBase: string, apiKey?: string, forceRefresh?: boolean) => Promise<ModelInfo[]>;
clearCache: () => void;
isCacheValid: (apiBase: string) => boolean;
}
export const useModelsStore = create<ModelsState>((set, get) => ({
models: [],
loading: false,
error: null,
cache: null,
fetchModels: async (apiBase, apiKey, forceRefresh = false) => {
const { cache, isCacheValid } = get();
// 检查缓存
if (!forceRefresh && isCacheValid(apiBase) && cache) {
set({ models: cache.data, error: null });
return cache.data;
}
set({ loading: true, error: null });
try {
const list = await modelsApi.fetchModels(apiBase, apiKey);
const now = Date.now();
set({
models: list,
loading: false,
cache: { data: list, timestamp: now, apiBase }
});
return list;
} catch (error: any) {
const message = error?.message || 'Failed to fetch models';
set({
error: message,
loading: false,
models: []
});
throw error;
}
},
clearCache: () => {
set({ cache: null, models: [] });
},
isCacheValid: (apiBase) => {
const { cache } = get();
if (!cache) return false;
if (cache.apiBase !== apiBase) return false;
return Date.now() - cache.timestamp < CACHE_EXPIRY_MS;
}
}));