From 45d4ac2216868e4c3a4a296b755b4fb2b72ccac4 Mon Sep 17 00:00:00 2001 From: aid Date: Thu, 9 Apr 2026 20:08:38 +0800 Subject: [PATCH] =?UTF-8?q?fix(leai):=20originalImageUrl=20=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E5=85=9C=E5=BA=95=E5=90=8C=E6=AD=A5=E4=B8=8E=E5=8E=86?= =?UTF-8?q?=E5=8F=B2=E6=95=B0=E6=8D=AE=E5=9B=9E=E5=A1=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 背景: 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) --- .../modules/leai/service/LeaiSyncService.java | 15 ++++++++++ .../V13__backfill_original_image_url.sql | 29 +++++++++++++++++++ ...V14__force_backfill_original_image_url.sql | 15 ++++++++++ ...ckfill_original_image_url_empty_string.sql | 22 ++++++++++++++ 4 files changed, 81 insertions(+) create mode 100644 backend-java/src/main/resources/db/migration/V13__backfill_original_image_url.sql create mode 100644 backend-java/src/main/resources/db/migration/V14__force_backfill_original_image_url.sql create mode 100644 backend-java/src/main/resources/db/migration/V15__backfill_original_image_url_empty_string.sql diff --git a/backend-java/src/main/java/com/competition/modules/leai/service/LeaiSyncService.java b/backend-java/src/main/java/com/competition/modules/leai/service/LeaiSyncService.java index 62a83fd..ccb3ffa 100644 --- a/backend-java/src/main/java/com/competition/modules/leai/service/LeaiSyncService.java +++ b/backend-java/src/main/java/com/competition/modules/leai/service/LeaiSyncService.java @@ -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()); diff --git a/backend-java/src/main/resources/db/migration/V13__backfill_original_image_url.sql b/backend-java/src/main/resources/db/migration/V13__backfill_original_image_url.sql new file mode 100644 index 0000000..6f5b3fe --- /dev/null +++ b/backend-java/src/main/resources/db/migration/V13__backfill_original_image_url.sql @@ -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; diff --git a/backend-java/src/main/resources/db/migration/V14__force_backfill_original_image_url.sql b/backend-java/src/main/resources/db/migration/V14__force_backfill_original_image_url.sql new file mode 100644 index 0000000..e04b197 --- /dev/null +++ b/backend-java/src/main/resources/db/migration/V14__force_backfill_original_image_url.sql @@ -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; diff --git a/backend-java/src/main/resources/db/migration/V15__backfill_original_image_url_empty_string.sql b/backend-java/src/main/resources/db/migration/V15__backfill_original_image_url_empty_string.sql new file mode 100644 index 0000000..c2a81e5 --- /dev/null +++ b/backend-java/src/main/resources/db/migration/V15__backfill_original_image_url_empty_string.sql @@ -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 != '';