Parcourir la source

Merge branch 'wyp/1118-articlePromotion' of Server/long-article-recommend into master

wangyunpeng il y a 7 mois
Parent
commit
3f816ce0e0
37 fichiers modifiés avec 1241 ajouts et 39 suppressions
  1. 47 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/common/enums/aigc/CrawlerModeEnum.java
  2. 3 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/mapper/longArticle/LongArticleBaseMapper.java
  3. 28 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/vo/IdNameVO.java
  4. 52 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/vo/WxContentDetailResponse.java
  5. 15 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/vo/aigc/CommonListDataVO.java
  6. 1 1
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/vo/aigc/ProduceAuditLayoutContentObjVO.java
  7. 69 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/vo/aigc/ProduceContentListItemVO.java
  8. 30 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/vo/aigc/ProducePlanDetailVO.java
  9. 13 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/vo/aigc/ProducePlanInputSourceGroupOrderParam.java
  10. 25 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/vo/aigc/ProducePlanInputSourceGroupParam.java
  11. 20 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/vo/aigc/ProducePlanInputSourceParam.java
  12. 17 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/vo/aigc/SaveFilterConditionParam.java
  13. 5 6
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/remote/WxFetchRemoteService.java
  14. 75 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/remote/aigc/AIGCCrawlerPlanSaveService.java
  15. 95 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/remote/aigc/AIGCProduceContentListService.java
  16. 73 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/remote/aigc/AIGCProducePlanDetailService.java
  17. 85 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/remote/aigc/AIGCProducePlanSaveService.java
  18. 2 2
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/remote/aigc/AIGCWaitingPublishContentService.java
  19. 5 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/longArticle/DatastatSortStrategyRepository.java
  20. 5 5
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/JobService.java
  21. 15 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/XxlJobService.java
  22. 325 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/ArticlePromotionService.java
  23. 16 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/ArticleService.java
  24. 1 1
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/DataDashboardService.java
  25. 3 3
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/filter/strategy/BadStrategy.java
  26. 1 1
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/filter/strategy/HistoryTitleForFwhColdStartStrategy.java
  27. 2 2
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/filter/strategy/HistoryTitleStrategy.java
  28. 2 2
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/filter/strategy/InfiniteHisTitleStrategy.java
  29. 1 1
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/filter/strategy/SensitiveStrategy.java
  30. 5 5
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/rank/RankStrategy.java
  31. 3 3
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/recall/RecallService.java
  32. 5 4
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/util/TitleSimilarCheckUtil.java
  33. 5 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/web/XxlJobController.java
  34. 51 0
      long-article-recommend-service/src/main/resources/file/长文_抓取计划_根据url列表抓取.json
  35. 124 0
      long-article-recommend-service/src/main/resources/file/长文_生成结果库_根据计划id获取内容.json
  36. 14 0
      long-article-recommend-service/src/main/resources/mapper/longArticle/LongArticleBaseMapper.xml
  37. 3 3
      long-article-recommend-service/src/test/java/com/tzld/longarticle/recommend/server/FilterStrategyTest.java

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

@@ -0,0 +1,47 @@
+package com.tzld.longarticle.recommend.server.common.enums.aigc;
+
+import lombok.Getter;
+
+/**
+ * @description:抓取模式
+ * @author: TanJingyu
+ * @create:2023-10-09 16:39:29
+ **/
+@Getter
+public enum CrawlerModeEnum {
+    DesignatedBlogger(1, "指定博主"),
+    CategoryBlogger(2, "分类博主"),
+    RecommendedBlogger(3, "推荐流博主"),
+    Account(4, "账号"),
+    ContentIDs(5, "内容IDs"),
+    KeywordSearch(6, "关键词搜索"),
+    HotList(7, "热榜"),
+    Recommended(8, "推荐"),
+    ImageSearch(9, "图片搜索"),
+    AlgorithmRecommended(10, "算法推荐"),
+    BloggerList(11, "博主榜单"),
+    RankList(12, "榜单"),
+    RelRecommended(13, "相关推荐"),
+
+    PublishContentIds(101, "Aigc发布内容Id"),
+
+    Other(999, "其他");
+
+    private final int val;
+    private final String description;
+
+    CrawlerModeEnum(int val, String description) {
+        this.val = val;
+        this.description = description;
+    }
+
+    public static CrawlerModeEnum from(int val) {
+        for (CrawlerModeEnum typeEnum : CrawlerModeEnum.values()) {
+            if (typeEnum.getVal() == val) {
+                return typeEnum;
+            }
+        }
+
+        return Other;
+    }
+}

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

@@ -26,4 +26,7 @@ public interface LongArticleBaseMapper {
     void batchInsertDatastatScore(List<DatastatScore> list);
 
     void batchInsertArticleCategory(List<ArticleCategory> list);
+
+    List<DatastatSortStrategy> getArticlePromotion(Integer viewCount, Double viewCountRate,
+                                                   Integer fans, String dateStr, List<Integer> positions);
 }

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

@@ -0,0 +1,28 @@
+package com.tzld.longarticle.recommend.server.model.vo;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+import java.util.Objects;
+
+@Getter
+@Setter
+@Accessors(chain = true)
+public class IdNameVO<T> {
+    private T id;
+    private String name;
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        IdNameVO<?> idNameVO = (IdNameVO<?>) o;
+        return Objects.equals(id, idNameVO.id);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(id);
+    }
+}

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

@@ -0,0 +1,52 @@
+package com.tzld.longarticle.recommend.server.model.vo;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+@Getter
+@Setter
+public class WxContentDetailResponse {
+    private String channelContentId;
+    private String title;
+    private String bodyText;
+    private Long publishTimestamp;
+    private List<MiniProgram> miniProgram;
+    private AdInfo adInfo;
+    private Integer viewCount;
+    private Integer likeCount;
+    private Integer shareCount;
+
+    public AdInfo getAdInfo() {
+        if (Objects.isNull(adInfo)) {
+            return new AdInfo();
+        }
+        return adInfo;
+    }
+
+    public List<MiniProgram> getMiniProgram() {
+        if (Objects.isNull(miniProgram)) {
+            return new ArrayList<>();
+        }
+        return miniProgram;
+    }
+
+    @Getter
+    @Setter
+    public static class AdInfo {
+        @JSONField(name = "文中")
+        private Integer middle;
+        @JSONField(name = "文末")
+        private Integer tail;
+    }
+
+    @Getter
+    @Setter
+    public static class MiniProgram {
+        private String path;
+    }
+}

+ 15 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/vo/aigc/CommonListDataVO.java

@@ -0,0 +1,15 @@
+package com.tzld.longarticle.recommend.server.model.vo.aigc;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+import java.util.List;
+
+@Getter
+@Setter
+@Accessors(chain = true)
+public class CommonListDataVO<T> {
+    private Integer totalCount;
+    private List<T> data;
+}

+ 1 - 1
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/vo/ProduceAuditLayoutContentObjVO.java → long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/vo/aigc/ProduceAuditLayoutContentObjVO.java

@@ -1,4 +1,4 @@
-package com.tzld.longarticle.recommend.server.model.vo;
+package com.tzld.longarticle.recommend.server.model.vo.aigc;
 
 import lombok.Getter;
 import lombok.Setter;

+ 69 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/vo/aigc/ProduceContentListItemVO.java

@@ -0,0 +1,69 @@
+package com.tzld.longarticle.recommend.server.model.vo.aigc;
+
+import com.tzld.longarticle.recommend.server.model.vo.IdNameVO;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+import java.util.List;
+
+@Getter
+@Setter
+@Accessors(chain = true)
+public class ProduceContentListItemVO {
+    private String id;
+    private String coverImageUrl;
+    private List<String> imageUrls;
+    private String title;
+    private String bodyText;
+    private List<String> animationUrls;
+    private String prePublishContentId;
+    private String prePublishContentIdLink;
+    private String actionAccountId;
+    private String commentDetail;
+    private String letterDetail;
+    private String receiveId;
+    private String receiveIdLink;
+    private String receiveContent;
+    private String sendAccountId;
+//    private PublishAccountSimpleVO sendAccountData;
+    private String replyCommentDetail;
+    private String replyLetterDetail;
+    private List<String> inputSrtTexts;
+    private List<String> inputImageUrls;
+    private Integer produceAgainFlag;
+    private Long produceAgainCount;
+    private Long produceAgainTimestamp;
+    private List<String> compositeVideoUrls;
+    private Integer compositeStatus;
+    private Integer compositeCount;
+    private Integer uploadVideoFlag;
+    private IdNameVO<String> sourceProducePlan;
+//    private List<ProducePlanQuoteVO<String>> quotePublishPlans;
+    private String referContentTitle;
+    private String referContentLink;
+    private String referContentAccountName;
+    private String referContentAccountLink;
+    private Integer referContentChannel;
+//    private List<ProduceReferContentVO> referContents;
+    private Long produceTimestamp;
+    private Integer auditStatus;
+    private String auditAccount;
+    private Long auditTimestamp;
+    private List<Integer> editModuleTypes;
+    private String editAccount;
+    private Long editTimestamp;
+    private Integer produceStatus;
+    private String errorMsg;
+//    private List<ProducePlanErrorDetailVO> errorDetails;
+    private String tagJson;
+//    private List<CrawlerContentMiniProgramVO> miniProgramList;
+//    private List<ListFieldValueVO> expressionValue;
+    private Integer reviewFlag;
+//    private List<ProduceContentReviewStatusVO> reviewStatusList;
+    private Integer reviewSetCount;
+    private Integer reviewFinishCount;
+    private List<String> reviewInfoList;
+    private Long lastReviewTimestamp;
+
+}

+ 30 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/vo/aigc/ProducePlanDetailVO.java

@@ -0,0 +1,30 @@
+package com.tzld.longarticle.recommend.server.model.vo.aigc;
+
+import com.alibaba.fastjson.JSONArray;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+@Getter
+@Setter
+public class ProducePlanDetailVO {
+    private String id;
+    private String name;
+    private Integer produceModal;
+    private String planTag;
+    private Integer tagPenetrateFlag;
+    private Integer inputType;
+    private Integer inputModal;
+    private Integer inputChannel;
+    private Integer layoutType;
+    private Integer activeManualReview;
+    private Integer activeManualReviewCount;
+    private Integer autoComposite;
+    private Integer dailyProduceNum;
+    private Integer totalProduceNum;
+    private Integer maxConcurrentNum;
+    private List<ProducePlanInputSourceGroupParam> inputSourceGroups;
+    private JSONArray moduleGroups;
+    private JSONArray tasks;
+}

+ 13 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/vo/aigc/ProducePlanInputSourceGroupOrderParam.java

@@ -0,0 +1,13 @@
+package com.tzld.longarticle.recommend.server.model.vo.aigc;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+@Getter
+@Setter
+@Accessors(chain = true)
+public class ProducePlanInputSourceGroupOrderParam {
+    private Integer orderField;
+    private String orderType;
+}

+ 25 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/vo/aigc/ProducePlanInputSourceGroupParam.java

@@ -0,0 +1,25 @@
+package com.tzld.longarticle.recommend.server.model.vo.aigc;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+@Getter
+@Setter
+public class ProducePlanInputSourceGroupParam {
+    private Integer inputType;
+    private String groupId;
+    private String exampleCaseId;
+    private String groupName;
+    private Integer groupIndex;
+    private Integer batchActive;
+    private List<ProducePlanInputSourceParam> inputSources;
+    private Integer filterMatchMode;
+    private List<SaveFilterConditionParam> contentFilters;
+    private List<ProducePlanInputSourceGroupOrderParam> contentOrders;
+    private Integer perInputCount;
+    private Integer samplingType;
+    private Integer randomMinCount;
+    private Integer inputMaxUseCount;
+}

+ 20 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/vo/aigc/ProducePlanInputSourceParam.java

@@ -0,0 +1,20 @@
+package com.tzld.longarticle.recommend.server.model.vo.aigc;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+@Getter
+@Setter
+@Accessors(chain = true)
+public class ProducePlanInputSourceParam {
+    private Integer contentType;
+    private Integer inputSourceType;
+    private Integer inputSourceSubType;
+    private String fieldName;
+    private String inputSourceValue;
+    private String inputSourceLabel;
+    private Integer inputSourceModal;
+    private Integer inputSourceChannel;
+
+}

+ 17 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/vo/aigc/SaveFilterConditionParam.java

@@ -0,0 +1,17 @@
+package com.tzld.longarticle.recommend.server.model.vo.aigc;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+import java.util.List;
+
+@Getter
+@Setter
+@Accessors(chain = true)
+public class SaveFilterConditionParam {
+    private Integer conditionType;
+    private Integer operator;
+    private List<String> data;
+
+}

+ 5 - 6
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/remote/WxFetchRemoteService.java

@@ -2,6 +2,7 @@ package com.tzld.longarticle.recommend.server.remote;
 
 import com.alibaba.fastjson.JSONObject;
 import com.tzld.longarticle.recommend.server.common.HttpPoolFactory;
+import com.tzld.longarticle.recommend.server.model.vo.WxContentDetailResponse;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.http.HttpEntity;
 import org.apache.http.StatusLine;
@@ -13,7 +14,7 @@ import org.apache.http.util.EntityUtils;
 import org.springframework.stereotype.Service;
 
 import java.nio.charset.StandardCharsets;
-import java.util.*;
+import java.util.Objects;
 
 /**
  * @author dyp
@@ -25,8 +26,8 @@ public class WxFetchRemoteService {
     private static final String url = "http://8.217.190.241:8888/crawler/wei_xin/detail";
 
 
-    public Map<String, String> getContent(String contentUrl) {
-        Map<String, String> result = new HashMap<>();
+    public WxContentDetailResponse getContent(String contentUrl) {
+        WxContentDetailResponse result = new WxContentDetailResponse();
         JSONObject bodyParam = new JSONObject();
         bodyParam.put("content_link", contentUrl);
         bodyParam.put("is_count", true);
@@ -45,9 +46,7 @@ public class WxFetchRemoteService {
                     JSONObject jsonObject = JSONObject.parseObject(responseBody);
                     if (jsonObject.getInteger("code") == 0) {
                         JSONObject data = jsonObject.getJSONObject("data");
-                        data = data.getJSONObject("data");
-                        result.put("view_count", data.getString("view_count"));
-                        result.put("title", data.getString("title"));
+                        result = data.getObject("data", WxContentDetailResponse.class);
                     }
                 }
             }

+ 75 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/remote/aigc/AIGCCrawlerPlanSaveService.java

@@ -0,0 +1,75 @@
+package com.tzld.longarticle.recommend.server.remote.aigc;
+
+import cn.hutool.core.io.resource.ResourceUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.tzld.longarticle.recommend.server.common.HttpPoolFactory;
+import com.tzld.longarticle.recommend.server.model.vo.IdNameVO;
+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.List;
+import java.util.Objects;
+
+@Service
+@Slf4j
+public class AIGCCrawlerPlanSaveService {
+
+    private final CloseableHttpClient client = HttpPoolFactory.aigcPool();
+
+    public IdNameVO<String> createArticleUrlPlan(String planName, List<String> contentList, String tag, Integer crawlerMode) {
+        IdNameVO<String> result = new IdNameVO<>();
+        if (contentList == null || contentList.isEmpty()) {
+            return null;
+        }
+        // 从配置中读取模板文件路径
+        String templateFile = ResourceUtil.readUtf8Str("file/长文_抓取计划_根据url列表抓取.json");
+        // 读取模板文件内容
+        JSONObject template = JSONObject.parseObject(templateFile);
+        String apiUrl = template.getString("api_url");
+        JSONObject data = template.getJSONObject("data");
+        // 设置请求参数
+        JSONObject params = data.getJSONObject("params");
+        params.put("name", planName);
+        params.put("crawlerMode", crawlerMode);
+        if (tag != null) {
+            params.put("planTag", tag);
+        }
+        params.put("inputModeValues", contentList);
+        // 将数据转为 JSON 格式
+        String requestData = data.toString();
+        try {
+            HttpPost httpPost = new HttpPost(apiUrl);
+            StringEntity stringEntity = new StringEntity(requestData, 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) {
+                        JSONObject responseData = jsonObject.getJSONObject("data");
+                        String planId = responseData.getString("id");
+                        String returnedPlanName = responseData.getString("name");
+                        log.info("plan_name: {}, plan_id: {}", returnedPlanName, planId);
+                        result.setId(planId);
+                        result.setName(returnedPlanName);
+                    }
+                }
+            }
+        } catch (Exception e) {
+            log.error("createArticleUrlPlan error", e);
+        }
+        return result;
+    }
+}

+ 95 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/remote/aigc/AIGCProduceContentListService.java

@@ -0,0 +1,95 @@
+package com.tzld.longarticle.recommend.server.remote.aigc;
+
+import cn.hutool.core.io.resource.ResourceUtil;
+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.aigc.CommonListDataVO;
+import com.tzld.longarticle.recommend.server.model.vo.aigc.ProduceContentListItemVO;
+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.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+
+@Service
+@Slf4j
+public class AIGCProduceContentListService {
+
+    private final CloseableHttpClient client = HttpPoolFactory.aigcPool();
+
+    public CommonListDataVO<ProduceContentListItemVO> list(List<String> planIdList, int pageNum, int pageSize, List<Integer> produceStatus) {
+        CommonListDataVO<ProduceContentListItemVO> result = new CommonListDataVO<ProduceContentListItemVO>();
+        result.setData(new ArrayList<>());
+        result.setTotalCount(0);
+        if (planIdList.isEmpty()) {
+            log.info("getProduceContentListByPlanIdListRaw: planIdList empty");
+            return result;
+        }
+
+        String templateFile = ResourceUtil.readUtf8Str("file/长文_生成结果库_根据计划id获取内容.json");
+        // 读取模板文件内容
+        JSONObject template = JSONObject.parseObject(templateFile);
+        String apiUrl = template.getString("api_url");
+        JSONObject data = template.getJSONObject("data");
+
+        data.getJSONObject("params").getJSONArray("filterItems").getJSONObject(0)
+                .put("selectValues", produceStatus);
+        data.getJSONObject("params").getJSONArray("filterItems").getJSONObject(1)
+                .put("selectValues", planIdList);
+        data.getJSONObject("params").put("pageNum", pageNum);
+        data.getJSONObject("params").put("pageSize", pageSize);
+
+        try {
+            HttpPost httpPost = new HttpPost(apiUrl);
+            StringEntity stringEntity = new StringEntity(data.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) {
+                        JSONObject dataObj = jsonObject.getJSONObject("data");
+                        int totalCnt = dataObj.getInteger("totalCount");
+                        JSONArray dataArray = dataObj.getJSONArray("data");
+                        List<ProduceContentListItemVO> contentList = dataArray.toJavaList(ProduceContentListItemVO.class);
+                        result.setData(contentList);
+                        result.setTotalCount(totalCnt);
+                        return result;
+                    }
+                }
+            }
+        } catch (IOException e) {
+            log.error("articleGetProducePlanDetail error", e);
+        }
+        return result;
+    }
+
+    private JSONObject getBaseInfo() {
+        JSONObject baseInfo = new JSONObject();
+        baseInfo.put("token", "79dcb40af1de43b1bd9fe3a731dbaa15");
+        baseInfo.put("appType", 9);
+        baseInfo.put("platform", "pc");
+        baseInfo.put("appVersionCode", 1000);
+        baseInfo.put("clientTimestamp", 1);
+        baseInfo.put("fid", 1);
+        baseInfo.put("loginUid", 1);
+        baseInfo.put("pageSource", 1);
+        baseInfo.put("requestId", 1);
+        baseInfo.put("rid", 1);
+        baseInfo.put("uid", 1);
+        return baseInfo;
+    }
+}

+ 73 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/remote/aigc/AIGCProducePlanDetailService.java

@@ -0,0 +1,73 @@
+package com.tzld.longarticle.recommend.server.remote.aigc;
+
+import com.alibaba.fastjson.JSONObject;
+import com.tzld.longarticle.recommend.server.common.HttpPoolFactory;
+import com.tzld.longarticle.recommend.server.model.vo.aigc.ProducePlanDetailVO;
+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.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.Objects;
+
+@Service
+@Slf4j
+public class AIGCProducePlanDetailService {
+
+    private final CloseableHttpClient client = HttpPoolFactory.aigcPool();
+
+    public ProducePlanDetailVO articleGetProducePlanDetail(String planId) {
+        String apiUrl = "http://aigc-api.cybertogether.net/aigc/produce/plan/detail";
+
+        // 构建请求的 JSON Payload
+        JSONObject payload = new JSONObject();
+        JSONObject params = new JSONObject();
+        params.put("id", planId);
+        payload.put("params", params);
+        payload.put("baseInfo", getBaseInfo());
+        try {
+            HttpPost httpPost = new HttpPost(apiUrl);
+            StringEntity stringEntity = new StringEntity(payload.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) {
+                        return jsonObject.getObject("data", ProducePlanDetailVO.class);
+                    }
+                }
+            }
+        } catch (IOException e) {
+            log.error("articleGetProducePlanDetail error", e);
+        }
+        return null;
+    }
+
+    private JSONObject getBaseInfo() {
+        JSONObject baseInfo = new JSONObject();
+        baseInfo.put("token", "79dcb40af1de43b1bd9fe3a731dbaa15");
+        baseInfo.put("appType", 9);
+        baseInfo.put("platform", "pc");
+        baseInfo.put("appVersionCode", 1000);
+        baseInfo.put("clientTimestamp", 1);
+        baseInfo.put("fid", 1);
+        baseInfo.put("loginUid", 1);
+        baseInfo.put("pageSource", 1);
+        baseInfo.put("requestId", 1);
+        baseInfo.put("rid", 1);
+        baseInfo.put("uid", 1);
+        return baseInfo;
+    }
+}

+ 85 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/remote/aigc/AIGCProducePlanSaveService.java

@@ -0,0 +1,85 @@
+package com.tzld.longarticle.recommend.server.remote.aigc;
+
+import com.alibaba.fastjson.JSONObject;
+import com.tzld.longarticle.recommend.server.common.HttpPoolFactory;
+import com.tzld.longarticle.recommend.server.model.vo.IdNameVO;
+import com.tzld.longarticle.recommend.server.model.vo.aigc.ProducePlanDetailVO;
+import com.tzld.longarticle.recommend.server.model.vo.aigc.ProducePlanInputSourceParam;
+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.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Objects;
+
+@Service
+@Slf4j
+public class AIGCProducePlanSaveService {
+
+    private final CloseableHttpClient client = HttpPoolFactory.aigcPool();
+
+    private static String apiUrl = "http://aigc-api.cybertogether.net/aigc/produce/plan/save";
+
+    public IdNameVO<String> save(String planName, String planId, ProducePlanDetailVO detail) {
+        // 添加新的依赖计划
+        List<ProducePlanInputSourceParam> inputSources = detail.getInputSourceGroups().get(0).getInputSources();
+        ProducePlanInputSourceParam newInputSource = new ProducePlanInputSourceParam();
+        newInputSource.setContentType(1);
+        newInputSource.setInputSourceType(2);
+        newInputSource.setInputSourceValue(planId);
+        newInputSource.setInputSourceLabel(String.format("原始帖子-长文-微信公众号-内容添加计划-%s", planName));
+        newInputSource.setInputSourceModal(3);
+        newInputSource.setInputSourceChannel(5);
+        inputSources.add(newInputSource);
+
+        // 准备请求参数
+        JSONObject payload = new JSONObject();
+        payload.put("params", detail);
+        payload.put("baseInfo", getBaseInfo());
+        try {
+            HttpPost httpPost = new HttpPost(apiUrl);
+            StringEntity stringEntity = new StringEntity(payload.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) {
+                        return jsonObject.getObject("data", IdNameVO.class);
+                    }
+                }
+            }
+        } catch (IOException e) {
+            log.error("articleGetProducePlanDetail error", e);
+        }
+        return null;
+    }
+
+    private JSONObject getBaseInfo() {
+        JSONObject baseInfo = new JSONObject();
+        baseInfo.put("token", "79dcb40af1de43b1bd9fe3a731dbaa15");
+        baseInfo.put("appType", 9);
+        baseInfo.put("platform", "pc");
+        baseInfo.put("appVersionCode", 1000);
+        baseInfo.put("clientTimestamp", 1);
+        baseInfo.put("fid", 1);
+        baseInfo.put("loginUid", 1);
+        baseInfo.put("pageSource", 1);
+        baseInfo.put("requestId", 1);
+        baseInfo.put("rid", 1);
+        baseInfo.put("uid", 1);
+        return baseInfo;
+    }
+}

+ 2 - 2
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/remote/AIGCRemoteService.java → long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/remote/aigc/AIGCWaitingPublishContentService.java

@@ -1,4 +1,4 @@
-package com.tzld.longarticle.recommend.server.remote;
+package com.tzld.longarticle.recommend.server.remote.aigc;
 
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
@@ -23,7 +23,7 @@ import java.util.*;
  */
 @Service
 @Slf4j
-public class AIGCRemoteService {
+public class AIGCWaitingPublishContentService {
     private final CloseableHttpClient client = HttpPoolFactory.aigcPool();
     private static final String aigcGetAllContentUrl = "http://aigc-api.cybertogether.net/aigc/publish/content/gzhWaitingPublishContent";
 

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

@@ -4,7 +4,12 @@ import com.tzld.longarticle.recommend.server.model.entity.longArticle.DatastatSo
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.stereotype.Repository;
 
+import java.util.List;
+
 @Repository
 public interface DatastatSortStrategyRepository extends JpaRepository<DatastatSortStrategy, DatastatSortStrategy.PK> {
 
+    List<DatastatSortStrategy> getByViewCountGreaterThanEqualAndReadRateGreaterThanEqualAndPositionIn(Integer viewCount,
+                                                                                                      Double readRate,
+                                                                                                      List<Integer> positionList);
 }

+ 5 - 5
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/JobService.java

@@ -1,7 +1,8 @@
 package com.tzld.longarticle.recommend.server.service;
 
-import com.tzld.longarticle.recommend.server.remote.WxFetchRemoteService;
 import com.tzld.longarticle.recommend.server.mapper.crawler.ArticleContentLinkMapper;
+import com.tzld.longarticle.recommend.server.model.vo.WxContentDetailResponse;
+import com.tzld.longarticle.recommend.server.remote.WxFetchRemoteService;
 import com.tzld.longarticle.recommend.server.repository.model.ArticleContentLink;
 import com.tzld.longarticle.recommend.server.repository.model.ArticleContentLinkExample;
 import lombok.extern.slf4j.Slf4j;
@@ -13,7 +14,6 @@ import java.time.LocalDate;
 import java.time.ZoneId;
 import java.time.ZonedDateTime;
 import java.util.List;
-import java.util.Map;
 
 /**
  * @author dyp
@@ -46,9 +46,9 @@ public class JobService {
         example.createCriteria().andCreateTimeGreaterThanOrEqualTo(time);
         List<ArticleContentLink> links = articleContentLinkMapper.selectByExample(example);
         for (ArticleContentLink link : links) {
-            Map<String, String> content = wxFetchRemoteService.getContent(link.getContentLink());
-            link.setTitle(content.getOrDefault("title", ""));
-            link.setViewCount(NumberUtils.toLong(content.getOrDefault("view_count", "0"), 0L));
+            WxContentDetailResponse content = wxFetchRemoteService.getContent(link.getContentLink());
+            link.setTitle(content.getTitle());
+            link.setViewCount(NumberUtils.toLong(String.valueOf(content.getViewCount()), 0L));
             link.setUpdateTime(System.currentTimeMillis());
 
             articleContentLinkMapper.updateByPrimaryKey(link);

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

@@ -5,6 +5,7 @@ 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.google.common.collect.Lists;
 import com.tzld.longarticle.recommend.server.common.enums.recommend.AccountBusinessTypeEnum;
 import com.tzld.longarticle.recommend.server.common.enums.recommend.FeishuRobotIdEnum;
 import com.tzld.longarticle.recommend.server.mapper.aigc.AigcBaseMapper;
@@ -29,6 +30,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.ArticlePromotionService;
 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;
@@ -74,6 +76,8 @@ public class XxlJobService {
     private ODPSManager odpsManager;
     @Autowired
     private ArticleService articleService;
+    @Autowired
+    private ArticlePromotionService articlePromotionService;
 
     @ApolloJsonValue("${touliu.account.ghIds:[\"gh_93e00e187787\", \"gh_ac43e43b253b\", \"gh_68e7fdc09fe4\",\"gh_77f36c109fb1\", \"gh_b181786a6c8c\", \"gh_1ee2e1b39ccf\"]}")
     private List<String> touliuAccountGhIds;
@@ -410,4 +414,15 @@ public class XxlJobService {
         articleService.articleCategoryJobRetry();
         return ReturnT.SUCCESS;
     }
+
+    @XxlJob("articlePromotion")
+    public ReturnT<String> articlePromotion(String param) {
+        articlePromotionService.articlePromotion("【1】", "direct", "头条利用池_v1",
+                "头条利用池_v4", 500, 1.1, Lists.newArrayList(1));
+        articlePromotionService.articlePromotion("【1】", "direct", "头条利用池_v2",
+                "头条利用池_v4", 250, 1.21, Lists.newArrayList(2));
+        articlePromotionService.articlePromotion("【2】", "direct", "次条利用池_v1",
+                "头条利用池_v4", 100, 1.33, Lists.newArrayList(3, 4, 5, 6, 7, 8));
+        return ReturnT.SUCCESS;
+    }
 }

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

@@ -0,0 +1,325 @@
+package com.tzld.longarticle.recommend.server.service.recommend;
+
+import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue;
+import com.tzld.longarticle.recommend.server.common.enums.aigc.CrawlerModeEnum;
+import com.tzld.longarticle.recommend.server.mapper.longArticle.LongArticleBaseMapper;
+import com.tzld.longarticle.recommend.server.model.entity.aigc.PublishAccount;
+import com.tzld.longarticle.recommend.server.model.entity.longArticle.ArticlePoolPromotionSource;
+import com.tzld.longarticle.recommend.server.model.entity.longArticle.DatastatSortStrategy;
+import com.tzld.longarticle.recommend.server.model.vo.IdNameVO;
+import com.tzld.longarticle.recommend.server.model.vo.WxContentDetailResponse;
+import com.tzld.longarticle.recommend.server.model.vo.aigc.CommonListDataVO;
+import com.tzld.longarticle.recommend.server.model.vo.aigc.ProduceContentListItemVO;
+import com.tzld.longarticle.recommend.server.model.vo.aigc.ProducePlanDetailVO;
+import com.tzld.longarticle.recommend.server.model.vo.aigc.ProducePlanInputSourceParam;
+import com.tzld.longarticle.recommend.server.remote.WxFetchRemoteService;
+import com.tzld.longarticle.recommend.server.remote.aigc.AIGCCrawlerPlanSaveService;
+import com.tzld.longarticle.recommend.server.remote.aigc.AIGCProduceContentListService;
+import com.tzld.longarticle.recommend.server.remote.aigc.AIGCProducePlanDetailService;
+import com.tzld.longarticle.recommend.server.remote.aigc.AIGCProducePlanSaveService;
+import com.tzld.longarticle.recommend.server.repository.aigc.PublishAccountRepository;
+import com.tzld.longarticle.recommend.server.repository.longArticle.ArticlePoolPromotionSourceRepository;
+import com.tzld.longarticle.recommend.server.repository.longArticle.DatastatSortStrategyRepository;
+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.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import java.net.URLDecoder;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Service
+@Slf4j
+public class ArticlePromotionService {
+
+    @Autowired
+    LongArticleBaseMapper longArticleBaseMapper;
+    @Autowired
+    DatastatSortStrategyRepository datastatSortStrategyRepository;
+    @Autowired
+    AIGCCrawlerPlanSaveService aigcCrawlerPlanSaveService;
+    @Autowired
+    AIGCProducePlanDetailService aigcProducePlanDetailService;
+    @Autowired
+    AIGCProducePlanSaveService aigcProducePlanSaveService;
+    @Autowired
+    AIGCProduceContentListService aigcProduceContentListService;
+    @Autowired
+    ArticlePoolPromotionSourceRepository articlePoolPromotionSourceRepository;
+    @Autowired
+    WxFetchRemoteService wxFetchRemoteService;
+    @Autowired
+    PublishAccountRepository publishAccountRepository;
+    @Autowired
+    ArticleService articleService;
+
+    @ApolloJsonValue("${articlePromotionProduceConfig:{}}")
+    private Map<String, Map<String, Map<String, String>>> produceConfig;
+
+    private final List<String> contentPoolType = Arrays.asList("autoArticlePoolLevel1", "autoArticlePoolLevel3", "autoArticlePoolLevel4");
+
+    public void articlePromotion(String pos, String way, String accountNickName, String tag,
+                                 Integer viewCountFilter, Double viewCountRateFilter, List<Integer> positionFilter) {
+        String today = DateUtils.getCurrentDateStr("yyyyMMdd");
+        String dateStrFilter = DateUtils.getBeforeDaysDateStr("yyyyMMdd", 10);
+        // 获取内部表现
+        List<DatastatSortStrategy> list = longArticleBaseMapper.getArticlePromotion(viewCountFilter, viewCountRateFilter,
+                10000, dateStrFilter, positionFilter);
+        list = filterEarlyContent(list);
+        log.info("优质{}文章数量: {}", accountNickName, list.size());
+        List<DatastatSortStrategy> distinct = filterSameTitle(list);
+        distinct.sort(Comparator.comparing(DatastatSortStrategy::getDateStr, Comparator.reverseOrder()));
+        log.info("优质{}文章数量(去重后): {}", accountNickName, distinct.size());
+        addUrlListToAccount(accountNickName, distinct, pos, way, today, tag);
+    }
+
+    private List<DatastatSortStrategy> filterEarlyContent(List<DatastatSortStrategy> list) {
+        List<String> ghIds = list.stream().map(DatastatSortStrategy::getGhId).distinct().collect(Collectors.toList());
+        List<PublishAccount> publishAccountList = publishAccountRepository.getAllByGhIdIn(ghIds);
+        Map<String, Long> publishAccountCreateTimeMap = publishAccountList.stream().collect(Collectors.toMap(
+                PublishAccount::getGhId, PublishAccount::getCreateTimestamp));
+        list = list.stream().filter(o -> {
+            long publishTime = DateUtils.dateStrToTimestamp(o.getDateStr(), "yyyyMMdd");
+            Long accountCreateTime = publishAccountCreateTimeMap.get(o.getGhId());
+            return publishTime * 1000 > accountCreateTime;
+        }).collect(Collectors.toList());
+        return list;
+    }
+
+    private List<DatastatSortStrategy> filterSameTitle(List<DatastatSortStrategy> list) {
+        List<DatastatSortStrategy> result = new ArrayList<>();
+        List<String> titles = new ArrayList<>();
+        for (DatastatSortStrategy datastatSortStrategy : list) {
+            String title = datastatSortStrategy.getTitle();
+            if (titles.contains(title)) {
+                continue;
+            }
+            if (!TitleSimilarCheckUtil.isDuplicateContent(datastatSortStrategy.getTitle(), titles, TitleSimilarCheckUtil.ARTICLE_PROMOTION_THRESHOLD)) {
+                result.add(datastatSortStrategy);
+                titles.add(title);
+            }
+        }
+        return result;
+    }
+
+    private void addUrlListToAccount(String accountNickName, List<DatastatSortStrategy> list, String pos, String way,
+                                     String today, String tag) {
+        List<String> urlList = list.stream().map(DatastatSortStrategy::getLink).collect(Collectors.toList());
+        if (!produceConfig.containsKey(accountNickName)) {
+            log.info("account_nickname not in produceConfig: " + accountNickName);
+            String planName = String.format("%d_%s_%s_%s【%s】_%s", list.size(), today, accountNickName, pos, way, today);
+            aigcCrawlerPlanSaveService.createArticleUrlPlan(planName, urlList, tag, CrawlerModeEnum.ContentIDs.getVal());
+            return;
+        }
+        String produceId = produceConfig.get(accountNickName).get(pos).get(way).trim();
+        List<ProduceContentListItemVO> contentList = getProduceContentList(accountNickName, pos, way);
+        // 获取已访问的标题和URL
+        List<String> visitedTitleList = contentList.stream()
+                .flatMap(content -> Arrays.stream(new String[]{content.getReferContentTitle(), content.getTitle()}))
+                .distinct().collect(Collectors.toList());
+        Set<String> visitedUrlIdList = contentList.stream().map(content -> getUrlId(content.getReferContentLink()))
+                .collect(Collectors.toSet());
+        // 筛选URL和标题
+        List<String> publishContentIds = new ArrayList<>();
+        List<String> filterUrlList = new ArrayList<>();
+        for (DatastatSortStrategy item : list) {
+            String url = item.getLink();
+            String urlId = getUrlId(item.getLink());
+            String title = item.getTitle();
+            String wxSn = item.getWxSn();
+            if (visitedUrlIdList.contains(urlId)) {
+                continue;
+            }
+            if (TitleSimilarCheckUtil.isDuplicateContent(title, visitedTitleList, TitleSimilarCheckUtil.ARTICLE_PROMOTION_THRESHOLD)) {
+                continue;
+            }
+            filterUrlList.add(url);
+            // 调用爬虫 detail 接口并保存数据
+            WxContentDetailResponse detail = getArticleDetail(url);
+            String level = pos.equals("【1】") ? contentPoolType.get(0) : contentPoolType.get(1);
+            if (detail != null && StringUtils.hasText(detail.getChannelContentId())) {
+                saveArticlePoolPromotionSource(detail.getChannelContentId(), wxSn, title, level);
+            } else {
+                String publishContentId = articleService.getPublishContentByWxSn(wxSn);
+                if (StringUtils.hasText(publishContentId)) {
+                    publishContentIds.add(publishContentId);
+                    saveArticlePoolPromotionSource(Md5Util.encoderByMd5(publishContentId), wxSn, title, level);
+                }
+            }
+        }
+        if (filterUrlList.isEmpty()) {
+            log.info("url_list empty: " + accountNickName + ", " + pos + ", " + way);
+            return;
+        }
+        int urlLen = filterUrlList.size();
+        String planName = String.format("%d_%s_%s_%s【%s】_%s", urlLen, today, accountNickName, pos, way, today);
+        log.info("url_len: " + list.size() + ", " + urlLen);
+        IdNameVO<String> planInfo = aigcCrawlerPlanSaveService.createArticleUrlPlan(planName, filterUrlList, tag, CrawlerModeEnum.ContentIDs.getVal());
+        if (StringUtils.hasText(produceId)) {
+            articleAddDependPlan(produceId, planInfo.getId(), planInfo.getName());
+        }
+        log.info("{}, {}, produce plan not exist: {}, {}, {}", planInfo.getName(), planInfo.getId(), accountNickName, pos, way);
+        if (CollectionUtils.isNotEmpty(publishContentIds)) {
+            planInfo = aigcCrawlerPlanSaveService.createArticleUrlPlan(planName, publishContentIds, tag, CrawlerModeEnum.PublishContentIds.getVal());
+            if (StringUtils.hasText(produceId)) {
+                articleAddDependPlan(produceId, planInfo.getId(), planInfo.getName());
+            }
+        }
+    }
+
+    private List<ProduceContentListItemVO> getProduceContentList(String accountNickName, String pos, String way) {
+        List<String> planIdList = getProducePlanIdList(accountNickName, pos, way);
+        CommonListDataVO<ProduceContentListItemVO> contentData = getProduceContentListByPlanIdList(planIdList);
+        return contentData.getData();
+    }
+
+    public List<String> getProducePlanIdList(String accountNickname, String pos, String way) {
+        List<String> res = new ArrayList<>();
+        if (!produceConfig.containsKey(accountNickname)) {
+            return res;
+        }
+        Map<String, Map<String, String>> accountConfig = produceConfig.get(accountNickname);
+        for (String posKey : accountConfig.keySet()) {
+            if (pos != null && !pos.equals(posKey)) {
+                continue;
+            }
+            Map<String, String> posConfig = accountConfig.get(posKey);
+            for (String wayKey : posConfig.keySet()) {
+                if (way != null && !way.equals(wayKey)) {
+                    continue;
+                }
+                String planId = posConfig.get(wayKey).trim();
+                if (!planId.isEmpty()) {
+                    res.add(planId);
+                }
+            }
+        }
+        return res;
+    }
+
+    public CommonListDataVO<ProduceContentListItemVO> getProduceContentListByPlanIdList(List<String> planIdList) {
+        CommonListDataVO<ProduceContentListItemVO> result = new CommonListDataVO<>();
+        if (planIdList.isEmpty()) {
+            log.info("getProduceContentListByPlanIdList: planIdList empty");
+            result.setData(new ArrayList<>());
+            result.setTotalCount(0);
+            return result;
+        }
+        int pageSize = 500;
+        List<Integer> produceStatus = Arrays.asList(1,2,3,4,5,6);
+        CommonListDataVO<ProduceContentListItemVO> rawData = aigcProduceContentListService.list(planIdList, 1, 1, produceStatus);
+        int totalCnt = rawData.getTotalCount();
+        int pageNumMax = totalCnt / pageSize;
+        List<ProduceContentListItemVO> allContent = new ArrayList<>();
+        for (int i = 0; i <= pageNumMax; i++) {
+            CommonListDataVO<ProduceContentListItemVO> pageData = aigcProduceContentListService.list(planIdList, i + 1, pageSize, produceStatus);
+            allContent.addAll(pageData.getData());
+        }
+        List<ProduceContentListItemVO> filteredContent = new ArrayList<>();
+        for (ProduceContentListItemVO content : allContent) {
+            if (StringUtils.hasText(content.getTitle())) {
+                filteredContent.add(content);
+            }
+        }
+        result.setData(filteredContent);
+        result.setTotalCount(filteredContent.size());
+        return result;
+    }
+
+    public String getUrlId(String url) {
+        if (url == null) {
+            return null;
+        }
+        // 检查是否包含特定的前缀
+        if (url.contains("https://mp.weixin.qq.com/s/")) {
+            return url.split("https://mp.weixin.qq.com/s/")[1];
+        }
+        Map<String, String> params = new HashMap<>();
+        try {
+            String pureUrl = URLDecoder.decode(url, "utf-8");
+            // 解析 URL 参数
+            params = parseQueryString(pureUrl);
+
+            String biz = params.get("http://mp.weixin.qq.com/s?__biz");
+            String sn = params.get("sn");
+            String mid = params.get("mid");
+            String idx = params.get("idx");
+            if (biz != null && sn != null && mid != null && idx != null) {
+                return String.format("biz=%s_mid=%s_idx=%s_sn=%s", biz, mid, idx, sn);
+            }
+        } catch (Exception e) {
+            log.error("get_url_id error: " + url);
+        }
+
+        return params.get("sn");
+    }
+
+    // 辅助方法:解析查询参数
+    private Map<String, String> parseQueryString(String url) {
+        Map<String, String> params = new java.util.HashMap<>();
+        if (url.contains("?")) {
+            String query = url.substring(url.indexOf("?") + 1);
+            for (String param : query.split("&")) {
+                String[] keyValue = param.split("=", 2);
+                if (keyValue.length == 2) {
+                    params.put(keyValue[0], keyValue[1]);
+                }
+            }
+        }
+        return params;
+    }
+
+    public WxContentDetailResponse getArticleDetail(String url) {
+        if (url == null) {
+            return null;
+        }
+        try {
+            return wxFetchRemoteService.getContent(url);
+        } catch (Exception e) {
+            log.error("URL error: " + url);
+        }
+        return null;
+    }
+
+    private void saveArticlePoolPromotionSource(String channelContentId, String wxSn, String title, String level) {
+        ArticlePoolPromotionSource articlePromotion = articlePoolPromotionSourceRepository.getByChannelContentId(channelContentId);
+        if (Objects.isNull(articlePromotion)) {
+            articlePromotion = new ArticlePoolPromotionSource();
+            articlePromotion.setChannelContentId(channelContentId);
+            articlePromotion.setTitle(title);
+            articlePromotion.setTitleMd5(Md5Util.encoderByMd5(title));
+            articlePromotion.setCreateTimestamp(System.currentTimeMillis());
+        }
+        articlePromotion.setWxSn(wxSn);
+        articlePromotion.setLevel(level);
+        articlePromotion.setUpdateTimestamp(System.currentTimeMillis());
+        articlePoolPromotionSourceRepository.save(articlePromotion);
+    }
+
+    private void articleAddDependPlan(String produceId, String planId, String planName) {
+        // 获取生产计划的详细信息
+        ProducePlanDetailVO detail = aigcProducePlanDetailService.articleGetProducePlanDetail(produceId);
+        if (detail == null) {
+            log.info("Failed to fetch produce plan detail.");
+            return;
+        }
+        // 获取依赖计划 ID 列表
+        List<ProducePlanInputSourceParam> inputSources = detail.getInputSourceGroups().get(0).getInputSources();
+        List<String> dependPlanIds = new ArrayList<>();
+        for (ProducePlanInputSourceParam inputSource : inputSources) {
+            dependPlanIds.add(inputSource.getInputSourceValue());
+        }
+        // 如果计划 ID 已存在,直接返回
+        if (dependPlanIds.contains(planId)) {
+            log.info("depend_plan_id exist: {}", planId);
+            return;
+        }
+        aigcProducePlanSaveService.save(planName, planId, detail);
+    }
+
+}

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

@@ -335,6 +335,7 @@ public class ArticleService {
                         item.setChannelContentId(midChannelContentId);
                         item.setCreateTimestamp(item.getUpdateTimestamp());
                     }
+                    item.setDeleted(0);
                     articlePoolPromotionSourceRepository.save(item);
                 }
                 longArticleBaseMapper.updateRootProduceContentLevel(task.getRootProduceContentId(), task.getLevel());
@@ -523,4 +524,19 @@ public class ArticleService {
             articleCategoryRepository.save(articleCategory);
         }
     }
+
+    public String getPublishContentByWxSn(String wxSn) {
+        Article article = articleRepository.getByWxSn(wxSn);
+        PublishAccount publishAccount = publishAccountRepository.getByGhId(article.getGhId());
+        if (Objects.isNull(publishAccount)) {
+            return null;
+        }
+        long publishTimestamp = article.getPublishTimestamp() > 0 ? article.getPublishTimestamp() * 1000 : article.getUpdateTime() * 1000;
+        List<PublishContent> publishContentList = aigcBaseMapper.getNearestPublishContent(publishAccount.getId(), publishTimestamp, 100);
+        PublishContent publishContent = findPublishContent(publishContentList, article.getTitle(), publishTimestamp);
+        if (Objects.nonNull(publishContent)) {
+            return publishContent.getId();
+        }
+        return null;
+    }
 }

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

@@ -23,7 +23,7 @@ import com.tzld.longarticle.recommend.server.model.param.PublishContentParam;
 import com.tzld.longarticle.recommend.server.model.vo.FirstContentScoreExport;
 import com.tzld.longarticle.recommend.server.model.vo.IntermediateIndicatorsExport;
 import com.tzld.longarticle.recommend.server.model.vo.NewSortStrategyExport;
-import com.tzld.longarticle.recommend.server.model.vo.ProduceAuditLayoutContentObjVO;
+import com.tzld.longarticle.recommend.server.model.vo.aigc.ProduceAuditLayoutContentObjVO;
 import com.tzld.longarticle.recommend.server.repository.aigc.*;
 import com.tzld.longarticle.recommend.server.repository.crawler.AccountAvgInfoRepository;
 import com.tzld.longarticle.recommend.server.repository.crawler.ArticleDetailInfoRepository;

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

@@ -2,7 +2,7 @@ package com.tzld.longarticle.recommend.server.service.recommend.filter.strategy;
 
 import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue;
 import com.tzld.longarticle.recommend.server.model.dto.Content;
-import com.tzld.longarticle.recommend.server.remote.AIGCRemoteService;
+import com.tzld.longarticle.recommend.server.remote.aigc.AIGCWaitingPublishContentService;
 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;
@@ -19,7 +19,7 @@ import java.util.List;
 public class BadStrategy implements FilterStrategy {
 
     @Autowired
-    private AIGCRemoteService aigcRemoteService;
+    private AIGCWaitingPublishContentService aigcWaitingPublishContentService;
 
     @ApolloJsonValue("${badTitles:[]}")
     private static List<String> badTitles;
@@ -32,7 +32,7 @@ public class BadStrategy implements FilterStrategy {
         List<Content> contents = param.getContents();
         List<Content> filterContents = new ArrayList<>();
         for (Content content : contents) {
-            if (!TitleSimilarCheckUtil.isDuplicateContent(content.getTitle(), badTitles)) {
+            if (!TitleSimilarCheckUtil.isDuplicateContent(content.getTitle(), badTitles, TitleSimilarCheckUtil.SIMILARITY_THRESHOLD)) {
                 result.add(content.getId());
             } else {
                 content.setFilterReason("历史表现差的文章");

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

@@ -40,7 +40,7 @@ public class HistoryTitleForFwhColdStartStrategy implements FilterStrategy {
         List<String> allTitleList = allArticleList.stream().map(Article::getTitle).distinct().collect(Collectors.toList());
 
         for (Content content : param.getContents()) {
-            boolean isDuplicate = TitleSimilarCheckUtil.isDuplicateContent(content.getTitle(), allTitleList);
+            boolean isDuplicate = TitleSimilarCheckUtil.isDuplicateContent(content.getTitle(), allTitleList, TitleSimilarCheckUtil.SIMILARITY_THRESHOLD);
             if (!isDuplicate) {
                 result.add(content.getId());
             } else {

+ 2 - 2
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/filter/strategy/HistoryTitleStrategy.java

@@ -66,9 +66,9 @@ public class HistoryTitleStrategy implements FilterStrategy {
                     boolean isDuplicate;
                     if (CollectionUtils.isNotEmpty(firstSecondContentPool) && firstSecondContentPool.contains(content.getContentPoolType())) {
                         // 四个内容池 配置 判断头条,次头条
-                        isDuplicate = TitleSimilarCheckUtil.isDuplicateContent(content.getTitle(), firstSecondTitleList);
+                        isDuplicate = TitleSimilarCheckUtil.isDuplicateContent(content.getTitle(), firstSecondTitleList, TitleSimilarCheckUtil.SIMILARITY_THRESHOLD);
                     } else {
-                        isDuplicate = TitleSimilarCheckUtil.isDuplicateContent(content.getTitle(), allTitleList);
+                        isDuplicate = TitleSimilarCheckUtil.isDuplicateContent(content.getTitle(), allTitleList, TitleSimilarCheckUtil.SIMILARITY_THRESHOLD);
                     }
                     if (isDuplicate) {
                         content.setFilterReason("历史已发布文章");

+ 2 - 2
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/filter/strategy/InfiniteHisTitleStrategy.java

@@ -49,9 +49,9 @@ public class InfiniteHisTitleStrategy implements FilterStrategy {
         for (Content content : param.getContents()) {
             Future<Content> future = pool.submit(() -> {
                 try {
-                    boolean isDuplicate = TitleSimilarCheckUtil.isDuplicateContent(content.getTitle(), qunfaTitleList);
+                    boolean isDuplicate = TitleSimilarCheckUtil.isDuplicateContent(content.getTitle(), qunfaTitleList, TitleSimilarCheckUtil.SIMILARITY_THRESHOLD);
                     if (!isDuplicate) {
-                        isDuplicate = TitleSimilarCheckUtil.isDuplicateContent(content.getTitle(), allTitleList);
+                        isDuplicate = TitleSimilarCheckUtil.isDuplicateContent(content.getTitle(), allTitleList, TitleSimilarCheckUtil.SIMILARITY_THRESHOLD);
                     }
                     if (isDuplicate) {
                         content.setFilterReason("历史已发布文章");

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

@@ -73,7 +73,7 @@ public class SensitiveStrategy implements FilterStrategy {
 //                    if (isSensitive) {
 //                        content.setFilterReason("安全违规");
 //                    } else
-                    if (TitleSimilarCheckUtil.isDuplicateContent(content.getTitle(), UnSafeTitles)) {
+                    if (TitleSimilarCheckUtil.isDuplicateContent(content.getTitle(), UnSafeTitles, TitleSimilarCheckUtil.SIMILARITY_THRESHOLD)) {
                         content.setFilterReason("安全违规");
                     }
                     return content;

+ 5 - 5
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/rank/RankStrategy.java

@@ -25,10 +25,10 @@ public interface RankStrategy {
     public static void deduplication(List<Content> result, Map<String, List<Content>> contentMap, String[] publishPool) {
         List<String> titles = new ArrayList<>();
         for (int i = 0; i < result.size(); i++) {
-            if (TitleSimilarCheckUtil.isDuplicateContent(result.get(i).getTitle(), titles)) {
+            if (TitleSimilarCheckUtil.isDuplicateContent(result.get(i).getTitle(), titles, TitleSimilarCheckUtil.SIMILARITY_THRESHOLD)) {
                 if (i == 0) {
                     for (Content content : contentMap.get(publishPool[0])) {
-                        if (!TitleSimilarCheckUtil.isDuplicateContent(content.getTitle(), titles)) {
+                        if (!TitleSimilarCheckUtil.isDuplicateContent(content.getTitle(), titles, TitleSimilarCheckUtil.SIMILARITY_THRESHOLD)) {
                             result.set(i, content);
                             titles.add(content.getTitle());
                             break;
@@ -36,7 +36,7 @@ public interface RankStrategy {
                     }
                 } else if (i == 1) {
                     for (Content content : contentMap.get(publishPool[1])) {
-                        if (!TitleSimilarCheckUtil.isDuplicateContent(content.getTitle(), titles)) {
+                        if (!TitleSimilarCheckUtil.isDuplicateContent(content.getTitle(), titles, TitleSimilarCheckUtil.SIMILARITY_THRESHOLD)) {
                             result.set(i, content);
                             titles.add(content.getTitle());
                             break;
@@ -44,7 +44,7 @@ public interface RankStrategy {
                     }
                 } else {
                     for (Content content : contentMap.get(publishPool[2])) {
-                        if (!TitleSimilarCheckUtil.isDuplicateContent(content.getTitle(), titles)) {
+                        if (!TitleSimilarCheckUtil.isDuplicateContent(content.getTitle(), titles, TitleSimilarCheckUtil.SIMILARITY_THRESHOLD)) {
                             result.set(i, content);
                             titles.add(content.getTitle());
                             break;
@@ -77,7 +77,7 @@ public interface RankStrategy {
                 if (!contentPool.equals(c.getContentPoolType())) {
                     continue;
                 }
-                if (!TitleSimilarCheckUtil.isDuplicateContent(c.getTitle(), titles)) {
+                if (!TitleSimilarCheckUtil.isDuplicateContent(c.getTitle(), titles, TitleSimilarCheckUtil.SIMILARITY_THRESHOLD)) {
                     result.add(c);
                     titles.add(c.getTitle());
                 }

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

@@ -14,7 +14,7 @@ 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.remote.aigc.AIGCWaitingPublishContentService;
 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;
@@ -65,7 +65,7 @@ public class RecallService implements ApplicationContextAware {
     @Autowired
     CrawlerMetaArticleRepository crawlerMetaArticleRepository;
     @Autowired
-    AIGCRemoteService aigcRemoteService;
+    AIGCWaitingPublishContentService aigcWaitingPublishContentService;
     @Autowired
     AccountIndexAvgViewCountService accountIndexAvgViewCountService;
     @Autowired
@@ -150,7 +150,7 @@ public class RecallService implements ApplicationContextAware {
     }
 
     private List<Content> getAllContent(RecallParam param) {
-        List<Content> content = aigcRemoteService.getAllContent(param);
+        List<Content> content = aigcWaitingPublishContentService.getAllContent(param);
         if (CollectionUtils.isEmpty(content)) {
             FeishuMessageSender.sendWebHookMessage(FeishuRobotIdEnum.RECOMMEND.getRobotId(),
                     "内容召回失败\n"

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

@@ -9,16 +9,17 @@ import java.util.Set;
 
 public class TitleSimilarCheckUtil {
 
-    public static final double SIMILARITY_THRESHOLD = 0.8; // 相似度阈值
+    public static final double SIMILARITY_THRESHOLD = 0.8;
+    public static final double ARTICLE_PROMOTION_THRESHOLD = 0.75;
 
-    public static boolean isDuplicateContent(String title, List<String> existsContentTitle) {
+    public static boolean isDuplicateContent(String title, List<String> existsContentTitle, double threshold) {
         boolean result = false;
         if (CollectionUtils.isEmpty(existsContentTitle)) {
             return result;
         }
         title = title.trim().replace("\u200b", "");
         for (String existsTitle : existsContentTitle) {
-            if (isSimilar(title, existsTitle, SIMILARITY_THRESHOLD)) {
+            if (isSimilar(title, existsTitle, threshold)) {
                 result = true;
                 break;
             }
@@ -51,7 +52,7 @@ public class TitleSimilarCheckUtil {
                 "人到晚年才明白:多子女家庭,老人大概率过得比独子家庭的要幸福",
                 "可供中国使用3800年?山东意外发现巨大宝藏,西方当场酸了!",
                 "陕西女孩去医院体检后,发现左肾不见了,意外牵出8年前手术疑云");
-        boolean result = isDuplicateContent(title, existsContentTitle);
+        boolean result = isDuplicateContent(title, existsContentTitle, SIMILARITY_THRESHOLD);
         System.out.println(result);
     }
 }

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

@@ -44,6 +44,11 @@ public class XxlJobController {
         service.syncArticleRootPublishId(dateStr);
     }
 
+    @GetMapping("/articlePromotion")
+    public void articlePromotion() {
+        service.articlePromotion(null);
+    }
+
     @GetMapping("/articlePromotionTraceability")
     public void articlePromotionTraceability(String channelContentId) {
         service.articlePromotionTraceability(channelContentId);

+ 51 - 0
long-article-recommend-service/src/main/resources/file/长文_抓取计划_根据url列表抓取.json

@@ -0,0 +1,51 @@
+{
+    "describe": "长文_抓取计划_根据url列表抓取",
+    "api_url": "http://aigc-api.cybertogether.net/aigc/crawler/plan/save",
+    "res": {
+        "code": 0,
+        "msg": "success",
+        "data": {
+            "id": "20240618072529702764841",
+            "name": "测试抓取_20240618"
+        }
+    },
+    
+    "data": {
+      "params": {
+        "contentFilters": [],
+        "accountFilters": [],
+        "filterAccountMatchMode": 1,
+        "filterContentMatchMode": 1,
+        "selectModeValues": [],
+        "searchModeValues": [],
+        "contentModal": 3,
+        "analyze": {},
+        "crawlerComment": 0,
+        "inputGroup": [],
+        "inputSourceGroups": [],
+        "modePublishTime": [],
+        "name": "ceshi_2",
+        "frequencyType": 2,
+        "channel": 5,
+        "crawlerMode": 5,
+        "tagPenetrateFlag": 1,
+        "inputModeValues": [
+          "https://mp.weixin.qq.com/s?__biz=MzkzNjYxMjY0Nw==&mid=2247493247&idx=5&sn=affe5583151b5172e08c6dddc562409a&chksm=c310f88194bc350bd68d77843279b815e5ab12c760ad5abf8c9fc60a28afac01c767e3fff1ee&scene=126&sessionid=1679649075#rd"
+        ],
+        "planType": 2
+      },
+      "baseInfo": {
+        "token": "79dcb40af1de43b1bd9fe3a731dbaa15",
+        "appType": 9,
+        "platform": "pc",
+        "appVersionCode": 1000,
+        "clientTimestamp": 1,
+        "fid": 1,
+        "loginUid": 1,
+        "pageSource": 1,
+        "requestId": 1,
+        "rid": 1,
+        "uid": 1
+      }
+    }
+}

+ 124 - 0
long-article-recommend-service/src/main/resources/file/长文_生成结果库_根据计划id获取内容.json

@@ -0,0 +1,124 @@
+{
+    "describe": "长文_生成结果库_根据计划id获取内容",
+    "api_url": "http://aigc-api.cybertogether.net/aigc/produce/content/listProduceContent",
+        "res": {
+        "code": 0,
+        "msg": "success",
+        "data": {
+            "totalCount": 13,
+            "data": [
+                {
+                    "id": "20240625085017128585898",
+                    "coverImageUrl": "http://mmbiz.qpic.cn/sz_mmbiz_jpg/yDPAYn5Q12m5pdJhp1gSZNQCib0viaHZe7zUEz35iaeAJ0WBS901SFXdXrWPmnTFSXEoLC6fxNNj2uVVfKicaG9kng/0?from=appmsg",
+                    "imageUrls": [
+                        "http://mmbiz.qpic.cn/sz_mmbiz_jpg/janiabPMf2s6BGHNZgmgJGVb1ywc4icIH9qeEHQjGf3ZxoZM9ML9jXTVtoyibI9tWo96Dia40MKEPjo5Cx307RLu6A/0?from=appmsg",
+                        "http://mmbiz.qpic.cn/mmbiz_jpg/GuzV7vbicpkXTrM2FMy1tN2WlnGY5PEuYN7ibvUicBBBPCkCuASwDoLmGXpCTU5kuYPpVpRMYG3X4qLrkLHibP3fHw/0?from=appmsg",
+                        "http://mmbiz.qpic.cn/mmbiz_jpg/ibJhJfc7Ybm9sgsENqN0iaj3bJOvYIz55wSDY0e1sxUYMjSLwzHvzHWSvG0qbk4701olmUmMQZ7RWricA9b7NiccjA/0?from=appmsg"
+                    ],
+                    "title": "被捡来的儿子考上清华被亲生父母认领那一刻说的话,让养父哭了",
+                    "bodyText": "最重要的财富。无论是养育之恩还是血缘之情,真正的亲情在于无私的付出和深厚的感情,而不是物质的交换。小明的经历让人们重新思考亲情和感恩的意义,感动了无数人。\n\n这种感恩之心和对亲情的珍视,是人生中最宝贵的财富。正是因为有无私的爱和关怀,我们才能在困境中找到前行的力量。小明的故事不仅展示了人性中最美好的部分,也传递出一种正能量,呼吁人们在物欲横流的社会中珍视亲情和感恩之心。这段感人的亲情故事,必将长久地激励着每一个读者。",
+                    "animationUrls": null,
+                    "prePublishContentId": null,
+                    "prePublishContentIdLink": null,
+                    "actionAccountId": null,
+                    "commentDetail": null,
+                    "letterDetail": null,
+                    "receiveId": null,
+                    "receiveIdLink": null,
+                    "receiveContent": null,
+                    "sendAccountId": null,
+                    "sendAccountData": null,
+                    "replyCommentDetail": null,
+                    "replyLetterDetail": null,
+                    "inputSrtTexts": null,
+                    "inputImageUrls": null,
+                    "produceAgainFlag": null,
+                    "produceAgainCount": null,
+                    "produceAgainTimestamp": null,
+                    "compositeVideoUrls": null,
+                    "compositeStatus": null,
+                    "compositeCount": null,
+                    "uploadVideoFlag": null,
+                    "sourceProducePlan": {
+                        "id": "20240625084744349304308",
+                        "name": "【1】【bing_v1】历史复用"
+                    },
+                    "quotePublishPlans": null,
+                    "referContentTitle": "被捡来的儿子考上清华被亲生父母认领那一刻说的话,让养父哭了",
+                    "referContentLink": "http://mp.weixin.qq.com/s?__biz=MzkwODUwODM3Mw==&mid=2247489660&idx=1&sn=33c0f654f784347590b1daad4246b695&chksm=c0c9b5c6f7be3cd0484790164a353524dfb1ca9fd95ad3b34b3c26b5770fb33a1c1b337c7a1e#rd",
+                    "referContentAccountName": "路边闲聊社",
+                    "referContentAccountLink": "https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=MzkwODUwODM3Mw==&scene=124#wechat_redirect",
+                    "referContentChannel": 5,
+                    "referContents": [
+                        {
+                            "groupId": "0",
+                            "groupIndex": 1,
+                            "groupName": "分组0",
+                            "referContentTitle": "被捡来的儿子考上清华被亲生父母认领那一刻说的话,让养父哭了",
+                            "referContentLink": "http://mp.weixin.qq.com/s?__biz=MzkwODUwODM3Mw==&mid=2247489660&idx=1&sn=33c0f654f784347590b1daad4246b695&chksm=c0c9b5c6f7be3cd0484790164a353524dfb1ca9fd95ad3b34b3c26b5770fb33a1c1b337c7a1e#rd",
+                            "referContentAccountName": "路边闲聊社",
+                            "referContentAccountLink": "https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=MzkwODUwODM3Mw==&scene=124#wechat_redirect",
+                            "referContentChannel": 5,
+                            "referContentModal": 3,
+                            "referContentId": 5048535,
+                            "midAdNum": null,
+                            "bottomAdNum": null
+                        }
+                    ],
+                    "produceTimestamp": 1719306484382,
+                    "auditStatus": 0,
+                    "auditAccount": null,
+                    "auditTimestamp": null,
+                    "editModuleTypes": [],
+                    "editAccount": null,
+                    "editTimestamp": null,
+                    "produceStatus": 2,
+                    "errorMsg": null,
+                    "errorDetails": null,
+                    "tagJson": null,
+                    "miniProgram": [],
+                    "expressionValue": null
+                }
+            ]
+        }
+    },
+    "data": {
+        "params": {
+            "filterItems": [
+                {
+                    "itemName": "produceStatus",
+                    "selectValues": [
+                        2
+                    ]
+                },
+                {
+                    "itemName": "sourceProducePlan",
+                    "selectValues": [
+                        "20240625084744349304308"
+                    ]
+                },
+                {
+                    "itemName": "produceTimestamp",
+                    "orderType": "asc"
+                }
+            ],
+            "listFieldFormula": [],
+            "pageNum": 1,
+            "pageSize": 50,
+            "produceModal": 3
+        },
+        "baseInfo": {
+            "token": "79dcb40af1de43b1bd9fe3a731dbaa15",
+            "appType": 9,
+            "platform": "pc",
+            "appVersionCode": 1000,
+            "clientTimestamp": 1,
+            "fid": 1,
+            "loginUid": 1,
+            "pageSource": 1,
+            "requestId": 1,
+            "rid": 1,
+            "uid": 1
+        }
+    }
+}

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

@@ -88,4 +88,18 @@
         </foreach>
     </insert>
 
+    <select id="getArticlePromotion"
+            resultType="com.tzld.longarticle.recommend.server.model.entity.longArticle.DatastatSortStrategy">
+        select *
+        from datastat_sort_strategy
+        where view_count >= #{viewCount}
+        and read_rate >= #{viewCountRate}
+        and fans > #{fans}
+        and date_str > #{dateStr}
+        and position in
+        <foreach collection="positions" item="item" open="(" close=")" separator=",">
+            #{item}
+        </foreach>
+    </select>
+
 </mapper>

+ 3 - 3
long-article-recommend-service/src/test/java/com/tzld/longarticle/recommend/server/FilterStrategyTest.java

@@ -4,7 +4,7 @@ import cn.hutool.core.io.resource.ResourceUtil;
 import com.alibaba.fastjson.JSONObject;
 import com.tencentcloudapi.tms.v20201229.models.TextModerationResponse;
 import com.tzld.longarticle.recommend.server.model.dto.Content;
-import com.tzld.longarticle.recommend.server.remote.AIGCRemoteService;
+import com.tzld.longarticle.recommend.server.remote.aigc.AIGCWaitingPublishContentService;
 import com.tzld.longarticle.recommend.server.remote.ArticleSensitiveRemoteService;
 import com.tzld.longarticle.recommend.server.repository.crawler.AccountAvgInfoRepository;
 import com.tzld.longarticle.recommend.server.model.entity.crawler.AccountAvgInfo;
@@ -34,7 +34,7 @@ public class FilterStrategyTest {
     @Resource
     FilterStrategy historyTitleStrategy;
     @Resource
-    AIGCRemoteService aigcRemoteService;
+    AIGCWaitingPublishContentService aigcWaitingPublishContentService;
     @Resource
     ArticleSensitiveRemoteService articleSensitiveRemoteService;
     @Resource
@@ -62,7 +62,7 @@ public class FilterStrategyTest {
         param.setAccountName("票圈最新消息");
         param.setAccountId("20231212144543068928298");
         param.setPlanId("20240724092832149199870");
-        List<Content> content = aigcRemoteService.getAllContent(param);;
+        List<Content> content = aigcWaitingPublishContentService.getAllContent(param);;
         FilterParam filterParam = new FilterParam();
         filterParam.setAccountName(param.getAccountName());
         filterParam.setContents(content);