import { useEffect, useMemo, useRef, useState, type ChangeEvent, type KeyboardEvent, } from 'react'; import { Bot, Check, Clock3, Cloud, Download, Film, ImageIcon, Loader2, Maximize2, Plus, RefreshCw, Send, Sparkles, Upload, WandSparkles, X, } from 'lucide-react'; import { toast } from 'sonner'; import { Button } from '@/components/ui/button'; import { Dialog, DialogClose, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { Textarea } from '@/components/ui/textarea'; import { IMAGE_WORKSPACE_CREATE_PROJECT_EVENT, resolveImageWorkspaceAssetUrl, saveImageWorkspaceAsset, uploadImageWorkspaceAsset, } from '@/lib/image-workspace'; import { cn } from '@/lib/utils'; import { useImageWorkspaceStore } from '@/stores/image-workspace'; import { useAuthStore } from '@/stores/auth'; import type { DesignAsset, DesignGenerationQuote, DesignGenerationTask, DesignMessage, DesignTaskStatus, } from '../../../shared/image-workspace'; const ACTIVE_TASK_STATUSES = new Set(['queued', 'running']); const TASK_FAILURE_MESSAGES: Record = { policy_blocked: '内容可能涉及版权或安全风险,请调整设计后重试', budget_denied: '当前设计点不足,无法开始生成', quote_expired: '生成方案已过期,请重新确认', asset_rejected: '生成结果未通过媒体检查,请调整设计后重试', dependency_unavailable: '生成服务暂时不可用,请稍后重试', submission_unknown: '正在确认生成请求状态,请稍后查看', submission_not_accepted: '生成请求未被服务接受,请重新确认后再试', generation_failed: '生成未完成,请调整设计或稍后重试', result_persist_failed: '生成结果保存失败,请稍后重试', cancelled: '生成任务已取消', expired: '生成任务已过期,请重新确认', }; const CONFIRMATION_UNAVAILABLE_MESSAGE = ( '当前没有可确认的生成报价,请先让设计 Agent 完成方案与报价。' ); const GENERATION_CONFIRMATION_INTENTS = new Set([ '确认生成', '确认开始生成', '确认并开始生成', '确认开始制作', '确认并开始制作', ]); const VIDEO_FIRST_FRAME_PICKER_REPLY = '从作品列表选择图片'; function isGenerationConfirmationIntent(message: string): boolean { const normalized = message.trim().replace(/[\s,,。.!!??、]/g, ''); return GENERATION_CONFIRMATION_INTENTS.has(normalized); } function taskStatusLabel(status: DesignTaskStatus): string { if (status === 'queued') return '排队中'; if (status === 'running') return '生成中'; if (status === 'succeeded') return '已完成'; if (status === 'cancelled') return '已取消'; return '失败'; } function taskFailureMessage(code: string): string { return TASK_FAILURE_MESSAGES[code] ?? '生成未完成,请稍后重试'; } function mediumLabel(medium: 'image' | 'video'): string { return medium === 'video' ? '视频' : '图片'; } function activeQuote(messages: DesignMessage[]): DesignGenerationQuote | null { for (let index = messages.length - 1; index >= 0; index -= 1) { const quote = messages[index].generationQuote; if (quote?.status === 'active') return quote; } return null; } type RenderedDesignMessage = DesignMessage & { streaming?: boolean }; function AssetPreview({ asset }: { asset: DesignAsset }) { const [url, setUrl] = useState(null); const [previewOpen, setPreviewOpen] = useState(false); const [downloading, setDownloading] = useState(false); useEffect(() => { let cancelled = false; void resolveImageWorkspaceAssetUrl(asset.contentPath).then((nextUrl) => { if (!cancelled) setUrl(nextUrl); }); return () => { cancelled = true; }; }, [asset.contentPath]); if (!url) { return (
); } if (asset.mimeType.startsWith('video/')) { return (