fix: tighten task detail component interactions

This commit is contained in:
2026-05-26 12:48:27 +08:00
parent 9002d1206f
commit 542b23ef6e
3 changed files with 90 additions and 9 deletions

View File

@ -55,6 +55,40 @@ function artifactHref(artifact: ProcessArtifact): string | null {
return null;
}
function inlineArtifactPayload(artifact: ProcessArtifact): { content: string; filename: string; mimeType: string } | null {
const baseName = (artifact.title || artifact.artifact_id || 'artifact').replace(/[\\/:*?"<>|]+/g, '-');
if (artifact.content !== undefined) {
const isMarkdown = artifact.artifact_type === 'markdown';
return {
content: artifact.content,
filename: `${baseName}.${isMarkdown ? 'md' : 'txt'}`,
mimeType: isMarkdown ? 'text/markdown;charset=utf-8' : 'text/plain;charset=utf-8',
};
}
if (artifact.data !== undefined) {
return {
content: JSON.stringify(artifact.data, null, 2),
filename: `${baseName}.json`,
mimeType: 'application/json;charset=utf-8',
};
}
return null;
}
function downloadInlineArtifact(artifact: ProcessArtifact): void {
const payload = inlineArtifactPayload(artifact);
if (!payload) return;
const url = URL.createObjectURL(new Blob([payload.content], { type: payload.mimeType }));
const anchor = document.createElement('a');
anchor.href = url;
anchor.download = payload.filename;
document.body.appendChild(anchor);
anchor.click();
anchor.remove();
URL.revokeObjectURL(url);
}
function RunRow({ run }: { run: ProcessRun }) {
const { locale } = useAppI18n();
@ -165,6 +199,7 @@ export function TaskSideRail({ task, runs, artifacts, cards }: Props) {
) : (
artifacts.map((artifact) => {
const href = artifactHref(artifact);
const inlinePayload = inlineArtifactPayload(artifact);
return (
<div key={artifact.artifact_id} className="flex items-center justify-between gap-3 rounded-md border border-border bg-muted/20 p-3">
<div className="min-w-0">
@ -181,6 +216,11 @@ export function TaskSideRail({ task, runs, artifacts, cards }: Props) {
{artifact.url ? pickAppText(locale, '打开', 'Open') : pickAppText(locale, '下载', 'Download')}
</a>
</Button>
) : inlinePayload ? (
<Button size="sm" variant="outline" className="shrink-0" onClick={() => downloadInlineArtifact(artifact)}>
<Download className="mr-2 h-3.5 w-3.5" />
{pickAppText(locale, '下载', 'Download')}
</Button>
) : null}
</div>
);