Co-authored-by: sikongyue <3155157671@qq.com> Original-PR: https://github.com/ddcat-ai/open-ai-canvas/pull/217
68 lines
3.6 KiB
TypeScript
68 lines
3.6 KiB
TypeScript
import { Button, Tooltip } from "antd";
|
|
import { Eye, FileText, Image as ImageIcon, RotateCcw, Video, X } from "lucide-react";
|
|
|
|
import { CONTENT_MODERATION_ERROR_CODE, isContentModerationError } from "@/lib/generation-error";
|
|
import { statusLabel } from "@/lib/generation-task-display";
|
|
import type { GenerationTask } from "@/services/api/task-center";
|
|
import { isTaskFailed, statusDotClassName, TaskDate } from "./task-shared";
|
|
|
|
export function TaskGridCard({ task, actingId, onOpen, onRetry, onCancel }: { task: GenerationTask; actingId: string; onOpen: () => void; onRetry: () => void; onCancel: () => void }) {
|
|
const isActive = task.status === "queued" || task.status === "running";
|
|
const isFailed = isTaskFailed(task);
|
|
const isVideo = task.previewKind === "video";
|
|
const fallbackVideo = task.type.includes("video");
|
|
const Icon = fallbackVideo ? Video : task.type.includes("image") ? ImageIcon : FileText;
|
|
return (
|
|
<article className={`task-grid-card${isFailed ? " is-attention" : ""}`}>
|
|
<div className="task-grid-thumb">
|
|
{task.previewUrl ? (
|
|
isVideo ? (
|
|
<video src={task.previewUrl} muted playsInline preload="metadata" className="h-full w-full object-cover" />
|
|
) : (
|
|
<img src={task.previewUrl} alt="" loading="lazy" className="h-full w-full object-cover" />
|
|
)
|
|
) : (
|
|
<Icon />
|
|
)}
|
|
<div className="task-grid-overlay">
|
|
<Tooltip title="查看详情">
|
|
<Button type="text" size="small" icon={<Eye className="size-3.5" />} aria-label="查看详情" onClick={onOpen} />
|
|
</Tooltip>
|
|
{isFailed ? (
|
|
<Tooltip title="重试任务">
|
|
<Button
|
|
type="text"
|
|
size="small"
|
|
icon={<RotateCcw className="size-3.5" />}
|
|
aria-label="重试任务"
|
|
loading={actingId === task.id}
|
|
disabled={task.errorCode === CONTENT_MODERATION_ERROR_CODE || isContentModerationError(task.error)}
|
|
onClick={onRetry}
|
|
/>
|
|
</Tooltip>
|
|
) : null}
|
|
{isActive ? (
|
|
<Tooltip title="取消任务">
|
|
<Button type="text" size="small" danger icon={<X className="size-3.5" />} aria-label="取消任务" loading={actingId === task.id} onClick={onCancel} />
|
|
</Tooltip>
|
|
) : null}
|
|
</div>
|
|
</div>
|
|
<div className="task-grid-body">
|
|
<button type="button" className="task-grid-title" title={task.prompt} onClick={onOpen}>
|
|
{task.prompt || "未命名任务"}
|
|
</button>
|
|
<div className="task-grid-meta">
|
|
<span className={`task-grid-status ${isFailed ? "is-failed" : isActive ? "is-active" : task.status === "succeeded" ? "is-success" : ""}`}>
|
|
<i className={statusDotClassName(task.status)} />
|
|
{statusLabel[task.status]}
|
|
</span>
|
|
<span className="task-grid-date">
|
|
<TaskDate value={task.createdAt} />
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</article>
|
|
);
|
|
}
|