Quellcode durchsuchen

Merge branch 'master' into wyp/1031-articlePublishTimestamp

# Conflicts:
#	long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/entity/crawler/Article.java
#	long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/DataDashboardService.java
wangyunpeng vor 8 Monaten
Ursprung
Commit
390f417d44
90 geänderte Dateien mit 3967 neuen und 96 gelöschten Zeilen
  1. 36 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/common/enums/GhTypeEnum.java
  2. 28 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/common/enums/StatusEnum.java
  3. 43 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/common/enums/aigc/PublishContentTypeEnum.java
  4. 1 1
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/common/enums/aigc/PushTypeEnum.java
  5. 31 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/common/enums/recommend/ArticleCategoryStatusEnum.java
  6. 30 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/common/enums/recommend/ArticlePoolPromotionSourceStatusEnum.java
  7. 19 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/config/db/GrowthDBConfig.java
  8. 38 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/config/mybatis/GrowthMybatisConfig.java
  9. 11 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/mapper/aigc/AigcBaseMapper.java
  10. 6 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/mapper/crawler/CrawlerBaseMapper.java
  11. 1 1
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/mapper/growth/AlgGhAutoreplyVideoRankDataMapper.java
  12. 1 1
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/mapper/growth/CgiReplyBucketDataMapper.java
  13. 33 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/mapper/growth/GhDetailMapper.java
  14. 35 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/mapper/growth/NewPushMessageCallbackMapper.java
  15. 4 1
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/mapper/growth/ReplyStaffMapper.java
  16. 10 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/mapper/longArticle/LongArticleBaseMapper.java
  17. 12 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/dto/CrawlerContent.java
  18. 39 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/dto/kimi/KimiOfficialApiResponse.java
  19. 11 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/dto/kimi/KimiResult.java
  20. 82 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/entity/aigc/PublishContentOutput.java
  21. 10 1
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/entity/crawler/Article.java
  22. 48 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/entity/longArticle/AccountCategory.java
  23. 56 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/entity/longArticle/ArticleCategory.java
  24. 34 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/entity/longArticle/ArticleCrawlerPlan.java
  25. 43 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/entity/longArticle/ArticlePoolPromotionSource.java
  26. 68 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/entity/longArticle/DatastatScore.java
  27. 10 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/param/ArticleFindSourceParam.java
  28. 1 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/vo/FirstContentScoreExport.java
  29. 27 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/vo/GhDetailVo.java
  30. 16 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/vo/GhTypeVo.java
  31. 10 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/vo/ProduceContentCrawlerVO.java
  32. 12 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/vo/ReportUvVo.java
  33. 18 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/vo/RootPublishContentVO.java
  34. 13 3
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/mq/MessageCallbackCustomer.java
  35. 62 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/remote/CrawlerContentByPlanService.java
  36. 89 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/remote/KimiApiService.java
  37. 2 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/aigc/PublishAccountRepository.java
  38. 13 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/aigc/PublishContentOutputRepository.java
  39. 4 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/crawler/ArticleRepository.java
  40. 1 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/crawler/PublishSortLogRepository.java
  41. 12 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/longArticle/AccountCategoryRepository.java
  42. 19 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/longArticle/ArticleCategoryRepository.java
  43. 14 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/longArticle/ArticleCrawlerPlanRepository.java
  44. 19 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/longArticle/ArticlePoolPromotionSourceRepository.java
  45. 12 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/longArticle/DatastatScoreRepository.java
  46. 28 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/model/GhDetail.java
  47. 791 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/model/GhDetailExample.java
  48. 80 4
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/XxlJobService.java
  49. 17 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/exterior/GhDetailService.java
  50. 4 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/exterior/ThirdPartyService.java
  51. 139 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/exterior/impl/GhDetailServiceImpl.java
  52. 50 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/exterior/impl/ThirdPartyServiceImpl.java
  53. 1 1
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/exterior/impl/WeComServiceImpl.java
  54. 476 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/ArticleService.java
  55. 84 25
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/DataDashboardService.java
  56. 13 4
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/RecommendService.java
  57. 1 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/filter/FilterService.java
  58. 52 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/filter/strategy/ArticlePromotionStrategy.java
  59. 6 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/rank/strategy/InfiniteRankStrategy.java
  60. 6 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/rank/strategy/LateRankStrategy.java
  61. 8 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/rank/strategy/RankV10Strategy.java
  62. 4 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/rank/strategy/RankV11Strategy.java
  63. 4 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/rank/strategy/RankV12Strategy.java
  64. 4 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/rank/strategy/RankV13Strategy.java
  65. 4 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/rank/strategy/RankV14Strategy.java
  66. 3 3
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/rank/strategy/RankV5Strategy.java
  67. 11 4
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/rank/strategy/RankV8Strategy.java
  68. 43 17
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/recall/RecallService.java
  69. 16 16
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/score/strategy/CategoryStrategy.java
  70. 2 2
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/strategy/reply/impl/BuckStrategyV1.java
  71. 2 2
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/strategy/reply/impl/PushMessageStrategyV1.java
  72. 2 2
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/strategy/reply/impl/WeComPushMessageStrategyV1.java
  73. 29 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/util/DateUtils.java
  74. 1 1
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/util/TitleSimilarCheckUtil.java
  75. 108 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/util/page/Page.java
  76. 54 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/web/AccountDetailController.java
  77. 7 4
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/web/ThirdPartyController.java
  78. 21 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/web/XxlJobController.java
  79. 24 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/web/recommend/ArticleController.java
  80. 11 0
      long-article-recommend-service/src/main/resources/application-dev.yml
  81. 11 0
      long-article-recommend-service/src/main/resources/application-prod.yml
  82. 55 0
      long-article-recommend-service/src/main/resources/mapper/aigc/AigcBaseMapper.xml
  83. 19 0
      long-article-recommend-service/src/main/resources/mapper/crawler/CrawlerBaseMapper.xml
  84. 1 1
      long-article-recommend-service/src/main/resources/mapper/growth/AlgGhAutoreplyVideoRankDataMapper.xml
  85. 1 1
      long-article-recommend-service/src/main/resources/mapper/growth/CgiReplyBucketDataMapper.xml
  86. 276 0
      long-article-recommend-service/src/main/resources/mapper/growth/GhDetailMapper.xml
  87. 278 0
      long-article-recommend-service/src/main/resources/mapper/growth/NewPushMessageCallbackMapper.xml
  88. 1 1
      long-article-recommend-service/src/main/resources/mapper/growth/ReplyStaffMapper.xml
  89. 40 0
      long-article-recommend-service/src/main/resources/mapper/longArticle/LongArticleBaseMapper.xml
  90. 95 0
      long-article-recommend-service/src/test/java/com/tzld/longarticle/recommend/server/XxlJobTest.java

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

@@ -0,0 +1,36 @@
+package com.tzld.longarticle.recommend.server.common.enums;
+
+import java.util.Objects;
+
+public enum GhTypeEnum {
+
+    GH(1, "内部公众号"),
+    THIRD_PARTY_GH(2, "外部公众号"),
+    WE_COM(3, "企业微信");
+
+    GhTypeEnum(Integer type, String name) {
+        this.type = type;
+        this.name = name;
+    }
+
+    public final Integer type;
+
+    public final String name;
+
+
+    public static String getTypeName(Integer type) {
+        if (type == null) {
+            return null;
+        }
+        for (GhTypeEnum ghTypeEnum : GhTypeEnum.values()) {
+            if (Objects.equals(ghTypeEnum.type, type)) {
+                return ghTypeEnum.name;
+            }
+        }
+        return null;
+    }
+
+
+
+
+}

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

@@ -0,0 +1,28 @@
+package com.tzld.longarticle.recommend.server.common.enums;
+
+import lombok.Getter;
+
+@Getter
+public enum StatusEnum {
+
+    ZERO(0, "0"),
+    ONE(1, "1"),
+    ;
+
+    private int code;
+    private String msg;
+
+    StatusEnum(int code, String msg) {
+        this.code = code;
+        this.msg = msg;
+    }
+
+    public static StatusEnum getByCode(int code) {
+        for (StatusEnum statusEnum : StatusEnum.values()) {
+            if (statusEnum.getCode() == code) {
+                return statusEnum;
+            }
+        }
+        return null;
+    }
+}

+ 43 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/common/enums/aigc/PublishContentTypeEnum.java

@@ -0,0 +1,43 @@
+package com.tzld.longarticle.recommend.server.common.enums.aigc;
+
+import lombok.Getter;
+
+import java.util.Objects;
+
+@Getter
+public enum PublishContentTypeEnum {
+    cover(1, "封面"),
+    image(2, "图片"),
+    title(3, "标题"),
+    bodyText(4, "正文"),
+    animation(5, "动效"),
+    video(6, "视频"),
+    textLetter(7, "文本私信"),
+    imageLetter(8, "图片私信"),
+    noteLetter(9, "笔记私信"),
+    textComment(10, "文本评论"),
+    imageComment(11, "图片评论"),
+    commentId(12, "动作对象为评论,被评论/被删除的/被点赞的评论ID"),
+    contentStageId(13, "动作对象为内容,被评论的/被隐藏的/被删除的/被修改的内容的三方平台ID"),
+    receiverUserPlatformId(14, "动作对象为用户,动作接收人三方平台用户ID"),
+    actionAccountId(15, "动作账号ID"),
+    other(999, "其他"),
+    ;
+
+    private final Integer val;
+    private final String description;
+
+    PublishContentTypeEnum(Integer val, String description) {
+        this.val = val;
+        this.description = description;
+    }
+
+    public static PublishContentTypeEnum from(Integer val) {
+        for (PublishContentTypeEnum statusEnum : PublishContentTypeEnum.values()) {
+            if (Objects.equals(statusEnum.val, val)) {
+                return statusEnum;
+            }
+        }
+        return other;
+    }
+}

+ 1 - 1
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/common/enums/recommend/PushTypeEnum.java → long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/common/enums/aigc/PushTypeEnum.java

@@ -1,4 +1,4 @@
-package com.tzld.longarticle.recommend.server.common.enums.recommend;
+package com.tzld.longarticle.recommend.server.common.enums.aigc;
 
 import lombok.Getter;
 

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

@@ -0,0 +1,31 @@
+package com.tzld.longarticle.recommend.server.common.enums.recommend;
+
+import lombok.Getter;
+
+@Getter
+public enum ArticleCategoryStatusEnum {
+
+    WAITING(0, "待分类"),
+    PROCESS(1, "执行中"),
+    SUCCESS(2, "成功"),
+    FAIL(3, "失败"),
+    ;
+
+    //状态(0-待分类 1-执行中 2-成功 3-失败)
+    private int code;
+    private String msg;
+
+    ArticleCategoryStatusEnum(int code, String msg) {
+        this.code = code;
+        this.msg = msg;
+    }
+
+    public static ArticleCategoryStatusEnum getByCode(int code) {
+        for (ArticleCategoryStatusEnum statusEnum : ArticleCategoryStatusEnum.values()) {
+            if (statusEnum.getCode() == code) {
+                return statusEnum;
+            }
+        }
+        return null;
+    }
+}

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

@@ -0,0 +1,30 @@
+package com.tzld.longarticle.recommend.server.common.enums.recommend;
+
+import lombok.Getter;
+
+@Getter
+public enum ArticlePoolPromotionSourceStatusEnum {
+
+    WAITING(0, "waiting"),
+    FINISH(1, "finish");
+
+    //0-待溯源处理 1-已完成
+
+    private Integer code;
+    private String desc;
+
+    ArticlePoolPromotionSourceStatusEnum(Integer code, String desc) {
+        this.code = code;
+        this.desc = desc;
+    }
+
+    public static ArticlePoolPromotionSourceStatusEnum getByCode(Integer code) {
+        for (ArticlePoolPromotionSourceStatusEnum status : ArticlePoolPromotionSourceStatusEnum.values()) {
+            if (status.getCode().equals(code)) {
+                return status;
+            }
+        }
+        return null;
+    }
+
+}

+ 19 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/config/db/GrowthDBConfig.java

@@ -0,0 +1,19 @@
+package com.tzld.longarticle.recommend.server.config.db;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.jdbc.DataSourceBuilder;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.sql.DataSource;
+
+@Configuration
+public class GrowthDBConfig {
+
+    @Bean(name = "growthDataSource")
+    @ConfigurationProperties(prefix = "spring.datasource.growth")
+    public DataSource growthDataSource() {
+        return DataSourceBuilder.create().build();
+    }
+}
+

+ 38 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/config/mybatis/GrowthMybatisConfig.java

@@ -0,0 +1,38 @@
+package com.tzld.longarticle.recommend.server.config.mybatis;
+
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.mybatis.spring.SqlSessionFactoryBean;
+import org.mybatis.spring.SqlSessionTemplate;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+
+import javax.sql.DataSource;
+
+@Configuration
+@MapperScan(basePackages = "com.tzld.longarticle.recommend.server.mapper.growth",
+        sqlSessionFactoryRef = "growthSqlSessionFactory")
+public class GrowthMybatisConfig {
+
+    @Primary
+    @Bean(name = "growthSqlSessionFactory")
+    public SqlSessionFactory crawlerSqlSessionFactory(@Qualifier("growthDataSource") DataSource dataSource) throws Exception {
+        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
+        sessionFactory.setDataSource(dataSource);
+        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
+                .getResources("classpath*:mapper/**/*.xml"));
+        sessionFactory.setTypeAliasesPackage("com.tzld.longarticle.recommend.server");
+        sessionFactory.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
+        sessionFactory.getObject().getConfiguration().setUseGeneratedKeys(true);
+        return sessionFactory.getObject();
+    }
+
+    @Primary
+    @Bean(name = "growthSqlSessionTemplate")
+    public SqlSessionTemplate crawlerSqlSessionTemplate(@Qualifier("growthSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
+        return new SqlSessionTemplate(sqlSessionFactory);
+    }
+}

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

@@ -1,6 +1,7 @@
 package com.tzld.longarticle.recommend.server.mapper.aigc;
 
 import com.tzld.longarticle.recommend.server.model.dto.AccountTypeFansDTO;
+import com.tzld.longarticle.recommend.server.model.dto.CrawlerContent;
 import com.tzld.longarticle.recommend.server.model.dto.NotPublishPlan;
 import com.tzld.longarticle.recommend.server.model.dto.ProduceContentDTO;
 import com.tzld.longarticle.recommend.server.model.entity.aigc.*;
@@ -32,4 +33,14 @@ public interface AigcBaseMapper {
     List<AccountTypeFansDTO> getAccountTypeFans();
 
     List<PublishContent> getHisPublishByTitles(List<String> titleList);
+
+    List<PublishContent> getNearestPublishContent(String publishAccountId, Long publishTimestamp, Integer size);
+
+    CrawlerContent getCrawlerContentByChannelContentId(String channelContentId);
+
+    List<CrawlerContent> getCrawlerContentByChannelContentIdIn(List<String> channelContentIds);
+
+    List<ProduceContentDTO> getProduceContentByPlanId(String planId);
+
+    List<ProducePlanExeRecord> getAllByProducePlanId(List<String> producePlanIds);
 }

+ 6 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/mapper/crawler/CrawlerBaseMapper.java

@@ -2,6 +2,7 @@ package com.tzld.longarticle.recommend.server.mapper.crawler;
 
 import com.tzld.longarticle.recommend.server.model.entity.crawler.AccountAvgInfo;
 import com.tzld.longarticle.recommend.server.model.entity.crawler.AccountCorrelation;
+import com.tzld.longarticle.recommend.server.model.entity.crawler.Article;
 import com.tzld.longarticle.recommend.server.model.entity.crawler.LongArticlesRootSourceId;
 
 import java.util.List;
@@ -18,4 +19,9 @@ public interface CrawlerBaseMapper {
 
     void updateAccountAvgInfoStatus(String ghId, String date);
 
+    void updateArticleAigcId(String wxsn, String publishContentId, String channelContentId);
+
+    void updateArticleSourceRootId(String wxsn, String sourcePublishContentId, String rootPublishContentId, String rootProduceContentId);
+
+    List<Article> getWaitingFindArticle(Long timestamp);
 }

+ 1 - 1
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/mapper/crawler/AlgGhAutoreplyVideoRankDataMapper.java → long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/mapper/growth/AlgGhAutoreplyVideoRankDataMapper.java

@@ -1,4 +1,4 @@
-package com.tzld.longarticle.recommend.server.mapper.crawler;
+package com.tzld.longarticle.recommend.server.mapper.growth;
 
 import com.tzld.longarticle.recommend.server.repository.model.AlgGhAutoreplyVideoRankData;
 import com.tzld.longarticle.recommend.server.repository.model.AlgGhAutoreplyVideoRankDataExample;

+ 1 - 1
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/mapper/crawler/CgiReplyBucketDataMapper.java → long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/mapper/growth/CgiReplyBucketDataMapper.java

@@ -1,4 +1,4 @@
-package com.tzld.longarticle.recommend.server.mapper.crawler;
+package com.tzld.longarticle.recommend.server.mapper.growth;
 
 import com.tzld.longarticle.recommend.server.repository.model.CgiReplyBucketData;
 import com.tzld.longarticle.recommend.server.repository.model.CgiReplyBucketDataExample;

+ 33 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/mapper/growth/GhDetailMapper.java

@@ -0,0 +1,33 @@
+package com.tzld.longarticle.recommend.server.mapper.growth;
+
+import com.tzld.longarticle.recommend.server.repository.model.GhDetail;
+import com.tzld.longarticle.recommend.server.repository.model.GhDetailExample;
+import java.util.List;
+
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+@Mapper
+public interface GhDetailMapper {
+    long countByExample(GhDetailExample example);
+
+    int deleteByExample(GhDetailExample example);
+
+    int deleteByPrimaryKey(Long id);
+
+    int insert(GhDetail row);
+
+    int insertSelective(GhDetail row);
+
+    List<GhDetail> selectByExample(GhDetailExample example);
+
+    GhDetail selectByPrimaryKey(Long id);
+
+    int updateByExampleSelective(@Param("row") GhDetail row, @Param("example") GhDetailExample example);
+
+    int updateByExample(@Param("row") GhDetail row, @Param("example") GhDetailExample example);
+
+    int updateByPrimaryKeySelective(GhDetail row);
+
+    int updateByPrimaryKey(GhDetail row);
+}

+ 35 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/mapper/growth/NewPushMessageCallbackMapper.java

@@ -0,0 +1,35 @@
+package com.tzld.longarticle.recommend.server.mapper.growth;
+
+import com.tzld.longarticle.recommend.server.repository.model.PushMessageCallback;
+import com.tzld.longarticle.recommend.server.repository.model.PushMessageCallbackExample;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+@Mapper
+public interface NewPushMessageCallbackMapper {
+    long countByExample(PushMessageCallbackExample example);
+
+    int deleteByExample(PushMessageCallbackExample example);
+
+    int deleteByPrimaryKey(Long id);
+
+    int insert(PushMessageCallback row);
+
+    int insertSelective(PushMessageCallback row);
+
+    List<PushMessageCallback> selectByExample(PushMessageCallbackExample example);
+
+    PushMessageCallback selectByPrimaryKey(Long id);
+
+    int updateByExampleSelective(@Param("row") PushMessageCallback row, @Param("example") PushMessageCallbackExample example);
+
+    int updateByExample(@Param("row") PushMessageCallback row, @Param("example") PushMessageCallbackExample example);
+
+    int updateByPrimaryKeySelective(PushMessageCallback row);
+
+    int updateByPrimaryKey(PushMessageCallback row);
+
+    int insertList(@Param("list") List<PushMessageCallback> list);
+}

+ 4 - 1
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/mapper/crawler/ReplyStaffMapper.java → long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/mapper/growth/ReplyStaffMapper.java

@@ -1,10 +1,13 @@
-package com.tzld.longarticle.recommend.server.mapper.crawler;
+package com.tzld.longarticle.recommend.server.mapper.growth;
 
 import com.tzld.longarticle.recommend.server.repository.model.ReplyStaff;
 import com.tzld.longarticle.recommend.server.repository.model.ReplyStaffExample;
 import java.util.List;
+
+import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
+@Mapper
 public interface ReplyStaffMapper {
     long countByExample(ReplyStaffExample example);
 

+ 10 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/mapper/longArticle/LongArticleBaseMapper.java

@@ -1,5 +1,8 @@
 package com.tzld.longarticle.recommend.server.mapper.longArticle;
 
+import com.tzld.longarticle.recommend.server.model.entity.longArticle.ArticleCategory;
+import com.tzld.longarticle.recommend.server.model.entity.longArticle.DatastatScore;
+import com.tzld.longarticle.recommend.server.model.entity.longArticle.ArticlePoolPromotionSource;
 import com.tzld.longarticle.recommend.server.model.entity.longArticle.DatastatSortStrategy;
 import org.apache.ibatis.annotations.Mapper;
 
@@ -14,4 +17,11 @@ public interface LongArticleBaseMapper {
 
     void batchInsertDatastatSortStrategy(List<DatastatSortStrategy> list);
 
+    void batchInsertArticlePoolPromotionSource(List<ArticlePoolPromotionSource> list);
+
+    void updateRootProduceContentLevel(String rootProduceContentId, String level);
+
+    void batchInsertDatastatScore(List<DatastatScore> list);
+
+    void batchInsertArticleCategory(List<ArticleCategory> list);
 }

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

@@ -0,0 +1,12 @@
+package com.tzld.longarticle.recommend.server.model.dto;
+
+import lombok.Data;
+
+@Data
+public class CrawlerContent {
+    private String channelContentId;
+    private String crawlerPlanId;
+    private String ghId;
+    private String title;
+    private Long publishTimestamp;
+}

+ 39 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/dto/kimi/KimiOfficialApiResponse.java

@@ -0,0 +1,39 @@
+package com.tzld.longarticle.recommend.server.model.dto.kimi;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class KimiOfficialApiResponse {
+
+    private String id;
+    private String object;
+    private long created;
+    private String model;
+    private List<Choice> choices;
+    private Usage usage;
+
+
+    @Data
+    public static class Choice {
+        private long index;
+        private Message message;
+        private String finishReason;
+    }
+
+
+    @Data
+    public static class Message {
+        private String role;
+        private String content;
+    }
+
+    @Data
+    public static class Usage {
+        private long promptTokens;
+        private long completionTokens;
+        private long totalTokens;
+    }
+
+}

+ 11 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/dto/kimi/KimiResult.java

@@ -0,0 +1,11 @@
+package com.tzld.longarticle.recommend.server.model.dto.kimi;
+
+import lombok.Data;
+
+@Data
+public class KimiResult {
+    private boolean success;
+    private KimiOfficialApiResponse response;
+    private String failReason;
+    private String responseStr;
+}

+ 82 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/entity/aigc/PublishContentOutput.java

@@ -0,0 +1,82 @@
+package com.tzld.longarticle.recommend.server.model.entity.aigc;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.*;
+import java.math.BigDecimal;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@Table(name = "publish_content_output")
+public class PublishContentOutput {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @Column(name = "id", nullable = false)
+    private Long id;
+
+    @Column(name = "publish_content_id", length = 64)
+    private String publishContentId;
+
+    @Column(name = "content_type", nullable = false)
+    private Integer contentType;
+
+    @Column(name = "source_output_id", length = 64)
+    private String sourceOutputId;
+
+    @Column(name = "group_id", length = 64)
+    private String groupId;
+
+    @Column(name = "output_from", columnDefinition = "int default 1")
+    private Integer outputFrom = 1;
+
+    @Column(name = "output", columnDefinition = "mediumtext", nullable = false)
+    private String output;
+
+    @Column(name = "output_ref_data", columnDefinition = "mediumtext")
+    private String outputRefData;
+
+    @Column(name = "`index`")
+    private Integer index;
+
+    @Column(name = "select_status")
+    private Integer selectStatus;
+
+    @Column(name = "require_word_num")
+    private Integer requireWordNum;
+
+    @Column(name = "require_word_operator", length = 20)
+    private String requireWordOperator;
+
+    @Column(name = "word_num")
+    private Integer wordNum;
+
+    @Column(name = "require_similarity_ratio", precision = 5, scale = 2)
+    private BigDecimal requireSimilarityRatio;
+
+    @Column(name = "require_similarity_operator", length = 20)
+    private String requireSimilarityOperator;
+
+    @Column(name = "similarity_ratio", precision = 6, scale = 2)
+    private BigDecimal similarityRatio;
+
+    @Column(name = "edit_account", length = 255)
+    private String editAccount;
+
+    @Column(name = "edit_timestamp")
+    private Long editTimestamp;
+
+    @Column(name = "edit_param", length = 2048)
+    private String editParam;
+
+    @Column(name = "create_timestamp", nullable = false)
+    private Long createTimestamp;
+
+    @Column(name = "update_timestamp")
+    private Long updateTimestamp;
+
+}

+ 10 - 1
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/entity/crawler/Article.java

@@ -74,6 +74,15 @@ public class Article implements Serializable {
     private Integer status;
     @Column(name = "publish_timestamp")
     private Long publishTimestamp;
-
+    @Column(name = "publish_content_id")
+    private String publishContentId;
+    @Column(name = "channel_content_id")
+    private String channelContentId;
+    @Column(name = "source_publish_content_id")
+    private String sourcePublishContentId;
+    @Column(name = "root_publish_content_id")
+    private String rootPublishContentId;
+    @Column(name = "root_produce_content_id")
+    private String rootProduceContentId;
 }
 

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

@@ -0,0 +1,48 @@
+package com.tzld.longarticle.recommend.server.model.entity.longArticle;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@Table(name = "account_category")
+@IdClass(AccountCategory.PK.class)
+public class AccountCategory {
+
+    @Id
+    private String dt;
+    @Id
+    private String ghId;
+
+    @Column(name = "category_map")
+    private String categoryMap;
+
+    @Column(name = "status")
+    private Integer status;
+
+    @Column(name = "create_timestamp")
+    private Long createTimestamp;
+
+    @Column(name = "update_timestamp")
+    private Long updateTimestamp;
+
+
+    @Data
+    public static class PK implements Serializable {
+
+        @Column(name = "dt")
+        private String dt;
+        @Column(name = "gh_id")
+        private String ghId;
+
+        public PK() {
+        }
+
+    }
+}

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

@@ -0,0 +1,56 @@
+package com.tzld.longarticle.recommend.server.model.entity.longArticle;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@Table(name = "article_category")
+public class ArticleCategory {
+
+    @Id
+    @Column(name = "produce_content_id")
+    private String produceContentId;
+
+    @Column(name = "channel_content_id")
+    private String channelContentId;
+
+    @Column(name = "crawler_plan_id")
+    private String crawlerPlanId;
+
+    @Column(name = "title")
+    private String title;
+
+    @Column(name = "title_md5")
+    private String titleMd5;
+
+    @Column(name = "category")
+    private String category;
+
+    @Column(name = "kimi_result")
+    private String kimiResult;
+
+    @Column(name = "status")
+    private Integer status;
+
+    @Column(name = "fail_reason")
+    private String failReason;
+
+    @Column(name = "retry_times")
+    private Integer retryTimes;
+
+    @Column(name = "create_timestamp")
+    private Long createTimestamp;
+
+    @Column(name = "update_timestamp")
+    private Long updateTimestamp;
+
+}

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

@@ -0,0 +1,34 @@
+package com.tzld.longarticle.recommend.server.model.entity.longArticle;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@Table(name = "article_crawler_plan")
+public class ArticleCrawlerPlan {
+
+    @Id
+    @Column(name = "crawler_plan_id")
+    private String crawlerPlanId;
+
+    @Column(name = "name")
+    private String name;
+
+    @Column(name = "status")
+    private Integer status;
+
+    @Column(name = "create_timestamp")
+    private Long createTimestamp;
+
+    @Column(name = "update_timestamp")
+    private Long updateTimestamp;
+}

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

@@ -0,0 +1,43 @@
+package com.tzld.longarticle.recommend.server.model.entity.longArticle;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@Table(name = "article_pool_promotion_source")
+public class ArticlePoolPromotionSource implements Serializable {
+
+    @Id
+    @Column(name = "channel_content_id")
+    private String channelContentId;
+    @Column(name = "source_publish_content_id")
+    private String sourcePublishContentId;
+    @Column(name = "root_publish_content_id")
+    private String rootPublishContentId;
+    @Column(name = "root_produce_content_id")
+    private String rootProduceContentId;
+    @Column(name = "wx_sn")
+    private String wxSn;
+    @Column(name = "title")
+    private String title;
+    @Column(name = "title_md5")
+    private String titleMd5;
+    @Column(name = "level")
+    private String level;
+    @Column(name = "status")
+    private Integer status;
+    @Column(name = "deleted")
+    private Integer deleted;
+    @Column(name = "create_timestamp")
+    private Long createTimestamp;
+    @Column(name = "update_timestamp")
+    private Long updateTimestamp;
+
+}

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

@@ -0,0 +1,68 @@
+package com.tzld.longarticle.recommend.server.model.entity.longArticle;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@Table(name = "datastat_score")
+public class DatastatScore {
+
+    @Id
+    @Column(name = "id")
+    private Long id;
+
+    @Column(name = "dt")
+    private String dt;
+
+    @Column(name = "gh_id")
+    private String ghId;
+
+    @Column(name = "index")
+    private Integer index;
+
+    @Column(name = "account_name")
+    private String accountName;
+
+    @Column(name = "title")
+    private String title;
+
+    @Column(name = "strategy")
+    private String strategy;
+
+    @Column(name = "score")
+    private Double score;
+
+    @Column(name = "similarity")
+    private Double similarity;
+
+    @Column(name = "view_count_rate")
+    private Double viewCountRate;
+
+    @Column(name = "his_fission_avg_read_rate_rate")
+    private Double hisFissionAvgReadRateRate;
+
+    @Column(name = "his_fission_avg_read_sum_rate")
+    private Double hisFissionAvgReadSumRate;
+
+    @Column(name = "his_fission_de_weight_avg_read_sum_rate")
+    private Double hisFissionDeWeightAvgReadSumRate;
+
+    @Column(name = "read_count")
+    private Integer readCount;
+
+    @Column(name = "read_avg")
+    private Double readAvg;
+
+    @Column(name = "read_avg_rate")
+    private Double readAvgRate;
+
+}

+ 10 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/param/ArticleFindSourceParam.java

@@ -0,0 +1,10 @@
+package com.tzld.longarticle.recommend.server.model.param;
+
+import lombok.Data;
+
+@Data
+public class ArticleFindSourceParam {
+
+    private String dateStr;
+    private String wxSn;
+}

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

@@ -8,6 +8,7 @@ public class FirstContentScoreExport {
     private String dateStr;
     private String ghId;
     private String accountName;
+    private Integer index;
     private String title;
     private String strategy;
 

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

@@ -0,0 +1,27 @@
+package com.tzld.longarticle.recommend.server.model.vo;
+
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class GhDetailVo {
+
+    private Long id;
+
+    private String accountId;
+
+    private String accountName;
+
+    private Integer type;
+
+    private String typeName;
+
+    private String category1;
+
+    private String category2;
+
+    private Date createTime;
+
+    private Date updateTime;
+}

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

@@ -0,0 +1,16 @@
+package com.tzld.longarticle.recommend.server.model.vo;
+
+import lombok.Data;
+
+@Data
+public class GhTypeVo {
+
+    private Integer type;
+
+    private String name;
+
+    public GhTypeVo(Integer type, String name) {
+        this.type = type;
+        this.name = name;
+    }
+}

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

@@ -0,0 +1,10 @@
+package com.tzld.longarticle.recommend.server.model.vo;
+
+import lombok.Data;
+
+@Data
+public class ProduceContentCrawlerVO {
+    private String produceContentId;
+    private String channelContentId;
+    private String title;
+}

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

@@ -0,0 +1,12 @@
+package com.tzld.longarticle.recommend.server.model.vo;
+
+import lombok.Data;
+
+@Data
+public class ReportUvVo {
+
+    private String ghId;
+
+    private Long uv;
+
+}

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

@@ -0,0 +1,18 @@
+package com.tzld.longarticle.recommend.server.model.vo;
+
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Data
+public class RootPublishContentVO {
+
+    private String channelContentId;
+    private String sourcePublishContentId;
+    private String rootPublishContentId;
+    private String rootProduceContentId;
+
+    private List<String> midChannelContentIds = new ArrayList<>();
+
+}

+ 13 - 3
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/mq/MessageCallbackCustomer.java

@@ -7,6 +7,7 @@ import com.aliyun.openservices.ons.api.ConsumeContext;
 import com.aliyun.openservices.ons.api.Message;
 import com.aliyun.openservices.ons.api.MessageListener;
 import com.tzld.longarticle.recommend.server.mapper.crawler.PushMessageCallbackMapper;
+import com.tzld.longarticle.recommend.server.mapper.growth.NewPushMessageCallbackMapper;
 import com.tzld.longarticle.recommend.server.model.bo.ReplyInfo;
 import com.tzld.longarticle.recommend.server.model.param.CallbackParam;
 import com.tzld.longarticle.recommend.server.repository.model.PushMessageCallback;
@@ -27,6 +28,9 @@ public class MessageCallbackCustomer implements MessageListener {
     @Autowired
     private PushMessageCallbackMapper pushMessageCallbackMapper;
 
+    @Autowired
+    private NewPushMessageCallbackMapper newPushMessageCallbackMapper;
+
     @Override
     public Action consume(Message message, ConsumeContext consumeContext) {
         CallbackParam param = JSONObject.parseObject(new String(message.getBody()), CallbackParam.class);
@@ -48,10 +52,16 @@ public class MessageCallbackCustomer implements MessageListener {
         }
         try {
             pushMessageCallbackMapper.insertList(insertList);
-            return Action.CommitMessage;
         } catch (Exception e) {
-            log.error("PushMessageCallback insert pushMessageCallback={}, error={}", pushMessageCallback, e.getMessage());
+            log.error("PushMessageCallback pushMessageCallbackMapper insert pushMessageCallback={}, error={}", pushMessageCallback, e.getMessage());
+            return Action.ReconsumeLater;
+        }
+        try {
+            newPushMessageCallbackMapper.insertList(insertList);
+        } catch (Exception e) {
+            log.error("PushMessageCallback newPushMessageCallbackMapper insert pushMessageCallback={}, error={}", pushMessageCallback, e.getMessage());
         }
-        return Action.ReconsumeLater;
+        return Action.CommitMessage;
+
     }
 }

+ 62 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/remote/CrawlerContentByPlanService.java

@@ -0,0 +1,62 @@
+package com.tzld.longarticle.recommend.server.remote;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.tzld.longarticle.recommend.server.common.HttpPoolFactory;
+import com.tzld.longarticle.recommend.server.model.vo.ProduceContentCrawlerVO;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.HttpEntity;
+import org.apache.http.StatusLine;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.util.EntityUtils;
+import org.springframework.stereotype.Service;
+
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+@Service
+@Slf4j
+public class CrawlerContentByPlanService {
+    private final CloseableHttpClient client = HttpPoolFactory.aigcPool();
+    private static final String url = "http://aigc-api.cybertogether.net/aigc/produce/content/getContentByCrawlerPlan";
+
+
+    public List<ProduceContentCrawlerVO> getCrawlerContentByPlan(String crawlerPlanId, List<String> producePlanIds) {
+        long start = System.currentTimeMillis();
+        List<ProduceContentCrawlerVO> result = new ArrayList<>();
+        JSONObject bodyParam = new JSONObject();
+        JSONObject bodyParamParams = new JSONObject();
+        bodyParamParams.put("crawlerPlanId", crawlerPlanId);
+        bodyParamParams.put("producePlanIds", producePlanIds);
+        bodyParam.put("params", bodyParamParams);
+        try {
+            HttpPost httpPost = new HttpPost(url);
+            StringEntity stringEntity = new StringEntity(bodyParam.toJSONString(), StandardCharsets.UTF_8);
+            httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");
+            httpPost.setEntity(stringEntity);
+            CloseableHttpResponse response = client.execute(httpPost);
+            StatusLine statusLine = response.getStatusLine();
+            if (statusLine.getStatusCode() == 200) {
+                HttpEntity responseEntity = response.getEntity();
+                if (Objects.nonNull(responseEntity)) {
+                    String responseBody = EntityUtils.toString(responseEntity, "UTF-8");
+                    JSONObject jsonObject = JSONObject.parseObject(responseBody);
+                    if (jsonObject.getInteger("code") == 0) {
+                        JSONArray data = jsonObject.getJSONArray("data");
+                        result.addAll(JSONArray.parseArray(data.toJSONString(), ProduceContentCrawlerVO.class));
+                    }
+                }
+            }
+        } catch (Exception e) {
+            log.error("getCrawlerContentByPlan error", e);
+        }
+        log.info("getCrawlerContentByPlan耗时:{}", System.currentTimeMillis() - start);
+        return result;
+    }
+
+}

+ 89 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/remote/KimiApiService.java

@@ -0,0 +1,89 @@
+package com.tzld.longarticle.recommend.server.remote;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.tzld.longarticle.recommend.server.model.dto.kimi.KimiOfficialApiResponse;
+import com.tzld.longarticle.recommend.server.model.dto.kimi.KimiResult;
+import com.tzld.longarticle.recommend.server.util.MapBuilder;
+import lombok.extern.slf4j.Slf4j;
+import okhttp3.*;
+import org.apache.http.util.TextUtils;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.TimeUnit;
+
+@Service
+@Slf4j
+public class KimiApiService {
+
+    private OkHttpClient client;
+
+    @PostConstruct
+    public void init() {
+        client = new OkHttpClient().newBuilder()
+                .connectTimeout(15, TimeUnit.MINUTES)
+                .readTimeout(15, TimeUnit.MINUTES)
+                .writeTimeout(15, TimeUnit.MINUTES)
+                .build();
+
+    }
+
+
+    public KimiResult requestOfficialApi(String prompt, String model, Double temperature) {
+        KimiResult result = new KimiResult();
+        result.setSuccess(false);
+        if (TextUtils.isBlank(prompt) || TextUtils.isBlank(prompt.trim())) {
+            result.setFailReason("prompt is empty");
+            return result;
+        }
+
+        try {
+            JSONArray jsonArray = new JSONArray();
+            JSONObject message = new JSONObject();
+            message.put("role", "user");
+            message.put("content", prompt);
+            jsonArray.add(message);
+
+            Map<Object, Object> bodyParam = MapBuilder
+                    .builder()
+                    .put("model", Optional.ofNullable(model).orElse("moonshot-v1-auto"))
+                    .put("temperature", Optional.ofNullable(temperature).orElse(0.3))
+                    .put("messages", jsonArray)
+                    .build();
+
+            MediaType mediaType = MediaType.parse("application/json");
+            RequestBody body = RequestBody.create(mediaType, JSONObject.toJSONString(bodyParam));
+            Request request = new Request.Builder()
+                    .url("https://api.moonshot.cn/v1/chat/completions")
+                    .method("POST", body)
+                    .addHeader("Content-Type", "application/json")
+                    .addHeader("Authorization", "Bearer sk-5DqYCa88kche6nwIWjLE1p4oMm8nXrR9kQMKbBolNAWERu7q")
+                    .build();
+            Response response = client.newCall(request).execute();
+
+            String responseContent = response.body().string();
+            result.setResponseStr(responseContent);
+            log.info("kimi api responseContent = {}", responseContent);
+            if (response.isSuccessful()) {
+                KimiOfficialApiResponse obj = JSONObject.parseObject(responseContent, KimiOfficialApiResponse.class);
+                if (CollectionUtil.isNotEmpty(obj.getChoices())) {
+                    result.setSuccess(true);
+                    result.setResponse(obj);
+                } else {
+                    result.setFailReason("response empty");
+                }
+            } else {
+                JSONObject json = JSONObject.parseObject(responseContent);
+                result.setFailReason("request error code:" + response.code() + " message:" + json.getString("error"));
+            }
+        } catch (Exception e) {
+            log.error("kimi official api fail: " + e.getMessage());
+            result.setFailReason(e.getMessage());
+        }
+        return result;
+    }
+}

+ 2 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/aigc/PublishAccountRepository.java

@@ -10,4 +10,6 @@ import java.util.List;
 public interface PublishAccountRepository extends JpaRepository<PublishAccount, String> {
 
     List<PublishAccount> getAllByGhIdIn(List<String> ghIds);
+
+    PublishAccount getByGhId(String ghId);
 }

+ 13 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/aigc/PublishContentOutputRepository.java

@@ -0,0 +1,13 @@
+package com.tzld.longarticle.recommend.server.repository.aigc;
+
+import com.tzld.longarticle.recommend.server.model.entity.aigc.PublishContentOutput;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface PublishContentOutputRepository extends JpaRepository<PublishContentOutput, String> {
+
+    List<PublishContentOutput> getByPublishContentIdInAndContentTypeAndSelectStatus(List<String> publishContentIds, Integer contentType, Integer selectStatus);
+}

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

@@ -29,4 +29,8 @@ public interface ArticleRepository extends JpaRepository<Article, String> {
 
     List<Article> getByGhIdAndItemIndexAndTypeEqualsAndStatusEquals(String ghId, Integer itemIndex, String type, Integer status);
 
+    List<Article> getByChannelContentIdAndRootPublishContentIdIsNotNull(String channelContentId);
+
+    Article getByWxSn(String wxSn);
+
 }

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

@@ -25,4 +25,5 @@ public interface PublishSortLogRepository extends JpaRepository<PublishSortLog,
 
     List<PublishSortLog> findByDateStrIn(List<String> dateStrList);
 
+    List<PublishSortLog> findByDateStrAndGhId(String dateStr, String ghId);
 }

+ 12 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/longArticle/AccountCategoryRepository.java

@@ -0,0 +1,12 @@
+package com.tzld.longarticle.recommend.server.repository.longArticle;
+
+import com.tzld.longarticle.recommend.server.model.entity.longArticle.AccountCategory;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface AccountCategoryRepository extends JpaRepository<AccountCategory, AccountCategory.PK> {
+
+    AccountCategory getByGhIdAndStatus(String ghId, Integer status);
+
+}

+ 19 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/longArticle/ArticleCategoryRepository.java

@@ -0,0 +1,19 @@
+package com.tzld.longarticle.recommend.server.repository.longArticle;
+
+import com.tzld.longarticle.recommend.server.model.entity.longArticle.ArticleCategory;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface ArticleCategoryRepository extends JpaRepository<ArticleCategory, String> {
+
+    List<ArticleCategory> getByProduceContentIdIn(List<String> produceContentIds);
+
+    List<ArticleCategory> getByStatus(Integer status);
+
+    List<ArticleCategory> getAllByChannelContentIdIn(List<String> channelContentIds);
+
+    List<ArticleCategory> getByStatusAndRetryTimesLessThan(Integer status, Integer retryTimes);
+}

+ 14 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/longArticle/ArticleCrawlerPlanRepository.java

@@ -0,0 +1,14 @@
+package com.tzld.longarticle.recommend.server.repository.longArticle;
+
+import com.tzld.longarticle.recommend.server.model.entity.longArticle.ArticleCrawlerPlan;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface ArticleCrawlerPlanRepository extends JpaRepository<ArticleCrawlerPlan, String> {
+
+    List<ArticleCrawlerPlan> getByStatus(Integer status);
+
+}

+ 19 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/longArticle/ArticlePoolPromotionSourceRepository.java

@@ -0,0 +1,19 @@
+package com.tzld.longarticle.recommend.server.repository.longArticle;
+
+import com.tzld.longarticle.recommend.server.model.entity.longArticle.ArticlePoolPromotionSource;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface ArticlePoolPromotionSourceRepository extends JpaRepository<ArticlePoolPromotionSource, String> {
+
+    ArticlePoolPromotionSource getByChannelContentId(String channelContentId);
+
+    List<ArticlePoolPromotionSource> getByChannelContentIdIn(List<String> channelContentIds);
+
+    List<ArticlePoolPromotionSource> getByChannelContentIdInAndStatusAndDeleted(List<String> channelContentIds, Integer status, Integer deleted);
+
+    List<ArticlePoolPromotionSource> getByStatusAndDeleted(Integer status, Integer deleted);
+}

+ 12 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/longArticle/DatastatScoreRepository.java

@@ -0,0 +1,12 @@
+package com.tzld.longarticle.recommend.server.repository.longArticle;
+
+import com.tzld.longarticle.recommend.server.model.entity.longArticle.DatastatScore;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface DatastatScoreRepository extends JpaRepository<DatastatScore, Long> {
+    void deleteByDtIn(List<String> dateStrList);
+}

+ 28 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/model/GhDetail.java

@@ -0,0 +1,28 @@
+package com.tzld.longarticle.recommend.server.repository.model;
+
+import lombok.Data;
+import lombok.ToString;
+
+import java.util.Date;
+
+@Data
+@ToString
+public class GhDetail {
+    private Long id;
+
+    private String ghId;
+
+    private String ghName;
+
+    private Integer type;
+
+    private String category1;
+
+    private String category2;
+
+    private Integer isDelete;
+
+    private Date createTime;
+
+    private Date updateTime;
+}

+ 791 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/model/GhDetailExample.java

@@ -0,0 +1,791 @@
+package com.tzld.longarticle.recommend.server.repository.model;
+
+import com.tzld.longarticle.recommend.server.util.page.Page;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+public class GhDetailExample {
+    protected String orderByClause;
+
+    protected boolean distinct;
+
+    protected List<Criteria> oredCriteria;
+    protected Page page;
+
+    public GhDetailExample() {
+        oredCriteria = new ArrayList<>();
+    }
+
+    public void setOrderByClause(String orderByClause) {
+        this.orderByClause = orderByClause;
+    }
+
+    public String getOrderByClause() {
+        return orderByClause;
+    }
+
+    public void setDistinct(boolean distinct) {
+        this.distinct = distinct;
+    }
+
+    public boolean isDistinct() {
+        return distinct;
+    }
+
+    public List<Criteria> getOredCriteria() {
+        return oredCriteria;
+    }
+
+    public void or(Criteria criteria) {
+        oredCriteria.add(criteria);
+    }
+
+    public Criteria or() {
+        Criteria criteria = createCriteriaInternal();
+        oredCriteria.add(criteria);
+        return criteria;
+    }
+
+    public Criteria createCriteria() {
+        Criteria criteria = createCriteriaInternal();
+        if (oredCriteria.size() == 0) {
+            oredCriteria.add(criteria);
+        }
+        return criteria;
+    }
+
+    protected Criteria createCriteriaInternal() {
+        Criteria criteria = new Criteria();
+        return criteria;
+    }
+
+    public void clear() {
+        oredCriteria.clear();
+        orderByClause = null;
+        distinct = false;
+    }
+
+    public void setPage(Page page) {
+        this.page=page;
+    }
+
+    public Page getPage() {
+        return page;
+    }
+
+    protected abstract static class GeneratedCriteria {
+        protected List<Criterion> criteria;
+
+        protected GeneratedCriteria() {
+            super();
+            criteria = new ArrayList<>();
+        }
+
+        public boolean isValid() {
+            return criteria.size() > 0;
+        }
+
+        public List<Criterion> getAllCriteria() {
+            return criteria;
+        }
+
+        public List<Criterion> getCriteria() {
+            return criteria;
+        }
+
+        protected void addCriterion(String condition) {
+            if (condition == null) {
+                throw new RuntimeException("Value for condition cannot be null");
+            }
+            criteria.add(new Criterion(condition));
+        }
+
+        protected void addCriterion(String condition, Object value, String property) {
+            if (value == null) {
+                throw new RuntimeException("Value for " + property + " cannot be null");
+            }
+            criteria.add(new Criterion(condition, value));
+        }
+
+        protected void addCriterion(String condition, Object value1, Object value2, String property) {
+            if (value1 == null || value2 == null) {
+                throw new RuntimeException("Between values for " + property + " cannot be null");
+            }
+            criteria.add(new Criterion(condition, value1, value2));
+        }
+
+        public Criteria andIdIsNull() {
+            addCriterion("id is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdIsNotNull() {
+            addCriterion("id is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdEqualTo(Long value) {
+            addCriterion("id =", value, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdNotEqualTo(Long value) {
+            addCriterion("id <>", value, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdGreaterThan(Long value) {
+            addCriterion("id >", value, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdGreaterThanOrEqualTo(Long value) {
+            addCriterion("id >=", value, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdLessThan(Long value) {
+            addCriterion("id <", value, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdLessThanOrEqualTo(Long value) {
+            addCriterion("id <=", value, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdIn(List<Long> values) {
+            addCriterion("id in", values, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdNotIn(List<Long> values) {
+            addCriterion("id not in", values, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdBetween(Long value1, Long value2) {
+            addCriterion("id between", value1, value2, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdNotBetween(Long value1, Long value2) {
+            addCriterion("id not between", value1, value2, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andGhIdIsNull() {
+            addCriterion("gh_id is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andGhIdIsNotNull() {
+            addCriterion("gh_id is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andGhIdEqualTo(String value) {
+            addCriterion("gh_id =", value, "ghId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGhIdNotEqualTo(String value) {
+            addCriterion("gh_id <>", value, "ghId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGhIdGreaterThan(String value) {
+            addCriterion("gh_id >", value, "ghId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGhIdGreaterThanOrEqualTo(String value) {
+            addCriterion("gh_id >=", value, "ghId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGhIdLessThan(String value) {
+            addCriterion("gh_id <", value, "ghId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGhIdLessThanOrEqualTo(String value) {
+            addCriterion("gh_id <=", value, "ghId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGhIdLike(String value) {
+            addCriterion("gh_id like", value, "ghId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGhIdNotLike(String value) {
+            addCriterion("gh_id not like", value, "ghId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGhIdIn(List<String> values) {
+            addCriterion("gh_id in", values, "ghId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGhIdNotIn(List<String> values) {
+            addCriterion("gh_id not in", values, "ghId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGhIdBetween(String value1, String value2) {
+            addCriterion("gh_id between", value1, value2, "ghId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGhIdNotBetween(String value1, String value2) {
+            addCriterion("gh_id not between", value1, value2, "ghId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGhNameIsNull() {
+            addCriterion("gh_name is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andGhNameIsNotNull() {
+            addCriterion("gh_name is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andGhNameEqualTo(String value) {
+            addCriterion("gh_name =", value, "ghName");
+            return (Criteria) this;
+        }
+
+        public Criteria andGhNameNotEqualTo(String value) {
+            addCriterion("gh_name <>", value, "ghName");
+            return (Criteria) this;
+        }
+
+        public Criteria andGhNameGreaterThan(String value) {
+            addCriterion("gh_name >", value, "ghName");
+            return (Criteria) this;
+        }
+
+        public Criteria andGhNameGreaterThanOrEqualTo(String value) {
+            addCriterion("gh_name >=", value, "ghName");
+            return (Criteria) this;
+        }
+
+        public Criteria andGhNameLessThan(String value) {
+            addCriterion("gh_name <", value, "ghName");
+            return (Criteria) this;
+        }
+
+        public Criteria andGhNameLessThanOrEqualTo(String value) {
+            addCriterion("gh_name <=", value, "ghName");
+            return (Criteria) this;
+        }
+
+        public Criteria andGhNameLike(String value) {
+            addCriterion("gh_name like", value, "ghName");
+            return (Criteria) this;
+        }
+
+        public Criteria andGhNameNotLike(String value) {
+            addCriterion("gh_name not like", value, "ghName");
+            return (Criteria) this;
+        }
+
+        public Criteria andGhNameIn(List<String> values) {
+            addCriterion("gh_name in", values, "ghName");
+            return (Criteria) this;
+        }
+
+        public Criteria andGhNameNotIn(List<String> values) {
+            addCriterion("gh_name not in", values, "ghName");
+            return (Criteria) this;
+        }
+
+        public Criteria andGhNameBetween(String value1, String value2) {
+            addCriterion("gh_name between", value1, value2, "ghName");
+            return (Criteria) this;
+        }
+
+        public Criteria andGhNameNotBetween(String value1, String value2) {
+            addCriterion("gh_name not between", value1, value2, "ghName");
+            return (Criteria) this;
+        }
+
+        public Criteria andTypeIsNull() {
+            addCriterion("type is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andTypeIsNotNull() {
+            addCriterion("type is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andTypeEqualTo(Integer value) {
+            addCriterion("type =", value, "type");
+            return (Criteria) this;
+        }
+
+        public Criteria andTypeNotEqualTo(Integer value) {
+            addCriterion("type <>", value, "type");
+            return (Criteria) this;
+        }
+
+        public Criteria andTypeGreaterThan(Integer value) {
+            addCriterion("type >", value, "type");
+            return (Criteria) this;
+        }
+
+        public Criteria andTypeGreaterThanOrEqualTo(Integer value) {
+            addCriterion("type >=", value, "type");
+            return (Criteria) this;
+        }
+
+        public Criteria andTypeLessThan(Integer value) {
+            addCriterion("type <", value, "type");
+            return (Criteria) this;
+        }
+
+        public Criteria andTypeLessThanOrEqualTo(Integer value) {
+            addCriterion("type <=", value, "type");
+            return (Criteria) this;
+        }
+
+        public Criteria andTypeIn(List<Integer> values) {
+            addCriterion("type in", values, "type");
+            return (Criteria) this;
+        }
+
+        public Criteria andTypeNotIn(List<Integer> values) {
+            addCriterion("type not in", values, "type");
+            return (Criteria) this;
+        }
+
+        public Criteria andTypeBetween(Integer value1, Integer value2) {
+            addCriterion("type between", value1, value2, "type");
+            return (Criteria) this;
+        }
+
+        public Criteria andTypeNotBetween(Integer value1, Integer value2) {
+            addCriterion("type not between", value1, value2, "type");
+            return (Criteria) this;
+        }
+
+        public Criteria andCategory1IsNull() {
+            addCriterion("category1 is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andCategory1IsNotNull() {
+            addCriterion("category1 is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andCategory1EqualTo(String value) {
+            addCriterion("category1 =", value, "category1");
+            return (Criteria) this;
+        }
+
+        public Criteria andCategory1NotEqualTo(String value) {
+            addCriterion("category1 <>", value, "category1");
+            return (Criteria) this;
+        }
+
+        public Criteria andCategory1GreaterThan(String value) {
+            addCriterion("category1 >", value, "category1");
+            return (Criteria) this;
+        }
+
+        public Criteria andCategory1GreaterThanOrEqualTo(String value) {
+            addCriterion("category1 >=", value, "category1");
+            return (Criteria) this;
+        }
+
+        public Criteria andCategory1LessThan(String value) {
+            addCriterion("category1 <", value, "category1");
+            return (Criteria) this;
+        }
+
+        public Criteria andCategory1LessThanOrEqualTo(String value) {
+            addCriterion("category1 <=", value, "category1");
+            return (Criteria) this;
+        }
+
+        public Criteria andCategory1Like(String value) {
+            addCriterion("category1 like", value, "category1");
+            return (Criteria) this;
+        }
+
+        public Criteria andCategory1NotLike(String value) {
+            addCriterion("category1 not like", value, "category1");
+            return (Criteria) this;
+        }
+
+        public Criteria andCategory1In(List<String> values) {
+            addCriterion("category1 in", values, "category1");
+            return (Criteria) this;
+        }
+
+        public Criteria andCategory1NotIn(List<String> values) {
+            addCriterion("category1 not in", values, "category1");
+            return (Criteria) this;
+        }
+
+        public Criteria andCategory1Between(String value1, String value2) {
+            addCriterion("category1 between", value1, value2, "category1");
+            return (Criteria) this;
+        }
+
+        public Criteria andCategory1NotBetween(String value1, String value2) {
+            addCriterion("category1 not between", value1, value2, "category1");
+            return (Criteria) this;
+        }
+
+        public Criteria andCategory2IsNull() {
+            addCriterion("category2 is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andCategory2IsNotNull() {
+            addCriterion("category2 is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andCategory2EqualTo(String value) {
+            addCriterion("category2 =", value, "category2");
+            return (Criteria) this;
+        }
+
+        public Criteria andCategory2NotEqualTo(String value) {
+            addCriterion("category2 <>", value, "category2");
+            return (Criteria) this;
+        }
+
+        public Criteria andCategory2GreaterThan(String value) {
+            addCriterion("category2 >", value, "category2");
+            return (Criteria) this;
+        }
+
+        public Criteria andCategory2GreaterThanOrEqualTo(String value) {
+            addCriterion("category2 >=", value, "category2");
+            return (Criteria) this;
+        }
+
+        public Criteria andCategory2LessThan(String value) {
+            addCriterion("category2 <", value, "category2");
+            return (Criteria) this;
+        }
+
+        public Criteria andCategory2LessThanOrEqualTo(String value) {
+            addCriterion("category2 <=", value, "category2");
+            return (Criteria) this;
+        }
+
+        public Criteria andCategory2Like(String value) {
+            addCriterion("category2 like", value, "category2");
+            return (Criteria) this;
+        }
+
+        public Criteria andCategory2NotLike(String value) {
+            addCriterion("category2 not like", value, "category2");
+            return (Criteria) this;
+        }
+
+        public Criteria andCategory2In(List<String> values) {
+            addCriterion("category2 in", values, "category2");
+            return (Criteria) this;
+        }
+
+        public Criteria andCategory2NotIn(List<String> values) {
+            addCriterion("category2 not in", values, "category2");
+            return (Criteria) this;
+        }
+
+        public Criteria andCategory2Between(String value1, String value2) {
+            addCriterion("category2 between", value1, value2, "category2");
+            return (Criteria) this;
+        }
+
+        public Criteria andCategory2NotBetween(String value1, String value2) {
+            addCriterion("category2 not between", value1, value2, "category2");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsDeleteIsNull() {
+            addCriterion("is_delete is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsDeleteIsNotNull() {
+            addCriterion("is_delete is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsDeleteEqualTo(Integer value) {
+            addCriterion("is_delete =", value, "isDelete");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsDeleteNotEqualTo(Integer value) {
+            addCriterion("is_delete <>", value, "isDelete");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsDeleteGreaterThan(Integer value) {
+            addCriterion("is_delete >", value, "isDelete");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsDeleteGreaterThanOrEqualTo(Integer value) {
+            addCriterion("is_delete >=", value, "isDelete");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsDeleteLessThan(Integer value) {
+            addCriterion("is_delete <", value, "isDelete");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsDeleteLessThanOrEqualTo(Integer value) {
+            addCriterion("is_delete <=", value, "isDelete");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsDeleteIn(List<Integer> values) {
+            addCriterion("is_delete in", values, "isDelete");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsDeleteNotIn(List<Integer> values) {
+            addCriterion("is_delete not in", values, "isDelete");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsDeleteBetween(Integer value1, Integer value2) {
+            addCriterion("is_delete between", value1, value2, "isDelete");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsDeleteNotBetween(Integer value1, Integer value2) {
+            addCriterion("is_delete not between", value1, value2, "isDelete");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimeIsNull() {
+            addCriterion("create_time is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimeIsNotNull() {
+            addCriterion("create_time is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimeEqualTo(Date value) {
+            addCriterion("create_time =", value, "createTime");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimeNotEqualTo(Date value) {
+            addCriterion("create_time <>", value, "createTime");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimeGreaterThan(Date value) {
+            addCriterion("create_time >", value, "createTime");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimeGreaterThanOrEqualTo(Date value) {
+            addCriterion("create_time >=", value, "createTime");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimeLessThan(Date value) {
+            addCriterion("create_time <", value, "createTime");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimeLessThanOrEqualTo(Date value) {
+            addCriterion("create_time <=", value, "createTime");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimeIn(List<Date> values) {
+            addCriterion("create_time in", values, "createTime");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimeNotIn(List<Date> values) {
+            addCriterion("create_time not in", values, "createTime");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimeBetween(Date value1, Date value2) {
+            addCriterion("create_time between", value1, value2, "createTime");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimeNotBetween(Date value1, Date value2) {
+            addCriterion("create_time not between", value1, value2, "createTime");
+            return (Criteria) this;
+        }
+
+        public Criteria andUpdateTimeIsNull() {
+            addCriterion("update_time is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andUpdateTimeIsNotNull() {
+            addCriterion("update_time is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andUpdateTimeEqualTo(Date value) {
+            addCriterion("update_time =", value, "updateTime");
+            return (Criteria) this;
+        }
+
+        public Criteria andUpdateTimeNotEqualTo(Date value) {
+            addCriterion("update_time <>", value, "updateTime");
+            return (Criteria) this;
+        }
+
+        public Criteria andUpdateTimeGreaterThan(Date value) {
+            addCriterion("update_time >", value, "updateTime");
+            return (Criteria) this;
+        }
+
+        public Criteria andUpdateTimeGreaterThanOrEqualTo(Date value) {
+            addCriterion("update_time >=", value, "updateTime");
+            return (Criteria) this;
+        }
+
+        public Criteria andUpdateTimeLessThan(Date value) {
+            addCriterion("update_time <", value, "updateTime");
+            return (Criteria) this;
+        }
+
+        public Criteria andUpdateTimeLessThanOrEqualTo(Date value) {
+            addCriterion("update_time <=", value, "updateTime");
+            return (Criteria) this;
+        }
+
+        public Criteria andUpdateTimeIn(List<Date> values) {
+            addCriterion("update_time in", values, "updateTime");
+            return (Criteria) this;
+        }
+
+        public Criteria andUpdateTimeNotIn(List<Date> values) {
+            addCriterion("update_time not in", values, "updateTime");
+            return (Criteria) this;
+        }
+
+        public Criteria andUpdateTimeBetween(Date value1, Date value2) {
+            addCriterion("update_time between", value1, value2, "updateTime");
+            return (Criteria) this;
+        }
+
+        public Criteria andUpdateTimeNotBetween(Date value1, Date value2) {
+            addCriterion("update_time not between", value1, value2, "updateTime");
+            return (Criteria) this;
+        }
+    }
+
+    public static class Criteria extends GeneratedCriteria {
+        protected Criteria() {
+            super();
+        }
+    }
+
+    public static class Criterion {
+        private String condition;
+
+        private Object value;
+
+        private Object secondValue;
+
+        private boolean noValue;
+
+        private boolean singleValue;
+
+        private boolean betweenValue;
+
+        private boolean listValue;
+
+        private String typeHandler;
+
+        public String getCondition() {
+            return condition;
+        }
+
+        public Object getValue() {
+            return value;
+        }
+
+        public Object getSecondValue() {
+            return secondValue;
+        }
+
+        public boolean isNoValue() {
+            return noValue;
+        }
+
+        public boolean isSingleValue() {
+            return singleValue;
+        }
+
+        public boolean isBetweenValue() {
+            return betweenValue;
+        }
+
+        public boolean isListValue() {
+            return listValue;
+        }
+
+        public String getTypeHandler() {
+            return typeHandler;
+        }
+
+        protected Criterion(String condition) {
+            super();
+            this.condition = condition;
+            this.typeHandler = null;
+            this.noValue = true;
+        }
+
+        protected Criterion(String condition, Object value, String typeHandler) {
+            super();
+            this.condition = condition;
+            this.value = value;
+            this.typeHandler = typeHandler;
+            if (value instanceof List<?>) {
+                this.listValue = true;
+            } else {
+                this.singleValue = true;
+            }
+        }
+
+        protected Criterion(String condition, Object value) {
+            this(condition, value, null);
+        }
+
+        protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {
+            super();
+            this.condition = condition;
+            this.value = value;
+            this.secondValue = secondValue;
+            this.typeHandler = typeHandler;
+            this.betweenValue = true;
+        }
+
+        protected Criterion(String condition, Object value, Object secondValue) {
+            this(condition, value, secondValue, null);
+        }
+    }
+}

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

@@ -3,6 +3,7 @@ package com.tzld.longarticle.recommend.server.service;
 import cn.hutool.core.collection.CollectionUtil;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
+import com.aliyun.odps.data.Record;
 import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue;
 import com.tzld.longarticle.recommend.server.common.enums.recommend.AccountBusinessTypeEnum;
 import com.tzld.longarticle.recommend.server.common.enums.recommend.FeishuRobotIdEnum;
@@ -19,6 +20,8 @@ import com.tzld.longarticle.recommend.server.model.entity.crawler.LongArticlesVi
 import com.tzld.longarticle.recommend.server.model.entity.longArticle.GetOffVideoArticle;
 import com.tzld.longarticle.recommend.server.model.entity.longArticle.LongArticlesMatchVideo;
 import com.tzld.longarticle.recommend.server.model.entity.longArticle.LongArticlesReadRate;
+import com.tzld.longarticle.recommend.server.model.param.ArticleFindSourceParam;
+import com.tzld.longarticle.recommend.server.remote.ODPSManager;
 import com.tzld.longarticle.recommend.server.repository.crawler.GetOffVideoCrawlerRepository;
 import com.tzld.longarticle.recommend.server.repository.crawler.LongArticlesRootSourceIdRepository;
 import com.tzld.longarticle.recommend.server.repository.crawler.LongArticlesVideoRepository;
@@ -26,6 +29,7 @@ import com.tzld.longarticle.recommend.server.repository.longArticle.GetOffVideoA
 import com.tzld.longarticle.recommend.server.repository.longArticle.LongArticlesMatchVideoRepository;
 import com.tzld.longarticle.recommend.server.repository.longArticle.LongArticlesReadRateRepository;
 import com.tzld.longarticle.recommend.server.repository.model.PushMessageCallbackExample;
+import com.tzld.longarticle.recommend.server.service.recommend.ArticleService;
 import com.tzld.longarticle.recommend.server.util.DateUtils;
 import com.tzld.longarticle.recommend.server.util.LarkRobotUtil;
 import com.tzld.longarticle.recommend.server.util.feishu.FeishuMessageSender;
@@ -38,10 +42,7 @@ import org.springframework.stereotype.Service;
 import org.springframework.util.StringUtils;
 
 import java.time.LocalTime;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.stream.Collectors;
 
 import static com.tzld.longarticle.recommend.server.common.constant.TimeConstant.MILLISECOND_DAY;
@@ -69,6 +70,10 @@ public class XxlJobService {
     private LongArticlesRootSourceIdRepository longArticlesRootSourceIdRepository;
     @Autowired
     private PushMessageCallbackMapper pushMessageCallbackMapper;
+    @Autowired
+    private ODPSManager odpsManager;
+    @Autowired
+    private ArticleService articleService;
 
     @ApolloJsonValue("${touliu.account.ghIds:[\"gh_93e00e187787\", \"gh_ac43e43b253b\", \"gh_68e7fdc09fe4\",\"gh_77f36c109fb1\", \"gh_b181786a6c8c\", \"gh_1ee2e1b39ccf\"]}")
     private List<String> touliuAccountGhIds;
@@ -327,4 +332,75 @@ public class XxlJobService {
         }
         return ReturnT.SUCCESS;
     }
+
+    @XxlJob("delPushMessageCallbackJob")
+    public ReturnT<String> delPushMessageCallbackJob(String param) {
+        Calendar calendar = Calendar.getInstance();
+        Long beforeDayStart = DateUtils.getBeforeDayStart(7);
+        Date startDay = new Date(beforeDayStart * 1000);
+        if (StringUtils.hasText(param)) {
+            startDay = DateUtils.getDate(param);
+        }
+        for (int i = 0; i < 30; i++) {
+            // 计算当前遍历日期
+            Date currentStartDate = (Date) startDay.clone();
+            calendar.setTime(currentStartDate);
+            calendar.add(Calendar.DAY_OF_MONTH, -i); // 向前推i天
+
+            // 生成开始时间和结束时间
+            Date startTime = calendar.getTime(); // 开始时间
+            calendar.set(Calendar.HOUR_OF_DAY, 23);
+            calendar.set(Calendar.MINUTE, 59);
+            calendar.set(Calendar.SECOND, 59);
+            Date endTime = calendar.getTime(); // 结束时间
+
+            PushMessageCallbackExample example = new PushMessageCallbackExample();
+            example.createCriteria().andCreateTimeBetween(startTime, endTime);
+            long mysqlCount = pushMessageCallbackMapper.countByExample(example);
+            if (mysqlCount == 0) {
+                break;
+            }
+            String pt = DateUtils.getDateString(startTime.getTime());
+            String sql = String.format("SELECT count(*) FROM push_message_callback WHERE pt = %s;", pt);
+            List<Record> recordList = odpsManager.query(sql);
+            if (CollectionUtil.isEmpty(recordList)) {
+                LarkRobotUtil.sendMessage("查询hive失败" + pt);
+                return ReturnT.FAIL;
+            }
+            Long hiveCount = recordList.get(0).getBigint(0);
+            if (Math.abs(mysqlCount - hiveCount) > 0) {
+                LarkRobotUtil.sendMessage("数量异常" + pt + "\n mysql数量:" + mysqlCount + "\n hive数量:" + hiveCount);
+                return ReturnT.FAIL;
+            }
+            pushMessageCallbackMapper.deleteByExample(example);
+        }
+        return ReturnT.SUCCESS;
+    }
+
+
+    @XxlJob("syncArticleRootPublishId")
+    public ReturnT<String> syncArticleRootPublishId(String param) {
+        ArticleFindSourceParam findSourceParam = new ArticleFindSourceParam();
+        findSourceParam.setDateStr(param);
+        articleService.findSource(findSourceParam);
+        return ReturnT.SUCCESS;
+    }
+
+    @XxlJob("articlePromotionTraceability")
+    public ReturnT<String> articlePromotionTraceability(String channelContentId) {
+        articleService.articlePromotionTraceability(channelContentId);
+        return ReturnT.SUCCESS;
+    }
+
+    @XxlJob("articleCategoryJob")
+    public ReturnT<String> articleCategoryJob(String param) {
+        articleService.articleCategory();
+        return ReturnT.SUCCESS;
+    }
+
+    @XxlJob("articleCategoryJobRetry")
+    public ReturnT<String> articleCategoryJobRetry(String param) {
+        articleService.articleCategoryJobRetry();
+        return ReturnT.SUCCESS;
+    }
 }

+ 17 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/exterior/GhDetailService.java

@@ -0,0 +1,17 @@
+package com.tzld.longarticle.recommend.server.service.exterior;
+
+import com.tzld.longarticle.recommend.server.common.response.CommonResponse;
+import com.tzld.longarticle.recommend.server.model.vo.GhDetailVo;
+import com.tzld.longarticle.recommend.server.repository.model.GhDetail;
+import com.tzld.longarticle.recommend.server.util.page.Page;
+
+public interface GhDetailService {
+
+    CommonResponse<Page<GhDetailVo>> getGhDetailList(Integer pageNum, Integer pageSize, String accountId);
+
+    CommonResponse<Void> addGhDetail(GhDetailVo ghDetailVo);
+
+    CommonResponse<Void> updateDetail(GhDetailVo ghDetailVo);
+
+    CommonResponse<Void> refreshGhDetail();
+}

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

@@ -4,6 +4,7 @@ import com.tzld.longarticle.recommend.server.common.response.CommonResponse;
 import com.tzld.longarticle.recommend.server.model.param.CallbackParam;
 import com.tzld.longarticle.recommend.server.model.param.PushMessageParam;
 import com.tzld.longarticle.recommend.server.model.vo.PushMessageVo;
+import com.tzld.longarticle.recommend.server.model.vo.ReportUvVo;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
@@ -11,4 +12,7 @@ import java.util.List;
 @Service
 public interface ThirdPartyService {
     CommonResponse<List<PushMessageVo>> getPushMessage(PushMessageParam param);
+
+
+    CommonResponse<List<ReportUvVo>> getReportUv(String date, String accessToken);
 }

+ 139 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/exterior/impl/GhDetailServiceImpl.java

@@ -0,0 +1,139 @@
+package com.tzld.longarticle.recommend.server.service.exterior.impl;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.tzld.longarticle.recommend.server.common.enums.GhTypeEnum;
+import com.tzld.longarticle.recommend.server.common.response.CommonResponse;
+import com.tzld.longarticle.recommend.server.mapper.growth.GhDetailMapper;
+import com.tzld.longarticle.recommend.server.model.vo.GhDetailVo;
+import com.tzld.longarticle.recommend.server.repository.model.GhDetail;
+import com.tzld.longarticle.recommend.server.repository.model.GhDetailExample;
+import com.tzld.longarticle.recommend.server.service.exterior.GhDetailService;
+import com.tzld.longarticle.recommend.server.util.page.Page;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.reactive.function.client.WebClient;
+import reactor.core.publisher.Mono;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Slf4j
+@Service
+public class GhDetailServiceImpl implements GhDetailService {
+
+    @Autowired
+    private GhDetailMapper ghDetailMapper;
+
+    @Override
+    public CommonResponse<Page<GhDetailVo>> getGhDetailList(Integer pageNum, Integer pageSize, String accountId) {
+        if (pageNum == null) {
+            pageNum = 1;
+        }
+        if (pageSize == null) {
+            pageSize = 20;
+        }
+        if (pageSize > 100) {
+            pageSize = 100;
+        }
+        Page<GhDetailVo> page = new Page<>();
+        page.setCurrentPage(pageNum);
+        page.setPageSize(pageSize);
+        GhDetailExample example = new GhDetailExample();
+        if (StringUtils.isNotEmpty(accountId)) {
+            example.createCriteria().andGhIdEqualTo(accountId);
+        }
+        example.setPage(page);
+        long total = ghDetailMapper.countByExample(example);
+        int totalSize = (int) (total % pageSize == 0 ? (total / pageSize) : (total / pageSize + 1));
+        page.setTotalSize(totalSize);
+        List<GhDetail> ghDetails = ghDetailMapper.selectByExample(example);
+        List<GhDetailVo> ghDetailVos = new ArrayList<>();
+        if (!CollectionUtils.isEmpty(ghDetails)) {
+            for (GhDetail ghDetail : ghDetails) {
+                GhDetailVo ghDetailVo = new GhDetailVo();
+                BeanUtils.copyProperties(ghDetail, ghDetailVo);
+                ghDetailVo.setAccountId(ghDetail.getGhId());
+                ghDetailVo.setAccountName(ghDetail.getGhName());
+                ghDetailVo.setTypeName(GhTypeEnum.getTypeName(ghDetailVo.getType()));
+                ghDetailVos.add(ghDetailVo);
+            }
+        }
+        page.setObjs(ghDetailVos);
+        return CommonResponse.success(page);
+    }
+
+    @Override
+    public CommonResponse<Void> addGhDetail(GhDetailVo ghDetailVo) {
+        if (ghDetailVo == null
+                || StringUtils.isEmpty(ghDetailVo.getAccountId())
+                || StringUtils.isEmpty(ghDetailVo.getAccountName())
+                || ghDetailVo.getType() == null
+                || StringUtils.isEmpty(ghDetailVo.getCategory1())) {
+            return CommonResponse.create(500, "参数错误");
+        }
+
+        try {
+            GhDetail ghDetail = new GhDetail();
+            BeanUtils.copyProperties(ghDetailVo, ghDetail);
+            ghDetail.setGhId(ghDetailVo.getAccountId());
+            ghDetail.setGhName(ghDetailVo.getAccountName());
+            ghDetailMapper.insert(ghDetail);
+            return CommonResponse.success();
+        } catch (Exception e) {
+            log.error("addGhDetail error", e);
+        }
+        return CommonResponse.create(500, "插入失败,可能已经存在该记录");
+    }
+
+    @Override
+    public CommonResponse<Void> updateDetail(GhDetailVo ghDetailVo) {
+        try {
+            GhDetail ghDetail = new GhDetail();
+            BeanUtils.copyProperties(ghDetailVo, ghDetail);
+            ghDetail.setGhId(ghDetailVo.getAccountId());
+            ghDetail.setGhName(ghDetailVo.getAccountName());
+            ghDetailMapper.updateByPrimaryKeySelective(ghDetail);
+            return CommonResponse.success();
+        } catch (Exception e) {
+            log.error("updateDetail error", e);
+        }
+        return CommonResponse.create(500, "修改失败");
+    }
+
+    @Override
+    public CommonResponse<Void> refreshGhDetail() {
+        GhDetailExample example = new GhDetailExample();
+        example.createCriteria().andTypeEqualTo(1);
+        List<GhDetail> ghDetails = ghDetailMapper.selectByExample(example);
+        if (CollectionUtils.isEmpty(ghDetails)) {
+            return CommonResponse.success();
+        }
+        for (GhDetail ghDetail : ghDetails) {
+            getGhDetail(ghDetail);
+            log.info("getGhDetail = {}", ghDetail);
+            ghDetailMapper.updateByPrimaryKeySelective(ghDetail);
+        }
+        return CommonResponse.success();
+    }
+
+    public void getGhDetail(GhDetail ghDetail) {
+        String baseUrl = "http://aigc-api.cybertogether.net";
+        WebClient webClient = WebClient.builder()
+                .baseUrl(baseUrl)
+                .build();
+        Mono<String> mono = webClient.get()
+                .uri(String.format("/aigc/publish/account/algorithm/wechat/list?gh_id=%s", ghDetail.getGhId()))
+                .retrieve().bodyToMono(String.class);
+        String block = mono.block();
+        JSONArray jsonArray = JSONArray.parseArray(block);
+        if (jsonArray != null && !jsonArray.isEmpty()) {
+            JSONObject jsonObject = jsonArray.getJSONObject(0);
+            ghDetail.setGhName(jsonObject.getString("name"));
+        }
+    }
+}

+ 50 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/exterior/impl/ThirdPartyServiceImpl.java

@@ -1,6 +1,8 @@
 package com.tzld.longarticle.recommend.server.service.exterior.impl;
 
 import com.alibaba.fastjson.JSON;
+import com.aliyun.odps.data.Record;
+import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue;
 import com.tzld.longarticle.recommend.server.common.enums.SecretEnum;
 import com.tzld.longarticle.recommend.server.common.enums.cgi.ReplyStrategyServiceEnum;
 import com.tzld.longarticle.recommend.server.common.response.CommonResponse;
@@ -12,9 +14,12 @@ import com.tzld.longarticle.recommend.server.model.cgi.MsgData;
 import com.tzld.longarticle.recommend.server.model.cgi.ReplyBucketData;
 import com.tzld.longarticle.recommend.server.model.param.PushMessageParam;
 import com.tzld.longarticle.recommend.server.model.vo.PushMessageVo;
+import com.tzld.longarticle.recommend.server.model.vo.ReportUvVo;
 import com.tzld.longarticle.recommend.server.service.exterior.AccessTokenService;
 import com.tzld.longarticle.recommend.server.service.exterior.ThirdPartyService;
 import com.tzld.longarticle.recommend.server.service.strategy.reply.ReplyStrategyService;
+import com.tzld.longarticle.recommend.server.util.DateUtils;
+import lombok.Data;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.BeanUtils;
@@ -22,6 +27,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.ApplicationContext;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
+import com.tzld.longarticle.recommend.server.remote.ODPSManager;
 
 import javax.annotation.PostConstruct;
 import java.util.ArrayList;
@@ -38,6 +44,12 @@ public class ThirdPartyServiceImpl implements ThirdPartyService {
     @Autowired
     private AccessTokenService accessTokenService;
 
+    @Autowired
+    private ODPSManager odpsManager;
+
+    @ApolloJsonValue("${canViewReportDate:2024-10-31}")
+    private String canViewReportDate;
+
     private Map<String, ReplyStrategyService> strategyServiceMap;
 
     @PostConstruct
@@ -85,6 +97,44 @@ public class ThirdPartyServiceImpl implements ThirdPartyService {
         return CommonResponse.success(pushMessageVoList);
     }
 
+    @Override
+    public CommonResponse<List<ReportUvVo>> getReportUv(String date, String accessToken) {
+        if (StringUtils.isEmpty(date) || !DateUtils.isValidDate(date) || StringUtils.isEmpty(accessToken)) {
+            return CommonResponse.create(ExceptionCodeEnum.PARAM_ERROR, "参数错误");
+        }
+        if (!accessTokenService.validateAccessToken(accessToken)) {
+            return CommonResponse.create(ExceptionCodeEnum.PARAM_ERROR, "accessToken错误或者已失效");
+        }
+        SecretEnum secretEnum = accessTokenService.getSecretEnum(accessToken);
+        if (secretEnum == null) {
+            return CommonResponse.create(ExceptionCodeEnum.PARAM_ERROR, "获取secret失败");
+        }
+        if (!DateUtils.isValidDate(canViewReportDate)) {
+            return CommonResponse.create(ExceptionCodeEnum.PARAM_ERROR, "系统异常");
+        }
+        String channel = secretEnum.channel;
+        long targetTime = DateUtils.dateStrToTimestamp(date, "yyyy-MM-dd");
+        long limitTime = DateUtils.dateStrToTimestamp(canViewReportDate, "yyyy-MM-dd");
+        if (targetTime > limitTime) {
+            return CommonResponse.create(500, "数据不存在");
+        }
+        String dt = date.replace("-", "").substring(0, 8);
+        String sql = String.format("SELECT * FROM alg_growth_3rd_gh_reply_uv_report WHERE dt = %s AND channel = '%s';",
+                dt, channel);
+        List<ReportUvVo> res = new ArrayList<>();
+        List<Record> recordList = odpsManager.query(sql);
+        if (CollectionUtils.isEmpty(recordList)) {
+            return CommonResponse.success(res);
+        }
+        for (Record record : recordList) {
+            ReportUvVo reportUvVo = new ReportUvVo();
+            reportUvVo.setGhId(record.getString(0));
+            reportUvVo.setUv(record.getBigint(1));
+            res.add(reportUvVo);
+        }
+        return CommonResponse.success(res);
+    }
+
     private ReplyBucketData getPushMessageData(PushMessageParam param, String channel) {
         log.info("strategyServiceMap={}", JSON.toJSONString(strategyServiceMap));
         for (Map.Entry<String, ReplyStrategyService> stringReplyStrategyServiceEntry : strategyServiceMap.entrySet()) {

+ 1 - 1
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/exterior/impl/WeComServiceImpl.java

@@ -4,7 +4,7 @@ import com.alibaba.fastjson.JSON;
 import com.tzld.longarticle.recommend.server.common.enums.cgi.ReplyStrategyServiceEnum;
 import com.tzld.longarticle.recommend.server.common.response.CommonResponse;
 import com.tzld.longarticle.recommend.server.common.response.ExceptionCodeEnum;
-import com.tzld.longarticle.recommend.server.mapper.crawler.ReplyStaffMapper;
+import com.tzld.longarticle.recommend.server.mapper.growth.ReplyStaffMapper;
 import com.tzld.longarticle.recommend.server.model.cgi.BucketDataParam;
 import com.tzld.longarticle.recommend.server.model.cgi.GroupData;
 import com.tzld.longarticle.recommend.server.model.cgi.MsgData;

+ 476 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/ArticleService.java

@@ -0,0 +1,476 @@
+package com.tzld.longarticle.recommend.server.service.recommend;
+
+import com.alibaba.fastjson.JSONObject;
+import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue;
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import com.tzld.longarticle.recommend.server.common.CommonThreadPoolExecutor;
+import com.tzld.longarticle.recommend.server.common.enums.StatusEnum;
+import com.tzld.longarticle.recommend.server.common.enums.aigc.PublishContentTypeEnum;
+import com.tzld.longarticle.recommend.server.common.enums.recommend.ArticleCategoryStatusEnum;
+import com.tzld.longarticle.recommend.server.common.enums.recommend.ArticlePoolPromotionSourceStatusEnum;
+import com.tzld.longarticle.recommend.server.mapper.aigc.AigcBaseMapper;
+import com.tzld.longarticle.recommend.server.mapper.crawler.CrawlerBaseMapper;
+import com.tzld.longarticle.recommend.server.mapper.longArticle.LongArticleBaseMapper;
+import com.tzld.longarticle.recommend.server.model.dto.CrawlerContent;
+import com.tzld.longarticle.recommend.server.model.dto.kimi.KimiResult;
+import com.tzld.longarticle.recommend.server.model.entity.aigc.PublishAccount;
+import com.tzld.longarticle.recommend.server.model.entity.aigc.PublishContent;
+import com.tzld.longarticle.recommend.server.model.entity.aigc.PublishContentOutput;
+import com.tzld.longarticle.recommend.server.model.entity.crawler.Article;
+import com.tzld.longarticle.recommend.server.model.entity.longArticle.ArticleCategory;
+import com.tzld.longarticle.recommend.server.model.entity.longArticle.ArticleCrawlerPlan;
+import com.tzld.longarticle.recommend.server.model.entity.longArticle.ArticlePoolPromotionSource;
+import com.tzld.longarticle.recommend.server.model.param.ArticleFindSourceParam;
+import com.tzld.longarticle.recommend.server.model.vo.ProduceContentCrawlerVO;
+import com.tzld.longarticle.recommend.server.model.vo.RootPublishContentVO;
+import com.tzld.longarticle.recommend.server.remote.CrawlerContentByPlanService;
+import com.tzld.longarticle.recommend.server.remote.KimiApiService;
+import com.tzld.longarticle.recommend.server.repository.aigc.PublishAccountRepository;
+import com.tzld.longarticle.recommend.server.repository.aigc.PublishContentOutputRepository;
+import com.tzld.longarticle.recommend.server.repository.crawler.AccountAvgInfoRepository;
+import com.tzld.longarticle.recommend.server.repository.crawler.ArticleRepository;
+import com.tzld.longarticle.recommend.server.repository.longArticle.ArticleCategoryRepository;
+import com.tzld.longarticle.recommend.server.repository.longArticle.ArticleCrawlerPlanRepository;
+import com.tzld.longarticle.recommend.server.repository.longArticle.ArticlePoolPromotionSourceRepository;
+import com.tzld.longarticle.recommend.server.service.recommend.config.AccountIndexAvgViewCountService;
+import com.tzld.longarticle.recommend.server.util.DateUtils;
+import com.tzld.longarticle.recommend.server.util.Md5Util;
+import com.tzld.longarticle.recommend.server.util.TitleSimilarCheckUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author dyp
+ */
+@Service
+@Slf4j
+public class ArticleService {
+
+    @Autowired
+    AccountIndexAvgViewCountService accountIndexAvgViewCountService;
+    @Autowired
+    AccountAvgInfoRepository accountAvgInfoRepository;
+    @Autowired
+    ArticleRepository articleRepository;
+    @Autowired
+    PublishContentOutputRepository publishContentOutputRepository;
+    @Autowired
+    PublishAccountRepository publishAccountRepository;
+    @Autowired
+    AigcBaseMapper aigcBaseMapper;
+    @Autowired
+    CrawlerBaseMapper crawlerBaseMapper;
+    @Autowired
+    LongArticleBaseMapper longArticleBaseMapper;
+    @Autowired
+    ArticlePoolPromotionSourceRepository articlePoolPromotionSourceRepository;
+    @Autowired
+    ArticleCrawlerPlanRepository articleCrawlerPlanRepository;
+    @Autowired
+    ArticleCategoryRepository articleCategoryRepository;
+    @Autowired
+    CrawlerContentByPlanService crawlerContentByPlanService;
+    @Autowired
+    KimiApiService kimiApiService;
+
+    @ApolloJsonValue("${cold.pool.produce.planId:[\"20240802021606053813696\", \"20240802080355355308981\",\n" +
+            "\"20240805154433785506170\", \"20240805154359027876170\", \"20241024100016206421084\", " +
+            "\"20241030070010871546586\"]}")
+    private static List<String> producePlanIds;
+
+    private final static ExecutorService pool = new CommonThreadPoolExecutor(
+            32,
+            128,
+            0L, TimeUnit.SECONDS,
+            new LinkedBlockingQueue<>(1000),
+            new ThreadFactoryBuilder().setNameFormat("DEFAULT-%d").build(),
+            new ThreadPoolExecutor.AbortPolicy());
+
+    public void findSource(ArticleFindSourceParam param) {
+        if (StringUtils.hasText(param.getWxSn())) {
+            syncAigcIdByWxSn(param.getWxSn());
+            return;
+        }
+        long minUpdateTimestamp;
+        if (StringUtils.hasText(param.getDateStr())) {
+            minUpdateTimestamp = DateUtils.dateStrToTimestamp(param.getDateStr(), "yyyyMMdd") - 86400 * 7;
+        } else {
+            minUpdateTimestamp = DateUtils.getTodayStart() - 86400 * 7;
+        }
+        while (true) {
+            List<Article> articleList = crawlerBaseMapper.getWaitingFindArticle(minUpdateTimestamp);
+            if (CollectionUtils.isEmpty(articleList)) {
+                return;
+            }
+            CountDownLatch cdl = new CountDownLatch(articleList.size());
+            for (Article article : articleList) {
+                pool.execute(() -> {
+                    try {
+                        syncAigcIdByWxSn(article.getWxSn());
+                    } finally {
+                        cdl.countDown();
+                    }
+                });
+                minUpdateTimestamp = minUpdateTimestamp > article.getUpdateTime() ? minUpdateTimestamp : article.getUpdateTime();
+            }
+            try {
+                cdl.await();
+            } catch (Exception e) {
+                log.error("cdl error", e);
+            }
+            log.info("findSource timestamp:{}", minUpdateTimestamp);
+        }
+    }
+
+    private void syncAigcIdByWxSn(String wxSn) {
+        Article article = articleRepository.getByWxSn(wxSn);
+        String ghId = article.getGhId();
+        String title = article.getTitle();
+        Long publishTimestamp = article.getUpdateTime() * 1000;
+        PublishAccount publishAccount = publishAccountRepository.getByGhId(ghId);
+        List<PublishContent> publishContentList = aigcBaseMapper.getNearestPublishContent(publishAccount.getId(), publishTimestamp, 100);
+        if (CollectionUtils.isEmpty(publishContentList)) {
+            return;
+        }
+        String publishContentId = null;
+        String channelContentId = null;
+
+        PublishContent publishContent = findPublishContent(publishContentList, title, publishTimestamp);
+        if (Objects.nonNull(publishContent)) {
+            publishContentId = publishContent.getId();
+            channelContentId = publishContent.getCrawlerChannelContentId();
+        }
+        log.info("syncAigcIdByWxSn titleMatch finish");
+        if (Objects.isNull(channelContentId)) {
+            return;
+        }
+        // 更新 official_article_v2
+        crawlerBaseMapper.updateArticleAigcId(wxSn, publishContentId, channelContentId);
+        // 查找记录根记录
+        long start = System.currentTimeMillis();
+        RootPublishContentVO result = getRootPublishContent(channelContentId, null, publishContentId, null, 0);
+        log.info("syncAigcIdByWxSn getRootPublishContent finish cost:{}", System.currentTimeMillis() - start);
+        // 更新source root publish_content_id
+        crawlerBaseMapper.updateArticleSourceRootId(wxSn, result.getSourcePublishContentId(), result.getRootPublishContentId(),
+                result.getRootProduceContentId());
+    }
+
+    private PublishContent findPublishContent(List<PublishContent> publishContentList,
+                                              String title,
+                                              Long publishTimestamp) {
+        Map<String, PublishContent> publishContentMap = publishContentList.stream().collect(
+                Collectors.toMap(PublishContent::getId, publishContent -> publishContent));
+        List<String> publishContentIds = publishContentList.stream().map(PublishContent::getId).collect(Collectors.toList());
+        List<PublishContentOutput> publishContentOutputList = publishContentOutputRepository.
+                getByPublishContentIdInAndContentTypeAndSelectStatus(publishContentIds, PublishContentTypeEnum.title.getVal(), 1);
+        Map<String, List<PublishContentOutput>> publishContentOutputMap = publishContentOutputList.stream().collect(
+                Collectors.groupingBy(PublishContentOutput::getOutput));
+        List<String> titles = publishContentOutputList.stream().map(PublishContentOutput::getOutput).collect(Collectors.toList());
+        PublishContent publishContent = null;
+        if (titles.contains(title)) {
+            publishContent = getPublishContentByTitle(publishContentOutputMap, publishContentMap, title,
+                    publishTimestamp);
+        } else {
+            for (String aTitle : titles) {
+                if (TitleSimilarCheckUtil.isSimilar(title, aTitle, TitleSimilarCheckUtil.SIMILARITY_THRESHOLD)) {
+                    publishContent = getPublishContentByTitle(publishContentOutputMap, publishContentMap, aTitle,
+                            publishTimestamp);
+                    break;
+                }
+            }
+        }
+        return publishContent;
+    }
+
+    private PublishContent getPublishContentByTitle(Map<String, List<PublishContentOutput>> publishContentOutputMap,
+                                                    Map<String, PublishContent> publishContentMap,
+                                                    String title,
+                                                    Long publishTimestamp) {
+        List<PublishContentOutput> outputList = publishContentOutputMap.get(title);
+        List<PublishContent> publishContents = outputList.stream().map(o -> publishContentMap.get(o.getPublishContentId()))
+                .collect(Collectors.toList());
+        return getNearestContent(publishContents, publishTimestamp);
+    }
+
+    private PublishContent getNearestContent(List<PublishContent> publishContents, Long publishTimestamp) {
+        if (publishContents.size() == 1) {
+            return publishContents.get(0);
+        }
+        PublishContent result = null;
+        Long nearest = 0L;
+        for (PublishContent publishContent : publishContents) {
+            Long timestamp = publishContent.getPublishTimestamp();
+            if (Objects.isNull(result)) {
+                result = publishContent;
+                nearest = timestamp;
+                continue;
+            }
+            if (Math.abs(timestamp - publishTimestamp) < Math.abs(nearest - publishTimestamp)) {
+                result = publishContent;
+                nearest = timestamp;
+            }
+        }
+        return result;
+    }
+
+    public RootPublishContentVO getRootPublishContent(String channelContentId,
+                                                      String sourcePublishContentId,
+                                                      String rootPublishContentId,
+                                                      String rootProduceContentId,
+                                                      int times) {
+        RootPublishContentVO result = new RootPublishContentVO();
+        result.setChannelContentId(channelContentId);
+        result.setSourcePublishContentId(sourcePublishContentId);
+        result.setRootPublishContentId(rootPublishContentId);
+        result.setRootProduceContentId(rootProduceContentId);
+        if (times > 20) {
+            return result;
+        }
+        CrawlerContent crawlerContent = aigcBaseMapper.getCrawlerContentByChannelContentId(channelContentId);
+        if (Objects.isNull(crawlerContent) || !StringUtils.hasText(crawlerContent.getGhId())) {
+            return result;
+        }
+        PublishAccount publishAccount = publishAccountRepository.getByGhId(crawlerContent.getGhId());
+        if (Objects.isNull(publishAccount)) {
+            return result;
+        }
+        String title = crawlerContent.getTitle();
+        Long publishTimestamp = crawlerContent.getPublishTimestamp();
+        List<PublishContent> publishContentList = aigcBaseMapper.getNearestPublishContent(publishAccount.getId(), publishTimestamp, 100);
+        if (CollectionUtils.isEmpty(publishContentList)) {
+            return result;
+        }
+        PublishContent publishContent = findPublishContent(publishContentList, title, publishTimestamp);
+        if (Objects.nonNull(publishContent)) {
+            if (!StringUtils.hasText(sourcePublishContentId)) {
+                result.setSourcePublishContentId(publishContent.getId());
+            }
+            result.setRootPublishContentId(publishContent.getId());
+            result.setRootProduceContentId(publishContent.getSourceId());
+            channelContentId = publishContent.getCrawlerChannelContentId();
+        }
+        // channelContentId未被修改,说明未找到
+        if (channelContentId.equals(crawlerContent.getChannelContentId())) {
+            return result;
+        } else {
+            result = getRootPublishContent(channelContentId, result.getSourcePublishContentId(),
+                    result.getRootPublishContentId(), result.getRootProduceContentId(), ++times);
+            if (!channelContentId.equals(result.getChannelContentId())) {
+                result.getMidChannelContentIds().add(channelContentId);
+            }
+            return result;
+        }
+    }
+
+    public void articlePromotionTraceability(String channelContentId) {
+        // 查找待处理任务
+        List<ArticlePoolPromotionSource> tasks = new ArrayList<>();
+        if (StringUtils.hasText(channelContentId)) {
+            ArticlePoolPromotionSource item = articlePoolPromotionSourceRepository.getByChannelContentId(channelContentId);
+            tasks.add(item);
+        } else {
+            tasks = articlePoolPromotionSourceRepository.getByStatusAndDeleted(0, 0);
+        }
+        long now = System.currentTimeMillis();
+        for (ArticlePoolPromotionSource task : tasks) {
+            // 溯源
+            Article article = articleRepository.getByWxSn(task.getWxSn());
+            if (Objects.isNull(article)) {
+                task.setDeleted(StatusEnum.ONE.getCode());
+                articlePoolPromotionSourceRepository.save(task);
+                continue;
+            }
+            PublishAccount publishAccount = publishAccountRepository.getByGhId(article.getGhId());
+            if (Objects.isNull(publishAccount)) {
+                continue;
+            }
+            long publishTimestamp = article.getPublishTimestamp() > 0 ? article.getPublishTimestamp() * 1000 : article.getUpdateTime() * 1000;
+            List<PublishContent> publishContentList = aigcBaseMapper.getNearestPublishContent(publishAccount.getId(), publishTimestamp, 100);
+            PublishContent publishContent = findPublishContent(publishContentList, task.getTitle(), publishTimestamp);
+            if (Objects.isNull(publishContent)) {
+                task.setDeleted(StatusEnum.ONE.getCode());
+                articlePoolPromotionSourceRepository.save(task);
+                continue;
+            }
+            RootPublishContentVO source = getRootPublishContent(publishContent.getCrawlerChannelContentId(), null, publishContent.getId(), null, 0);
+            // 更新
+            if (StringUtils.hasText(source.getRootProduceContentId())) {
+                task.setStatus(ArticlePoolPromotionSourceStatusEnum.FINISH.getCode());
+                task.setSourcePublishContentId(source.getSourcePublishContentId());
+                task.setRootProduceContentId(source.getRootProduceContentId());
+                task.setRootPublishContentId(source.getRootPublishContentId());
+                task.setUpdateTimestamp(now);
+                articlePoolPromotionSourceRepository.save(task);
+                // 保存中间环节 晋级溯源
+                for (String midChannelContentId : source.getMidChannelContentIds()) {
+                    ArticlePoolPromotionSource item = new ArticlePoolPromotionSource();
+                    BeanUtils.copyProperties(task, item);
+                    ArticlePoolPromotionSource dto = articlePoolPromotionSourceRepository.getByChannelContentId(midChannelContentId);
+                    if (Objects.nonNull(dto)) {
+                        // 以dto为基础
+                        dto.setRootProduceContentId(task.getRootProduceContentId());
+                        dto.setRootPublishContentId(task.getRootPublishContentId());
+                        dto.setStatus(task.getStatus());
+                        dto.setLevel(task.getLevel());
+                        dto.setUpdateTimestamp(task.getUpdateTimestamp());
+                        item = dto;
+                    } else {
+                        // 以新item为基础
+                        item.setChannelContentId(midChannelContentId);
+                        item.setCreateTimestamp(item.getUpdateTimestamp());
+                    }
+                    articlePoolPromotionSourceRepository.save(item);
+                }
+                longArticleBaseMapper.updateRootProduceContentLevel(task.getRootProduceContentId(), task.getLevel());
+            } else {
+                task.setDeleted(StatusEnum.ONE.getCode());
+                articlePoolPromotionSourceRepository.save(task);
+            }
+        }
+    }
+
+
+    public void articleCategory() {
+        List<ArticleCrawlerPlan> articleCrawlerPlanList = articleCrawlerPlanRepository.getByStatus(StatusEnum.ZERO.getCode());
+        for (ArticleCrawlerPlan crawlerPlan : articleCrawlerPlanList) {
+            List<ProduceContentCrawlerVO> list = crawlerContentByPlanService.getCrawlerContentByPlan(crawlerPlan.getCrawlerPlanId(), producePlanIds);
+            List<String> produceContentIds = list.stream().map(ProduceContentCrawlerVO::getProduceContentId).collect(Collectors.toList());
+            List<ArticleCategory> exists = articleCategoryRepository.getByProduceContentIdIn(produceContentIds);
+            List<String> existsIds = exists.stream().map(ArticleCategory::getProduceContentId).collect(Collectors.toList());
+            list = list.stream().filter(o -> !existsIds.contains(o.getProduceContentId())).collect(Collectors.toList());
+            long now = System.currentTimeMillis();
+            List<ArticleCategory> saveList = new ArrayList<>();
+            for (ProduceContentCrawlerVO vo : list) {
+                ArticleCategory item = new ArticleCategory();
+                item.setCrawlerPlanId(crawlerPlan.getCrawlerPlanId());
+                item.setChannelContentId(vo.getChannelContentId());
+                item.setProduceContentId(vo.getProduceContentId());
+                item.setTitle(vo.getTitle());
+                item.setTitleMd5(Md5Util.encoderByMd5(vo.getTitle()));
+                item.setCreateTimestamp(now);
+                saveList.add(item);
+            }
+            if (CollectionUtils.isNotEmpty(saveList)) {
+                longArticleBaseMapper.batchInsertArticleCategory(saveList);
+            }
+            // 抓取计划超过5天设置为已处理
+            String dateStr = crawlerPlan.getCrawlerPlanId().substring(0, 8);
+            if (DateUtils.dateStrToTimestamp(dateStr, "yyyyMMdd") < now - 86400 * 5) {
+                crawlerPlan.setStatus(StatusEnum.ONE.getCode());
+                crawlerPlan.setUpdateTimestamp(now);
+                articleCrawlerPlanRepository.save(crawlerPlan);
+            }
+        }
+        List<ArticleCategory> dealList = articleCategoryRepository.getByStatus(ArticleCategoryStatusEnum.WAITING.getCode());
+        List<List<ArticleCategory>> partitionList = Lists.partition(dealList, 20);
+        for (List<ArticleCategory> partition : partitionList) {
+            List<String> partitionTitles = partition.stream().map(ArticleCategory::getTitle).distinct().collect(Collectors.toList());
+            String prompt = buildKimiPrompt(partitionTitles);
+            KimiResult kimiResult = kimiApiService.requestOfficialApi(prompt, null, null);
+            long now = System.currentTimeMillis();
+            JSONObject obj = null;
+            if (kimiResult.isSuccess()) {
+                try {
+                    obj = JSONObject.parseObject(kimiResult.getResponse().getChoices().get(0).getMessage().getContent());
+                } catch (Exception e) {
+                    log.error(kimiResult.getResponse().getChoices().get(0).getMessage().getContent());
+                }
+            }
+            for (ArticleCategory articleCategory : partition) {
+                articleCategory.setKimiResult(kimiResult.getResponseStr());
+                articleCategory.setUpdateTimestamp(now);
+                if (kimiResult.isSuccess() && Objects.nonNull(obj) && obj.containsKey(articleCategory.getTitle())) {
+                    articleCategory.setCategory(obj.getString(articleCategory.getTitle()));
+                    articleCategory.setStatus(ArticleCategoryStatusEnum.SUCCESS.getCode());
+                } else {
+                    articleCategory.setStatus(ArticleCategoryStatusEnum.FAIL.getCode());
+                    articleCategory.setFailReason(kimiResult.getFailReason());
+                }
+                articleCategoryRepository.save(articleCategory);
+            }
+        }
+
+    }
+
+    private String buildKimiPrompt(List<String> titleList) {
+        StringBuilder prompt = new StringBuilder(
+                "请帮我完成以下任务:输入为文章的标题,根据标题判断其内容所属的类目,输出为文章标题及其对应的类目。\n" +
+                "类目需从以下范围内选择:\n" +
+                "奇闻趣事\n" +
+                "历史人物\n" +
+                "家长里短\n" +
+                "温情故事\n" +
+                "健康养生\n" +
+                "生活知识\n" +
+                "名人八卦\n" +
+                "政治新闻\n" +
+                "军事新闻\n" +
+                "为了更好地完成任务,可参考下列对文章标题的分类:\n" +
+                "{" +
+                "\"大舅病了,我取了三万元送过去,病房门口听到舅妈的话我改了主意\": \"家长里短\",\n" +
+                "\"能活到90岁的老人,基本上在70岁的时候,就不再做这些事了!\": \"健康养生\",\n" +
+                "\"去医院看望病人时,切忌带这4样东西,再亲近也不行,这是做人的根本\": \"生活知识\",\n" +
+                "\"上海一女子去饭店吃生煎包,戳了个洞想凉一凉,往里一看,瞬间惊呆了\": \"奇闻趣事\",\n" +
+                "\"卫生间放一把食盐,一年能省下好几百,涨新知识\": \"生活知识\",\n" +
+                "\"中国有一古寺,庙不大,却有武警24小时站岗,到底有何“过人”之处\": \"奇闻趣事\",\n" +
+                "\"1974年,苏联外长故意拿邓小平身高“取笑”,邓小平一句话轻松反击\": \"历史人物\",\n" +
+                "\"中国最美的女将军:上世纪曾家喻户晓,如今仍然健在\": \"历史人物\",\n" +
+                "\"北大才女蒙曼48岁仍未婚,被问最想嫁给谁,一个名字让全场笑喷\": \"名人八卦\",\n" +
+                "\"广东一老人去世,家人把老人的旧床垫扔了,环卫工人看到后,竟发现里面藏了15万元现金!家人傻眼了\": \"奇闻趣事\",\n" +
+                "}" +
+                "最后输出结果请用JSON格式输出,key为title,value为类目,仅输出JSON,不要markdown格式,不要任何其他内容," +
+                "并且内容可以被 fastJSON 的JSONObject.parseObject转换为JSON对象\n" +
+                "当标题的开头或结尾为以下字符时“”“,则在标题的开头或结尾增加\" " +
+                "输出结果格式如下:\n" +
+                "{" +
+                "\"浙江老人用“假钱”吃霸王餐9年,离世后,老板却崩溃大哭:“每天都在等他!”\": \"奇闻趣事\"," +
+                "\"“最美婴儿”迅速走红,像在娘胎里整过容,网友:看到第一眼就想抱回家\": \"奇闻趣事\"" +
+                "}" +
+                "以下是需要分析的文章标题列表,每一行是一个标题:\n");
+        for (String title : titleList) {
+            prompt.append(title).append("\n");
+        }
+        return prompt.toString();
+    }
+
+    public void articleCategoryJobRetry() {
+        List<ArticleCategory> dealList = articleCategoryRepository.getByStatusAndRetryTimesLessThan(ArticleCategoryStatusEnum.FAIL.getCode(), 3);
+        for (ArticleCategory articleCategory : dealList) {
+            List<String> partitionTitles = Collections.singletonList(articleCategory.getTitle());
+            String prompt = buildKimiPrompt(partitionTitles);
+            KimiResult kimiResult = kimiApiService.requestOfficialApi(prompt, null, null);
+            long now = System.currentTimeMillis();
+            JSONObject obj = null;
+            if (kimiResult.isSuccess()) {
+                try {
+                    obj = JSONObject.parseObject(kimiResult.getResponse().getChoices().get(0).getMessage().getContent());
+                } catch (Exception e) {
+                    log.error(kimiResult.getResponse().getChoices().get(0).getMessage().getContent());
+                }
+            }
+            articleCategory.setKimiResult(kimiResult.getResponseStr());
+            articleCategory.setUpdateTimestamp(now);
+            articleCategory.setRetryTimes(articleCategory.getRetryTimes() + 1);
+            if (kimiResult.isSuccess() && Objects.nonNull(obj)) {
+                List<String> keys = new ArrayList<>(obj.keySet());
+                String category = obj.getString(keys.get(0));
+                articleCategory.setCategory(category);
+                articleCategory.setStatus(ArticleCategoryStatusEnum.SUCCESS.getCode());
+                articleCategory.setFailReason(null);
+            } else {
+                articleCategory.setStatus(ArticleCategoryStatusEnum.FAIL.getCode());
+                articleCategory.setFailReason(kimiResult.getFailReason());
+            }
+            articleCategoryRepository.save(articleCategory);
+        }
+    }
+}

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

@@ -16,6 +16,7 @@ import com.tzld.longarticle.recommend.server.model.entity.crawler.AccountAvgInfo
 import com.tzld.longarticle.recommend.server.model.entity.crawler.Article;
 import com.tzld.longarticle.recommend.server.model.entity.crawler.ArticleDetailInfo;
 import com.tzld.longarticle.recommend.server.model.entity.crawler.PublishSortLog;
+import com.tzld.longarticle.recommend.server.model.entity.longArticle.DatastatScore;
 import com.tzld.longarticle.recommend.server.model.entity.longArticle.DatastatSortStrategy;
 import com.tzld.longarticle.recommend.server.model.param.MiniprogramTaskParam;
 import com.tzld.longarticle.recommend.server.model.param.PublishContentParam;
@@ -28,6 +29,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.repository.longArticle.DatastatScoreRepository;
 import com.tzld.longarticle.recommend.server.service.recommend.score.ScoreStrategy;
 import com.tzld.longarticle.recommend.server.util.DateUtils;
 import com.tzld.longarticle.recommend.server.util.MapBuilder;
@@ -75,6 +77,8 @@ public class DataDashboardService {
     private ProducePlanRepository producePlanRepository;
     @Autowired
     private ProducePlanInputSourceRepository producePlanInputSourceRepository;
+    @Autowired
+    private DatastatScoreRepository datastatScoreRepository;
 
     @ApolloJsonValue("${export.account.ghId:[]}")
     private static List<String> ghIdList;
@@ -189,6 +193,7 @@ public class DataDashboardService {
         }
         log.info("newSortStrategyData publishContents finish");
         Map<String, Map<String, Map<Long, PublishContent>>> publishContentMap = publishContents.stream()
+                .filter(o -> Objects.nonNull(o.getPublishTimestamp()))
                 .sorted(Comparator.comparingLong(PublishContent::getPublishTimestamp)).collect(
                         Collectors.groupingBy(PublishContent::getPublishAccountId,
                                 Collectors.groupingBy(PublishContent::getTitle,
@@ -873,13 +878,25 @@ public class DataDashboardService {
             list = list.stream().filter(publish -> publish.getPublishTimestamp() < (article.getPublishTimestamp() - 3600 * 8))
                     .collect(Collectors.toList());
             Integer poolLevel = getArticlePoolLevel(data.getGhId(), list, small);
+            // L1层仅统计历史发布在3-8位置文章
+            if (poolLevel > 1 && "L1".equals(item.getType())) {
+                continue;
+            }
             List<String> titles = titleTypeMap.computeIfAbsent(type, k -> new ArrayList<>());
             Map<Integer, List<String>> titlePoolMap = titleTypePoolMap.computeIfAbsent(type, k -> new HashMap<>());
             List<String> poolTitles = titlePoolMap.computeIfAbsent(poolLevel, k -> new ArrayList<>());
 
+            AccountAvgInfo accountAvgInfo = getAccountAvgInfo(accountAvgInfoIndexMap, article.getGhId(),
+                    article.getUpdateTime(), article.getItemIndex());
+//            // L4层仅统计 稳定-大和稳定
+//            if ("L4".equals(item.getType()) && (Objects.isNull(accountAvgInfo)
+//                    || !StringUtils.hasText(accountAvgInfo.getAccountStatus())
+//                    || !accountAvgInfo.getAccountStatus().contains("稳定"))) {
+//                continue;
+//            }
             // 发布情况
             setPublishSituation(item, type, titleTypeMap, titleTypePoolMap, poolLevel, article, fansAccountTypeMap,
-                    accountAvgInfoIndexMap);
+                    accountAvgInfo);
             // 发布表现
             setPublishPerformance(item, data, publishSortLogMap);
             // 发布依赖表现
@@ -1215,7 +1232,7 @@ public class DataDashboardService {
     private void setPublishSituation(IntermediateIndicatorsExport item, String type, Map<String, List<String>> titleTypeMap,
                                      Map<String, Map<Integer, List<String>>> titleTypePoolMap, Integer poolLevel,
                                      Article article, Map<String, List<String>> fansAccountTypeMap,
-                                     Map<String, Map<String, Map<String, AccountAvgInfo>>> accountAvgInfoIndexMap) {
+                                     AccountAvgInfo accountAvgInfo) {
         item.setArticleReleaseSlot(item.getArticleReleaseSlot() + 1);
         item.setActualArticleReleaseCount(item.getActualArticleReleaseCount() + 1);
         if (titleTypeMap.containsKey(type) && !titleTypeMap.get(type).contains(article.getTitle())) {
@@ -1225,8 +1242,6 @@ public class DataDashboardService {
         List<String> ghIds = fansAccountTypeMap.computeIfAbsent(type, k -> new ArrayList<>());
         if (!ghIds.contains(article.getGhId())) {
             ghIds.add(article.getGhId());
-            AccountAvgInfo accountAvgInfo = getAccountAvgInfo(accountAvgInfoIndexMap, article.getGhId(),
-                    article.getPublishTimestamp(), article.getItemIndex());
             if (Objects.nonNull(accountAvgInfo)) {
                 item.setFansCount(item.getFansCount() + accountAvgInfo.getFans());
             }
@@ -1346,7 +1361,6 @@ public class DataDashboardService {
 
         List<Pair<String, String>> styles = Arrays
                 .asList(
-                        Pair.of("F", "#,##0.00"),
                         Pair.of("G", "#,##0.00"),
                         Pair.of("H", "#,##0.00"),
                         Pair.of("I", "#,##0.00"),
@@ -1358,7 +1372,8 @@ public class DataDashboardService {
                         Pair.of("O", "#,##0.00"),
                         Pair.of("P", "#,##0.00"),
                         Pair.of("Q", "#,##0.00"),
-                        Pair.of("T", "#,##0.00")
+                        Pair.of("R", "#,##0.00"),
+                        Pair.of("U", "#,##0.00")
                 );
 
         doSendFeishuSheet(dateStrList, sheetToken, sheetId, rowNum, rows, 2, styles);
@@ -1367,16 +1382,16 @@ public class DataDashboardService {
     private List<FirstContentScoreExport> firstContentScoreData(List<String> dateStrList) {
         List<FirstContentScoreExport> result = new ArrayList<>();
         List<PublishSortLog> sortLogList = publishSortLogRepository.findByDateStrIn(dateStrList);
-        sortLogList = sortLogList.stream().filter(o -> o.getIndex() == 1).collect(Collectors.toList());
+        sortLogList = sortLogList.stream().filter(o -> o.getIndex() == 1 || o.getIndex() == 2).collect(Collectors.toList());
         sortLogList.sort(Comparator.comparing(PublishSortLog::getGhId).thenComparing(PublishSortLog::getDateStr));
         List<String> ghIds = sortLogList.stream().map(PublishSortLog::getGhId).distinct().collect(Collectors.toList());
         long minTimestamp = DateUtils.dateStrToTimestamp(dateStrList.get(0), "yyyyMMdd");
         List<Article> articleList = articleRepository.getByGhIdInAndPublishTimestampGreaterThanAndTypeEquals(ghIds, minTimestamp, ArticleTypeEnum.QUNFA.getVal());
-        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.getPublishTimestamp(), "yyyyMMdd"), o -> o,
-                        (existing, replacement) -> replacement)));
+        articleList = articleList.stream().filter(o -> o.getItemIndex() == 1 || o.getItemIndex() == 2).collect(Collectors.toList());
+        Map<String, Map<String, Map<Integer, Article>>> articleMap = articleList.stream().collect(
+                Collectors.groupingBy(Article::getGhId, Collectors.groupingBy(o -> DateUtils.timestampToYMDStr(o.getUpdateTime(), "yyyyMMdd"),
+                        Collectors.toMap(Article::getItemIndex, o -> o,
+                                (existing, replacement) -> replacement))));
         List<String> titleList = articleList.stream().map(Article::getTitle).distinct().collect(Collectors.toList());
         List<PublishContent> hisPublishList = new ArrayList<>();
         for (List<String> partitions : Lists.partition(new ArrayList<>(titleList), 100)) {
@@ -1385,17 +1400,23 @@ public class DataDashboardService {
         Map<String, List<PublishContent>> hisPublishMap = hisPublishList.stream().collect(Collectors.groupingBy(PublishContent::getTitle));
         String ymd = DateUtils.timestampToYMDStr(minTimestamp - 86400 * 7, "yyyy-MM-dd");
         List<AccountAvgInfo> accountAvgInfoList = accountAvgInfoRepository.getAllByUpdateTimeGreaterThanEqual(ymd);
-        Map<String, Map<String, AccountAvgInfo>> accountAvgInfoMap = accountAvgInfoList.stream()
-                .filter(o -> Objects.equals(o.getPosition(), "1")).collect(Collectors.groupingBy(AccountAvgInfo::getGhId,
-                        Collectors.toMap(AccountAvgInfo::getUpdateTime, o -> o)));
+        Map<String, Map<String, Map<String, AccountAvgInfo>>> accountAvgInfoMap = accountAvgInfoList.stream()
+                .filter(o -> Objects.equals(o.getPosition(), "1") || Objects.equals(o.getPosition(), "2"))
+                .collect(Collectors.groupingBy(AccountAvgInfo::getGhId,
+                        Collectors.groupingBy(AccountAvgInfo::getUpdateTime,
+                                Collectors.toMap(AccountAvgInfo::getPosition, o -> o))));
 
         String title = "";
         for (PublishSortLog publishSortLog : sortLogList) {
-            Map<String, Article> dateArticleMap = articleMap.get(publishSortLog.getGhId());
+            Map<String, Map<Integer, Article>> dateArticleMap = articleMap.get(publishSortLog.getGhId());
             if (Objects.isNull(dateArticleMap)) {
                 continue;
             }
-            Article article = dateArticleMap.get(publishSortLog.getDateStr());
+            Map<Integer, Article> indexMap = dateArticleMap.get(publishSortLog.getDateStr());
+            if (Objects.isNull(indexMap)) {
+                continue;
+            }
+            Article article = indexMap.get(publishSortLog.getIndex());
             if (Objects.isNull(article) || !publishSortLog.getTitle().equals(article.getTitle())) {
                 continue;
             }
@@ -1407,6 +1428,7 @@ public class DataDashboardService {
             item.setDateStr(publishSortLog.getDateStr());
             item.setGhId(publishSortLog.getGhId());
             item.setAccountName(publishSortLog.getAccountName());
+            item.setIndex(publishSortLog.getIndex());
             item.setTitle(publishSortLog.getTitle());
             item.setStrategy(publishSortLog.getStrategy());
             item.setScore(Double.valueOf(publishSortLog.getScore()));
@@ -1423,26 +1445,63 @@ public class DataDashboardService {
             item.setViewCountRateStrategy(scoreMap.getDoubleValue("ViewCountRateStrategy"));
             item.setHisFissionDeWeightAvgReadSumRateStrategy(scoreMap.getDoubleValue("HisFissionDeWeightAvgReadSumRateStrategy"));
             item.setReadCount(article.getShowViewCount());
-            Map<String, AccountAvgInfo> map = accountAvgInfoMap.get(article.getGhId());
+            Map<String, Map<String, AccountAvgInfo>> map = accountAvgInfoMap.get(article.getGhId());
             if (Objects.nonNull(map)) {
                 List<String> avgMapDateList = new ArrayList<>(map.keySet());
                 String publishDate = DateUtils.findNearestDate(avgMapDateList,
                         DateUtils.timestampToYMDStr(article.getPublishTimestamp(), "yyyy-MM-dd"), "yyyy-MM-dd");
-                AccountAvgInfo accountAvgInfo = map.get(publishDate);
-                if (Objects.nonNull(accountAvgInfo)) {
-                    item.setReadAvg(accountAvgInfo.getReadAvg());
-                    item.setReadAvgRate(article.getShowViewCount() / (double) accountAvgInfo.getReadAvg());
+                Map<String, AccountAvgInfo> avgIndexMap = map.get(publishDate);
+                if (Objects.nonNull(avgIndexMap)) {
+                    AccountAvgInfo accountAvgInfo = avgIndexMap.get(String.valueOf(publishSortLog.getIndex()));
+                    if (Objects.nonNull(accountAvgInfo)) {
+                        item.setReadAvg(accountAvgInfo.getReadAvg());
+                        item.setReadAvgRate(article.getShowViewCount() / (double) accountAvgInfo.getReadAvg());
+                    }
                 }
             }
             List<PublishContent> hisPublish = hisPublishMap.get(article.getTitle());
-            long hisMinDate = hisPublish.stream().mapToLong(PublishContent::getPublishTimestamp).min().orElse(0);
-            int explorationInterval = (int) ((article.getPublishTimestamp() - (hisMinDate / 1000)) / 86400);
-            item.setFirstExplorationIntervalAvg(explorationInterval);
+            if (CollectionUtils.isNotEmpty(hisPublish)) {
+                long hisMinDate = hisPublish.stream().filter(o -> Objects.nonNull(o.getPublishTimestamp()))
+                        .mapToLong(PublishContent::getPublishTimestamp).min().orElse(0);
+                int explorationInterval = (int) ((article.getPublishTimestamp() - (hisMinDate / 1000)) / 86400);
+                item.setFirstExplorationIntervalAvg(explorationInterval);
+            }
             result.add(item);
         }
+        saveDatastatScore(dateStrList, result);
+        result = result.stream().filter(o -> o.getIndex() == 1).collect(Collectors.toList());
         result.sort(Comparator.comparing(FirstContentScoreExport::getDateStr).reversed()
                 .thenComparing(FirstContentScoreExport::getGhId));
         return result;
     }
 
+    private void saveDatastatScore(List<String> dateStrList, List<FirstContentScoreExport> result) {
+        if (CollectionUtils.isNotEmpty(result)) {
+            datastatScoreRepository.deleteByDtIn(dateStrList);
+            List<DatastatScore> saveList = new ArrayList<>();
+            for (FirstContentScoreExport value : result) {
+                DatastatScore item = new DatastatScore();
+                item.setDt(value.getDateStr());
+                item.setGhId(value.getGhId());
+                item.setAccountName(value.getAccountName());
+                item.setIndex(value.getIndex());
+                item.setTitle(value.getTitle());
+                item.setStrategy(value.getStrategy());
+                item.setScore(value.getScore());
+                item.setHisFissionAvgReadRateRate(value.getHisFissionAvgReadRateRateStrategy());
+                item.setHisFissionAvgReadSumRate(value.getHisFissionAvgReadSumRateStrategy());
+                item.setSimilarity(value.getSimilarityStrategy());
+                item.setViewCountRate(value.getViewCountRateStrategy());
+                item.setHisFissionDeWeightAvgReadSumRate(value.getHisFissionDeWeightAvgReadSumRateStrategy());
+                item.setReadCount(value.getReadCount());
+                item.setReadAvg(value.getReadAvg());
+                item.setReadAvgRate(value.getReadAvgRate());
+                saveList.add(item);
+            }
+            for (List<DatastatScore> saveListPartition : Lists.partition(saveList, 1000)) {
+                longArticleBaseMapper.batchInsertDatastatScore(saveListPartition);
+            }
+        }
+    }
+
 }

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

@@ -3,7 +3,7 @@ package com.tzld.longarticle.recommend.server.service.recommend;
 import com.alibaba.fastjson.JSONObject;
 import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue;
 import com.tzld.longarticle.recommend.server.common.enums.recommend.ArticleTypeEnum;
-import com.tzld.longarticle.recommend.server.common.enums.recommend.PushTypeEnum;
+import com.tzld.longarticle.recommend.server.common.enums.aigc.PushTypeEnum;
 import com.tzld.longarticle.recommend.server.common.enums.recommend.RankStrategyEnum;
 import com.tzld.longarticle.recommend.server.mapper.aigc.AigcBaseMapper;
 import com.tzld.longarticle.recommend.server.mapper.crawler.ArticleUserGroupMapper;
@@ -275,13 +275,20 @@ public class RecommendService {
                 break;
 
         }
+        String dateStr = DateUtils.getCurrentDateStr("yyyyMMdd");
         List<PublishSortLog> publishSortLogSaveList = new ArrayList<>();
         List<AccountAvgInfo> avgInfoList = accountAvgInfoRepository.getAllByGhIdEqualsAndStatusEquals(param.getGhId(), 1);
+        List<PublishSortLog> hisSortLog = publishSortLogRepository.findByDateStrAndGhId(dateStr, param.getGhId());
+        List<String> hisSortTitles = hisSortLog.stream().map(PublishSortLog::getTitle).collect(Collectors.toList());
         for (int i = 1; i < rankResult.getContents().size() + 1; i++) {
             Content content = rankResult.getContents().get(i - 1);
-
+            if (CollectionUtils.isNotEmpty(hisSortLog)) {
+                if (hisSortTitles.contains(content.getTitle())) {
+                    continue;
+                }
+            }
             PublishSortLog sortLog = new PublishSortLog();
-            sortLog.setDateStr(DateUtils.getCurrentDateStr("yyyyMMdd"));
+            sortLog.setDateStr(dateStr);
             sortLog.setGhId(param.getGhId());
             sortLog.setAccountName(param.getAccountName());
             sortLog.setCrawlerChannelContentId(content.getCrawlerChannelContentId());
@@ -297,7 +304,9 @@ public class RecommendService {
             sortLog.setCreateTimestamp(System.currentTimeMillis());
             publishSortLogSaveList.add(sortLog);
         }
-        publishSortLogRepository.saveAll(publishSortLogSaveList);
+        if (CollectionUtils.isNotEmpty(publishSortLogSaveList)) {
+            publishSortLogRepository.saveAll(publishSortLogSaveList);
+        }
     }
 
 }

+ 1 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/filter/FilterService.java

@@ -93,6 +93,7 @@ public class FilterService {
         strategies.add(ServiceBeanFactory.getBean(SensitiveStrategy.class));
         strategies.add(ServiceBeanFactory.getBean(DeDuplicationStrategy.class));
         strategies.add(ServiceBeanFactory.getBean(KeywordStrategy.class));
+        strategies.add(ServiceBeanFactory.getBean(ArticlePromotionStrategy.class));
         if (param.getScene().equals(FWH_COLD_START)) {
             strategies.add(ServiceBeanFactory.getBean(HistoryTitleForFwhColdStartStrategy.class));
         } else {

+ 52 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/filter/strategy/ArticlePromotionStrategy.java

@@ -0,0 +1,52 @@
+package com.tzld.longarticle.recommend.server.service.recommend.filter.strategy;
+
+import com.tzld.longarticle.recommend.server.model.dto.Content;
+import com.tzld.longarticle.recommend.server.model.entity.longArticle.ArticlePoolPromotionSource;
+import com.tzld.longarticle.recommend.server.repository.longArticle.ArticlePoolPromotionSourceRepository;
+import com.tzld.longarticle.recommend.server.service.recommend.filter.FilterParam;
+import com.tzld.longarticle.recommend.server.service.recommend.filter.FilterResult;
+import com.tzld.longarticle.recommend.server.service.recommend.filter.FilterStrategy;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Component
+@Slf4j
+public class ArticlePromotionStrategy implements FilterStrategy {
+
+    @Autowired
+    ArticlePoolPromotionSourceRepository repository;
+
+    @Override
+    public FilterResult filter(FilterParam param) {
+        FilterResult filterResult = new FilterResult();
+        List<String> result = new ArrayList<>();
+        List<Content> contents = param.getContents();
+        List<Content> filterContents = new ArrayList<>();
+        List<String> channelContentIds = contents.stream().map(Content::getCrawlerChannelContentId).collect(Collectors.toList());
+        List<ArticlePoolPromotionSource> promotionSourceList = repository.getByChannelContentIdInAndStatusAndDeleted(channelContentIds, 1, 0);
+        Map<String, ArticlePoolPromotionSource> promotionSourceMap = promotionSourceList.stream().collect(Collectors.toMap(ArticlePoolPromotionSource::getChannelContentId, a -> a));
+        for (Content content : contents) {
+            if (promotionSourceMap.containsKey(content.getCrawlerChannelContentId())) {
+                ArticlePoolPromotionSource promotionSource = promotionSourceMap.get(content.getCrawlerChannelContentId());
+                if (!promotionSource.getLevel().equals(content.getContentPoolType())) {
+                    content.setFilterReason("内容已晋级过滤");
+                    filterContents.add(content);
+                }
+            }
+            if (!StringUtils.hasText(content.getFilterReason())) {
+                result.add(content.getId());
+            }
+        }
+        filterResult.setContentIds(result);
+        filterResult.setFilterContent(filterContents);
+        return filterResult;
+    }
+
+}

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

@@ -3,6 +3,7 @@ package com.tzld.longarticle.recommend.server.service.recommend.rank.strategy;
 import com.tzld.longarticle.recommend.server.common.enums.recommend.ScoreStrategyEnum;
 import com.tzld.longarticle.recommend.server.model.dto.Content;
 import com.tzld.longarticle.recommend.server.service.recommend.config.AccountContentPoolConfigService;
+import com.tzld.longarticle.recommend.server.service.recommend.config.StrategyIndexScoreWeightService;
 import com.tzld.longarticle.recommend.server.service.recommend.rank.RankItem;
 import com.tzld.longarticle.recommend.server.service.recommend.rank.RankParam;
 import com.tzld.longarticle.recommend.server.service.recommend.rank.RankResult;
@@ -27,6 +28,8 @@ public class InfiniteRankStrategy implements RankStrategy {
     private ScoreService scoreService;
     @Autowired
     private AccountContentPoolConfigService accountContentPoolConfigService;
+    @Autowired
+    private StrategyIndexScoreWeightService weightService;
 
     public RankResult rank(RankParam param) {
         List<Content> result = new ArrayList<>();
@@ -44,9 +47,12 @@ public class InfiniteRankStrategy implements RankStrategy {
             c.setScoreMap(scoreMap.get(c.getId()));
             item.setScoreMap(scoreMap.get(c.getId()));
             double score = 0.0;
+            int index = weightService.getIndex(item.getContent().getContentPoolType(), contentPools);
             if (contentPools[2].equals(item.getContent().getContentPoolType())) {
                 score = item.getScore(ScoreStrategyEnum.SIMILARITY.value())
                         + item.getScore(ScoreStrategyEnum.CATEGORY.value())
+                        * weightService.getWeight(param.getStrategy(), param.getGhId(), index,
+                        ScoreStrategyEnum.CATEGORY.value())
                         + item.getScore(ScoreStrategyEnum.ACCOUNT_PRE_DISTRIBUTE.value())
                         + item.getScore(ScoreStrategyEnum.PUBLISH_TIMES.value())
                         + item.getScore(ScoreStrategyEnum.CRAWLER_DAYS_DECREASE_STRATEGY.value())

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

@@ -3,6 +3,7 @@ package com.tzld.longarticle.recommend.server.service.recommend.rank.strategy;
 import com.tzld.longarticle.recommend.server.common.enums.recommend.ScoreStrategyEnum;
 import com.tzld.longarticle.recommend.server.model.dto.Content;
 import com.tzld.longarticle.recommend.server.service.recommend.config.AccountContentPoolConfigService;
+import com.tzld.longarticle.recommend.server.service.recommend.config.StrategyIndexScoreWeightService;
 import com.tzld.longarticle.recommend.server.service.recommend.rank.RankItem;
 import com.tzld.longarticle.recommend.server.service.recommend.rank.RankParam;
 import com.tzld.longarticle.recommend.server.service.recommend.rank.RankResult;
@@ -27,6 +28,8 @@ public class LateRankStrategy implements RankStrategy {
     private ScoreService scoreService;
     @Autowired
     private AccountContentPoolConfigService accountContentPoolConfigService;
+    @Autowired
+    private StrategyIndexScoreWeightService weightService;
 
     public RankResult rank(RankParam param) {
         List<Content> result = new ArrayList<>();
@@ -44,9 +47,12 @@ public class LateRankStrategy implements RankStrategy {
             c.setScoreMap(scoreMap.get(c.getId()));
             item.setScoreMap(scoreMap.get(c.getId()));
             double score = 0.0;
+            int index = weightService.getIndex(item.getContent().getContentPoolType(), contentPools);
             if (contentPools[2].equals(item.getContent().getContentPoolType())) {
                 score = item.getScore(ScoreStrategyEnum.SIMILARITY.value())
                         + item.getScore(ScoreStrategyEnum.CATEGORY.value())
+                        * weightService.getWeight(param.getStrategy(), param.getGhId(), index,
+                        ScoreStrategyEnum.CATEGORY.value())
                         + item.getScore(ScoreStrategyEnum.ACCOUNT_PRE_DISTRIBUTE.value())
                         + item.getScore(ScoreStrategyEnum.PUBLISH_TIMES.value())
                         + item.getScore(ScoreStrategyEnum.CRAWLER_DAYS_DECREASE_STRATEGY.value())

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

@@ -6,6 +6,7 @@ import com.tzld.longarticle.recommend.server.model.dto.Content;
 import com.tzld.longarticle.recommend.server.model.entity.crawler.Article;
 import com.tzld.longarticle.recommend.server.repository.crawler.ArticleRepository;
 import com.tzld.longarticle.recommend.server.service.recommend.config.AccountContentPoolConfigService;
+import com.tzld.longarticle.recommend.server.service.recommend.config.StrategyIndexScoreWeightService;
 import com.tzld.longarticle.recommend.server.service.recommend.rank.RankItem;
 import com.tzld.longarticle.recommend.server.service.recommend.rank.RankParam;
 import com.tzld.longarticle.recommend.server.service.recommend.rank.RankResult;
@@ -35,6 +36,8 @@ public class RankV10Strategy implements RankStrategy {
     private AccountContentPoolConfigService accountContentPoolConfigService;
     @Autowired
     private ArticleRepository articleRepository;
+    @Autowired
+    private StrategyIndexScoreWeightService weightService;
 
     public RankResult rank(RankParam param) {
         List<Content> result = new ArrayList<>();
@@ -51,11 +54,14 @@ public class RankV10Strategy implements RankStrategy {
             c.setScoreMap(scoreMap.get(c.getId()));
             item.setScoreMap(scoreMap.get(c.getId()));
             double score;
+            int index = weightService.getIndex(item.getContent().getContentPoolType(), contentPools);
             if (contentPools[0].equals(item.getContent().getContentPoolType())) {
                 score = item.getScore(ScoreStrategyEnum.HIS_FISSION_AVG_READ_SUM_RATE.value());
             } else if (contentPools[1].equals(item.getContent().getContentPoolType())) {
                 score = item.getScore(ScoreStrategyEnum.SIMILARITY.value())
                         + item.getScore(ScoreStrategyEnum.CATEGORY.value())
+                        * weightService.getWeight(param.getStrategy(), param.getGhId(), index,
+                        ScoreStrategyEnum.CATEGORY.value())
                         + item.getScore(ScoreStrategyEnum.FLOW_CTL_DECREASE.value());
                 if (item.getScore(ScoreStrategyEnum.PUBLISH_TIMES.value()) >= 0) {
                     score += item.getScore(ScoreStrategyEnum.VIEW_COUNT_RATE.value());
@@ -63,6 +69,8 @@ public class RankV10Strategy implements RankStrategy {
             } else {
                 score = item.getScore(ScoreStrategyEnum.SIMILARITY.value())
                         + item.getScore(ScoreStrategyEnum.CATEGORY.value())
+                        * weightService.getWeight(param.getStrategy(), param.getGhId(), index,
+                        ScoreStrategyEnum.CATEGORY.value())
                         + item.getScore(ScoreStrategyEnum.ACCOUNT_PRE_DISTRIBUTE.value())
                         + item.getScore(ScoreStrategyEnum.PUBLISH_TIMES.value())
                         + item.getScore(ScoreStrategyEnum.CRAWLER_DAYS_DECREASE_STRATEGY.value())

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

@@ -70,6 +70,8 @@ public class RankV11Strategy implements RankStrategy {
                         * weightService.getWeight(param.getStrategy(), param.getGhId(), index,
                         ScoreStrategyEnum.SIMILARITY.value()))
                         + item.getScore(ScoreStrategyEnum.CATEGORY.value())
+                        * weightService.getWeight(param.getStrategy(), param.getGhId(), index,
+                        ScoreStrategyEnum.CATEGORY.value())
                         + item.getScore(ScoreStrategyEnum.FLOW_CTL_DECREASE.value());
                 if (item.getScore(ScoreStrategyEnum.PUBLISH_TIMES.value()) >= 0) {
                     score += item.getScore(ScoreStrategyEnum.VIEW_COUNT_RATE.value())
@@ -81,6 +83,8 @@ public class RankV11Strategy implements RankStrategy {
                         * weightService.getWeight(param.getStrategy(), param.getGhId(), index,
                         ScoreStrategyEnum.SIMILARITY.value()))
                         + item.getScore(ScoreStrategyEnum.CATEGORY.value())
+                        * weightService.getWeight(param.getStrategy(), param.getGhId(), index,
+                        ScoreStrategyEnum.CATEGORY.value())
                         + (item.getScore(ScoreStrategyEnum.ACCOUNT_PRE_DISTRIBUTE.value())
                         * weightService.getWeight(param.getStrategy(), param.getGhId(), index,
                         ScoreStrategyEnum.ACCOUNT_PRE_DISTRIBUTE.value()))

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

@@ -70,6 +70,8 @@ public class RankV12Strategy implements RankStrategy {
                         * weightService.getWeight(param.getStrategy(), param.getGhId(), index,
                         ScoreStrategyEnum.SIMILARITY.value()))
                         + item.getScore(ScoreStrategyEnum.CATEGORY.value())
+                        * weightService.getWeight(param.getStrategy(), param.getGhId(), index,
+                        ScoreStrategyEnum.CATEGORY.value())
                         + item.getScore(ScoreStrategyEnum.FLOW_CTL_DECREASE.value());
                 if (item.getScore(ScoreStrategyEnum.PUBLISH_TIMES.value()) >= 0) {
                     score += item.getScore(ScoreStrategyEnum.VIEW_COUNT_RATE.value())
@@ -81,6 +83,8 @@ public class RankV12Strategy implements RankStrategy {
                         * weightService.getWeight(param.getStrategy(), param.getGhId(), index,
                         ScoreStrategyEnum.SIMILARITY.value()))
                         + item.getScore(ScoreStrategyEnum.CATEGORY.value())
+                        * weightService.getWeight(param.getStrategy(), param.getGhId(), index,
+                        ScoreStrategyEnum.CATEGORY.value())
                         + (item.getScore(ScoreStrategyEnum.ACCOUNT_PRE_DISTRIBUTE.value())
                         * weightService.getWeight(param.getStrategy(), param.getGhId(), index,
                         ScoreStrategyEnum.ACCOUNT_PRE_DISTRIBUTE.value()))

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

@@ -71,6 +71,8 @@ public class RankV13Strategy implements RankStrategy {
                         * weightService.getWeight(param.getStrategy(), param.getGhId(), index,
                         ScoreStrategyEnum.SIMILARITY.value()))
                         + item.getScore(ScoreStrategyEnum.CATEGORY.value())
+                        * weightService.getWeight(param.getStrategy(), param.getGhId(), index,
+                        ScoreStrategyEnum.CATEGORY.value())
                         + item.getScore(ScoreStrategyEnum.FLOW_CTL_DECREASE.value());
                 if (item.getScore(ScoreStrategyEnum.PUBLISH_TIMES.value()) >= 0) {
                     score += item.getScore(ScoreStrategyEnum.VIEW_COUNT_RATE.value())
@@ -82,6 +84,8 @@ public class RankV13Strategy implements RankStrategy {
                         * weightService.getWeight(param.getStrategy(), param.getGhId(), index,
                         ScoreStrategyEnum.SIMILARITY.value()))
                         + item.getScore(ScoreStrategyEnum.CATEGORY.value())
+                        * weightService.getWeight(param.getStrategy(), param.getGhId(), index,
+                        ScoreStrategyEnum.CATEGORY.value())
                         + (item.getScore(ScoreStrategyEnum.ACCOUNT_PRE_DISTRIBUTE.value())
                         * weightService.getWeight(param.getStrategy(), param.getGhId(), index,
                         ScoreStrategyEnum.ACCOUNT_PRE_DISTRIBUTE.value()))

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

@@ -71,6 +71,8 @@ public class RankV14Strategy implements RankStrategy {
                         * weightService.getWeight(param.getStrategy(), param.getGhId(), index,
                         ScoreStrategyEnum.SIMILARITY.value()))
                         + item.getScore(ScoreStrategyEnum.CATEGORY.value())
+                        * weightService.getWeight(param.getStrategy(), param.getGhId(), index,
+                        ScoreStrategyEnum.CATEGORY.value())
                         + item.getScore(ScoreStrategyEnum.FLOW_CTL_DECREASE.value());
                 if (item.getScore(ScoreStrategyEnum.PUBLISH_TIMES.value()) >= 0) {
                     score += item.getScore(ScoreStrategyEnum.VIEW_COUNT_RATE.value())
@@ -82,6 +84,8 @@ public class RankV14Strategy implements RankStrategy {
                         * weightService.getWeight(param.getStrategy(), param.getGhId(), index,
                         ScoreStrategyEnum.SIMILARITY.value()))
                         + item.getScore(ScoreStrategyEnum.CATEGORY.value())
+                        * weightService.getWeight(param.getStrategy(), param.getGhId(), index,
+                        ScoreStrategyEnum.CATEGORY.value())
                         + (item.getScore(ScoreStrategyEnum.ACCOUNT_PRE_DISTRIBUTE.value())
                         * weightService.getWeight(param.getStrategy(), param.getGhId(), index,
                         ScoreStrategyEnum.ACCOUNT_PRE_DISTRIBUTE.value()))

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

@@ -63,6 +63,8 @@ public class RankV5Strategy implements RankStrategy {
                         * weightService.getWeight(param.getStrategy(), param.getGhId(), index,
                         ScoreStrategyEnum.SIMILARITY.value())
                         + item.getScore(ScoreStrategyEnum.CATEGORY.value())
+                        * weightService.getWeight(param.getStrategy(), param.getGhId(), index,
+                        ScoreStrategyEnum.CATEGORY.value())
                         + item.getScore(ScoreStrategyEnum.FLOW_CTL_DECREASE.value());
                 if (item.getScore(ScoreStrategyEnum.PUBLISH_TIMES.value()) >= 0) {
                     score += item.getScore(ScoreStrategyEnum.VIEW_COUNT_RATE.value())
@@ -104,9 +106,7 @@ public class RankV5Strategy implements RankStrategy {
 
         // 头
         List<Content> pool1 = contentMap.get(contentPools[0]);
-        if (touliuAccountGhIds.contains(param.getGhId())) {
-            RankService.printSortLog(RankStrategyEnum.ArticleRankV5.getStrategy(), param.getAccountName(), pool1);
-        }
+        RankService.printSortLog(RankStrategyEnum.ArticleRankV5.getStrategy(), param.getAccountName(), pool1);
         if (CollectionUtils.isNotEmpty(pool1)) {
             result.add(pool1.get(0));
         } else {

+ 11 - 4
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/rank/strategy/RankV8Strategy.java

@@ -1,15 +1,14 @@
 package com.tzld.longarticle.recommend.server.service.recommend.rank.strategy;
 
 
+import com.tzld.longarticle.recommend.server.common.enums.recommend.RankStrategyEnum;
 import com.tzld.longarticle.recommend.server.common.enums.recommend.ScoreStrategyEnum;
 import com.tzld.longarticle.recommend.server.model.dto.Content;
 import com.tzld.longarticle.recommend.server.model.entity.crawler.Article;
 import com.tzld.longarticle.recommend.server.repository.crawler.ArticleRepository;
 import com.tzld.longarticle.recommend.server.service.recommend.config.AccountContentPoolConfigService;
-import com.tzld.longarticle.recommend.server.service.recommend.rank.RankItem;
-import com.tzld.longarticle.recommend.server.service.recommend.rank.RankParam;
-import com.tzld.longarticle.recommend.server.service.recommend.rank.RankResult;
-import com.tzld.longarticle.recommend.server.service.recommend.rank.RankStrategy;
+import com.tzld.longarticle.recommend.server.service.recommend.config.StrategyIndexScoreWeightService;
+import com.tzld.longarticle.recommend.server.service.recommend.rank.*;
 import com.tzld.longarticle.recommend.server.service.recommend.score.AccountIndexReplacePoolConfig;
 import com.tzld.longarticle.recommend.server.service.recommend.score.ScoreResult;
 import com.tzld.longarticle.recommend.server.service.recommend.score.ScoreService;
@@ -35,6 +34,8 @@ public class RankV8Strategy implements RankStrategy {
     private AccountContentPoolConfigService accountContentPoolConfigService;
     @Autowired
     private ArticleRepository articleRepository;
+    @Autowired
+    private StrategyIndexScoreWeightService weightService;
 
     public RankResult rank(RankParam param) {
         List<Content> result = new ArrayList<>();
@@ -51,9 +52,12 @@ public class RankV8Strategy implements RankStrategy {
             c.setScoreMap(scoreMap.get(c.getId()));
             item.setScoreMap(scoreMap.get(c.getId()));
             double score;
+            int index = weightService.getIndex(item.getContent().getContentPoolType(), contentPools);
             if (contentPools[0].equals(item.getContent().getContentPoolType())) {
                 score = item.getScore(ScoreStrategyEnum.SIMILARITY.value())
                         + item.getScore(ScoreStrategyEnum.CATEGORY.value())
+                        * weightService.getWeight(param.getStrategy(), param.getGhId(), index,
+                        ScoreStrategyEnum.CATEGORY.value())
                         + item.getScore(ScoreStrategyEnum.FLOW_CTL_DECREASE.value());
                 score += item.getScore(ScoreStrategyEnum.HIS_FISSION_AVG_READ_RATE_RATE.value());
             } else if (contentPools[1].equals(item.getContent().getContentPoolType())) {
@@ -66,6 +70,8 @@ public class RankV8Strategy implements RankStrategy {
             } else {
                 score = item.getScore(ScoreStrategyEnum.SIMILARITY.value())
                         + item.getScore(ScoreStrategyEnum.CATEGORY.value())
+                        * weightService.getWeight(param.getStrategy(), param.getGhId(), index,
+                        ScoreStrategyEnum.CATEGORY.value())
                         + item.getScore(ScoreStrategyEnum.ACCOUNT_PRE_DISTRIBUTE.value())
                         + item.getScore(ScoreStrategyEnum.PUBLISH_TIMES.value())
                         + item.getScore(ScoreStrategyEnum.CRAWLER_DAYS_DECREASE_STRATEGY.value())
@@ -98,6 +104,7 @@ public class RankV8Strategy implements RankStrategy {
 
         // 头
         List<Content> pool1 = contentMap.get(contentPools[0]);
+        RankService.printSortLog(RankStrategyEnum.ArticleRankV8.getStrategy(), param.getAccountName(), pool1);
         if (CollectionUtils.isNotEmpty(pool1)) {
             result.add(pool1.get(0));
         } else {

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

@@ -12,12 +12,16 @@ import com.tzld.longarticle.recommend.server.model.entity.crawler.AccountAvgInfo
 import com.tzld.longarticle.recommend.server.model.entity.crawler.AccountCorrelation;
 import com.tzld.longarticle.recommend.server.model.entity.crawler.Article;
 import com.tzld.longarticle.recommend.server.model.entity.crawler.ArticleDetailInfo;
+import com.tzld.longarticle.recommend.server.model.entity.longArticle.ArticleCategory;
+import com.tzld.longarticle.recommend.server.model.entity.longArticle.ArticlePoolPromotionSource;
 import com.tzld.longarticle.recommend.server.remote.AIGCRemoteService;
 import com.tzld.longarticle.recommend.server.repository.aigc.CrawlerMetaArticleRepository;
 import com.tzld.longarticle.recommend.server.repository.crawler.AccountAvgInfoRepository;
 import com.tzld.longarticle.recommend.server.repository.crawler.AccountCorrelationRepository;
 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.longArticle.ArticleCategoryRepository;
+import com.tzld.longarticle.recommend.server.repository.longArticle.ArticlePoolPromotionSourceRepository;
 import com.tzld.longarticle.recommend.server.service.recommend.config.AccountIndexAvgViewCountService;
 import com.tzld.longarticle.recommend.server.service.recommend.recall.strategy.DefaultRecallStrategy;
 import com.tzld.longarticle.recommend.server.service.recommend.score.ScoreStrategy;
@@ -42,6 +46,7 @@ import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 /**
@@ -67,6 +72,10 @@ public class RecallService implements ApplicationContextAware {
     CrawlerBaseMapper crawlerBaseMapper;
     @Autowired
     AccountCorrelationRepository accountCorrelationRepository;
+    @Autowired
+    ArticlePoolPromotionSourceRepository articlePoolPromotionSourceRepository;
+    @Autowired
+    ArticleCategoryRepository articleCategoryRepository;
 
     private final Map<String, RecallStrategy> strategyMap = new HashMap<>();
     private ApplicationContext applicationContext;
@@ -157,25 +166,42 @@ public class RecallService implements ApplicationContextAware {
     }
 
     public void setContentCategory(List<Content> contentList) {
-        long start = System.currentTimeMillis();
-        Map<String, String> articleMd5Map = new HashMap<>();
-        List<String> md5List = new ArrayList<>();
-        for (Content content : contentList) {
-            String md5 = generateArticleUniqueMd5(content.getCrawlerLink());
-            md5List.add(md5);
-            articleMd5Map.put(content.getId(), md5);
-        }
-        List<CrawlerMetaArticle> categoryList = getByUniqueIndexIn(md5List);
-        if (CollectionUtils.isEmpty(categoryList)) {
-            return;
-        }
-        Map<String, List<String>> categoryMap = categoryList.stream().collect(Collectors.groupingBy(CrawlerMetaArticle::getUniqueIndex,
-                Collectors.mapping(CrawlerMetaArticle::getCategory, Collectors.toList())));
+//        Map<String, String> articleMd5Map = new HashMap<>();
+//        List<String> md5List = new ArrayList<>();
+//        for (Content content : contentList) {
+//            String md5 = generateArticleUniqueMd5(content.getCrawlerLink());
+//            md5List.add(md5);
+//            articleMd5Map.put(content.getId(), md5);
+//        }
+//        List<CrawlerMetaArticle> categoryList = getByUniqueIndexIn(md5List);
+//        if (CollectionUtils.isEmpty(categoryList)) {
+//            return;
+//        }
+//        Map<String, List<String>> categoryMap = categoryList.stream().collect(Collectors.groupingBy(CrawlerMetaArticle::getUniqueIndex,
+//                Collectors.mapping(CrawlerMetaArticle::getCategory, Collectors.toList())));
+//        for (Content content : contentList) {
+//            String md5 = articleMd5Map.get(content.getId());
+//            content.setCategory(categoryMap.get(md5));
+//        }
+        List<String> channelContentIds = contentList.stream().map(Content::getCrawlerChannelContentId).collect(Collectors.toList());
+        // 查询晋升rootProduceContentId
+        List<ArticlePoolPromotionSource> sourceList = articlePoolPromotionSourceRepository.getByChannelContentIdIn(channelContentIds);
+        Map<String, ArticlePoolPromotionSource> sourceMap = sourceList.stream().collect(Collectors.toMap(ArticlePoolPromotionSource::getChannelContentId, Function.identity()));
+        List<String> produceContentIds = sourceMap.values().stream().map(ArticlePoolPromotionSource::getRootProduceContentId).collect(Collectors.toList());
+        // 根据produceContentId查询category
+        List<ArticleCategory> articleCategoryList = articleCategoryRepository.getByProduceContentIdIn(produceContentIds);
+        Map<String, ArticleCategory> categoryMap = articleCategoryList.stream().collect(Collectors.toMap(ArticleCategory::getProduceContentId, Function.identity()));
         for (Content content : contentList) {
-            String md5 = articleMd5Map.get(content.getId());
-            content.setCategory(categoryMap.get(md5));
+            ArticlePoolPromotionSource source = sourceMap.get(content.getCrawlerChannelContentId());
+            if (Objects.nonNull(source) && Objects.nonNull(source.getRootProduceContentId())) {
+                ArticleCategory category = categoryMap.get(source.getRootProduceContentId());
+                if (Objects.nonNull(category)) {
+                    content.setCategory(Collections.singletonList(category.getCategory()));
+                    continue;
+                }
+            }
+            log.error("setContentCategory NullError channelContentId:{}", content.getCrawlerChannelContentId());
         }
-        log.info("setContentCategory cost:{}", System.currentTimeMillis() - start);
     }
 
     private List<CrawlerMetaArticle> getByUniqueIndexIn(List<String> md5List) {

+ 16 - 16
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/score/strategy/CategoryStrategy.java

@@ -1,8 +1,12 @@
 package com.tzld.longarticle.recommend.server.service.recommend.score.strategy;
 
+import com.alibaba.fastjson.JSONObject;
 import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue;
+import com.tzld.longarticle.recommend.server.common.enums.StatusEnum;
 import com.tzld.longarticle.recommend.server.model.dto.Content;
+import com.tzld.longarticle.recommend.server.model.entity.longArticle.AccountCategory;
 import com.tzld.longarticle.recommend.server.repository.aigc.CrawlerMetaArticleRepository;
+import com.tzld.longarticle.recommend.server.repository.longArticle.AccountCategoryRepository;
 import com.tzld.longarticle.recommend.server.service.recommend.config.AccountContentPoolConfigService;
 import com.tzld.longarticle.recommend.server.service.recommend.score.AccountCategoryWeightConfig;
 import com.tzld.longarticle.recommend.server.service.recommend.score.Score;
@@ -12,9 +16,9 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
 
 import java.util.*;
-import java.util.stream.Collectors;
 
 @Component
 @Slf4j
@@ -24,6 +28,8 @@ public class CategoryStrategy implements ScoreStrategy {
     CrawlerMetaArticleRepository crawlerMetaArticleRepository;
     @Autowired
     AccountContentPoolConfigService accountContentPoolConfigService;
+    @Autowired
+    AccountCategoryRepository accountCategoryRepository;
 
     @ApolloJsonValue("${accountCategoryWeightConfig:{}}")
     private Map<String, AccountCategoryWeightConfig[]> accountCategoryWeightConfigMap;
@@ -36,12 +42,11 @@ public class CategoryStrategy implements ScoreStrategy {
         if (CollectionUtils.isEmpty(param.getContents())) {
             return scores;
         }
-        AccountCategoryWeightConfig[] categoryWeightConfigList = accountCategoryWeightConfigMap.get(param.getAccountName());
-        if (Objects.isNull(categoryWeightConfigList) || categoryWeightConfigList.length == 0) {
+        AccountCategory accountCategory = accountCategoryRepository.getByGhIdAndStatus(param.getGhId(), StatusEnum.ONE.getCode());
+        if (Objects.isNull(accountCategory) || !StringUtils.hasText(accountCategory.getCategoryMap())) {
             return scores;
         }
-        Map<Integer, AccountCategoryWeightConfig> categoryWeightConfigMap = Arrays.stream(categoryWeightConfigList).collect(Collectors.toMap(AccountCategoryWeightConfig::getIndex, o -> o));
-        String[] contentPools = accountContentPoolConfigService.getContentPools(param.getAccountName());
+        JSONObject categoryWeightMap = JSONObject.parseObject(accountCategory.getCategoryMap());
         for (Content content : param.getContents()) {
             if (CollectionUtils.isEmpty(content.getCategory())) {
                 continue;
@@ -49,19 +54,14 @@ public class CategoryStrategy implements ScoreStrategy {
             Score score = new Score();
             score.setStrategy(this);
             score.setContentId(content.getId());
-            for (int i = 0; i < contentPools.length; i++) {
-                if (contentPools[i].equals(content.getContentPoolType())) {
-                    AccountCategoryWeightConfig categoryWeightConfig = categoryWeightConfigMap.get(i+1);
-                    if (Objects.nonNull(categoryWeightConfig)) {
-                        List<AccountCategoryWeightConfig.CategoryWeight> categoryWeightList = categoryWeightConfig.getCategoryWeightList();
-                        for (AccountCategoryWeightConfig.CategoryWeight categoryWeight : categoryWeightList) {
-                            if (content.getCategory().contains(categoryWeight.getCategory())) {
-                                score.setScore(Double.valueOf(categoryWeight.getWeight()));
-                            }
-                        }
-                    }
+            double scoreValue = 0.0;
+            for (String category : content.getCategory()) {
+                if (!categoryWeightMap.containsKey(category)) {
+                    continue;
                 }
+                scoreValue += categoryWeightMap.getDoubleValue(category);
             }
+            score.setScore(scoreValue);
             scores.add(score);
         }
         log.info("CategoryStrategy cost:{}", System.currentTimeMillis() - start);

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

@@ -3,8 +3,8 @@ 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.mapper.crawler.AlgGhAutoreplyVideoRankDataMapper;
-import com.tzld.longarticle.recommend.server.mapper.crawler.CgiReplyBucketDataMapper;
+import com.tzld.longarticle.recommend.server.mapper.growth.AlgGhAutoreplyVideoRankDataMapper;
+import com.tzld.longarticle.recommend.server.mapper.growth.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;

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

@@ -3,8 +3,8 @@ 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.mapper.crawler.AlgGhAutoreplyVideoRankDataMapper;
-import com.tzld.longarticle.recommend.server.mapper.crawler.CgiReplyBucketDataMapper;
+import com.tzld.longarticle.recommend.server.mapper.growth.AlgGhAutoreplyVideoRankDataMapper;
+import com.tzld.longarticle.recommend.server.mapper.growth.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;

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

@@ -3,8 +3,8 @@ 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.mapper.crawler.AlgGhAutoreplyVideoRankDataMapper;
-import com.tzld.longarticle.recommend.server.mapper.crawler.CgiReplyBucketDataMapper;
+import com.tzld.longarticle.recommend.server.mapper.growth.AlgGhAutoreplyVideoRankDataMapper;
+import com.tzld.longarticle.recommend.server.mapper.growth.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;

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

@@ -8,6 +8,7 @@ import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
 import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
 import java.time.temporal.ChronoUnit;
 import java.util.*;
 
@@ -75,6 +76,19 @@ public final class DateUtils {
         return dateTime.toEpochSecond(zone.getRules().getOffset(dateTime));
     }
 
+    public static boolean isValidDate(String dateString) {
+        // 定义日期格式
+        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+
+        try {
+            // 尝试解析日期字符串
+            LocalDate date = LocalDate.parse(dateString, dateFormatter);
+            return true; // 如果解析成功,返回 true
+        } catch (DateTimeParseException e) {
+            return false; // 如果解析失败,返回 false
+        }
+    }
+
     public static String timestampToYMDStr(Long timestamp, String format) {
 
         // 定义北京时区
@@ -254,4 +268,19 @@ public final class DateUtils {
         date = date.minusDays(days);
         return date.format(formatter);
     }
+
+    public static String getDateString(Long timestamp) {
+        // 创建日期时间格式化器
+        DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyyMMdd");
+        // 将时间戳转换为 LocalDateTime
+        LocalDateTime dateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault());
+        // 格式化日期时间并返回
+        return dateTime.format(dateFormat);
+    }
+
+    public static Date getDate(String dateString) {
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+        LocalDate localDate = LocalDate.parse(dateString, formatter);
+        return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
+    }
 }

+ 1 - 1
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/util/TitleSimilarCheckUtil.java

@@ -9,7 +9,7 @@ import java.util.Set;
 
 public class TitleSimilarCheckUtil {
 
-    private static final double SIMILARITY_THRESHOLD = 0.8; // 相似度阈值
+    public static final double SIMILARITY_THRESHOLD = 0.8; // 相似度阈值
 
     public static boolean isDuplicateContent(String title, List<String> existsContentTitle) {
         boolean result = false;

+ 108 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/util/page/Page.java

@@ -0,0 +1,108 @@
+package com.tzld.longarticle.recommend.server.util.page;
+
+import java.util.List;
+
+public class Page<T> {
+
+    public static final String DEFAULT_PAGE_SIZE = "20";
+    public static final String DEFAULT_CURRENT_PAGE = "1";
+
+    private int currentPage = Integer.valueOf(DEFAULT_CURRENT_PAGE);
+    private int totalSize;
+    private int pageSize = Integer.valueOf(DEFAULT_PAGE_SIZE);
+
+    private List<T> objs;
+
+    private T obj;
+
+    public Page() {
+    }
+
+    public Page(int currentPage) {
+        this.currentPage = currentPage;
+    }
+
+    public Page(int currentPage, int pageSize) {
+        setCurrentPage(currentPage);
+        setPageSize(pageSize);
+    }
+
+    public int getNextPage() {
+        return currentPage == getTotalPage() ? currentPage : currentPage + 1;
+    }
+
+    public int getPrePage() {
+        return currentPage > 1 ? currentPage - 1 : 1;
+    }
+
+    public int getOffset() {
+        return getCurPageFirstRecNum() - 1;
+    }
+
+    public int getCurPageFirstRecNum() {
+        return (getCurrentPage() - 1) * pageSize + 1;
+    }
+
+    public int getCurPageLastRecNum() {
+        return getCurrentPage() * pageSize;
+    }
+
+    public int getTotalPage() {
+        int t = totalSize % pageSize > 0 ? totalSize / pageSize + 1 : totalSize / pageSize;
+        if (t <= 0) {
+            t = 1;
+        }
+        return t;
+    }
+
+    public void setObjs(List<T> objs) {
+        this.objs = objs;
+    }
+
+    public List<T> getObjs() {
+        return objs;
+    }
+
+    public int getCurrentPage() {
+        return currentPage;
+    }
+
+    public void setCurrentPage(int currentPage) {
+        this.currentPage = currentPage;
+    }
+
+    public int getTotalSize() {
+        return totalSize;
+    }
+
+    public void setTotalSize(int totalSize) {
+        this.totalSize = totalSize;
+    }
+
+    public int getPageSize() {
+        return pageSize;
+    }
+
+    public void setPageSize(int pageSize) {
+        if (pageSize > 0) {
+            this.pageSize = pageSize;
+        }
+    }
+
+    public boolean containData() {
+        return getTotalSize() > 0;
+    }
+    @Override
+    public String toString() {
+        return "Page [currentPage=" + getCurrentPage() + ", totalSize=" + getTotalSize() + ", pageSize=" + getPageSize()
+                + "]";
+    }
+
+    public T getObj() {
+        return obj;
+    }
+
+    public void setObj(T obj) {
+        this.obj = obj;
+    }
+}

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

@@ -0,0 +1,54 @@
+package com.tzld.longarticle.recommend.server.web;
+
+
+import com.tzld.longarticle.recommend.server.common.enums.GhTypeEnum;
+import com.tzld.longarticle.recommend.server.common.response.CommonResponse;
+import com.tzld.longarticle.recommend.server.model.vo.GhDetailVo;
+import com.tzld.longarticle.recommend.server.model.vo.GhTypeVo;
+import com.tzld.longarticle.recommend.server.service.exterior.GhDetailService;
+import com.tzld.longarticle.recommend.server.util.page.Page;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Slf4j
+@RestController
+@RequestMapping("/account")
+public class AccountDetailController {
+
+    @Autowired
+    private GhDetailService ghDetailService;
+
+    @GetMapping("/getList")
+    public CommonResponse<Page<GhDetailVo>> getAccountDetailList(@RequestParam Integer pageNum,
+                                                            @RequestParam Integer pageSize,
+                                                            @RequestParam(defaultValue = "") String accountId) {
+        return ghDetailService.getGhDetailList(pageNum, pageSize, accountId);
+    }
+
+    @PostMapping("/add")
+    public CommonResponse<Void> addAccountDetail(@RequestBody GhDetailVo detailVo) {
+        return ghDetailService.addGhDetail(detailVo);
+    }
+
+    @PostMapping("/update")
+    public CommonResponse<Void> updateAccountDetail(@RequestBody GhDetailVo detailVo) {
+        return ghDetailService.updateDetail(detailVo);
+    }
+
+    @GetMapping("/refresh")
+    public CommonResponse<Void> refreshAccountDetail() {
+        return ghDetailService.refreshGhDetail();
+    }
+
+    @GetMapping("/types")
+    public CommonResponse<List<GhTypeVo>> getAllAccountTypes() {
+        return CommonResponse.success(Arrays.stream(GhTypeEnum.values())
+                .map(ghTypeEnum -> new GhTypeVo(ghTypeEnum.type, ghTypeEnum.name))
+                .collect(Collectors.toList()));
+    }
+}

+ 7 - 4
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/web/ThirdPartyController.java

@@ -6,14 +6,12 @@ import com.tzld.longarticle.recommend.server.model.param.CallbackParam;
 import com.tzld.longarticle.recommend.server.model.param.PushMessageParam;
 import com.tzld.longarticle.recommend.server.model.vo.AccessTokenVo;
 import com.tzld.longarticle.recommend.server.model.vo.PushMessageVo;
+import com.tzld.longarticle.recommend.server.model.vo.ReportUvVo;
 import com.tzld.longarticle.recommend.server.mq.MessageCallbackProducer;
 import com.tzld.longarticle.recommend.server.service.exterior.AccessTokenService;
 import com.tzld.longarticle.recommend.server.service.exterior.ThirdPartyService;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
 
@@ -44,4 +42,9 @@ public class ThirdPartyController {
     public CommonResponse<Void> pushMessageCallback(@RequestBody CallbackParam param) {
         return messageCallbackProducer.sendMessage(param);
     }
+
+    @GetMapping("/report/uv")
+    public CommonResponse<List<ReportUvVo>> getReportUv(@RequestParam String date, @RequestParam String accessToken) {
+        return thirdPartyService.getReportUv(date, accessToken);
+    }
 }

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

@@ -38,4 +38,25 @@ public class XxlJobController {
     public void alertPushMessageJob(String dateStr) {
         service.alertPushMessageJob(dateStr);
     }
+
+    @GetMapping("/syncArticleRootPublishId")
+    public void syncArticleRootPublishId(String dateStr) {
+        service.syncArticleRootPublishId(dateStr);
+    }
+
+    @GetMapping("/articlePromotionTraceability")
+    public void articlePromotionTraceability(String channelContentId) {
+        service.articlePromotionTraceability(channelContentId);
+    }
+
+    @GetMapping("/articleCategoryJob")
+    public void articleCategoryJob() {
+        service.articleCategoryJob(null);
+    }
+
+    @GetMapping("/articleCategoryJobRetry")
+    public void articleCategoryJobRetry() {
+        service.articleCategoryJobRetry(null);
+    }
+
 }

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

@@ -0,0 +1,24 @@
+package com.tzld.longarticle.recommend.server.web.recommend;
+
+import com.tzld.longarticle.recommend.server.common.response.CommonResponse;
+import com.tzld.longarticle.recommend.server.model.param.ArticleFindSourceParam;
+import com.tzld.longarticle.recommend.server.service.recommend.ArticleService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/article")
+@Slf4j
+public class ArticleController {
+
+    @Autowired
+    private ArticleService service;
+
+    @PostMapping("/findSource")
+    public CommonResponse<Void> findSource(@RequestBody ArticleFindSourceParam param) {
+        service.findSource(param);
+        return CommonResponse.success();
+    }
+
+}

+ 11 - 0
long-article-recommend-service/src/main/resources/application-dev.yml

@@ -62,6 +62,17 @@ spring:
         maximum-pool-size: 10
         auto-commit: true
         idle-timeout: 30000
+    growth:
+      jdbc-url: jdbc:mysql://rm-bp1k5853td1r25g3n690.mysql.rds.aliyuncs.com:3306/growth?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false
+      username: crawler
+      password: crawler123456@
+      driver-class-name: com.mysql.jdbc.Driver
+      hikari:
+        connection-timeout: 30000
+        minimum-idle: 5
+        maximum-pool-size: 10
+        auto-commit: true
+        idle-timeout: 30000
   jpa:
     crawler:
       hibernate:

+ 11 - 0
long-article-recommend-service/src/main/resources/application-prod.yml

@@ -59,6 +59,17 @@ spring:
         maximum-pool-size: 10
         auto-commit: true
         idle-timeout: 30000
+    growth:
+      jdbc-url: jdbc:mysql://rm-bp17q95335a99272b.mysql.rds.aliyuncs.com:3306/growth?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false
+      username: crawler
+      password: crawler123456@
+      driver-class-name: com.mysql.jdbc.Driver
+      hikari:
+        connection-timeout: 30000
+        minimum-idle: 5
+        maximum-pool-size: 10
+        auto-commit: true
+        idle-timeout: 30000
   jpa:
     crawler:
       hibernate:

+ 55 - 0
long-article-recommend-service/src/main/resources/mapper/aigc/AigcBaseMapper.xml

@@ -144,5 +144,60 @@
         </foreach>
     </select>
 
+    <select id="getNearestPublishContent"
+            resultType="com.tzld.longarticle.recommend.server.model.entity.aigc.PublishContent">
+        select *
+        from publish_content
+        where publish_account_id = #{publishAccountId}
+          and channel = 5
+          and status = 2
+          <if test="publishTimestamp != null">
+            and publish_timestamp &lt;= (#{publishTimestamp} + 3600000)
+          </if>
+        order by publish_timestamp desc
+        <if test="size != null">
+            limit #{size}
+        </if>
+    </select>
+
+    <select id="getCrawlerContentByChannelContentId"
+            resultType="com.tzld.longarticle.recommend.server.model.dto.CrawlerContent">
+        select cc.channel_content_id, ca.wx_gh as ghId, cc.title, cc.publish_timestamp
+        from crawler_content cc
+        join crawler_account ca on cc.channel_account_id = ca.channel_account_id
+        where cc.channel_content_id = #{channelContentId}
+    </select>
+
+    <select id="getProduceContentByPlanId" resultType="com.tzld.longarticle.recommend.server.model.dto.ProduceContentDTO">
+        select distinct record.channel_content_id as contentId,
+               output.output             as title
+        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
+        where record.plan_id = #{planId} and record.status = 2 and audit_status = 1
+    </select>
+    <select id="getAllByProducePlanId"
+            resultType="com.tzld.longarticle.recommend.server.model.entity.aigc.ProducePlanExeRecord">
+        select *
+        from produce_plan_exe_record
+        where plan_id in
+        <foreach collection="producePlanIds" item="item" open="(" close=")" separator=",">
+            #{item}
+        </foreach>
+        and status = 2
+    </select>
+    <select id="getCrawlerContentByChannelContentIdIn"
+            resultType="com.tzld.longarticle.recommend.server.model.dto.CrawlerContent">
+        select cc.channel_content_id, cprr.plan_id as crawlerPlanId, ca.wx_gh as ghId, cc.title, cc.publish_timestamp
+        from crawler_content cc
+        join (select channel_source_id, max(plan_id) as plan_id from crawler_plan_result_rel group by channel_source_id) cprr
+            on cc.channel_content_id = cprr.channel_source_id
+        join crawler_account ca on cc.channel_account_id = ca.channel_account_id
+        where cc.channel_content_id in
+        <foreach collection="channelContentIds" item="item" open="(" close=")" separator=",">
+            #{item}
+        </foreach>
+    </select>
+
 
 </mapper>

+ 19 - 0
long-article-recommend-service/src/main/resources/mapper/crawler/CrawlerBaseMapper.xml

@@ -40,4 +40,23 @@
         update account_avg_info_v3 set status = 0 where gh_id = #{ghId} and update_time != #{date}
     </update>
 
+    <update id="updateArticleAigcId">
+        update official_articles_v2
+        set publish_content_id = #{publishContentId},
+            channel_content_id = #{channelContentId}
+        where wx_sn = #{wxsn}
+    </update>
+    <update id="updateArticleSourceRootId">
+        update official_articles_v2
+        set source_publish_content_id = #{sourcePublishContentId},
+            root_publish_content_id = #{rootPublishContentId},
+            root_produce_content_id = #{rootProduceContentId}
+        where wx_sn = #{wxsn}
+    </update>
+
+    <select id="getWaitingFindArticle"
+            resultType="com.tzld.longarticle.recommend.server.model.entity.crawler.Article">
+        select * from official_articles_v2 where updateTime > #{timestamp} order by updateTime limit 100
+    </select>
+
 </mapper>

+ 1 - 1
long-article-recommend-service/src/main/resources/mapper/crawler/AlgGhAutoreplyVideoRankDataMapper.xml → long-article-recommend-service/src/main/resources/mapper/growth/AlgGhAutoreplyVideoRankDataMapper.xml

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.tzld.longarticle.recommend.server.mapper.crawler.AlgGhAutoreplyVideoRankDataMapper">
+<mapper namespace="com.tzld.longarticle.recommend.server.mapper.growth.AlgGhAutoreplyVideoRankDataMapper">
   <resultMap id="BaseResultMap" type="com.tzld.longarticle.recommend.server.repository.model.AlgGhAutoreplyVideoRankData">
     <id column="id" jdbcType="BIGINT" property="id" />
     <result column="strategy_key" jdbcType="VARCHAR" property="strategyKey" />

+ 1 - 1
long-article-recommend-service/src/main/resources/mapper/crawler/CgiReplyBucketDataMapper.xml → long-article-recommend-service/src/main/resources/mapper/growth/CgiReplyBucketDataMapper.xml

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.tzld.longarticle.recommend.server.mapper.crawler.CgiReplyBucketDataMapper">
+<mapper namespace="com.tzld.longarticle.recommend.server.mapper.growth.CgiReplyBucketDataMapper">
   <resultMap id="BaseResultMap" type="com.tzld.longarticle.recommend.server.repository.model.CgiReplyBucketData">
     <id column="id" jdbcType="BIGINT" property="id" />
     <result column="strategy" jdbcType="VARCHAR" property="strategy" />

+ 276 - 0
long-article-recommend-service/src/main/resources/mapper/growth/GhDetailMapper.xml

@@ -0,0 +1,276 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.tzld.longarticle.recommend.server.mapper.growth.GhDetailMapper">
+  <resultMap id="BaseResultMap" type="com.tzld.longarticle.recommend.server.repository.model.GhDetail">
+    <id column="id" jdbcType="BIGINT" property="id" />
+    <result column="gh_id" jdbcType="VARCHAR" property="ghId" />
+    <result column="gh_name" jdbcType="VARCHAR" property="ghName" />
+    <result column="type" jdbcType="INTEGER" property="type" />
+    <result column="category1" jdbcType="VARCHAR" property="category1" />
+    <result column="category2" jdbcType="VARCHAR" property="category2" />
+    <result column="is_delete" jdbcType="INTEGER" property="isDelete" />
+    <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
+    <result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
+  </resultMap>
+  <sql id="Example_Where_Clause">
+    <where>
+      <foreach collection="oredCriteria" item="criteria" separator="or">
+        <if test="criteria.valid">
+          <trim prefix="(" prefixOverrides="and" suffix=")">
+            <foreach collection="criteria.criteria" item="criterion">
+              <choose>
+                <when test="criterion.noValue">
+                  and ${criterion.condition}
+                </when>
+                <when test="criterion.singleValue">
+                  and ${criterion.condition} #{criterion.value}
+                </when>
+                <when test="criterion.betweenValue">
+                  and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
+                </when>
+                <when test="criterion.listValue">
+                  and ${criterion.condition}
+                  <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
+                    #{listItem}
+                  </foreach>
+                </when>
+              </choose>
+            </foreach>
+          </trim>
+        </if>
+      </foreach>
+    </where>
+  </sql>
+  <sql id="Update_By_Example_Where_Clause">
+    <where>
+      <foreach collection="example.oredCriteria" item="criteria" separator="or">
+        <if test="criteria.valid">
+          <trim prefix="(" prefixOverrides="and" suffix=")">
+            <foreach collection="criteria.criteria" item="criterion">
+              <choose>
+                <when test="criterion.noValue">
+                  and ${criterion.condition}
+                </when>
+                <when test="criterion.singleValue">
+                  and ${criterion.condition} #{criterion.value}
+                </when>
+                <when test="criterion.betweenValue">
+                  and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
+                </when>
+                <when test="criterion.listValue">
+                  and ${criterion.condition}
+                  <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
+                    #{listItem}
+                  </foreach>
+                </when>
+              </choose>
+            </foreach>
+          </trim>
+        </if>
+      </foreach>
+    </where>
+  </sql>
+  <sql id="Base_Column_List">
+    id, gh_id, gh_name, type, category1, category2, is_delete, create_time, update_time
+  </sql>
+  <select id="selectByExample" parameterType="com.tzld.longarticle.recommend.server.repository.model.GhDetailExample" resultMap="BaseResultMap">
+    select
+    <if test="distinct">
+      distinct
+    </if>
+    <include refid="Base_Column_List" />
+    from gh_detail
+    <if test="_parameter != null">
+      <include refid="Example_Where_Clause" />
+    </if>
+    <if test="orderByClause != null">
+      order by ${orderByClause}
+    </if>
+    <if test="page != null">
+      limit #{page.offset} , #{page.pageSize}
+    </if>
+  </select>
+  <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
+    select 
+    <include refid="Base_Column_List" />
+    from gh_detail
+    where id = #{id,jdbcType=BIGINT}
+  </select>
+  <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
+    delete from gh_detail
+    where id = #{id,jdbcType=BIGINT}
+  </delete>
+  <delete id="deleteByExample" parameterType="com.tzld.longarticle.recommend.server.repository.model.GhDetailExample">
+    delete from gh_detail
+    <if test="_parameter != null">
+      <include refid="Example_Where_Clause" />
+    </if>
+  </delete>
+  <insert id="insert" parameterType="com.tzld.longarticle.recommend.server.repository.model.GhDetail">
+    <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Long">
+      SELECT LAST_INSERT_ID()
+    </selectKey>
+    insert into gh_detail (gh_id, gh_name, `type`,
+      category1, category2,
+      create_time, update_time)
+    values (#{ghId,jdbcType=VARCHAR}, #{ghName,jdbcType=VARCHAR}, #{type,jdbcType=INTEGER}, 
+      #{category1,jdbcType=VARCHAR}, #{category2,jdbcType=VARCHAR},
+      #{createTime,jdbcType=TIMESTAMP}, #{updateTime,jdbcType=TIMESTAMP})
+  </insert>
+  <insert id="insertSelective" parameterType="com.tzld.longarticle.recommend.server.repository.model.GhDetail">
+    <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Long">
+      SELECT LAST_INSERT_ID()
+    </selectKey>
+    insert into gh_detail
+    <trim prefix="(" suffix=")" suffixOverrides=",">
+      <if test="ghId != null">
+        gh_id,
+      </if>
+      <if test="ghName != null">
+        gh_name,
+      </if>
+      <if test="type != null">
+        type,
+      </if>
+      <if test="category1 != null">
+        category1,
+      </if>
+      <if test="category2 != null">
+        category2,
+      </if>
+      <if test="isDelete != null">
+        is_delete,
+      </if>
+      <if test="createTime != null">
+        create_time,
+      </if>
+      <if test="updateTime != null">
+        update_time,
+      </if>
+    </trim>
+    <trim prefix="values (" suffix=")" suffixOverrides=",">
+      <if test="ghId != null">
+        #{ghId,jdbcType=VARCHAR},
+      </if>
+      <if test="ghName != null">
+        #{ghName,jdbcType=VARCHAR},
+      </if>
+      <if test="type != null">
+        #{type,jdbcType=INTEGER},
+      </if>
+      <if test="category1 != null">
+        #{category1,jdbcType=VARCHAR},
+      </if>
+      <if test="category2 != null">
+        #{category2,jdbcType=VARCHAR},
+      </if>
+      <if test="isDelete != null">
+        #{isDelete,jdbcType=INTEGER},
+      </if>
+      <if test="createTime != null">
+        #{createTime,jdbcType=TIMESTAMP},
+      </if>
+      <if test="updateTime != null">
+        #{updateTime,jdbcType=TIMESTAMP},
+      </if>
+    </trim>
+  </insert>
+  <select id="countByExample" parameterType="com.tzld.longarticle.recommend.server.repository.model.GhDetailExample" resultType="java.lang.Long">
+    select count(*) from gh_detail
+    <if test="_parameter != null">
+      <include refid="Example_Where_Clause" />
+    </if>
+  </select>
+  <update id="updateByExampleSelective" parameterType="map">
+    update gh_detail
+    <set>
+      <if test="row.id != null">
+        id = #{row.id,jdbcType=BIGINT},
+      </if>
+      <if test="row.ghId != null">
+        gh_id = #{row.ghId,jdbcType=VARCHAR},
+      </if>
+      <if test="row.ghName != null">
+        gh_name = #{row.ghName,jdbcType=VARCHAR},
+      </if>
+      <if test="row.type != null">
+        type = #{row.type,jdbcType=INTEGER},
+      </if>
+      <if test="row.category1 != null">
+        category1 = #{row.category1,jdbcType=VARCHAR},
+      </if>
+      <if test="row.category2 != null">
+        category2 = #{row.category2,jdbcType=VARCHAR},
+      </if>
+      <if test="row.isDelete != null">
+        is_delete = #{row.isDelete,jdbcType=INTEGER},
+      </if>
+      <if test="row.createTime != null">
+        create_time = #{row.createTime,jdbcType=TIMESTAMP},
+      </if>
+      <if test="row.updateTime != null">
+        update_time = #{row.updateTime,jdbcType=TIMESTAMP},
+      </if>
+    </set>
+    <if test="example != null">
+      <include refid="Update_By_Example_Where_Clause" />
+    </if>
+  </update>
+  <update id="updateByExample" parameterType="map">
+    update gh_detail
+    set id = #{row.id,jdbcType=BIGINT},
+      gh_id = #{row.ghId,jdbcType=VARCHAR},
+      gh_name = #{row.ghName,jdbcType=VARCHAR},
+      type = #{row.type,jdbcType=INTEGER},
+      category1 = #{row.category1,jdbcType=VARCHAR},
+      category2 = #{row.category2,jdbcType=VARCHAR},
+      is_delete = #{row.isDelete,jdbcType=INTEGER},
+      create_time = #{row.createTime,jdbcType=TIMESTAMP},
+      update_time = #{row.updateTime,jdbcType=TIMESTAMP}
+    <if test="example != null">
+      <include refid="Update_By_Example_Where_Clause" />
+    </if>
+  </update>
+  <update id="updateByPrimaryKeySelective" parameterType="com.tzld.longarticle.recommend.server.repository.model.GhDetail">
+    update gh_detail
+    <set>
+      <if test="ghId != null">
+        gh_id = #{ghId,jdbcType=VARCHAR},
+      </if>
+      <if test="ghName != null">
+        gh_name = #{ghName,jdbcType=VARCHAR},
+      </if>
+      <if test="type != null">
+        type = #{type,jdbcType=INTEGER},
+      </if>
+      <if test="category1 != null">
+        category1 = #{category1,jdbcType=VARCHAR},
+      </if>
+      <if test="category2 != null">
+        category2 = #{category2,jdbcType=VARCHAR},
+      </if>
+      <if test="isDelete != null">
+        is_delete = #{isDelete,jdbcType=INTEGER},
+      </if>
+      <if test="createTime != null">
+        create_time = #{createTime,jdbcType=TIMESTAMP},
+      </if>
+      <if test="updateTime != null">
+        update_time = #{updateTime,jdbcType=TIMESTAMP},
+      </if>
+    </set>
+    where id = #{id,jdbcType=BIGINT}
+  </update>
+  <update id="updateByPrimaryKey" parameterType="com.tzld.longarticle.recommend.server.repository.model.GhDetail">
+    update gh_detail
+    set gh_id = #{ghId,jdbcType=VARCHAR},
+      gh_name = #{ghName,jdbcType=VARCHAR},
+      type = #{type,jdbcType=INTEGER},
+      category1 = #{category1,jdbcType=VARCHAR},
+      category2 = #{category2,jdbcType=VARCHAR},
+      is_delete = #{isDelete,jdbcType=INTEGER},
+      create_time = #{createTime,jdbcType=TIMESTAMP},
+      update_time = #{updateTime,jdbcType=TIMESTAMP}
+    where id = #{id,jdbcType=BIGINT}
+  </update>
+</mapper>

+ 278 - 0
long-article-recommend-service/src/main/resources/mapper/growth/NewPushMessageCallbackMapper.xml

@@ -0,0 +1,278 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.tzld.longarticle.recommend.server.mapper.growth.NewPushMessageCallbackMapper">
+    <resultMap id="BaseResultMap" type="com.tzld.longarticle.recommend.server.repository.model.PushMessageCallback">
+        <id column="id" jdbcType="BIGINT" property="id"/>
+        <result column="gh_id" jdbcType="VARCHAR" property="ghId"/>
+        <result column="open_id" jdbcType="VARCHAR" property="openId"/>
+        <result column="timestamp" jdbcType="BIGINT" property="timestamp"/>
+        <result column="msg_type" jdbcType="INTEGER" property="msgType"/>
+        <result column="video_id" jdbcType="BIGINT" property="videoId"/>
+        <result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
+    </resultMap>
+    <sql id="Example_Where_Clause">
+        <where>
+            <foreach collection="oredCriteria" item="criteria" separator="or">
+                <if test="criteria.valid">
+                    <trim prefix="(" prefixOverrides="and" suffix=")">
+                        <foreach collection="criteria.criteria" item="criterion">
+                            <choose>
+                                <when test="criterion.noValue">
+                                    and ${criterion.condition}
+                                </when>
+                                <when test="criterion.singleValue">
+                                    and ${criterion.condition} #{criterion.value}
+                                </when>
+                                <when test="criterion.betweenValue">
+                                    and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
+                                </when>
+                                <when test="criterion.listValue">
+                                    and ${criterion.condition}
+                                    <foreach close=")" collection="criterion.value" item="listItem" open="("
+                                             separator=",">
+                                        #{listItem}
+                                    </foreach>
+                                </when>
+                            </choose>
+                        </foreach>
+                    </trim>
+                </if>
+            </foreach>
+        </where>
+    </sql>
+    <sql id="Update_By_Example_Where_Clause">
+        <where>
+            <foreach collection="example.oredCriteria" item="criteria" separator="or">
+                <if test="criteria.valid">
+                    <trim prefix="(" prefixOverrides="and" suffix=")">
+                        <foreach collection="criteria.criteria" item="criterion">
+                            <choose>
+                                <when test="criterion.noValue">
+                                    and ${criterion.condition}
+                                </when>
+                                <when test="criterion.singleValue">
+                                    and ${criterion.condition} #{criterion.value}
+                                </when>
+                                <when test="criterion.betweenValue">
+                                    and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
+                                </when>
+                                <when test="criterion.listValue">
+                                    and ${criterion.condition}
+                                    <foreach close=")" collection="criterion.value" item="listItem" open="("
+                                             separator=",">
+                                        #{listItem}
+                                    </foreach>
+                                </when>
+                            </choose>
+                        </foreach>
+                    </trim>
+                </if>
+            </foreach>
+        </where>
+    </sql>
+    <sql id="Base_Column_List">
+        id
+        , gh_id, open_id, timestamp, msg_type, video_id, create_time
+    </sql>
+    <select id="selectByExample"
+            parameterType="com.tzld.longarticle.recommend.server.repository.model.PushMessageCallbackExample"
+            resultMap="BaseResultMap">
+        select
+        <if test="distinct">
+            distinct
+        </if>
+        <include refid="Base_Column_List"/>
+        from push_message_callback
+        <if test="_parameter != null">
+            <include refid="Example_Where_Clause"/>
+        </if>
+        <if test="orderByClause != null">
+            order by ${orderByClause}
+        </if>
+    </select>
+    <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
+        select
+        <include refid="Base_Column_List"/>
+        from push_message_callback
+        where id = #{id,jdbcType=BIGINT}
+    </select>
+    <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
+        delete
+        from push_message_callback
+        where id = #{id,jdbcType=BIGINT}
+    </delete>
+    <delete id="deleteByExample"
+            parameterType="com.tzld.longarticle.recommend.server.repository.model.PushMessageCallbackExample">
+        delete from push_message_callback
+        <if test="_parameter != null">
+            <include refid="Example_Where_Clause"/>
+        </if>
+    </delete>
+    <insert id="insert" parameterType="com.tzld.longarticle.recommend.server.repository.model.PushMessageCallback">
+        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Long">
+            SELECT LAST_INSERT_ID()
+        </selectKey>
+        insert into push_message_callback (gh_id, open_id, timestamp,
+        msg_type, video_id, create_time
+        )
+        values (#{ghId,jdbcType=VARCHAR}, #{openId,jdbcType=VARCHAR}, #{timestamp,jdbcType=BIGINT},
+        #{msgType,jdbcType=INTEGER}, #{videoId,jdbcType=BIGINT}, #{createTime,jdbcType=TIMESTAMP}
+        )
+    </insert>
+    <insert id="insertSelective"
+            parameterType="com.tzld.longarticle.recommend.server.repository.model.PushMessageCallback">
+        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Long">
+            SELECT LAST_INSERT_ID()
+        </selectKey>
+        insert into push_message_callback
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="ghId != null">
+                gh_id,
+            </if>
+            <if test="openId != null">
+                open_id,
+            </if>
+            <if test="timestamp != null">
+                timestamp,
+            </if>
+            <if test="msgType != null">
+                msg_type,
+            </if>
+            <if test="videoId != null">
+                video_id,
+            </if>
+            <if test="createTime != null">
+                create_time,
+            </if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="ghId != null">
+                #{ghId,jdbcType=VARCHAR},
+            </if>
+            <if test="openId != null">
+                #{openId,jdbcType=VARCHAR},
+            </if>
+            <if test="timestamp != null">
+                #{timestamp,jdbcType=BIGINT},
+            </if>
+            <if test="msgType != null">
+                #{msgType,jdbcType=INTEGER},
+            </if>
+            <if test="videoId != null">
+                #{videoId,jdbcType=BIGINT},
+            </if>
+            <if test="createTime != null">
+                #{createTime,jdbcType=TIMESTAMP},
+            </if>
+        </trim>
+    </insert>
+    <select id="countByExample"
+            parameterType="com.tzld.longarticle.recommend.server.repository.model.PushMessageCallbackExample"
+            resultType="java.lang.Long">
+        select count(*) from push_message_callback
+        <if test="_parameter != null">
+            <include refid="Example_Where_Clause"/>
+        </if>
+    </select>
+    <update id="updateByExampleSelective" parameterType="map">
+        update push_message_callback
+        <set>
+            <if test="row.id != null">
+                id = #{row.id,jdbcType=BIGINT},
+            </if>
+            <if test="row.ghId != null">
+                gh_id = #{row.ghId,jdbcType=VARCHAR},
+            </if>
+            <if test="row.openId != null">
+                open_id = #{row.openId,jdbcType=VARCHAR},
+            </if>
+            <if test="row.timestamp != null">
+                timestamp = #{row.timestamp,jdbcType=BIGINT},
+            </if>
+            <if test="row.msgType != null">
+                msg_type = #{row.msgType,jdbcType=INTEGER},
+            </if>
+            <if test="row.videoId != null">
+                video_id = #{row.videoId,jdbcType=BIGINT},
+            </if>
+            <if test="row.createTime != null">
+                create_time = #{row.createTime,jdbcType=TIMESTAMP},
+            </if>
+        </set>
+        <if test="example != null">
+            <include refid="Update_By_Example_Where_Clause"/>
+        </if>
+    </update>
+    <update id="updateByExample" parameterType="map">
+        update push_message_callback
+        set id = #{row.id,jdbcType=BIGINT},
+        gh_id = #{row.ghId,jdbcType=VARCHAR},
+        open_id = #{row.openId,jdbcType=VARCHAR},
+        timestamp = #{row.timestamp,jdbcType=BIGINT},
+        msg_type = #{row.msgType,jdbcType=INTEGER},
+        video_id = #{row.videoId,jdbcType=BIGINT},
+        create_time = #{row.createTime,jdbcType=TIMESTAMP}
+        <if test="example != null">
+            <include refid="Update_By_Example_Where_Clause"/>
+        </if>
+    </update>
+    <update id="updateByPrimaryKeySelective"
+            parameterType="com.tzld.longarticle.recommend.server.repository.model.PushMessageCallback">
+        update push_message_callback
+        <set>
+            <if test="ghId != null">
+                gh_id = #{ghId,jdbcType=VARCHAR},
+            </if>
+            <if test="openId != null">
+                open_id = #{openId,jdbcType=VARCHAR},
+            </if>
+            <if test="timestamp != null">
+                timestamp = #{timestamp,jdbcType=BIGINT},
+            </if>
+            <if test="msgType != null">
+                msg_type = #{msgType,jdbcType=INTEGER},
+            </if>
+            <if test="videoId != null">
+                video_id = #{videoId,jdbcType=BIGINT},
+            </if>
+            <if test="createTime != null">
+                create_time = #{createTime,jdbcType=TIMESTAMP},
+            </if>
+        </set>
+        where id = #{id,jdbcType=BIGINT}
+    </update>
+    <update id="updateByPrimaryKey"
+            parameterType="com.tzld.longarticle.recommend.server.repository.model.PushMessageCallback">
+        update push_message_callback
+        set gh_id       = #{ghId,jdbcType=VARCHAR},
+            open_id     = #{openId,jdbcType=VARCHAR},
+            timestamp   = #{timestamp,jdbcType=BIGINT},
+            msg_type    = #{msgType,jdbcType=INTEGER},
+            video_id    = #{videoId,jdbcType=BIGINT},
+            create_time = #{createTime,jdbcType=TIMESTAMP}
+        where id = #{id,jdbcType=BIGINT}
+    </update>
+
+    <insert id="insertList" parameterType="java.util.List">
+        insert into push_message_callback
+        (
+        gh_id,
+        open_id,
+        timestamp,
+        msg_type,
+        video_id,
+        create_time
+        )
+        values
+        <foreach collection="list" item="item" separator=",">
+            (
+            #{item.ghId,jdbcType=VARCHAR},
+            #{item.openId,jdbcType=VARCHAR},
+            #{item.timestamp,jdbcType=BIGINT},
+            #{item.msgType,jdbcType=INTEGER},
+            #{item.videoId,jdbcType=BIGINT},
+            #{item.createTime,jdbcType=TIMESTAMP}
+            )
+        </foreach>
+    </insert>
+</mapper>

+ 1 - 1
long-article-recommend-service/src/main/resources/mapper/crawler/ReplyStaffMapper.xml → long-article-recommend-service/src/main/resources/mapper/growth/ReplyStaffMapper.xml

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.tzld.longarticle.recommend.server.mapper.crawler.ReplyStaffMapper">
+<mapper namespace="com.tzld.longarticle.recommend.server.mapper.growth.ReplyStaffMapper">
   <resultMap id="BaseResultMap" type="com.tzld.longarticle.recommend.server.repository.model.ReplyStaff">
     <id column="id" jdbcType="BIGINT" property="id" />
     <result column="user_id" jdbcType="VARCHAR" property="userId" />

+ 40 - 0
long-article-recommend-service/src/main/resources/mapper/longArticle/LongArticleBaseMapper.xml

@@ -41,4 +41,44 @@
         </foreach>
     </insert>
 
+    <insert id="batchInsertArticlePoolPromotionSource">
+        insert into article_pool_promotion_source
+            (channel_content_id, source_publish_content_id, root_publish_content_id, root_produce_content_id, title,
+             title_md5, level, status, deleted, create_timestamp, update_timestamp)
+        values
+        <foreach collection="list" item="item" separator=",">
+            (#{item.channelContentId}, #{item.sourcePublishContentId}, #{item.rootPublishContentId},
+               #{item.rootProduceContentId}, #{item.title}, #{item.titleMd5}, #{item.level}, #{item.status},
+               #{item.deleted}, #{item.createTimestamp}, #{item.updateTimestamp})
+        </foreach>
+    </insert>
+
+    <update id="updateRootProduceContentLevel">
+        update article_pool_promotion_source set level = #{level} where root_produce_content_id = #{rootProduceContentId}
+    </update>
+
+    <insert id="batchInsertDatastatScore">
+        INSERT INTO datastat_score
+        (dt, gh_id, account_name, `index`, title, strategy, score, similarity, view_count_rate,
+         his_fission_avg_read_rate_rate, his_fission_avg_read_sum_rate, his_fission_de_weight_avg_read_sum_rate,
+        read_count, read_avg, read_avg_rate)
+        VALUES
+        <foreach collection="list" item="item" separator=",">
+            (#{item.dt}, #{item.ghId}, #{item.accountName}, #{item.index}, #{item.title}, #{item.strategy},
+             #{item.score}, #{item.similarity}, #{item.viewCountRate}, #{item.hisFissionAvgReadRateRate},
+            #{item.hisFissionAvgReadSumRate}, #{item.hisFissionDeWeightAvgReadSumRate}, #{item.readCount},
+             #{item.readAvg}, #{item.readAvgRate})
+        </foreach>
+    </insert>
+
+    <insert id="batchInsertArticleCategory">
+        INSERT INTO article_category
+        (produce_content_id, channel_content_id, crawler_plan_id, title, title_md5, create_timestamp)
+        VALUES
+        <foreach collection="list" item="item" separator=",">
+            (#{item.produceContentId}, #{item.channelContentId}, #{item.crawlerPlanId}, #{item.title}, #{item.titleMd5},
+             #{item.createTimestamp})
+        </foreach>
+    </insert>
+
 </mapper>

+ 95 - 0
long-article-recommend-service/src/test/java/com/tzld/longarticle/recommend/server/XxlJobTest.java

@@ -0,0 +1,95 @@
+package com.tzld.longarticle.recommend.server;
+
+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.CrawlerContent;
+import com.tzld.longarticle.recommend.server.model.dto.ProduceContentDTO;
+import com.tzld.longarticle.recommend.server.model.entity.aigc.ProducePlanExeRecord;
+import com.tzld.longarticle.recommend.server.model.entity.longArticle.ArticleCategory;
+import com.tzld.longarticle.recommend.server.model.entity.longArticle.ArticlePoolPromotionSource;
+import com.tzld.longarticle.recommend.server.model.vo.ProduceContentCrawlerVO;
+import com.tzld.longarticle.recommend.server.repository.longArticle.ArticleCategoryRepository;
+import com.tzld.longarticle.recommend.server.repository.longArticle.ArticlePoolPromotionSourceRepository;
+import com.tzld.longarticle.recommend.server.service.recommend.ArticleService;
+import com.tzld.longarticle.recommend.server.util.Md5Util;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import javax.annotation.Resource;
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+@SpringBootTest(classes = Application.class)
+public class XxlJobTest {
+    @Resource
+    private ArticleService articleService;
+    @Resource
+    private AigcBaseMapper aigcBaseMapper;
+    @Resource
+    private LongArticleBaseMapper longArticleBaseMapper;
+    @Resource
+    private ArticlePoolPromotionSourceRepository articlePoolPromotionSourceRepository;
+    @Resource
+    private ArticleCategoryRepository articleCategoryRepository;
+
+    @Test
+    public void test() {
+        List<String> planIds = Arrays.asList("20240804003153130851174", "20240802171417146947657", "20240802143345289374071");
+        List<String> levels = Arrays.asList("autoArticlePoolLevel3", "autoArticlePoolLevel1", "autoArticlePoolLevel1");
+        List<ArticlePoolPromotionSource> dis = articlePoolPromotionSourceRepository.findAll();
+        List<String> channelContentIds = dis.stream().map(ArticlePoolPromotionSource::getChannelContentId).collect(Collectors.toList());
+        for (int i = 0; i < planIds.size(); i++) {
+            List<ProduceContentDTO> list = aigcBaseMapper.getProduceContentByPlanId(planIds.get(i));
+            list = list.stream().filter(item -> !channelContentIds.contains(item.getContentId())).collect(Collectors.toList());
+            List<ArticlePoolPromotionSource> saveList = new ArrayList<>();
+            for (ProduceContentDTO produceContentDTO : list) {
+                ArticlePoolPromotionSource item = new ArticlePoolPromotionSource();
+                item.setChannelContentId(produceContentDTO.getContentId());
+                item.setTitle(produceContentDTO.getTitle());
+                item.setTitleMd5(Md5Util.encoderByMd5(produceContentDTO.getTitle()));
+                item.setLevel(levels.get(i));
+                item.setCreateTimestamp(System.currentTimeMillis());
+                saveList.add(item);
+            }
+            articlePoolPromotionSourceRepository.saveAll(saveList);
+        }
+    }
+
+    @Test
+    public void articleCategoryTest() {
+        List<String> producePlanIds = Arrays.asList("20240802021606053813696", "20240802080355355308981",
+                "20240805154433785506170", "20240805154359027876170", "20241024100016206421084", "20241030070010871546586");
+        List<ProducePlanExeRecord> produceContentList = aigcBaseMapper.getAllByProducePlanId(producePlanIds);
+        List<String> channelContentIds = produceContentList.stream().map(ProducePlanExeRecord::getChannelContentId).distinct().collect(Collectors.toList());
+        List<ArticleCategory> articleCategoryList = articleCategoryRepository.getAllByChannelContentIdIn(channelContentIds);
+        List<String>  articleCategoryIds = articleCategoryList.stream().map(ArticleCategory::getChannelContentId).collect(Collectors.toList());
+        List<ProduceContentCrawlerVO> list = produceContentList.stream().filter(o -> !articleCategoryIds.contains(o.getChannelContentId())).map(o -> {
+            ProduceContentCrawlerVO item = new ProduceContentCrawlerVO();
+            item.setChannelContentId(o.getChannelContentId());
+            item.setProduceContentId(o.getPlanExeId());
+            return item;
+        }).collect(Collectors.toList());
+        channelContentIds = channelContentIds.stream().filter(o -> !articleCategoryIds.contains(o)).collect(Collectors.toList());
+        List<CrawlerContent> crawlerContentList = aigcBaseMapper.getCrawlerContentByChannelContentIdIn(channelContentIds);
+        Map<String, CrawlerContent> map = crawlerContentList.stream().collect(Collectors.toMap(CrawlerContent::getChannelContentId, Function.identity()));
+        long now = System.currentTimeMillis();
+        List<ArticleCategory> saveList = new ArrayList<>();
+        for (ProduceContentCrawlerVO vo : list) {
+            ArticleCategory item = new ArticleCategory();
+            item.setChannelContentId(vo.getChannelContentId());
+            item.setProduceContentId(vo.getProduceContentId());
+            CrawlerContent crawlerContent = map.get(vo.getChannelContentId());
+            if (Objects.nonNull(crawlerContent)) {
+                String title = crawlerContent.getTitle();
+                item.setCrawlerPlanId(crawlerContent.getCrawlerPlanId());
+                item.setTitle(title);
+                item.setTitleMd5(Md5Util.encoderByMd5(title));
+                item.setCreateTimestamp(now);
+                saveList.add(item);
+            }
+        }
+        longArticleBaseMapper.batchInsertArticleCategory(saveList);
+
+    }
+}