Browse Source

Merge branch 'master' of http://git.tjyourong.com.cn/ctop/adsp-cloud

yumeng 3 years ago
parent
commit
1ac9081abf
18 changed files with 687 additions and 169 deletions
  1. 1 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java
  2. 5 0
      jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/ai/entity/AiKuaishouAccountAutoStrategy.java
  3. 2 1
      jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/ai/entity/AiKuaishouCreativeLevelOperationRecord.java
  4. 132 75
      jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/ai/service/impl/AiKuaishouAccountAutoDoServiceImpl.java
  5. 3 5
      jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/batch/controller/KuaiShouGroupTemplateController.java
  6. 35 1
      jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/batch/controller/KuaiShouTitleCollectionController.java
  7. 2 2
      jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/batch/mapper/KuaiShouGroupTemplateMapper.java
  8. 2 0
      jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/batch/mapper/KuaiShouVideoGetMapper.java
  9. 6 5
      jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/batch/mapper/xml/KuaiShouGroupTemplateMapper.xml
  10. 14 0
      jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/batch/mapper/xml/KuaiShouVideoGetMapper.xml
  11. 2 1
      jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/batch/service/IKuaiShouGroupTemplateService.java
  12. 2 0
      jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/batch/service/IKuaiShouVideoGetService.java
  13. 254 29
      jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/batch/service/impl/KuaiShouGroupTemplateServiceImpl.java
  14. 5 0
      jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/batch/service/impl/KuaiShouVideoGetServiceImpl.java
  15. 1 0
      jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/batch/service/impl/KuaishouInterfaceServiceImpl.java
  16. 8 1
      jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/channel/mapper/KuaishouChannelMapper.java
  17. 105 5
      jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/channel/mapper/xml/KuaishouChannelMapper.xml
  18. 108 44
      jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/channel/service/impl/KuaishouChannelServiceImpl.java

+ 1 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java

@@ -239,6 +239,7 @@ public class ShiroConfig {
         filterChainDefinitionMap.put("/cwjsSaleAssistantInfo/**", "anon");
         filterChainDefinitionMap.put("/overView/**", "anon");
         filterChainDefinitionMap.put("/agent/**", "anon");
+        filterChainDefinitionMap.put("/auto/**", "anon");
         filterChainDefinitionMap.put("/task/kuaishouHostingTask/**", "anon");
         filterChainDefinitionMap.put("/audienceReport/**", "anon");
 

+ 5 - 0
jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/ai/entity/AiKuaishouAccountAutoStrategy.java

@@ -274,6 +274,11 @@ public class AiKuaishouAccountAutoStrategy {
     @Excel(name = "封面广告语标题", width = 15)
     @ApiModelProperty(value = "封面广告语标题")
     private String stickerTitle;
+
+    /**
+     * 行为意向-系统优选,0关闭,1开启
+     */
+    private Integer intentionTarget;
     /**
      * 贴纸样式类型
      */

+ 2 - 1
jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/ai/entity/AiKuaishouCreativeLevelOperationRecord.java

@@ -162,12 +162,13 @@ public class AiKuaishouCreativeLevelOperationRecord {
 
     }
 
-    public AiKuaishouCreativeLevelOperationRecord(AiKuaishouAccountAutoStrategy strategy, Integer creativeCode, JSONObject creativeParams, String creativeMessage, Long unitId, String uuid) {
+    public AiKuaishouCreativeLevelOperationRecord(AiKuaishouAccountAutoStrategy strategy, Integer creativeCode, JSONObject creativeParams, String creativeMessage,Long newCampaignId, Long unitId, String uuid) {
         BeanUtils.copyProperties(strategy, this);
         this.status = creativeCode;
         this.description = creativeParams.getString("description");
         this.photoId = creativeParams.getString("photo_id");
         this.message = creativeMessage;
+        this.campaignId = newCampaignId;
         this.unitId = unitId;
         this.aiStrategyUuid = uuid;
         this.createTime = new Date();

+ 132 - 75
jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/ai/service/impl/AiKuaishouAccountAutoDoServiceImpl.java

@@ -187,6 +187,7 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
             unitNum = unitNum - customUnitCnt;
         }
         if (unitNum <= 0) {
+            log.info("今日创建已达标");
             return;
         }
         log.info("----- (自定义)账户:{},已建组数:{};剩余待建组数:{}", strategy.getAccountId(), customUnitCnt, unitNum);
@@ -270,8 +271,9 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
             KuaishouChannel usedchannel = null;
             try {
                 KuaishouChannel channel = null;
-                Integer useChannel = Check.isNull(strategy.getUseChannel()) ? 0 : strategy.getUseChannel();//0不使用,1使用
-                if (useChannel == 1) {
+                //0不使用,1使用
+                Integer useChannel = Check.isNull(strategy.getUseChannel()) ? 0 : strategy.getUseChannel();
+                if (useChannel == 1 && !"group".equals(level)) {
                     /*获取渠道号*/
                     channel = getChannel(level, accountId, appName);
                     if (Check.isNull(channel)) {
@@ -283,6 +285,8 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
                 if (null == newCampaignId) {
                     return videoCnt;
                 }
+                //赋值本次执行可创建数
+                videoCnt = strategy.getToBeBuiltCnt();
                 log.info("---------获取计划成功,计划id:{}", newCampaignId);
                 // 1 :使用渠道号
                 if (useChannel == 1) {
@@ -298,6 +302,7 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
                                 log.error("****** 获取已创建的计划所使用的渠道号失败");
                                 return videoCnt;
                             }
+                            log.info("------因计划层级,更新为已创建的计划所使用的渠道号:{}", usedchannel.getChannelCode());
                         } else {
                             usedchannel = channel;
                         }
@@ -359,7 +364,7 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
                     AiKuaishouUnitLevelOperationRecord unitRecord = new AiKuaishouUnitLevelOperationRecord(strategy, unitParams, unitCode, unitMessage, strategyUuid, videoItem.getAutoTargetId(), channelId);
                     if (unitCode != 0) {
                         log.error("****** 账户({})组创建失败,入参:{},message:{}", accountId, unitParams, unitMessage);
-                        String redisKey = strategy.getAccountId() + "_" + newCampaignId + DateUtils.formatDate(new Date(), "yy-MMdd");
+                        String redisKey = strategy.getAccountId() + "_" + newCampaignId + DateUtils.formatDate(new Date(), "yyMMdd");
                         Integer redisCnt = (Integer) redisUtil.get(redisKey);
                         redisUtil.set(redisKey, redisCnt - 1, 100000L);
                         unitLevelOperationRecordService.saveOrUpdate(unitRecord);
@@ -377,7 +382,7 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
                     //获取创意参数
                     JSONObject creativeParams = getCreativeParams(token, unitId, videoItem, strategy, usedchannel, null);
                     //执行创建创意
-                    boolean flag = createCreative(token, creativeParams, strategy, unitId, strategyUuid);
+                    boolean flag = createCreative(token, creativeParams, strategy, newCampaignId, unitId, strategyUuid);
                     if (flag) {
                         //创意成功,则素材置为不可用,添加素材使用记录
                         updateVideoUsed(videoType, null, "custom", videoItem);
@@ -414,14 +419,14 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
     }
 
     /**
-     * 更新广告组数
+     * 更新广告组编号
      */
     private void updateVideoStatus(String key) {
         Integer unitCnt = (Integer) redisUtil.get(key);
         if (Check.isNull(unitCnt)) {
             redisUtil.set(key, 1, 100000L);
         } else {
-            redisUtil.set(key, unitCnt + 1, 100000L);
+            redisUtil.set(key, unitCnt - 1, 100000L);
         }
     }
 
@@ -476,6 +481,8 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
                 if (campaignId == null) {
                     continue;
                 }
+                //赋值本次执行可创建数
+                videoCnt = strategy.getToBeBuiltCnt();
                 /*根据匹配逻辑,定向包和素材进行匹配,获取匹配后的素材*/
                 getTargetsAndVideos(strategy, allVideos, videoKey, appId, campaignId, appInfo.getAppVersion(), 0);
             }
@@ -534,7 +541,7 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
                 //获取创意参数
                 JSONObject creativeParams = getCreativeParams(token, unitId, videoItem, strategy, null, videoItem.getAppVersion());
                 //执行创建创意
-                createCreative(token, creativeParams, strategy, unitId, strategyUuid);
+                createCreative(token, creativeParams, strategy, campaignId, unitId, strategyUuid);
                 if (videoCnt <= 0) {
                     removeRedisVideos(successVideoList, videoKey);
                     return 0;
@@ -575,6 +582,7 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
             unitNum = unitNum - programUnitCnt;
         }
         if (unitNum == 0) {
+            log.info("今日创建已达标");
             return;
         }
         log.info("----- (程序化)账户:{},已建组数:{};剩余待建组数:{}", strategy.getAccountId(), programUnitCnt, unitNum);
@@ -671,6 +679,8 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
                 if (null == newCampaignId) {
                     return videoCnt;
                 }
+                //赋值本次执行可创建数
+                videoCnt = strategy.getToBeBuiltCnt();
                 log.info("---------获取计划成功,计划id:{}", newCampaignId);
 
                 if (!Check.isNull(channel)) {
@@ -893,6 +903,8 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
                 if (campaignId == null) {
                     continue;
                 }
+                //赋值本次执行可创建数
+                videoCnt = strategy.getToBeBuiltCnt();
                 /*根据匹配逻辑,定向包和素材进行匹配,获取匹配后的素材*/
                 getProTargetsAndVideos(strategy, proVideos, programKey, 0, appId, campaignId, appInfo.getAppVersion());
             }
@@ -975,6 +987,7 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
         Long accountId = strategy.getAccountId();
         KuaishouChannel channel = null;
         /*获取组级渠道号*/
+         /*
         channel = getChannel("group", accountId, appName);
         if (Check.isNull(channel)) {
             log.error("****** 获取组级渠道号失败");
@@ -985,6 +998,7 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
         if (!Check.isNull(items) && !items.isEmpty()) {
             strategy.setMaterialKeyword(items.get(0).getKeyword());
         }
+        */
 
         //待建素材集 redis key值
         String date = DateUtils.formatDate(new Date());
@@ -1004,7 +1018,14 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
 
         //记录创建成功的素材,待最后执行删除redis
         List<AiKuaishouAccountAutoVideo> successVideoList = new ArrayList<>();
+        Integer unitCode = null;
+        String unitMessage = null;
         for (AiKuaishouAccountAutoVideo videoItem : targetsAndVideos) {
+            channel = getChannel("group", accountId, appName);
+            if (Check.isNull(channel)) {
+                log.error("****** 获取组级渠道号失败");
+                return videoCnt;
+            }
             boolean unitOverrun = getUnitOverrun(accountId);
             if (unitOverrun) {
                 log.error("****** 账户({})创建广告组超限", accountId);
@@ -1018,8 +1039,7 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
                 return 0;
             }
 
-            Integer unitCode = null;
-            String unitMessage = null;
+
             String unitName = getName(strategy.getGroupName(), strategy, videoType, videoItem.getPhotoName(), "unit", newCampaignId, videoItem.getAutoTargetId(), appId, channel);
             Result<Object> result = createUnitParams(token, newCampaignId, strategy, unitName, appId, channel, videoItem.getAutoTargetId());
             if (result.getCode() != CommonConstant.SC_OK_200) {
@@ -1054,7 +1074,7 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
             //获取创意参数
             JSONObject creativeParams = getCreativeParams(token, unitId, videoItem, strategy, channel, null);
             //执行创建创意
-            boolean flag = createCreative(token, creativeParams, strategy, unitId, strategyUuid);
+            boolean flag = createCreative(token, creativeParams, strategy, newCampaignId, unitId, strategyUuid);
             if (flag) {
                 //创意成功,则素材置为不可用,添加素材使用记录
                 updateVideoUsed(videoType, null, "custom", videoItem);
@@ -1066,7 +1086,7 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
             }
         }
         removeRedisVideos(successVideoList, videoKey);
-        if (videoCnt > 0) {
+        if (videoCnt > 0 && unitCode == 0) {
             return addCustomByGroupChannel(strategy, appName, videoType, token, newCampaignId, appId, videoCnt, strategyUuid);
         }
         return videoCnt;
@@ -1079,7 +1099,7 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
     private Integer addProgramByGroupChannel(AiKuaishouAccountAutoStrategy strategy, String appName, Integer videoType, CtopOauthToken token, Long newCampaignId, Long appId, Integer videoCnt, String uuid) throws Exception {
         Long accountId = strategy.getAccountId();
         /*获取组级渠道号*/
-        KuaishouChannel channel = getChannel("group", accountId, appName);
+        /*KuaishouChannel channel = getChannel("group", accountId, appName);
         if (Check.isNull(channel)) {
             log.error("****** 获取组级渠道号失败");
             return videoCnt;
@@ -1089,6 +1109,7 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
         if (!Check.isNull(items) && !items.isEmpty()) {
             strategy.setMaterialKeyword(items.get(0).getKeyword());
         }
+        */
         String date = DateUtils.formatDate(new Date());
 
         //程序化创建创意超限标识,redis key值
@@ -1103,21 +1124,25 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
             log.error("****** {}账户({})通过组级渠道号关键词{},未获取到素材(程序化)", date, accountId, strategy.getMaterialKeyword());
         } else {
             if (allVideos.size() >= 3) {
-                List<List<AiKuaishouAccountAutoVideo>> splitVideos = Lists.partition(allVideos, 10);
-                int size = splitVideos.size() - 1;
+                List<List<AiKuaishouAccountAutoVideo>> splitVideos = Lists.newArrayList(Lists.partition(allVideos, 10));
+                List<List<AiKuaishouAccountAutoVideo>> newVideos = new ArrayList<>();
+                for (List<AiKuaishouAccountAutoVideo> splitVideo : splitVideos) {
+                    newVideos.add(Lists.newArrayList(splitVideo));
+                }
+                int size = newVideos.size() - 1;
                 if (size > 0) {
                     //判断最后一个集合小于3
-                    List<AiKuaishouAccountAutoVideo> lastVideos = splitVideos.get(size);
+                    List<AiKuaishouAccountAutoVideo> lastVideos = newVideos.get(size);
                     if (lastVideos.size() < 3) {
                         //小于3 则去除
                         for (int i = 0; i < size; i++) {
-                            proVideos.add(splitVideos.get(i));
+                            proVideos.add(newVideos.get(i));
                         }
                     } else {
-                        proVideos = splitVideos;
+                        proVideos = newVideos;
                     }
                 } else {
-                    proVideos = splitVideos;
+                    proVideos = newVideos;
                 }
             }
         }
@@ -1130,6 +1155,8 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
 
         //记录创建成功的素材,待最后执行删除redis
         List<List<AiKuaishouAccountAutoVideo>> successVideoList = new ArrayList<>();
+        Integer unitCode = null;
+        String unitMessage = null;
         for (List<AiKuaishouAccountAutoVideo> videos : targetsAndVideos) {
             boolean unitOverrun = getUnitOverrun(accountId);
             if (unitOverrun) {
@@ -1137,6 +1164,12 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
                 removeProRedisVideos(successVideoList, videoKey);
                 return 0;
             }
+            /*获取组级渠道号*/
+            KuaishouChannel channel = getChannel("group", accountId, appName);
+            if (Check.isNull(channel)) {
+                log.error("****** 获取组级渠道号失败");
+                return videoCnt;
+            }
 
             Object redisObj = redisUtil.get(programKey);
             if (!Check.isNull(redisObj)) {
@@ -1148,8 +1181,7 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
                 }
             }
 
-            Integer unitCode = null;
-            String unitMessage = null;
+
             String unitName = getName(strategy.getGroupName(), strategy, videoType, null, "unit", newCampaignId, appId, videos.get(0).getAutoTargetId(), channel);
             Result<Object> result = createUnitParams(token, newCampaignId, strategy, unitName, appId, channel, videos.get(0).getAutoTargetId());
             if (result.getCode() != CommonConstant.SC_OK_200) {
@@ -1197,7 +1229,7 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
         }
         //删除已使用的素材
         removeProRedisVideos(successVideoList, videoKey);
-        if (videoCnt > 0) {
+        if (videoCnt > 0 && unitCode == 0) {
             return addProgramByGroupChannel(strategy, appName, videoType, token, newCampaignId, appId, videoCnt, uuid);
         }
         return videoCnt;
@@ -1511,18 +1543,16 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
         KuaishouChannel channel = null;
         try {
             channel = null;
-            if (("account".equals(level) || "plan".equals(level))) {
-                Result<Object> result = channelService.queryChannel(accountId, level, appName, null);
-                if (result.getCode() == 200) {
-                    channel = (KuaishouChannel) result.getResult();
-                    if (Check.isNull(channel)) {
-                        log.error("****** 账户({})未获取到渠道号,{}", accountId, result.getMessage());
-                    } else {
-                        log.info("------获取渠道号:{}", channel.getChannelCode());
-                    }
+            Result<Object> result = channelService.queryChannel(accountId, level, appName, null);
+            if (result.getCode() == 200) {
+                channel = (KuaishouChannel) result.getResult();
+                if (Check.isNull(channel)) {
+                    log.error("****** 账户({})未获取到渠道号,{}", accountId, result.getMessage());
                 } else {
-                    log.error("******  账户({})根据应用名:{},未查询渠道号!{}", accountId, appName, result.getMessage());
+                    log.info("------获取渠道号:{}", channel.getChannelCode());
                 }
+            } else {
+                log.error("******  账户({})根据应用名:{},未查询渠道号!{}", accountId, appName, result.getMessage());
             }
         } catch (Exception e) {
             e.printStackTrace();
@@ -1585,15 +1615,15 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
 
             //行动号召按钮
             if (!Check.isNull(strategy.getActionBarText())) {
-                programJson.put("action_bar", strategy.getActionBarText());
+                programJson.put("action_bar", getActionBar(strategy.getActionBarText()));
             }
 
             //第三方点击检测链接
             if (!Check.isNull(strategy.getClickTrackUrl())) {
                 programJson.put("click_url", strategy.getClickTrackUrl());
             }
-            if (!Check.isNull(channel) && !Check.isNull(channel.getActionbarClickUrl())) {
-                programJson.put("click_url", channel.getActionbarClickUrl());
+            if (!Check.isNull(channel) && !Check.isNull(channel.getClickTrackUrl())) {
+                programJson.put("click_url", channel.getClickTrackUrl());
             }
 
             //第三方 ActionBar 点击监控链接
@@ -1746,7 +1776,7 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
      */
     private Long getCampaignId(AiKuaishouAccountAutoStrategy strategy, CtopOauthToken token, Integer videoType, String uuid, KuaishouChannel channel) {
         String nowDate = DateUtils.getNowDate("yyyy-MM-dd") + " 00:00:01";
-        String typeNa = "程序化";
+        String typeNa = "程序化";
         //计划数
         Integer planCnt = strategy.getProgramPlanCnt();
         //组数
@@ -1754,7 +1784,7 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
         if (strategy.getUnitType() == 4) {
             planCnt = strategy.getCustomPlanCnt();
             unitCnt = strategy.getCustomUnitCnt();
-            typeNa = "自定义";
+            typeNa = "自定义";
         }
         List<JSONObject> datas = campaignService.getCampaignIdsByParameters(strategy.getAccountId(), typeNa, nowDate);
         int toBeBuiltCnt = 0;
@@ -1776,6 +1806,8 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
             //判断是否扔可创建计划
             if (planCnt > datas.size()) {
                 return createCampaign(strategy, token, videoType, uuid, channel);
+            } else {
+                log.info("当日创建量已达标");
             }
         } else {
             return createCampaign(strategy, token, videoType, uuid, channel);
@@ -1939,6 +1971,9 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
                 if (!Check.isNull(appId)) {
                     unitParams.put("app_id", appId);
                 }
+                if (!Check.isNull(channel) && !Check.isNull(channel.getAppId())) {
+                    unitParams.put("app_id", channel.getAppId());
+                }
                 //  url
                 if (!Check.isNull(strategy.getUrl())) {
                     unitParams.put("url", strategy.getUrl());
@@ -1947,6 +1982,9 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
                 if (!Check.isNull(strategy.getSchemaUri())) {
                     unitParams.put("schema_uri", strategy.getSchemaUri());
                 }
+                if (!Check.isNull(channel) && !Check.isNull(channel.getSchemaUri())) {
+                    unitParams.put("schema_uri", channel.getSchemaUri());
+                }
             }
             //投放开始时间
             if (!Check.isNull(strategy.getBeginTime())) {
@@ -1982,6 +2020,11 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
             if (!Check.isNull(strategy.getAutoTarget())) {
                 unitParams.put("auto_target", strategy.getAutoTarget());
             }
+            //行为意向-系统优选
+            if (!Check.isNull(strategy.getIntentionTarget()) && strategy.getIntentionTarget() != 0) {
+                unitParams.put("intention_target", true);
+            }
+
             //是否开启自动生成视频
             if (!Check.isNull(strategy.getAutoCreatePhoto())) {
                 unitParams.put("auto_create_photo", strategy.getAutoCreatePhoto());
@@ -2271,7 +2314,7 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
             if (Check.isNull(count) || count == 0) {
                 count = 1;
             }
-            //广告语集 
+            //广告语集
             JSONArray descList = JSONArray.parseArray(strategy.getDescription());
             JSONArray creatives = new JSONArray();
             for (int i = 0; i < count; i++) {
@@ -2286,7 +2329,7 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
                 //素材类型 1:竖版视频 2:横版视频
                 creative.put("creative_material_type", videoItem.getMaterialType());
                 //行动号召按钮文案
-                creative.put("action_bar_text", strategy.getActionBarText());
+                creative.put("action_bar_text", getActionBar(strategy.getActionBarText()));
                 //广告语
                 int index = new Random().nextInt(descList.size());
                 creative.put("description", descList.getString(index));
@@ -2334,7 +2377,7 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
     /**
      * 执行创建自定义创意
      */
-    private boolean createCreative(CtopOauthToken token, JSONObject creativeParams, AiKuaishouAccountAutoStrategy strategy, Long unitId, String uuid) {
+    private boolean createCreative(CtopOauthToken token, JSONObject creativeParams, AiKuaishouAccountAutoStrategy strategy, Long newCampaignId, Long unitId, String uuid) {
         try {
             Map<String, Object> creativeCreateResult = kuaishouInterfaceService.batchCreativeCreate(token.getAccessToken(), token.getAccountId(), creativeParams, 1, null);
             Integer creativeCode = (Integer) creativeCreateResult.get("code");
@@ -2347,7 +2390,7 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
             } else if (creativeCode == -1 && creativeMessage.contains("视频不存在")) {
                 updateService.updateUnitStatus(token.getAccessToken(), token.getAccountId(), unitId, 3, "e9ca23d68d884d4ebb19d07889727dae");
             }
-            AiKuaishouCreativeLevelOperationRecord record = new AiKuaishouCreativeLevelOperationRecord(strategy, creativeCode, creativeParams, creativeMessage, unitId, uuid);
+            AiKuaishouCreativeLevelOperationRecord record = new AiKuaishouCreativeLevelOperationRecord(strategy, creativeCode, creativeParams, creativeMessage, newCampaignId, unitId, uuid);
             if (creativeCode == 0) {
                 JSONArray addCreativeIds = (JSONArray) creativeCreateResult.get("ids");
                 for (int i = 0; i < addCreativeIds.size(); i++) {
@@ -2373,76 +2416,76 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
      */
     private String getName(String wildcard, AiKuaishouAccountAutoStrategy strategy, Integer videoType,
                            String materialName, String type, Long campaignId, Long appId, Long targetId, KuaishouChannel channel) {
-        if (wildcard.contains("{{渠道号}}") || wildcard.contains("{{渠道号名称}}")) {
+        if (wildcard.contains("-{{渠道号}}-") || wildcard.contains("-{{渠道号名称}}-")) {
             if (Check.isNull(channel)) {
-                wildcard = wildcard.replace("{{渠道号}}", "");
-                wildcard = wildcard.replace("{{渠道号名称}}", "");
+                wildcard = wildcard.replace("-{{渠道号}}-", "");
+                wildcard = wildcard.replace("-{{渠道号名称}}-", "");
             } else {
-                wildcard = wildcard.replace("{{渠道号}}", channel.getChannelCode());
-                wildcard = wildcard.replace("{{渠道号名称}}", channel.getChannelName());
+                wildcard = wildcard.replace("-{{渠道号}}-", channel.getChannelCode());
+                wildcard = wildcard.replace("-{{渠道号名称}}-", channel.getChannelName());
             }
         }
 
-        if (wildcard.contains("{{定向包名}}")) {
+        if (wildcard.contains("-{{定向包名}}-")) {
             AiKuaishouAccountAutoTarget templateTarget = autoTargetService.getById(targetId);
             if (!Check.isNull(templateTarget)) {
-                wildcard = wildcard.replace("{{定向包名}}", templateTarget.getTargetName());
+                wildcard = wildcard.replace("-{{定向包名}}-", templateTarget.getTargetName());
             } else {
-                wildcard = wildcard.replace("{{定向包名}}", "");
+                wildcard = wildcard.replace("-{{定向包名}}-", "");
             }
         }
 
-        if (wildcard.contains("{{应用名称}}") || wildcard.contains("{{应用标记}}") || wildcard.contains("{{应用包名}}")) {
+        if (wildcard.contains("-{{应用名称}}-") || wildcard.contains("-{{应用标记}}-") || wildcard.contains("-{{应用包名}}-")) {
             KuaiShouAppList getAppInfo = appListService.getAppInfo(strategy.getAccountId(), appId);
             if (!Check.isNull(getAppInfo)) {
-                wildcard = wildcard.replace("{{应用名称}}", getAppInfo.getAppName());
-                wildcard = wildcard.replace("{{应用标记}}", getAppInfo.getAppVersion());
-                wildcard = wildcard.replace("{{应用包名}}", getAppInfo.getPackageName());
+                wildcard = wildcard.replace("-{{应用名称}}-", getAppInfo.getAppName());
+                wildcard = wildcard.replace("-{{应用标记}}-", getAppInfo.getAppVersion());
+                wildcard = wildcard.replace("-{{应用包名}}-", getAppInfo.getPackageName());
             } else {
-                wildcard = wildcard.replace("{{应用名称}}", "");
-                wildcard = wildcard.replace("{{应用标记}}", "");
-                wildcard = wildcard.replace("{{应用包名}}", "");
+                wildcard = wildcard.replace("-{{应用名称}}-", "");
+                wildcard = wildcard.replace("-{{应用标记}}-", "");
+                wildcard = wildcard.replace("-{{应用包名}}-", "");
             }
         }
 
-        if (wildcard.contains("{{创意制作方式}}")) {
+        if (wildcard.contains("-{{创意制作方式}}-")) {
             if (strategy.getUnitType() == 4) {
-                wildcard = wildcard.replace("{{创意制作方式}}", "自定义");
+                wildcard = wildcard.replace("-{{创意制作方式}}-", "自定义");
             } else if (strategy.getUnitType() == 7) {
-                wildcard = wildcard.replace("{{创意制作方式}}", "程序化");
+                wildcard = wildcard.replace("-{{创意制作方式}}-", "程序化");
             }
         }
 
-        if (wildcard.contains("{{广告位置}}")) {
+        if (wildcard.contains("-{{广告位置}}-")) {
             String adsence = getAdSenceByParams(strategy.getSceneId());
-            wildcard = wildcard.replace("{{广告位置}}", adsence);
+            wildcard = wildcard.replace("-{{广告位置}}-", adsence);
         }
 
-        if (wildcard.contains("{{素材名称}}")) {
+        if (wildcard.contains("-{{素材名称}}-")) {
             if (Check.isNull(materialName)) {
-                wildcard = wildcard.replace("{{素材名称}}", "");
+                wildcard = wildcard.replace("-{{素材名称}}-", "");
             } else {
-                wildcard = wildcard.replace("{{素材名称}}", materialName);
+                wildcard = wildcard.replace("-{{素材名称}}-", materialName);
             }
         }
-        if (!wildcard.contains("{{自定义}}")) {
-            wildcard = wildcard + "-{{自定义}}";
+        if (!wildcard.contains("-{{自定义}}-")) {
+            wildcard = wildcard + "-{{自定义}}-";
         }
-        String nowDate = DateUtils.formatDate(new Date(), "yy-MMdd");
+        String nowDate = DateUtils.formatDate(new Date(), "yyMMdd");
         if ("plan".equals(type)) {
             //创意制作方式
             if (strategy.getUnitType() == 4) {
-                wildcard = wildcard.replace("{{自定义}}", "自定义");
+                wildcard = wildcard.replace("-{{自定义}}-", "自定义");
             } else {
-                wildcard = wildcard.replace("{{自定义}}", "程序化");
+                wildcard = wildcard.replace("-{{自定义}}-", "程序化");
             }
-            if (wildcard.contains("{{日期}}")) {
-                wildcard = wildcard.replace("{{日期}}", nowDate);
+            if (wildcard.contains("-{{日期}}-")) {
+                wildcard = wildcard.replace("-{{日期}}-", nowDate);
             } else {
                 wildcard = wildcard + "-" + nowDate;
             }
-            if (!wildcard.contains("{{序号}}")) {
-                wildcard = wildcard + "{{序号}}";
+            if (!wildcard.contains("-{{序号}}-")) {
+                wildcard = wildcard + "-{{序号}}-";
             }
             Integer count = 0;
             String redisKey = strategy.getAccountId() + "_planCnt";
@@ -2454,11 +2497,11 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
                 count = redisValue + 1;
                 redisUtil.set(redisKey, count);
             }
-            wildcard = wildcard.replace("{{序号}}", count + "");
+            wildcard = wildcard.replace("-{{序号}}-", count + "");
         } else if ("unit".equals(type)) {
             String targetName = KuaishouAutoTypeEnum.getNameByType(strategy.getUnitType().toString() + videoType.toString());
-            wildcard = wildcard.replace("{{自定义}}", targetName);
-            wildcard = wildcard.replace("{{日期}}", nowDate);
+            wildcard = wildcard.replace("-{{自定义}}-", targetName);
+            wildcard = wildcard.replace("-{{日期}}-", nowDate);
         }
         //组序号,必填
         if (!Check.isNull(campaignId)) {
@@ -2695,4 +2738,18 @@ public class AiKuaishouAccountAutoDoServiceImpl implements IAiKuaishouAccountAut
         }
         return upNewCnt;
     }
+
+    public static String getActionBar(String actionBarText) {
+        if (Check.isNull(actionBarText)) {
+            return null;
+        }
+        String[] split = actionBarText.split(",");
+        int i = getrandom(0, split.length - 1);
+        return split[i];
+    }
+
+    public static int getrandom(int start, int end) {
+        int num = (int) (Math.random() * (end - start + 1) + start);
+        return num;
+    }
 }

+ 3 - 5
jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/batch/controller/KuaiShouGroupTemplateController.java

@@ -110,16 +110,14 @@ public class KuaiShouGroupTemplateController {
      * @return
      */
     @GetMapping(value = "/getApiCreateCount")
-    public Result<Integer> getApiCreateCount(Long accountId) {
-        Result<Integer> result = new Result<>();
+    public Result<Object> getApiCreateCount(Long accountId) {
+        Result<Object> result = new Result<>();
         try {
             if (Check.isNull(accountId)) {
                 throw new Exception("accountId参数不能为空");
             }
             String date = DateUtils.getNowDate("yyyy-MM-dd");
-            Integer count = kuaiShouGroupTemplateService.getApiCreateCount(accountId, date);
-            result.setSuccess(true);
-            result.setResult(count);
+            return kuaiShouGroupTemplateService.getApiCreateCount(accountId, date);
         } catch (Exception e) {
             e.printStackTrace();
             result.setSuccess(false);

+ 35 - 1
jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/batch/controller/KuaiShouTitleCollectionController.java

@@ -3,6 +3,8 @@ package cn.com.ctop.kuaishou.modules.batch.controller;
 import cn.com.ctop.kuaishou.modules.batch.entity.KuaiShouTitleCollection;
 import cn.com.ctop.kuaishou.modules.batch.service.IKuaiShouTitleCollectionService;
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -19,7 +21,15 @@ import org.jeecgframework.poi.excel.entity.ExportParams;
 import org.jeecgframework.poi.excel.entity.ImportParams;
 import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.multipart.MultipartFile;
 import org.springframework.web.multipart.MultipartHttpServletRequest;
 import org.springframework.web.servlet.ModelAndView;
@@ -97,6 +107,30 @@ public class KuaiShouTitleCollectionController {
     }
 
     /**
+     * 添加
+     *
+     * @param kuaiShouTitleCollection
+     * @return
+     */
+    @PostMapping(value = "/addMore")
+    public Result<KuaiShouTitleCollection> addMore(@RequestBody JSONObject data) {
+        Result<KuaiShouTitleCollection> result = new Result<>();
+        try {
+            JSONArray titles = data.getJSONArray("titles");
+            KuaiShouTitleCollection kuaiShouTitleCollection = JSONObject.parseObject(data.toJSONString(), KuaiShouTitleCollection.class);
+            for (Object title : titles) {
+                kuaiShouTitleCollection.setTitle(title.toString());
+                kuaiShouTitleCollectionService.save(kuaiShouTitleCollection);
+            }
+            result.success("添加成功!");
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            result.error500("操作失败");
+        }
+        return result;
+    }
+
+    /**
      * 编辑
      *
      * @param kuaiShouTitleCollection

+ 2 - 2
jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/batch/mapper/KuaiShouGroupTemplateMapper.java

@@ -18,9 +18,9 @@ public interface KuaiShouGroupTemplateMapper extends BaseMapper<KuaiShouGroupTem
 
     JSONObject getMd5ByPhotoId(@Param("photoId") String photoId);
 
-    List<JSONObject> getImageListByMd5(@Param("md5") String md5,@Param("imageCount") Integer imageCount);
+    List<JSONObject> getImageListByMd5(@Param("md5") String md5, @Param("imageCount") Integer imageCount);
 
-    Integer getApiCreateCount(@Param("accountId") Long accountId, @Param("date") String date);
+    Integer getApiCreateCount(@Param("accountId") Long accountId, @Param("date") String date, @Param("unitType") Integer unitType);
 
     JSONObject getUrlByPhotoId(@Param("photoId") String photoId);
 

+ 2 - 0
jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/batch/mapper/KuaiShouVideoGetMapper.java

@@ -61,4 +61,6 @@ public interface KuaiShouVideoGetMapper extends BaseMapper<KuaiShouVideoGet> {
     List<JSONObject> getVideoListByDate(@Param("startDate") Date startDate,@Param("endDate") Date endDate);
 
     List<String> getDateList();
+
+    List<KuaiShouVideoGet> getVideoListByPhotoIds(@Param("photoIds") JSONArray photoIds,@Param("accountId")Long accountId);
 }

+ 6 - 5
jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/batch/mapper/xml/KuaiShouGroupTemplateMapper.xml

@@ -31,11 +31,12 @@
 
 
     <select id="getApiCreateCount" resultType="java.lang.Integer">
-    select count(1)
-    from
-    ctop_kuaishou_creative
-    where  account_id = #{accountId}
-    and DATE_FORMAT(creative_create_time,'%Y-%m-%d') = #{date}
+        select count(1)
+        from
+            ctop_kuaishou_group
+        where  account_id = #{accountId}
+          and unit_type = #{unitType}
+          and DATE_FORMAT(group_create_time,'%Y-%m-%d') =  #{date}
     </select>
 
     <select id="getUrlByPhotoId" resultType="com.alibaba.fastjson.JSONObject">

+ 14 - 0
jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/batch/mapper/xml/KuaiShouVideoGetMapper.xml

@@ -404,4 +404,18 @@
             #{videoGet.id}
         </foreach>
     </update>
+
+    <select id="getVideoListByPhotoIds" resultType="cn.com.ctop.kuaishou.modules.batch.entity.KuaiShouVideoGet">
+        SELECT
+            photo_id,
+            cover_url,
+            material_type
+        FROM ctop_kuaishou_video_get
+        WHERE account_id = #{accountId}
+          AND photo_id IN
+        <foreach item="phtotId" index="index" collection="photoIds" open="(" separator="," close=")">
+            #{phtotId}
+        </foreach>
+    </select>
+
 </mapper>

+ 2 - 1
jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/batch/service/IKuaiShouGroupTemplateService.java

@@ -3,6 +3,7 @@ package cn.com.ctop.kuaishou.modules.batch.service;
 import cn.com.ctop.kuaishou.modules.batch.entity.KuaiShouGroupTemplate;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.extension.service.IService;
+import org.jeecg.common.api.vo.Result;
 
 import java.util.List;
 
@@ -24,7 +25,7 @@ public interface IKuaiShouGroupTemplateService extends IService<KuaiShouGroupTem
      * @param accountId
      * @return
      */
-    Integer getApiCreateCount(Long accountId, String date);
+    Result<Object> getApiCreateCount(Long accountId, String date);
 
     /**
      * 通过photoId 获取 url

+ 2 - 0
jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/batch/service/IKuaiShouVideoGetService.java

@@ -66,4 +66,6 @@ public interface IKuaiShouVideoGetService extends IService<KuaiShouVideoGet> {
     List<JSONObject> getVideoListByDate(Date startDate, Date endDate);
 
     List<String> getDateList();
+
+    List<KuaiShouVideoGet> getVideoListByPhotoIds(JSONArray photoIds,Long accountId);
 }

+ 254 - 29
jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/batch/service/impl/KuaiShouGroupTemplateServiceImpl.java

@@ -3,22 +3,38 @@ package cn.com.ctop.kuaishou.modules.batch.service.impl;
 import cn.com.ctop.common.module.entity.CtopOauthToken;
 import cn.com.ctop.common.module.service.ICtopOauthTokenService;
 import cn.com.ctop.common.module.utils.Check;
+import cn.com.ctop.common.module.utils.HttpUtils;
+import cn.com.ctop.common.module.utils.KuaishouInterfaceConstant;
+import cn.com.ctop.common.module.utils.PropertiesUtils;
+import cn.com.ctop.kuaishou.modules.ai.service.IKuaishouLandpagePackageService;
 import cn.com.ctop.kuaishou.modules.batch.entity.KuaiShouGroupTemplate;
 import cn.com.ctop.kuaishou.modules.batch.entity.KuaiShouImageGet;
+import cn.com.ctop.kuaishou.modules.batch.entity.KuaiShouVideoGet;
 import cn.com.ctop.kuaishou.modules.batch.entity.KuaishouTemplateTarget;
 import cn.com.ctop.kuaishou.modules.batch.mapper.KuaiShouGroupTemplateMapper;
-import cn.com.ctop.kuaishou.modules.batch.service.*;
+import cn.com.ctop.kuaishou.modules.batch.service.IKuaiShouGroupTemplateService;
+import cn.com.ctop.kuaishou.modules.batch.service.IKuaiShouImageGetService;
+import cn.com.ctop.kuaishou.modules.batch.service.IKuaiShouMaterialUploadService;
+import cn.com.ctop.kuaishou.modules.batch.service.IKuaiShouVideoGetService;
+import cn.com.ctop.kuaishou.modules.batch.service.IKuaishouInterfaceService;
+import cn.com.ctop.kuaishou.modules.batch.service.IKuaishouTemplateTargetService;
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.google.common.collect.Lists;
 import lombok.extern.slf4j.Slf4j;
+import org.jeecg.common.api.vo.Result;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Random;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
@@ -44,7 +60,8 @@ public class KuaiShouGroupTemplateServiceImpl extends ServiceImpl<KuaiShouGroupT
     private IKuaiShouMaterialUploadService uploadService;
     @Autowired
     private IKuaishouTemplateTargetService templateTargetService;
-
+    @Autowired
+    private IKuaiShouVideoGetService kuaiShouVideoGetService;
     static ExecutorService executorService = Executors.newFixedThreadPool(5);
 
     /**
@@ -73,19 +90,30 @@ public class KuaiShouGroupTemplateServiceImpl extends ServiceImpl<KuaiShouGroupT
             throw new Exception("请选择需要创建的视频");
         }
 
+        Integer imageCount = requestJson.getInteger("imageCount");
+
         Integer createType = requestJson.getInteger("createType"); // 创建类型 0 单品 1 混搭
-        if (Check.isNull(createType)) {
-            throw new Exception("请选择创意创建方式混搭、单品");
-        }
+        Integer unitType = requestJson.getInteger("unitType"); // 7程序化。4自定义
+        List<List<String>> photoIdsList = null;
+        if (unitType == 4) {
+            if (Check.isNull(createType)) {
+                throw new Exception("请选择创意创建方式混搭、单品");
+            }
 
-        if (createType == 0 && createCount != photoArr.size()) {
-            throw new Exception("单品视频数量必须和创建数量保持一致");
-        }
+            if (createType == 0 && createCount != photoArr.size()) {
+                throw new Exception("单品视频数量必须和创建数量保持一致");
+            }
 
-        if (createType == 1 && createCount * 15 != photoArr.size()) {
-            throw new Exception("混搭视频数量必须和创建数量保持倍数关系");
+            if (createType == 1 && createCount * 15 != photoArr.size()) {
+                throw new Exception("混搭视频数量必须和创建数量保持倍数关系");
+            }
+        } else {
+            List<String> photoIds = JSONArray.parseObject(photoArr.toJSONString(), List.class);
+            photoIdsList = Lists.newArrayList(Lists.partition(photoIds, imageCount));
+            if (createCount != photoIdsList.size()) {
+                throw new Exception("程序化视频数量必须和创建数量保持倍数关系");
+            }
         }
-
         JSONObject returnJson = new JSONObject();
         String userId = requestJson.getString("userId");
         String unitName = requestJson.getString("unitName");
@@ -125,22 +153,23 @@ public class KuaiShouGroupTemplateServiceImpl extends ServiceImpl<KuaiShouGroupT
                 startNumber = requestJson.getInteger("startNumber");
             }
         }
-        Integer imageCount = requestJson.getInteger("imageCount");
 
         List<KuaiShouGroupTemplate> templates = new ArrayList<>();
         for (int i = 0; i < createCount; i++) {
             KuaiShouGroupTemplate template = new KuaiShouGroupTemplate();
             template.setCreateType(createType);
-            if (createType == 0) { // 创建方式为单品
+            if (!Check.isNull(createType) && createType == 0) { // 创建方式为单品
                 Long photoId = photoArr.getLong(i);
                 template.setPhotoId(photoId);
-            } else if (createType == 1) { // 创建方式为混搭
+            } else if (!Check.isNull(createType) && createType == 1) { // 创建方式为混搭
                 JSONArray photoIds = getPhotoIds(photoArr, i);
                 if (Check.isNull(photoIds)) {
                     log.error("根据下标未获取到详细信息");
                     continue;
                 }
                 template.setPhotoIds(photoIds.toJSONString());
+            } else {
+                template.setPhotoIds(photoIdsList.get(i).toString());
             }
             String name = "";
             if (!unitName.contains("{{序号}}")) {
@@ -365,9 +394,6 @@ public class KuaiShouGroupTemplateServiceImpl extends ServiceImpl<KuaiShouGroupT
         if (!Check.isNull(template.getDeepConversionBid())) {
             createUnitJson.put("deep_conversion_bid", template.getDeepConversionBid()); //深度转化目标出价
         }
-        if (!Check.isNull(template.getUnitType())) {
-            createUnitJson.put("unit_type", template.getUnitType()); //创意制作方式
-        }
         if (!Check.isNull(template.getBeginTime())) {
             createUnitJson.put("begin_time", template.getBeginTime()); //投放开始时间
         }
@@ -402,6 +428,10 @@ public class KuaiShouGroupTemplateServiceImpl extends ServiceImpl<KuaiShouGroupT
         if (!Check.isNull(template.getSpeed())) {
             createUnitJson.put("speed", template.getSpeed()); // 投放方式
         }
+        if (!Check.isNull(template.getUnitType())) {
+            createUnitJson.put("unit_type", template.getUnitType()); //创意制作方式
+        }
+
         Map<String, Object> groupMap = iKuaishouInterfaceService.adUnitCreate(token.getAccessToken(), accountId, createUnitJson, 1);
         updateTemplate = new KuaiShouGroupTemplate();
         updateTemplate.setId(template.getId());
@@ -410,13 +440,23 @@ public class KuaiShouGroupTemplateServiceImpl extends ServiceImpl<KuaiShouGroupT
             updateTemplate.setTaskStatus(2);
             Long unit = (Long) groupMap.get("unitId");
             updateTemplate.setUnitId((unit));
-            Thread thread = new Thread() {
-                @Override
-                public void run() {
-                    createCreative(token.getAccessToken(), unit, template);
-                }
-            };
-            thread.start();
+            if (template.getUnitType() == 4) {
+                Thread thread = new Thread() {
+                    @Override
+                    public void run() {
+                        createCreative(token.getAccessToken(), unit, template);
+                    }
+                };
+                thread.start();
+            } else {
+                Thread thread = new Thread() {
+                    @Override
+                    public void run() {
+                        createProgramCreative(token.getAccessToken(), unit, template);
+                    }
+                };
+                thread.start();
+            }
         } else {
             updateTemplate.setTaskStatus(3);
             updateTemplate.setReviewDetail((String) groupMap.get("message"));
@@ -564,8 +604,16 @@ public class KuaiShouGroupTemplateServiceImpl extends ServiceImpl<KuaiShouGroupT
      * @return
      */
     @Override
-    public Integer getApiCreateCount(Long accountId, String date) {
-        return groupTemplateMapper.getApiCreateCount(accountId, date);
+    public Result<Object> getApiCreateCount(Long accountId, String date) {
+        //自定义
+        Integer ctmCount = groupTemplateMapper.getApiCreateCount(accountId, date, 4);
+        //程序化
+        Integer pgdCount = groupTemplateMapper.getApiCreateCount(accountId, date, 7);
+        JSONObject obj = new JSONObject();
+        obj.put("ctmCount", ctmCount);
+        obj.put("pgdCount", pgdCount);
+        return Result.ok(obj);
+
     }
 
     /**
@@ -608,6 +656,7 @@ public class KuaiShouGroupTemplateServiceImpl extends ServiceImpl<KuaiShouGroupT
             createJson.put("creative_tag", JSONArray.parseArray(template.getCreativeTag()));
         }
 
+        JSONArray descriptionList = JSONArray.parseArray(template.getDescription());
         JSONArray creatives = new JSONArray();
         Integer createType = template.getCreateType();
         if (createType == 0) { // 单品
@@ -629,13 +678,14 @@ public class KuaiShouGroupTemplateServiceImpl extends ServiceImpl<KuaiShouGroupT
                 json.put("photo_id", template.getPhotoId());
                 json.put("creative_material_type", materialType);
                 json.put("action_bar_text", template.getActionBarText());
-                json.put("description", template.getDescription());
+                json.put("description", getOneDescription(descriptionList));
                 if (!Check.isNull(template.getSiteId())) {
                     json.put("site_id", template.getSiteId());
                 }
                 creatives.add(json);
             } else {
                 for (int i = 0; i < imageList.size(); i++) {
+
                     JSONObject imageJson = imageList.get(i);
                     if (Check.isNull(imageJson)) {
                         continue;
@@ -651,7 +701,7 @@ public class KuaiShouGroupTemplateServiceImpl extends ServiceImpl<KuaiShouGroupT
                     json.put("photo_id", template.getPhotoId());
                     json.put("creative_material_type", materialType);
                     json.put("action_bar_text", template.getActionBarText());
-                    json.put("description", template.getDescription());
+                    json.put("description", getOneDescription(descriptionList));
                     if (!Check.isNull(template.getSiteId())) {
                         json.put("site_id", template.getSiteId());
                     }
@@ -690,7 +740,7 @@ public class KuaiShouGroupTemplateServiceImpl extends ServiceImpl<KuaiShouGroupT
                 json.put("photo_id", photoId);
                 json.put("creative_material_type", materialType);
                 json.put("action_bar_text", template.getActionBarText());
-                json.put("description", template.getDescription());
+                json.put("description", getOneDescription(descriptionList));
                 if (!Check.isNull(template.getSiteId())) {
                     json.put("site_id", template.getSiteId());
                 }
@@ -711,6 +761,160 @@ public class KuaiShouGroupTemplateServiceImpl extends ServiceImpl<KuaiShouGroupT
         this.updateById(updateTemplate);
     }
 
+    private String getOneDescription(JSONArray descriptionList) {
+        if (!Check.isNull(descriptionList)) {
+            int number = new Random().nextInt(descriptionList.size());
+            return descriptionList.getString(number);
+        }
+        return null;
+    }
+
+    private void createProgramCreative(String accessToken, Long unitId, KuaiShouGroupTemplate template) {
+        KuaiShouGroupTemplate updateTemplate = new KuaiShouGroupTemplate();
+        updateTemplate.setId(template.getId());
+        updateTemplate.setCreativeStatus(1);
+        updateTemplate.setCreativeReviewDetail("创意创建中");
+        updateTemplate.setUnitId(unitId);
+        this.updateById(updateTemplate);
+        JSONObject createJson = new JSONObject();
+        Long accountId = template.getAccountId();
+        createJson.put("advertiser_id", accountId);
+        createJson.put("unit_id", unitId);
+        createJson.put("package_name", template.getCreativeName());
+
+        JSONArray photoIds = JSONArray.parseArray(template.getPhotoIds());
+        if (Check.isNull(photoIds)) {
+            updateTemplate.setCreativeStatus(3);
+            updateTemplate.setCreativeReviewDetail("未获取到PhotoIds");
+            this.updateById(updateTemplate);
+            return;
+        }
+        //素材列表
+        List<KuaiShouVideoGet> videos = kuaiShouVideoGetService.getVideoListByPhotoIds(photoIds, accountId);
+        if (Check.isNull(videos) || videos.isEmpty()) {
+            updateTemplate.setCreativeStatus(3);
+            updateTemplate.setCreativeReviewDetail("未获取到素材信息");
+            this.updateById(updateTemplate);
+            return;
+        }
+        // 程序化视频数
+        Integer imageCount = template.getImageCount();
+        if (imageCount < 3) {
+            log.error("视频数小于3个,不执行创建");
+            return;
+        }
+
+        //落地页 ID
+        if (!Check.isNull(template.getSiteId()) && !"-1".equals(template.getSiteId())) {
+            createJson.put("site_id", template.getSiteId());
+        }
+        //行动号召按钮
+        if (!Check.isNull(template.getActionBarText())) {
+            createJson.put("action_bar", template.getActionBarText());
+        }
+        //第三方点击检测链接
+        if (!Check.isNull(template.getClickTrackUrl())) {
+            createJson.put("click_url", template.getClickTrackUrl());
+        }
+        //第三方 ActionBar 点击监控链接
+        if (!Check.isNull(template.getActionbarClickUrl())) {
+            createJson.put("actionbar_click_url", template.getActionbarClickUrl());
+        }
+        //创意分类 与创意标签同时传或同时不传
+        if (!Check.isNull(template.getCreativeCategory())) {
+            createJson.put("creative_category", template.getCreativeCategory());
+            createJson.put("creative_tag", JSONArray.parseArray(template.getCreativeTag()));
+        }
+        //作品广告语
+        createJson.put("captions", getCaptions(template.getDescription()));
+
+        JSONArray photoList = new JSONArray();
+        for (KuaiShouVideoGet video : videos) {
+            JSONObject photo = new JSONObject();
+            photo.put("photo_id", video.getPhotoId());//视频 ID
+            photo.put("cover_image_token", null);//封面图片 token,通过上传图片接口获得,不传值则直接使用视频的首帧作为封面图片
+            photo.put("creative_material_type", video.getMaterialType());//1:竖版视频 2:横版视频
+            photoList.add(photo);
+        }
+        createJson.put("photo_list", photoList);
+        Map<String, Object> creativeMap = this.createProgramCreatives(accountId, accessToken, createJson, 1);
+        Integer code = (Integer) creativeMap.get("code");
+        if (code == 0) {
+            updateTemplate.setCreativeStatus(2);
+            updateTemplate.setCreativeReviewDetail("创建程序化2.0创意成功");
+        } else {
+            updateTemplate.setCreativeStatus(3);
+            updateTemplate.setCreativeReviewDetail((String) creativeMap.get("message"));
+        }
+        this.updateById(updateTemplate);
+    }
+
+    /**
+     * 创建程序化创意
+     */
+    private Map<String, Object> createProgramCreatives(Long accountId, String token, JSONObject creativeParams, int count) {
+        Map<String, Object> returnMap = new HashMap<>();
+        try {
+            Map<String, String> headers = new HashMap<>();
+            headers.put("Content-Type", "application/json");
+            headers.put("Access-Token", token);
+            String url = PropertiesUtils.getConfig("kuaishou_api_url") + KuaishouInterfaceConstant.PROGRAM_CREATE;
+            String result = HttpUtils.kuaiShouhttpPostRequest(url, creativeParams.toJSONString(), headers);
+            JSONObject resultJson = JSON.parseObject(result);
+            if (Check.isNull(resultJson)) {
+                log.error("程序化创意创意异常:api接口返回为空");
+                returnMap.put("code", -1);
+                returnMap.put("message", "程序化创意创意异常:api接口返回为空");
+                returnMap.put("success", false);
+                return returnMap;
+            }
+            Integer code = resultJson.getInteger("code");
+            String message = resultJson.getString("message");
+            Long unitId = creativeParams.getLong("unit_id");
+            if (code == 0) {
+                createLandPageAndUnit(creativeParams, resultJson.getJSONObject("data"));
+                returnMap.put("code", 0);
+                returnMap.put("message", "success");
+                returnMap.put("success", true);
+            } else {
+                log.error("批量2.0创建程序化创意失败,入参:{},返回结果:{}", creativeParams.toString(), resultJson.toString());
+                if ("系统错误".equals(message) && count <= 3) {
+                    log.info("第{}次重新创建程序化创意", count);
+                    //系统错误,则重新执行
+                    return createProgramCreatives(accountId, token, creativeParams, count + 1);
+                }
+                returnMap.put("code", -1);
+                returnMap.put("message", resultJson.getString("message"));
+                returnMap.put("success", false);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            log.error("执行创建程序化创意异常", e);
+            returnMap.put("code", -1);
+            returnMap.put("message", "执行创建程序化创意异常");
+            returnMap.put("success", false);
+        }
+        return returnMap;
+    }
+
+    /**
+     * 绑定落地页与广告组、创意的关系
+     */
+    @Autowired
+    private IKuaishouLandpagePackageService landpagePackageService;
+
+    private void createLandPageAndUnit(JSONObject programJson, JSONObject data) {
+        if (!Check.isNull(data) && !Check.isNull(programJson.getLong("site_id"))) {
+            Thread thread = new Thread() {
+                @Override
+                public void run() {
+                    landpagePackageService.createLandPageAndUnit(programJson.getLong("site_id"), data.getLong("creative_id"), programJson.getLong("unit_id"), programJson.getLong("advertiser_id"));
+                }
+            };
+            thread.start();
+        }
+    }
+
 
     private String getImageToken(String md5, Long accountId, String accessToken, String url) {
 
@@ -730,4 +934,25 @@ public class KuaiShouGroupTemplateServiceImpl extends ServiceImpl<KuaiShouGroupT
         return imageToken;
 
     }
+
+
+    /**
+     * 获取程序化广告语
+     */
+    private JSONArray getCaptions(String description) {
+        JSONArray jsonArray = JSONArray.parseArray(description);
+        if (jsonArray.size() <= 3) {
+            return jsonArray;
+        }
+        //重置顺序
+        Collections.shuffle(jsonArray);
+        JSONArray captions = new JSONArray();
+        for (int i = 0; i < jsonArray.size(); i++) {
+            captions.add(jsonArray.getString(i));
+            if (captions.size() == 3) {
+                break;
+            }
+        }
+        return captions;
+    }
 }

+ 5 - 0
jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/batch/service/impl/KuaiShouVideoGetServiceImpl.java

@@ -359,4 +359,9 @@ public class KuaiShouVideoGetServiceImpl extends ServiceImpl<KuaiShouVideoGetMap
     public List<String> getDateList() {
         return videoGetMapper.getDateList();
     }
+
+    @Override
+    public List<KuaiShouVideoGet> getVideoListByPhotoIds(JSONArray photoIds,Long accountId) {
+        return videoGetMapper.getVideoListByPhotoIds(photoIds, accountId);
+    }
 }

+ 1 - 0
jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/batch/service/impl/KuaishouInterfaceServiceImpl.java

@@ -3379,6 +3379,7 @@ public class KuaishouInterfaceServiceImpl implements IKuaishouInterfaceService {
                             appList.setImageToken(dataJson.getString("image_token"));
                             appList.setPackageName(dataJson.getString("package_name"));
                             appList.setReturnTime(DateUtils.timeStamp2Date(dataJson.getTimestamp("update_time")));
+                            appList.setAppPrivacyUrl(dataJson.getString("app_privacy_url"));
                             addList.add(appList);
                         }
                     }

+ 8 - 1
jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/channel/mapper/KuaishouChannelMapper.java

@@ -1,7 +1,6 @@
 package cn.com.ctop.kuaishou.modules.channel.mapper;
 
 import cn.com.ctop.kuaishou.modules.channel.entity.KuaishouChannel;
-import cn.com.ctop.kuaishou.modules.channel.entity.KuaishouChannelCreateStrategy;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
@@ -51,4 +50,12 @@ public interface KuaishouChannelMapper extends BaseMapper<KuaishouChannel> {
     List<JSONObject> queryChannelList(@Param("accountId") Long accountId, @Param("appName") String appName);
 
     List<KuaishouChannel> queryChannelListByAccount(@Param("accountId") Long accountId);
+
+    List<KuaishouChannel> getAccountLevelRepeatChannel(@Param("accountId") Long accountId, @Param("appName") String appName);
+
+    List<KuaishouChannel> getAccountLevelNoRepeatChannel(@Param("accountId") Long accountId, @Param("appName") String appName);
+
+    KuaishouChannel getChannelEntity(@Param("accountId") Long accountId);
+
+    List<KuaishouChannel> queryNoAccountLevelNoRepeatChannel(@Param("usageLevel") String usageLevel, @Param("accountId") Long accountId, @Param("appName") String appName);
 }

+ 105 - 5
jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/channel/mapper/xml/KuaishouChannelMapper.xml

@@ -131,6 +131,7 @@
         FROM `ctop_kuaishou_channel`
         WHERE account_id = #{accountId}
           AND state = 1
+          AND channel_state = 1
           AND id > #{usedId}
           AND usage_range = #{usageRange}
         ORDER BY channel_code, channel_number limit 10
@@ -146,6 +147,7 @@
         FROM `ctop_kuaishou_channel`
         WHERE account_id = #{accountId}
         AND state = 1
+        AND channel_state = 1
         <if test="isHaveItem != null">
             and is_have_item = #{isHaveItem}
         </if>
@@ -205,14 +207,109 @@
         <if test="usageTimes > 1">
             AND is_cycle = 1
           </if>
+        <if test="appName != null">
             AND app_id in (
                 SELECT DISTINCT app_id FROM ctop_kuaishou_channel_app_info where app_name = #{appName}  and app_id is not null
             )
+        </if>
             AND t1.usage_times = #{usageTimes}
             and t1.usage_level = #{usageLevel}
             ORDER BY t1.create_time,t1.channel_number
     </select>
 
+    <select id="getAccountLevelRepeatChannel" resultType="cn.com.ctop.kuaishou.modules.channel.entity.KuaishouChannel">
+        SELECT t1.id,
+               t1.channel_code,
+               t1.usage_level,
+               t1.usage_range,
+               t1.usage_times,
+               t1.is_have_item,
+               t1.channel_name,
+               t1.click_track_url,
+               t1.actionbar_click_url,
+               t1.schema_uri
+        FROM `ctop_kuaishou_channel` t1
+        LEFT JOIN ctop_kuaishou_channel_rel t2 ON t1.account_id = t2.account_id AND t1.channel_code = t2.channel_code
+        WHERE
+            t1.account_id = #{accountId}
+          AND t1.state = 1
+          AND t1.channel_state = 1
+          AND t1.app_id is not null
+          and t1.usage_level = 'account'
+        <if test="appName != null">
+            AND t1.app_id in (
+            SELECT DISTINCT app_id FROM ctop_kuaishou_channel_app_info where app_name = #{appName}  and app_id is not null
+            )
+        </if>
+        GROUP BY t1.channel_code
+        ORDER BY t1.create_time,t1.channel_number
+            LIMIT 100
+    </select>
+
+    <select id="getAccountLevelNoRepeatChannel" resultType="cn.com.ctop.kuaishou.modules.channel.entity.KuaishouChannel">
+        SELECT t1.id,
+               t1.channel_code,
+               t1.usage_level,
+               t1.usage_range,
+               t1.usage_times,
+               t1.is_have_item,
+               t1.channel_name,
+               t1.click_track_url,
+               t1.actionbar_click_url,
+               t1.schema_uri
+        FROM `ctop_kuaishou_channel` t1
+        WHERE
+            t1.account_id = #{accountId}
+          AND t1.state = 1
+          AND t1.channel_state = 1
+          AND app_id is not null
+          AND t1.channel_code not in (
+            SELECT channel_code FROM ctop_kuaishou_channel_rel WHERE account_id = #{accountId}  AND unit_id is not null
+        )
+        <if test="appName != null">
+            AND t1.app_id in (
+            SELECT DISTINCT app_id FROM ctop_kuaishou_channel_app_info WHERE app_name = #{appName}  AND app_id is not null
+            )
+        </if>
+        ORDER BY t1.create_time,t1.channel_number
+            LIMIT 100
+    </select>
+
+    <select id="queryNoAccountLevelNoRepeatChannel" resultType="cn.com.ctop.kuaishou.modules.channel.entity.KuaishouChannel">
+        SELECT t1.id,
+               t1.channel_code,
+               t1.usage_level,
+               t1.usage_range,
+               t1.usage_times,
+               t1.is_have_item,
+               t1.channel_name,
+               t1.click_track_url,
+               t1.actionbar_click_url,
+               t1.schema_uri
+        FROM `ctop_kuaishou_channel` t1
+        WHERE  t1.account_id = #{accountId}
+          AND t1.state = 1
+          AND t1.channel_state = 1
+          AND app_id is not null
+        <if test="appName != null">
+            AND t1.app_id in (
+            SELECT DISTINCT app_id FROM ctop_kuaishou_channel_app_info where app_name = #{appName}  and app_id is not null
+            )
+        </if>
+          AND t1.usage_times = 0
+          and t1.usage_level = #{usageLevel}
+        ORDER BY t1.create_time,t1.channel_number
+            LIMIT 100
+    </select>
+
+    <select id="getChannelEntity" resultType="cn.com.ctop.kuaishou.modules.channel.entity.KuaishouChannel">
+        SELECT *
+        FROM `ctop_kuaishou_channel`
+        WHERE account_id = #{accountId}
+          AND state = 1
+          AND channel_state = 1 LIMIT 1
+    </select>
+
     <select id="queryUsedLevel" resultType="java.lang.Integer">
         SELECT usage_times
         FROM `ctop_kuaishou_channel`
@@ -222,6 +319,7 @@
             #{item}
         </foreach>
         AND state = 1
+        AND channel_state = 1
         group by usage_times
     </select>
 
@@ -245,17 +343,18 @@
   <select id="queryChannelList" resultType="com.alibaba.fastjson.JSONObject">
       SELECT
           t1.id,
-          channel_code,
-          channel_name,
+          channel_code as 'channelCode',
+          channel_name as 'channelName',
           t1.url,
-          schema_uri,
-          click_track_url,
-          actionbar_click_url
+          schema_uri as 'schemaUri',
+          click_track_url as 'clickTrackUrl',
+          actionbar_click_url as 'actionbarClickUrl'
       FROM
           ctop_kuaishou_channel t1
               LEFT JOIN ctop_kuaishou_channel_app_info t2 ON t1.app_id = t2.app_id
       WHERE
           t1.state = 1
+        AND t1.channel_state = 1
         AND t1.account_id = #{accountId}
         AND t2.app_name = #{appName}
 
@@ -284,6 +383,7 @@
         WHERE t2.account_id = #{accountId}
           AND t2.usage_level = #{level}
           AND t2.state = 1
+          AND t2.channel_state = 1
           AND t1.campaign_id = #{campaignId} LIMIT 1
     </select>
 

+ 108 - 44
jeecg-boot-module-system/src/main/java/cn/com/ctop/kuaishou/modules/channel/service/impl/KuaishouChannelServiceImpl.java

@@ -168,16 +168,9 @@ public class KuaishouChannelServiceImpl extends ServiceImpl<KuaishouChannelMappe
      * 校验渠道号是否重复
      */
     private boolean checkChannelCode(KuaishouChannelCreateStrategy strategy) {
-        String numberValue = strategy.getNumberValue();
-        Integer min = null;
-        Integer max = null;
-        if (numberValue.contains("-")) {
-            String[] split = numberValue.split("-");
-            min = Integer.valueOf(split[0]);
-            max = Integer.valueOf(split[1]);
-            strategy.setNumberMin(min);
-            strategy.setNumberMax(max);
-        }
+        String numberValue = strategy.getNumberValue().trim();
+        Integer min = strategy.getNumberMin();
+        Integer max = strategy.getNumberMax();
 
         QueryWrapper<KuaishouChannelCreateStrategy> queryWrapper = new QueryWrapper<>();
         queryWrapper.eq("product_id", strategy.getProductId());
@@ -243,6 +236,15 @@ public class KuaishouChannelServiceImpl extends ServiceImpl<KuaishouChannelMappe
             queryWrapper.eq("account_id", strategy.getAccountId());
         }
         queryWrapper.eq("project_id", strategy.getProjectId());
+        Integer numberMin = 0;
+        Integer numberMax = 0;
+        if (strategy.getNumberValue().contains("-")) {
+            String[] split = strategy.getNumberValue().split("-");
+            numberMin = Integer.valueOf(split[0]);
+            numberMax = Integer.valueOf(split[1]);
+            strategy.setNumberMin(numberMin);
+            strategy.setNumberMax(numberMax);
+        }
         //查询是否已经创建过策略,若已创建则某些字段必须一致,比如是否循环、使用层级
         KuaishouChannelCreateStrategy one = channelCreateStrategyService.getOne(queryWrapper.last("limit 1"));
         if (!Check.isNull(one)) {
@@ -279,8 +281,6 @@ public class KuaishouChannelServiceImpl extends ServiceImpl<KuaishouChannelMappe
             if (!strategy.getNumberValue().contains("-")) {
                 return customizedCreate(strategy);
             }
-            Integer numberMin = strategy.getNumberMin();
-            Integer numberMax = strategy.getNumberMax();
             Integer usageRange = strategy.getUsageRange();
             if (usageRange == 2) {
                 /*==========================范围是 项目==========================*/
@@ -511,6 +511,18 @@ public class KuaishouChannelServiceImpl extends ServiceImpl<KuaishouChannelMappe
                     updateApp(strategy, app, token);
                 }
             }
+        }else{
+            KuaiShouAppList appInfo = kuaiShouAppListService.getAppInfo(strategy.getAccountId(), strategy.getAppId());
+            KuaishouChannelAppInfo channelAppInfo = new KuaishouChannelAppInfo();
+            BeanUtils.copyProperties(appInfo, channelAppInfo);
+            channelAppInfo.setState(1);
+            channelAppInfo.setUrl((String) appInfo.getUrl());
+            channelAppInfo.setUseSdk(0);
+            channelAppInfo.setAppIconUrl((String) appInfo.getAppIconUrl());
+            channelAppInfo.setId(null);
+            channelAppInfo.setType("check");
+            channelAppInfo.setRemark("选择原有App");
+            channelAppInfoService.save(channelAppInfo);
         }
     }
 
@@ -906,6 +918,14 @@ public class KuaishouChannelServiceImpl extends ServiceImpl<KuaishouChannelMappe
                 }
                 strategy.setCreateType(createType);
 
+                if (strategy.getNumberValue().contains("-")) {
+                    String[] split = strategy.getNumberValue().split("-");
+                    Integer numberMin = Integer.valueOf(split[0]);
+                    Integer numberMax = Integer.valueOf(split[1]);
+                    strategy.setNumberMin(numberMin);
+                    strategy.setNumberMax(numberMax);
+                }
+
                 QueryWrapper<KuaishouChannelCreateStrategy> queryWrapper = new QueryWrapper<>();
                 queryWrapper.eq("product_id", strategy.getProductId());
                 if (!Check.isNull(strategy.getAccountId())) {
@@ -949,36 +969,81 @@ public class KuaishouChannelServiceImpl extends ServiceImpl<KuaishouChannelMappe
 
     @Override
     public Result<Object> queryChannel(Long accountId, String level, String appName, String photoName) throws Exception {
-        //查询账户所有策略
-        List<Long> strategyIds = channelCreateStrategyService.queryAllIdByAccountId(accountId);
-        if (Check.isNull(strategyIds) || strategyIds.isEmpty()) {
-            return Result.error("渠道号获取失败,该账户没有创建过渠道号");
-        }
-        List<Integer> usageTimesTypes = channelMapper.queryUsedLevel(strategyIds);
-        if (Check.isNull(usageTimesTypes)) {
-            return Result.error("渠道号已无效");
+        KuaishouChannel one = channelMapper.getChannelEntity(accountId);
+        if (Check.isNull(one)) {
+            return Result.error("未查询到渠道号");
         }
-        for (Integer usageTimes : usageTimesTypes) {
-            //获取可用渠道号,筛查出一个返回给前端
-            List<KuaishouChannel> list = channelMapper.queryChannelByUsageTimes(usageTimes, level, strategyIds, appName);
-            if (Check.isNull(list)) {
-                continue;
+        //是否循环重复使用 0:否,1:是
+        Integer isCycle = one.getIsCycle();
+        if (isCycle == 0) {
+            if ("account".equals(level)) {
+                //账户层级   不可循环使用渠道号
+                List<KuaishouChannel> list = channelMapper.getAccountLevelNoRepeatChannel(accountId, appName);
+                KuaishouChannel channel = getValidChannel(list);
+                if (!Check.isNull(channel)) {
+                    return Result.ok(channel);
+                }
+            } else {
+                //获取可用渠道号,筛查出一个返回给前端
+                List<KuaishouChannel> list = channelMapper.queryNoAccountLevelNoRepeatChannel(level, accountId, appName);
+                KuaishouChannel channel = getValidChannel(list);
+                if (!Check.isNull(channel)) {
+                    return Result.ok(channel);
+                }
             }
-            for (KuaishouChannel channel : list) {
-                //1 关联单品,无单品则跳过
-                if (channel.getIsHaveItem() == 1) {
-                    List<KuaishouChannelItems> items = channelItemsRelService.queryItems(channel.getId());
-                    if (Check.isNull(items) || items.isEmpty()) {
-                        continue;
+        } else {
+            //循环使用逻辑
+            if ("account".equals(level)) {
+                //账户层级可循环使用渠道号
+                List<KuaishouChannel> list = channelMapper.getAccountLevelRepeatChannel(accountId,appName);
+                KuaishouChannel channel = getValidChannel(list);
+                if (!Check.isNull(channel)) {
+                    return Result.ok(channel);
+                }
+            } else {
+                //查询账户所有策略
+                List<Long> strategyIds = channelCreateStrategyService.queryAllIdByAccountId(accountId);
+                if (Check.isNull(strategyIds) || strategyIds.isEmpty()) {
+                    return Result.error("渠道号获取失败,该账户没有创建过渠道号");
+                }
+                List<Integer> usageTimesTypes = channelMapper.queryUsedLevel(strategyIds);
+                if (Check.isNull(usageTimesTypes)) {
+                    return Result.error("渠道号已无效");
+                }
+                for (Integer usageTimes : usageTimesTypes) {
+                    //获取可用渠道号,筛查出一个返回给前端
+                    List<KuaishouChannel> list = channelMapper.queryChannelByUsageTimes(usageTimes, level, strategyIds, appName);
+                    KuaishouChannel channel = getValidChannel(list);
+                    if (!Check.isNull(channel)) {
+                        return Result.ok(channel);
                     }
-                    channel.setItems(items);
                 }
-                return Result.ok(channel);
             }
         }
         return Result.error("查询失败");
     }
 
+    /**
+     * 筛选渠道号,给渠道号添加单品
+     */
+    private KuaishouChannel getValidChannel(List<KuaishouChannel> list) {
+        if (Check.isNull(list) || list.isEmpty()) {
+            return null;
+        }
+        for (KuaishouChannel channel : list) {
+            //1 关联单品,无单品则跳过
+            if (channel.getIsHaveItem() == 1) {
+                List<KuaishouChannelItems> items = channelItemsRelService.queryItems(channel.getId());
+                if (Check.isNull(items) || items.isEmpty()) {
+                    continue;
+                }
+                channel.setItems(items);
+            }
+            return channel;
+        }
+        return null;
+    }
+
     @Override
     public Result<Object> queryChannelLevel(JSONObject data) {
         Long accountId = data.getLong("accountId");
@@ -999,8 +1064,7 @@ public class KuaishouChannelServiceImpl extends ServiceImpl<KuaishouChannelMappe
     }
 
     @Override
-    public void callBackUpdateChannelRel(String level, String channelCode, Long accountId, Long planId, Long
-            groupId) {
+    public void callBackUpdateChannelRel(String level, String channelCode, Long accountId, Long planId, Long groupId) {
         try {
             QueryWrapper<KuaishouChannel> queryWrapper = new QueryWrapper<>();
             queryWrapper.eq("account_id", accountId);
@@ -1020,15 +1084,15 @@ public class KuaishouChannelServiceImpl extends ServiceImpl<KuaishouChannelMappe
                     rel.setUnitId(groupId);
                     rel.setUpdateTime(new Date());
                     channelRelService.save(rel);
-                    if ("plan".equals(level)) {
-                        Integer usageTimes = channelRelService.queryUsePlanCount(accountId, channelCode);
-                        one.setUsageTimes(usageTimes);
-                        this.saveOrUpdate(one);
-                    } else if ("group".equals(level)) {
-                        Integer usageTimes = channelRelService.queryUseGroupCount(accountId, channelCode);
-                        one.setUsageTimes(usageTimes);
-                        this.saveOrUpdate(one);
-                    }
+//                    if ("plan".equals(level)) {
+//                        Integer usageTimes = channelRelService.queryUsePlanCount(accountId, channelCode);
+//                        one.setUsageTimes(usageTimes);
+//                        this.saveOrUpdate(one);
+//                    } else if ("group".equals(level)) {
+                    Integer usageTimes = channelRelService.queryUseGroupCount(accountId, channelCode);
+                    one.setUsageTimes(usageTimes);
+                    this.saveOrUpdate(one);
+//                    }
                 }
             }
         } catch (Exception e) {