From 13d4027559d3bacce06cfc7c4dcbda2d04a15309 Mon Sep 17 00:00:00 2001 From: songtianlun Date: Sun, 10 Aug 2025 23:34:15 +0800 Subject: [PATCH] fix image simulator --- src/app/simulator/[id]/page.tsx | 197 +++++++++++++++++++++++++++++--- 1 file changed, 182 insertions(+), 15 deletions(-) diff --git a/src/app/simulator/[id]/page.tsx b/src/app/simulator/[id]/page.tsx index 3927d20..e319ed6 100644 --- a/src/app/simulator/[id]/page.tsx +++ b/src/app/simulator/[id]/page.tsx @@ -45,6 +45,8 @@ interface SimulatorRun { promptContent?: string | null output?: string error?: string + outputType?: string + generatedFilePath?: string createdAt: string completedAt?: string temperature?: number @@ -97,6 +99,9 @@ export default function SimulatorRunPage({ params }: { params: Promise<{ id: str const [isEditing, setIsEditing] = useState(false) const [isSaving, setIsSaving] = useState(false) const [models, setModels] = useState([]) + const [generatedImageUrl, setGeneratedImageUrl] = useState(null) + const [isLoadingImage, setIsLoadingImage] = useState(false) + const [imageLoadError, setImageLoadError] = useState(false) const [editForm, setEditForm] = useState({ name: '', userInput: '', @@ -118,6 +123,32 @@ export default function SimulatorRunPage({ params }: { params: Promise<{ id: str getParams() }, [params]) + const fetchImageUrl = useCallback(async (runId: string) => { + try { + setIsLoadingImage(true) + const response = await fetch(`/api/simulator/${runId}/image`) + + if (response.ok) { + const data = await response.json() + if (data.fileUrl) { + setGeneratedImageUrl(data.fileUrl) + } + } + } catch (error) { + console.error('Error fetching image URL:', error) + } finally { + setIsLoadingImage(false) + } + }, []) + + const copyToClipboard = useCallback(async (text: string) => { + try { + await navigator.clipboard.writeText(text) + } catch (error) { + console.error('Failed to copy to clipboard:', error) + } + }, []) + const fetchRunCallback = useCallback(async () => { if (!runId) return try { @@ -126,7 +157,14 @@ export default function SimulatorRunPage({ params }: { params: Promise<{ id: str if (response.ok) { const data = await response.json() setRun(data) - setStreamOutput(data.output || '') + + // 如果是图片类型且有生成的文件路径,获取临时 URL + if (data.outputType === 'image' && data.generatedFilePath) { + fetchImageUrl(runId) + } else { + // 只有非图片类型才设置文本输出 + setStreamOutput(data.output || '') + } } else if (response.status === 404) { router.push('/simulator') } @@ -135,7 +173,7 @@ export default function SimulatorRunPage({ params }: { params: Promise<{ id: str } finally { setIsLoading(false) } - }, [runId, router]) + }, [runId, router, fetchImageUrl]) const fetchModels = useCallback(async () => { try { @@ -297,14 +335,6 @@ export default function SimulatorRunPage({ params }: { params: Promise<{ id: str } } - const copyToClipboard = async (text: string) => { - try { - await navigator.clipboard.writeText(text) - // You could add a toast notification here - } catch (error) { - console.error('Error copying to clipboard:', error) - } - } const handleDuplicateRun = async () => { if (!run || !confirm(t('duplicateRunConfirm'))) { @@ -847,17 +877,154 @@ export default function SimulatorRunPage({ params }: { params: Promise<{ id: str - ) : currentOutput ? ( + ) : (run.outputType === 'image' && generatedImageUrl) || (run.outputType !== 'image' && currentOutput) ? (
{t('completed')}
-
-
- {currentOutput} + + {/* 图片输出 */} + {run.outputType === 'image' && generatedImageUrl && ( +
+
+
+ + + + + + 生成的图片 +
+
+ +
+
+
+ Generated image { + console.error('Failed to load image') + setImageLoadError(true) + }} + onLoad={() => { + setImageLoadError(false) + }} + onClick={() => window.open(generatedImageUrl, '_blank')} + /> +
+
+ +
+ + + +
-
+ )} + + {/* 文本输出 - 只在非图片类型时显示 */} + {run.outputType !== 'image' && currentOutput && ( +
+
+ {currentOutput} +
+
+ )} + + {/* 图片错误状态 */} + {run.outputType === 'image' && generatedImageUrl && imageLoadError && ( +
+
+
+ + + +
+
+

图片加载失败

+

图片可能已过期或无法访问

+
+ +
+
+ )} + + {/* 图片加载中状态 */} + {run.outputType === 'image' && !generatedImageUrl && isLoadingImage && ( +
+
+
+
+
+ +
+
+
+

正在获取图片

+

正在从云端加载您生成的图片...

+
+
+
+
+
+
+ )} +
+ ) : run.outputType === 'image' && !generatedImageUrl && !isLoadingImage ? ( +
+ +

+ 等待图片生成完成... +

) : (