ソースを参照

Merge branch '20250522-wyp-qwPlanSubChannel' into test

wangyunpeng 1 ヶ月 前
コミット
074bf72a35
27 ファイル変更1792 行追加308 行削除
  1. 1 0
      api-module/src/main/java/com/tzld/piaoquan/api/common/enums/ExceptionEnum.java
  2. 12 0
      api-module/src/main/java/com/tzld/piaoquan/api/controller/contentplatform/ContentPlatformCooperateAccountController.java
  3. 8 0
      api-module/src/main/java/com/tzld/piaoquan/api/controller/contentplatform/ContentPlatformDatastatController.java
  4. 30 0
      api-module/src/main/java/com/tzld/piaoquan/api/dao/mapper/contentplatform/ContentPlatformQwDataStatSubChannelMapper.java
  5. 11 0
      api-module/src/main/java/com/tzld/piaoquan/api/dao/mapper/contentplatform/ext/ContentPlatformDataStatMapperExt.java
  6. 173 56
      api-module/src/main/java/com/tzld/piaoquan/api/job/ContentPlatformDatastatJob.java
  7. 63 0
      api-module/src/main/java/com/tzld/piaoquan/api/job/ContentPlatformGzhAccountJob.java
  8. 1 1
      api-module/src/main/java/com/tzld/piaoquan/api/model/param/contentplatform/QwDatastatListParam.java
  9. 3 0
      api-module/src/main/java/com/tzld/piaoquan/api/model/param/contentplatform/QwPlanListParam.java
  10. 3 0
      api-module/src/main/java/com/tzld/piaoquan/api/model/param/contentplatform/QwPlanSaveParam.java
  11. 90 0
      api-module/src/main/java/com/tzld/piaoquan/api/model/po/contentplatform/ContentPlatformQwDataStatSubChannel.java
  12. 651 0
      api-module/src/main/java/com/tzld/piaoquan/api/model/po/contentplatform/ContentPlatformQwDataStatSubChannelExample.java
  13. 11 0
      api-module/src/main/java/com/tzld/piaoquan/api/model/po/contentplatform/ContentPlatformQwPlan.java
  14. 70 0
      api-module/src/main/java/com/tzld/piaoquan/api/model/po/contentplatform/ContentPlatformQwPlanExample.java
  15. 3 0
      api-module/src/main/java/com/tzld/piaoquan/api/model/vo/contentplatform/QwDatastatItemVO.java
  16. 3 0
      api-module/src/main/java/com/tzld/piaoquan/api/model/vo/contentplatform/QwPlanItemVO.java
  17. 30 0
      api-module/src/main/java/com/tzld/piaoquan/api/model/vo/contentplatform/QwSubChannelDatastatItemExportVO.java
  18. 43 0
      api-module/src/main/java/com/tzld/piaoquan/api/service/contentplatform/impl/ContentPlatformDatastatServiceImpl.java
  19. 7 1
      api-module/src/main/java/com/tzld/piaoquan/api/service/contentplatform/impl/ContentPlatformPlanServiceImpl.java
  20. 246 0
      api-module/src/main/resources/mapper/contentplatform/ContentPlatformQwDataStatSubChannelMapper.xml
  21. 25 10
      api-module/src/main/resources/mapper/contentplatform/ContentPlatformQwPlanMapper.xml
  22. 29 0
      api-module/src/main/resources/mapper/contentplatform/ext/ContentPlatformDataStatMapperExt.xml
  23. 8 2
      api-module/src/main/resources/mapper/contentplatform/ext/ContentPlatformPlanMapperExt.xml
  24. 1 0
      api-module/src/main/resources/mybatis-api-contentPlatform-generator-config.xml
  25. 3 0
      common-module/src/main/java/com/tzld/piaoquan/growth/common/dao/mapper/UserWithTagMapper.java
  26. 251 234
      common-module/src/main/resources/mapper/UserWithTagMapper.xml
  27. 16 4
      offline-module/src/main/java/com/tzld/piaoquan/offline/job/WeComSpecialDataJob.java

+ 1 - 0
api-module/src/main/java/com/tzld/piaoquan/api/common/enums/ExceptionEnum.java

@@ -38,6 +38,7 @@ public enum ExceptionEnum {
     QW_PLAN_NOT_EXISTS(3003, "企微计划不存在"),
     GZH_ACCOUNT_NOT_EXISTS(3004, "公众号不存在"),
     GZH_ACCOUNT_NOT_AUTH(3005, "公众号未授权,无法使用平台发布"),
+    QW_PLAN_SUB_CHANNEL_LENGTH(3006, "子渠道名称不能超过20个字符"),
 
     // api
     API_TOKEN_ERROR(4000, "token无效"),

+ 12 - 0
api-module/src/main/java/com/tzld/piaoquan/api/controller/contentplatform/ContentPlatformCooperateAccountController.java

@@ -1,5 +1,7 @@
 package com.tzld.piaoquan.api.controller.contentplatform;
 
+import com.tzld.piaoquan.api.annotation.JwtIgnore;
+import com.tzld.piaoquan.api.job.ContentPlatformGzhAccountJob;
 import com.tzld.piaoquan.api.model.param.IdParam;
 import com.tzld.piaoquan.api.model.param.contentplatform.CooperateAccountListParam;
 import com.tzld.piaoquan.api.model.param.contentplatform.CooperateAccountSaveParam;
@@ -24,6 +26,8 @@ public class ContentPlatformCooperateAccountController {
 
     @Autowired
     ContentPlatformCooperateAccountService cooperateAccountService;
+    @Autowired
+    ContentPlatformGzhAccountJob job;
 
     @ApiOperation(value = "公众号列表")
     @PostMapping("/gzh/list")
@@ -69,4 +73,12 @@ public class ContentPlatformCooperateAccountController {
         cooperateAccountService.gzhDelete(param.getId());
         return CommonResponse.success();
     }
+
+    @ApiOperation(value = "公众号账号信息同步", hidden = true)
+    @GetMapping("/job/syncGzhAccountInfoJob")
+    @JwtIgnore
+    public CommonResponse<String> syncGzhAccountInfoJob(String id) {
+        job.syncGzhAccountInfoJob(id);
+        return CommonResponse.success();
+    }
 }

+ 8 - 0
api-module/src/main/java/com/tzld/piaoquan/api/controller/contentplatform/ContentPlatformDatastatController.java

@@ -104,4 +104,12 @@ public class ContentPlatformDatastatController {
         return CommonResponse.success();
     }
 
+    @ApiOperation(value = "企微数据统计分子渠道同步任务", hidden = true)
+    @GetMapping("/job/syncQwDatastatSubChannel")
+    @JwtIgnore
+    public CommonResponse<String> syncContentPlatformQwDatastatSubChannelJob(String dateStr) {
+        job.syncContentPlatformQwDatastatSubChannelJob(dateStr);
+        return CommonResponse.success();
+    }
+
 }

+ 30 - 0
api-module/src/main/java/com/tzld/piaoquan/api/dao/mapper/contentplatform/ContentPlatformQwDataStatSubChannelMapper.java

@@ -0,0 +1,30 @@
+package com.tzld.piaoquan.api.dao.mapper.contentplatform;
+
+import com.tzld.piaoquan.api.model.po.contentplatform.ContentPlatformQwDataStatSubChannel;
+import com.tzld.piaoquan.api.model.po.contentplatform.ContentPlatformQwDataStatSubChannelExample;
+import java.util.List;
+import org.apache.ibatis.annotations.Param;
+
+public interface ContentPlatformQwDataStatSubChannelMapper {
+    long countByExample(ContentPlatformQwDataStatSubChannelExample example);
+
+    int deleteByExample(ContentPlatformQwDataStatSubChannelExample example);
+
+    int deleteByPrimaryKey(Long id);
+
+    int insert(ContentPlatformQwDataStatSubChannel record);
+
+    int insertSelective(ContentPlatformQwDataStatSubChannel record);
+
+    List<ContentPlatformQwDataStatSubChannel> selectByExample(ContentPlatformQwDataStatSubChannelExample example);
+
+    ContentPlatformQwDataStatSubChannel selectByPrimaryKey(Long id);
+
+    int updateByExampleSelective(@Param("record") ContentPlatformQwDataStatSubChannel record, @Param("example") ContentPlatformQwDataStatSubChannelExample example);
+
+    int updateByExample(@Param("record") ContentPlatformQwDataStatSubChannel record, @Param("example") ContentPlatformQwDataStatSubChannelExample example);
+
+    int updateByPrimaryKeySelective(ContentPlatformQwDataStatSubChannel record);
+
+    int updateByPrimaryKey(ContentPlatformQwDataStatSubChannel record);
+}

+ 11 - 0
api-module/src/main/java/com/tzld/piaoquan/api/dao/mapper/contentplatform/ext/ContentPlatformDataStatMapperExt.java

@@ -58,6 +58,13 @@ public interface ContentPlatformDataStatMapperExt {
                                                                           @Param("offset") int offset,
                                                                           @Param("pageSize") Integer pageSize);
 
+    Integer getQwSubChannelDatastatCount(@Param("param") QwDatastatListParam param, @Param("createAccountId") Long createAccountId);
+
+    List<ContentPlatformQwDataStatReplyTotal> getQwSubChannelDatastatList(@Param("param") QwDatastatListParam param,
+                                                                          @Param("createAccountId") Long createAccountId,
+                                                                          @Param("offset") int offset,
+                                                                          @Param("pageSize") Integer pageSize);
+
     Integer getQwSceneDatastatCount(@Param("param") QwDatastatListParam param,
                                     @Param("scene") Integer scene,
                                     @Param("createAccountId") Long createAccountId);
@@ -89,6 +96,8 @@ public interface ContentPlatformDataStatMapperExt {
 
     void batchInsertQwDatastatReplyTotal(@Param("records") List<ContentPlatformQwDataStatReplyTotal> saveList);
 
+    void batchInsertQwDatastatSubChannel(@Param("records") List<ContentPlatformQwDataStatSubChannel> saveList);
+
     List<ContentPlatformQwDataStatTotal> getQwTotalDatastatScoreList(@Param("dt") String dt, @Param("channels") List<String> channels);
 
     List<ContentPlatformQwDataStatReplyTotal> getQwTotalDatastatReplyScoreList(@Param("dt") String dt, @Param("channels") List<String> channels);
@@ -97,6 +106,8 @@ public interface ContentPlatformDataStatMapperExt {
 
     void deleteQwDatastatReplyTotal(@Param("dt") String dt);
 
+    void deleteQwDatastatSubChannel(@Param("dt") String dt);
+
     void deleteGzhDatastatTotal(@Param("dt") String dt);
 
     void deleteFwhDatastatTotal(@Param("dt") String dt);

+ 173 - 56
api-module/src/main/java/com/tzld/piaoquan/api/job/ContentPlatformDatastatJob.java

@@ -45,6 +45,9 @@ public class ContentPlatformDatastatJob {
     @Autowired
     private ContentPlatformQwPlanMapper qwPlanMapper;
 
+    @Autowired
+    private ContentPlatformQwPlanVideoMapper qwPlanVideoMapper;
+
     @Autowired
     private ContentPlatformDataStatMapperExt dataStatMapperExt;
 
@@ -85,15 +88,15 @@ public class ContentPlatformDatastatJob {
                 ContentPlatformGzhPlanTypeEnum.AUTO_REPLY.getVal());
         List<Long> planIds = gzhPlanList.stream().map(ContentPlatformGzhPlan::getId).collect(Collectors.toList());
         Map<Long, List<Long>> gzhPlanMap = gzhPlanList.stream()
-               .collect(Collectors.groupingBy(ContentPlatformGzhPlan::getAccountId,
-                       Collectors.mapping(ContentPlatformGzhPlan::getId, Collectors.toList())));
+                .collect(Collectors.groupingBy(ContentPlatformGzhPlan::getAccountId,
+                        Collectors.mapping(ContentPlatformGzhPlan::getId, Collectors.toList())));
         List<ContentPlatformGzhPlanVideo> gzhPlanVideoList = planService.getGzhPlanVideoList(planIds);
         Map<Long, List<ContentPlatformGzhPlanVideo>> gzhPlanVideoMap = gzhPlanVideoList.stream()
-              .collect(Collectors.groupingBy(ContentPlatformGzhPlanVideo::getPlanId));
+                .collect(Collectors.groupingBy(ContentPlatformGzhPlanVideo::getPlanId));
         List<Long> videoIds = gzhPlanVideoList.stream().map(ContentPlatformGzhPlanVideo::getVideoId).collect(Collectors.toList());
         List<ContentPlatformVideo> contentPlatformVideoList = planService.getVideoContentListByVideoIds(videoIds);
         Map<Long, ContentPlatformVideo> videoMap = contentPlatformVideoList.stream()
-              .collect(Collectors.toMap(ContentPlatformVideo::getVideoId, video -> video, (a, b) -> a));
+                .collect(Collectors.toMap(ContentPlatformVideo::getVideoId, video -> video, (a, b) -> a));
         if (CollectionUtils.isNotEmpty(dataList)) {
             List<ContentPlatformGzhDataStat> saveList = new ArrayList<>();
             for (Record record : dataList) {
@@ -152,13 +155,13 @@ public class ContentPlatformDatastatJob {
         }
         Long now = System.currentTimeMillis();
         // 公众号自动回复数据统计
-        String sql = String.format("SELECT company_shortname, 首层访问人数, dt " +
-                "FROM loghubods.loghubods.gzh_autoreply_behavior_uv_total_agent WHERE dt=%s;", dt);
+        String sql = String.format("SELECT channel_shortname, first_uv, dt " +
+                "FROM loghubods.out_channel_mid_first_total WHERE tag = '投放渠道内去重' and type = '公众号即时回复' and dt=%s;", dt);
         List<Record> dataList = OdpsUtil.getOdpsData(sql);
         // 所有公众号
         List<ContentPlatformAccount> accountList = getAllAccount();
         Map<String, ContentPlatformAccount> accountMap = accountList.stream()
-              .collect(Collectors.toMap(ContentPlatformAccount::getChannel, account -> account));
+                .collect(Collectors.toMap(ContentPlatformAccount::getChannel, account -> account));
         List<ContentPlatformGzhAccount> gzhAccountList = getAllGzhAccount();
         Map<Long, List<ContentPlatformGzhAccount>> gzhAccountMap = gzhAccountList.stream()
                 .collect(Collectors.groupingBy(ContentPlatformGzhAccount::getCreateAccountId));
@@ -172,15 +175,15 @@ public class ContentPlatformDatastatJob {
                 ContentPlatformGzhPlanTypeEnum.AUTO_REPLY.getVal());
         List<Long> planIds = gzhPlanList.stream().map(ContentPlatformGzhPlan::getId).collect(Collectors.toList());
         Map<Long, List<Long>> gzhPlanMap = gzhPlanList.stream()
-               .collect(Collectors.groupingBy(ContentPlatformGzhPlan::getAccountId,
-                       Collectors.mapping(ContentPlatformGzhPlan::getId, Collectors.toList())));
+                .collect(Collectors.groupingBy(ContentPlatformGzhPlan::getAccountId,
+                        Collectors.mapping(ContentPlatformGzhPlan::getId, Collectors.toList())));
         List<ContentPlatformGzhPlanVideo> gzhPlanVideoList = planService.getGzhPlanVideoList(planIds);
         Map<Long, List<ContentPlatformGzhPlanVideo>> gzhPlanVideoMap = gzhPlanVideoList.stream()
-              .collect(Collectors.groupingBy(ContentPlatformGzhPlanVideo::getPlanId));
+                .collect(Collectors.groupingBy(ContentPlatformGzhPlanVideo::getPlanId));
         List<Long> videoIds = gzhPlanVideoList.stream().map(ContentPlatformGzhPlanVideo::getVideoId).collect(Collectors.toList());
         List<ContentPlatformVideo> contentPlatformVideoList = planService.getVideoContentListByVideoIds(videoIds);
         Map<Long, ContentPlatformVideo> videoMap = contentPlatformVideoList.stream()
-              .collect(Collectors.toMap(ContentPlatformVideo::getVideoId, video -> video, (a, b) -> a));
+                .collect(Collectors.toMap(ContentPlatformVideo::getVideoId, video -> video, (a, b) -> a));
         if (CollectionUtils.isNotEmpty(dataList)) {
             List<ContentPlatformGzhDataStatTotal> saveList = new ArrayList<>();
             for (Record record : dataList) {
@@ -267,15 +270,15 @@ public class ContentPlatformDatastatJob {
                 ContentPlatformGzhPlanTypeEnum.FWH_PUSH.getVal());
         List<Long> planIds = gzhPlanList.stream().map(ContentPlatformGzhPlan::getId).collect(Collectors.toList());
         Map<Long, List<Long>> gzhPlanMap = gzhPlanList.stream()
-               .collect(Collectors.groupingBy(ContentPlatformGzhPlan::getAccountId,
-                       Collectors.mapping(ContentPlatformGzhPlan::getId, Collectors.toList())));
+                .collect(Collectors.groupingBy(ContentPlatformGzhPlan::getAccountId,
+                        Collectors.mapping(ContentPlatformGzhPlan::getId, Collectors.toList())));
         List<ContentPlatformGzhPlanVideo> gzhPlanVideoList = planService.getGzhPlanVideoList(planIds);
         Map<Long, List<ContentPlatformGzhPlanVideo>> gzhPlanVideoMap = gzhPlanVideoList.stream()
-              .collect(Collectors.groupingBy(ContentPlatformGzhPlanVideo::getPlanId));
+                .collect(Collectors.groupingBy(ContentPlatformGzhPlanVideo::getPlanId));
         List<Long> videoIds = gzhPlanVideoList.stream().map(ContentPlatformGzhPlanVideo::getVideoId).collect(Collectors.toList());
         List<ContentPlatformVideo> contentPlatformVideoList = planService.getVideoContentListByVideoIds(videoIds);
         Map<Long, ContentPlatformVideo> videoMap = contentPlatformVideoList.stream()
-              .collect(Collectors.toMap(ContentPlatformVideo::getVideoId, video -> video, (a, b) -> a));
+                .collect(Collectors.toMap(ContentPlatformVideo::getVideoId, video -> video, (a, b) -> a));
         if (CollectionUtils.isNotEmpty(dataList)) {
             List<ContentPlatformFwhDataStat> saveList = new ArrayList<>();
             for (Record record : dataList) {
@@ -334,8 +337,8 @@ public class ContentPlatformDatastatJob {
         }
         Long now = System.currentTimeMillis();
         // 公众号自动回复数据统计
-        String sql = String.format("SELECT channel, 首层访问人数, dt " +
-                "FROM loghubods.loghubods.fwhhzdyy_data_per_channel WHERE dt=%s;", dt);
+        String sql = String.format("SELECT channel_shortname, first_uv, dt " +
+                "FROM loghubods.out_channel_mid_first_total WHERE tag = '投放渠道内去重' and type = '服务号代运营' and dt=%s;", dt);
         List<Record> dataList = OdpsUtil.getOdpsData(sql);
         // 所有公众号
         List<ContentPlatformAccount> accountList = getAllAccount();
@@ -462,15 +465,15 @@ public class ContentPlatformDatastatJob {
         List<ContentPlatformQwDataStat> existList = getQwDatastatCount(dt);
         List<String> existRootSourceIds = existList.stream().map(ContentPlatformQwDataStat::getRootSourceId).collect(Collectors.toList());
         Map<String, Long> rootSourceIdMap = qwPlanList.stream()
-            .collect(Collectors.toMap(ContentPlatformQwPlan::getRootSourceId, ContentPlatformQwPlan::getId));
+                .collect(Collectors.toMap(ContentPlatformQwPlan::getRootSourceId, ContentPlatformQwPlan::getId));
         List<Long> planIds = qwPlanList.stream().map(ContentPlatformQwPlan::getId).collect(Collectors.toList());
         List<ContentPlatformQwPlanVideo> planVideoList = planService.getQwPlanVideoList(planIds);
         Map<Long, Long> planVideoMap = planVideoList.stream()
-              .collect(Collectors.toMap(ContentPlatformQwPlanVideo::getPlanId, ContentPlatformQwPlanVideo::getVideoId));
+                .collect(Collectors.toMap(ContentPlatformQwPlanVideo::getPlanId, ContentPlatformQwPlanVideo::getVideoId));
         List<Long> videoIds = planVideoList.stream().map(ContentPlatformQwPlanVideo::getVideoId).collect(Collectors.toList());
         List<ContentPlatformVideo> videoList = planService.getVideoContentListByVideoIds(videoIds);
         Map<Long, Double> videoScoreMap = videoList.stream()
-              .collect(Collectors.toMap(ContentPlatformVideo::getVideoId, ContentPlatformVideo::getScore, (a, b) -> a));
+                .collect(Collectors.toMap(ContentPlatformVideo::getVideoId, ContentPlatformVideo::getScore, (a, b) -> a));
         List<ContentPlatformQwDataStat> saveList = new ArrayList<>();
         List<String> rootSourceIds = qwPlanList.stream().map(ContentPlatformQwPlan::getRootSourceId).collect(Collectors.toList());
         String outSql = String.format("SELECT * FROM loghubods.qw_out_touliu_behavior_detail WHERE dt=%s;", dt);
@@ -555,17 +558,19 @@ public class ContentPlatformDatastatJob {
         }
         dataStatMapperExt.deleteQwDatastatTotal(dt);
         Map<String, ContentPlatformQwDataStatTotal> saveMap = new HashMap<>();
-        String outSql = String.format("SELECT * FROM loghubods.qw_out_touliu_behavior_total WHERE dt=%s;", dt);
+        String outSql = String.format("SELECT channel_shortname, first_uv, dt " +
+                "FROM loghubods.out_channel_mid_first_total WHERE tag = '投放渠道内去重' and type = '企微外部' and dt=%s;", dt);
+//        String outSql = String.format("SELECT * FROM loghubods.qw_out_touliu_behavior_total WHERE dt=%s;", dt);
         List<Record> outDataList = OdpsUtil.getOdpsData(outSql);
         Long now = System.currentTimeMillis();
         if (CollectionUtils.isNotEmpty(outDataList)) {
             for (Record record : outDataList) {
-                String type = (String) record.get(1);
-                if (!"社群".equals(type) && !"自动回复".equals(type)) {
-                    continue;
-                }
-                String channel = (String) record.get(33);
-                int firstLevelCount = Integer.parseInt((String) record.get(6));
+//                String type = (String) record.get(1);
+//                if (!"社群".equals(type) && !"自动回复".equals(type)) {
+//                    continue;
+//                }
+                String channel = (String) record.get(0);
+                int firstLevelCount = Integer.parseInt((String) record.get(1));
                 if (firstLevelCount == 0) {
                     continue;
                 }
@@ -580,35 +585,35 @@ public class ContentPlatformDatastatJob {
                 saveMap.put(channel, item);
             }
         }
-        String out2Sql = String.format("SELECT * FROM loghubods.qw_out2_touliu_behavior_total WHERE dt=%s;", dt);
-        List<Record> out2DataList = OdpsUtil.getOdpsData(out2Sql);
-        if (CollectionUtils.isNotEmpty(out2DataList)) {
-            List<String> out2Channels = new ArrayList<>();
-            for (Record record : out2DataList) {
-                String type = (String) record.get(1);
-                if (!"社群".equals(type) && !"自动回复".equals(type)) {
-                    continue;
-                }
-                String channel = (String) record.get(33);
-                int firstLevelCount = Integer.parseInt((String) record.get(6));
-                if (firstLevelCount == 0) {
-                    continue;
-                }
-                if (saveMap.containsKey(channel) && !out2Channels.contains(channel)) {
-                    saveMap.remove(channel);
-                }
-                ContentPlatformQwDataStatTotal item = saveMap.getOrDefault(channel, new ContentPlatformQwDataStatTotal());
-                item.setDateStr(dt);
-                item.setChannel(channel);
-                if (item.getFirstLevelCount() == null) {
-                    item.setFirstLevelCount(0);
-                }
-                item.setFirstLevelCount(item.getFirstLevelCount() + firstLevelCount);
-                item.setCreateTimestamp(now);
-                out2Channels.add(channel);
-                saveMap.put(channel, item);
-            }
-        }
+//        String out2Sql = String.format("SELECT * FROM loghubods.qw_out2_touliu_behavior_total WHERE dt=%s;", dt);
+//        List<Record> out2DataList = OdpsUtil.getOdpsData(out2Sql);
+//        if (CollectionUtils.isNotEmpty(out2DataList)) {
+//            List<String> out2Channels = new ArrayList<>();
+//            for (Record record : out2DataList) {
+//                String type = (String) record.get(1);
+//                if (!"社群".equals(type) && !"自动回复".equals(type)) {
+//                    continue;
+//                }
+//                String channel = (String) record.get(33);
+//                int firstLevelCount = Integer.parseInt((String) record.get(6));
+//                if (firstLevelCount == 0) {
+//                    continue;
+//                }
+//                if (saveMap.containsKey(channel) && !out2Channels.contains(channel)) {
+//                    saveMap.remove(channel);
+//                }
+//                ContentPlatformQwDataStatTotal item = saveMap.getOrDefault(channel, new ContentPlatformQwDataStatTotal());
+//                item.setDateStr(dt);
+//                item.setChannel(channel);
+//                if (item.getFirstLevelCount() == null) {
+//                    item.setFirstLevelCount(0);
+//                }
+//                item.setFirstLevelCount(item.getFirstLevelCount() + firstLevelCount);
+//                item.setCreateTimestamp(now);
+//                out2Channels.add(channel);
+//                saveMap.put(channel, item);
+//            }
+//        }
         List<ContentPlatformQwDataStatTotal> saveList = new ArrayList<>(saveMap.values());
         if (CollectionUtils.isNotEmpty(saveList)) {
             List<String> channels = saveList.stream().map(ContentPlatformQwDataStatTotal::getChannel).distinct().collect(Collectors.toList());
@@ -692,4 +697,116 @@ public class ContentPlatformDatastatJob {
         return ReturnT.SUCCESS;
     }
 
+    @XxlJob("syncContentPlatformQwDatastatSubChannelJob")
+    public ReturnT<String> syncContentPlatformQwDatastatSubChannelJob(String param) {
+        String dt = DateUtil.getBeforeDayDateString("yyyyMMdd");
+        if (StringUtils.hasText(param)) {
+            dt = param;
+        }
+        List<ContentPlatformQwDataStatSubChannel> saveList = new ArrayList<>();
+        String outSql = String.format("SELECT channel, subchannel, first_uv FROM loghubods.qw_out_channel_mid_first_total WHERE dt=%s;", dt);
+        List<Record> outDataList = OdpsUtil.getOdpsData(outSql);
+        List<ContentPlatformAccount> accountList = getAllAccount();
+        Map<String, ContentPlatformAccount> accountMap = accountList.stream()
+                .collect(Collectors.toMap(ContentPlatformAccount::getChannel, account -> account));
+        List<ContentPlatformQwPlan> qwPlanList = getSubChannelQwPlanList();
+        Map<Long, List<ContentPlatformQwPlan>> qwPlanMap = qwPlanList.stream().collect(
+                Collectors.groupingBy(ContentPlatformQwPlan::getCreateAccountId));
+        List<Long> qwPlanIds = qwPlanList.stream().map(ContentPlatformQwPlan::getId).collect(Collectors.toList());
+        List<ContentPlatformQwPlanVideo> qwPlanVideoList = getSubChannelQwPlanVideoList(qwPlanIds);
+        Map<Long, List<ContentPlatformQwPlanVideo>> qwPlanVideoMap = qwPlanVideoList.stream()
+               .collect(Collectors.groupingBy(ContentPlatformQwPlanVideo::getPlanId));
+        List<Long> videoIdList = qwPlanVideoList.stream().map(ContentPlatformQwPlanVideo::getVideoId).collect(Collectors.toList());
+        List<ContentPlatformVideo> videoList = planService.getVideoContentListByVideoIds(videoIdList);
+        Map<Long, Double> videoScoreMap = videoList.stream()
+                .collect(Collectors.toMap(ContentPlatformVideo::getVideoId, ContentPlatformVideo::getScore, (a, b) -> a));
+        Long now = System.currentTimeMillis();
+        if (CollectionUtils.isNotEmpty(outDataList)) {
+            List<Record> noSubChannelRecordList = new ArrayList<>();
+            for (Record record : outDataList) {
+                String channel = (String) record.get(0);
+                String subChannel = (String) record.get(1);
+                int firstLevelCount = Integer.parseInt((String) record.get(2));
+                if (firstLevelCount == 0) {
+                    continue;
+                }
+                ContentPlatformQwDataStatSubChannel item = new ContentPlatformQwDataStatSubChannel();
+                item.setDateStr(dt);
+                ContentPlatformAccount account = accountMap.get(channel);
+                if (Objects.isNull(account)) {
+                    continue;
+                }
+                List<ContentPlatformQwPlan> qwPlans = qwPlanMap.getOrDefault(account.getId(), new ArrayList<>());
+                List<String> subChannelList = qwPlans.stream().map(ContentPlatformQwPlan::getSubChannel).distinct().collect(Collectors.toList());
+                if (CollectionUtils.isEmpty(qwPlans) || !subChannelList.contains(subChannel)) {
+                    noSubChannelRecordList.add(record);
+                    continue;
+                }
+                item.setCreateAccountId(account.getId());
+                item.setSubChannel(subChannel);
+                if (item.getFirstLevelCount() == null) {
+                    item.setFirstLevelCount(0);
+                }
+                Double score = 0.0;
+                int size = 0;
+                for (ContentPlatformQwPlan qwPlan : qwPlans) {
+                    List<ContentPlatformQwPlanVideo> planVideoList = qwPlanVideoMap.get(qwPlan.getId());
+                    if (CollectionUtils.isEmpty(planVideoList)) {
+                        continue;
+                    }
+                    List<Long> videoIds = planVideoList.stream().map(ContentPlatformQwPlanVideo::getVideoId).collect(Collectors.toList());
+                    size += videoIds.size();
+                    for (Long videoId : videoIds) {
+                        if (Objects.nonNull(videoScoreMap.get(videoId))) {
+                            score += videoScoreMap.get(videoId);
+                        }
+                    }
+                }
+                if (size > 0) {
+                    BigDecimal num = BigDecimal.valueOf(score / size);
+                    BigDecimal rounded = num.setScale(2, RoundingMode.HALF_UP);
+                    item.setScore(rounded.doubleValue());
+                }
+                item.setFirstLevelCount(item.getFirstLevelCount() + firstLevelCount);
+                item.setCreateTimestamp(now);
+                saveList.add(item);
+            }
+            for (Record record : noSubChannelRecordList) {
+                String channel = (String) record.get(0);
+                int firstLevelCount = Integer.parseInt((String) record.get(2));
+                ContentPlatformQwDataStatSubChannel item = new ContentPlatformQwDataStatSubChannel();
+                item.setDateStr(dt);
+                ContentPlatformAccount account = accountMap.get(channel);
+                if (Objects.isNull(account)) {
+                    continue;
+                }
+                item.setCreateAccountId(account.getId());
+                item.setSubChannel("未知");
+                if (item.getFirstLevelCount() == null) {
+                    item.setFirstLevelCount(0);
+                }
+                item.setFirstLevelCount(item.getFirstLevelCount() + firstLevelCount);
+                item.setCreateTimestamp(now);
+                saveList.add(item);
+            }
+        }
+        if (CollectionUtils.isNotEmpty(saveList)) {
+            dataStatMapperExt.deleteQwDatastatReplyTotal(dt);
+            dataStatMapperExt.batchInsertQwDatastatSubChannel(saveList);
+        }
+        return ReturnT.SUCCESS;
+    }
+
+    private List<ContentPlatformQwPlan> getSubChannelQwPlanList() {
+        ContentPlatformQwPlanExample example = new ContentPlatformQwPlanExample();
+        example.createCriteria().andSubChannelIsNotNull();
+        return qwPlanMapper.selectByExample(example);
+    }
+
+    private List<ContentPlatformQwPlanVideo> getSubChannelQwPlanVideoList(List<Long> qwPlanIds) {
+        ContentPlatformQwPlanVideoExample example = new ContentPlatformQwPlanVideoExample();
+        example.createCriteria().andPlanIdIn(qwPlanIds);
+        return qwPlanVideoMapper.selectByExample(example);
+    }
+
 }

+ 63 - 0
api-module/src/main/java/com/tzld/piaoquan/api/job/ContentPlatformGzhAccountJob.java

@@ -0,0 +1,63 @@
+package com.tzld.piaoquan.api.job;
+
+import com.alibaba.fastjson.JSONObject;
+import com.tzld.piaoquan.api.component.AigcApiService;
+import com.tzld.piaoquan.api.dao.mapper.contentplatform.ContentPlatformGzhAccountMapper;
+import com.tzld.piaoquan.api.model.po.contentplatform.ContentPlatformGzhAccount;
+import com.tzld.piaoquan.api.model.po.contentplatform.ContentPlatformGzhAccountExample;
+import com.xxl.job.core.biz.model.ReturnT;
+import com.xxl.job.core.handler.annotation.XxlJob;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+@Slf4j
+@Component
+public class ContentPlatformGzhAccountJob {
+
+    @Autowired
+    private ContentPlatformGzhAccountMapper gzhAccountMapper;
+    @Autowired
+    private AigcApiService aigcApiService;
+
+    @XxlJob("syncGzhAccountInfoJob")
+    public ReturnT<String> syncGzhAccountInfoJob(String param) {
+        List<ContentPlatformGzhAccount> accountList;
+        if (StringUtils.hasText(param)) {
+            ContentPlatformGzhAccount account = gzhAccountMapper.selectByPrimaryKey(Long.valueOf(param));
+            accountList = new ArrayList<>();
+            accountList.add(account);
+        } else {
+            accountList = getNeedSyncAccountInfo();
+        }
+        if (accountList.isEmpty()) {
+            return ReturnT.SUCCESS;
+        }
+        for (ContentPlatformGzhAccount account : accountList) {
+            log.info("同步公众号数据统计:{}", account.getGhId());
+            JSONObject accountInfo = aigcApiService.getAccountDetail(account.getExternalId());
+            if (Objects.isNull(accountInfo)) {
+                continue;
+            }
+            String newName = accountInfo.getString("name");
+            if (account.getName().equals(newName) || !StringUtils.hasText(newName)) {
+                continue;
+            }
+            account.setName(accountInfo.getString("name"));
+            gzhAccountMapper.updateByPrimaryKeySelective(account);
+        }
+
+        return ReturnT.SUCCESS;
+    }
+
+    private List<ContentPlatformGzhAccount> getNeedSyncAccountInfo() {
+        ContentPlatformGzhAccountExample example = new ContentPlatformGzhAccountExample();
+        example.createCriteria().andExternalIdIsNotNull();
+        return gzhAccountMapper.selectByExample(example);
+    }
+}

+ 1 - 1
api-module/src/main/java/com/tzld/piaoquan/api/model/param/contentplatform/QwDatastatListParam.java

@@ -7,6 +7,6 @@ import lombok.Data;
 @Data
 public class QwDatastatListParam extends PageParam {
 
-    @ApiModelProperty(value = "0-总计 1-群发 2-私发 3-自动回复 4-分链接")
+    @ApiModelProperty(value = "0-总计 1-群发 2-私发 3-自动回复 4-分链接 5-分子渠道")
     private Integer type;
 }

+ 3 - 0
api-module/src/main/java/com/tzld/piaoquan/api/model/param/contentplatform/QwPlanListParam.java

@@ -10,6 +10,9 @@ public class QwPlanListParam extends PageParam {
     @ApiModelProperty(value = "类型 0-自动回复 1-每日推送")
     private Integer type;
 
+    @ApiModelProperty(value = "子渠道")
+    private String subChannel;
+
     @ApiModelProperty(value = "场景 0-群发 1-单发")
     private Integer scene;
 

+ 3 - 0
api-module/src/main/java/com/tzld/piaoquan/api/model/param/contentplatform/QwPlanSaveParam.java

@@ -11,6 +11,9 @@ public class QwPlanSaveParam {
     @ApiModelProperty(value = "类型 0-社群 1-每日推送")
     private Integer type;
 
+    @ApiModelProperty(value = "子渠道")
+    private String subChannel;
+
     @ApiModelProperty(value = "视频列表")
     private List<QwPlanSaveVideoParam> videoList;
 }

+ 90 - 0
api-module/src/main/java/com/tzld/piaoquan/api/model/po/contentplatform/ContentPlatformQwDataStatSubChannel.java

@@ -0,0 +1,90 @@
+package com.tzld.piaoquan.api.model.po.contentplatform;
+
+public class ContentPlatformQwDataStatSubChannel {
+    private Long id;
+
+    private String dateStr;
+
+    private String subChannel;
+
+    private Integer firstLevelCount;
+
+    private Double score;
+
+    private Long createAccountId;
+
+    private Long createTimestamp;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getDateStr() {
+        return dateStr;
+    }
+
+    public void setDateStr(String dateStr) {
+        this.dateStr = dateStr;
+    }
+
+    public String getSubChannel() {
+        return subChannel;
+    }
+
+    public void setSubChannel(String subChannel) {
+        this.subChannel = subChannel;
+    }
+
+    public Integer getFirstLevelCount() {
+        return firstLevelCount;
+    }
+
+    public void setFirstLevelCount(Integer firstLevelCount) {
+        this.firstLevelCount = firstLevelCount;
+    }
+
+    public Double getScore() {
+        return score;
+    }
+
+    public void setScore(Double score) {
+        this.score = score;
+    }
+
+    public Long getCreateAccountId() {
+        return createAccountId;
+    }
+
+    public void setCreateAccountId(Long createAccountId) {
+        this.createAccountId = createAccountId;
+    }
+
+    public Long getCreateTimestamp() {
+        return createTimestamp;
+    }
+
+    public void setCreateTimestamp(Long createTimestamp) {
+        this.createTimestamp = createTimestamp;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getClass().getSimpleName());
+        sb.append(" [");
+        sb.append("Hash = ").append(hashCode());
+        sb.append(", id=").append(id);
+        sb.append(", dateStr=").append(dateStr);
+        sb.append(", subChannel=").append(subChannel);
+        sb.append(", firstLevelCount=").append(firstLevelCount);
+        sb.append(", score=").append(score);
+        sb.append(", createAccountId=").append(createAccountId);
+        sb.append(", createTimestamp=").append(createTimestamp);
+        sb.append("]");
+        return sb.toString();
+    }
+}

+ 651 - 0
api-module/src/main/java/com/tzld/piaoquan/api/model/po/contentplatform/ContentPlatformQwDataStatSubChannelExample.java

@@ -0,0 +1,651 @@
+package com.tzld.piaoquan.api.model.po.contentplatform;
+
+import com.tzld.piaoquan.growth.common.utils.page.Page;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ContentPlatformQwDataStatSubChannelExample {
+    protected String orderByClause;
+
+    protected boolean distinct;
+
+    protected List<Criteria> oredCriteria;
+
+    protected Page page;
+
+    public ContentPlatformQwDataStatSubChannelExample() {
+        oredCriteria = new ArrayList<Criteria>();
+    }
+
+    public void setOrderByClause(String orderByClause) {
+        this.orderByClause = orderByClause;
+    }
+
+    public String getOrderByClause() {
+        return orderByClause;
+    }
+
+    public void setDistinct(boolean distinct) {
+        this.distinct = distinct;
+    }
+
+    public boolean isDistinct() {
+        return distinct;
+    }
+
+    public List<Criteria> getOredCriteria() {
+        return oredCriteria;
+    }
+
+    public void or(Criteria criteria) {
+        oredCriteria.add(criteria);
+    }
+
+    public Criteria or() {
+        Criteria criteria = createCriteriaInternal();
+        oredCriteria.add(criteria);
+        return criteria;
+    }
+
+    public Criteria createCriteria() {
+        Criteria criteria = createCriteriaInternal();
+        if (oredCriteria.size() == 0) {
+            oredCriteria.add(criteria);
+        }
+        return criteria;
+    }
+
+    protected Criteria createCriteriaInternal() {
+        Criteria criteria = new Criteria();
+        return criteria;
+    }
+
+    public void clear() {
+        oredCriteria.clear();
+        orderByClause = null;
+        distinct = false;
+    }
+
+    public void setPage(Page page) {
+        this.page=page;
+    }
+
+    public Page getPage() {
+        return page;
+    }
+
+    protected abstract static class GeneratedCriteria {
+        protected List<Criterion> criteria;
+
+        protected GeneratedCriteria() {
+            super();
+            criteria = new ArrayList<Criterion>();
+        }
+
+        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 andDateStrIsNull() {
+            addCriterion("date_str is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andDateStrIsNotNull() {
+            addCriterion("date_str is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andDateStrEqualTo(String value) {
+            addCriterion("date_str =", value, "dateStr");
+            return (Criteria) this;
+        }
+
+        public Criteria andDateStrNotEqualTo(String value) {
+            addCriterion("date_str <>", value, "dateStr");
+            return (Criteria) this;
+        }
+
+        public Criteria andDateStrGreaterThan(String value) {
+            addCriterion("date_str >", value, "dateStr");
+            return (Criteria) this;
+        }
+
+        public Criteria andDateStrGreaterThanOrEqualTo(String value) {
+            addCriterion("date_str >=", value, "dateStr");
+            return (Criteria) this;
+        }
+
+        public Criteria andDateStrLessThan(String value) {
+            addCriterion("date_str <", value, "dateStr");
+            return (Criteria) this;
+        }
+
+        public Criteria andDateStrLessThanOrEqualTo(String value) {
+            addCriterion("date_str <=", value, "dateStr");
+            return (Criteria) this;
+        }
+
+        public Criteria andDateStrLike(String value) {
+            addCriterion("date_str like", value, "dateStr");
+            return (Criteria) this;
+        }
+
+        public Criteria andDateStrNotLike(String value) {
+            addCriterion("date_str not like", value, "dateStr");
+            return (Criteria) this;
+        }
+
+        public Criteria andDateStrIn(List<String> values) {
+            addCriterion("date_str in", values, "dateStr");
+            return (Criteria) this;
+        }
+
+        public Criteria andDateStrNotIn(List<String> values) {
+            addCriterion("date_str not in", values, "dateStr");
+            return (Criteria) this;
+        }
+
+        public Criteria andDateStrBetween(String value1, String value2) {
+            addCriterion("date_str between", value1, value2, "dateStr");
+            return (Criteria) this;
+        }
+
+        public Criteria andDateStrNotBetween(String value1, String value2) {
+            addCriterion("date_str not between", value1, value2, "dateStr");
+            return (Criteria) this;
+        }
+
+        public Criteria andSubChannelIsNull() {
+            addCriterion("sub_channel is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andSubChannelIsNotNull() {
+            addCriterion("sub_channel is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andSubChannelEqualTo(String value) {
+            addCriterion("sub_channel =", value, "subChannel");
+            return (Criteria) this;
+        }
+
+        public Criteria andSubChannelNotEqualTo(String value) {
+            addCriterion("sub_channel <>", value, "subChannel");
+            return (Criteria) this;
+        }
+
+        public Criteria andSubChannelGreaterThan(String value) {
+            addCriterion("sub_channel >", value, "subChannel");
+            return (Criteria) this;
+        }
+
+        public Criteria andSubChannelGreaterThanOrEqualTo(String value) {
+            addCriterion("sub_channel >=", value, "subChannel");
+            return (Criteria) this;
+        }
+
+        public Criteria andSubChannelLessThan(String value) {
+            addCriterion("sub_channel <", value, "subChannel");
+            return (Criteria) this;
+        }
+
+        public Criteria andSubChannelLessThanOrEqualTo(String value) {
+            addCriterion("sub_channel <=", value, "subChannel");
+            return (Criteria) this;
+        }
+
+        public Criteria andSubChannelLike(String value) {
+            addCriterion("sub_channel like", value, "subChannel");
+            return (Criteria) this;
+        }
+
+        public Criteria andSubChannelNotLike(String value) {
+            addCriterion("sub_channel not like", value, "subChannel");
+            return (Criteria) this;
+        }
+
+        public Criteria andSubChannelIn(List<String> values) {
+            addCriterion("sub_channel in", values, "subChannel");
+            return (Criteria) this;
+        }
+
+        public Criteria andSubChannelNotIn(List<String> values) {
+            addCriterion("sub_channel not in", values, "subChannel");
+            return (Criteria) this;
+        }
+
+        public Criteria andSubChannelBetween(String value1, String value2) {
+            addCriterion("sub_channel between", value1, value2, "subChannel");
+            return (Criteria) this;
+        }
+
+        public Criteria andSubChannelNotBetween(String value1, String value2) {
+            addCriterion("sub_channel not between", value1, value2, "subChannel");
+            return (Criteria) this;
+        }
+
+        public Criteria andFirstLevelCountIsNull() {
+            addCriterion("first_level_count is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andFirstLevelCountIsNotNull() {
+            addCriterion("first_level_count is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andFirstLevelCountEqualTo(Integer value) {
+            addCriterion("first_level_count =", value, "firstLevelCount");
+            return (Criteria) this;
+        }
+
+        public Criteria andFirstLevelCountNotEqualTo(Integer value) {
+            addCriterion("first_level_count <>", value, "firstLevelCount");
+            return (Criteria) this;
+        }
+
+        public Criteria andFirstLevelCountGreaterThan(Integer value) {
+            addCriterion("first_level_count >", value, "firstLevelCount");
+            return (Criteria) this;
+        }
+
+        public Criteria andFirstLevelCountGreaterThanOrEqualTo(Integer value) {
+            addCriterion("first_level_count >=", value, "firstLevelCount");
+            return (Criteria) this;
+        }
+
+        public Criteria andFirstLevelCountLessThan(Integer value) {
+            addCriterion("first_level_count <", value, "firstLevelCount");
+            return (Criteria) this;
+        }
+
+        public Criteria andFirstLevelCountLessThanOrEqualTo(Integer value) {
+            addCriterion("first_level_count <=", value, "firstLevelCount");
+            return (Criteria) this;
+        }
+
+        public Criteria andFirstLevelCountIn(List<Integer> values) {
+            addCriterion("first_level_count in", values, "firstLevelCount");
+            return (Criteria) this;
+        }
+
+        public Criteria andFirstLevelCountNotIn(List<Integer> values) {
+            addCriterion("first_level_count not in", values, "firstLevelCount");
+            return (Criteria) this;
+        }
+
+        public Criteria andFirstLevelCountBetween(Integer value1, Integer value2) {
+            addCriterion("first_level_count between", value1, value2, "firstLevelCount");
+            return (Criteria) this;
+        }
+
+        public Criteria andFirstLevelCountNotBetween(Integer value1, Integer value2) {
+            addCriterion("first_level_count not between", value1, value2, "firstLevelCount");
+            return (Criteria) this;
+        }
+
+        public Criteria andScoreIsNull() {
+            addCriterion("score is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andScoreIsNotNull() {
+            addCriterion("score is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andScoreEqualTo(Double value) {
+            addCriterion("score =", value, "score");
+            return (Criteria) this;
+        }
+
+        public Criteria andScoreNotEqualTo(Double value) {
+            addCriterion("score <>", value, "score");
+            return (Criteria) this;
+        }
+
+        public Criteria andScoreGreaterThan(Double value) {
+            addCriterion("score >", value, "score");
+            return (Criteria) this;
+        }
+
+        public Criteria andScoreGreaterThanOrEqualTo(Double value) {
+            addCriterion("score >=", value, "score");
+            return (Criteria) this;
+        }
+
+        public Criteria andScoreLessThan(Double value) {
+            addCriterion("score <", value, "score");
+            return (Criteria) this;
+        }
+
+        public Criteria andScoreLessThanOrEqualTo(Double value) {
+            addCriterion("score <=", value, "score");
+            return (Criteria) this;
+        }
+
+        public Criteria andScoreIn(List<Double> values) {
+            addCriterion("score in", values, "score");
+            return (Criteria) this;
+        }
+
+        public Criteria andScoreNotIn(List<Double> values) {
+            addCriterion("score not in", values, "score");
+            return (Criteria) this;
+        }
+
+        public Criteria andScoreBetween(Double value1, Double value2) {
+            addCriterion("score between", value1, value2, "score");
+            return (Criteria) this;
+        }
+
+        public Criteria andScoreNotBetween(Double value1, Double value2) {
+            addCriterion("score not between", value1, value2, "score");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateAccountIdIsNull() {
+            addCriterion("create_account_id is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateAccountIdIsNotNull() {
+            addCriterion("create_account_id is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateAccountIdEqualTo(Long value) {
+            addCriterion("create_account_id =", value, "createAccountId");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateAccountIdNotEqualTo(Long value) {
+            addCriterion("create_account_id <>", value, "createAccountId");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateAccountIdGreaterThan(Long value) {
+            addCriterion("create_account_id >", value, "createAccountId");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateAccountIdGreaterThanOrEqualTo(Long value) {
+            addCriterion("create_account_id >=", value, "createAccountId");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateAccountIdLessThan(Long value) {
+            addCriterion("create_account_id <", value, "createAccountId");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateAccountIdLessThanOrEqualTo(Long value) {
+            addCriterion("create_account_id <=", value, "createAccountId");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateAccountIdIn(List<Long> values) {
+            addCriterion("create_account_id in", values, "createAccountId");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateAccountIdNotIn(List<Long> values) {
+            addCriterion("create_account_id not in", values, "createAccountId");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateAccountIdBetween(Long value1, Long value2) {
+            addCriterion("create_account_id between", value1, value2, "createAccountId");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateAccountIdNotBetween(Long value1, Long value2) {
+            addCriterion("create_account_id not between", value1, value2, "createAccountId");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimestampIsNull() {
+            addCriterion("create_timestamp is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimestampIsNotNull() {
+            addCriterion("create_timestamp is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimestampEqualTo(Long value) {
+            addCriterion("create_timestamp =", value, "createTimestamp");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimestampNotEqualTo(Long value) {
+            addCriterion("create_timestamp <>", value, "createTimestamp");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimestampGreaterThan(Long value) {
+            addCriterion("create_timestamp >", value, "createTimestamp");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimestampGreaterThanOrEqualTo(Long value) {
+            addCriterion("create_timestamp >=", value, "createTimestamp");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimestampLessThan(Long value) {
+            addCriterion("create_timestamp <", value, "createTimestamp");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimestampLessThanOrEqualTo(Long value) {
+            addCriterion("create_timestamp <=", value, "createTimestamp");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimestampIn(List<Long> values) {
+            addCriterion("create_timestamp in", values, "createTimestamp");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimestampNotIn(List<Long> values) {
+            addCriterion("create_timestamp not in", values, "createTimestamp");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimestampBetween(Long value1, Long value2) {
+            addCriterion("create_timestamp between", value1, value2, "createTimestamp");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimestampNotBetween(Long value1, Long value2) {
+            addCriterion("create_timestamp not between", value1, value2, "createTimestamp");
+            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);
+        }
+    }
+}

+ 11 - 0
api-module/src/main/java/com/tzld/piaoquan/api/model/po/contentplatform/ContentPlatformQwPlan.java

@@ -5,6 +5,8 @@ public class ContentPlatformQwPlan {
 
     private Integer type;
 
+    private String subChannel;
+
     private Integer scene;
 
     private String pageUrl;
@@ -35,6 +37,14 @@ public class ContentPlatformQwPlan {
         this.type = type;
     }
 
+    public String getSubChannel() {
+        return subChannel;
+    }
+
+    public void setSubChannel(String subChannel) {
+        this.subChannel = subChannel;
+    }
+
     public Integer getScene() {
         return scene;
     }
@@ -99,6 +109,7 @@ public class ContentPlatformQwPlan {
         sb.append("Hash = ").append(hashCode());
         sb.append(", id=").append(id);
         sb.append(", type=").append(type);
+        sb.append(", subChannel=").append(subChannel);
         sb.append(", scene=").append(scene);
         sb.append(", pageUrl=").append(pageUrl);
         sb.append(", rootSourceId=").append(rootSourceId);

+ 70 - 0
api-module/src/main/java/com/tzld/piaoquan/api/model/po/contentplatform/ContentPlatformQwPlanExample.java

@@ -235,6 +235,76 @@ public class ContentPlatformQwPlanExample {
             return (Criteria) this;
         }
 
+        public Criteria andSubChannelIsNull() {
+            addCriterion("sub_channel is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andSubChannelIsNotNull() {
+            addCriterion("sub_channel is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andSubChannelEqualTo(String value) {
+            addCriterion("sub_channel =", value, "subChannel");
+            return (Criteria) this;
+        }
+
+        public Criteria andSubChannelNotEqualTo(String value) {
+            addCriterion("sub_channel <>", value, "subChannel");
+            return (Criteria) this;
+        }
+
+        public Criteria andSubChannelGreaterThan(String value) {
+            addCriterion("sub_channel >", value, "subChannel");
+            return (Criteria) this;
+        }
+
+        public Criteria andSubChannelGreaterThanOrEqualTo(String value) {
+            addCriterion("sub_channel >=", value, "subChannel");
+            return (Criteria) this;
+        }
+
+        public Criteria andSubChannelLessThan(String value) {
+            addCriterion("sub_channel <", value, "subChannel");
+            return (Criteria) this;
+        }
+
+        public Criteria andSubChannelLessThanOrEqualTo(String value) {
+            addCriterion("sub_channel <=", value, "subChannel");
+            return (Criteria) this;
+        }
+
+        public Criteria andSubChannelLike(String value) {
+            addCriterion("sub_channel like", value, "subChannel");
+            return (Criteria) this;
+        }
+
+        public Criteria andSubChannelNotLike(String value) {
+            addCriterion("sub_channel not like", value, "subChannel");
+            return (Criteria) this;
+        }
+
+        public Criteria andSubChannelIn(List<String> values) {
+            addCriterion("sub_channel in", values, "subChannel");
+            return (Criteria) this;
+        }
+
+        public Criteria andSubChannelNotIn(List<String> values) {
+            addCriterion("sub_channel not in", values, "subChannel");
+            return (Criteria) this;
+        }
+
+        public Criteria andSubChannelBetween(String value1, String value2) {
+            addCriterion("sub_channel between", value1, value2, "subChannel");
+            return (Criteria) this;
+        }
+
+        public Criteria andSubChannelNotBetween(String value1, String value2) {
+            addCriterion("sub_channel not between", value1, value2, "subChannel");
+            return (Criteria) this;
+        }
+
         public Criteria andSceneIsNull() {
             addCriterion("scene is null");
             return (Criteria) this;

+ 3 - 0
api-module/src/main/java/com/tzld/piaoquan/api/model/vo/contentplatform/QwDatastatItemVO.java

@@ -9,6 +9,9 @@ public class QwDatastatItemVO {
     @ApiModelProperty(value = "日期")
     private String dateStr;
 
+    @ApiModelProperty(value = "子渠道")
+    private String subChannel;
+
     @ApiModelProperty(value = "小程序访问人数")
     private Integer firstLevel;
 

+ 3 - 0
api-module/src/main/java/com/tzld/piaoquan/api/model/vo/contentplatform/QwPlanItemVO.java

@@ -14,6 +14,9 @@ public class QwPlanItemVO {
     @ApiModelProperty(value = "类型 0-自动回复 1-每日推送")
     private Integer type;
 
+    @ApiModelProperty(value = "子渠道")
+    private String subChannel;
+
     @ApiModelProperty(value = "场景 0-群发 1-单发")
     private Integer scene;
 

+ 30 - 0
api-module/src/main/java/com/tzld/piaoquan/api/model/vo/contentplatform/QwSubChannelDatastatItemExportVO.java

@@ -0,0 +1,30 @@
+package com.tzld.piaoquan.api.model.vo.contentplatform;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.write.style.ColumnWidth;
+import com.alibaba.excel.annotation.write.style.ContentRowHeight;
+import com.alibaba.excel.annotation.write.style.HeadRowHeight;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@ColumnWidth(20)//宽
+@HeadRowHeight(50)//表头高
+@ContentRowHeight(25)//正文行高
+public class QwSubChannelDatastatItemExportVO {
+
+    @ExcelProperty("日期")
+    private String dateStr;
+
+    @ExcelProperty("子渠道")
+    private String subChannel;
+
+    @ExcelProperty("小程序访问人数")
+    private Integer firstLevel;
+
+    @ExcelProperty("传播得分")
+    private Double score;
+}

+ 43 - 0
api-module/src/main/java/com/tzld/piaoquan/api/service/contentplatform/impl/ContentPlatformDatastatServiceImpl.java

@@ -161,6 +161,8 @@ public class ContentPlatformDatastatServiceImpl implements ContentPlatformDatast
                 return qwReplyDatastatList(param);
             case 4:
                 return qwRootSourceIdDatastatList(param);
+            case 5:
+                return qwSubChannelDatastatList(param);
             default:
                 return qwRootSourceIdDatastatList(param);
         }
@@ -226,6 +228,28 @@ public class ContentPlatformDatastatServiceImpl implements ContentPlatformDatast
         return result;
     }
 
+    private Page<QwDatastatItemVO> qwSubChannelDatastatList(QwDatastatListParam param) {
+        ContentPlatformAccount user = LoginUserContext.getUser();
+        Page<QwDatastatItemVO> result = new Page<>(param.getPageNum(), param.getPageSize());
+        int offset = (param.getPageNum() - 1) * param.getPageSize();
+        int count = dataStatMapperExt.getQwSubChannelDatastatCount(param, user.getId());
+        result.setTotalSize(count);
+        if (count == 0) {
+            return result;
+        }
+        List<ContentPlatformQwDataStatReplyTotal> datastatList = dataStatMapperExt.getQwSubChannelDatastatList(param,
+                user.getId(), offset, param.getPageSize());
+        List<QwDatastatItemVO> list = datastatList.stream().map(datastat -> {
+            QwDatastatItemVO vo = new QwDatastatItemVO();
+            vo.setDateStr(datastat.getDateStr());
+            vo.setFirstLevel(datastat.getFirstLevelCount());
+            vo.setScore(datastat.getScore());
+            return vo;
+        }).collect(Collectors.toList());
+        result.setObjs(list);
+        return result;
+    }
+
     private Page<QwDatastatItemVO> qwRootSourceIdDatastatList(QwDatastatListParam param) {
         ContentPlatformAccount user = LoginUserContext.getUser();
         Page<QwDatastatItemVO> result = new Page<>(param.getPageNum(), param.getPageSize());
@@ -338,6 +362,8 @@ public class ContentPlatformDatastatServiceImpl implements ContentPlatformDatast
         List<QwDatastatItemVO> dataList = pageResult.getObjs();
         if (param.getType() == 4) {
             return generateQwDatastatExcelFile(dataList);
+        } else if (param.getType() == 5) {
+            return generateQwSubChannelDatastatExcelFile(dataList);
         } else {
             return generateGroupQwDatastatExcelFile(dataList);
         }
@@ -360,6 +386,23 @@ public class ContentPlatformDatastatServiceImpl implements ContentPlatformDatast
         return CdnUtil.DOWNLOAD_CDN_URL_HOST_PICTURE + fileName;
     }
 
+    public String generateQwSubChannelDatastatExcelFile(List<QwDatastatItemVO> dataList) {
+        ArrayList<QwSubChannelDatastatItemExportVO> list = new ArrayList<>();
+        if (CollectionUtils.isNotEmpty(dataList)) {
+            for (QwDatastatItemVO data : dataList) {
+                list.add(new QwSubChannelDatastatItemExportVO(data.getDateStr(), data.getSubChannel(), data.getFirstLevel(), data.getScore()));
+            }
+        } else {
+            list.add(new QwSubChannelDatastatItemExportVO());
+        }
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        EasyExcel.write(out, QwSubChannelDatastatItemExportVO.class).sheet("").doWrite(list);
+        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(out.toByteArray());
+        String fileName = "企微数据统计_" + System.currentTimeMillis() + ".xls";
+        AliOssFileTool.saveInPublicReturnHost(byteArrayInputStream, EnumPublicBuckets.PUBBUCKET, fileName, EnumFileType.TEMP_PICTURE);
+        return CdnUtil.DOWNLOAD_CDN_URL_HOST_PICTURE + fileName;
+    }
+
     public String generateGroupQwDatastatExcelFile(List<QwDatastatItemVO> dataList) {
         ArrayList<QwGroupDatastatItemExportVO> list = new ArrayList<>();
         if (CollectionUtils.isNotEmpty(dataList)) {

+ 7 - 1
api-module/src/main/java/com/tzld/piaoquan/api/service/contentplatform/impl/ContentPlatformPlanServiceImpl.java

@@ -530,6 +530,7 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
             QwPlanItemVO planItemVO = new QwPlanItemVO();
             planItemVO.setId(qwPlan.getId());
             planItemVO.setType(qwPlan.getType());
+            planItemVO.setSubChannel(qwPlan.getSubChannel());
             planItemVO.setScene(qwPlan.getScene());
             planItemVO.setPageUrl(qwPlan.getPageUrl());
             planItemVO.setCreateTimestamp(qwPlan.getCreateTimestamp());
@@ -561,13 +562,18 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
     @Override
     public List<QwPlanItemVO> qwPlanSave(QwPlanSaveParam param) {
         ContentPlatformAccount loginUser = LoginUserContext.getUser();
+        if (StringUtils.hasText(param.getSubChannel()) && param.getSubChannel().length() > 20) {
+            throw new CommonException(ExceptionEnum.QW_PLAN_SUB_CHANNEL_LENGTH);
+        }
         Long now = System.currentTimeMillis();
         List<ContentPlatformQwPlan> list = new ArrayList<>();
         for (QwPlanSaveVideoParam videoParam : param.getVideoList()) {
             ContentPlatformQwPlan qwPlan = new ContentPlatformQwPlan();
             qwPlan.setType(param.getType());
+            qwPlan.setSubChannel(param.getSubChannel());
             qwPlan.setScene(videoParam.getScene());
-            String pageUrl = messageAttachmentService.getPage(loginUser.getChannel(), "wxbdd2a2e93d9a6e25",
+            String carrierId = StringUtils.hasText(param.getSubChannel()) ? param.getSubChannel() : "wxbdd2a2e93d9a6e25";
+            String pageUrl = messageAttachmentService.getPage(loginUser.getChannel(), carrierId,
                     "dyyqw", "企微", QwPlanTypeEnum.from(param.getType()).getDescription(),
                     "位置1", videoParam.getVideoId());
             String rootSourceId = MessageUtil.getRootSourceId(pageUrl);

+ 246 - 0
api-module/src/main/resources/mapper/contentplatform/ContentPlatformQwDataStatSubChannelMapper.xml

@@ -0,0 +1,246 @@
+<?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.piaoquan.api.dao.mapper.contentplatform.ContentPlatformQwDataStatSubChannelMapper">
+  <resultMap id="BaseResultMap" type="com.tzld.piaoquan.api.model.po.contentplatform.ContentPlatformQwDataStatSubChannel">
+    <id column="id" jdbcType="BIGINT" property="id" />
+    <result column="date_str" jdbcType="VARCHAR" property="dateStr" />
+    <result column="sub_channel" jdbcType="VARCHAR" property="subChannel" />
+    <result column="first_level_count" jdbcType="INTEGER" property="firstLevelCount" />
+    <result column="score" jdbcType="DOUBLE" property="score" />
+    <result column="create_account_id" jdbcType="BIGINT" property="createAccountId" />
+    <result column="create_timestamp" jdbcType="BIGINT" property="createTimestamp" />
+  </resultMap>
+  <sql id="Example_Where_Clause">
+    <where>
+      <foreach collection="oredCriteria" item="criteria" separator="or">
+        <if test="criteria.valid">
+          <trim prefix="(" prefixOverrides="and" suffix=")">
+            <foreach collection="criteria.criteria" item="criterion">
+              <choose>
+                <when test="criterion.noValue">
+                  and ${criterion.condition}
+                </when>
+                <when test="criterion.singleValue">
+                  and ${criterion.condition} #{criterion.value}
+                </when>
+                <when test="criterion.betweenValue">
+                  and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
+                </when>
+                <when test="criterion.listValue">
+                  and ${criterion.condition}
+                  <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
+                    #{listItem}
+                  </foreach>
+                </when>
+              </choose>
+            </foreach>
+          </trim>
+        </if>
+      </foreach>
+    </where>
+  </sql>
+  <sql id="Update_By_Example_Where_Clause">
+    <where>
+      <foreach collection="example.oredCriteria" item="criteria" separator="or">
+        <if test="criteria.valid">
+          <trim prefix="(" prefixOverrides="and" suffix=")">
+            <foreach collection="criteria.criteria" item="criterion">
+              <choose>
+                <when test="criterion.noValue">
+                  and ${criterion.condition}
+                </when>
+                <when test="criterion.singleValue">
+                  and ${criterion.condition} #{criterion.value}
+                </when>
+                <when test="criterion.betweenValue">
+                  and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
+                </when>
+                <when test="criterion.listValue">
+                  and ${criterion.condition}
+                  <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
+                    #{listItem}
+                  </foreach>
+                </when>
+              </choose>
+            </foreach>
+          </trim>
+        </if>
+      </foreach>
+    </where>
+  </sql>
+  <sql id="Base_Column_List">
+    id, date_str, sub_channel, first_level_count, score, create_account_id, create_timestamp
+  </sql>
+  <select id="selectByExample" parameterType="com.tzld.piaoquan.api.model.po.contentplatform.ContentPlatformQwDataStatSubChannelExample" resultMap="BaseResultMap">
+    select
+    <if test="distinct">
+      distinct
+    </if>
+    <include refid="Base_Column_List" />
+    from content_platform_qw_datastat_sub_channel
+    <if test="_parameter != null">
+      <include refid="Example_Where_Clause" />
+    </if>
+    <if test="orderByClause != null">
+      order by ${orderByClause}
+    </if>
+    <if test="page != null">
+      limit #{page.offset} , #{page.pageSize}
+    </if>
+  </select>
+  <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
+    select 
+    <include refid="Base_Column_List" />
+    from content_platform_qw_datastat_sub_channel
+    where id = #{id,jdbcType=BIGINT}
+  </select>
+  <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
+    delete from content_platform_qw_datastat_sub_channel
+    where id = #{id,jdbcType=BIGINT}
+  </delete>
+  <delete id="deleteByExample" parameterType="com.tzld.piaoquan.api.model.po.contentplatform.ContentPlatformQwDataStatSubChannelExample">
+    delete from content_platform_qw_datastat_sub_channel
+    <if test="_parameter != null">
+      <include refid="Example_Where_Clause" />
+    </if>
+  </delete>
+  <insert id="insert" parameterType="com.tzld.piaoquan.api.model.po.contentplatform.ContentPlatformQwDataStatSubChannel">
+    insert into content_platform_qw_datastat_sub_channel (id, date_str, sub_channel, 
+      first_level_count, score, create_account_id, 
+      create_timestamp)
+    values (#{id,jdbcType=BIGINT}, #{dateStr,jdbcType=VARCHAR}, #{subChannel,jdbcType=VARCHAR}, 
+      #{firstLevelCount,jdbcType=INTEGER}, #{score,jdbcType=DOUBLE}, #{createAccountId,jdbcType=BIGINT}, 
+      #{createTimestamp,jdbcType=BIGINT})
+  </insert>
+  <insert id="insertSelective" parameterType="com.tzld.piaoquan.api.model.po.contentplatform.ContentPlatformQwDataStatSubChannel">
+    insert into content_platform_qw_datastat_sub_channel
+    <trim prefix="(" suffix=")" suffixOverrides=",">
+      <if test="id != null">
+        id,
+      </if>
+      <if test="dateStr != null">
+        date_str,
+      </if>
+      <if test="subChannel != null">
+        sub_channel,
+      </if>
+      <if test="firstLevelCount != null">
+        first_level_count,
+      </if>
+      <if test="score != null">
+        score,
+      </if>
+      <if test="createAccountId != null">
+        create_account_id,
+      </if>
+      <if test="createTimestamp != null">
+        create_timestamp,
+      </if>
+    </trim>
+    <trim prefix="values (" suffix=")" suffixOverrides=",">
+      <if test="id != null">
+        #{id,jdbcType=BIGINT},
+      </if>
+      <if test="dateStr != null">
+        #{dateStr,jdbcType=VARCHAR},
+      </if>
+      <if test="subChannel != null">
+        #{subChannel,jdbcType=VARCHAR},
+      </if>
+      <if test="firstLevelCount != null">
+        #{firstLevelCount,jdbcType=INTEGER},
+      </if>
+      <if test="score != null">
+        #{score,jdbcType=DOUBLE},
+      </if>
+      <if test="createAccountId != null">
+        #{createAccountId,jdbcType=BIGINT},
+      </if>
+      <if test="createTimestamp != null">
+        #{createTimestamp,jdbcType=BIGINT},
+      </if>
+    </trim>
+  </insert>
+  <select id="countByExample" parameterType="com.tzld.piaoquan.api.model.po.contentplatform.ContentPlatformQwDataStatSubChannelExample" resultType="java.lang.Long">
+    select count(*) from content_platform_qw_datastat_sub_channel
+    <if test="_parameter != null">
+      <include refid="Example_Where_Clause" />
+    </if>
+  </select>
+  <update id="updateByExampleSelective" parameterType="map">
+    update content_platform_qw_datastat_sub_channel
+    <set>
+      <if test="record.id != null">
+        id = #{record.id,jdbcType=BIGINT},
+      </if>
+      <if test="record.dateStr != null">
+        date_str = #{record.dateStr,jdbcType=VARCHAR},
+      </if>
+      <if test="record.subChannel != null">
+        sub_channel = #{record.subChannel,jdbcType=VARCHAR},
+      </if>
+      <if test="record.firstLevelCount != null">
+        first_level_count = #{record.firstLevelCount,jdbcType=INTEGER},
+      </if>
+      <if test="record.score != null">
+        score = #{record.score,jdbcType=DOUBLE},
+      </if>
+      <if test="record.createAccountId != null">
+        create_account_id = #{record.createAccountId,jdbcType=BIGINT},
+      </if>
+      <if test="record.createTimestamp != null">
+        create_timestamp = #{record.createTimestamp,jdbcType=BIGINT},
+      </if>
+    </set>
+    <if test="_parameter != null">
+      <include refid="Update_By_Example_Where_Clause" />
+    </if>
+  </update>
+  <update id="updateByExample" parameterType="map">
+    update content_platform_qw_datastat_sub_channel
+    set id = #{record.id,jdbcType=BIGINT},
+      date_str = #{record.dateStr,jdbcType=VARCHAR},
+      sub_channel = #{record.subChannel,jdbcType=VARCHAR},
+      first_level_count = #{record.firstLevelCount,jdbcType=INTEGER},
+      score = #{record.score,jdbcType=DOUBLE},
+      create_account_id = #{record.createAccountId,jdbcType=BIGINT},
+      create_timestamp = #{record.createTimestamp,jdbcType=BIGINT}
+    <if test="_parameter != null">
+      <include refid="Update_By_Example_Where_Clause" />
+    </if>
+  </update>
+  <update id="updateByPrimaryKeySelective" parameterType="com.tzld.piaoquan.api.model.po.contentplatform.ContentPlatformQwDataStatSubChannel">
+    update content_platform_qw_datastat_sub_channel
+    <set>
+      <if test="dateStr != null">
+        date_str = #{dateStr,jdbcType=VARCHAR},
+      </if>
+      <if test="subChannel != null">
+        sub_channel = #{subChannel,jdbcType=VARCHAR},
+      </if>
+      <if test="firstLevelCount != null">
+        first_level_count = #{firstLevelCount,jdbcType=INTEGER},
+      </if>
+      <if test="score != null">
+        score = #{score,jdbcType=DOUBLE},
+      </if>
+      <if test="createAccountId != null">
+        create_account_id = #{createAccountId,jdbcType=BIGINT},
+      </if>
+      <if test="createTimestamp != null">
+        create_timestamp = #{createTimestamp,jdbcType=BIGINT},
+      </if>
+    </set>
+    where id = #{id,jdbcType=BIGINT}
+  </update>
+  <update id="updateByPrimaryKey" parameterType="com.tzld.piaoquan.api.model.po.contentplatform.ContentPlatformQwDataStatSubChannel">
+    update content_platform_qw_datastat_sub_channel
+    set date_str = #{dateStr,jdbcType=VARCHAR},
+      sub_channel = #{subChannel,jdbcType=VARCHAR},
+      first_level_count = #{firstLevelCount,jdbcType=INTEGER},
+      score = #{score,jdbcType=DOUBLE},
+      create_account_id = #{createAccountId,jdbcType=BIGINT},
+      create_timestamp = #{createTimestamp,jdbcType=BIGINT}
+    where id = #{id,jdbcType=BIGINT}
+  </update>
+</mapper>

+ 25 - 10
api-module/src/main/resources/mapper/contentplatform/ContentPlatformQwPlanMapper.xml

@@ -4,6 +4,7 @@
   <resultMap id="BaseResultMap" type="com.tzld.piaoquan.api.model.po.contentplatform.ContentPlatformQwPlan">
     <id column="id" jdbcType="BIGINT" property="id" />
     <result column="type" jdbcType="INTEGER" property="type" />
+    <result column="sub_channel" jdbcType="VARCHAR" property="subChannel" />
     <result column="scene" jdbcType="INTEGER" property="scene" />
     <result column="page_url" jdbcType="VARCHAR" property="pageUrl" />
     <result column="root_source_id" jdbcType="VARCHAR" property="rootSourceId" />
@@ -71,8 +72,8 @@
     </where>
   </sql>
   <sql id="Base_Column_List">
-    id, `type`, scene, page_url, root_source_id, `status`, create_account_id, create_timestamp, 
-    update_timestamp
+    id, `type`, sub_channel, scene, page_url, root_source_id, `status`, create_account_id, 
+    create_timestamp, update_timestamp
   </sql>
   <select id="selectByExample" parameterType="com.tzld.piaoquan.api.model.po.contentplatform.ContentPlatformQwPlanExample" resultMap="BaseResultMap">
     select
@@ -108,14 +109,14 @@
     </if>
   </delete>
   <insert id="insert" parameterType="com.tzld.piaoquan.api.model.po.contentplatform.ContentPlatformQwPlan">
-    insert into content_platform_qw_plan (id, `type`, scene, 
-      page_url, root_source_id, `status`, 
-      create_account_id, create_timestamp, update_timestamp
-      )
-    values (#{id,jdbcType=BIGINT}, #{type,jdbcType=INTEGER}, #{scene,jdbcType=INTEGER}, 
-      #{pageUrl,jdbcType=VARCHAR}, #{rootSourceId,jdbcType=VARCHAR}, #{status,jdbcType=INTEGER}, 
-      #{createAccountId,jdbcType=BIGINT}, #{createTimestamp,jdbcType=BIGINT}, #{updateTimestamp,jdbcType=BIGINT}
-      )
+    insert into content_platform_qw_plan (id, `type`, sub_channel, 
+      scene, page_url, root_source_id, 
+      `status`, create_account_id, create_timestamp, 
+      update_timestamp)
+    values (#{id,jdbcType=BIGINT}, #{type,jdbcType=INTEGER}, #{subChannel,jdbcType=VARCHAR}, 
+      #{scene,jdbcType=INTEGER}, #{pageUrl,jdbcType=VARCHAR}, #{rootSourceId,jdbcType=VARCHAR}, 
+      #{status,jdbcType=INTEGER}, #{createAccountId,jdbcType=BIGINT}, #{createTimestamp,jdbcType=BIGINT}, 
+      #{updateTimestamp,jdbcType=BIGINT})
   </insert>
   <insert id="insertSelective" parameterType="com.tzld.piaoquan.api.model.po.contentplatform.ContentPlatformQwPlan">
     insert into content_platform_qw_plan
@@ -126,6 +127,9 @@
       <if test="type != null">
         `type`,
       </if>
+      <if test="subChannel != null">
+        sub_channel,
+      </if>
       <if test="scene != null">
         scene,
       </if>
@@ -155,6 +159,9 @@
       <if test="type != null">
         #{type,jdbcType=INTEGER},
       </if>
+      <if test="subChannel != null">
+        #{subChannel,jdbcType=VARCHAR},
+      </if>
       <if test="scene != null">
         #{scene,jdbcType=INTEGER},
       </if>
@@ -193,6 +200,9 @@
       <if test="record.type != null">
         `type` = #{record.type,jdbcType=INTEGER},
       </if>
+      <if test="record.subChannel != null">
+        sub_channel = #{record.subChannel,jdbcType=VARCHAR},
+      </if>
       <if test="record.scene != null">
         scene = #{record.scene,jdbcType=INTEGER},
       </if>
@@ -223,6 +233,7 @@
     update content_platform_qw_plan
     set id = #{record.id,jdbcType=BIGINT},
       `type` = #{record.type,jdbcType=INTEGER},
+      sub_channel = #{record.subChannel,jdbcType=VARCHAR},
       scene = #{record.scene,jdbcType=INTEGER},
       page_url = #{record.pageUrl,jdbcType=VARCHAR},
       root_source_id = #{record.rootSourceId,jdbcType=VARCHAR},
@@ -240,6 +251,9 @@
       <if test="type != null">
         `type` = #{type,jdbcType=INTEGER},
       </if>
+      <if test="subChannel != null">
+        sub_channel = #{subChannel,jdbcType=VARCHAR},
+      </if>
       <if test="scene != null">
         scene = #{scene,jdbcType=INTEGER},
       </if>
@@ -267,6 +281,7 @@
   <update id="updateByPrimaryKey" parameterType="com.tzld.piaoquan.api.model.po.contentplatform.ContentPlatformQwPlan">
     update content_platform_qw_plan
     set `type` = #{type,jdbcType=INTEGER},
+      sub_channel = #{subChannel,jdbcType=VARCHAR},
       scene = #{scene,jdbcType=INTEGER},
       page_url = #{pageUrl,jdbcType=VARCHAR},
       root_source_id = #{rootSourceId,jdbcType=VARCHAR},

+ 29 - 0
api-module/src/main/resources/mapper/contentplatform/ext/ContentPlatformDataStatMapperExt.xml

@@ -129,6 +129,21 @@
         limit #{offset}, #{pageSize}
     </select>
 
+    <select id="getQwSubChannelDatastatCount" resultType="java.lang.Integer">
+        select count(1)
+        from content_platform_qw_datastat_sub_channel
+        where create_account_id = #{channel}
+    </select>
+
+    <select id="getQwSubChannelDatastatList"
+            resultType="com.tzld.piaoquan.api.model.po.contentplatform.ContentPlatformQwDataStatReplyTotal">
+        select date_str, sub_channel, first_level_count, score
+        from content_platform_qw_datastat_sub_channel
+        where channel = #{channel}
+        order by date_str desc
+        limit #{offset}, #{pageSize}
+    </select>
+
     <select id="getQwSceneDatastatCount" resultType="java.lang.Integer">
         select count(1)
         from (select cpqd.date_str
@@ -237,6 +252,16 @@
         </foreach>
     </insert>
 
+    <insert id="batchInsertQwDatastatSubChannel">
+        insert into content_platform_qw_datastat_sub_channel (date_str, sub_channel, first_level_count, score,
+                                                              create_account_id, create_timestamp)
+        values
+        <foreach collection="records" item="item" separator=",">
+            (#{item.dateStr}, #{item.subChannel}, #{item.firstLevelCount}, #{item.score}, #{item.createAccountId},
+             #{item.createTimestamp})
+        </foreach>
+    </insert>
+
     <select id="getQwTotalDatastatScoreList"
             resultType="com.tzld.piaoquan.api.model.po.contentplatform.ContentPlatformQwDataStatTotal">
         select cpa.channel, round(avg(cpqd.score), 2) as score
@@ -265,6 +290,10 @@
         delete from content_platform_qw_datastat_reply_total where date_str = #{dt}
     </delete>
 
+    <delete id="deleteQwDatastatSubChannel">
+        delete from content_platform_qw_datastat_sub_channel where date_str = #{dt}
+    </delete>
+
     <delete id="deleteGzhDatastatTotal">
         delete from content_platform_gzh_datastat_total where date_str = #{dt}
     </delete>

+ 8 - 2
api-module/src/main/resources/mapper/contentplatform/ext/ContentPlatformPlanMapperExt.xml

@@ -152,6 +152,9 @@
         <if test="param.scene != null">
             and scene = #{param.scene}
         </if>
+        <if test="param.subChannel != null and param.subChannel != ''">
+            and sub_channel like concat('%', #{param.subChannel}, '%')
+        </if>
         <if test="param.title != null and param.title != ''">
             and id in (select plan_id from content_platform_qw_plan_video where title like concat('%', #{param.title},
             '%'))
@@ -168,6 +171,9 @@
         <if test="param.scene != null">
             and scene = #{param.scene}
         </if>
+        <if test="param.subChannel != null and param.subChannel != ''">
+            and sub_channel like concat('%', #{param.subChannel}, '%')
+        </if>
         <if test="param.title != null and param.title != ''">
             and id in (select plan_id from content_platform_qw_plan_video where title like concat('%', #{param.title},
             '%'))
@@ -189,9 +195,9 @@
     </insert>
 
     <insert id="insertQwPlanReturnId" useGeneratedKeys="true" keyProperty="id">
-        insert into content_platform_qw_plan (`type`, scene, page_url, root_source_id, create_account_id,
+        insert into content_platform_qw_plan (`type`, sub_channel, scene, page_url, root_source_id, create_account_id,
                                               create_timestamp, update_timestamp)
-        values ( #{record.type}, #{record.scene}, #{record.pageUrl}, #{record.rootSourceId},
+        values (#{record.type}, #{record.subChannel}, #{record.scene}, #{record.pageUrl}, #{record.rootSourceId},
                 #{record.createAccountId}, #{record.createTimestamp}, #{record.updateTimestamp})
     </insert>
 

+ 1 - 0
api-module/src/main/resources/mybatis-api-contentPlatform-generator-config.xml

@@ -62,6 +62,7 @@
         <table tableName="content_platform_qw_datastat" domainObjectName="ContentPlatformQwDataStat" alias=""/>
         <table tableName="content_platform_qw_datastat_total" domainObjectName="ContentPlatformQwDataStatTotal" alias=""/>
         <table tableName="content_platform_qw_datastat_reply_total" domainObjectName="ContentPlatformQwDataStatReplyTotal" alias=""/>
+        <table tableName="content_platform_qw_datastat_sub_channel" domainObjectName="ContentPlatformQwDataStatSubChannel" alias=""/>
         <table tableName="content_platform_qw_plan" domainObjectName="ContentPlatformQwPlan" alias=""/>
         <table tableName="content_platform_qw_plan_video" domainObjectName="ContentPlatformQwPlanVideo" alias=""/>
         <table tableName="content_platform_verify_code" domainObjectName="ContentPlatformVerifyCode" alias=""/>

+ 3 - 0
common-module/src/main/java/com/tzld/piaoquan/growth/common/dao/mapper/UserWithTagMapper.java

@@ -2,6 +2,7 @@ package com.tzld.piaoquan.growth.common.dao.mapper;
 
 import com.tzld.piaoquan.growth.common.model.po.UserWithTag;
 import com.tzld.piaoquan.growth.common.model.po.UserWithTagExample;
+
 import java.util.List;
 
 import org.apache.ibatis.annotations.Mapper;
@@ -32,4 +33,6 @@ public interface UserWithTagMapper {
     int updateByPrimaryKeySelective(UserWithTag record);
 
     int updateByPrimaryKey(UserWithTag record);
+
+    List<Long> selectFilterUserList();
 }

+ 251 - 234
common-module/src/main/resources/mapper/UserWithTagMapper.xml

@@ -1,246 +1,263 @@
 <?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.piaoquan.growth.common.dao.mapper.UserWithTagMapper">
-  <resultMap id="BaseResultMap" type="com.tzld.piaoquan.growth.common.model.po.UserWithTag">
-    <id column="id" jdbcType="BIGINT" property="id" />
-    <result column="user_id" jdbcType="BIGINT" property="userId" />
-    <result column="tag_id" jdbcType="BIGINT" property="tagId" />
-    <result column="status" jdbcType="INTEGER" property="status" />
-    <result column="is_delete" jdbcType="INTEGER" property="isDelete" />
-    <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
-    <result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
-  </resultMap>
-  <sql id="Example_Where_Clause">
-    <where>
-      <foreach collection="oredCriteria" item="criteria" separator="or">
-        <if test="criteria.valid">
-          <trim prefix="(" prefixOverrides="and" suffix=")">
-            <foreach collection="criteria.criteria" item="criterion">
-              <choose>
-                <when test="criterion.noValue">
-                  and ${criterion.condition}
-                </when>
-                <when test="criterion.singleValue">
-                  and ${criterion.condition} #{criterion.value}
-                </when>
-                <when test="criterion.betweenValue">
-                  and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
-                </when>
-                <when test="criterion.listValue">
-                  and ${criterion.condition}
-                  <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
-                    #{listItem}
-                  </foreach>
-                </when>
-              </choose>
+    <resultMap id="BaseResultMap" type="com.tzld.piaoquan.growth.common.model.po.UserWithTag">
+        <id column="id" jdbcType="BIGINT" property="id"/>
+        <result column="user_id" jdbcType="BIGINT" property="userId"/>
+        <result column="tag_id" jdbcType="BIGINT" property="tagId"/>
+        <result column="status" jdbcType="INTEGER" property="status"/>
+        <result column="is_delete" jdbcType="INTEGER" property="isDelete"/>
+        <result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
+        <result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
+    </resultMap>
+    <sql id="Example_Where_Clause">
+        <where>
+            <foreach collection="oredCriteria" item="criteria" separator="or">
+                <if test="criteria.valid">
+                    <trim prefix="(" prefixOverrides="and" suffix=")">
+                        <foreach collection="criteria.criteria" item="criterion">
+                            <choose>
+                                <when test="criterion.noValue">
+                                    and ${criterion.condition}
+                                </when>
+                                <when test="criterion.singleValue">
+                                    and ${criterion.condition} #{criterion.value}
+                                </when>
+                                <when test="criterion.betweenValue">
+                                    and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
+                                </when>
+                                <when test="criterion.listValue">
+                                    and ${criterion.condition}
+                                    <foreach close=")" collection="criterion.value" item="listItem" open="("
+                                             separator=",">
+                                        #{listItem}
+                                    </foreach>
+                                </when>
+                            </choose>
+                        </foreach>
+                    </trim>
+                </if>
             </foreach>
-          </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>
+        </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>
-          </trim>
+        </where>
+    </sql>
+    <sql id="Base_Column_List">
+        id
+        , user_id, tag_id, `status`, is_delete, create_time, update_time
+    </sql>
+    <select id="selectByExample" parameterType="com.tzld.piaoquan.growth.common.model.po.UserWithTagExample"
+            resultMap="BaseResultMap">
+        select
+        <if test="distinct">
+            distinct
+        </if>
+        <include refid="Base_Column_List"/>
+        from we_com_user_with_tag
+        <if test="_parameter != null">
+            <include refid="Example_Where_Clause"/>
+        </if>
+        <if test="orderByClause != null">
+            order by ${orderByClause}
+        </if>
+        <if test="page != null">
+            limit #{page.offset} , #{page.pageSize}
         </if>
-      </foreach>
-    </where>
-  </sql>
-  <sql id="Base_Column_List">
-    id, user_id, tag_id, `status`, is_delete, create_time, update_time
-  </sql>
-  <select id="selectByExample" parameterType="com.tzld.piaoquan.growth.common.model.po.UserWithTagExample" resultMap="BaseResultMap">
-    select
-    <if test="distinct">
-      distinct
-    </if>
-    <include refid="Base_Column_List" />
-    from we_com_user_with_tag
-    <if test="_parameter != null">
-      <include refid="Example_Where_Clause" />
-    </if>
-    <if test="orderByClause != null">
-      order by ${orderByClause}
-    </if>
-    <if test="page != null">
-      limit #{page.offset} , #{page.pageSize}
-    </if>
-  </select>
-  <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
-    select 
-    <include refid="Base_Column_List" />
-    from we_com_user_with_tag
-    where id = #{id,jdbcType=BIGINT}
-  </select>
-  <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
-    delete from we_com_user_with_tag
-    where id = #{id,jdbcType=BIGINT}
-  </delete>
-  <delete id="deleteByExample" parameterType="com.tzld.piaoquan.growth.common.model.po.UserWithTagExample">
-    delete from we_com_user_with_tag
-    <if test="_parameter != null">
-      <include refid="Example_Where_Clause" />
-    </if>
-  </delete>
-  <insert id="insert" parameterType="com.tzld.piaoquan.growth.common.model.po.UserWithTag">
-    insert into we_com_user_with_tag (id, user_id, tag_id, 
-      `status`, is_delete, create_time, 
-      update_time)
-    values (#{id,jdbcType=BIGINT}, #{userId,jdbcType=BIGINT}, #{tagId,jdbcType=BIGINT}, 
-      #{status,jdbcType=INTEGER}, #{isDelete,jdbcType=INTEGER}, #{createTime,jdbcType=TIMESTAMP}, 
-      #{updateTime,jdbcType=TIMESTAMP})
-  </insert>
-  <insert id="insertSelective" parameterType="com.tzld.piaoquan.growth.common.model.po.UserWithTag">
-    insert into we_com_user_with_tag
-    <trim prefix="(" suffix=")" suffixOverrides=",">
-      <if test="id != null">
-        id,
-      </if>
-      <if test="userId != null">
-        user_id,
-      </if>
-      <if test="tagId != null">
-        tag_id,
-      </if>
-      <if test="status != null">
-        `status`,
-      </if>
-      <if test="isDelete != null">
-        is_delete,
-      </if>
-      <if test="createTime != null">
-        create_time,
-      </if>
-      <if test="updateTime != null">
-        update_time,
-      </if>
-    </trim>
-    <trim prefix="values (" suffix=")" suffixOverrides=",">
-      <if test="id != null">
-        #{id,jdbcType=BIGINT},
-      </if>
-      <if test="userId != null">
-        #{userId,jdbcType=BIGINT},
-      </if>
-      <if test="tagId != null">
-        #{tagId,jdbcType=BIGINT},
-      </if>
-      <if test="status != null">
-        #{status,jdbcType=INTEGER},
-      </if>
-      <if test="isDelete != null">
-        #{isDelete,jdbcType=INTEGER},
-      </if>
-      <if test="createTime != null">
-        #{createTime,jdbcType=TIMESTAMP},
-      </if>
-      <if test="updateTime != null">
-        #{updateTime,jdbcType=TIMESTAMP},
-      </if>
-    </trim>
-  </insert>
-  <select id="countByExample" parameterType="com.tzld.piaoquan.growth.common.model.po.UserWithTagExample" resultType="java.lang.Long">
-    select count(*) from we_com_user_with_tag
-    <if test="_parameter != null">
-      <include refid="Example_Where_Clause" />
-    </if>
-  </select>
-  <update id="updateByExampleSelective" parameterType="map">
-    update we_com_user_with_tag
-    <set>
-      <if test="record.id != null">
-        id = #{record.id,jdbcType=BIGINT},
-      </if>
-      <if test="record.userId != null">
+    </select>
+    <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
+        select
+        <include refid="Base_Column_List"/>
+        from we_com_user_with_tag
+        where id = #{id,jdbcType=BIGINT}
+    </select>
+    <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
+        delete
+        from we_com_user_with_tag
+        where id = #{id,jdbcType=BIGINT}
+    </delete>
+    <delete id="deleteByExample" parameterType="com.tzld.piaoquan.growth.common.model.po.UserWithTagExample">
+        delete from we_com_user_with_tag
+        <if test="_parameter != null">
+            <include refid="Example_Where_Clause"/>
+        </if>
+    </delete>
+    <insert id="insert" parameterType="com.tzld.piaoquan.growth.common.model.po.UserWithTag">
+        insert into we_com_user_with_tag (id, user_id, tag_id,
+                                          `status`, is_delete, create_time,
+                                          update_time)
+        values (#{id,jdbcType=BIGINT}, #{userId,jdbcType=BIGINT}, #{tagId,jdbcType=BIGINT},
+                #{status,jdbcType=INTEGER}, #{isDelete,jdbcType=INTEGER}, #{createTime,jdbcType=TIMESTAMP},
+                #{updateTime,jdbcType=TIMESTAMP})
+    </insert>
+    <insert id="insertSelective" parameterType="com.tzld.piaoquan.growth.common.model.po.UserWithTag">
+        insert into we_com_user_with_tag
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">
+                id,
+            </if>
+            <if test="userId != null">
+                user_id,
+            </if>
+            <if test="tagId != null">
+                tag_id,
+            </if>
+            <if test="status != null">
+                `status`,
+            </if>
+            <if test="isDelete != null">
+                is_delete,
+            </if>
+            <if test="createTime != null">
+                create_time,
+            </if>
+            <if test="updateTime != null">
+                update_time,
+            </if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">
+                #{id,jdbcType=BIGINT},
+            </if>
+            <if test="userId != null">
+                #{userId,jdbcType=BIGINT},
+            </if>
+            <if test="tagId != null">
+                #{tagId,jdbcType=BIGINT},
+            </if>
+            <if test="status != null">
+                #{status,jdbcType=INTEGER},
+            </if>
+            <if test="isDelete != null">
+                #{isDelete,jdbcType=INTEGER},
+            </if>
+            <if test="createTime != null">
+                #{createTime,jdbcType=TIMESTAMP},
+            </if>
+            <if test="updateTime != null">
+                #{updateTime,jdbcType=TIMESTAMP},
+            </if>
+        </trim>
+    </insert>
+    <select id="countByExample" parameterType="com.tzld.piaoquan.growth.common.model.po.UserWithTagExample"
+            resultType="java.lang.Long">
+        select count(*) from we_com_user_with_tag
+        <if test="_parameter != null">
+            <include refid="Example_Where_Clause"/>
+        </if>
+    </select>
+    <update id="updateByExampleSelective" parameterType="map">
+        update we_com_user_with_tag
+        <set>
+            <if test="record.id != null">
+                id = #{record.id,jdbcType=BIGINT},
+            </if>
+            <if test="record.userId != null">
+                user_id = #{record.userId,jdbcType=BIGINT},
+            </if>
+            <if test="record.tagId != null">
+                tag_id = #{record.tagId,jdbcType=BIGINT},
+            </if>
+            <if test="record.status != null">
+                `status` = #{record.status,jdbcType=INTEGER},
+            </if>
+            <if test="record.isDelete != null">
+                is_delete = #{record.isDelete,jdbcType=INTEGER},
+            </if>
+            <if test="record.createTime != null">
+                create_time = #{record.createTime,jdbcType=TIMESTAMP},
+            </if>
+            <if test="record.updateTime != null">
+                update_time = #{record.updateTime,jdbcType=TIMESTAMP},
+            </if>
+        </set>
+        <if test="_parameter != null">
+            <include refid="Update_By_Example_Where_Clause"/>
+        </if>
+    </update>
+    <update id="updateByExample" parameterType="map">
+        update we_com_user_with_tag
+        set id = #{record.id,jdbcType=BIGINT},
         user_id = #{record.userId,jdbcType=BIGINT},
-      </if>
-      <if test="record.tagId != null">
         tag_id = #{record.tagId,jdbcType=BIGINT},
-      </if>
-      <if test="record.status != null">
         `status` = #{record.status,jdbcType=INTEGER},
-      </if>
-      <if test="record.isDelete != null">
         is_delete = #{record.isDelete,jdbcType=INTEGER},
-      </if>
-      <if test="record.createTime != null">
         create_time = #{record.createTime,jdbcType=TIMESTAMP},
-      </if>
-      <if test="record.updateTime != null">
-        update_time = #{record.updateTime,jdbcType=TIMESTAMP},
-      </if>
-    </set>
-    <if test="_parameter != null">
-      <include refid="Update_By_Example_Where_Clause" />
-    </if>
-  </update>
-  <update id="updateByExample" parameterType="map">
-    update we_com_user_with_tag
-    set id = #{record.id,jdbcType=BIGINT},
-      user_id = #{record.userId,jdbcType=BIGINT},
-      tag_id = #{record.tagId,jdbcType=BIGINT},
-      `status` = #{record.status,jdbcType=INTEGER},
-      is_delete = #{record.isDelete,jdbcType=INTEGER},
-      create_time = #{record.createTime,jdbcType=TIMESTAMP},
-      update_time = #{record.updateTime,jdbcType=TIMESTAMP}
-    <if test="_parameter != null">
-      <include refid="Update_By_Example_Where_Clause" />
-    </if>
-  </update>
-  <update id="updateByPrimaryKeySelective" parameterType="com.tzld.piaoquan.growth.common.model.po.UserWithTag">
-    update we_com_user_with_tag
-    <set>
-      <if test="userId != null">
-        user_id = #{userId,jdbcType=BIGINT},
-      </if>
-      <if test="tagId != null">
-        tag_id = #{tagId,jdbcType=BIGINT},
-      </if>
-      <if test="status != null">
-        `status` = #{status,jdbcType=INTEGER},
-      </if>
-      <if test="isDelete != null">
-        is_delete = #{isDelete,jdbcType=INTEGER},
-      </if>
-      <if test="createTime != null">
-        create_time = #{createTime,jdbcType=TIMESTAMP},
-      </if>
-      <if test="updateTime != null">
-        update_time = #{updateTime,jdbcType=TIMESTAMP},
-      </if>
-    </set>
-    where id = #{id,jdbcType=BIGINT}
-  </update>
-  <update id="updateByPrimaryKey" parameterType="com.tzld.piaoquan.growth.common.model.po.UserWithTag">
-    update we_com_user_with_tag
-    set user_id = #{userId,jdbcType=BIGINT},
-      tag_id = #{tagId,jdbcType=BIGINT},
-      `status` = #{status,jdbcType=INTEGER},
-      is_delete = #{isDelete,jdbcType=INTEGER},
-      create_time = #{createTime,jdbcType=TIMESTAMP},
-      update_time = #{updateTime,jdbcType=TIMESTAMP}
-    where id = #{id,jdbcType=BIGINT}
-  </update>
+        update_time = #{record.updateTime,jdbcType=TIMESTAMP}
+        <if test="_parameter != null">
+            <include refid="Update_By_Example_Where_Clause"/>
+        </if>
+    </update>
+    <update id="updateByPrimaryKeySelective" parameterType="com.tzld.piaoquan.growth.common.model.po.UserWithTag">
+        update we_com_user_with_tag
+        <set>
+            <if test="userId != null">
+                user_id = #{userId,jdbcType=BIGINT},
+            </if>
+            <if test="tagId != null">
+                tag_id = #{tagId,jdbcType=BIGINT},
+            </if>
+            <if test="status != null">
+                `status` = #{status,jdbcType=INTEGER},
+            </if>
+            <if test="isDelete != null">
+                is_delete = #{isDelete,jdbcType=INTEGER},
+            </if>
+            <if test="createTime != null">
+                create_time = #{createTime,jdbcType=TIMESTAMP},
+            </if>
+            <if test="updateTime != null">
+                update_time = #{updateTime,jdbcType=TIMESTAMP},
+            </if>
+        </set>
+        where id = #{id,jdbcType=BIGINT}
+    </update>
+    <update id="updateByPrimaryKey" parameterType="com.tzld.piaoquan.growth.common.model.po.UserWithTag">
+        update we_com_user_with_tag
+        set user_id     = #{userId,jdbcType=BIGINT},
+            tag_id      = #{tagId,jdbcType=BIGINT},
+            `status`    = #{status,jdbcType=INTEGER},
+            is_delete   = #{isDelete,jdbcType=INTEGER},
+            create_time = #{createTime,jdbcType=TIMESTAMP},
+            update_time = #{updateTime,jdbcType=TIMESTAMP}
+        where id = #{id,jdbcType=BIGINT}
+    </update>
+
+    <select id="selectFilterUserList" resultType="java.lang.Long">
+        select t1.user_id
+        from we_com_staff_with_user t1
+                 left join we_com_user_with_tag t2 on t1.user_id = t2.user_id
+        where staff_id in (
+                           39, 40, 41
+            )
+          and t2.tag_id = 39
+          and t2.create_time > '2025-05-16'
+    </select>
 </mapper>

+ 16 - 4
offline-module/src/main/java/com/tzld/piaoquan/offline/job/WeComSpecialDataJob.java

@@ -7,10 +7,7 @@ import com.google.common.collect.Lists;
 import com.tzld.piaoquan.growth.common.common.constant.MessageConstant;
 import com.tzld.piaoquan.growth.common.common.enums.MessageAttachmentTypeEnum;
 import com.tzld.piaoquan.growth.common.common.enums.PreSpecialStatusEnum;
-import com.tzld.piaoquan.growth.common.dao.mapper.PreSpecialSendMessageMapper;
-import com.tzld.piaoquan.growth.common.dao.mapper.SpecialSendMessageMapper;
-import com.tzld.piaoquan.growth.common.dao.mapper.StaffMapper;
-import com.tzld.piaoquan.growth.common.dao.mapper.WeComUserMapper;
+import com.tzld.piaoquan.growth.common.dao.mapper.*;
 import com.tzld.piaoquan.growth.common.model.po.*;
 import com.tzld.piaoquan.growth.common.service.MessageAttachmentService;
 import com.tzld.piaoquan.growth.common.service.MessageService;
@@ -55,6 +52,9 @@ public class WeComSpecialDataJob {
     @Autowired
     private PreSpecialSendMessageMapper preSpecialSendMessageMapper;
 
+    @Autowired
+    UserWithTagMapper userWithTagMapper;
+
     //发送小程序标题限制字节数
     private static final int MAX_BYTES = 64;
 
@@ -108,9 +108,13 @@ public class WeComSpecialDataJob {
     public void defaultSpecialAssembleSendMessage(Long preId, Long staffId, Integer pageNum, Integer pageSize,
                                                   byte groupMsgDisabled, String attachmentIds, String content, String date) {
         List<Long> filterTagId = weComUserService.getFilterTagId();
+        List<Long> filterUserList = userWithTagMapper.selectFilterUserList();
         List<WeComUser> weComUserList = weComUserMapper.selectUserList(staffId, groupMsgDisabled, filterTagId, (pageNum - 1) * pageSize, pageSize);
         //落库逻辑
         for (WeComUser weComUser : weComUserList) {
+            if (filterUserList.contains(weComUser.getId())) {
+                continue;
+            }
             SpecialSendMessage specialSendMessage = new SpecialSendMessage();
             specialSendMessage.setStaffId(staffId);
             specialSendMessage.setUserId(weComUser.getId());
@@ -127,11 +131,15 @@ public class WeComSpecialDataJob {
     }
 
     public void tagSpecialAssembleSendMessage(Long preId, Long staffId, String attachmentIds, String content, String date, Long tagId, Integer gender) {
+        List<Long> filterUserList = userWithTagMapper.selectFilterUserList();
         List<WeComUser> weComUsers = weComUserMapper.selectByTagUserList(tagId);
         if (CollectionUtils.isEmpty(weComUsers)) {
             return;
         }
         for (WeComUser weComUser : weComUsers) {
+            if (filterUserList.contains(weComUser.getId())) {
+                continue;
+            }
             if (gender != null && !gender.equals(weComUser.getGender())) {
                 continue;
             }
@@ -163,9 +171,13 @@ public class WeComSpecialDataJob {
     public void genderSpecialAssembleSendMessage(Long preId, Long staffId, byte groupMsgDisabled, String attachmentIds,
                                                  String content, String date, Integer gender) {
         List<Long> filterTagId = weComUserService.getFilterTagId();
+        List<Long> filterUserList = userWithTagMapper.selectFilterUserList();
         List<WeComUser> weComUserList = weComUserMapper.selectByGenderUserList(staffId, groupMsgDisabled, filterTagId, gender);
         //落库逻辑
         for (WeComUser weComUser : weComUserList) {
+            if (filterUserList.contains(weComUser.getId())) {
+                continue;
+            }
             SpecialSendMessage specialSendMessage = new SpecialSendMessage();
             specialSendMessage.setStaffId(staffId);
             specialSendMessage.setUserId(weComUser.getId());