Ver código fonte

Merge branch 'feature_fuwuhao' of Server/long-article-recommend into master

dingyunpeng 10 meses atrás
pai
commit
280870f28f
40 arquivos alterados com 2728 adições e 24 exclusões
  1. 6 0
      long-article-recommend-service/pom.xml
  2. BIN
      long-article-recommend-service/src/main/.DS_Store
  3. 2 1
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/Application.java
  4. 25 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/MBG.java
  5. 1 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/common/enums/RankStrategyEnum.java
  6. 50 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/RecommendWithUserGroupResponse.java
  7. 23 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/Result.java
  8. 26 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/WxUserGetResponse.java
  9. 98 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/remote/WxAccessTokenRemoteService.java
  10. 97 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/remote/WxUserManagementRemoteService.java
  11. 36 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/mapper/crawler/ArticleGzhDeveloperMapper.java
  12. 109 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/mapper/crawler/ArticleUserGroupMapper.java
  13. 23 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/model/ArticleGzhDeveloper.java
  14. 339 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/model/ArticleGzhDeveloperExample.java
  15. 168 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/model/ArticleUserGroup.java
  16. 621 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/model/ArticleUserGroupExample.java
  17. 4 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/RecommendParam.java
  18. 78 5
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/RecommendService.java
  19. 9 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/SceneConstants.java
  20. 213 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/UserManagementService.java
  21. 1 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/filter/FilterParam.java
  22. 14 6
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/filter/FilterService.java
  23. 56 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/filter/strategy/HistoryTitleForFwhColdStartStrategy.java
  24. 3 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/rank/RankParam.java
  25. 16 2
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/rank/RankService.java
  26. 109 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/rank/strategy/FwhColdStartRankStrategy.java
  27. 2 5
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/rank/strategy/RankV5Strategy.java
  28. 1 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recall/FilterParamFactory.java
  29. 2 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recall/RecallParam.java
  30. 0 1
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recall/RecallService.java
  31. 1 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/score/ScoreParam.java
  32. 0 1
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/score/ScoreService.java
  33. 8 1
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/web/RecommendController.java
  34. 50 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/web/UserManagementController.java
  35. 2 0
      long-article-recommend-service/src/main/resources/application-dev.yml
  36. 4 1
      long-article-recommend-service/src/main/resources/application.yml
  37. 41 0
      long-article-recommend-service/src/main/resources/generatorConfig.xml
  38. 171 0
      long-article-recommend-service/src/main/resources/mapper/crawler/ArticleGzhDeveloperMapper.xml
  39. 319 0
      long-article-recommend-service/src/main/resources/mapper/crawler/ArticleUserGroupMapper.xml
  40. 0 1
      long-article-recommend-service/src/main/resources/mapper/crawler/CrawlerBaseMapper.xml

+ 6 - 0
long-article-recommend-service/pom.xml

@@ -116,6 +116,12 @@
             <groupId>org.mybatis.spring.boot</groupId>
             <artifactId>mybatis-spring-boot-starter</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.mybatis.generator</groupId>
+            <artifactId>mybatis-generator-core</artifactId>
+            <version>1.4.2</version>
+        </dependency>
+
 
     </dependencies>
 

BIN
long-article-recommend-service/src/main/.DS_Store


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

@@ -2,6 +2,7 @@ package com.tzld.longarticle.recommend.server;
 
 
 import com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig;
+import org.mybatis.spring.annotation.MapperScan;
 import org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
@@ -25,6 +26,7 @@ import org.springframework.context.annotation.EnableAspectJAutoProxy;
         "com.tzld.longarticle.recommend.server.util",
         "com.tzld.longarticle.recommend.server.repository",
 })
+@MapperScan("com.tzld.longarticle.recommend.server.repository.mapper")
 @EnableAspectJAutoProxy
 @EnableApolloConfig
 public class Application {
@@ -32,6 +34,5 @@ public class Application {
         SpringApplication.run(Application.class, args);
     }
 
-
 }
 

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

@@ -0,0 +1,25 @@
+package com.tzld.longarticle.recommend.server;
+
+import org.mybatis.generator.api.MyBatisGenerator;
+import org.mybatis.generator.config.Configuration;
+import org.mybatis.generator.config.xml.ConfigurationParser;
+import org.mybatis.generator.internal.DefaultShellCallback;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author dyp
+ */
+public class MBG {
+    public static void main(String[] args) throws Exception {
+        List<String> warnings = new ArrayList<String>();
+        boolean overwrite = true;
+        ConfigurationParser cp = new ConfigurationParser(warnings);
+        Configuration config = cp.parseConfiguration(new File("/Users/dingyunpeng/Desktop/code/changwen/long-article-recommend/long-article-recommend-service/src/main/resources/generatorConfig.xml"));
+        DefaultShellCallback callback = new DefaultShellCallback(overwrite);
+        MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
+        myBatisGenerator.generate(null);
+    }
+}

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

@@ -10,6 +10,7 @@ public enum RankStrategyEnum {
     ArticleRankV3("ArticleRankV3", "ArticleRankV3", "rankV3Strategy"),
     ArticleRankV4("ArticleRankV4", "ArticleRankV4", "rankV4Strategy"),
     ArticleRankV5("ArticleRankV5", "ArticleRankV5", "rankV5Strategy"),
+    ArticleRankV6("ArticleRankV6", "ArticleRankV6", "rankV6Strategy"),
 
     default_strategy("ArticleRankV1", "默认策略", "defaultRankStrategy"),
     ;

+ 50 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/RecommendWithUserGroupResponse.java

@@ -0,0 +1,50 @@
+package com.tzld.longarticle.recommend.server.model;
+
+import lombok.Data;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import java.util.List;
+
+/**
+ * @author dyp
+ */
+
+@Data
+public class RecommendWithUserGroupResponse {
+    private int code;
+    private String msg;
+    private RecommendWithUserGroupData data;
+
+    public RecommendWithUserGroupResponse(int code, String msg,
+                                          RecommendWithUserGroupData data) {
+        this.code = code;
+        this.msg = msg;
+        this.data = data;
+    }
+
+    @Data
+    public static class RecommendWithUserGroupData {
+        private List<RankData> rankList;
+        private List<FilterData> filterList;
+
+        public RecommendWithUserGroupData(List<RankData> rankList, List<FilterData> filterList) {
+            this.rankList = rankList;
+            this.filterList = filterList;
+        }
+    }
+
+    @Data
+    public static class RankData {
+        private Integer userGroupId;
+        private List<String> contentIds;
+    }
+
+    @Data
+    public static class FilterData {
+        private String contentId;
+        private String filterReason;
+    }
+}
+

+ 23 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/Result.java

@@ -0,0 +1,23 @@
+package com.tzld.longarticle.recommend.server.model;
+
+import com.tzld.longarticle.recommend.server.util.JSONUtils;
+import lombok.Data;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author dyp
+ */
+@Data
+public class Result {
+
+    public static String success(Object data) {
+        Map<String, Object> map = new HashMap<>();
+        map.put("code", 1);
+        map.put("msg", "success");
+        map.put("data", data);
+        return JSONUtils.toJson(map);
+    }
+
+}

+ 26 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/WxUserGetResponse.java

@@ -0,0 +1,26 @@
+package com.tzld.longarticle.recommend.server.model;
+
+import lombok.*;
+
+import java.util.List;
+
+/**
+ * @author dyp
+ */
+
+@NoArgsConstructor
+@Getter
+@Setter
+@AllArgsConstructor
+public class WxUserGetResponse {
+    private int total;
+    private int count;
+    private String next_openid;
+    private ResponseData data;
+
+    @lombok.Data
+    public static class ResponseData {
+        private List<String> openid;
+    }
+}
+

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

@@ -0,0 +1,98 @@
+package com.tzld.longarticle.recommend.server.remote;
+
+import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.tzld.longarticle.recommend.server.common.HttpPoolFactory;
+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.HttpGet;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.util.EntityUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author dyp
+ */
+@Service
+@Slf4j
+public class WxAccessTokenRemoteService {
+
+    private final CloseableHttpClient client = HttpPoolFactory.defaultPool();
+
+    private LoadingCache<String, String> cache = CacheBuilder.newBuilder()
+            .expireAfterWrite(10, TimeUnit.SECONDS)
+            .build(new CacheLoader<String, String>() {
+                @Override
+                public String load(String s) {
+                    return loadAccessToken(s);
+                }
+            });
+
+
+    @ApolloJsonValue("${gzhConfig:{}}")
+    private Map<String, Map<String, String>> gzhConfig;
+
+    public String getAccessToken(String gzhId) {
+        return cache.getUnchecked(gzhId);
+    }
+
+    private String loadAccessToken(String gzhId) {
+        try {
+
+            URIBuilder uriBuilder = new URIBuilder("http://aigc-api.cybertogether.net/aigc/publish/account/getAccessTokenByGhId");
+            uriBuilder.setParameter("gzhId", gzhId); // 假设需要传递gzhId参数
+            HttpGet httpGet = new HttpGet();
+            httpGet.setURI(uriBuilder.build());
+
+            CloseableHttpResponse response = client.execute(httpGet);
+            StatusLine statusLine = response.getStatusLine();
+            if (statusLine.getStatusCode() == 200) {
+                HttpEntity responseEntity = response.getEntity();
+                if (Objects.nonNull(responseEntity)) {
+                    return EntityUtils.toString(responseEntity, "UTF-8");
+                }
+            }
+        } catch (Exception e) {
+            log.error("get user error gzhId {} ", gzhId, e);
+        }
+        return null;
+    }
+
+//    private String loadAccessToken(String gzhId) {
+//        try {
+//            Map<String, Object> param = new HashMap<>();
+//            param.put("grant_type", "client_credential");
+//            param.put("appid", gzhConfig.get(gzhId).get("appid"));
+//            param.put("secret", gzhConfig.get(gzhId).get("secret"));
+//            param.put("force_refresh", false);
+//
+//            HttpPost httpPost = new HttpPost("https://api.weixin.qq.com/cgi-bin/stable_token");
+//            StringEntity stringEntity = new StringEntity(JSONUtils.toJson(param), 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");
+//                    Map<String, String> result = JSONUtils.fromJson(responseBody, new TypeToken<Map<String, String>>() {
+//                    }, Collections.emptyMap());
+//                    return result.get("access_token");
+//                }
+//            }
+//        } catch (Exception e) {
+//            log.error("get user error gzhId {} ", gzhId, e);
+//        }
+//        return null;
+//    }
+}

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

@@ -0,0 +1,97 @@
+package com.tzld.longarticle.recommend.server.remote;
+
+import com.aliyun.odps.utils.StringUtils;
+import com.google.common.reflect.TypeToken;
+import com.tzld.longarticle.recommend.server.common.HttpPoolFactory;
+import com.tzld.longarticle.recommend.server.model.WxUserGetResponse;
+import com.tzld.longarticle.recommend.server.util.JSONUtils;
+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.HttpGet;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.util.EntityUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Objects;
+
+/**
+ * @author dyp
+ */
+@Service
+@Slf4j
+public class WxUserManagementRemoteService {
+
+    private final CloseableHttpClient client = HttpPoolFactory.defaultPool();
+
+    @Autowired
+    private WxAccessTokenRemoteService wxAccessTokenRemoteService;
+
+    public WxUserGetResponse getAllUserLimit10000(String gzhId) {
+
+        try {
+
+            String accessToken = wxAccessTokenRemoteService.getAccessToken(gzhId);
+            if (StringUtils.isBlank(accessToken)) {
+                log.error("gzh {} access_token not config", gzhId);
+                return null;
+            }
+
+            URIBuilder uriBuilder = new URIBuilder("https://api.weixin.qq.com/cgi-bin/user/get");
+            uriBuilder.setParameter("gzhId", gzhId); // 假设需要传递gzhId参数
+            uriBuilder.setParameter("access_token", accessToken);
+            HttpGet httpGet = new HttpGet();
+            httpGet.setURI(uriBuilder.build());
+
+            CloseableHttpResponse response = client.execute(httpGet);
+            StatusLine statusLine = response.getStatusLine();
+            if (statusLine.getStatusCode() == 200) {
+                HttpEntity responseEntity = response.getEntity();
+                if (Objects.nonNull(responseEntity)) {
+                    String responseBody = EntityUtils.toString(responseEntity, "UTF-8");
+                    return JSONUtils.fromJson(responseBody, new TypeToken<WxUserGetResponse>() {
+                    }, null);
+                }
+            }
+        } catch (Exception e) {
+            log.error("get user error gzhId {} ", gzhId, e);
+        }
+        return null;
+    }
+
+    public WxUserGetResponse getAllUserLimit10000(String gzhId, String nextOpenId) {
+        try {
+
+            String accessToken = wxAccessTokenRemoteService.getAccessToken(gzhId);
+            if (StringUtils.isBlank(accessToken)) {
+                log.error("gzh {} access_token not config", gzhId);
+                return null;
+            }
+
+            URIBuilder uriBuilder = new URIBuilder("https://api.weixin.qq.com/cgi-bin/user/get");
+            uriBuilder.setParameter("gzhId", gzhId); // 假设需要传递gzhId参数
+            uriBuilder.setParameter("access_token", accessToken);
+            uriBuilder.setParameter("next_openid", nextOpenId);
+            HttpGet httpGet = new HttpGet();
+            httpGet.setURI(uriBuilder.build());
+
+            CloseableHttpResponse response = client.execute(httpGet);
+            StatusLine statusLine = response.getStatusLine();
+            if (statusLine.getStatusCode() == 200) {
+                HttpEntity responseEntity = response.getEntity();
+                if (Objects.nonNull(responseEntity)) {
+                    String responseBody = EntityUtils.toString(responseEntity, "UTF-8");
+                    return JSONUtils.fromJson(responseBody, new TypeToken<WxUserGetResponse>() {
+                    }, null);
+                }
+            }
+        } catch (Exception e) {
+            log.error("get user error gzhId={} nextOpenId={} ", gzhId, nextOpenId, e);
+        }
+        return null;
+    }
+
+}

+ 36 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/mapper/crawler/ArticleGzhDeveloperMapper.java

@@ -0,0 +1,36 @@
+package com.tzld.longarticle.recommend.server.repository.mapper.crawler;
+
+import com.tzld.longarticle.recommend.server.repository.model.ArticleGzhDeveloper;
+import com.tzld.longarticle.recommend.server.repository.model.ArticleGzhDeveloperExample;
+import java.util.List;
+
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+@Mapper
+public interface ArticleGzhDeveloperMapper {
+    long countByExample(ArticleGzhDeveloperExample example);
+
+    int deleteByExample(ArticleGzhDeveloperExample example);
+
+    int deleteByPrimaryKey(String gzhId);
+
+    int insert(ArticleGzhDeveloper row);
+
+    int insertSelective(ArticleGzhDeveloper row);
+
+    List<ArticleGzhDeveloper> selectByExample(ArticleGzhDeveloperExample example);
+
+    ArticleGzhDeveloper selectByPrimaryKey(String gzhId);
+
+    int updateByExampleSelective(@Param("row") ArticleGzhDeveloper row, @Param("example") ArticleGzhDeveloperExample example);
+
+    int updateByExample(@Param("row") ArticleGzhDeveloper row, @Param("example") ArticleGzhDeveloperExample example);
+
+    int updateByPrimaryKeySelective(ArticleGzhDeveloper row);
+
+    int updateByPrimaryKey(ArticleGzhDeveloper row);
+
+    String selectGzhIdByAppId(String appId);
+
+}

+ 109 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/mapper/crawler/ArticleUserGroupMapper.java

@@ -0,0 +1,109 @@
+package com.tzld.longarticle.recommend.server.repository.mapper.crawler;
+
+import com.tzld.longarticle.recommend.server.repository.model.ArticleUserGroup;
+import com.tzld.longarticle.recommend.server.repository.model.ArticleUserGroupExample;
+
+import java.util.List;
+
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+@Mapper
+public interface ArticleUserGroupMapper {
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table article_user_group
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    long countByExample(ArticleUserGroupExample example);
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table article_user_group
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    int deleteByExample(ArticleUserGroupExample example);
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table article_user_group
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    int deleteByPrimaryKey(Long id);
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table article_user_group
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    int insert(ArticleUserGroup row);
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table article_user_group
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    int insertSelective(ArticleUserGroup row);
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table article_user_group
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    List<ArticleUserGroup> selectByExample(ArticleUserGroupExample example);
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table article_user_group
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    ArticleUserGroup selectByPrimaryKey(Long id);
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table article_user_group
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    int updateByExampleSelective(@Param("row") ArticleUserGroup row, @Param("example") ArticleUserGroupExample example);
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table article_user_group
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    int updateByExample(@Param("row") ArticleUserGroup row, @Param("example") ArticleUserGroupExample example);
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table article_user_group
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    int updateByPrimaryKeySelective(ArticleUserGroup row);
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table article_user_group
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    int updateByPrimaryKey(ArticleUserGroup row);
+
+    int insertBatch(List<ArticleUserGroup> list);
+
+    ArticleUserGroup selectByGzhIdAndOpenId(String gzhId, String openId);
+
+    List<Integer> selectUserGroupIdByGzhId(String gzhId);
+
+    List<String> selectOpenIdByGzhIdAndUserGroupId(String gzhId, Integer userGroupId);
+
+}

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

@@ -0,0 +1,23 @@
+package com.tzld.longarticle.recommend.server.repository.model;
+
+public class ArticleGzhDeveloper {
+    private String gzhId;
+
+    private String appId;
+
+    public String getGzhId() {
+        return gzhId;
+    }
+
+    public void setGzhId(String gzhId) {
+        this.gzhId = gzhId == null ? null : gzhId.trim();
+    }
+
+    public String getAppId() {
+        return appId;
+    }
+
+    public void setAppId(String appId) {
+        this.appId = appId == null ? null : appId.trim();
+    }
+}

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

@@ -0,0 +1,339 @@
+package com.tzld.longarticle.recommend.server.repository.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ArticleGzhDeveloperExample {
+    protected String orderByClause;
+
+    protected boolean distinct;
+
+    protected List<Criteria> oredCriteria;
+
+    public ArticleGzhDeveloperExample() {
+        oredCriteria = new ArrayList<>();
+    }
+
+    public void setOrderByClause(String orderByClause) {
+        this.orderByClause = orderByClause;
+    }
+
+    public String getOrderByClause() {
+        return orderByClause;
+    }
+
+    public void setDistinct(boolean distinct) {
+        this.distinct = distinct;
+    }
+
+    public boolean isDistinct() {
+        return distinct;
+    }
+
+    public List<Criteria> getOredCriteria() {
+        return oredCriteria;
+    }
+
+    public void or(Criteria criteria) {
+        oredCriteria.add(criteria);
+    }
+
+    public Criteria or() {
+        Criteria criteria = createCriteriaInternal();
+        oredCriteria.add(criteria);
+        return criteria;
+    }
+
+    public Criteria createCriteria() {
+        Criteria criteria = createCriteriaInternal();
+        if (oredCriteria.size() == 0) {
+            oredCriteria.add(criteria);
+        }
+        return criteria;
+    }
+
+    protected Criteria createCriteriaInternal() {
+        Criteria criteria = new Criteria();
+        return criteria;
+    }
+
+    public void clear() {
+        oredCriteria.clear();
+        orderByClause = null;
+        distinct = false;
+    }
+
+    protected abstract static class GeneratedCriteria {
+        protected List<Criterion> criteria;
+
+        protected GeneratedCriteria() {
+            super();
+            criteria = new ArrayList<>();
+        }
+
+        public boolean isValid() {
+            return criteria.size() > 0;
+        }
+
+        public List<Criterion> getAllCriteria() {
+            return criteria;
+        }
+
+        public List<Criterion> getCriteria() {
+            return criteria;
+        }
+
+        protected void addCriterion(String condition) {
+            if (condition == null) {
+                throw new RuntimeException("Value for condition cannot be null");
+            }
+            criteria.add(new Criterion(condition));
+        }
+
+        protected void addCriterion(String condition, Object value, String property) {
+            if (value == null) {
+                throw new RuntimeException("Value for " + property + " cannot be null");
+            }
+            criteria.add(new Criterion(condition, value));
+        }
+
+        protected void addCriterion(String condition, Object value1, Object value2, String property) {
+            if (value1 == null || value2 == null) {
+                throw new RuntimeException("Between values for " + property + " cannot be null");
+            }
+            criteria.add(new Criterion(condition, value1, value2));
+        }
+
+        public Criteria andGzhIdIsNull() {
+            addCriterion("gzh_id is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andGzhIdIsNotNull() {
+            addCriterion("gzh_id is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andGzhIdEqualTo(String value) {
+            addCriterion("gzh_id =", value, "gzhId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGzhIdNotEqualTo(String value) {
+            addCriterion("gzh_id <>", value, "gzhId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGzhIdGreaterThan(String value) {
+            addCriterion("gzh_id >", value, "gzhId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGzhIdGreaterThanOrEqualTo(String value) {
+            addCriterion("gzh_id >=", value, "gzhId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGzhIdLessThan(String value) {
+            addCriterion("gzh_id <", value, "gzhId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGzhIdLessThanOrEqualTo(String value) {
+            addCriterion("gzh_id <=", value, "gzhId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGzhIdLike(String value) {
+            addCriterion("gzh_id like", value, "gzhId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGzhIdNotLike(String value) {
+            addCriterion("gzh_id not like", value, "gzhId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGzhIdIn(List<String> values) {
+            addCriterion("gzh_id in", values, "gzhId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGzhIdNotIn(List<String> values) {
+            addCriterion("gzh_id not in", values, "gzhId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGzhIdBetween(String value1, String value2) {
+            addCriterion("gzh_id between", value1, value2, "gzhId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGzhIdNotBetween(String value1, String value2) {
+            addCriterion("gzh_id not between", value1, value2, "gzhId");
+            return (Criteria) this;
+        }
+
+        public Criteria andAppIdIsNull() {
+            addCriterion("app_id is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andAppIdIsNotNull() {
+            addCriterion("app_id is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andAppIdEqualTo(String value) {
+            addCriterion("app_id =", value, "appId");
+            return (Criteria) this;
+        }
+
+        public Criteria andAppIdNotEqualTo(String value) {
+            addCriterion("app_id <>", value, "appId");
+            return (Criteria) this;
+        }
+
+        public Criteria andAppIdGreaterThan(String value) {
+            addCriterion("app_id >", value, "appId");
+            return (Criteria) this;
+        }
+
+        public Criteria andAppIdGreaterThanOrEqualTo(String value) {
+            addCriterion("app_id >=", value, "appId");
+            return (Criteria) this;
+        }
+
+        public Criteria andAppIdLessThan(String value) {
+            addCriterion("app_id <", value, "appId");
+            return (Criteria) this;
+        }
+
+        public Criteria andAppIdLessThanOrEqualTo(String value) {
+            addCriterion("app_id <=", value, "appId");
+            return (Criteria) this;
+        }
+
+        public Criteria andAppIdLike(String value) {
+            addCriterion("app_id like", value, "appId");
+            return (Criteria) this;
+        }
+
+        public Criteria andAppIdNotLike(String value) {
+            addCriterion("app_id not like", value, "appId");
+            return (Criteria) this;
+        }
+
+        public Criteria andAppIdIn(List<String> values) {
+            addCriterion("app_id in", values, "appId");
+            return (Criteria) this;
+        }
+
+        public Criteria andAppIdNotIn(List<String> values) {
+            addCriterion("app_id not in", values, "appId");
+            return (Criteria) this;
+        }
+
+        public Criteria andAppIdBetween(String value1, String value2) {
+            addCriterion("app_id between", value1, value2, "appId");
+            return (Criteria) this;
+        }
+
+        public Criteria andAppIdNotBetween(String value1, String value2) {
+            addCriterion("app_id not between", value1, value2, "appId");
+            return (Criteria) this;
+        }
+    }
+
+    public static class Criteria extends GeneratedCriteria {
+        protected Criteria() {
+            super();
+        }
+    }
+
+    public static class Criterion {
+        private String condition;
+
+        private Object value;
+
+        private Object secondValue;
+
+        private boolean noValue;
+
+        private boolean singleValue;
+
+        private boolean betweenValue;
+
+        private boolean listValue;
+
+        private String typeHandler;
+
+        public String getCondition() {
+            return condition;
+        }
+
+        public Object getValue() {
+            return value;
+        }
+
+        public Object getSecondValue() {
+            return secondValue;
+        }
+
+        public boolean isNoValue() {
+            return noValue;
+        }
+
+        public boolean isSingleValue() {
+            return singleValue;
+        }
+
+        public boolean isBetweenValue() {
+            return betweenValue;
+        }
+
+        public boolean isListValue() {
+            return listValue;
+        }
+
+        public String getTypeHandler() {
+            return typeHandler;
+        }
+
+        protected Criterion(String condition) {
+            super();
+            this.condition = condition;
+            this.typeHandler = null;
+            this.noValue = true;
+        }
+
+        protected Criterion(String condition, Object value, String typeHandler) {
+            super();
+            this.condition = condition;
+            this.value = value;
+            this.typeHandler = typeHandler;
+            if (value instanceof List<?>) {
+                this.listValue = true;
+            } else {
+                this.singleValue = true;
+            }
+        }
+
+        protected Criterion(String condition, Object value) {
+            this(condition, value, null);
+        }
+
+        protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {
+            super();
+            this.condition = condition;
+            this.value = value;
+            this.secondValue = secondValue;
+            this.typeHandler = typeHandler;
+            this.betweenValue = true;
+        }
+
+        protected Criterion(String condition, Object value, Object secondValue) {
+            this(condition, value, secondValue, null);
+        }
+    }
+}

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

@@ -0,0 +1,168 @@
+package com.tzld.longarticle.recommend.server.repository.model;
+
+public class ArticleUserGroup {
+    /**
+     *
+     * This field was generated by MyBatis Generator.
+     * This field corresponds to the database column article_user_group.id
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    private Long id;
+
+    /**
+     *
+     * This field was generated by MyBatis Generator.
+     * This field corresponds to the database column article_user_group.gzh_id
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    private String gzhId;
+
+    /**
+     *
+     * This field was generated by MyBatis Generator.
+     * This field corresponds to the database column article_user_group.user_group_id
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    private Integer userGroupId;
+
+    /**
+     *
+     * This field was generated by MyBatis Generator.
+     * This field corresponds to the database column article_user_group.open_id
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    private String openId;
+
+    /**
+     *
+     * This field was generated by MyBatis Generator.
+     * This field corresponds to the database column article_user_group.is_delete
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    private Integer isDelete;
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method returns the value of the database column article_user_group.id
+     *
+     * @return the value of article_user_group.id
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    public Long getId() {
+        return id;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method sets the value of the database column article_user_group.id
+     *
+     * @param id the value for article_user_group.id
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method returns the value of the database column article_user_group.gzh_id
+     *
+     * @return the value of article_user_group.gzh_id
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    public String getGzhId() {
+        return gzhId;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method sets the value of the database column article_user_group.gzh_id
+     *
+     * @param gzhId the value for article_user_group.gzh_id
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    public void setGzhId(String gzhId) {
+        this.gzhId = gzhId == null ? null : gzhId.trim();
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method returns the value of the database column article_user_group.user_group_id
+     *
+     * @return the value of article_user_group.user_group_id
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    public Integer getUserGroupId() {
+        return userGroupId;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method sets the value of the database column article_user_group.user_group_id
+     *
+     * @param userGroupId the value for article_user_group.user_group_id
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    public void setUserGroupId(Integer userGroupId) {
+        this.userGroupId = userGroupId;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method returns the value of the database column article_user_group.open_id
+     *
+     * @return the value of article_user_group.open_id
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    public String getOpenId() {
+        return openId;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method sets the value of the database column article_user_group.open_id
+     *
+     * @param openId the value for article_user_group.open_id
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    public void setOpenId(String openId) {
+        this.openId = openId == null ? null : openId.trim();
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method returns the value of the database column article_user_group.is_delete
+     *
+     * @return the value of article_user_group.is_delete
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    public Integer getIsDelete() {
+        return isDelete;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method sets the value of the database column article_user_group.is_delete
+     *
+     * @param isDelete the value for article_user_group.is_delete
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    public void setIsDelete(Integer isDelete) {
+        this.isDelete = isDelete;
+    }
+}

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

@@ -0,0 +1,621 @@
+package com.tzld.longarticle.recommend.server.repository.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ArticleUserGroupExample {
+    /**
+     * This field was generated by MyBatis Generator.
+     * This field corresponds to the database table article_user_group
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    protected String orderByClause;
+
+    /**
+     * This field was generated by MyBatis Generator.
+     * This field corresponds to the database table article_user_group
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    protected boolean distinct;
+
+    /**
+     * This field was generated by MyBatis Generator.
+     * This field corresponds to the database table article_user_group
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    protected List<Criteria> oredCriteria;
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table article_user_group
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    public ArticleUserGroupExample() {
+        oredCriteria = new ArrayList<>();
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table article_user_group
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    public void setOrderByClause(String orderByClause) {
+        this.orderByClause = orderByClause;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table article_user_group
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    public String getOrderByClause() {
+        return orderByClause;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table article_user_group
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    public void setDistinct(boolean distinct) {
+        this.distinct = distinct;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table article_user_group
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    public boolean isDistinct() {
+        return distinct;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table article_user_group
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    public List<Criteria> getOredCriteria() {
+        return oredCriteria;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table article_user_group
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    public void or(Criteria criteria) {
+        oredCriteria.add(criteria);
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table article_user_group
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    public Criteria or() {
+        Criteria criteria = createCriteriaInternal();
+        oredCriteria.add(criteria);
+        return criteria;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table article_user_group
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    public Criteria createCriteria() {
+        Criteria criteria = createCriteriaInternal();
+        if (oredCriteria.size() == 0) {
+            oredCriteria.add(criteria);
+        }
+        return criteria;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table article_user_group
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    protected Criteria createCriteriaInternal() {
+        Criteria criteria = new Criteria();
+        return criteria;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table article_user_group
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    public void clear() {
+        oredCriteria.clear();
+        orderByClause = null;
+        distinct = false;
+    }
+
+    /**
+     * This class was generated by MyBatis Generator.
+     * This class corresponds to the database table article_user_group
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    protected abstract static class GeneratedCriteria {
+        protected List<Criterion> criteria;
+
+        protected GeneratedCriteria() {
+            super();
+            criteria = new ArrayList<>();
+        }
+
+        public boolean isValid() {
+            return criteria.size() > 0;
+        }
+
+        public List<Criterion> getAllCriteria() {
+            return criteria;
+        }
+
+        public List<Criterion> getCriteria() {
+            return criteria;
+        }
+
+        protected void addCriterion(String condition) {
+            if (condition == null) {
+                throw new RuntimeException("Value for condition cannot be null");
+            }
+            criteria.add(new Criterion(condition));
+        }
+
+        protected void addCriterion(String condition, Object value, String property) {
+            if (value == null) {
+                throw new RuntimeException("Value for " + property + " cannot be null");
+            }
+            criteria.add(new Criterion(condition, value));
+        }
+
+        protected void addCriterion(String condition, Object value1, Object value2, String property) {
+            if (value1 == null || value2 == null) {
+                throw new RuntimeException("Between values for " + property + " cannot be null");
+            }
+            criteria.add(new Criterion(condition, value1, value2));
+        }
+
+        public Criteria andIdIsNull() {
+            addCriterion("id is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdIsNotNull() {
+            addCriterion("id is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdEqualTo(Long value) {
+            addCriterion("id =", value, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdNotEqualTo(Long value) {
+            addCriterion("id <>", value, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdGreaterThan(Long value) {
+            addCriterion("id >", value, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdGreaterThanOrEqualTo(Long value) {
+            addCriterion("id >=", value, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdLessThan(Long value) {
+            addCriterion("id <", value, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdLessThanOrEqualTo(Long value) {
+            addCriterion("id <=", value, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdIn(List<Long> values) {
+            addCriterion("id in", values, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdNotIn(List<Long> values) {
+            addCriterion("id not in", values, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdBetween(Long value1, Long value2) {
+            addCriterion("id between", value1, value2, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdNotBetween(Long value1, Long value2) {
+            addCriterion("id not between", value1, value2, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andGzhIdIsNull() {
+            addCriterion("gzh_id is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andGzhIdIsNotNull() {
+            addCriterion("gzh_id is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andGzhIdEqualTo(String value) {
+            addCriterion("gzh_id =", value, "gzhId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGzhIdNotEqualTo(String value) {
+            addCriterion("gzh_id <>", value, "gzhId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGzhIdGreaterThan(String value) {
+            addCriterion("gzh_id >", value, "gzhId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGzhIdGreaterThanOrEqualTo(String value) {
+            addCriterion("gzh_id >=", value, "gzhId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGzhIdLessThan(String value) {
+            addCriterion("gzh_id <", value, "gzhId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGzhIdLessThanOrEqualTo(String value) {
+            addCriterion("gzh_id <=", value, "gzhId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGzhIdLike(String value) {
+            addCriterion("gzh_id like", value, "gzhId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGzhIdNotLike(String value) {
+            addCriterion("gzh_id not like", value, "gzhId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGzhIdIn(List<String> values) {
+            addCriterion("gzh_id in", values, "gzhId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGzhIdNotIn(List<String> values) {
+            addCriterion("gzh_id not in", values, "gzhId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGzhIdBetween(String value1, String value2) {
+            addCriterion("gzh_id between", value1, value2, "gzhId");
+            return (Criteria) this;
+        }
+
+        public Criteria andGzhIdNotBetween(String value1, String value2) {
+            addCriterion("gzh_id not between", value1, value2, "gzhId");
+            return (Criteria) this;
+        }
+
+        public Criteria andUserGroupIdIsNull() {
+            addCriterion("user_group_id is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andUserGroupIdIsNotNull() {
+            addCriterion("user_group_id is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andUserGroupIdEqualTo(Integer value) {
+            addCriterion("user_group_id =", value, "userGroupId");
+            return (Criteria) this;
+        }
+
+        public Criteria andUserGroupIdNotEqualTo(Integer value) {
+            addCriterion("user_group_id <>", value, "userGroupId");
+            return (Criteria) this;
+        }
+
+        public Criteria andUserGroupIdGreaterThan(Integer value) {
+            addCriterion("user_group_id >", value, "userGroupId");
+            return (Criteria) this;
+        }
+
+        public Criteria andUserGroupIdGreaterThanOrEqualTo(Integer value) {
+            addCriterion("user_group_id >=", value, "userGroupId");
+            return (Criteria) this;
+        }
+
+        public Criteria andUserGroupIdLessThan(Integer value) {
+            addCriterion("user_group_id <", value, "userGroupId");
+            return (Criteria) this;
+        }
+
+        public Criteria andUserGroupIdLessThanOrEqualTo(Integer value) {
+            addCriterion("user_group_id <=", value, "userGroupId");
+            return (Criteria) this;
+        }
+
+        public Criteria andUserGroupIdIn(List<Integer> values) {
+            addCriterion("user_group_id in", values, "userGroupId");
+            return (Criteria) this;
+        }
+
+        public Criteria andUserGroupIdNotIn(List<Integer> values) {
+            addCriterion("user_group_id not in", values, "userGroupId");
+            return (Criteria) this;
+        }
+
+        public Criteria andUserGroupIdBetween(Integer value1, Integer value2) {
+            addCriterion("user_group_id between", value1, value2, "userGroupId");
+            return (Criteria) this;
+        }
+
+        public Criteria andUserGroupIdNotBetween(Integer value1, Integer value2) {
+            addCriterion("user_group_id not between", value1, value2, "userGroupId");
+            return (Criteria) this;
+        }
+
+        public Criteria andOpenIdIsNull() {
+            addCriterion("open_id is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andOpenIdIsNotNull() {
+            addCriterion("open_id is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andOpenIdEqualTo(String value) {
+            addCriterion("open_id =", value, "openId");
+            return (Criteria) this;
+        }
+
+        public Criteria andOpenIdNotEqualTo(String value) {
+            addCriterion("open_id <>", value, "openId");
+            return (Criteria) this;
+        }
+
+        public Criteria andOpenIdGreaterThan(String value) {
+            addCriterion("open_id >", value, "openId");
+            return (Criteria) this;
+        }
+
+        public Criteria andOpenIdGreaterThanOrEqualTo(String value) {
+            addCriterion("open_id >=", value, "openId");
+            return (Criteria) this;
+        }
+
+        public Criteria andOpenIdLessThan(String value) {
+            addCriterion("open_id <", value, "openId");
+            return (Criteria) this;
+        }
+
+        public Criteria andOpenIdLessThanOrEqualTo(String value) {
+            addCriterion("open_id <=", value, "openId");
+            return (Criteria) this;
+        }
+
+        public Criteria andOpenIdLike(String value) {
+            addCriterion("open_id like", value, "openId");
+            return (Criteria) this;
+        }
+
+        public Criteria andOpenIdNotLike(String value) {
+            addCriterion("open_id not like", value, "openId");
+            return (Criteria) this;
+        }
+
+        public Criteria andOpenIdIn(List<String> values) {
+            addCriterion("open_id in", values, "openId");
+            return (Criteria) this;
+        }
+
+        public Criteria andOpenIdNotIn(List<String> values) {
+            addCriterion("open_id not in", values, "openId");
+            return (Criteria) this;
+        }
+
+        public Criteria andOpenIdBetween(String value1, String value2) {
+            addCriterion("open_id between", value1, value2, "openId");
+            return (Criteria) this;
+        }
+
+        public Criteria andOpenIdNotBetween(String value1, String value2) {
+            addCriterion("open_id not between", value1, value2, "openId");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsDeleteIsNull() {
+            addCriterion("is_delete is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsDeleteIsNotNull() {
+            addCriterion("is_delete is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsDeleteEqualTo(Integer value) {
+            addCriterion("is_delete =", value, "isDelete");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsDeleteNotEqualTo(Integer value) {
+            addCriterion("is_delete <>", value, "isDelete");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsDeleteGreaterThan(Integer value) {
+            addCriterion("is_delete >", value, "isDelete");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsDeleteGreaterThanOrEqualTo(Integer value) {
+            addCriterion("is_delete >=", value, "isDelete");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsDeleteLessThan(Integer value) {
+            addCriterion("is_delete <", value, "isDelete");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsDeleteLessThanOrEqualTo(Integer value) {
+            addCriterion("is_delete <=", value, "isDelete");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsDeleteIn(List<Integer> values) {
+            addCriterion("is_delete in", values, "isDelete");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsDeleteNotIn(List<Integer> values) {
+            addCriterion("is_delete not in", values, "isDelete");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsDeleteBetween(Integer value1, Integer value2) {
+            addCriterion("is_delete between", value1, value2, "isDelete");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsDeleteNotBetween(Integer value1, Integer value2) {
+            addCriterion("is_delete not between", value1, value2, "isDelete");
+            return (Criteria) this;
+        }
+    }
+
+    /**
+     * This class was generated by MyBatis Generator.
+     * This class corresponds to the database table article_user_group
+     *
+     * @mbg.generated do_not_delete_during_merge Thu Aug 22 20:53:08 CST 2024
+     */
+    public static class Criteria extends GeneratedCriteria {
+        protected Criteria() {
+            super();
+        }
+    }
+
+    /**
+     * This class was generated by MyBatis Generator.
+     * This class corresponds to the database table article_user_group
+     *
+     * @mbg.generated Thu Aug 22 20:53:08 CST 2024
+     */
+    public static class Criterion {
+        private String condition;
+
+        private Object value;
+
+        private Object secondValue;
+
+        private boolean noValue;
+
+        private boolean singleValue;
+
+        private boolean betweenValue;
+
+        private boolean listValue;
+
+        private String typeHandler;
+
+        public String getCondition() {
+            return condition;
+        }
+
+        public Object getValue() {
+            return value;
+        }
+
+        public Object getSecondValue() {
+            return secondValue;
+        }
+
+        public boolean isNoValue() {
+            return noValue;
+        }
+
+        public boolean isSingleValue() {
+            return singleValue;
+        }
+
+        public boolean isBetweenValue() {
+            return betweenValue;
+        }
+
+        public boolean isListValue() {
+            return listValue;
+        }
+
+        public String getTypeHandler() {
+            return typeHandler;
+        }
+
+        protected Criterion(String condition) {
+            super();
+            this.condition = condition;
+            this.typeHandler = null;
+            this.noValue = true;
+        }
+
+        protected Criterion(String condition, Object value, String typeHandler) {
+            super();
+            this.condition = condition;
+            this.value = value;
+            this.typeHandler = typeHandler;
+            if (value instanceof List<?>) {
+                this.listValue = true;
+            } else {
+                this.singleValue = true;
+            }
+        }
+
+        protected Criterion(String condition, Object value) {
+            this(condition, value, null);
+        }
+
+        protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {
+            super();
+            this.condition = condition;
+            this.value = value;
+            this.secondValue = secondValue;
+            this.typeHandler = typeHandler;
+            this.betweenValue = true;
+        }
+
+        protected Criterion(String condition, Object value, Object secondValue) {
+            this(condition, value, secondValue, null);
+        }
+    }
+}

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

@@ -4,6 +4,8 @@ import lombok.Getter;
 import lombok.NoArgsConstructor;
 import lombok.Setter;
 
+import java.util.List;
+
 /**
  * @author dyp
  */
@@ -20,5 +22,7 @@ public class RecommendParam {
     private String planId;
     // true 不记录日志
     private boolean excludeLog = false;
+    private String scene;
+    private List<Integer> userGroupIds;
 }
 

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

@@ -7,12 +7,14 @@ import com.tzld.longarticle.recommend.server.repository.crawler.PublishContentSo
 import com.tzld.longarticle.recommend.server.repository.crawler.PublishSortLogRepository;
 import com.tzld.longarticle.recommend.server.repository.entity.crawler.PublishContentSortLog;
 import com.tzld.longarticle.recommend.server.repository.entity.crawler.PublishSortLog;
+import com.tzld.longarticle.recommend.server.repository.mapper.crawler.ArticleUserGroupMapper;
 import com.tzld.longarticle.recommend.server.service.rank.RankParam;
 import com.tzld.longarticle.recommend.server.service.rank.RankResult;
 import com.tzld.longarticle.recommend.server.service.rank.RankService;
 import com.tzld.longarticle.recommend.server.service.recall.RecallParam;
 import com.tzld.longarticle.recommend.server.service.recall.RecallResult;
 import com.tzld.longarticle.recommend.server.service.recall.RecallService;
+import com.tzld.longarticle.recommend.server.util.CommonCollectionUtils;
 import com.tzld.longarticle.recommend.server.util.DateUtils;
 import com.tzld.longarticle.recommend.server.util.JSONUtils;
 import lombok.extern.slf4j.Slf4j;
@@ -23,12 +25,15 @@ import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.util.StringUtils;
 
+import java.time.LocalDate;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.stream.Collectors;
 
+import static com.tzld.longarticle.recommend.server.service.SceneConstants.FWH_COLD_START;
+
 /**
  * @author dyp
  */
@@ -46,6 +51,8 @@ public class RecommendService {
     private PublishSortLogRepository publishSortLogRepository;
     @Autowired
     AccountIndexAvgViewCountService accountIndexAvgViewCountService;
+    @Autowired
+    private ArticleUserGroupMapper articleUserGroupMapper;
 
     @ApolloJsonValue("${accountStrategyConfig:{}}")
     private Map<String, String> accountStrategyConfigMap;
@@ -55,7 +62,7 @@ public class RecommendService {
 
     public RecommendResponse recommend(RecommendRequest request) {
 
-        RecommendParam param = genRecommendParam(request);
+        RecommendParam param = genRecommendParam(request, SceneConstants.DEFAULT);
         log.info("genRecommendParam {}", JSONUtils.toJson(param));
         // 获取账号排序设置
         String strategyConfig = accountStrategyConfigMap.get(request.getAccountName());
@@ -63,16 +70,61 @@ public class RecommendService {
             param.setStrategy(strategyConfig);
         }
         RecallResult recallResult = recallService.recall(convertToRecallParam(param));
-        log.info("recallResult {}", JSONUtils.toJson(recallResult));
 
         RankResult rankResult = rankService.rank(convertToRankParam(param, recallResult));
-        log.info("rankResult {}", JSONUtils.toJson(rankResult));
+        //log.info("rankResult {}", JSONUtils.toJson(rankResult));
 
         saveSortLog(param, rankResult);
 
         return buildRecommendResponse(recallResult, rankResult, param.getPublishNum());
     }
 
+    public RecommendWithUserGroupResponse recommend4FwhColdStart(RecommendRequest request) {
+
+        RecommendParam param = genRecommendParam(request, FWH_COLD_START);
+        log.info("genRecommendParam {}", JSONUtils.toJson(param));
+        // 获取账号排序设置
+        String strategyConfig = accountStrategyConfigMap.get(request.getAccountName());
+        if (StringUtils.hasText(strategyConfig)) {
+            param.setStrategy(strategyConfig);
+        }
+        RecallResult recallResult = recallService.recall(convertToRecallParam(param));
+        //log.info("recallResult {}", JSONUtils.toJson(recallResult));
+
+        RankResult rankResult = rankService.rank(convertToRankParam(param, recallResult));
+        //log.info("rankResult {}", JSONUtils.toJson(rankResult));
+
+        saveSortLog(param, rankResult);
+
+
+        List<RecommendWithUserGroupResponse.RankData> rankList = new ArrayList<>();
+        List<Content> contentList = rankResult.getContents();
+        for (int i = 0, start = 0; i < param.getUserGroupIds().size() && start < contentList.size(); i++) {
+            RecommendWithUserGroupResponse.RankData rankData = new RecommendWithUserGroupResponse.RankData();
+            rankData.setUserGroupId(param.getUserGroupIds().get(i));
+            int end = Math.min(contentList.size(), start + param.getPublishNum());
+            rankData.setContentIds(CommonCollectionUtils.toList(contentList.subList(start, end), Content::getId));
+            rankList.add(rankData);
+            start += param.getPublishNum();
+        }
+
+        List<RecommendWithUserGroupResponse.FilterData> filterList = new ArrayList<>();
+        for (RecallResult.RecallData data : recallResult.getData()) {
+            if (CollectionUtils.isNotEmpty(data.getFilterContents())) {
+                for (Content filterContent : data.getFilterContents()) {
+                    RecommendWithUserGroupResponse.FilterData filterData = new RecommendWithUserGroupResponse.FilterData();
+                    filterData.setContentId(filterContent.getId());
+                    filterData.setFilterReason(filterContent.getFilterReason());
+                    filterList.add(filterData);
+                }
+            }
+        }
+
+
+        return new RecommendWithUserGroupResponse(0, "success",
+                new RecommendWithUserGroupResponse.RecommendWithUserGroupData(rankList, filterList));
+    }
+
     private RecommendResponse buildRecommendResponse(RecallResult recallResult, RankResult rankResult, Integer publishNum) {
         List<Content> contentList = rankResult.getContents();
         List<ArticleSortResponseDataItem> rankList = new ArrayList<>();
@@ -104,9 +156,27 @@ public class RecommendService {
         return response;
     }
 
-    public RecommendParam genRecommendParam(RecommendRequest request) {
+    public RecommendParam genRecommendParam(RecommendRequest request, String abCode) {
         RecommendParam param = new RecommendParam();
         BeanUtils.copyProperties(request, param);
+        param.setScene(abCode);
+
+        switch (abCode) {
+            case FWH_COLD_START:
+                List<Integer> userGroupIds = articleUserGroupMapper.selectUserGroupIdByGzhId(request.getGhId());
+                LocalDate today = LocalDate.now(); // 获取当前日期
+                int dayOfYear = today.getDayOfYear();
+                int tailNum = dayOfYear % 8;
+                List<Integer> needPushUserGroupIds = new ArrayList<>();
+                for (int userGroupId : userGroupIds) {
+                    if (userGroupId % 8 == tailNum) {
+                        needPushUserGroupIds.add(userGroupId);
+                    }
+                }
+                param.setUserGroupIds(needPushUserGroupIds);
+                break;
+        }
+
         return param;
     }
 
@@ -139,11 +209,15 @@ public class RecommendService {
         rankParam.setGhId(param.getGhId());
         rankParam.setAccountName(param.getAccountName());
         rankParam.setSize(param.getPublishNum());
+        rankParam.setScene(param.getScene());
+        rankParam.setUserGroupIds(param.getUserGroupIds());
+
         return rankParam;
     }
 
     /**
      * 记录 账号、排序策略、结果。。。
+     *
      * @param param
      * @param rankResult
      */
@@ -159,7 +233,6 @@ public class RecommendService {
         log.setPublishContentId(JSONObject.toJSONString(publishContentIds));
         log.setCreateTimestamp(System.currentTimeMillis());
         publishContentSortLogRepository.save(log);
-        // 仅记录3-8条 冷启层内容
         List<PublishSortLog> publishSortLogSaveList = new ArrayList<>();
         for (int i = 1; i < rankResult.getContents().size() + 1; i++) {
             Content content = rankResult.getContents().get(i - 1);

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

@@ -0,0 +1,9 @@
+package com.tzld.longarticle.recommend.server.service;
+
+/**
+ * @author dyp
+ */
+public class SceneConstants {
+    public static final String DEFAULT = "DEFAULT";
+    public static final String FWH_COLD_START = "FWH_COLD_START";
+}

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

@@ -0,0 +1,213 @@
+package com.tzld.longarticle.recommend.server.service;
+
+import com.tzld.longarticle.recommend.server.model.WxUserGetResponse;
+import com.tzld.longarticle.recommend.server.remote.WxUserManagementRemoteService;
+import com.tzld.longarticle.recommend.server.repository.mapper.crawler.ArticleGzhDeveloperMapper;
+import com.tzld.longarticle.recommend.server.repository.mapper.crawler.ArticleUserGroupMapper;
+import com.tzld.longarticle.recommend.server.repository.model.ArticleGzhDeveloper;
+import com.tzld.longarticle.recommend.server.repository.model.ArticleUserGroup;
+import com.tzld.longarticle.recommend.server.util.CommonCollectionUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang.math.RandomUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.dom4j.Document;
+import org.dom4j.Element;
+import org.dom4j.io.SAXReader;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.io.StringReader;
+import java.util.*;
+
+/**
+ * @author dyp
+ */
+@Slf4j
+@Service
+public class UserManagementService {
+    @Autowired
+    private WxUserManagementRemoteService wxUserManagementRemoteService;
+
+    @Autowired
+    private ArticleUserGroupMapper articleUserGroupMapper;
+
+    @Autowired
+    private ArticleGzhDeveloperMapper articleGzhDeveloperMapper;
+
+    public void addGZH(String gzhId, String appId, int groupNum) {
+
+        // syncAllUserOnce(gzhId, groupNum);
+
+        // 同步用户
+        log.info("start sync user gzhId={}", gzhId);
+
+        WxUserGetResponse response = wxUserManagementRemoteService.getAllUserLimit10000(gzhId);
+        if (response == null) {
+            return;
+        }
+
+        int total = response.getTotal();
+        int count = response.getCount();
+        log.info("sync user gzhId={} total={} count={}", gzhId, total, count);
+        List<String> openIds = response.getData() == null
+                ? Collections.emptyList()
+                : response.getData().getOpenid();
+        String nextOpenId = response.getNext_openid();
+        if (CollectionUtils.isNotEmpty(openIds)) {
+            List<ArticleUserGroup> userGroups = CommonCollectionUtils.toList(openIds, s -> {
+                ArticleUserGroup ug = new ArticleUserGroup();
+                ug.setGzhId(gzhId);
+                ug.setOpenId(s);
+                ug.setUserGroupId(RandomUtils.nextInt(groupNum));
+                ug.setIsDelete(0);
+                return ug;
+            });
+
+            //articleUserGroupRepository.saveAll(userGroups);
+            articleUserGroupMapper.insertBatch(userGroups);
+        }
+
+        while (StringUtils.isNotBlank(nextOpenId)) {
+            response = wxUserManagementRemoteService.getAllUserLimit10000(gzhId, nextOpenId);
+            if (response == null) {
+                return;
+            }
+            openIds = response.getData() == null
+                    ? Collections.emptyList()
+                    : response.getData().getOpenid();
+            nextOpenId = response.getNext_openid();
+            count += response.getCount();
+            log.info("sync user gzhId={} total={} count={}", gzhId, total, count);
+            if (CollectionUtils.isNotEmpty(openIds)) {
+                List<ArticleUserGroup> userGroups = CommonCollectionUtils.toList(openIds, s -> {
+                    ArticleUserGroup ug = new ArticleUserGroup();
+                    ug.setGzhId(gzhId);
+                    ug.setOpenId(s);
+                    ug.setUserGroupId(RandomUtils.nextInt(groupNum));
+                    ug.setIsDelete(0);
+                    ug.setUserGroupId(RandomUtils.nextInt(groupNum));
+                    return ug;
+                });
+                articleUserGroupMapper.insertBatch(userGroups);
+                // articleUserGroupRepository.saveAll(userGroups);
+            }
+        }
+
+        log.info("end sync user gzhId={}", gzhId);
+
+        ArticleGzhDeveloper obj = new ArticleGzhDeveloper();
+        obj.setAppId(appId);
+        obj.setGzhId(gzhId);
+        articleGzhDeveloperMapper.insert(obj);
+//        log.info("start group gzhId={}", gzhId);
+
+
+    }
+
+//    private void syncAllUserOnce(String gzhId, int groupNum) {
+//        List<String> openIds = wxUserManagementRemoteService.getAllUser(gzhId);
+//        // 相对均匀
+//        Collections.shuffle(openIds);
+//        int size = openIds.size() / groupNum;
+//        List<List<String>> partition = ListUtils.partition(openIds, size);
+//        for (int i = 0; i < (openIds.size() % groupNum); i++) {
+//            partition.get(i).add(openIds.get(size - i - 1));
+//        }
+//
+//        // 写入DB
+//        int ugId = 0;
+//        for (List<String> partOpenIds : partition) {
+//
+//            int finalUgId = ugId;
+//            List<ArticleUserGroup> userGroups = CommonCollectionUtils.toList(partOpenIds, s -> {
+//                ArticleUserGroup ug = new ArticleUserGroup();
+//                ug.setGzhId(gzhId);
+//                ug.setOpenId(s);
+//                ug.setUserGroupId(finalUgId);
+//                return ug;
+//            });
+//            articleUserGroupRepository.saveAll(userGroups);
+//            ugId++;
+//        }
+//    }
+
+    /**
+     * https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_event_pushes.html
+     *
+     * <xml>
+     * <ToUserName><![CDATA[toUser]]></ToUserName>
+     * <FromUserName><![CDATA[FromUser]]></FromUserName>
+     * <CreateTime>123456789</CreateTime>
+     * <MsgType><![CDATA[event]]></MsgType>
+     * <Event><![CDATA[subscribe]]></Event>
+     * </xml>
+     */
+    public void listenWx(String xmlData) {
+        try {
+            SAXReader saxReader = new SAXReader();
+            Document document = saxReader.read(new StringReader(xmlData));
+            Element root = document.getRootElement();
+            Map<String, String> param = new HashMap<>();
+            for (Element e : root.elements()) {
+                param.put(e.getName(), e.getTextTrim());
+            }
+
+            String appId = param.get("ToUserName");
+            String gzhId = articleGzhDeveloperMapper.selectGzhIdByAppId(appId);
+
+            String openId = param.get("FromUserName");
+            if (StringUtils.equals("event", param.get("MsgType"))) {
+                String event = param.get("Event");
+                switch (event) {
+                    case "subscribe":
+                        handleSubscribe(gzhId, openId);
+                        break;
+                    case "unsubscribe":
+                        handleUnsubscribe(gzhId, openId);
+                        break;
+                    default:
+                        break;
+                }
+            }
+
+        } catch (Exception e) {
+            log.error("listenWx handle error {} ", xmlData, e);
+        }
+    }
+
+    private void handleSubscribe(String gzhId, String openId) {
+
+        ArticleUserGroup group = articleUserGroupMapper.selectByGzhIdAndOpenId(gzhId, openId);
+        if (group == null) {
+            // insert
+            // 查库,知道所有分组
+            List<Integer> ugIds = articleUserGroupMapper.selectUserGroupIdByGzhId(gzhId);
+            // 随机选一个组
+            int ugId = ugIds.get(RandomUtils.nextInt(ugIds.size()));
+            group = new ArticleUserGroup();
+            group.setGzhId(gzhId);
+            group.setOpenId(openId);
+            group.setUserGroupId(ugId);
+            group.setIsDelete(0);
+            articleUserGroupMapper.insert(group);
+        } else {
+            // update
+            group.setIsDelete(0);
+            articleUserGroupMapper.updateByPrimaryKey(group);
+        }
+
+    }
+
+    private void handleUnsubscribe(String gzhId, String openId) {
+        ArticleUserGroup group = articleUserGroupMapper.selectByGzhIdAndOpenId(gzhId, openId);
+        if (group != null) {
+            group.setIsDelete(1);
+            articleUserGroupMapper.updateByPrimaryKey(group);
+        }
+    }
+
+    public List<String> listByUserGroupId(String gzhId, int userGroupId) {
+        return articleUserGroupMapper.selectOpenIdByGzhIdAndUserGroupId(gzhId, userGroupId);
+    }
+}

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

@@ -16,4 +16,5 @@ public class FilterParam {
     private String strategy;
     private String ghId;
     private boolean backup;
+    private String scene;
 }

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

@@ -4,7 +4,7 @@ import com.tzld.longarticle.recommend.server.common.ThreadPoolFactory;
 import com.tzld.longarticle.recommend.server.model.Content;
 import com.tzld.longarticle.recommend.server.service.ServiceBeanFactory;
 import com.tzld.longarticle.recommend.server.service.filter.strategy.BadStrategy;
-import com.tzld.longarticle.recommend.server.service.filter.strategy.ColdStartBackupFilterStrategy;
+import com.tzld.longarticle.recommend.server.service.filter.strategy.HistoryTitleForFwhColdStartStrategy;
 import com.tzld.longarticle.recommend.server.service.filter.strategy.HistoryTitleStrategy;
 import com.tzld.longarticle.recommend.server.service.filter.strategy.SensitiveStrategy;
 import com.tzld.longarticle.recommend.server.util.CommonCollectionUtils;
@@ -23,6 +23,8 @@ import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
+import static com.tzld.longarticle.recommend.server.service.SceneConstants.FWH_COLD_START;
+
 @Slf4j
 @Service
 public class FilterService {
@@ -90,11 +92,17 @@ public class FilterService {
 
     private List<FilterStrategy> getStrategies(FilterParam param) {
         List<FilterStrategy> strategies = new ArrayList<>();
-        strategies.add(ServiceBeanFactory.getBean(HistoryTitleStrategy.class));
-        strategies.add(ServiceBeanFactory.getBean(BadStrategy.class));
-        strategies.add(ServiceBeanFactory.getBean(SensitiveStrategy.class));
-        if (param.isBackup()) {
-            strategies.add(ServiceBeanFactory.getBean(ColdStartBackupFilterStrategy.class));
+        switch (param.getScene()) {
+            case FWH_COLD_START:
+                strategies.add(ServiceBeanFactory.getBean(HistoryTitleForFwhColdStartStrategy.class));
+                strategies.add(ServiceBeanFactory.getBean(BadStrategy.class));
+                strategies.add(ServiceBeanFactory.getBean(SensitiveStrategy.class));
+                break;
+            default:
+                strategies.add(ServiceBeanFactory.getBean(HistoryTitleStrategy.class));
+                strategies.add(ServiceBeanFactory.getBean(BadStrategy.class));
+                strategies.add(ServiceBeanFactory.getBean(SensitiveStrategy.class));
+                break;
         }
         return strategies;
     }

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

@@ -0,0 +1,56 @@
+package com.tzld.longarticle.recommend.server.service.filter.strategy;
+
+import com.tzld.longarticle.recommend.server.model.Content;
+import com.tzld.longarticle.recommend.server.remote.ArticleListRemoteService;
+import com.tzld.longarticle.recommend.server.repository.entity.crawler.Article;
+import com.tzld.longarticle.recommend.server.service.filter.FilterParam;
+import com.tzld.longarticle.recommend.server.service.filter.FilterResult;
+import com.tzld.longarticle.recommend.server.service.filter.FilterStrategy;
+import com.tzld.longarticle.recommend.server.util.TitleSimilarCheckUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author dyp
+ */
+@Component
+@Slf4j
+public class HistoryTitleForFwhColdStartStrategy implements FilterStrategy {
+
+    @Autowired
+    private ArticleListRemoteService articleListRemoteService;
+
+    private static final List<Integer> allIndex = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);
+
+
+    @Override
+    public FilterResult filter(FilterParam param) {
+        long start = System.currentTimeMillis();
+        FilterResult filterResult = new FilterResult();
+        List<String> result = new ArrayList<>();
+        List<Content> filterContents = new ArrayList<>();
+        List<Article> allArticleList = articleListRemoteService.articleList(param.getAccountName(), allIndex);
+        List<String> allTitleList = allArticleList.stream().map(Article::getTitle).distinct().collect(Collectors.toList());
+
+        for (Content content : param.getContents()) {
+            boolean isDuplicate = TitleSimilarCheckUtil.isDuplicateContent(content.getTitle(), allTitleList);
+            if (!isDuplicate) {
+                result.add(content.getId());
+            } else {
+                content.setFilterReason("历史已发布文章");
+                filterContents.add(content);
+            }
+        }
+        filterResult.setContentIds(result);
+        filterResult.setFilterContent(filterContents);
+        log.info("HistoryTitleStrategy cost:{}", System.currentTimeMillis() - start);
+        return filterResult;
+    }
+
+}

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

@@ -16,4 +16,7 @@ public class RankParam {
     private List<Content> backup;
     private int size;
     private String strategy;
+    private String scene;
+    private List<Integer> userGroupIds;
+
 }

+ 16 - 2
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/rank/RankService.java

@@ -3,9 +3,16 @@ package com.tzld.longarticle.recommend.server.service.rank;
 
 import com.tzld.longarticle.recommend.server.common.enums.RankStrategyEnum;
 import com.tzld.longarticle.recommend.server.service.ServiceBeanFactory;
+import com.tzld.longarticle.recommend.server.service.filter.strategy.BadStrategy;
+import com.tzld.longarticle.recommend.server.service.filter.strategy.HistoryTitleForFwhColdStartStrategy;
+import com.tzld.longarticle.recommend.server.service.filter.strategy.HistoryTitleStrategy;
+import com.tzld.longarticle.recommend.server.service.filter.strategy.SensitiveStrategy;
+import com.tzld.longarticle.recommend.server.service.rank.strategy.FwhColdStartRankStrategy;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 
+import static com.tzld.longarticle.recommend.server.service.SceneConstants.FWH_COLD_START;
+
 /**
  * @author dyp
  */
@@ -19,8 +26,15 @@ public class RankService {
     }
 
     private RankStrategy getRankStrategy(RankParam param) {
-        RankStrategyEnum rankStrategyEnum = RankStrategyEnum.from(param.getStrategy());
-        return (RankStrategy) ServiceBeanFactory.getBeanByName(rankStrategyEnum.getTaskExecutorName());
+
+        switch (param.getScene()) {
+            case FWH_COLD_START:
+                return ServiceBeanFactory.getBean(FwhColdStartRankStrategy.class);
+            default:
+                RankStrategyEnum rankStrategyEnum = RankStrategyEnum.from(param.getStrategy());
+                return (RankStrategy) ServiceBeanFactory.getBeanByName(rankStrategyEnum.getTaskExecutorName());
+        }
+
     }
 
 }

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

@@ -0,0 +1,109 @@
+package com.tzld.longarticle.recommend.server.service.rank.strategy;
+
+
+import com.tzld.longarticle.recommend.server.common.enums.ContentPoolEnum;
+import com.tzld.longarticle.recommend.server.model.Content;
+import com.tzld.longarticle.recommend.server.service.AccountContentPoolConfigService;
+import com.tzld.longarticle.recommend.server.service.rank.RankItem;
+import com.tzld.longarticle.recommend.server.service.rank.RankParam;
+import com.tzld.longarticle.recommend.server.service.rank.RankResult;
+import com.tzld.longarticle.recommend.server.service.rank.RankStrategy;
+import com.tzld.longarticle.recommend.server.service.score.ScoreParam;
+import com.tzld.longarticle.recommend.server.service.score.ScoreResult;
+import com.tzld.longarticle.recommend.server.service.score.ScoreService;
+import com.tzld.longarticle.recommend.server.service.score.strategy.*;
+import com.tzld.longarticle.recommend.server.util.CommonCollectionUtils;
+import com.tzld.longarticle.recommend.server.util.JSONUtils;
+import com.tzld.longarticle.recommend.server.util.TitleSimilarCheckUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+
+/**
+ * @author dyp
+ */
+@Service
+@Slf4j
+public class FwhColdStartRankStrategy implements RankStrategy {
+
+    @Autowired
+    private ScoreService scoreService;
+    @Autowired
+    private AccountContentPoolConfigService accountContentPoolConfigService;
+
+    public RankResult rank(RankParam param) {
+
+        ScoreResult scoreResult = scoreService.score(convertToScoreParam(param));
+
+        Map<String, Map<String, Double>> scoreMap = scoreResult.getScoreMap();
+        String[] contentPools = accountContentPoolConfigService.getContentPools(param.getAccountName());
+
+        List<RankItem> items = CommonCollectionUtils.toList(param.getContents(), c -> {
+            RankItem item = new RankItem();
+            item.setContent(c);
+            item.setScoreMap(scoreMap.get(c.getId()));
+            double score;
+            if (contentPools[0].equals(item.getContent().getContentPoolType())
+                    || contentPools[1].equals(item.getContent().getContentPoolType())) {
+                score = item.getScore(SimilarityStrategy.class.getSimpleName())
+                        + item.getScore(CategoryStrategy.class.getSimpleName())
+                        + item.getScore(FlowCtlDecreaseStrategy.class.getSimpleName());
+                if (item.getScore(PublishTimesStrategy.class.getSimpleName()) >= 0) {
+                    score += item.getScore(ViewCountRateStrategy.class.getSimpleName());
+                }
+            } else {
+                score = item.getScore(SimilarityStrategy.class.getSimpleName())
+                        + item.getScore(CategoryStrategy.class.getSimpleName())
+                        + item.getScore(AccountPreDistributeStrategy.class.getSimpleName())
+                        + item.getScore(PublishTimesStrategy.class.getSimpleName())
+                        + item.getScore(FlowCtlDecreaseStrategy.class.getSimpleName());
+            }
+            item.setScore(score);
+            return item;
+        });
+
+        // 1 排序
+        Collections.sort(items, (o1, o2) -> -Double.compare(o1.getScore(), o2.getScore()));
+        // 2 相似去重
+        List<Content> contents = CommonCollectionUtils.toList(items, RankItem::getContent);
+        contents = deduplication(contents);
+
+        // 3 选文章
+        List<Content> result = new ArrayList<>();
+        int size = param.getSize() * param.getUserGroupIds().size();
+        result.addAll(contents.subList(0, Math.min(contents.size(), size)));
+
+        return new RankResult(result);
+    }
+
+    private ScoreParam convertToScoreParam(RankParam param) {
+        ScoreParam scoreParam = new ScoreParam();
+        scoreParam.setGhId(param.getGhId());
+        scoreParam.setAccountName(param.getAccountName());
+        scoreParam.setContents(param.getContents());
+        scoreParam.setStrategy(param.getStrategy());
+        return scoreParam;
+    }
+
+    private List<Content> deduplication(List<Content> contents) {
+        List<String> titles = new ArrayList<>();
+        List<Content> result = new ArrayList<>();
+        // 遍历所有列表
+        for (String contentPool : ContentPoolEnum.getOrderContentPool()) {
+            for (Content c : contents) {
+                if (!contentPool.equals(c.getContentPoolType())) {
+                    continue;
+                }
+                if (!TitleSimilarCheckUtil.isDuplicateContent(c.getTitle(), titles)) {
+                    result.add(c);
+                    titles.add(c.getTitle());
+                }
+            }
+        }
+
+        return result;
+    }
+
+}

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

@@ -38,9 +38,8 @@ public class RankV5Strategy implements RankStrategy {
 
     public RankResult rank(RankParam param) {
 
-        log.info("RankParam {}", JSONUtils.toJson(param));
+        //log.info("RankParam {}", JSONUtils.toJson(param));
         ScoreResult scoreResult = scoreService.score(convertToScoreParam(param));
-        log.info("ScoreResult {}", JSONUtils.toJson(scoreResult));
 
         Map<String, Map<String, Double>> scoreMap = scoreResult.getScoreMap();
         String[] contentPools = accountContentPoolConfigService.getContentPools(param.getAccountName());
@@ -72,11 +71,9 @@ public class RankV5Strategy implements RankStrategy {
 
         // 1 排序
         Collections.sort(items, (o1, o2) -> -Double.compare(o1.getScore(), o2.getScore()));
-        log.info("SortResult {}", JSONUtils.toJson(items));
         // 2 相似去重
         List<Content> contents = CommonCollectionUtils.toList(items, RankItem::getContent);
         contents = deduplication(contents);
-        log.info("Deduplication {}", JSONUtils.toJson(contents));
 
         // 3 文章按照内容池分组
         Map<String, List<Content>> contentMap = new HashMap<>();
@@ -84,7 +81,6 @@ public class RankV5Strategy implements RankStrategy {
             List<Content> data = contentMap.computeIfAbsent(c.getContentPoolType(), k -> new ArrayList<>());
             data.add(c);
         }
-        log.info("ContentMap {}", JSONUtils.toJson(contentMap));
         // 4 选文章
         List<Content> result = new ArrayList<>();
 
@@ -144,6 +140,7 @@ public class RankV5Strategy implements RankStrategy {
         scoreParam.setAccountName(param.getAccountName());
         scoreParam.setContents(param.getContents());
         scoreParam.setStrategy(param.getStrategy());
+        scoreParam.setScene(param.getScene());
         return scoreParam;
     }
 

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

@@ -16,6 +16,7 @@ public class FilterParamFactory {
         filterParam.setAccountId(param.getAccountId());
         filterParam.setStrategy(param.getStrategy());
         filterParam.setGhId(param.getGhId());
+        filterParam.setScene(param.getScene());
         return filterParam;
     }
 }

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

@@ -17,4 +17,6 @@ public class RecallParam {
     private String strategy;
     private String ghId;
     private List<Content> content;
+    // 实现配置化之前,连接各个过程
+    private String scene;
 }

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

@@ -103,7 +103,6 @@ public class RecallService implements ApplicationContextAware {
     private List<RecallStrategy> getRecallStrategy(RecallParam param) {
         List<RecallStrategy> strategies = new ArrayList<>();
         strategies.add(strategyMap.get(DefaultRecallStrategy.class.getSimpleName()));
-//        strategies.add(strategyMap.get(ColdStartBackupRecallStrategy.class.getSimpleName()));
         return strategies;
     }
 

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

@@ -20,4 +20,5 @@ public class ScoreParam {
     private String accountName;
     private List<Content> contents;
     private String strategy;
+    private String scene;
 }

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

@@ -44,7 +44,6 @@ public class ScoreService implements ApplicationContextAware {
     }
 
     public ScoreResult score(ScoreParam param) {
-        log.info("ScoreParam {}", JSONUtils.toJson(param));
         List<ScoreStrategy> strategies = getScoreStrategy(param);
         log.info("ScoreStrategy {}", JSONUtils.toJson(CommonCollectionUtils.toList(strategies,
                 s -> s.getClass().getSimpleName())));

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

@@ -2,6 +2,7 @@ package com.tzld.longarticle.recommend.server.web;
 
 import com.tzld.longarticle.recommend.server.model.RecommendRequest;
 import com.tzld.longarticle.recommend.server.model.RecommendResponse;
+import com.tzld.longarticle.recommend.server.model.RecommendWithUserGroupResponse;
 import com.tzld.longarticle.recommend.server.service.RecommendService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -19,9 +20,15 @@ public class RecommendController {
     private RecommendService recommendService;
 
     @RequestMapping("/recommend")
-    public RecommendResponse homepageRecommend(@RequestBody RecommendRequest httpRequest) {
+    public RecommendResponse recommend(@RequestBody RecommendRequest httpRequest) {
 
         return recommendService.recommend(httpRequest);
     }
 
+    @RequestMapping("/recommend4FwhColdStart")
+    public RecommendWithUserGroupResponse recommend4FwhColdStart(@RequestBody RecommendRequest httpRequest) {
+
+        return recommendService.recommend4FwhColdStart(httpRequest);
+    }
+
 }

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

@@ -0,0 +1,50 @@
+package com.tzld.longarticle.recommend.server.web;
+
+import com.tzld.longarticle.recommend.server.model.Result;
+import com.tzld.longarticle.recommend.server.service.UserManagementService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * @author dyp
+ */
+@RestController
+@Slf4j
+@RequestMapping("/user")
+public class UserManagementController {
+    @Autowired
+    private UserManagementService userManagementService;
+
+
+    @RequestMapping("/addGZH")
+    public String addGZH(@RequestParam(name = "gzhId") String gzhId,
+                         @RequestParam(name = "appId") String appId,
+                         @RequestParam(name = "groupNum") int groupNum) {
+        userManagementService.addGZH(gzhId,appId, groupNum);
+        return "success";
+    }
+
+    @RequestMapping("/listByUserGroupId")
+    public String list(@RequestParam(name = "gzhId") String gzhId,
+                       @RequestParam(name = "userGroupId") int userGroupId) {
+        List<String> openIds = userManagementService.listByUserGroupId(gzhId, userGroupId);
+
+        return Result.success(openIds);
+    }
+
+    /**
+     * 微信关注/取消事件监听
+     */
+    @RequestMapping("/listenWx")
+    public String listenWx(@RequestBody String xmlData) {
+        userManagementService.listenWx(xmlData);
+        return "success";
+    }
+
+}

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

@@ -51,6 +51,8 @@ spring:
     crawler:
       hibernate:
         ddl-auto: validate
+        jdbc:
+          batch_size: 2000
       database: mysql
     adplatform:
       hibernate:

+ 4 - 1
long-article-recommend-service/src/main/resources/application.yml

@@ -51,4 +51,7 @@ apollo:
   bootstrap:
     enabled: true
     namespaces: application
-  cacheDir: /datalog/apollo-cache-dir
+  cacheDir: /datalog/apollo-cache-dir
+
+mybatis:
+  mapper-locations: classpath:/mapper/*.xml

+ 41 - 0
long-article-recommend-service/src/main/resources/generatorConfig.xml

@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE generatorConfiguration
+        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
+        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
+
+<generatorConfiguration>
+    <context id="simple" targetRuntime="MyBatis3">
+        <commentGenerator>
+            <property name="suppressAllComments" value="true"/>
+        </commentGenerator>
+        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
+                        connectionURL="jdbc:mysql://rm-bp1159bu17li9hi94.mysql.rds.aliyuncs.com:3306/piaoquan-crawler?useUnicode=true&amp;characterEncoding=utf-8&amp;zeroDateTimeBehavior=convertToNull&amp;useSSL=false"
+                        userId="crawler"
+                        password="crawler123456@">
+        </jdbcConnection>
+
+        <javaTypeResolver >
+            <property name="forceBigDecimals" value="false" />
+        </javaTypeResolver>
+
+        <javaModelGenerator targetPackage="com.tzld.longarticle.recommend.server.repository.model" targetProject="/Users/dingyunpeng/Desktop/code/changwen/long-article-recommend/long-article-recommend-service/src/main/java">
+            <property name="enableSubPackages" value="true" />
+            <property name="trimStrings" value="true" />
+        </javaModelGenerator>
+
+        <sqlMapGenerator targetPackage="crawler"  targetProject="/Users/dingyunpeng/Desktop/code/changwen/long-article-recommend/long-article-recommend-service/src/main/resources/mapper">
+            <property name="enableSubPackages" value="true" />
+        </sqlMapGenerator>
+
+        <javaClientGenerator type="XMLMAPPER"
+                             targetPackage="com.tzld.longarticle.recommend.server.repository.mapper.crawler"
+                             targetProject="/Users/dingyunpeng/Desktop/code/changwen/long-article-recommend/long-article-recommend-service/src/main/java">
+            <property name="enableSubPackages" value="true" />
+        </javaClientGenerator>
+
+        <table schema="mybatis" tableName="article_gzh_developer" >
+            <generatedKey column="id" sqlStatement="mysql" identity="true" />
+        </table>
+
+    </context>
+</generatorConfiguration>

+ 171 - 0
long-article-recommend-service/src/main/resources/mapper/crawler/ArticleGzhDeveloperMapper.xml

@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.tzld.longarticle.recommend.server.repository.mapper.crawler.ArticleGzhDeveloperMapper">
+  <resultMap id="BaseResultMap" type="com.tzld.longarticle.recommend.server.repository.model.ArticleGzhDeveloper">
+    <id column="gzh_id" jdbcType="VARCHAR" property="gzhId" />
+    <result column="app_id" jdbcType="VARCHAR" property="appId" />
+  </resultMap>
+  <sql id="Example_Where_Clause">
+    <where>
+      <foreach collection="oredCriteria" item="criteria" separator="or">
+        <if test="criteria.valid">
+          <trim prefix="(" prefixOverrides="and" suffix=")">
+            <foreach collection="criteria.criteria" item="criterion">
+              <choose>
+                <when test="criterion.noValue">
+                  and ${criterion.condition}
+                </when>
+                <when test="criterion.singleValue">
+                  and ${criterion.condition} #{criterion.value}
+                </when>
+                <when test="criterion.betweenValue">
+                  and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
+                </when>
+                <when test="criterion.listValue">
+                  and ${criterion.condition}
+                  <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
+                    #{listItem}
+                  </foreach>
+                </when>
+              </choose>
+            </foreach>
+          </trim>
+        </if>
+      </foreach>
+    </where>
+  </sql>
+  <sql id="Update_By_Example_Where_Clause">
+    <where>
+      <foreach collection="example.oredCriteria" item="criteria" separator="or">
+        <if test="criteria.valid">
+          <trim prefix="(" prefixOverrides="and" suffix=")">
+            <foreach collection="criteria.criteria" item="criterion">
+              <choose>
+                <when test="criterion.noValue">
+                  and ${criterion.condition}
+                </when>
+                <when test="criterion.singleValue">
+                  and ${criterion.condition} #{criterion.value}
+                </when>
+                <when test="criterion.betweenValue">
+                  and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
+                </when>
+                <when test="criterion.listValue">
+                  and ${criterion.condition}
+                  <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
+                    #{listItem}
+                  </foreach>
+                </when>
+              </choose>
+            </foreach>
+          </trim>
+        </if>
+      </foreach>
+    </where>
+  </sql>
+  <sql id="Base_Column_List">
+    gzh_id, app_id
+  </sql>
+  <select id="selectByExample" parameterType="com.tzld.longarticle.recommend.server.repository.model.ArticleGzhDeveloperExample" resultMap="BaseResultMap">
+    select
+    <if test="distinct">
+      distinct
+    </if>
+    <include refid="Base_Column_List" />
+    from article_gzh_developer
+    <if test="_parameter != null">
+      <include refid="Example_Where_Clause" />
+    </if>
+    <if test="orderByClause != null">
+      order by ${orderByClause}
+    </if>
+  </select>
+  <select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="BaseResultMap">
+    select 
+    <include refid="Base_Column_List" />
+    from article_gzh_developer
+    where gzh_id = #{gzhId,jdbcType=VARCHAR}
+  </select>
+  <delete id="deleteByPrimaryKey" parameterType="java.lang.String">
+    delete from article_gzh_developer
+    where gzh_id = #{gzhId,jdbcType=VARCHAR}
+  </delete>
+  <delete id="deleteByExample" parameterType="com.tzld.longarticle.recommend.server.repository.model.ArticleGzhDeveloperExample">
+    delete from article_gzh_developer
+    <if test="_parameter != null">
+      <include refid="Example_Where_Clause" />
+    </if>
+  </delete>
+  <insert id="insert" parameterType="com.tzld.longarticle.recommend.server.repository.model.ArticleGzhDeveloper">
+    insert into article_gzh_developer (gzh_id, app_id)
+    values (#{gzhId,jdbcType=VARCHAR}, #{appId,jdbcType=VARCHAR})
+  </insert>
+  <insert id="insertSelective" parameterType="com.tzld.longarticle.recommend.server.repository.model.ArticleGzhDeveloper">
+    insert into article_gzh_developer
+    <trim prefix="(" suffix=")" suffixOverrides=",">
+      <if test="gzhId != null">
+        gzh_id,
+      </if>
+      <if test="appId != null">
+        app_id,
+      </if>
+    </trim>
+    <trim prefix="values (" suffix=")" suffixOverrides=",">
+      <if test="gzhId != null">
+        #{gzhId,jdbcType=VARCHAR},
+      </if>
+      <if test="appId != null">
+        #{appId,jdbcType=VARCHAR},
+      </if>
+    </trim>
+  </insert>
+  <select id="countByExample" parameterType="com.tzld.longarticle.recommend.server.repository.model.ArticleGzhDeveloperExample" resultType="java.lang.Long">
+    select count(*) from article_gzh_developer
+    <if test="_parameter != null">
+      <include refid="Example_Where_Clause" />
+    </if>
+  </select>
+  <update id="updateByExampleSelective" parameterType="map">
+    update article_gzh_developer
+    <set>
+      <if test="row.gzhId != null">
+        gzh_id = #{row.gzhId,jdbcType=VARCHAR},
+      </if>
+      <if test="row.appId != null">
+        app_id = #{row.appId,jdbcType=VARCHAR},
+      </if>
+    </set>
+    <if test="example != null">
+      <include refid="Update_By_Example_Where_Clause" />
+    </if>
+  </update>
+  <update id="updateByExample" parameterType="map">
+    update article_gzh_developer
+    set gzh_id = #{row.gzhId,jdbcType=VARCHAR},
+      app_id = #{row.appId,jdbcType=VARCHAR}
+    <if test="example != null">
+      <include refid="Update_By_Example_Where_Clause" />
+    </if>
+  </update>
+  <update id="updateByPrimaryKeySelective" parameterType="com.tzld.longarticle.recommend.server.repository.model.ArticleGzhDeveloper">
+    update article_gzh_developer
+    <set>
+      <if test="appId != null">
+        app_id = #{appId,jdbcType=VARCHAR},
+      </if>
+    </set>
+    where gzh_id = #{gzhId,jdbcType=VARCHAR}
+  </update>
+  <update id="updateByPrimaryKey" parameterType="com.tzld.longarticle.recommend.server.repository.model.ArticleGzhDeveloper">
+    update article_gzh_developer
+    set app_id = #{appId,jdbcType=VARCHAR}
+    where gzh_id = #{gzhId,jdbcType=VARCHAR}
+  </update>
+
+  <select id="selectGzhIdByAppId" resultType="string">
+    select
+      distinct gzh_id
+    from article_gzh_developer
+    where app_id = #{appId}
+  </select>
+</mapper>

+ 319 - 0
long-article-recommend-service/src/main/resources/mapper/crawler/ArticleUserGroupMapper.xml

@@ -0,0 +1,319 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.tzld.longarticle.recommend.server.repository.mapper.crawler.ArticleUserGroupMapper">
+  <resultMap id="BaseResultMap" type="com.tzld.longarticle.recommend.server.repository.model.ArticleUserGroup">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+      This element was generated on Thu Aug 22 20:53:08 CST 2024.
+    -->
+    <id column="id" jdbcType="BIGINT" property="id" />
+    <result column="gzh_id" jdbcType="VARCHAR" property="gzhId" />
+    <result column="user_group_id" jdbcType="INTEGER" property="userGroupId" />
+    <result column="open_id" jdbcType="VARCHAR" property="openId" />
+    <result column="is_delete" jdbcType="INTEGER" property="isDelete" />
+  </resultMap>
+
+  <sql id="Example_Where_Clause">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+      This element was generated on Thu Aug 22 20:53:08 CST 2024.
+    -->
+    <where>
+      <foreach collection="oredCriteria" item="criteria" separator="or">
+        <if test="criteria.valid">
+          <trim prefix="(" prefixOverrides="and" suffix=")">
+            <foreach collection="criteria.criteria" item="criterion">
+              <choose>
+                <when test="criterion.noValue">
+                  and ${criterion.condition}
+                </when>
+                <when test="criterion.singleValue">
+                  and ${criterion.condition} #{criterion.value}
+                </when>
+                <when test="criterion.betweenValue">
+                  and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
+                </when>
+                <when test="criterion.listValue">
+                  and ${criterion.condition}
+                  <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
+                    #{listItem}
+                  </foreach>
+                </when>
+              </choose>
+            </foreach>
+          </trim>
+        </if>
+      </foreach>
+    </where>
+  </sql>
+  <sql id="Update_By_Example_Where_Clause">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+      This element was generated on Thu Aug 22 20:53:08 CST 2024.
+    -->
+    <where>
+      <foreach collection="example.oredCriteria" item="criteria" separator="or">
+        <if test="criteria.valid">
+          <trim prefix="(" prefixOverrides="and" suffix=")">
+            <foreach collection="criteria.criteria" item="criterion">
+              <choose>
+                <when test="criterion.noValue">
+                  and ${criterion.condition}
+                </when>
+                <when test="criterion.singleValue">
+                  and ${criterion.condition} #{criterion.value}
+                </when>
+                <when test="criterion.betweenValue">
+                  and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
+                </when>
+                <when test="criterion.listValue">
+                  and ${criterion.condition}
+                  <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
+                    #{listItem}
+                  </foreach>
+                </when>
+              </choose>
+            </foreach>
+          </trim>
+        </if>
+      </foreach>
+    </where>
+  </sql>
+  <sql id="Base_Column_List">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+      This element was generated on Thu Aug 22 20:53:08 CST 2024.
+    -->
+    id, gzh_id, user_group_id, open_id, is_delete
+  </sql>
+  <select id="selectByExample" parameterType="com.tzld.longarticle.recommend.server.repository.model.ArticleUserGroupExample" resultMap="BaseResultMap">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+      This element was generated on Thu Aug 22 20:53:08 CST 2024.
+    -->
+    select
+    <if test="distinct">
+      distinct
+    </if>
+    <include refid="Base_Column_List" />
+    from article_user_group
+    <if test="_parameter != null">
+      <include refid="Example_Where_Clause" />
+    </if>
+    <if test="orderByClause != null">
+      order by ${orderByClause}
+    </if>
+  </select>
+  <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+      This element was generated on Thu Aug 22 20:53:08 CST 2024.
+    -->
+    select 
+    <include refid="Base_Column_List" />
+    from article_user_group
+    where id = #{id,jdbcType=BIGINT}
+  </select>
+  <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+      This element was generated on Thu Aug 22 20:53:08 CST 2024.
+    -->
+    delete from article_user_group
+    where id = #{id,jdbcType=BIGINT}
+  </delete>
+  <delete id="deleteByExample" parameterType="com.tzld.longarticle.recommend.server.repository.model.ArticleUserGroupExample">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+      This element was generated on Thu Aug 22 20:53:08 CST 2024.
+    -->
+    delete from article_user_group
+    <if test="_parameter != null">
+      <include refid="Example_Where_Clause" />
+    </if>
+  </delete>
+  <insert id="insert" parameterType="com.tzld.longarticle.recommend.server.repository.model.ArticleUserGroup">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+      This element was generated on Thu Aug 22 20:53:08 CST 2024.
+    -->
+    <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Long">
+      SELECT LAST_INSERT_ID()
+    </selectKey>
+    insert into article_user_group (gzh_id, user_group_id, open_id, 
+      is_delete)
+    values (#{gzhId,jdbcType=VARCHAR}, #{userGroupId,jdbcType=INTEGER}, #{openId,jdbcType=VARCHAR}, 
+      #{isDelete,jdbcType=INTEGER})
+  </insert>
+  <insert id="insertSelective" parameterType="com.tzld.longarticle.recommend.server.repository.model.ArticleUserGroup">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+      This element was generated on Thu Aug 22 20:53:08 CST 2024.
+    -->
+    <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Long">
+      SELECT LAST_INSERT_ID()
+    </selectKey>
+    insert into article_user_group
+    <trim prefix="(" suffix=")" suffixOverrides=",">
+      <if test="gzhId != null">
+        gzh_id,
+      </if>
+      <if test="userGroupId != null">
+        user_group_id,
+      </if>
+      <if test="openId != null">
+        open_id,
+      </if>
+      <if test="isDelete != null">
+        is_delete,
+      </if>
+    </trim>
+    <trim prefix="values (" suffix=")" suffixOverrides=",">
+      <if test="gzhId != null">
+        #{gzhId,jdbcType=VARCHAR},
+      </if>
+      <if test="userGroupId != null">
+        #{userGroupId,jdbcType=INTEGER},
+      </if>
+      <if test="openId != null">
+        #{openId,jdbcType=VARCHAR},
+      </if>
+      <if test="isDelete != null">
+        #{isDelete,jdbcType=INTEGER},
+      </if>
+    </trim>
+  </insert>
+  <select id="countByExample" parameterType="com.tzld.longarticle.recommend.server.repository.model.ArticleUserGroupExample" resultType="java.lang.Long">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+      This element was generated on Thu Aug 22 20:53:08 CST 2024.
+    -->
+    select count(*) from article_user_group
+    <if test="_parameter != null">
+      <include refid="Example_Where_Clause" />
+    </if>
+  </select>
+  <update id="updateByExampleSelective" parameterType="map">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+      This element was generated on Thu Aug 22 20:53:08 CST 2024.
+    -->
+    update article_user_group
+    <set>
+      <if test="row.id != null">
+        id = #{row.id,jdbcType=BIGINT},
+      </if>
+      <if test="row.gzhId != null">
+        gzh_id = #{row.gzhId,jdbcType=VARCHAR},
+      </if>
+      <if test="row.userGroupId != null">
+        user_group_id = #{row.userGroupId,jdbcType=INTEGER},
+      </if>
+      <if test="row.openId != null">
+        open_id = #{row.openId,jdbcType=VARCHAR},
+      </if>
+      <if test="row.isDelete != null">
+        is_delete = #{row.isDelete,jdbcType=INTEGER},
+      </if>
+    </set>
+    <if test="example != null">
+      <include refid="Update_By_Example_Where_Clause" />
+    </if>
+  </update>
+  <update id="updateByExample" parameterType="map">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+      This element was generated on Thu Aug 22 20:53:08 CST 2024.
+    -->
+    update article_user_group
+    set id = #{row.id,jdbcType=BIGINT},
+      gzh_id = #{row.gzhId,jdbcType=VARCHAR},
+      user_group_id = #{row.userGroupId,jdbcType=INTEGER},
+      open_id = #{row.openId,jdbcType=VARCHAR},
+      is_delete = #{row.isDelete,jdbcType=INTEGER}
+    <if test="example != null">
+      <include refid="Update_By_Example_Where_Clause" />
+    </if>
+  </update>
+  <update id="updateByPrimaryKeySelective" parameterType="com.tzld.longarticle.recommend.server.repository.model.ArticleUserGroup">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+      This element was generated on Thu Aug 22 20:53:08 CST 2024.
+    -->
+    update article_user_group
+    <set>
+      <if test="gzhId != null">
+        gzh_id = #{gzhId,jdbcType=VARCHAR},
+      </if>
+      <if test="userGroupId != null">
+        user_group_id = #{userGroupId,jdbcType=INTEGER},
+      </if>
+      <if test="openId != null">
+        open_id = #{openId,jdbcType=VARCHAR},
+      </if>
+      <if test="isDelete != null">
+        is_delete = #{isDelete,jdbcType=INTEGER},
+      </if>
+    </set>
+    where id = #{id,jdbcType=BIGINT}
+  </update>
+  <update id="updateByPrimaryKey" parameterType="com.tzld.longarticle.recommend.server.repository.model.ArticleUserGroup">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+      This element was generated on Thu Aug 22 20:53:08 CST 2024.
+    -->
+    update article_user_group
+    set gzh_id = #{gzhId,jdbcType=VARCHAR},
+      user_group_id = #{userGroupId,jdbcType=INTEGER},
+      open_id = #{openId,jdbcType=VARCHAR},
+      is_delete = #{isDelete,jdbcType=INTEGER}
+    where id = #{id,jdbcType=BIGINT}
+  </update>
+
+  <insert id="insertBatch" parameterType="list">
+    INSERT INTO article_user_group (gzh_id, user_group_id, open_id, is_delete)
+    VALUES
+    <foreach collection="list" item="item" separator=",">
+      (#{item.gzhId}, #{item.userGroupId}, #{item.openId}, #{item.isDelete})
+    </foreach>
+  </insert>
+
+  <select id="selectByGzhIdAndOpenId" resultMap="BaseResultMap">
+    select
+    <include refid="Base_Column_List" />
+    from article_user_group
+    where gzh_id = #{gzhId}
+    and open_id = #{openId}
+  </select>
+
+  <select id="selectUserGroupIdByGzhId" parameterType="java.lang.String" resultType="integer">
+    select
+    distinct user_group_id
+    from article_user_group
+    where gzh_id = #{gzhId}
+  </select>
+
+  <select id="selectOpenIdByGzhIdAndUserGroupId" resultType="string">
+    select
+      distinct open_id
+    from article_user_group
+    where gzh_id = #{gzhId}
+    and user_group_id = #{userGroupId}
+    and is_delete = 0
+  </select>
+</mapper>

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

@@ -3,5 +3,4 @@
 <mapper namespace="com.tzld.longarticle.recommend.server.repository.mapper.crawler.CrawlerBaseMapper">
 
 
-
 </mapper>