// ============================================================ // OutputPreview — 任务输出预览(图片 / 视频) // 使用 useTaskDetail() Hook 获取任务详情,组件仅负责渲染 // ============================================================ import { useMemo } from 'react'; import { Image, Empty, Spin, Typography, Button, Tag, theme as antTheme } from 'antd'; import { EyeOutlined, DownloadOutlined, CloseCircleOutlined, } from '@ant-design/icons'; import { useHomeContext } from '@/contexts/home-context'; import { useTaskDetail } from '@/hooks/use-api'; import type { TaskStatusString } from '@/services/modules'; const { Text } = Typography; // ---------- 状态标签配置 ---------- const STATUS_CONFIG: Record = { pending: { color: 'blue', label: '排队中' }, submitted: { color: 'cyan', label: '已提交' }, processing: { color: 'orange', label: '处理中' }, success: { color: 'green', label: '已完成' }, failed: { color: 'red', label: '失败' }, }; // ---------- 工具函数 ---------- function isVideoUrl(url: string): boolean { return /\.(mp4|webm|mov|avi|mkv)(\?|$)/i.test(url); } function splitAssets(assets: Array<{ url: string }>): { images: string[]; videos: string[] } { const images: string[] = []; const videos: string[] = []; assets.forEach(({ url }) => { if (isVideoUrl(url)) videos.push(url); else images.push(url); }); return { images, videos }; } // ---------- 组件 ---------- export function OutputPreview() { const { token } = antTheme.useToken(); const { selectedTask } = useHomeContext(); // 数据获取(Hook 自动处理:taskId 为 null 时不请求、竞态、loading/error) const { data: detail, loading } = useTaskDetail(selectedTask?.id); // 从 output_assets 提取图片/视频 const { images, videos } = useMemo(() => { if (!detail?.output_assets || detail.output_assets.length === 0) { return { images: [], videos: [] }; } return splitAssets(detail.output_assets); }, [detail]); const status = selectedTask?.status as TaskStatusString | undefined; const statusCfg = status ? (STATUS_CONFIG[status] || { color: 'default', label: status }) : { color: 'default', label: '未知' }; // ---- 无选中任务 ---- if (!selectedTask) { return (
); } // ---- 处理中 ---- if (status === 'pending' || status === 'submitted' || status === 'processing') { return (
{statusCfg.label} 任务正在处理中,请稍候...
); } // ---- 失败 ---- if (status === 'failed') { return (
任务执行失败 {detail?.error_message && ( {detail.error_message} )}
); } // ---- 加载中 ---- if (loading) { return (
); } // ---- 无结果 ---- if (!detail || images.length + videos.length === 0) { return (
); } // ---- 展示 ---- return (
输出预览 {statusCfg.label}
{videos.length > 0 && ( )}
{videos.map((url, i) => (
))} {images.length === 1 ? ( 输出结果 ) : ( {images.map((url, i) => ( {`输出结果 ))} )}
); }