import { CSS } from "@dnd-kit/utilities"; import { DndContext, closestCenter } from "@dnd-kit/core"; import { SortableContext, useSortable, verticalListSortingStrategy, } from "@dnd-kit/sortable"; import { useMemo } from "react"; import type { CSSProperties } from "react"; import type { Provider } from "@/types"; import type { AppId } from "@/lib/api"; import { useDragSort } from "@/hooks/useDragSort"; import { useModelTest } from "@/hooks/useModelTest"; import { ProviderCard } from "@/components/providers/ProviderCard"; import { ProviderEmptyState } from "@/components/providers/ProviderEmptyState"; interface ProviderListProps { providers: Record; currentProviderId: string; appId: AppId; onSwitch: (provider: Provider) => void; onEdit: (provider: Provider) => void; onDelete: (provider: Provider) => void; onDuplicate: (provider: Provider) => void; onConfigureUsage?: (provider: Provider) => void; onOpenWebsite: (url: string) => void; onCreate?: () => void; isLoading?: boolean; isProxyRunning?: boolean; // 代理服务运行状态 } export function ProviderList({ providers, currentProviderId, appId, onSwitch, onEdit, onDelete, onDuplicate, onConfigureUsage, onOpenWebsite, onCreate, isLoading = false, isProxyRunning = false, // 默认值为 false }: ProviderListProps) { const { sortedProviders, sensors, handleDragEnd } = useDragSort( providers, appId, ); // 模型测试 const { testProvider, isTesting } = useModelTest(appId); // 计算代理目标的实际优先级映射 (P1, P2, P3...) const proxyPriorityMap = useMemo(() => { // 获取所有启用代理目标的供应商 const proxyTargets = sortedProviders.filter((p) => p.isProxyTarget); // 按 sortIndex 排序 const sortedTargets = proxyTargets.sort((a, b) => { const indexA = a.sortIndex ?? Number.MAX_SAFE_INTEGER; const indexB = b.sortIndex ?? Number.MAX_SAFE_INTEGER; return indexA - indexB; }); // 创建优先级映射 const map = new Map(); sortedTargets.forEach((provider, index) => { map.set(provider.id, index + 1); // P1, P2, P3... }); return map; }, [sortedProviders]); const handleTest = (provider: Provider) => { testProvider(provider.id, provider.name); }; if (isLoading) { return (
{[0, 1, 2].map((index) => (
))}
); } if (sortedProviders.length === 0) { return ; } return ( provider.id)} strategy={verticalListSortingStrategy} >
{sortedProviders.map((provider) => ( ))}
); } interface SortableProviderCardProps { provider: Provider; isCurrent: boolean; appId: AppId; onSwitch: (provider: Provider) => void; onEdit: (provider: Provider) => void; onDelete: (provider: Provider) => void; onDuplicate: (provider: Provider) => void; onConfigureUsage?: (provider: Provider) => void; onOpenWebsite: (url: string) => void; onTest: (provider: Provider) => void; isTesting: boolean; isProxyRunning: boolean; proxyPriority?: number; // 代理目标的实际优先级 (1, 2, 3...) allProviders?: Provider[]; // 所有供应商列表 } function SortableProviderCard({ provider, isCurrent, appId, onSwitch, onEdit, onDelete, onDuplicate, onConfigureUsage, onOpenWebsite, onTest, isTesting, isProxyRunning, proxyPriority, allProviders, }: SortableProviderCardProps) { const { setNodeRef, attributes, listeners, transform, transition, isDragging, } = useSortable({ id: provider.id }); const style: CSSProperties = { transform: CSS.Transform.toString(transform), transition, }; return (
onConfigureUsage(item) : () => undefined } onOpenWebsite={onOpenWebsite} onTest={onTest} isTesting={isTesting} isProxyRunning={isProxyRunning} proxyPriority={proxyPriority} allProviders={allProviders} dragHandleProps={{ attributes, listeners, isDragging, }} />
); }