refactor: update artifact list style

This commit is contained in:
tao.chen
2026-08-24 17:28:55 +08:00
parent b87f58be60
commit b8246b1e9b
4 changed files with 473 additions and 89 deletions
+109 -34
View File
@@ -1,4 +1,4 @@
import { memo } from "react";
import { memo, useMemo, useState } from "react";
import { type ScheduleArtifact } from "../../services/api";
import Icon from "../../components/common/Icon";
@@ -29,10 +29,41 @@ function ArtifactListImpl({
))
: artifacts;
const [expandedScriptNames, setExpandedScriptNames] = useState<Set<string>>(new Set());
const groups = useMemo(() => {
const map = new Map<string, ScheduleArtifact[]>();
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 (
<section className="schedule-panel schedule-artifacts-panel">
<div className="schedule-panel__title">
<div><strong></strong><span>{artifacts.length}</span></div>
<div>
<strong></strong>
<span className="schedule-panel__count">{artifacts.length}</span>
</div>
</div>
<label className="schedule-search">
<Icon name="search" size={15} />
@@ -42,45 +73,89 @@ function ArtifactListImpl({
onChange={(event) => onKeywordChange(event.target.value)}
/>
</label>
<p className="artifact-tip"> versions_id</p>
<div className="artifact-list">
{filtered.length ? filtered.map((artifact) => (
<div
className="artifact-card"
draggable
key={artifact.versions_id}
onDragStart={(event) => {
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)}
>
<span className={`artifact-card__icon artifact-card__icon--${artifact.script_type}`}>
<Icon
name={artifact.script_type === "notebook" ? "notebook" : "python"}
size={17}
/>
</span>
<span>
<strong>{artifact.script_name}</strong>
<small>
{artifact.version_label} · {shortHash(artifact.content_hash)}
</small>
</span>
</div>
)) : (
{groups.length === 0 ? (
<p className="schedule-empty">
"构建脚本"
</p>
) : (
groups.map(([scriptName, items]) => {
const isExpanded = expandedScriptNames.has(scriptName);
const scriptType = items[0].script_type;
const iconName = scriptType === "notebook" ? "notebook" : "python";
return (
<div key={scriptName} className="artifact-group">
<button
type="button"
className="artifact-group__header"
aria-expanded={isExpanded}
onClick={() => toggle(scriptName)}
>
<span className="artifact-group__main">
<span className={`artifact-group__chevron${isExpanded ? " is-open" : ""}`}>
<Icon name="chevron" size={14} />
</span>
<span className={`artifact-group__icon artifact-group__icon--${scriptType}`}>
<Icon name={iconName} size={14} />
</span>
<span className="artifact-group__name" title={scriptName}>
{scriptName}
</span>
</span>
{items.length > 1 && (
<span className="artifact-group__count">{items.length}</span>
)}
</button>
{isExpanded && (
<div className="artifact-versions">
{items.map((artifact) => (
<div
className="artifact-version"
draggable
key={artifact.versions_id}
onDragStart={(event) => {
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)}
>
<span className="artifact-version__main">
<span className="artifact-version__handle">
<Icon name="grip-vertical" size={13} />
</span>
<span className="artifact-version__name">
{artifact.version_label}
</span>
<span className="artifact-version__commit">
{shortHash(artifact.content_hash)}
</span>
</span>
<span className="artifact-version__action">
<Icon name="external" size={12} />
</span>
</div>
))}
</div>
)}
</div>
);
})
)}
</div>
<p className="artifact-tip artifact-tip--footer">
<span></span>
<span className="artifact-tip__grip">
<Icon name="grip-vertical" size={12} />
</span>
<span></span>
</p>
</section>
);
}
export const ArtifactList = memo(ArtifactListImpl);
export const ArtifactList = memo(ArtifactListImpl);