import { useState, useCallback, useEffect } from "react"; import { useTranslation } from "react-i18next"; import { Layers } from "lucide-react"; import { toast } from "sonner"; import { ConfirmDialog } from "@/components/ConfirmDialog"; import { UniversalProviderCard } from "./UniversalProviderCard"; import { UniversalProviderFormModal } from "./UniversalProviderFormModal"; import { universalProvidersApi } from "@/lib/api"; import type { UniversalProvider, UniversalProvidersMap } from "@/types"; export function UniversalProviderPanel() { const { t } = useTranslation(); // 状态 const [providers, setProviders] = useState({}); const [loading, setLoading] = useState(true); const [isFormOpen, setIsFormOpen] = useState(false); const [editingProvider, setEditingProvider] = useState(null); const [deleteConfirm, setDeleteConfirm] = useState<{ open: boolean; id: string; name: string; }>({ open: false, id: "", name: "" }); const [syncConfirm, setSyncConfirm] = useState<{ open: boolean; id: string; name: string; }>({ open: false, id: "", name: "" }); // 加载数据 const loadProviders = useCallback(async () => { try { setLoading(true); const data = await universalProvidersApi.getAll(); setProviders(data); } catch (error) { console.error("Failed to load universal providers:", error); toast.error( t("universalProvider.loadError", { defaultValue: "加载统一供应商失败", }), ); } finally { setLoading(false); } }, [t]); useEffect(() => { loadProviders(); }, [loadProviders]); // 添加/编辑供应商 const handleSave = useCallback( async (provider: UniversalProvider) => { try { await universalProvidersApi.upsert(provider); // 新建模式下自动同步到各应用 if (!editingProvider) { await universalProvidersApi.sync(provider.id); } toast.success( editingProvider ? t("universalProvider.updated", { defaultValue: "统一供应商已更新", }) : t("universalProvider.addedAndSynced", { defaultValue: "统一供应商已添加并同步", }), ); loadProviders(); setEditingProvider(null); } catch (error) { console.error("Failed to save universal provider:", error); toast.error( t("universalProvider.saveError", { defaultValue: "保存统一供应商失败", }), ); } }, [editingProvider, loadProviders, t], ); // 保存并同步供应商 const handleSaveAndSync = useCallback( async (provider: UniversalProvider) => { try { await universalProvidersApi.upsert(provider); await universalProvidersApi.sync(provider.id); toast.success( t("universalProvider.savedAndSynced", { defaultValue: "已保存并同步到所有应用", }), ); loadProviders(); setEditingProvider(null); } catch (error) { console.error("Failed to save and sync universal provider:", error); toast.error( t("universalProvider.saveAndSyncError", { defaultValue: "保存并同步失败", }), ); } }, [loadProviders, t], ); // 删除供应商 const handleDelete = useCallback(async () => { if (!deleteConfirm.id) return; try { await universalProvidersApi.delete(deleteConfirm.id); toast.success( t("universalProvider.deleted", { defaultValue: "统一供应商已删除" }), ); loadProviders(); } catch (error) { console.error("Failed to delete universal provider:", error); toast.error( t("universalProvider.deleteError", { defaultValue: "删除统一供应商失败", }), ); } finally { setDeleteConfirm({ open: false, id: "", name: "" }); } }, [deleteConfirm.id, loadProviders, t]); // 同步供应商 const handleSync = useCallback(async () => { if (!syncConfirm.id) return; try { await universalProvidersApi.sync(syncConfirm.id); toast.success( t("universalProvider.synced", { defaultValue: "已同步到所有应用" }), ); } catch (error) { console.error("Failed to sync universal provider:", error); toast.error( t("universalProvider.syncError", { defaultValue: "同步统一供应商失败", }), ); } finally { setSyncConfirm({ open: false, id: "", name: "" }); } }, [syncConfirm.id, t]); // 打开同步确认 const handleSyncClick = useCallback( (id: string) => { const provider = providers[id]; setSyncConfirm({ open: true, id, name: provider?.name || id, }); }, [providers], ); // 复制供应商 const handleDuplicate = useCallback( async (provider: UniversalProvider) => { const duplicated: UniversalProvider = { ...JSON.parse(JSON.stringify(provider)), id: crypto.randomUUID(), name: `${provider.name} copy`, createdAt: Date.now(), }; try { await universalProvidersApi.upsert(duplicated); await universalProvidersApi.sync(duplicated.id); toast.success( t("universalProvider.duplicatedAndSynced", { defaultValue: "统一供应商已复制并同步", }), ); loadProviders(); } catch (error) { console.error("Failed to duplicate universal provider:", error); toast.error( t("universalProvider.duplicateError", { defaultValue: "复制统一供应商失败", }), ); } }, [loadProviders, t], ); // 打开编辑 const handleEdit = useCallback((provider: UniversalProvider) => { setEditingProvider(provider); setIsFormOpen(true); }, []); // 打开删除确认 const handleDeleteClick = useCallback( (id: string) => { const provider = providers[id]; setDeleteConfirm({ open: true, id, name: provider?.name || id, }); }, [providers], ); const providerList = Object.values(providers); return (
{/* 头部 */}

{t("universalProvider.title", { defaultValue: "统一供应商" })}

{providerList.length}
{/* 描述 */}

{t("universalProvider.description", { defaultValue: "统一供应商可以同时管理 Claude、Codex 和 Gemini 的配置。修改后会自动同步到所有启用的应用。", })}

{/* 供应商列表 */} {loading ? (
) : providerList.length === 0 ? (

{t("universalProvider.empty", { defaultValue: "还没有统一供应商", })}

{t("universalProvider.emptyHint", { defaultValue: "点击下方「添加统一供应商」按钮创建一个", })}

) : (
{providerList.map((provider) => ( ))}
)} {/* 表单模态框 */} { setIsFormOpen(false); setEditingProvider(null); }} onSave={handleSave} onSaveAndSync={handleSaveAndSync} editingProvider={editingProvider} /> {/* 删除确认对话框 */} setDeleteConfirm({ open: false, id: "", name: "" })} /> {/* 同步确认对话框 */} setSyncConfirm({ open: false, id: "", name: "" })} />
); }