feat(records): 视频卡片/详情弹窗用 thumbnail_url 显示首帧 poster
后端 GenerationRecord.thumbnail_url 字段早就被 tasks.py:_handle_completed (L109-111)
通过 ffmpeg 提取首帧 + 上传 TOS 填充,但只在 _serialize_task (生成页) 返回。
admin_records / team_records / profile_records 三个 view 都没回传,前端无从用。
后端:三个 records view 各加一行 'thumbnail_url': r.thumbnail_url or ''
前端:
- types/index.ts AdminRecord 加 thumbnail_url?: string
- 三处 <video> 加 poster={thumbnailUrl ? rewriteTosUrl(...) : undefined}
- RecordDetailModal.tsx (消费记录详情)
- VideoDetailModal.tsx (资产页/生成页详情)
- GenerationCard.tsx (生成页卡片)
效果:卡片首屏直接显示首帧海报(几十 KB),不再等视频 metadata 加载完
才有视觉;hover 触发 v.play() 时再真正下载视频,UX 不变。
老记录 thumbnail_url='' 时 poster=undefined,行为同改前。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
e86e3d45b1
commit
72f351d54f
@ -1819,6 +1819,7 @@ def admin_records_view(request):
|
||||
'seed': r.seed,
|
||||
'ark_task_id': r.ark_task_id or '',
|
||||
'result_url': r.result_url or '',
|
||||
'thumbnail_url': r.thumbnail_url or '',
|
||||
})
|
||||
|
||||
return Response({
|
||||
@ -1884,6 +1885,7 @@ def team_records_view(request):
|
||||
'seed': r.seed,
|
||||
'ark_task_id': r.ark_task_id or '',
|
||||
'result_url': r.result_url or '',
|
||||
'thumbnail_url': r.thumbnail_url or '',
|
||||
})
|
||||
|
||||
return Response({
|
||||
@ -2770,6 +2772,8 @@ def profile_records_view(request):
|
||||
'resolution': r.resolution,
|
||||
'status': r.status,
|
||||
'error_message': r.error_message or '',
|
||||
'result_url': r.result_url or '',
|
||||
'thumbnail_url': r.thumbnail_url or '',
|
||||
})
|
||||
|
||||
return Response({
|
||||
|
||||
@ -476,6 +476,7 @@ export function GenerationCard({ task, onOpenDetail }: Props) {
|
||||
<video
|
||||
ref={videoRef}
|
||||
src={rewriteTosUrl(task.resultUrl)}
|
||||
poster={task.thumbnailUrl ? rewriteTosUrl(task.thumbnailUrl) : undefined}
|
||||
className={styles.resultMedia}
|
||||
loop
|
||||
preload="metadata"
|
||||
|
||||
@ -121,6 +121,7 @@ function MediaArea({ record: r }: { record: AdminRecord }) {
|
||||
{r.status === 'completed' && r.result_url ? (
|
||||
<video
|
||||
src={rewriteTosUrl(r.result_url)}
|
||||
poster={r.thumbnail_url ? rewriteTosUrl(r.thumbnail_url) : undefined}
|
||||
style={mediaVideo}
|
||||
controls
|
||||
preload="metadata"
|
||||
|
||||
@ -303,6 +303,7 @@ export function VideoDetailModal({ task, onClose, onReEdit, onRegenerate, onDele
|
||||
<video
|
||||
ref={videoRef}
|
||||
src={rewriteTosUrl(task.resultUrl)}
|
||||
poster={task.thumbnailUrl ? rewriteTosUrl(task.thumbnailUrl) : undefined}
|
||||
className={styles.video}
|
||||
onTimeUpdate={handleTimeUpdate}
|
||||
onLoadedMetadata={handleLoadedMetadata}
|
||||
|
||||
@ -218,6 +218,7 @@ export interface AdminRecord {
|
||||
seed?: number;
|
||||
ark_task_id?: string;
|
||||
result_url?: string;
|
||||
thumbnail_url?: string;
|
||||
}
|
||||
|
||||
export interface SystemSettings {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user