import { Button, Tooltip } from "antd"; import { Eye, FileText, FolderKanban, Image as ImageIcon, Play, RotateCcw, Video } from "lucide-react"; import { useState } from "react"; import { MediaPreview } from "@/components/media-preview"; import { CONTENT_MODERATION_ERROR_CODE, generationErrorMessage, isContentModerationError } from "@/lib/generation-error"; import { formatTaskKind, statusLabel } from "@/lib/generation-task-display"; import type { GenerationTask } from "@/services/api/task-center"; import type { AiConfig } from "@/stores/use-config-store"; import { formatModelName, getTaskCanvasContext, isTaskFailed, statusDotClassName, taskAttentionReason, TaskBilling, TaskDate } from "./task-shared"; export function TaskListRow({ task, canvasById, projectNameById, effectiveConfig, creditsEnabled, actingId, onOpen, onRetry, onPreview, }: { task: GenerationTask; canvasById: Map; projectNameById: Map; effectiveConfig: AiConfig; creditsEnabled: boolean; actingId: string; onOpen: () => void; onRetry: () => void; onPreview: () => void; }) { const context = getTaskCanvasContext(task, canvasById, projectNameById); const isActive = task.status === "queued" || task.status === "running"; const isFailed = isTaskFailed(task); return (
{statusLabel[task.status]}
{formatTaskKind(task)} {formatModelName(effectiveConfig, task)} {context.canvasName} {context.projectName ? ` · ${context.projectName}` : ""}
{isActive ? (
{task.stage || "正在生成"} {task.progress || 0}%
) : null} {isFailed ? (

{taskAttentionReason(task)}

) : null}
{creditsEnabled ? :
); } function TaskPreviewThumbnail({ task, onOpen }: { task: GenerationTask; onOpen: () => void }) { const isVideo = task.previewKind === "video"; const fallbackVideo = task.type.includes("video"); const [unavailableUrl, setUnavailableUrl] = useState(""); const previewUnavailable = Boolean(task.previewUrl && unavailableUrl === task.previewUrl); if (!task.previewUrl) { const Icon = fallbackVideo ? Video : task.type.includes("image") ? ImageIcon : FileText; return ( ); } return ( ); }