import { useNavigate } from '@tanstack/react-router' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card' import { Progress } from '@/components/ui/progress' import { AlertCircle, CheckCircle2, Download, Loader2, RefreshCw, Star, Trash2 } from 'lucide-react' import type { GitStatus, MaimaiVersion, PluginInfo, PluginLoadProgress, PluginStatsData } from './types' import { CATEGORY_NAMES } from './types' interface PluginCardProps { plugin: PluginInfo gitStatus: GitStatus | null maimaiVersion: MaimaiVersion | null pluginStats: Record loadProgress: PluginLoadProgress | null onInstall: (plugin: PluginInfo) => void onUpdate: (plugin: PluginInfo) => void onUninstall: (plugin: PluginInfo) => void checkPluginCompatibility: (plugin: PluginInfo) => boolean needsUpdate: (plugin: PluginInfo) => boolean getStatusBadge: (plugin: PluginInfo) => React.JSX.Element | null getIncompatibleReason: (plugin: PluginInfo) => string | null } export function PluginCard({ plugin, gitStatus, maimaiVersion, pluginStats, loadProgress, onInstall, onUpdate, onUninstall, checkPluginCompatibility, needsUpdate, getStatusBadge, getIncompatibleReason, }: PluginCardProps) { const navigate = useNavigate() return (
{plugin.manifest?.name || plugin.id}
{plugin.manifest?.categories && plugin.manifest.categories[0] && ( {CATEGORY_NAMES[plugin.manifest.categories[0]] || plugin.manifest.categories[0]} )} {getStatusBadge(plugin)}
{plugin.manifest?.description || '无描述'}
{/* 统计信息 */}
{(pluginStats[plugin.id]?.downloads ?? plugin.downloads ?? 0).toLocaleString()}
{(pluginStats[plugin.id]?.rating ?? plugin.rating ?? 0).toFixed(1)}
{/* 标签 */}
{plugin.manifest?.keywords && plugin.manifest.keywords.slice(0, 3).map((keyword) => ( {keyword} ))} {plugin.manifest?.keywords && plugin.manifest.keywords.length > 3 && ( +{plugin.manifest.keywords.length - 3} )}
{/* 版本和作者 */}
v{plugin.manifest?.version || 'unknown'} · {plugin.manifest?.author?.name || 'Unknown'}
{/* 支持版本 */} {plugin.manifest?.host_application && (
支持: {plugin.manifest.host_application.min_version} {plugin.manifest.host_application.max_version ? ` - ${plugin.manifest.host_application.max_version}` : ' - 最新版本' }
)}
{plugin.installed ? ( needsUpdate(plugin) ? ( ) : ( ) ) : ( )}
{/* 安装/卸载/更新进度显示 - 在卡片下方 */} {loadProgress && (loadProgress.stage === 'loading' || loadProgress.stage === 'success' || loadProgress.stage === 'error') && loadProgress.operation !== 'fetch' && loadProgress.plugin_id === plugin.id && (
{loadProgress.stage === 'loading' ? ( ) : loadProgress.stage === 'success' ? ( ) : ( )} {loadProgress.stage === 'loading' ? ( <> {loadProgress.operation === 'install' && '正在安装'} {loadProgress.operation === 'uninstall' && '正在卸载'} {loadProgress.operation === 'update' && '正在更新'} ) : loadProgress.stage === 'success' ? ( <> {loadProgress.operation === 'install' && '安装完成'} {loadProgress.operation === 'uninstall' && '卸载完成'} {loadProgress.operation === 'update' && '更新完成'} ) : ( <> {loadProgress.operation === 'install' && '安装失败'} {loadProgress.operation === 'uninstall' && '卸载失败'} {loadProgress.operation === 'update' && '更新失败'} )}
{loadProgress.stage !== 'error' && ( {loadProgress.progress}% )}
{loadProgress.stage !== 'error' && ( div]:bg-green-500' : ''}`} /> )}
{loadProgress.stage === 'error' ? (loadProgress.error || loadProgress.message || '操作失败') : loadProgress.message}
)}
) }