Selaa lähdekoodia

fix: deconstructPoints 接口拿不到解构数据

根因:
1. result_json 字段是 BLOB 类型,需用 selectByExampleWithBLOBs 才能加载,
   原代码用 selectByExample 拿不到这个字段,所以 rawResult 永远 null
2. 即使本地 result_json 为空,正确做法是调 videoSearchService.getDeconstructResult
   (内部会用 taskId 调外部 API + 回填本地表),原代码无此 fallback

修复:
- 改用 selectByExampleWithBLOBs 加载 result_json BLOB 字段
- 本地无 result_json 时, 包装 GetDeconstructParam 调
  videoSearchService.getDeconstructResult(taskId) 拿真实数据 + 回填
- 透传 result 字段(含 point_label/inspiration/purpose/keypoint 等真实层级)

实测 channelContentId=8075198879 现在能拿到完整解构 JSON,
含 关键点 / 灵感点 / 目的点 三级结构,前端 DeconstructTree
递归渲染即可,无需改前端。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
刘立冬 1 viikko sitten
vanhempi
commit
2a8f41abc2

+ 47 - 7
core/src/main/java/com/tzld/videoVector/service/recall/impl/VectorRecallTestServiceImpl.java

@@ -8,6 +8,7 @@ import com.tzld.videoVector.common.enums.Modality;
 import com.tzld.videoVector.dao.mapper.videoVector.VideoAiUnderstandingMapper;
 import com.tzld.videoVector.dao.mapper.videoVector.deconstruct.DeconstructContentMapper;
 import com.tzld.videoVector.model.entity.VideoDetail;
+import com.tzld.videoVector.model.param.GetDeconstructParam;
 import com.tzld.videoVector.model.param.MatchTopNVideoParam;
 import com.tzld.videoVector.model.param.recall.MatchByTextParam;
 import com.tzld.videoVector.model.param.recall.MatchByVideoIdParam;
@@ -128,13 +129,23 @@ public class VectorRecallTestServiceImpl implements VectorRecallTestService {
         if (videoId == null || videoId <= 0L) {
             return null;
         }
-        // 通过 channelContentId = String(videoId) 查 deconstruct_content
-        Map<String, DeconstructContent> map = queryDeconstructContent(
-                Collections.singletonList(String.valueOf(videoId))
-        );
-        DeconstructContent content = map.get(String.valueOf(videoId));
+        String channelContentId = String.valueOf(videoId);
+
+        // 1. 按 channel_content_id 查 deconstruct_content (用 WithBLOBs 拿 result_json BLOB)
+        DeconstructContent content;
+        try {
+            DeconstructContentExample example = new DeconstructContentExample();
+            example.createCriteria().andChannelContentIdEqualTo(channelContentId);
+            example.setOrderByClause("id DESC");
+            List<DeconstructContent> list = deconstructContentMapper.selectByExampleWithBLOBs(example);
+            content = list.isEmpty() ? null : list.get(0);
+        } catch (Exception e) {
+            log.error("getDeconstructPoints: query db fail, videoId={}, err={}", videoId, e.getMessage(), e);
+            return null;
+        }
+
         if (content == null) {
-            log.info("getDeconstructPoints: not found, videoId={}", videoId);
+            log.info("getDeconstructPoints: deconstruct_content 表无 channel_content_id={} 的记录", channelContentId);
             return null;
         }
 
@@ -150,14 +161,43 @@ public class VectorRecallTestServiceImpl implements VectorRecallTestService {
         vo.setTitle(content.getTitle());
         vo.setFailureReason(content.getFailureReason());
 
+        // 2. 优先用本地 result_json (已 WithBLOBs)
         if (StringUtils.hasText(content.getResultJson())) {
             try {
                 vo.setRawResult(JSON.parseObject(content.getResultJson()));
+                return vo;
             } catch (Exception e) {
-                log.warn("getDeconstructPoints: parse resultJson fail, videoId={}, err={}",
+                log.warn("getDeconstructPoints: parse local resultJson fail, videoId={}, err={}",
                         videoId, e.getMessage());
             }
         }
+
+        // 3. 本地 result_json 为空 → 用 taskId 调现有 getDeconstructResult,
+        //    它内部会调外部 API 拉数据 + 回填本地表
+        if (StringUtils.hasText(content.getTaskId())) {
+            try {
+                GetDeconstructParam p = new GetDeconstructParam();
+                p.setTaskId(content.getTaskId());
+                p.setBizType(content.getBizType() == null ? null : content.getBizType().intValue());
+                p.setContentType(content.getContentType() == null ? null : content.getContentType().intValue());
+                p.setChannelContentId(channelContentId);
+                JSONObject apiResult = videoSearchService.getDeconstructResult(p);
+                if (apiResult != null) {
+                    // 现有 getDeconstructResult 返回结构: { result: {...}, status, taskId, url }
+                    // 解构 JSON 在 result 字段里, 透传给前端
+                    Object inner = apiResult.get("result");
+                    if (inner instanceof JSONObject) {
+                        vo.setRawResult((JSONObject) inner);
+                    } else if (inner != null) {
+                        // 兜底: 整个 apiResult 透传
+                        vo.setRawResult(apiResult);
+                    }
+                }
+            } catch (Exception e) {
+                log.warn("getDeconstructPoints: fallback to videoSearchService.getDeconstructResult failed, videoId={}, taskId={}, err={}",
+                        videoId, content.getTaskId(), e.getMessage());
+            }
+        }
         return vo;
     }