Compare commits

...

2 Commits

Author SHA1 Message Date
seaislee1209
e500c2d6a0 feat(assets): 3 个资产页视频也加 poster 首帧 — batch B 漏的补全
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 6m40s
v0.20.1 batch B 只给生成页 GenerationCard + 消费记录 RecordDetailModal +
视频详情 VideoDetailModal 加了 poster,3 个资产页漏了:
- 用户资产页 (AssetsPage.tsx)
- 超管内容资产 (AdminAssetsPage.tsx)
- 团管内容资产 (TeamAssetsPage.tsx)

用户实测:消费记录详情能看到首帧海报 + 加载圈;打开内容资产页 / 生成页面
其他位置的视频卡片黑底硬等加载,没首帧 — 体验不一致。

修法:
- 后端 admin_assets_user_videos / team_assets_member_videos view 各加一行
  'thumbnail_url': r.thumbnail_url or '' (batch B 的 3 个 records view 已有)
- AssetVideo 类型加 thumbnail_url?: string
- 3 个资产页 <video> 加 poster={... ? rewriteTosUrl(...) : undefined}
  (跟 GenerationCard/RecordDetailModal/VideoDetailModal 写法一致)

GenerationCard.tsx 已在 batch B 加过 poster — 用户感觉"生成页面也没"是因为本地
ARK_API_KEY 未配生不了新视频,老 record thumbnail_url 字段是空。新生成的视频
会有(后端 tasks.py:_handle_completed ffmpeg 已经写入)。

测试:tsc 0 error, v0.20.1-smoke 11/11 + modal-interaction 8/8 + announcement 17/17

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 17:23:56 +08:00
seaislee1209
08b5e66fbc fix(theme): 浅色下视频上的下载/收藏按钮看不见 — 改回深半透底+白图标
v0.20.0 浅色主题切换时把 --color-bg-on-media 改成 rgba(255,255,255,0.90),
但 --color-on-overlay 没动还是白色 ⇒ 白底白图标完全看不见。

用户实测:生成页面视频卡片 hover 时下载+收藏按钮浅色下都消失。

根因:这俩 var 是给 "video 上的悬浮控件" 设计的,视频帧本身可能任何颜色
(用户上传白雪景 / 深夜景都有),控件必须用 深底+白字 才能在任意视频背景上可读。
这是行业惯例(YouTube/抖音/Bilibili 浅色主题下视频控件也是黑底白字)。

修法:浅色下也用 rgba(0,0,0,0.55) 深半透底,保持 --color-on-overlay 白色不变。
跟 dark 主题语义对称(都是深底白字,只是 alpha 不同)。

涉及:
- GenerationCard.module.css .downloadBtn (生成页卡片下载+收藏)
- VideoDetailModal.module.css 其他 video overlay 用 var 的元素也受益

未改:VideoDetailModal 内部 .floatingBtn / .timeDisplay / .controls 等
硬编码 rgba(255,...) — 那些也是视频 overlay 控件,黑底白字是对的,不动。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 17:15:42 +08:00
6 changed files with 11 additions and 5 deletions

View File

@ -3022,6 +3022,7 @@ def admin_assets_user_videos(request, user_id):
'task_id': str(r.task_id),
'prompt': r.prompt,
'result_url': r.result_url or '',
'thumbnail_url': r.thumbnail_url or '',
'duration': r.duration,
'seconds_consumed': r.seconds_consumed,
'aspect_ratio': r.aspect_ratio,
@ -3104,6 +3105,7 @@ def team_assets_member_videos(request, member_id):
'task_id': str(r.task_id),
'prompt': r.prompt,
'result_url': r.result_url or '',
'thumbnail_url': r.thumbnail_url or '',
'duration': r.duration,
'seconds_consumed': r.seconds_consumed,
'aspect_ratio': r.aspect_ratio,

View File

@ -391,9 +391,11 @@
--color-info-shadow-soft: rgba(0, 153, 204, 0.20);
--color-info-shadow-strong: rgba(0, 153, 204, 0.35);
/* White alpha on dark media — 保留白色徽章语义 */
--color-bg-on-media: rgba(255, 255, 255, 0.90);
--color-bg-on-media-hover: rgba(255, 255, 255, 1.0);
/* Video 上的悬浮按钮(下载/收藏) 必须任意视频帧背景下都可读
沿用行业惯例:深半透底 + 白图标(参考 YouTube/抖音/小红书的视频控件)
v0.20.0 改成 rgba(255,255,255,0.90) 是错的 白底 + --color-on-overlay icon = 看不见 */
--color-bg-on-media: rgba(0, 0, 0, 0.55);
--color-bg-on-media-hover: rgba(0, 0, 0, 0.72);
/* Scrollbar */
--color-scrollbar-thumb: rgba(0, 0, 0, 0.15);

View File

@ -21,7 +21,7 @@ function VideoThumbnail({ video, onClick }: { video: AssetVideo; onClick: () =>
onClick={onClick}
>
{video.result_url ? (
<video ref={videoRef} src={rewriteTosUrl(video.result_url)} className={styles.thumbVideo} muted loop preload="metadata" />
<video ref={videoRef} src={rewriteTosUrl(video.result_url)} poster={video.thumbnail_url ? rewriteTosUrl(video.thumbnail_url) : undefined} className={styles.thumbVideo} muted loop preload="metadata" />
) : (
<div className={styles.thumbPlaceholder} />
)}

View File

@ -72,6 +72,7 @@ function VideoThumbnail({
<video
ref={videoRef}
src={rewriteTosUrl(task.resultUrl)}
poster={task.thumbnailUrl ? rewriteTosUrl(task.thumbnailUrl) : undefined}
className={styles.thumbVideo}
muted
loop

View File

@ -21,7 +21,7 @@ function VideoThumbnail({ video, onClick }: { video: AssetVideo; onClick: () =>
onClick={onClick}
>
{video.result_url ? (
<video ref={videoRef} src={rewriteTosUrl(video.result_url)} className={styles.thumbVideo} muted loop preload="metadata" />
<video ref={videoRef} src={rewriteTosUrl(video.result_url)} poster={video.thumbnail_url ? rewriteTosUrl(video.thumbnail_url) : undefined} className={styles.thumbVideo} muted loop preload="metadata" />
) : (
<div className={styles.thumbPlaceholder} />
)}

View File

@ -414,6 +414,7 @@ export interface AssetVideo {
task_id: string;
prompt: string;
result_url: string;
thumbnail_url?: string;
duration: number;
seconds_consumed: number;
cost_amount?: number;