wangyunpeng 1 день назад
Родитель
Сommit
0ae04d8f5e

+ 94 - 3
api-module/src/main/java/com/tzld/piaoquan/api/service/contentplatform/impl/ContentPlatformPlanServiceImpl.java

@@ -961,7 +961,77 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
                 exhausted[cur] = true;
             }
         }
-        return paginateCandidates(param, merged);
+        Page<VideoContentItemVO> page = paginateCandidates(param, merged);
+        enrichWithDisplayData(page.getObjs(), param, user);
+        return page;
+    }
+
+    /**
+     * 分页后按需补充分裂率和缺失封面,仅针对最终返回的 pageSize 条数据。
+     * 避免 fetchHotCandidates 拉取上万候选时全量查 content_platform_video_datastat_agg。
+     */
+    private void enrichWithDisplayData(List<VideoContentItemVO> items, VideoContentListParam param, ContentPlatformAccount user) {
+        if (CollectionUtils.isEmpty(items)) {
+            return;
+        }
+        String type = getVideoContentListType(param.getType());
+        String datastatDt = planMapperExt.getVideoDatastatMaxDt();
+        String userChannel = user.getChannel();
+
+        // 1. 补缺失封面
+        List<Long> missingCoverIds = items.stream()
+                .filter(o -> !StringUtils.hasText(o.getCover()))
+                .map(VideoContentItemVO::getVideoId)
+                .filter(Objects::nonNull)
+                .distinct()
+                .collect(Collectors.toList());
+        if (!missingCoverIds.isEmpty()) {
+            Map<Long, VideoDetail> coverMap = new HashMap<>();
+            for (List<Long> partition : Lists.partition(missingCoverIds, 20)) {
+                coverMap.putAll(messageAttachmentService.getVideoDetail(new HashSet<>(partition)));
+            }
+            for (VideoContentItemVO item : items) {
+                VideoDetail detail = coverMap.get(item.getVideoId());
+                if (detail != null) {
+                    String cover = detail.getCover().substring(0, detail.getCover().indexOf("/watermark"));
+                    item.setCover(cover);
+                }
+            }
+        }
+
+        // 2. 补充分裂率
+        List<Long> videoIds = items.stream()
+                .map(VideoContentItemVO::getVideoId)
+                .filter(Objects::nonNull)
+                .distinct()
+                .collect(Collectors.toList());
+        if (videoIds.isEmpty()) {
+            return;
+        }
+        List<ContentPlatformVideoDataStatAgg> aggList = getTypeChannelVideoDataStatAggList(
+                datastatDt, type, Arrays.asList("sum", userChannel), videoIds);
+
+        Map<Long, Double> typeNormalMap = aggList.stream()
+                .filter(o -> "sum".equals(o.getChannel()) && "normal".equals(o.getStrategy()))
+                .collect(Collectors.toMap(ContentPlatformVideoDataStatAgg::getVideoId, ContentPlatformVideoDataStatAgg::getFissionRate));
+        Map<Long, Double> channelNormalMap = aggList.stream()
+                .filter(o -> userChannel.equals(o.getChannel()) && "normal".equals(o.getStrategy()))
+                .collect(Collectors.toMap(ContentPlatformVideoDataStatAgg::getVideoId, ContentPlatformVideoDataStatAgg::getFissionRate));
+        Map<Long, Double> channelRecommendMap = aggList.stream()
+                .filter(o -> userChannel.equals(o.getChannel()) && "recommend".equals(o.getStrategy()))
+                .collect(Collectors.toMap(ContentPlatformVideoDataStatAgg::getVideoId, ContentPlatformVideoDataStatAgg::getFissionRate));
+        Map<Long, Double> typeRecommendMap = aggList.stream()
+                .filter(o -> "sum".equals(o.getChannel()) && "recommend".equals(o.getStrategy()))
+                .collect(Collectors.toMap(ContentPlatformVideoDataStatAgg::getVideoId, ContentPlatformVideoDataStatAgg::getFissionRate));
+
+        for (VideoContentItemVO item : items) {
+            item.setIndustryFissionRate(typeNormalMap.get(item.getVideoId()));
+            item.setChannelFissionRate(channelNormalMap.get(item.getVideoId()));
+            item.setRecommendScore(channelRecommendMap.get(item.getVideoId()));
+            if (Objects.isNull(item.getRecommendScore())) {
+                item.setRecommendScore(typeRecommendMap.get(item.getVideoId()));
+            }
+        }
     }
 
     /**
@@ -1265,8 +1335,29 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
         String strategy = param.getSort() == 3 ? "recommend" : "normal";
         List<ContentPlatformVideo> videoList = planMapperExt.getVideoList(param, dt, datastatDt, type, channel, strategy,
                 videoMinScore, 0, limit, sort);
-        List<VideoContentItemVO> result = buildVideoContentItemVOList(videoList, type, "sum", user.getChannel(), datastatDt);
-        return result == null ? new ArrayList<>() : result;
+        return toBasicVideoContentItems(videoList);
+    }
+
+    /**
+     * 轻量 PO→VO 转换,只设基础字段,不查 cover / fission_rate。
+     * cover 和 fission_rate 在分页后按需补充,避免对大量候选做无效 enrichment。
+     */
+    private List<VideoContentItemVO> toBasicVideoContentItems(List<ContentPlatformVideo> videoList) {
+        if (CollectionUtils.isEmpty(videoList)) {
+            return new ArrayList<>();
+        }
+        List<VideoContentItemVO> result = new ArrayList<>(videoList.size());
+        for (ContentPlatformVideo video : videoList) {
+            VideoContentItemVO item = new VideoContentItemVO();
+            item.setVideoId(video.getVideoId());
+            item.setTitle(video.getTitle());
+            item.setCover(video.getCover());
+            item.setVideo(video.getVideo());
+            item.setScore(video.getScore());
+            item.setExperimentId("hot");
+            result.add(item);
+        }
+        return result;
     }
 
     /**