Selaa lähdekoodia

Merge branch 'master' into dev-xym-we-com

xueyiming 9 kuukautta sitten
vanhempi
commit
77a8d71a6a
23 muutettua tiedostoa jossa 544 lisäystä ja 56 poistoa
  1. 1 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/common/enums/RankStrategyEnum.java
  2. 9 5
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/mapper/aigc/AigcBaseMapper.java
  3. 6 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/dto/NotPublishPlan.java
  4. 15 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/dto/ProduceContentDTO.java
  5. 8 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/entity/longArticle/DatastatSortStrategy.java
  6. 7 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/vo/NewSortStrategyExport.java
  7. 1 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/crawler/PublishSortLogRepository.java
  8. 109 7
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/DataDashboardService.java
  9. 23 11
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/RecommendService.java
  10. 18 2
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/XxlJobService.java
  11. 80 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/rank/strategy/LateRankStrategy.java
  12. 1 1
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/rank/strategy/RankV5Strategy.java
  13. 4 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recall/RecallService.java
  14. 7 1
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/score/ScoreService.java
  15. 8 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/score/ScoreStrategy.java
  16. 5 1
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/score/strategy/ViewCountRateCorrelationStrategy.java
  17. 5 1
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/score/strategy/ViewCountRateStrategy.java
  18. 30 2
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/strategy/reply/impl/BuckStrategyV1.java
  19. 9 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/util/DateUtils.java
  20. 21 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/web/XxlJobController.java
  21. 38 5
      long-article-recommend-service/src/main/resources/mapper/aigc/AigcBaseMapper.xml
  22. 8 6
      long-article-recommend-service/src/main/resources/mapper/longArticle/LongArticleBaseMapper.xml
  23. 131 14
      long-article-recommend-service/src/test/java/com/tzld/longarticle/recommend/server/RecommendTest.java

+ 1 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/common/enums/RankStrategyEnum.java

@@ -18,6 +18,7 @@ public enum RankStrategyEnum {
     ArticleRankV11("ArticleRankV11", "ArticleRankV11", "rankV11Strategy"),
     ArticleRankV12("ArticleRankV12", "ArticleRankV12", "rankV12Strategy"),
 
+    late_Strategy("ArticleRankLate", "晚间策略", "lateRankStrategy"),
     default_strategy("ArticleRankV1", "默认策略", "defaultRankStrategy"),
     ;
 

+ 9 - 5
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/mapper/aigc/AigcBaseMapper.java

@@ -1,10 +1,8 @@
 package com.tzld.longarticle.recommend.server.mapper.aigc;
 
 import com.tzld.longarticle.recommend.server.model.dto.NotPublishPlan;
-import com.tzld.longarticle.recommend.server.model.entity.aigc.CrawlerPlan;
-import com.tzld.longarticle.recommend.server.model.entity.aigc.CrawlerPlanResultRel;
-import com.tzld.longarticle.recommend.server.model.entity.aigc.PublishContent;
-import com.tzld.longarticle.recommend.server.model.entity.aigc.PublishPlanMiniprogramTask;
+import com.tzld.longarticle.recommend.server.model.dto.ProduceContentDTO;
+import com.tzld.longarticle.recommend.server.model.entity.aigc.*;
 import com.tzld.longarticle.recommend.server.model.param.MiniprogramTaskParam;
 import com.tzld.longarticle.recommend.server.model.param.PublishContentParam;
 import org.apache.ibatis.annotations.Mapper;
@@ -22,5 +20,11 @@ public interface AigcBaseMapper {
 
     List<CrawlerPlan> getCrawlerPlanByPlanIds(List<String> planIds);
 
-    List<NotPublishPlan> getNotPublishPlan();
+    List<NotPublishPlan> getNotPublishPlan(Long todayStart);
+
+    Integer getPublishPlanPushType(String planId);
+
+    List<PublishAccount> getPublishAccounts(String planId, Long todayStart);
+
+    List<ProduceContentDTO> getSourceProduceContentByTitles(List<String> titleList);
 }

+ 6 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/dto/NotPublishPlan.java

@@ -11,5 +11,11 @@ public class NotPublishPlan {
 
     private String planName;
 
+    private String errorMsg;
+
+    private Integer expectCount;
+
+    private Integer publishCount;
+
     private String publishPushTime;
 }

+ 15 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/dto/ProduceContentDTO.java

@@ -0,0 +1,15 @@
+package com.tzld.longarticle.recommend.server.model.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class ProduceContentDTO {
+
+    private String contentId;
+    private String title;
+    private Long produceTimestamp;
+    private String producePlanId;
+
+}

+ 8 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/entity/longArticle/DatastatSortStrategy.java

@@ -82,6 +82,12 @@ public class DatastatSortStrategy implements Serializable {
     private Double fission1Fission0Rate;
     @Column(name = "fission0_read_avg_rate")
     private Double fission0ReadAvgRate;
+    @Column(name = "his_read_rate")
+    private Double hisReadRate;
+    @Column(name = "his_first_read_rate")
+    private Double hisFirstReadRate;
+    @Column(name = "his_fission0_first_rate")
+    private Double hisFission0FirstRate;
     @Column(name = "gh_id")
     private String ghId;
     @Column(name = "title")
@@ -112,6 +118,8 @@ public class DatastatSortStrategy implements Serializable {
     private String publishMiniProgramInsertUseType;
     @Column(name = "publish_mini_program_num")
     private Integer publishMiniProgramNum;
+    @Column(name = "source_produce_plan_name")
+    private String sourceProducePlanName;
 
 
     @Data

+ 7 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/vo/NewSortStrategyExport.java

@@ -40,6 +40,11 @@ public class NewSortStrategyExport {
     private Double fission0FirstRate = 0.0;
     private Double fission1Fission0Rate = 0.0;
     private Double fission0ReadAvgRate = 0.0;
+    //历史信息
+    private Double hisReadRate = 0.0;
+    private Double hisFirstReadRate = 0.0;
+    private Double hisFission0FirstRate = 0.0;
+
     private Integer position;
     private String ghId;
     private String title;
@@ -65,5 +70,7 @@ public class NewSortStrategyExport {
     private String publishMiniProgramInsertUseType;
     // 发布内容小程序数量
     private Integer publishMiniProgramNum;
+    // 源生成计划名称
+    private String sourceProducePlanName;
 
 }

+ 1 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/crawler/PublishSortLogRepository.java

@@ -19,5 +19,6 @@ public interface PublishSortLogRepository extends JpaRepository<PublishSortLog,
 
     List<PublishSortLog> findByGhIdInAndDateStrGreaterThanEqual(List<String> ghIds, String dateStr);
 
+    List<PublishSortLog> findByStrategyInAndDateStrGreaterThanEqual(List<String> strategies, String dateStr);
 
 }

+ 109 - 7
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/DataDashboardService.java

@@ -9,6 +9,7 @@ import com.google.common.collect.Lists;
 import com.tzld.longarticle.recommend.server.common.enums.AccountBusinessTypeEnum;
 import com.tzld.longarticle.recommend.server.mapper.aigc.AigcBaseMapper;
 import com.tzld.longarticle.recommend.server.mapper.longArticle.LongArticleBaseMapper;
+import com.tzld.longarticle.recommend.server.model.dto.ProduceContentDTO;
 import com.tzld.longarticle.recommend.server.model.entity.aigc.*;
 import com.tzld.longarticle.recommend.server.model.entity.crawler.AccountAvgInfo;
 import com.tzld.longarticle.recommend.server.model.entity.crawler.Article;
@@ -25,6 +26,7 @@ import com.tzld.longarticle.recommend.server.repository.crawler.AccountAvgInfoRe
 import com.tzld.longarticle.recommend.server.repository.crawler.ArticleDetailInfoRepository;
 import com.tzld.longarticle.recommend.server.repository.crawler.ArticleRepository;
 import com.tzld.longarticle.recommend.server.repository.crawler.PublishSortLogRepository;
+import com.tzld.longarticle.recommend.server.service.score.ScoreStrategy;
 import com.tzld.longarticle.recommend.server.util.DateUtils;
 import com.tzld.longarticle.recommend.server.util.MapBuilder;
 import com.tzld.longarticle.recommend.server.util.feishu.FeiShu;
@@ -123,9 +125,12 @@ public class DataDashboardService {
                         Pair.of("AD", "0.00%"),
                         Pair.of("AE", "0.00%"),
                         Pair.of("AF", "0.00%"),
-                        Pair.of("AL", "0.00%"),
-                        Pair.of("AM", "0.00%"),
-                        Pair.of("AN", "0.00%")
+                        Pair.of("AG", "0.00%"),
+                        Pair.of("AH", "0.00%"),
+                        Pair.of("AI", "0.00%"),
+                        Pair.of("AO", "0.00%"),
+                        Pair.of("AP", "0.00%"),
+                        Pair.of("AQ", "0.00%")
                 );
 
         doSendFeishuSheet(dateStrList, sheetToken, sheetId, rowNum, rows, 2, styles);
@@ -134,7 +139,7 @@ public class DataDashboardService {
     private List<NewSortStrategyExport> newSortStrategyData(String dateStr) {
         long timestamp = DateUtils.dateStrToTimestamp(dateStr, "yyyyMMdd");
         String dateStrS = DateUtils.timestampToYMDStr(timestamp, "yyyy-MM-dd");
-        List<AccountAvgInfo> accountAvgInfoList = accountAvgInfoRepository.getAllByUpdateTimeGreaterThanEqual(dateStrS);
+        List<AccountAvgInfo> accountAvgInfoList = accountAvgInfoRepository.findAll();
         List<String> ghIds = accountAvgInfoList.stream().map(AccountAvgInfo::getGhId).distinct().collect(Collectors.toList());
 
         List<Article> articleList = articleRepository.getByGhIdInAndUpdateTimeGreaterThanAndTypeEquals(ghIds, timestamp, "9");
@@ -176,9 +181,10 @@ public class DataDashboardService {
         }
         Map<String, Map<String, Map<Long, PublishContent>>> publishContentMap = publishContents.stream()
                 .sorted(Comparator.comparingLong(PublishContent::getPublishTimestamp)).collect(
-                Collectors.groupingBy(PublishContent::getPublishAccountId,
-                Collectors.groupingBy(PublishContent::getTitle,
-                        Collectors.toMap(PublishContent::getPublishTimestamp, o -> o, (existing, replacement) -> replacement))));
+                        Collectors.groupingBy(PublishContent::getPublishAccountId,
+                                Collectors.groupingBy(PublishContent::getTitle,
+                                        Collectors.toMap(PublishContent::getPublishTimestamp, o -> o,
+                                                (existing, replacement) -> replacement))));
         // 获取发布内容排版
         List<String> publishContentIds = publishContents.stream().map(PublishContent::getId).collect(Collectors.toList());
         List<PublishContentLayout> publishContentLayoutList = new ArrayList<>();
@@ -247,6 +253,26 @@ public class DataDashboardService {
         }
         Map<String, List<PublishPlanMiniprogramTask>> miniprogramTaskMap = miniprogramTaskList.stream()
                 .collect(Collectors.groupingBy(PublishPlanMiniprogramTask::getPlanId));
+        // 源生成计划
+        List<String> titleList = articleList.stream().map(Article::getTitle).distinct().collect(Collectors.toList());
+        Map<String, ProducePlan> sourceTitlePlanMap = getTitleSourceProducePlanMap(titleList);
+        // 历史发布情况
+        List<String> titleMd5List = articleList.stream().map(Article::getTitleMd5).distinct().collect(Collectors.toList());
+        List<Article> hisArticleList = new ArrayList<>();
+        List<List<String>> titleMd5Partition = Lists.partition(new ArrayList<>(titleMd5List), 1000);
+        for (List<String> titleMd5s : titleMd5Partition) {
+            hisArticleList.addAll(articleRepository.getByTitleMd5InAndTypeEqualsAndStatusEquals(titleMd5s, "9", 1));
+        }
+        Map<String, List<Article>> hisArticleMap = hisArticleList.stream().collect(Collectors.groupingBy(Article::getTitle));
+        Set<String> hisWxSnList = hisArticleList.stream().map(Article::getWxSn).collect(Collectors.toSet());
+        List<ArticleDetailInfo> hisArticleDetailInfoList = new ArrayList<>();
+        List<List<String>> hisSnPartition = Lists.partition(new ArrayList<>(hisWxSnList), 1000);
+        for (List<String> sns : hisSnPartition) {
+            hisArticleDetailInfoList.addAll(articleDetailInfoRepository.getAllByWxSnIn(sns));
+        }
+        Map<String, List<ArticleDetailInfo>> hisArticleDetailInfoMap = hisArticleDetailInfoList.stream()
+                .collect(Collectors.groupingBy(ArticleDetailInfo::getWxSn));
+
         // result
         List<NewSortStrategyExport> result = new ArrayList<>();
         for (Article article : articleList) {
@@ -427,6 +453,49 @@ public class DataDashboardService {
                     }
                 }
             }
+            ProducePlan sourceProducePlan = sourceTitlePlanMap.get(article.getTitle());
+            if (Objects.nonNull(sourceProducePlan)) {
+                obj.setSourceProducePlanName(sourceProducePlan.getName());
+            }
+            List<Article> hisArticles = hisArticleMap.getOrDefault(article.getTitle(), new ArrayList<>());
+            hisArticles = hisArticles.stream().filter(o -> o.getUpdateTime() < (article.getUpdateTime() - 3600 * 8)
+                            && (1 == o.getItemIndex() || 2 == o.getItemIndex())
+                            && !ScoreStrategy.hisContentLateFilter(o.getUpdateTime())).collect(Collectors.toList());
+            Integer readCount = 0;
+            Double readAvgCount = 0.0;
+            int firstCount = 0;
+            int fission0Count = 0;
+            for (Article hisArticle : hisArticles) {
+                readCount += hisArticle.getShowViewCount();
+                AccountAvgInfo accountAvgInfo = getAccountAvgInfo(accountAvgInfoIndexMap, hisArticle.getGhId(),
+                        hisArticle.getUpdateTime(), hisArticle.getItemIndex());
+                if (Objects.nonNull(accountAvgInfo)) {
+                    readAvgCount += accountAvgInfo.getReadAvg();
+                }
+                List<ArticleDetailInfo> hisADIList = hisArticleDetailInfoMap.get(hisArticle.getWxSn());
+                if (CollectionUtil.isNotEmpty(hisADIList)) {
+                    Date hisMinDate = hisADIList.stream().map(ArticleDetailInfo::getRecallDt).min(Date::compareTo).orElse(new Date());
+                    for (ArticleDetailInfo articleDetailInfo : hisADIList) {
+                        if (articleDetailInfo.getRecallDt().equals(hisMinDate)) {
+                            if (Objects.nonNull(articleDetailInfo.getFirstLevel())) {
+                                firstCount += articleDetailInfo.getFirstLevel();
+                            }
+                            if (Objects.nonNull(articleDetailInfo.getFission0())) {
+                                fission0Count += articleDetailInfo.getFission0();
+                            }
+                        }
+                    }
+                }
+            }
+            if (readAvgCount > 0) {
+                obj.setHisReadRate(readCount / readAvgCount);
+            }
+            if (readCount > 0) {
+                obj.setHisFirstReadRate(firstCount / (double) readCount);
+            }
+            if (firstCount > 0) {
+                obj.setHisFission0FirstRate(fission0Count / (double) firstCount);
+            }
         }
         result.sort(Comparator.comparing(NewSortStrategyExport::getDateStr).reversed()
                 .thenComparing(NewSortStrategyExport::getGhId).thenComparing(NewSortStrategyExport::getPosition));
@@ -445,6 +514,35 @@ public class DataDashboardService {
         return result;
     }
 
+    private Map<String, ProducePlan> getTitleSourceProducePlanMap(List<String> titleList) {
+        List<ProduceContentDTO> sourceProduceContentList = new ArrayList<>();
+        for (List<String> partitions : Lists.partition(titleList, 1000)) {
+            sourceProduceContentList.addAll(aigcBaseMapper.getSourceProduceContentByTitles(partitions));
+        }
+        Map<String, List<ProduceContentDTO>> sourceProduceContentMap = sourceProduceContentList.stream()
+                .collect(Collectors.groupingBy(ProduceContentDTO::getTitle));
+        Map<String, String> sourceTitlePlanIdMap = new HashMap<>();
+        List<String> sourceProducePlanIds = new ArrayList<>();
+        for (Map.Entry<String, List<ProduceContentDTO>> entry : sourceProduceContentMap.entrySet()) {
+            String title = entry.getKey();
+            List<ProduceContentDTO> contentList = entry.getValue();
+            contentList.sort(Comparator.comparing(ProduceContentDTO::getProduceTimestamp));
+            sourceTitlePlanIdMap.put(title, contentList.get(0).getProducePlanId());
+            sourceProducePlanIds.add(contentList.get(0).getProducePlanId());
+        }
+        List<ProducePlan> sourceProducePlanList = producePlanRepository.findByIdIn(sourceProducePlanIds);
+        Map<String, ProducePlan> sourceProducePlanMap = sourceProducePlanList.stream()
+                .collect(Collectors.toMap(ProducePlan::getId, o -> o));
+        Map<String, ProducePlan> sourceTitlePlanMap = new HashMap<>();
+        for (Map.Entry<String, String> entry : sourceTitlePlanIdMap.entrySet()) {
+            String title = entry.getKey();
+            String planId = entry.getValue();
+            ProducePlan plan = sourceProducePlanMap.get(planId);
+            sourceTitlePlanMap.put(title, plan);
+        }
+        return sourceTitlePlanMap;
+    }
+
 
     private static void doSendFeishuSheet(List<String> dateStrList, String sheetToken, String sheetId,
                                           int rowNum, List<List<Object>> rows, Integer startRowIndex,
@@ -515,6 +613,10 @@ public class DataDashboardService {
             ResponseEntity<String> response = restTemplate.exchange(String.format("https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/%s/values_prepend",
                             sheetToken),
                     HttpMethod.POST, postEntity, String.class);
+            JSONObject responseJSON = JSONObject.parseObject(response.getBody());
+            if (0 != responseJSON.getInteger("code")) {
+                log.error("doSendFeishuSheet write error :{}", responseJSON.getString("msg"));
+            }
             startRow += partition.size();
         }
 //        // 合并单元格

+ 23 - 11
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/RecommendService.java

@@ -2,7 +2,13 @@ package com.tzld.longarticle.recommend.server.service;
 
 import com.alibaba.fastjson.JSONObject;
 import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue;
+import com.tzld.longarticle.recommend.server.common.enums.RankStrategyEnum;
+import com.tzld.longarticle.recommend.server.mapper.aigc.AigcBaseMapper;
+import com.tzld.longarticle.recommend.server.mapper.crawler.ArticleUserGroupMapper;
 import com.tzld.longarticle.recommend.server.model.dto.Content;
+import com.tzld.longarticle.recommend.server.model.entity.crawler.AccountAvgInfo;
+import com.tzld.longarticle.recommend.server.model.entity.crawler.PublishContentSortLog;
+import com.tzld.longarticle.recommend.server.model.entity.crawler.PublishSortLog;
 import com.tzld.longarticle.recommend.server.model.param.RecommendParam;
 import com.tzld.longarticle.recommend.server.model.param.RecommendRequest;
 import com.tzld.longarticle.recommend.server.model.vo.ArticleSortResponseData;
@@ -12,10 +18,6 @@ import com.tzld.longarticle.recommend.server.model.vo.RecommendWithUserGroupResp
 import com.tzld.longarticle.recommend.server.repository.crawler.AccountAvgInfoRepository;
 import com.tzld.longarticle.recommend.server.repository.crawler.PublishContentSortLogRepository;
 import com.tzld.longarticle.recommend.server.repository.crawler.PublishSortLogRepository;
-import com.tzld.longarticle.recommend.server.model.entity.crawler.AccountAvgInfo;
-import com.tzld.longarticle.recommend.server.model.entity.crawler.PublishContentSortLog;
-import com.tzld.longarticle.recommend.server.model.entity.crawler.PublishSortLog;
-import com.tzld.longarticle.recommend.server.mapper.crawler.ArticleUserGroupMapper;
 import com.tzld.longarticle.recommend.server.service.rank.RankParam;
 import com.tzld.longarticle.recommend.server.service.rank.RankResult;
 import com.tzld.longarticle.recommend.server.service.rank.RankService;
@@ -63,6 +65,8 @@ public class RecommendService {
     AccountAvgInfoRepository accountAvgInfoRepository;
     @Autowired
     private ArticleUserGroupMapper articleUserGroupMapper;
+    @Autowired
+    private AigcBaseMapper aigcBaseMapper;
 
     @ApolloJsonValue("${accountStrategyConfig:{}}")
     private Map<String, String> accountStrategyConfigMap;
@@ -75,20 +79,30 @@ public class RecommendService {
         RecommendParam param = genRecommendParam(request, SceneConstants.DEFAULT);
         log.info("genRecommendParam {}", JSONUtils.toJson(param));
         // 获取账号排序设置
-        String strategyConfig = accountStrategyConfigMap.get(request.getAccountName());
-        if (StringUtils.hasText(strategyConfig) && !request.isParamStrategy()) {
-            param.setStrategy(strategyConfig);
-        }
+        setStrategy(request, param);
+
         RecallResult recallResult = recallService.recall(convertToRecallParam(param));
 
         RankResult rankResult = rankService.rank(convertToRankParam(param, recallResult));
-        //log.info("rankResult {}", JSONUtils.toJson(rankResult));
 
         saveSortLog(param, rankResult);
 
         return buildRecommendResponse(recallResult, rankResult, param.getPublishNum());
     }
 
+    private void setStrategy(RecommendRequest request, RecommendParam param) {
+        String strategyConfig = accountStrategyConfigMap.get(request.getAccountName());
+        if (StringUtils.hasText(strategyConfig) && !request.isParamStrategy()) {
+            param.setStrategy(strategyConfig);
+        }
+        if (DateUtils.getCurrentHour() >= 19) {
+            Integer pushType = aigcBaseMapper.getPublishPlanPushType(request.getPlanId());
+            if (Objects.equals(2, pushType)) {
+                param.setStrategy(RankStrategyEnum.late_Strategy.getStrategy());
+            }
+        }
+    }
+
     public RecommendWithUserGroupResponse recommend4FwhColdStart(RecommendRequest request) {
 
         RecommendParam param = genRecommendParam(request, FWH_COLD_START);
@@ -99,10 +113,8 @@ public class RecommendService {
             param.setStrategy(strategyConfig);
         }
         RecallResult recallResult = recallService.recall(convertToRecallParam(param));
-        //log.info("recallResult {}", JSONUtils.toJson(recallResult));
 
         RankResult rankResult = rankService.rank(convertToRankParam(param, recallResult));
-        //log.info("rankResult {}", JSONUtils.toJson(rankResult));
 
         saveSortLog(param, rankResult);
 

+ 18 - 2
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/XxlJobService.java

@@ -1,7 +1,10 @@
 package com.tzld.longarticle.recommend.server.service;
 
+import cn.hutool.core.collection.CollectionUtil;
+import com.alibaba.fastjson.JSONObject;
 import com.tzld.longarticle.recommend.server.mapper.aigc.AigcBaseMapper;
 import com.tzld.longarticle.recommend.server.model.dto.NotPublishPlan;
+import com.tzld.longarticle.recommend.server.model.entity.aigc.PublishAccount;
 import com.tzld.longarticle.recommend.server.util.DateUtils;
 import com.tzld.longarticle.recommend.server.util.feishu.FeishuMessageSender;
 import com.xxl.job.core.biz.model.ReturnT;
@@ -12,7 +15,9 @@ import org.springframework.stereotype.Service;
 import org.springframework.util.StringUtils;
 
 import java.time.LocalTime;
+import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
 
 @Service
 @Slf4j
@@ -23,9 +28,10 @@ public class XxlJobService {
 
     @XxlJob("checkPublishPlan")
     public ReturnT<String> checkPublishPlan(String param) {
-        List<NotPublishPlan> notPublishPlan = aigcBaseMapper.getNotPublishPlan();
+        Long todayStart = DateUtils.getTodayStart();
+        List<NotPublishPlan> notPublishPlan = aigcBaseMapper.getNotPublishPlan(todayStart);
         for (NotPublishPlan publishPlan : notPublishPlan) {
-            Long now = System.currentTimeMillis();
+            long now = System.currentTimeMillis();
             int nowHour = DateUtils.getHourByTimestamp(now / 1000);
             int nowMinute = DateUtils.getMinuteByTimestamp(now / 1000);
             if (!StringUtils.hasText(publishPlan.getPublishPushTime())) {
@@ -44,10 +50,20 @@ public class XxlJobService {
     }
 
     private void sendFeishuPublishPlanNotPushWarn(NotPublishPlan publishPlan) {
+        Long todayStart = DateUtils.getTodayStart();
+        List<PublishAccount> publishAccounts = aigcBaseMapper.getPublishAccounts(publishPlan.getPlanId(), todayStart);
+        List<String> accountNames = new ArrayList<>();
+        if (CollectionUtil.isNotEmpty(publishAccounts)) {
+            accountNames = publishAccounts.stream().map(PublishAccount::getName).collect(Collectors.toList());
+        }
         FeishuMessageSender.sendWebHookMessage("07026a9f-43f5-448b-ba40-a8d71bd6e634",
                 "发布计划超1H未发送完成\n"
                         + "发布计划ID: " + publishPlan.getPlanId() + "\n"
                         + "发布计划名称: " + publishPlan.getPlanName() + "\n"
+                        + "预计数量: " + publishPlan.getExpectCount() + "\n"
+                        + "实际数量: " + publishPlan.getPublishCount() + "\n"
+                        + "发送失败账号: " + JSONObject.toJSONString(accountNames) + "\n"
+                        + "发布计划失败原因: " + publishPlan.getErrorMsg() + "\n"
                         + "发布时间: " + publishPlan.getPublishPushTime() + "\n"
                         + "<at user_id=\"all\">所有人</at> ");
     }

+ 80 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/rank/strategy/LateRankStrategy.java

@@ -0,0 +1,80 @@
+package com.tzld.longarticle.recommend.server.service.rank.strategy;
+
+import com.tzld.longarticle.recommend.server.model.dto.Content;
+import com.tzld.longarticle.recommend.server.service.AccountContentPoolConfigService;
+import com.tzld.longarticle.recommend.server.service.rank.RankItem;
+import com.tzld.longarticle.recommend.server.service.rank.RankParam;
+import com.tzld.longarticle.recommend.server.service.rank.RankResult;
+import com.tzld.longarticle.recommend.server.service.rank.RankStrategy;
+import com.tzld.longarticle.recommend.server.service.score.ScoreParam;
+import com.tzld.longarticle.recommend.server.service.score.ScoreResult;
+import com.tzld.longarticle.recommend.server.service.score.ScoreService;
+import com.tzld.longarticle.recommend.server.service.score.strategy.*;
+import com.tzld.longarticle.recommend.server.util.CommonCollectionUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Service
+@Slf4j
+public class LateRankStrategy implements RankStrategy {
+
+    @Autowired
+    private ScoreService scoreService;
+    @Autowired
+    private AccountContentPoolConfigService accountContentPoolConfigService;
+
+    public RankResult rank(RankParam param) {
+        List<Content> result = new ArrayList<>();
+        String[] contentPools = accountContentPoolConfigService.getContentPools(param.getAccountName());
+        ScoreParam scoreParam = RankStrategy.convertToScoreParam(param);
+        scoreParam.setContents(scoreParam.getContents().stream().filter(
+                c -> contentPools[2].equals(c.getContentPoolType())).collect(Collectors.toList()));
+        ScoreResult scoreResult = scoreService.score(RankStrategy.convertToScoreParam(param));
+
+        Map<String, Map<String, Double>> scoreMap = scoreResult.getScoreMap();
+
+        List<RankItem> items = CommonCollectionUtils.toList(scoreParam.getContents(), c -> {
+            RankItem item = new RankItem();
+            item.setContent(c);
+            c.setScoreMap(scoreMap.get(c.getId()));
+            item.setScoreMap(scoreMap.get(c.getId()));
+            double score = 0.0;
+            if (contentPools[2].equals(item.getContent().getContentPoolType())) {
+                score = item.getScore(SimilarityStrategy.class.getSimpleName())
+                        + item.getScore(CategoryStrategy.class.getSimpleName())
+                        + item.getScore(AccountPreDistributeStrategy.class.getSimpleName())
+                        + item.getScore(PublishTimesStrategy.class.getSimpleName())
+                        + item.getScore(FlowCtlDecreaseStrategy.class.getSimpleName());
+            }
+            c.setScore(score);
+            item.setScore(score);
+            return item;
+        });
+
+        // 1 排序
+        Collections.sort(items, (o1, o2) -> -Double.compare(o1.getScore(), o2.getScore()));
+        // 2 相似去重
+        List<Content> contents = CommonCollectionUtils.toList(items, RankItem::getContent);
+
+        // 3 文章按照内容池分组
+        Map<String, List<Content>> contentMap = new HashMap<>();
+        for (Content c : contents) {
+            List<Content> data = contentMap.computeIfAbsent(c.getContentPoolType(), k -> new ArrayList<>());
+            data.add(c);
+        }
+
+        // 全部使用3-8内容池
+        List<Content> pool = contentMap.get(contentPools[2]);
+        if (CollectionUtils.isNotEmpty(pool)) {
+            result.addAll(pool.subList(0, Math.min(pool.size(), param.getSize())));
+        }
+
+        return new RankResult(result);
+    }
+
+}

+ 1 - 1
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/rank/strategy/RankV5Strategy.java

@@ -66,7 +66,7 @@ public class RankV5Strategy implements RankStrategy {
             return item;
         });
         // 相似度评分为0 报警返回
-               if (CollectionUtils.isNotEmpty(items)
+        if (CollectionUtils.isNotEmpty(items)
                 && items.get(0).getScoreMap().containsKey(SimilarityStrategy.class.getSimpleName())
                 && items.get(0).getScoreMap().get(SimilarityStrategy.class.getSimpleName()) == 0) {
             FeishuMessageSender.sendWebHookMessage("07026a9f-43f5-448b-ba40-a8d71bd6e634",

+ 4 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recall/RecallService.java

@@ -18,6 +18,7 @@ import com.tzld.longarticle.recommend.server.repository.crawler.ArticleDetailInf
 import com.tzld.longarticle.recommend.server.repository.crawler.ArticleRepository;
 import com.tzld.longarticle.recommend.server.service.AccountIndexAvgViewCountService;
 import com.tzld.longarticle.recommend.server.service.recall.strategy.DefaultRecallStrategy;
+import com.tzld.longarticle.recommend.server.service.score.ScoreStrategy;
 import com.tzld.longarticle.recommend.server.util.CommonCollectionUtils;
 import com.tzld.longarticle.recommend.server.util.DateUtils;
 import com.tzld.longarticle.recommend.server.util.JSONUtils;
@@ -276,6 +277,9 @@ public class RecallService implements ApplicationContextAware {
             }
             content.setHisPublishArticleList(new ArrayList<>());
             for (Article hisArticle : hisArticles) {
+                if (ScoreStrategy.hisContentLateFilter(hisArticle.getUpdateTime())) {
+                    continue;
+                }
                 ContentHisPublishArticle article = new ContentHisPublishArticle();
                 BeanUtils.copyProperties(hisArticle, article);
                 article.setViewCount(hisArticle.getShowViewCount());

+ 7 - 1
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/score/ScoreService.java

@@ -10,7 +10,6 @@ import com.tzld.longarticle.recommend.server.util.JSONUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationContextAware;
 import org.springframework.stereotype.Service;
@@ -95,6 +94,13 @@ public class ScoreService implements ApplicationContextAware {
         if (!similarityStopStrategies.contains(param.getStrategy())) {
             strategies.add(strategyMap.get(SimilarityStrategy.class.getSimpleName()));
         }
+        if (StringUtils.equals(param.getStrategy(), RankStrategyEnum.late_Strategy.getStrategy())) {
+            strategies.add(strategyMap.get(CategoryStrategy.class.getSimpleName()));
+            strategies.add(strategyMap.get(AccountPreDistributeStrategy.class.getSimpleName()));
+            strategies.add(strategyMap.get(PublishTimesStrategy.class.getSimpleName()));
+            strategies.add(strategyMap.get(FlowCtlDecreaseStrategy.class.getSimpleName()));
+            return strategies;
+        }
         strategies.add(strategyMap.get(ViewCountStrategy.class.getSimpleName()));
         if (StringUtils.equals(param.getStrategy(), RankStrategyEnum.ArticleRankV3.getStrategy())
                 || StringUtils.equals(param.getStrategy(), RankStrategyEnum.ArticleRankV4.getStrategy())

+ 8 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/score/ScoreStrategy.java

@@ -1,6 +1,8 @@
 package com.tzld.longarticle.recommend.server.service.score;
 
 
+import com.tzld.longarticle.recommend.server.util.DateUtils;
+
 import java.util.List;
 
 /**
@@ -8,4 +10,10 @@ import java.util.List;
  */
 public interface ScoreStrategy {
     List<Score> score(ScoreParam param);
+
+    public static boolean hisContentLateFilter(Long publishTime) {
+        // 过滤掉发布时间晚于19点数据
+        int publishHour = DateUtils.getHourByTimestamp(publishTime);
+        return publishHour >= 19;
+    }
 }

+ 5 - 1
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/score/strategy/ViewCountRateCorrelationStrategy.java

@@ -2,8 +2,8 @@ package com.tzld.longarticle.recommend.server.service.score.strategy;
 
 import com.tzld.longarticle.recommend.server.model.dto.Content;
 import com.tzld.longarticle.recommend.server.model.dto.ContentHisPublishArticle;
-import com.tzld.longarticle.recommend.server.repository.crawler.AccountAvgInfoRepository;
 import com.tzld.longarticle.recommend.server.model.entity.crawler.AccountAvgInfo;
+import com.tzld.longarticle.recommend.server.repository.crawler.AccountAvgInfoRepository;
 import com.tzld.longarticle.recommend.server.service.AccountContentPoolConfigService;
 import com.tzld.longarticle.recommend.server.service.AccountIndexAvgViewCountService;
 import com.tzld.longarticle.recommend.server.service.score.Score;
@@ -68,6 +68,10 @@ public class ViewCountRateCorrelationStrategy implements ScoreStrategy {
                 double avgViewCountSumSecond = 0D;
                 double maxAvgViewCount = 0D;
                 for (ContentHisPublishArticle hisItem : content.getHisPublishArticleList()) {
+                    // 过滤掉发布时间晚于19点数据
+                    if (ScoreStrategy.hisContentLateFilter(hisItem.getUpdateTime())) {
+                        continue;
+                    }
                     if (hisItem.isInnerAccount() && Objects.nonNull(hisItem.getViewCount())
                             && hisItem.getViewCount() > 0 && Objects.nonNull(hisItem.getAvgViewCount())
                             && hisItem.getAvgViewCount() > 0) {

+ 5 - 1
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/score/strategy/ViewCountRateStrategy.java

@@ -2,8 +2,8 @@ package com.tzld.longarticle.recommend.server.service.score.strategy;
 
 import com.tzld.longarticle.recommend.server.model.dto.Content;
 import com.tzld.longarticle.recommend.server.model.dto.ContentHisPublishArticle;
-import com.tzld.longarticle.recommend.server.repository.crawler.AccountAvgInfoRepository;
 import com.tzld.longarticle.recommend.server.model.entity.crawler.AccountAvgInfo;
+import com.tzld.longarticle.recommend.server.repository.crawler.AccountAvgInfoRepository;
 import com.tzld.longarticle.recommend.server.service.AccountContentPoolConfigService;
 import com.tzld.longarticle.recommend.server.service.AccountIndexAvgViewCountService;
 import com.tzld.longarticle.recommend.server.service.score.Score;
@@ -68,6 +68,10 @@ public class ViewCountRateStrategy implements ScoreStrategy {
                 double avgViewCountSumSecond = 0D;
                 double maxAvgViewCount = 0D;
                 for (ContentHisPublishArticle hisItem : content.getHisPublishArticleList()) {
+                    // 过滤掉发布时间晚于19点数据
+                    if (ScoreStrategy.hisContentLateFilter(hisItem.getUpdateTime())) {
+                        continue;
+                    }
                     if (hisItem.isInnerAccount() && Objects.nonNull(hisItem.getViewCount())
                             && hisItem.getViewCount() > 0 && Objects.nonNull(hisItem.getAvgViewCount())
                             && hisItem.getAvgViewCount() > 0) {

+ 30 - 2
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/strategy/reply/impl/BuckStrategyV1.java

@@ -3,9 +3,9 @@ package com.tzld.longarticle.recommend.server.service.strategy.reply.impl;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.tzld.longarticle.recommend.server.common.enums.cgi.ReplyStrategyServiceEnum;
-import com.tzld.longarticle.recommend.server.model.cgi.*;
 import com.tzld.longarticle.recommend.server.mapper.crawler.AlgGhAutoreplyVideoRankDataMapper;
 import com.tzld.longarticle.recommend.server.mapper.crawler.CgiReplyBucketDataMapper;
+import com.tzld.longarticle.recommend.server.model.cgi.*;
 import com.tzld.longarticle.recommend.server.repository.model.AlgGhAutoreplyVideoRankData;
 import com.tzld.longarticle.recommend.server.repository.model.AlgGhAutoreplyVideoRankDataExample;
 import com.tzld.longarticle.recommend.server.repository.model.CgiReplyBucketData;
@@ -38,6 +38,9 @@ public class BuckStrategyV1 implements ReplyStrategyService {
      */
     private static final String bucketStrategyConfig = "{\"stg0909-base\":[5,6],\"stg0909-explore1\":[7],\"stg0909-explore2\":[8,9]}";
 
+    @Value("${bucketStrategyConfig:{}}")
+    private String bucketStrategyConfigV2;
+
     /**
      * 自动回复使用小程序Id
      */
@@ -58,7 +61,7 @@ public class BuckStrategyV1 implements ReplyStrategyService {
     @Override
     public ReplyBucketData getResult(BucketDataParam bucketDataParam) {
         // 0 获取策略key
-        JSONObject bucketStrategyConfigJsonObject = JSON.parseObject(bucketStrategyConfig);
+        JSONObject bucketStrategyConfigJsonObject = getStrategyConfig(bucketDataParam.getGhId());
         Set<String> keyedSet = bucketStrategyConfigJsonObject.keySet();
         // 1 处理文章--算法引擎--排序文章数据
 //        getWenzhangData();
@@ -73,11 +76,32 @@ public class BuckStrategyV1 implements ReplyStrategyService {
         return getReplyBucketData(bucketStrategyConfigJsonObject, keyedSet, bucketDataParam.getGhId());
     }
 
+    private JSONObject getStrategyConfig(String ghId) {
+        JSONObject allStrategyConfigs = JSON.parseObject(bucketStrategyConfigV2);
+        JSONObject currentGhIdStrategyConfig = null;
+        if (allStrategyConfigs.containsKey(ghId)) {
+            currentGhIdStrategyConfig = allStrategyConfigs.getJSONObject(ghId);
+        } else if (allStrategyConfigs.containsKey("default")) {
+            currentGhIdStrategyConfig = allStrategyConfigs.getJSONObject("default");
+        } else {
+            log.error("invalid strategy config: default key does not exist");
+            throw new RuntimeException("Default strategy config does not exist");
+        }
+        // check param
+        if (!currentGhIdStrategyConfig.containsKey("base")) {
+            throw new RuntimeException("Strategy config does not have manual base");
+        }
+        return currentGhIdStrategyConfig;
+    }
+
     private ReplyBucketData getReplyBucketData(JSONObject bucketStrategyConfigJsonObject, Set<String> keyedSet, String ghId) {
         // 策略小程序数据
         ReplyBucketData replyBucketData = new ReplyBucketData();
         List<GroupData> groupDataList = new ArrayList<>();
         for (String key : keyedSet) {
+            if ("base".equals(key)) {
+                continue;
+            }
             CgiReplyBucketDataExample cgiReplyBucketDataExample = new CgiReplyBucketDataExample();
             cgiReplyBucketDataExample.createCriteria().andIsDeleteEqualTo(0).andStrategyEqualTo(key).andGhIdEqualTo(ghId);
             cgiReplyBucketDataExample.setOrderByClause("sort");
@@ -112,6 +136,10 @@ public class BuckStrategyV1 implements ReplyStrategyService {
         }
         // 获取人工实验数据
         List<GroupData> groupDataBaseList = httpClientService.sendPenGongBaseRequest(ghId);
+        int baseBucketNum = bucketStrategyConfigJsonObject.getJSONArray("base").size();
+        if (groupDataBaseList.size() > baseBucketNum) {
+            groupDataBaseList = groupDataBaseList.subList(0, baseBucketNum);
+        }
         if (!CollectionUtils.isEmpty(groupDataBaseList)) {
             GroupData groupData = groupDataBaseList.get(0);
             List<MsgData> msgDataList = groupData.getMsgDataList();

+ 9 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/util/DateUtils.java

@@ -206,4 +206,13 @@ public final class DateUtils {
         System.out.println(new SimpleDateFormat("HH").format(calendar.getTime()));
 
     }
+
+    public static Long getTodayStart() {
+        Calendar calendar = Calendar.getInstance();
+        calendar.set(Calendar.HOUR_OF_DAY, 0);
+        calendar.set(Calendar.MINUTE, 0);
+        calendar.set(Calendar.SECOND, 0);
+        calendar.set(Calendar.MILLISECOND, 0);
+        return calendar.getTime().getTime();
+    }
 }

+ 21 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/web/XxlJobController.java

@@ -0,0 +1,21 @@
+package com.tzld.longarticle.recommend.server.web;
+
+import com.tzld.longarticle.recommend.server.service.XxlJobService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/xxlJob")
+@Slf4j
+public class XxlJobController {
+    @Autowired
+    private XxlJobService service;
+
+    @GetMapping("/checkPublishPlan")
+    public void checkPublishPlan() {
+        service.checkPublishPlan(null);
+    }
+}

+ 38 - 5
long-article-recommend-service/src/main/resources/mapper/aigc/AigcBaseMapper.xml

@@ -68,15 +68,48 @@
         SELECT
             plan.id as planId,
             plan.NAME as planName,
-            setting.publish_push_time
-        FROM
-            publish_plan plan
-                JOIN publish_plan_stat stat ON plan.id = stat.plan_id
-                JOIN publish_plan_setting setting ON plan.id = setting.plan_id
+            plan.error_msg as errorMsg,
+            stat.today_expect_publish_count as expectCount,
+            stat.today_publish_count as publishCount,
+            setting.publish_push_time as publishPushTime
+        FROM publish_plan plan
+        JOIN publish_plan_stat stat ON plan.id = stat.plan_id
+        JOIN publish_plan_setting setting ON plan.id = setting.plan_id
         WHERE
             stat.today_expect_publish_count > stat.today_publish_count
           AND plan.plan_status = 1
           AND setting.push_type = 2
+          and plan.create_timestamp &lt; #{todayStart}
+    </select>
+
+    <select id="getPublishPlanPushType" resultType="java.lang.Integer">
+        select push_type from publish_plan_setting where plan_id = #{planId}
+    </select>
+
+    <select id="getPublishAccounts"
+            resultType="com.tzld.longarticle.recommend.server.model.entity.aigc.PublishAccount">
+        SELECT account.*
+        FROM publish_plan_account planAccount
+        join publish_account account on planAccount.account_id = account.id
+        left join publish_content content
+            on content.publish_account_id = planAccount.account_id
+           and content.plan_id = planAccount.plan_id
+           and content.publish_timestamp > #{todayStart}
+        WHERE planAccount.plan_id = #{planId} and content.id is null and planAccount.publish_open_flag = 1
+    </select>
+    <select id="getSourceProduceContentByTitles"
+            resultType="com.tzld.longarticle.recommend.server.model.dto.ProduceContentDTO">
+        select record.plan_exe_id as contentId,
+               output.output as title,
+               record.produce_timestamp as produceTimestamp,
+               record.plan_id as producePlanId
+        from produce_plan_exe_record record
+        join produce_plan_module_output output on record.plan_exe_id = output.plan_exe_id and output.produce_module_type = 3
+        join publish_content pc on pc.source_id = record.plan_exe_id and pc.status = 2
+        where output.output in
+        <foreach collection="titleList" item="item" open="(" close=")" separator=",">
+            #{item}
+        </foreach>
     </select>
 
 

+ 8 - 6
long-article-recommend-service/src/main/resources/mapper/longArticle/LongArticleBaseMapper.xml

@@ -13,10 +13,11 @@
         first_level, fission0, fission1, fission2, second_first_level, second_fission0, second_fission1,
         second_fission2, third_first_level, third_fission0, third_fission1, third_fission2,
         read_rate, read_fans_rate, first_read_rate, fission0_first_rate, fission1_fission0_rate,
-        fission0_read_avg_rate, position, gh_id, title, link, wx_sn, fission0_read_avg_100_rate,
-        fission0_read_avg_500_rate, fission0_read_avg_1000_rate, crawler_plan_name, crawler_plan_tag,
-        produce_plan_name, produce_plan_tag, publish_plan_name, publish_mini_program_insert_strategy,
-        publish_mini_program_insert_use_type, publish_mini_program_num)
+        fission0_read_avg_rate, his_read_rate, his_first_read_rate, his_fission0_first_rate, position, gh_id, title,
+        link, wx_sn, fission0_read_avg_100_rate, fission0_read_avg_500_rate, fission0_read_avg_1000_rate,
+        crawler_plan_name, crawler_plan_tag, produce_plan_name, produce_plan_tag, publish_plan_name,
+        publish_mini_program_insert_strategy, publish_mini_program_insert_use_type, publish_mini_program_num,
+        source_produce_plan_name)
         VALUES
         <foreach collection="list" item="item" separator=",">
             (#{item.dateStr}, #{item.publishTime}, #{item.accountMode}, #{item.accountSource}, #{item.accountType},
@@ -26,12 +27,13 @@
             #{item.secondFission0}, #{item.secondFission1}, #{item.secondFission2}, #{item.thirdFirstLevel},
             #{item.thirdFission0}, #{item.thirdFission1}, #{item.thirdFission2}, #{item.readRate},
             #{item.readFansRate}, #{item.firstReadRate}, #{item.fission0FirstRate}, #{item.fission1Fission0Rate},
-            #{item.fission0ReadAvgRate}, #{item.position}, #{item.ghId}, #{item.title}, #{item.link},
+            #{item.fission0ReadAvgRate}, #{item.hisReadRate}, #{item.hisFirstReadRate}, #{item.hisFission0FirstRate},
+            #{item.position}, #{item.ghId}, #{item.title}, #{item.link},
             #{item.wxSn}, #{item.fission0ReadAvg100Rate}, #{item.fission0ReadAvg500Rate},
             #{item.fission0ReadAvg1000Rate}, #{item.crawlerPlanName}, #{item.crawlerPlanTag},
             #{item.producePlanName}, #{item.producePlanTag}, #{item.publishPlanName},
             #{item.publishMiniProgramInsertStrategy}, #{item.publishMiniProgramInsertUseType},
-            #{item.publishMiniProgramNum})
+            #{item.publishMiniProgramNum}, #{item.sourceProducePlanName})
         </foreach>
     </insert>
 

+ 131 - 14
long-article-recommend-service/src/test/java/com/tzld/longarticle/recommend/server/RecommendTest.java

@@ -16,6 +16,7 @@ import com.tzld.longarticle.recommend.server.repository.crawler.PublishSortLogRe
 import com.tzld.longarticle.recommend.server.service.RecommendService;
 import com.tzld.longarticle.recommend.server.service.recall.RecallService;
 import com.tzld.longarticle.recommend.server.util.DateUtils;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.poi.ss.usermodel.Cell;
 import org.apache.poi.ss.usermodel.Row;
 import org.apache.poi.ss.usermodel.Sheet;
@@ -25,12 +26,16 @@ import org.junit.jupiter.api.Test;
 import org.springframework.boot.test.context.SpringBootTest;
 
 import javax.annotation.Resource;
+import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
 import java.util.*;
 import java.util.stream.Collectors;
 
 @SpringBootTest(classes = Application.class)
+@Slf4j
 public class RecommendTest {
 
     @Resource
@@ -257,22 +262,12 @@ public class RecommendTest {
 
     @Test
     public void exportScoreData() {
-        List<String> ghIds = Lists.newArrayList("gh_e24da99dc899",
-                "gh_183d80deffb8",
-                "gh_be8c29139989",
-                "gh_c69776baf2cd",
-                "gh_b15de7c99912",
-                "gh_1d887d61088c",
-                "gh_3ed305b5817f",
-                "gh_3e91f0624545",
-                "gh_30816d8adb52",
-                "gh_970460d9ccec",
-                "gh_749271f1ccd5"
-        );
-        List<PublishSortLog> sortLogList = publishSortLogRepository.findByGhIdInAndDateStrGreaterThanEqual(ghIds, "20240907");
+        List<String> strategies = Arrays.asList("ArticleRankV11", "ArticleRankV12");
+        List<PublishSortLog> sortLogList = publishSortLogRepository.findByStrategyInAndDateStrGreaterThanEqual(strategies, "20240928");
         sortLogList = sortLogList.stream().filter(o -> o.getIndex() == 1).collect(Collectors.toList());
         sortLogList.sort(Comparator.comparing(PublishSortLog::getGhId).thenComparing(PublishSortLog::getDateStr));
-        List<Article> articleList = articleRepository.getByGhIdInAndUpdateTimeGreaterThanAndTypeEquals(ghIds, 1725638400L, "9");
+        List<String> ghIds = sortLogList.stream().map(PublishSortLog::getGhId).distinct().collect(Collectors.toList());
+        List<Article> articleList = articleRepository.getByGhIdInAndUpdateTimeGreaterThanAndTypeEquals(ghIds, 1727452800L, "9");
         articleList = articleList.stream().filter(o -> o.getItemIndex() == 1).collect(Collectors.toList());
         Map<String, Map<String, Article>> articleMap = articleList.stream().collect(Collectors.groupingBy(Article::getGhId, Collectors.toMap(
                 o -> DateUtils.timestampToYMDStr(o.getUpdateTime(),"yyyyMMdd"), o -> o,
@@ -406,4 +401,126 @@ public class RecommendTest {
         }
     }
 
+    @Test
+    public void exportFromAliyunLog() {
+
+        String folderPath = "/Users/wangyunpeng/Downloads/longarticle-recommend-server-test_info-log_20241014_150245.json";
+
+        File file = new File(folderPath);
+
+        Workbook workbook = new XSSFWorkbook();
+        Sheet sheet = workbook.createSheet("ExampleSheet");
+        int rowNum = 0;
+        // 创建标题行
+        Row titleRow = sheet.createRow(rowNum);
+        Cell titleCell = titleRow.createCell(0);
+        titleCell.setCellValue("日期");
+        titleCell = titleRow.createCell(1);
+        titleCell.setCellValue("账号名称");
+        titleCell = titleRow.createCell(2);
+        titleCell.setCellValue("id");
+        titleCell = titleRow.createCell(3);
+        titleCell.setCellValue("标题");
+        titleCell = titleRow.createCell(4);
+        titleCell.setCellValue("策略");
+        titleCell = titleRow.createCell(5);
+        titleCell.setCellValue("得分");
+        titleCell = titleRow.createCell(6);
+        titleCell.setCellValue("HisFissionFansRateRateStrategy");
+        titleCell = titleRow.createCell(7);
+        titleCell.setCellValue("HisFissionAvgReadRateRateStrategy");
+        titleCell = titleRow.createCell(8);
+        titleCell.setCellValue("PublishTimesStrategy");
+        titleCell = titleRow.createCell(9);
+        titleCell.setCellValue("ViewCountRateCorrelationStrategy");
+        titleCell = titleRow.createCell(10);
+        titleCell.setCellValue("HisFissionAvgReadSumRateStrategy");
+        titleCell = titleRow.createCell(11);
+        titleCell.setCellValue("HisFissionAvgReadRateCorrelationRateStrategy");
+        titleCell = titleRow.createCell(12);
+        titleCell.setCellValue("HisFissionFansSumRateStrategy");
+        titleCell = titleRow.createCell(13);
+        titleCell.setCellValue("SimilarityStrategy");
+        titleCell = titleRow.createCell(14);
+        titleCell.setCellValue("ViewCountStrategy");
+        titleCell = titleRow.createCell(15);
+        titleCell.setCellValue("ViewCountRateStrategy");
+        titleCell = titleRow.createCell(16);
+        titleCell.setCellValue("HisFissionDeWeightAvgReadSumRateStrategy");
+        try {
+            String content = new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8);
+            JSONArray jsonArray = JSONArray.parseArray(content);
+            for (Object o : jsonArray) {
+                JSONObject jsonObject = (JSONObject) o;
+                Long time = jsonObject.getLong("__time__");
+                String message = jsonObject.getString("message");
+                int index = message.indexOf("[");
+                String info = message.substring(0, index);
+                String strategy = info.substring(0, info.indexOf(" "));
+                String accountName = info.substring(info.indexOf(" ")).replace("账号名称 ", "")
+                        .replace(" 头条评分结果", "");
+                String json = message.substring(index);
+                JSONArray scoreArray = JSONArray.parseArray(json);
+                for (Object scoreJSON : scoreArray) {
+                    JSONObject scoreObject = (JSONObject) scoreJSON;
+                    String id = scoreObject.getString("id");
+                    String title = scoreObject.getString("title");
+                    String score = scoreObject.getString("score");
+                    String scoreMapStr = scoreObject.getString("scoreMap");
+                    rowNum++;
+                    Row row = sheet.createRow(rowNum);
+                    Cell cell = row.createCell(0);
+                    cell.setCellValue(DateUtils.timestampToYMDStr(time, "yyyyMMdd"));
+                    cell = row.createCell(1);
+                    cell.setCellValue(accountName);
+                    cell = row.createCell(2);
+                    cell.setCellValue(id);
+                    cell = row.createCell(3);
+                    cell.setCellValue(title);
+                    cell = row.createCell(4);
+                    cell.setCellValue(strategy);
+                    cell = row.createCell(5);
+                    cell.setCellValue(score);
+                    cell = row.createCell(6);
+                    JSONObject scoreMap = JSONObject.parseObject(scoreMapStr);
+                    cell.setCellValue(String.format("%.3f", Optional.of(scoreMap.getDoubleValue("HisFissionFansRateRateStrategy")).orElse(0.0)));
+                    cell = row.createCell(7);
+                    cell.setCellValue(String.format("%.3f", Optional.of(scoreMap.getDoubleValue("HisFissionAvgReadRateRateStrategy")).orElse(0.0)));
+                    cell = row.createCell(8);
+                    cell.setCellValue(String.format("%.3f", Optional.of(scoreMap.getDoubleValue("PublishTimesStrategy")).orElse(0.0)));
+                    cell = row.createCell(9);
+                    cell.setCellValue(String.format("%.3f", Optional.of(scoreMap.getDoubleValue("ViewCountRateCorrelationStrategy")).orElse(0.0)));
+                    cell = row.createCell(10);
+                    cell.setCellValue(String.format("%.3f", Optional.of(scoreMap.getDoubleValue("HisFissionAvgReadSumRateStrategy")).orElse(0.0)));
+                    cell = row.createCell(11);
+                    cell.setCellValue(String.format("%.3f", Optional.of(scoreMap.getDoubleValue("HisFissionAvgReadRateCorrelationRateStrategy")).orElse(0.0)));
+                    cell = row.createCell(12);
+                    cell.setCellValue(String.format("%.3f", Optional.of(scoreMap.getDoubleValue("HisFissionFansSumRateStrategy")).orElse(0.0)));
+                    cell = row.createCell(13);
+                    cell.setCellValue(String.format("%.3f", Optional.of(scoreMap.getDoubleValue("SimilarityStrategy")).orElse(0.0)));
+                    cell = row.createCell(14);
+                    cell.setCellValue(String.format("%.3f", Optional.of(scoreMap.getDoubleValue("ViewCountStrategy")).orElse(0.0)));
+                    cell = row.createCell(15);
+                    cell.setCellValue(String.format("%.3f", Optional.of(scoreMap.getDoubleValue("ViewCountRateStrategy")).orElse(0.0)));
+                    cell = row.createCell(16);
+                    cell.setCellValue(String.format("%.3f", Optional.of(scoreMap.getDoubleValue("HisFissionDeWeightAvgReadSumRateStrategy")).orElse(0.0)));
+                }
+            }
+
+            try (FileOutputStream outputStream = new FileOutputStream("/Users/wangyunpeng/Downloads/example.xlsx")) {
+                workbook.write(outputStream);
+            } catch (IOException e) {
+                e.printStackTrace();
+            } finally {
+                try {
+                    workbook.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        } catch (Exception e) {
+            log.error("readFileError fileName:{}", file.getName(), e);
+        }
+    }
+
 }