@@ -40,10 +40,11 @@ export default function DetailModal() {
4040 } , [ detailTaskId ] )
4141
4242 useEffect ( ( ) => {
43- if ( task ?. status !== 'running' ) return
43+ if ( task ?. status !== 'running' && ! ( task ?. status === 'error' && task . falRecoverable ) ) return
4444 const id = window . setInterval ( ( ) => setNow ( Date . now ( ) ) , 1000 )
45+ setNow ( Date . now ( ) )
4546 return ( ) => window . clearInterval ( id )
46- } , [ task ?. status ] )
47+ } , [ task ?. falRecoverable , task ?. status ] )
4748
4849 // 加载所有相关图片
4950 useEffect ( ( ) => {
@@ -164,17 +165,19 @@ export default function DetailModal() {
164165 const showPromptWarning = Boolean ( currentOutputImageId && ( ! currentRevisedPrompt || showRevisedPrompt ) && ! hasHandledPromptWarning )
165166 const aggregateActualParams = outputLen > 0 ? { ...task . actualParams , n : outputLen } : task . actualParams
166167 const taskProvider = task . apiProvider
167- const taskProviderName = taskProvider === 'fal' ? 'fal.ai' : taskProvider === 'oai-like' ? 'OAI-like ' : '未知'
168- const taskProfileName = task . apiProfileName || '旧记录未保存 '
168+ const taskProviderName = taskProvider === 'fal' ? 'fal.ai' : taskProvider ? 'OpenAI ' : '未知'
169+ const taskProfileName = task . apiProfileName || '未知 '
169170 const taskModel = task . apiModel || '未知'
171+ const showSourceInfo = Boolean ( task . apiProvider || task . apiProfileName || task . apiModel )
172+ const isFalReconnecting = task . status === 'error' && task . falRecoverable
170173
171174 const formatTime = ( ts : number | null ) => {
172175 if ( ! ts ) return ''
173176 return new Date ( ts ) . toLocaleString ( 'zh-CN' )
174177 }
175178
176179 const formatDuration = ( ) => {
177- if ( task . status === 'running' ) {
180+ if ( task . status === 'running' || isFalReconnecting ) {
178181 const seconds = Math . max ( 0 , Math . floor ( ( now - task . createdAt ) / 1000 ) )
179182 const mm = String ( Math . floor ( seconds / 60 ) ) . padStart ( 2 , '0' )
180183 const ss = String ( seconds % 60 ) . padStart ( 2 , '0' )
@@ -294,7 +297,7 @@ export default function DetailModal() {
294297 < img
295298 ref = { mainImageRef }
296299 src = { currentOutputImageSrc }
297- className = "max-w-[calc(100%-2rem)] max-h-[calc(100%-2rem)] object-contain cursor-pointer"
300+ className = "saveable-image max-w-[calc(100%-2rem)] max-h-[calc(100%-2rem)] object-contain cursor-pointer"
298301 onLoad = { ( ) => {
299302 const panel = imagePanelRef . current
300303 const image = mainImageRef . current
@@ -361,21 +364,31 @@ export default function DetailModal() {
361364 ) }
362365 </ >
363366 ) }
364- { task . status === 'running' && (
367+ { ( task . status === 'running' || isFalReconnecting ) && (
365368 < >
366369 < div className = "absolute left-4 top-4 flex items-center gap-1 bg-black/50 text-white text-xs px-2 py-0.5 rounded backdrop-blur-sm font-mono" >
367370 < svg className = "w-3 h-3" fill = "none" stroke = "currentColor" viewBox = "0 0 24 24" >
368371 < path strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 2 } d = "M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
369372 </ svg >
370373 { formatDuration ( ) }
371374 </ div >
372- < svg className = "w-10 h-10 text-blue-400 animate-spin" fill = "none" viewBox = "0 0 24 24" >
373- < circle className = "opacity-25" cx = "12" cy = "12" r = "10" stroke = "currentColor" strokeWidth = "4" />
374- < path className = "opacity-75" fill = "currentColor" d = "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" />
375- </ svg >
375+ { task . status === 'running' && (
376+ < svg className = "w-10 h-10 text-blue-400 animate-spin" fill = "none" viewBox = "0 0 24 24" >
377+ < circle className = "opacity-25" cx = "12" cy = "12" r = "10" stroke = "currentColor" strokeWidth = "4" />
378+ < path className = "opacity-75" fill = "currentColor" d = "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" />
379+ </ svg >
380+ ) }
376381 </ >
377382 ) }
378- { task . status === 'error' && (
383+ { task . status === 'error' && isFalReconnecting && (
384+ < div className = "w-full max-w-md px-4 text-center" >
385+ < svg className = "w-10 h-10 text-yellow-400 mx-auto mb-2" fill = "none" stroke = "currentColor" viewBox = "0 0 24 24" >
386+ < path strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 2 } d = "M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
387+ </ svg >
388+ < p className = "text-sm font-medium text-yellow-500" > 重连中</ p >
389+ </ div >
390+ ) }
391+ { task . status === 'error' && ! isFalReconnecting && (
379392 < div className = "w-full max-w-md px-4 text-center" >
380393 < svg className = "w-10 h-10 text-red-400 mx-auto mb-2" fill = "none" stroke = "currentColor" viewBox = "0 0 24 24" >
381394 < path strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 2 } d = "M12 9v2m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
@@ -527,12 +540,14 @@ export default function DetailModal() {
527540 < h3 className = "text-xs font-medium text-gray-400 dark:text-gray-500 uppercase tracking-wider mb-2" >
528541 参数配置
529542 </ h3 >
530- < div className = "mb-2 rounded-lg bg-gray-50 px-3 py-2 text-xs dark:bg-white/[0.03]" >
531- < span className = "text-gray-400 dark:text-gray-500" > Provider</ span >
532- < br />
533- < span className = "font-medium text-gray-700 dark:text-gray-200" > { taskProviderName } </ span >
534- < span className = "text-gray-400 dark:text-gray-500" > · { taskProfileName } · { taskModel } </ span >
535- </ div >
543+ { showSourceInfo && (
544+ < div className = "mb-2 rounded-lg bg-gray-50 px-3 py-2 text-xs dark:bg-white/[0.03]" >
545+ < span className = "text-gray-400 dark:text-gray-500" > 来源</ span >
546+ < br />
547+ < span className = "font-medium text-gray-700 dark:text-gray-200" > { taskProviderName } </ span >
548+ < span className = "text-gray-400 dark:text-gray-500" > · { taskProfileName } · { taskModel } </ span >
549+ </ div >
550+ ) }
536551 < div className = "grid grid-cols-2 gap-2 text-xs mb-4" >
537552 < div className = "bg-gray-50 dark:bg-white/[0.03] rounded-lg px-3 py-2" >
538553 < span className = "text-gray-400 dark:text-gray-500" > 尺寸</ span >
0 commit comments