import { memo, useMemo, useState } from "react"; import { type ScheduleArtifact } from "~/services/api"; import { BookText, ChevronRight, ExternalLink, FileCode2, GripVertical, Search, } from "lucide-react"; import { shortHash } from "./utils"; // 包裹 memo 让父级 SchedulePage 在画布交互(setSelectedNodeId / // setSelectedEdgeId / linkSourceId 等)重渲染时,artifact 卡片不会跟着 // 重建/重绑拖拽事件 —— 减少拖动过程中的事件重绑与列表抖动。 function ArtifactListImpl({ artifacts, keyword, onDrop, onDoubleClick, onContextMenu, onKeywordChange, }: { artifacts: ScheduleArtifact[]; keyword: string; onDrop: (artifact: ScheduleArtifact, x: number, y: number) => void; onDoubleClick: (artifact: ScheduleArtifact) => void; onContextMenu: (event: React.MouseEvent, artifact: ScheduleArtifact) => void; onKeywordChange: (keyword: string) => void; }) { const filtered = keyword.trim() ? artifacts.filter((item) => ( item.script_name.toLowerCase().includes(keyword.trim().toLowerCase()) || item.version_label.toLowerCase().includes(keyword.trim().toLowerCase()) )) : artifacts; const [expandedScriptNames, setExpandedScriptNames] = useState>(new Set()); const groups = useMemo(() => { const map = new Map(); for (const item of filtered) { const list = map.get(item.script_name); if (list) list.push(item); else map.set(item.script_name, [item]); } // 组内按 created_at desc,version_label desc 兜底 for (const list of map.values()) { list.sort((a, b) => { if (a.created_at !== b.created_at) return a.created_at < b.created_at ? 1 : -1; return a.version_label < b.version_label ? 1 : -1; }); } return Array.from(map.entries()).sort(([a], [b]) => a.localeCompare(b)); }, [filtered]); function toggle(scriptName: string) { setExpandedScriptNames((prev) => { const next = new Set(prev); if (next.has(scriptName)) next.delete(scriptName); else next.add(scriptName); return next; }); } return (
稳定版本脚本 {artifacts.length}
{groups.length === 0 ? (

暂无稳定版本,请先在"构建脚本"中发布

) : ( groups.map(([scriptName, items]) => { const isExpanded = expandedScriptNames.has(scriptName); const scriptType = items[0].script_type; return (
{isExpanded && (
{items.map((artifact) => (
{ event.dataTransfer.effectAllowed = "copy"; event.dataTransfer.setData( "application/x-model-platform-version", artifact.versions_id, ); event.dataTransfer.setData("text/plain", artifact.versions_id); }} onContextMenu={(event) => onContextMenu(event, artifact)} onDoubleClick={() => onDoubleClick(artifact)} > {artifact.version_label} {shortHash(artifact.content_hash)}
))}
)}
); }) )}

按住 拖拽卡片到画布即可绑定节点

); } export const ArtifactList = memo(ArtifactListImpl);