diff --git a/src/App.tsx b/src/App.tsx index c0614b73a..2f22385c1 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,6 +2,7 @@ import { useEffect, useMemo, useState, useRef } from "react"; import { useTranslation } from "react-i18next"; import { toast } from "sonner"; import { invoke } from "@tauri-apps/api/core"; +import { useQueryClient } from "@tanstack/react-query"; import { Plus, Settings, @@ -45,6 +46,7 @@ type View = "providers" | "settings" | "prompts" | "skills" | "mcp" | "agents"; function App() { const { t } = useTranslation(); + const queryClient = useQueryClient(); const [activeApp, setActiveApp] = useState("claude"); const [currentView, setCurrentView] = useState("providers"); @@ -258,7 +260,20 @@ function App() { // 导入配置成功后刷新 const handleImportSuccess = async () => { - await refetch(); + try { + // 导入会影响所有应用的供应商数据:刷新所有 providers 缓存 + await queryClient.invalidateQueries({ + queryKey: ["providers"], + refetchType: "all", + }); + await queryClient.refetchQueries({ + queryKey: ["providers"], + type: "all", + }); + } catch (error) { + console.error("[App] Failed to refresh providers after import", error); + await refetch(); + } try { await providersApi.updateTrayMenu(); } catch (error) { diff --git a/src/hooks/useImportExport.ts b/src/hooks/useImportExport.ts index be9cb267a..9e4b57f39 100644 --- a/src/hooks/useImportExport.ts +++ b/src/hooks/useImportExport.ts @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useRef, useState } from "react"; +import { useCallback, useState } from "react"; import { useTranslation } from "react-i18next"; import { toast } from "sonner"; import { settingsApi } from "@/lib/api"; @@ -39,15 +39,6 @@ export function useImportExport( const [errorMessage, setErrorMessage] = useState(null); const [backupId, setBackupId] = useState(null); const [isImporting, setIsImporting] = useState(false); - const successTimerRef = useRef(null); - - useEffect(() => { - return () => { - if (successTimerRef.current) { - window.clearTimeout(successTimerRef.current); - } - }; - }, []); const clearSelection = useCallback(() => { setSelectedFile(""); @@ -105,6 +96,10 @@ export function useImportExport( } setBackupId(result.backupId ?? null); + // 导入成功后立即触发外部刷新(与 live 同步结果解耦) + // - 避免 sync 失败时 UI 不刷新 + // - 避免依赖 setTimeout(组件卸载会取消) + void onImportSuccess?.(); const syncResult = await syncCurrentProvidersLiveSafe(); if (syncResult.ok) { @@ -114,10 +109,6 @@ export function useImportExport( defaultValue: "配置导入成功", }), ); - - successTimerRef.current = window.setTimeout(() => { - void onImportSuccess?.(); - }, 1500); } else { console.error( "[useImportExport] Failed to sync live config", diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index 3f08519b0..98f849c63 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -162,7 +162,7 @@ "selectFileFailed": "Please choose a valid SQL backup file", "configCorrupted": "SQL file may be corrupted or invalid", "backupId": "Backup ID", - "autoReload": "Data will refresh automatically in 2 seconds...", + "autoReload": "Data refreshed", "languageOptionChinese": "中文", "languageOptionEnglish": "English", "languageOptionJapanese": "日本語", diff --git a/src/i18n/locales/ja.json b/src/i18n/locales/ja.json index c4b25c649..ec79a4e08 100644 --- a/src/i18n/locales/ja.json +++ b/src/i18n/locales/ja.json @@ -162,7 +162,7 @@ "selectFileFailed": "有効な SQL バックアップファイルを選択してください", "configCorrupted": "SQL ファイルが壊れているか形式が無効な可能性があります", "backupId": "バックアップ ID", - "autoReload": "2 秒後に自動で再読み込みします...", + "autoReload": "データを更新しました", "languageOptionChinese": "中文", "languageOptionEnglish": "English", "languageOptionJapanese": "日本語", diff --git a/src/i18n/locales/zh.json b/src/i18n/locales/zh.json index d0955b5a6..14dd6278c 100644 --- a/src/i18n/locales/zh.json +++ b/src/i18n/locales/zh.json @@ -162,7 +162,7 @@ "selectFileFailed": "请选择有效的 SQL 备份文件", "configCorrupted": "SQL 文件可能已损坏或格式不正确", "backupId": "备份ID", - "autoReload": "数据将在2秒后自动刷新...", + "autoReload": "数据已刷新", "languageOptionChinese": "中文", "languageOptionEnglish": "English", "languageOptionJapanese": "日本語", diff --git a/tests/hooks/useImportExport.test.tsx b/tests/hooks/useImportExport.test.tsx index 4b2cfa0aa..7f9b3a416 100644 --- a/tests/hooks/useImportExport.test.tsx +++ b/tests/hooks/useImportExport.test.tsx @@ -110,12 +110,6 @@ describe("useImportExport Hook", () => { expect(result.current.status).toBe("success"); expect(result.current.backupId).toBe("backup-123"); expect(toastSuccessMock).toHaveBeenCalledTimes(1); - - // Skip delay to execute callback - await act(async () => { - vi.runOnlyPendingTimers(); - }); - expect(onImportSuccess).toHaveBeenCalledTimes(1); });