Prechádzať zdrojové kódy

Merge branch 'wyp/1029-rootId' of Server/long-article-recommend into master

wangyunpeng 10 mesiacov pred
rodič
commit
debfdfb554
30 zmenil súbory, kde vykonal 883 pridanie a 7 odobranie
  1. 28 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/common/enums/StatusEnum.java
  2. 43 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/common/enums/aigc/PublishContentTypeEnum.java
  3. 1 1
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/common/enums/aigc/PushTypeEnum.java
  4. 30 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/common/enums/recommend/ArticlePoolPromotionSourceStatusEnum.java
  5. 7 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/mapper/aigc/AigcBaseMapper.java
  6. 6 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/mapper/crawler/CrawlerBaseMapper.java
  7. 5 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/mapper/longArticle/LongArticleBaseMapper.java
  8. 11 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/dto/CrawlerContent.java
  9. 82 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/entity/aigc/PublishContentOutput.java
  10. 12 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/entity/crawler/Article.java
  11. 43 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/entity/longArticle/ArticlePoolPromotionSource.java
  12. 10 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/param/ArticleFindSourceParam.java
  13. 18 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/vo/RootPublishContentVO.java
  14. 2 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/aigc/PublishAccountRepository.java
  15. 13 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/aigc/PublishContentOutputRepository.java
  16. 4 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/crawler/ArticleRepository.java
  17. 17 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/longArticle/ArticlePoolPromotionSourceRepository.java
  18. 18 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/XxlJobService.java
  19. 310 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/ArticleService.java
  20. 14 4
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/DataDashboardService.java
  21. 1 1
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/RecommendService.java
  22. 1 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/filter/FilterService.java
  23. 52 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/filter/strategy/ArticlePromotionStrategy.java
  24. 1 1
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/util/TitleSimilarCheckUtil.java
  25. 10 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/web/XxlJobController.java
  26. 24 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/web/recommend/ArticleController.java
  27. 33 0
      long-article-recommend-service/src/main/resources/mapper/aigc/AigcBaseMapper.xml
  28. 19 0
      long-article-recommend-service/src/main/resources/mapper/crawler/CrawlerBaseMapper.xml
  29. 16 0
      long-article-recommend-service/src/main/resources/mapper/longArticle/LongArticleBaseMapper.xml
  30. 52 0
      long-article-recommend-service/src/test/java/com/tzld/longarticle/recommend/server/XxlJobTest.java

+ 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 {
+
+    FAIL(0, "fail"),
+    SUCCESS(1, "success"),
+    ;
+
+    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;
 

+ 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;
+    }
+
+}

+ 7 - 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,10 @@ 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<ProduceContentDTO> getProduceContentByPlanId(String planId);
 }

+ 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);
 }

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

@@ -1,6 +1,7 @@
 package com.tzld.longarticle.recommend.server.mapper.longArticle;
 
 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;
 
@@ -15,5 +16,9 @@ public interface LongArticleBaseMapper {
 
     void batchInsertDatastatSortStrategy(List<DatastatSortStrategy> list);
 
+    void batchInsertArticlePoolPromotionSource(List<ArticlePoolPromotionSource> list);
+
+    void updateRootProduceContentLevel(String rootProduceContentId, String level);
+
     void batchInsertDatastatScore(List<DatastatScore> list);
 }

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

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

+ 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;
+
+}

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

@@ -72,5 +72,17 @@ public class Article implements Serializable {
     private String articleGroup;
     @Column(name = "status")
     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;
 }
 

+ 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;
+
+}

+ 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;
+}

+ 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<>();
+
+}

+ 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);
+
 }

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

@@ -0,0 +1,17 @@
+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> getByChannelContentIdInAndStatusAndDeleted(List<String> channelContentIds, Integer status, Integer deleted);
+
+    List<ArticlePoolPromotionSource> getByStatus(Integer status);
+}

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

@@ -20,6 +20,7 @@ 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;
@@ -28,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;
@@ -70,6 +72,8 @@ public class XxlJobService {
     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;
@@ -373,4 +377,18 @@ public class XxlJobService {
         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;
+    }
 }

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

@@ -0,0 +1,310 @@
+package com.tzld.longarticle.recommend.server.service.recommend;
+
+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.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.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.ArticlePoolPromotionSource;
+import com.tzld.longarticle.recommend.server.model.param.ArticleFindSourceParam;
+import com.tzld.longarticle.recommend.server.model.vo.RootPublishContentVO;
+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.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.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.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+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;
+
+    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.getByStatus(0);
+        }
+        long now = System.currentTimeMillis();
+        for (ArticlePoolPromotionSource task : tasks) {
+            // 溯源
+            Article article = articleRepository.getByWxSn(task.getWxSn());
+            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)) {
+                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.SUCCESS.getCode());
+                articlePoolPromotionSourceRepository.save(task);
+            }
+        }
+    }
+}

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

@@ -878,13 +878,25 @@ public class DataDashboardService {
             list = list.stream().filter(publish -> publish.getUpdateTime() < (article.getUpdateTime() - 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);
             // 发布依赖表现
@@ -1220,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())) {
@@ -1230,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.getUpdateTime(), article.getItemIndex());
             if (Objects.nonNull(accountAvgInfo)) {
                 item.setFansCount(item.getFansCount() + accountAvgInfo.getFans());
             }

+ 1 - 1
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;

+ 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;
+    }
+
+}

+ 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;

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

@@ -38,4 +38,14 @@ 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);
+    }
 }

+ 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();
+    }
+
+}

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

@@ -144,5 +144,38 @@
         </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>
+
 
 </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>

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

@@ -41,6 +41,22 @@
         </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,

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

@@ -0,0 +1,52 @@
+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.ProduceContentDTO;
+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.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.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+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;
+
+    @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);
+        }
+    }
+}