'use client'; import React, { useEffect, useState, useCallback } from 'react'; import { Store, RefreshCw, Loader2, AlertCircle, Plus, Trash2, Download, Check, X, Globe, FolderOpen, } from 'lucide-react'; import { listMarketplaces, addMarketplace, removeMarketplace, updateMarketplace, listMarketplacePlugins, installMarketplacePlugin, uninstallPlugin, } from '@/lib/api'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Input } from '@/components/ui/input'; import type { Marketplace, MarketplacePlugin } from '@/types'; export default function MarketplacePage() { const [marketplaces, setMarketplaces] = useState([]); const [selectedMarketplace, setSelectedMarketplace] = useState(null); const [plugins, setPlugins] = useState([]); const [loading, setLoading] = useState(true); const [pluginsLoading, setPluginsLoading] = useState(false); const [error, setError] = useState(null); const [showAddForm, setShowAddForm] = useState(false); const [addSource, setAddSource] = useState(''); const [adding, setAdding] = useState(false); const [actionPlugin, setActionPlugin] = useState(null); const [updatingMarketplace, setUpdatingMarketplace] = useState(null); const loadMarketplaces = useCallback(async () => { setLoading(true); setError(null); try { const data = await listMarketplaces(); const list = Array.isArray(data) ? data : []; setMarketplaces(list); // Auto-select first marketplace if none selected or selected was removed if (list.length > 0) { setSelectedMarketplace((prev) => { if (prev && list.some((m) => m.name === prev)) return prev; return list[0].name; }); } else { setSelectedMarketplace(null); setPlugins([]); } } catch (err: any) { setError(err.message || '加载市场失败'); } finally { setLoading(false); } }, []); const loadPlugins = useCallback(async (marketplaceName: string) => { setPluginsLoading(true); try { const data = await listMarketplacePlugins(marketplaceName); setPlugins(Array.isArray(data) ? data : []); } catch (err: any) { setError(err.message || '加载插件失败'); } finally { setPluginsLoading(false); } }, []); useEffect(() => { loadMarketplaces(); }, [loadMarketplaces]); useEffect(() => { if (selectedMarketplace) { loadPlugins(selectedMarketplace); } }, [selectedMarketplace, loadPlugins]); const handleAdd = async () => { if (!addSource.trim()) return; setAdding(true); setError(null); try { const marketplace = await addMarketplace(addSource.trim()); setAddSource(''); setShowAddForm(false); await loadMarketplaces(); setSelectedMarketplace(marketplace.name); } catch (err: any) { setError(err.message || '添加市场失败'); } finally { setAdding(false); } }; const handleRemove = async (name: string) => { setError(null); try { await removeMarketplace(name); if (selectedMarketplace === name) { setSelectedMarketplace(null); setPlugins([]); } await loadMarketplaces(); } catch (err: any) { setError(err.message || '移除市场失败'); } }; const handleUpdateMarketplace = async (name: string) => { setUpdatingMarketplace(name); setError(null); try { await updateMarketplace(name); await loadPlugins(name); } catch (err: any) { setError(err.message || '更新市场失败'); } finally { setUpdatingMarketplace(null); } }; const handleUpdatePlugin = async (marketplaceName: string, pluginName: string) => { setActionPlugin(pluginName); setError(null); try { await installMarketplacePlugin(marketplaceName, pluginName); await loadPlugins(marketplaceName); } catch (err: any) { setError(err.message || '更新插件失败'); } finally { setActionPlugin(null); } }; const handleInstall = async (marketplaceName: string, pluginName: string) => { setActionPlugin(pluginName); setError(null); try { await installMarketplacePlugin(marketplaceName, pluginName); await loadPlugins(marketplaceName); } catch (err: any) { setError(err.message || '安装插件失败'); } finally { setActionPlugin(null); } }; const handleUninstall = async (pluginName: string) => { setActionPlugin(pluginName); setError(null); try { await uninstallPlugin(pluginName); if (selectedMarketplace) { await loadPlugins(selectedMarketplace); } } catch (err: any) { setError(err.message || '卸载插件失败'); } finally { setActionPlugin(null); } }; const handleRefresh = async () => { await loadMarketplaces(); if (selectedMarketplace) { await loadPlugins(selectedMarketplace); } }; if (loading) { return (
); } return (
{/* Page header */}

插件市场

浏览并安装已注册市场中的插件

{/* Error */} {error && (
{error}
)} {/* Add marketplace form */} {showAddForm && (
setAddSource(e.target.value)} onKeyDown={(e) => { if (e.key === 'Enter') handleAdd(); }} disabled={adding} className="flex-1" />
)} {/* Marketplace tabs */} {marketplaces.length > 0 && (
{marketplaces.map((marketplace) => (
))}
)} {/* Empty state */} {marketplaces.length === 0 && !error && (

还没有注册任何市场

点击上方的添加市场,填入本地路径或 Git 地址即可开始使用。

)} {/* Plugin list */} {selectedMarketplace && ( <> {pluginsLoading ? (
) : plugins.length === 0 ? (

暂无可用插件

这个市场里暂时还没有插件。

) : (
{plugins.map((plugin) => (
{plugin.name} {plugin.installed && ( 已安装 )}
{plugin.description && (

{plugin.description}

)}
{plugin.installed ? ( <> ) : ( )}
))}
)} )}
); }