fix(leai): originalImageUrl 字段兜底同步与历史数据回填

背景:
  leai webhook 同步作品时大多只传 coverUrl 不传 originalImageUrl,
  导致前端作品库 PIP 画中画与详情页「画作原图」卡片不展示
  (v-if="work.originalImageUrl" 检查为 null/空字符串时屏蔽)。

修复:
- LeaiSyncService 三处(createWork/updateProcessing/updateStatusForward)
  加 fallback:originalImageUrl 没传但 coverUrl 有传时,用 coverUrl 兜底
- V13 migration 回填历史数据(IS NULL 条件)
- V14 force 重跑(V13 因 history 表残留同版本号脏数据被 repair 跳过)
- V15 补充:部分作品 original_image_url 是空字符串而非 NULL,
  V14 的 IS NULL 没匹配到,V15 用 (IS NULL OR = '') 兼容空串

剩余 TODO(留给后端联调):
  - leai webhook 后续若拆分独立的 cover 字段,前端 PIP 将自动展现
    "AI 封面 + 原图" 的真实区分(当前所有作品大小图相同时由
    前端 !== 检查屏蔽 PIP)
  - 详见 docs/design/public/ugc-work-status-redesign.md

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
aid 2026-04-09 20:08:38 +08:00
parent 37bd82714d
commit 45d4ac2216
4 changed files with 81 additions and 0 deletions

View File

@ -129,6 +129,13 @@ public class LeaiSyncService implements ILeaiSyncService {
if (coverUrl == null) coverUrl = remoteData.get("cover_url");
if (coverUrl != null) work.setCoverUrl(coverUrl.toString());
// 兜底如果 originalImageUrl 没传但 coverUrl 传了 coverUrl 也写入 originalImageUrl
// 当前 leai webhook 大多只传 coverUrl实际就是用户上传的原图不传独立的 originalImageUrl 字段
// 这里兜底让前端 PIP / 详情页画作原图卡片能正确展示
if (originalImageUrl == null && coverUrl != null) {
work.setOriginalImageUrl(coverUrl.toString());
}
// 通过手机号查找用户ID多租户场景
if (phone != null && work.getUserId() == null) {
Long userId = findUserIdByPhone(phone);
@ -189,6 +196,10 @@ public class LeaiSyncService implements ILeaiSyncService {
if (coverUrl != null) {
wrapper.set(UgcWork::getCoverUrl, coverUrl.toString());
}
// 兜底originalImageUrl 没传但 coverUrl 传了 coverUrl 也写入 originalImageUrl
if (originalImageUrl == null && coverUrl != null) {
wrapper.set(UgcWork::getOriginalImageUrl, coverUrl.toString());
}
wrapper.set(UgcWork::getModifyTime, LocalDateTime.now());
ugcWorkMapper.update(null, wrapper);
@ -237,6 +248,10 @@ public class LeaiSyncService implements ILeaiSyncService {
if (coverUrl != null) {
wrapper.set(UgcWork::getCoverUrl, coverUrl.toString());
}
// 兜底originalImageUrl 没传但 coverUrl 传了 coverUrl 也写入 originalImageUrl
if (originalImageUrl == null && coverUrl != null) {
wrapper.set(UgcWork::getOriginalImageUrl, coverUrl.toString());
}
wrapper.set(UgcWork::getModifyTime, LocalDateTime.now());

View File

@ -0,0 +1,29 @@
-- ========================================================
-- V13: 回填 t_ugc_work.original_image_url 字段
-- ========================================================
-- 背景:
-- leai webhook 同步作品时,大多数情况下只传了 cover_url
-- 没有单独传 originalImageUrl 字段,导致 LeaiSyncService
-- 把 cover_url 写入了 cover 字段,但 original_image_url 字段为 null。
--
-- 实际情况:
-- 当前所有作品的 cover_url 实际上就是用户上传的原图,
-- AI 生成的独立绘本封面字段尚未在 leai webhook 中拆分提供。
--
-- 影响:
-- 前端作品库 / 发现页 PIP 画中画功能、详情页「画作原图」卡片
-- 需要 original_image_url 字段才能展示,当前为 null 时这些 UI
-- 全部不渲染,用户看不到原图。
--
-- 修复:
-- 把 original_image_url 为 null 但 cover_url 有值的数据,
-- 统一回填为 cover_url。
-- 同时 LeaiSyncService 已加 fallback新数据自动写入。
--
-- 详见 docs/design/public/ugc-work-status-redesign.md
-- ========================================================
UPDATE t_ugc_work
SET original_image_url = cover_url
WHERE original_image_url IS NULL
AND cover_url IS NOT NULL;

View File

@ -0,0 +1,15 @@
-- ========================================================
-- V14: 强制回填 t_ugc_work.original_image_url
-- ========================================================
-- 背景:
-- V13 因 Flyway schema_history 表残留同版本号脏数据被 repair 跳过,
-- 实际 SQL 没真正执行。新建 V14 强制重跑同样的 UPDATE 逻辑。
--
-- 详见 docs/design/public/ugc-work-status-redesign.md
-- 详见 V13__backfill_original_image_url.sql
-- ========================================================
UPDATE t_ugc_work
SET original_image_url = cover_url
WHERE original_image_url IS NULL
AND cover_url IS NOT NULL;

View File

@ -0,0 +1,22 @@
-- ========================================================
-- V15: 回填 t_ugc_work.original_image_url 空字符串数据
-- ========================================================
-- 背景:
-- V14 用 `WHERE original_image_url IS NULL` 回填了 NULL 的数据,
-- 但部分作品的 original_image_url 字段是空字符串 '' 而不是 NULL
-- JS 前端经常把空字段当 '' 传给后端V14 的 IS NULL 条件没匹配到。
--
-- 前端 v-if="work.originalImageUrl" 在空字符串时是 falsy
-- 导致这些作品的「画作原图」卡片和 PIP 不显示。
--
-- 修复:
-- 把 original_image_url 为 NULL 或空字符串的数据,统一回填为 cover_url。
--
-- 详见 V13、V14 历史
-- ========================================================
UPDATE t_ugc_work
SET original_image_url = cover_url
WHERE (original_image_url IS NULL OR original_image_url = '')
AND cover_url IS NOT NULL
AND cover_url != '';