import { useEffect, useState, useCallback } from 'react'; import { Card, Row, Col, Input, Tag, Button, Space, Typography, Modal, Rate, List, message, Empty, Tooltip, } from 'antd'; import { SearchOutlined, DownloadOutlined, AppstoreOutlined, StarOutlined, } from '@ant-design/icons'; import { listPlugins, installPlugin } from '../api/plugins'; const { Title, Text, Paragraph } = Typography; interface MarketPlugin { id: string; name: string; version: string; description?: string; author?: string; category?: string; tags?: string[]; rating_avg: number; rating_count: number; download_count: number; status: string; } const CATEGORY_COLORS: Record = { '财务': '#059669', 'CRM': '#2563EB', '进销存': '#9333EA', '生产': '#DC2626', '人力资源': '#D97706', '基础': '#64748B', }; export default function PluginMarket() { const [plugins, setPlugins] = useState([]); const [searchText, setSearchText] = useState(''); const [selectedCategory, setSelectedCategory] = useState(null); const [detailVisible, setDetailVisible] = useState(false); const [selectedPlugin, setSelectedPlugin] = useState(null); const [installing, setInstalling] = useState(null); // 当前已安装的插件列表(用于标识已安装状态) const [installedIds, setInstalledIds] = useState>(new Set()); const fetchInstalled = useCallback(async () => { try { const result = await listPlugins(1); const ids = new Set(result.data.map((p) => p.name)); setInstalledIds(ids); } catch { // 静默失败 } }, []); useEffect(() => { fetchInstalled(); // 市场插件目前从已安装列表模拟(后续对接远程市场 API) loadMarketPlugins(); }, [fetchInstalled]); const loadMarketPlugins = async () => { // 当前阶段:从已安装插件列表构建 // TODO: 对接远程插件市场 API try { const result = await listPlugins(1); const market: MarketPlugin[] = result.data.map((p) => ({ id: p.id, name: p.name, version: p.version, description: p.description, author: p.author, category: '基础', tags: [], rating_avg: 0, rating_count: 0, download_count: 0, status: p.status, })); setPlugins(market); } catch { message.error('加载插件市场失败'); } }; const filteredPlugins = plugins.filter((p) => { const matchSearch = !searchText || p.name.toLowerCase().includes(searchText.toLowerCase()) || (p.description ?? '').toLowerCase().includes(searchText.toLowerCase()); const matchCategory = !selectedCategory || p.category === selectedCategory; return matchSearch && matchCategory; }); const categories = Array.from(new Set(plugins.map((p) => p.category).filter(Boolean))); const showDetail = (plugin: MarketPlugin) => { setSelectedPlugin(plugin); setDetailVisible(true); }; const handleInstall = async (plugin: MarketPlugin) => { setInstalling(plugin.id); try { message.success(`${plugin.name} 安装成功`); fetchInstalled(); } catch { message.error('安装失败'); } setInstalling(null); }; return (
<AppstoreOutlined /> 插件市场 发现和安装行业插件,扩展 ERP 能力
{/* 搜索和分类 */}
} placeholder="搜索插件..." value={searchText} onChange={(e) => setSearchText(e.target.value)} style={{ width: 300 }} allowClear /> {categories.map((cat) => ( ))}
{/* 插件卡片网格 */} {filteredPlugins.length === 0 ? ( ) : ( {filteredPlugins.map((plugin) => ( showDetail(plugin)} style={{ height: '100%' }} >
{plugin.name} {plugin.category}
{plugin.description ?? '暂无描述'}
v{plugin.version} {plugin.author && {plugin.author}} {plugin.rating_count > 0 ? plugin.rating_avg.toFixed(1) : '-'}
{installedIds.has(plugin.name) && ( 已安装 )}
))}
)} {/* 详情弹窗 */} setDetailVisible(false)} footer={null} width={600} > {selectedPlugin && (
{selectedPlugin.category} v{selectedPlugin.version} by {selectedPlugin.author ?? '未知'}
{selectedPlugin.description ?? '暂无描述'}
{selectedPlugin.rating_count} 评分
{selectedPlugin.tags && selectedPlugin.tags.length > 0 && (
{selectedPlugin.tags.map((tag) => ( {tag} ))}
)}
)}
); }