|
@@ -3,6 +3,7 @@ package com.tzld.piaoquan.longarticle.service.local.impl;
|
|
|
import cn.hutool.core.collection.CollectionUtil;
|
|
import cn.hutool.core.collection.CollectionUtil;
|
|
|
import com.alibaba.fastjson.JSON;
|
|
import com.alibaba.fastjson.JSON;
|
|
|
import com.alibaba.fastjson.JSONArray;
|
|
import com.alibaba.fastjson.JSONArray;
|
|
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue;
|
|
import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue;
|
|
|
import com.google.common.collect.Lists;
|
|
import com.google.common.collect.Lists;
|
|
|
import com.tzld.piaoquan.longarticle.common.constants.TimeConstant;
|
|
import com.tzld.piaoquan.longarticle.common.constants.TimeConstant;
|
|
@@ -17,12 +18,15 @@ import com.tzld.piaoquan.longarticle.model.dto.MiniprogramCardRequest;
|
|
|
import com.tzld.piaoquan.longarticle.model.dto.PublishArticleData;
|
|
import com.tzld.piaoquan.longarticle.model.dto.PublishArticleData;
|
|
|
import com.tzld.piaoquan.longarticle.model.dto.RecallVideoScoreParam;
|
|
import com.tzld.piaoquan.longarticle.model.dto.RecallVideoScoreParam;
|
|
|
import com.tzld.piaoquan.longarticle.model.dto.RecallVideoScoreVO;
|
|
import com.tzld.piaoquan.longarticle.model.dto.RecallVideoScoreVO;
|
|
|
|
|
+import com.tzld.piaoquan.longarticle.model.dto.VideoArticleMatchQueryParam;
|
|
|
|
|
+import com.tzld.piaoquan.longarticle.model.dto.VideoArticleMatchResult;
|
|
|
import com.tzld.piaoquan.longarticle.model.po.crawler.FwhDailyPublishDetail;
|
|
import com.tzld.piaoquan.longarticle.model.po.crawler.FwhDailyPublishDetail;
|
|
|
import com.tzld.piaoquan.longarticle.model.po.longarticle.*;
|
|
import com.tzld.piaoquan.longarticle.model.po.longarticle.*;
|
|
|
import com.tzld.piaoquan.longarticle.model.vo.*;
|
|
import com.tzld.piaoquan.longarticle.model.vo.*;
|
|
|
import com.tzld.piaoquan.longarticle.service.local.AccountService;
|
|
import com.tzld.piaoquan.longarticle.service.local.AccountService;
|
|
|
import com.tzld.piaoquan.longarticle.service.local.CoreService;
|
|
import com.tzld.piaoquan.longarticle.service.local.CoreService;
|
|
|
import com.tzld.piaoquan.longarticle.service.local.PlanAccountService;
|
|
import com.tzld.piaoquan.longarticle.service.local.PlanAccountService;
|
|
|
|
|
+import com.tzld.piaoquan.longarticle.service.local.VideoMultiService;
|
|
|
import com.tzld.piaoquan.longarticle.service.remote.AigcService;
|
|
import com.tzld.piaoquan.longarticle.service.remote.AigcService;
|
|
|
import com.tzld.piaoquan.longarticle.service.remote.MatchService;
|
|
import com.tzld.piaoquan.longarticle.service.remote.MatchService;
|
|
|
import com.tzld.piaoquan.longarticle.service.remote.VideoService;
|
|
import com.tzld.piaoquan.longarticle.service.remote.VideoService;
|
|
@@ -103,6 +107,8 @@ public class CoreServiceImpl implements CoreService {
|
|
|
@Autowired
|
|
@Autowired
|
|
|
private VideoVectorService videoVectorService;
|
|
private VideoVectorService videoVectorService;
|
|
|
|
|
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private VideoMultiService videoMultiService;
|
|
|
@Autowired
|
|
@Autowired
|
|
|
private VectorMatchVideoMapper vectorMatchVideoMapper;
|
|
private VectorMatchVideoMapper vectorMatchVideoMapper;
|
|
|
|
|
|
|
@@ -860,22 +866,29 @@ public class CoreServiceImpl implements CoreService {
|
|
|
List<PublishMiniprogram> publishMiniprogramList = publicContentService.getPublishMiniprograms(publishContent);
|
|
List<PublishMiniprogram> publishMiniprogramList = publicContentService.getPublishMiniprograms(publishContent);
|
|
|
//不存在则重新生成
|
|
//不存在则重新生成
|
|
|
if (CollectionUtils.isEmpty(publishMiniprogramList)) {
|
|
if (CollectionUtils.isEmpty(publishMiniprogramList)) {
|
|
|
- // 优先尝试 recallWithScore 召回的视频(仅配置的账号或配置为ALL时生效)
|
|
|
|
|
- if (isRecallPublishMiniprogramAccount(planAccount.getAccountName())) {
|
|
|
|
|
- publishMiniprogramList = getRecallPublishMiniprograms(publishContent, planAccount);
|
|
|
|
|
- // 开关打开时,同时执行匹配流程获取小程序信息,将标题和封面替换至召回视频
|
|
|
|
|
- if (!CollectionUtils.isEmpty(publishMiniprogramList)
|
|
|
|
|
- && replaceRecallTitleCoverSwitch != null && replaceRecallTitleCoverSwitch) {
|
|
|
|
|
- List<PublishMiniprogram> matchedList = getDefaultPublishMiniprograms(publishContent, planAccount, false);
|
|
|
|
|
- if (!CollectionUtils.isEmpty(matchedList)) {
|
|
|
|
|
- replaceRecallTitleAndCover(publishMiniprogramList, matchedList);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // 如果有experimentId,优先通过queryBySourceId接口获取匹配视频生成小程序卡片
|
|
|
|
|
+ if (StringUtils.isNotEmpty(publishContent.getExperimentId())) {
|
|
|
|
|
+ publishMiniprogramList = getExperimentMatchMiniprograms(publishContent, planAccount);
|
|
|
}
|
|
}
|
|
|
|
|
+ // experimentId未获取到结果时,继续走原有逻辑
|
|
|
if (CollectionUtils.isEmpty(publishMiniprogramList)) {
|
|
if (CollectionUtils.isEmpty(publishMiniprogramList)) {
|
|
|
- publishMiniprogramList = getDefaultPublishMiniprograms(publishContent, planAccount, true);
|
|
|
|
|
|
|
+ // 优先尝试 recallWithScore 召回的视频(仅配置的账号或配置为ALL时生效)
|
|
|
|
|
+ if (isRecallPublishMiniprogramAccount(planAccount.getAccountName())) {
|
|
|
|
|
+ publishMiniprogramList = getRecallPublishMiniprograms(publishContent, planAccount);
|
|
|
|
|
+ // 开关打开时,同时执行匹配流程获取小程序信息,将标题和封面替换至召回视频
|
|
|
|
|
+ if (!CollectionUtils.isEmpty(publishMiniprogramList)
|
|
|
|
|
+ && replaceRecallTitleCoverSwitch != null && replaceRecallTitleCoverSwitch) {
|
|
|
|
|
+ List<PublishMiniprogram> matchedList = getDefaultPublishMiniprograms(publishContent, planAccount, false);
|
|
|
|
|
+ if (!CollectionUtils.isEmpty(matchedList)) {
|
|
|
|
|
+ replaceRecallTitleAndCover(publishMiniprogramList, matchedList);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
if (CollectionUtils.isEmpty(publishMiniprogramList)) {
|
|
if (CollectionUtils.isEmpty(publishMiniprogramList)) {
|
|
|
- return null;
|
|
|
|
|
|
|
+ publishMiniprogramList = getDefaultPublishMiniprograms(publishContent, planAccount, true);
|
|
|
|
|
+ if (CollectionUtils.isEmpty(publishMiniprogramList)) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -1003,6 +1016,99 @@ public class CoreServiceImpl implements CoreService {
|
|
|
return publishMiniprogramList;
|
|
return publishMiniprogramList;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 通过 experimentId 调用 queryBySourceId 接口获取匹配视频,生成小程序卡片
|
|
|
|
|
+ * 返回 null 表示无匹配结果,调用方应回退到原有流程
|
|
|
|
|
+ */
|
|
|
|
|
+ private List<PublishMiniprogram> getExperimentMatchMiniprograms(PublishContent publishContent, PlanAccount planAccount) {
|
|
|
|
|
+ VideoArticleMatchQueryParam param = new VideoArticleMatchQueryParam();
|
|
|
|
|
+ param.setAccount(planAccount.getAccountName());
|
|
|
|
|
+ param.setSourceId(publishContent.getSourceId());
|
|
|
|
|
+ param.setTopN(miniVideoNum);
|
|
|
|
|
+
|
|
|
|
|
+ List<VideoArticleMatchResult> matchResults = videoVectorService.queryBySourceId(param);
|
|
|
|
|
+ if (CollectionUtils.isEmpty(matchResults)) {
|
|
|
|
|
+ log.info("getExperimentMatchMiniprograms no results, experimentId={}, sourceId={}",
|
|
|
|
|
+ publishContent.getExperimentId(), publishContent.getSourceId());
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ log.info("getExperimentMatchMiniprograms found {} results, experimentId={}, sourceId={}",
|
|
|
|
|
+ matchResults.size(), publishContent.getExperimentId(), publishContent.getSourceId());
|
|
|
|
|
+
|
|
|
|
|
+ List<VideoDetail> videoDetails = new ArrayList<>();
|
|
|
|
|
+ Map<Long, String> videoExperimentMap = new LinkedHashMap<>();
|
|
|
|
|
+ for (VideoArticleMatchResult matchResult : matchResults) {
|
|
|
|
|
+ if (matchResult.getMatchVideoId() == null) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ VideoDetail videoDetail = VideoUtils.getVideoDetail(matchResult.getMatchVideoId());
|
|
|
|
|
+ if (videoDetail == null) {
|
|
|
|
|
+ log.warn("getVideoDetail null for matchVideoId={}", matchResult.getMatchVideoId());
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ videoDetail.setSource("piaoquan");
|
|
|
|
|
+ videoDetail.setKimiTitle(matchResult.getVideoTitle());
|
|
|
|
|
+ videoDetail.setVideoOss(videoDetail.getOssVideoPath());
|
|
|
|
|
+ videoDetail.setCoverOss(videoDetail.getShareImgPath());
|
|
|
|
|
+ videoDetails.add(videoDetail);
|
|
|
|
|
+ videoExperimentMap.put(matchResult.getMatchVideoId(), matchResult.getExperimentId());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (CollectionUtils.isEmpty(videoDetails)) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 数量不足时用第一个视频补足,超出则截断(补足的视频复用第一个视频的experimentId)
|
|
|
|
|
+ if (videoDetails.size() < miniVideoNum) {
|
|
|
|
|
+ VideoDetail first = videoDetails.get(0);
|
|
|
|
|
+ int needAddCount = miniVideoNum - videoDetails.size();
|
|
|
|
|
+ for (int i = 0; i < needAddCount; i++) {
|
|
|
|
|
+ VideoDetail copy = new VideoDetail();
|
|
|
|
|
+ BeanUtils.copyProperties(first, copy);
|
|
|
|
|
+ videoDetails.add(copy);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (videoDetails.size() > miniVideoNum) {
|
|
|
|
|
+ videoDetails = videoDetails.subList(0, miniVideoNum);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ List<PublishMiniprogram> publishMiniprogramList = cardService.generateCards(videoDetails, planAccount, publishContent);
|
|
|
|
|
+ if (!CollectionUtils.isEmpty(publishMiniprogramList)) {
|
|
|
|
|
+ // 为每张卡片的 productionPath 拼接对应视频的 growthExtData 参数
|
|
|
|
|
+ appendGrowthExtDataToCards(publishMiniprogramList, videoExperimentMap);
|
|
|
|
|
+ for (PublishMiniprogram publishMiniprogram : publishMiniprogramList) {
|
|
|
|
|
+ rootSourceService.addRootSource(publishMiniprogram, planAccount, publishContent);
|
|
|
|
|
+ publishMiniprogramMapper.insertSelective(publishMiniprogram);
|
|
|
|
|
+ }
|
|
|
|
|
+ log.info("getExperimentMatchMiniprograms success, cards={}, experimentId={}",
|
|
|
|
|
+ publishMiniprogramList.size(), publishContent.getExperimentId());
|
|
|
|
|
+ }
|
|
|
|
|
+ return publishMiniprogramList;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 为每张卡片的 productionPath 拼接对应视频的 growthExtData 参数
|
|
|
|
|
+ * 参照 TouLiuHttpClient.sendAdFlowAddRequest 的拼接方式
|
|
|
|
|
+ */
|
|
|
|
|
+ private void appendGrowthExtDataToCards(List<PublishMiniprogram> cards, Map<Long, String> videoExperimentMap) {
|
|
|
|
|
+ if (CollectionUtils.isEmpty(cards) || videoExperimentMap == null || videoExperimentMap.isEmpty()) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ for (PublishMiniprogram card : cards) {
|
|
|
|
|
+ String experimentId = videoExperimentMap.get(card.getVideoId());
|
|
|
|
|
+ if (StringUtils.isEmpty(experimentId)) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ String productionPath = card.getProductionPath();
|
|
|
|
|
+ if (StringUtils.isNotEmpty(productionPath)) {
|
|
|
|
|
+ JSONObject extData = new JSONObject();
|
|
|
|
|
+ extData.put("experimentId", experimentId);
|
|
|
|
|
+ card.setProductionPath(videoMultiService.appendGrowthExtData(productionPath, extData));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ log.info("appendGrowthExtDataToCards done, {} cards", cards.size());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private List<PublishMiniprogram> getPublishMiniprogramList(List<VideoDetail> videoDetails, PlanAccount planAccount,
|
|
private List<PublishMiniprogram> getPublishMiniprogramList(List<VideoDetail> videoDetails, PlanAccount planAccount,
|
|
|
PublishContent publishContent) {
|
|
PublishContent publishContent) {
|
|
|
if (CollectionUtils.isEmpty(videoDetails)) {
|
|
if (CollectionUtils.isEmpty(videoDetails)) {
|