فهرست منبع

快手自动投放账户策略遗漏素材创建创意

syh 4 سال پیش
والد
کامیت
d671a3b2f1
33فایلهای تغییر یافته به همراه1235 افزوده شده و 159 حذف شده
  1. 2 2
      jeecg-boot-base-common/src/main/java/org/jeecg/common/util/MD5Util.java
  2. 1 1
      jeecg-boot-base-common/src/main/java/org/jeecg/common/util/PmsUtil.java
  3. 1 5
      jeecg-boot-base-common/src/main/java/org/jeecg/common/util/db/FreemarkerParseFactory.java
  4. 1 7
      jeecg-boot-base-common/src/main/java/org/jeecg/common/util/dynamic/db/FreemarkerParseFactory.java
  5. 2 2
      jeecg-boot-base-common/src/main/java/org/jeecg/common/util/oConvertUtils.java
  6. 8 2
      jeecg-boot-module-system/src/main/java/org/jeecg/modules/cas/util/XmlUtils.java
  7. 1 1
      jeecg-boot-module-system/src/main/java/org/jeecg/modules/system/controller/SysDepartController.java
  8. 9 1
      jeecg-boot-module-system/src/test/java/org/jeecg/SampleTest.java
  9. 7 7
      module-alarm/src/main/java/cn/com/ctop/alarm/modules/constant/MatchLogic.java
  10. 1 1
      module-common/src/main/java/cn/com/ctop/common/module/enums/SceneIdEnum.java
  11. 3 3
      module-common/src/main/java/cn/com/ctop/common/module/utils/ParseInstallPackageUtil.java
  12. 4 4
      module-common/src/main/java/cn/com/ctop/common/module/utils/QueryGenerator.java
  13. 1 0
      module-common/src/main/java/cn/com/ctop/common/module/utils/StatusCode.java
  14. 2 0
      module-common/src/main/java/com/xxl/job/core/executor/impl/XxlJobSimpleExecutor.java
  15. 1 7
      module-crawler/src/main/java/cn/com/ctop/crawler/modules/taobao/service/impl/TaobaoJhsbybtServiceImpl.java
  16. 1 1
      module-crawler/src/main/java/cn/com/ctop/crawler/modules/taobao/service/impl/TaobaoTttmServiceImpl.java
  17. 12 12
      module-job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/handler/KuaishouAiAdsNewMaterialCreativityJob.java
  18. 1 0
      module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/ai/service/IAiKuaiShouAppInfoService.java
  19. 3 0
      module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/ai/service/IAiKuaishouAdvertiserStrategyService.java
  20. 9 0
      module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/ai/service/IAiKuaishouCreateCreativeService.java
  21. 20 4
      module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/ai/service/IAiKuaishouNewCreateCampaign.java
  22. 13 0
      module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/ai/service/impl/AiKuaiShouAppInfoServiceImpl.java
  23. 51 2
      module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/ai/service/impl/AiKuaishouAdvertiserStrategyServiceImpl.java
  24. 838 0
      module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/ai/service/impl/AiKuaishouCreateCreativeServiceImpl.java
  25. 222 86
      module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/ai/service/impl/AiKuaishouNewCreateCampaignServiceImpl.java
  26. 2 1
      module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/ai/service/impl/AiStrategyServiceImpl.java
  27. 1 1
      module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/batch/Enums/CampaignTypeEnum.java
  28. 1 1
      module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/batch/service/IKuaiShouVideoGetService.java
  29. 8 1
      module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/batch/service/impl/KuaiShouVideoGetServiceImpl.java
  30. 1 1
      module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/batch/service/impl/KuaishouCampaignCopyDataServiceImpl.java
  31. 1 0
      module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/batch/service/impl/KuaishouStrategyServiceImpl.java
  32. 1 0
      module-toutiao/src/main/java/cn/com/ctop/toutiao/modules/adlab/service/impl/CtopAdlabProjectDetailServiceImpl.java
  33. 6 6
      module-toutiao/src/main/java/cn/com/ctop/toutiao/modules/report/utils/ApkUtils.java

+ 2 - 2
jeecg-boot-base-common/src/main/java/org/jeecg/common/util/MD5Util.java

@@ -34,7 +34,7 @@ public class MD5Util {
 		return toHexStr(md5.digest(url.getBytes()));
 	}
 
-	public static String byteArrayToHexString(byte b[]) {
+	public static String byteArrayToHexString(byte[] b) {
 		StringBuffer resultSb = new StringBuffer();
 		for (int i = 0; i < b.length; i++){
 			resultSb.append(byteToHexString(b[i]));
@@ -80,7 +80,7 @@ public class MD5Util {
 		}
 		return resultString;
 	}
-	private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
+	private static final String[] hexDigits = { "0", "1", "2", "3", "4", "5",
 			"6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
 	private static final String[] HEX_DIGITS = {"0", "1", "2", "3", "4", "5",
 			"6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };

+ 1 - 1
jeecg-boot-base-common/src/main/java/org/jeecg/common/util/PmsUtil.java

@@ -41,7 +41,7 @@ public class PmsUtil {
             for (String s : msg) {
                 //写数据
                 if (s.indexOf("_") > 0) {
-                    String arr[] = s.split("_");
+                    String[] arr = s.split("_");
                     bw.write("第" + arr[0] + "行:" + arr[1]);
                 } else {
                     bw.write(s);

+ 1 - 5
jeecg-boot-base-common/src/main/java/org/jeecg/common/util/db/FreemarkerParseFactory.java

@@ -100,8 +100,6 @@ public class FreemarkerParseFactory {
         } catch (Exception e) {
             log.error(e.getMessage(), e.fillInStackTrace());
             log.error("发送一次的模板key:{ " + tplName + " }");
-            //System.err.println(e.getMessage());
-            //System.err.println("模板名:{ "+ tplName +" }");
             throw new RuntimeException("解析SQL模板异常");
         }
     }
@@ -132,8 +130,6 @@ public class FreemarkerParseFactory {
         } catch (Exception e) {
             log.error(e.getMessage(), e.fillInStackTrace());
             log.error("发送一次的模板key:{ " + tplContent + " }");
-            //System.err.println(e.getMessage());
-            //System.err.println("模板内容:{ "+ tplContent +" }");
             throw new RuntimeException("解析SQL模板异常");
         }
     }
@@ -168,4 +164,4 @@ public class FreemarkerParseFactory {
         }
         return sql;
     }
-}
+}

+ 1 - 7
jeecg-boot-base-common/src/main/java/org/jeecg/common/util/dynamic/db/FreemarkerParseFactory.java

@@ -6,8 +6,6 @@ import freemarker.template.Configuration;
 import freemarker.template.Template;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang.StringUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 import org.jeecgframework.codegenerate.generate.util.SimpleFormat;
 
 import java.io.StringWriter;
@@ -102,8 +100,6 @@ public class FreemarkerParseFactory {
         } catch (Exception e) {
             log.error(e.getMessage(), e.fillInStackTrace());
             log.error("发送一次的模板key:{ " + tplName + " }");
-            //System.err.println(e.getMessage());
-            //System.err.println("模板名:{ "+ tplName +" }");
             throw new RuntimeException("解析SQL模板异常");
         }
     }
@@ -134,8 +130,6 @@ public class FreemarkerParseFactory {
         } catch (Exception e) {
             log.error(e.getMessage(), e.fillInStackTrace());
             log.error("发送一次的模板key:{ " + tplContent + " }");
-            //System.err.println(e.getMessage());
-            //System.err.println("模板内容:{ "+ tplContent +" }");
             throw new RuntimeException("解析SQL模板异常");
         }
     }
@@ -170,4 +164,4 @@ public class FreemarkerParseFactory {
         }
         return sql;
     }
-}
+}

+ 2 - 2
jeecg-boot-base-common/src/main/java/org/jeecg/common/util/oConvertUtils.java

@@ -432,7 +432,7 @@ public class oConvertUtils {
 			//update-end--Author:zhoujf  Date:20180503 for:TASK #2500 【代码生成器】代码生成器开发一通用模板生成功能
 		}
 		// 用下划线将原始字符串分割
-		String camels[] = name.split("_");
+		String[] camels = name.split("_");
 		for (String camel : camels) {
 			// 跳过原始字符串中开头、结尾的下换线或双重下划线
 			if (camel.isEmpty()) {
@@ -495,7 +495,7 @@ public class oConvertUtils {
 			return name.substring(0, 1).toUpperCase() + name.substring(1).toLowerCase();
 		}
 		// 用下划线将原始字符串分割
-		String camels[] = name.split("_");
+		String[] camels = name.split("_");
 		for (String camel : camels) {
 			// 跳过原始字符串中开头、结尾的下换线或双重下划线
 			if (camel.isEmpty()) {

+ 8 - 2
jeecg-boot-module-system/src/main/java/org/jeecg/modules/cas/util/XmlUtils.java

@@ -88,13 +88,15 @@ public final class XmlUtils {
 
             private StringBuilder buffer = new StringBuilder();
 
+            @Override
             public void startElement(final String uri, final String localName, final String qName,
-                    final Attributes attributes) throws SAXException {
+                                     final Attributes attributes) throws SAXException {
                 if (localName.equals(element)) {
                     this.foundElement = true;
                 }
             }
 
+            @Override
             public void endElement(final String uri, final String localName, final String qName) throws SAXException {
                 if (localName.equals(element)) {
                     this.foundElement = false;
@@ -103,6 +105,7 @@ public final class XmlUtils {
                 }
             }
 
+            @Override
             public void characters(char[] ch, int start, int length) throws SAXException {
                 if (this.foundElement) {
                     this.buffer.append(ch, start, length);
@@ -139,19 +142,22 @@ public final class XmlUtils {
 
             private boolean foundElement = false;
 
+            @Override
             public void startElement(final String uri, final String localName, final String qName,
-                    final Attributes attributes) throws SAXException {
+                                     final Attributes attributes) throws SAXException {
                 if (localName.equals(element)) {
                     this.foundElement = true;
                 }
             }
 
+            @Override
             public void endElement(final String uri, final String localName, final String qName) throws SAXException {
                 if (localName.equals(element)) {
                     this.foundElement = false;
                 }
             }
 
+            @Override
             public void characters(char[] ch, int start, int length) throws SAXException {
                 if (this.foundElement) {
                     builder.append(ch, start, length);

+ 1 - 1
jeecg-boot-module-system/src/main/java/org/jeecg/modules/system/controller/SysDepartController.java

@@ -376,7 +376,7 @@ public class SysDepartController {
         LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<SysDepart>();
         query.orderByAsc(SysDepart::getOrgCode);
         if (oConvertUtils.isNotEmpty(id)) {
-            String arr[] = id.split(",");
+            String [] arr = id.split(",");
             query.in(SysDepart::getId, arr);
         }
         List<SysDepart> ls = this.sysDepartService.list(query);

+ 9 - 1
jeecg-boot-module-system/src/test/java/org/jeecg/SampleTest.java

@@ -20,7 +20,6 @@ import cn.com.ctop.toutiao.modules.material.service.IByteDanceAdvertiserDataServ
 import cn.com.ctop.toutiao.modules.report.entity.BytedanceAccountReportTaskRecord;
 import cn.com.ctop.toutiao.modules.report.mapper.BytedanceReportMaterialDailyMapper;
 import cn.com.ctop.toutiao.modules.report.service.*;
-import com.alibaba.fastjson.JSONObject;
 import lombok.extern.slf4j.Slf4j;
 import org.jeecg.common.util.DateUtils;
 import org.junit.Test;
@@ -153,6 +152,15 @@ public class SampleTest {
         }
     }
 
+    @Test
+    public void loadKuaishouCamgaignData(){
+        Date getDate = DateUtils.parseDate("2021-03-24","yyyy-MM-dd");
+        List<UserAllocation> list = allocationService.getByParams(50L,null,0);
+        list.forEach(userAllocation -> {
+            CtopOauthToken token = tokenService.getOauthTokenByAccountId(userAllocation.getAccountId().toString());
+            kuaishouInterfaceService.getAdvertiserCampaignReportDaily(token, getDate, getDate);
+        });
+    }
     static ExecutorService executorService = null;
     static CountDownLatch countDownLatch = null;
 

+ 7 - 7
module-alarm/src/main/java/cn/com/ctop/alarm/modules/constant/MatchLogic.java

@@ -20,7 +20,7 @@ import java.util.List;
 @Slf4j
 public class MatchLogic {
     /**
-     * @param type      数据类型
+     * @param indicator      数据类型
      * @param condition 条件
      * @param threshold 阈值
      * @param value     比对值
@@ -261,7 +261,7 @@ public class MatchLogic {
                         Long tplanId = targetDatas.getJSONObject(k).getLong("planId");
                         for (int j = 0; j < creativeDatas.size(); j++) {
                             Long cplanId = creativeDatas.getJSONObject(j).getLong("planId");
-                            if (cplanId == tplanId && cplanId == pplanId) {
+                            if (cplanId.equals(tplanId) && cplanId.equals(pplanId)) {
                                 sendData.add(creativeDatas.getJSONObject(j));
                             }
                         }
@@ -272,7 +272,7 @@ public class MatchLogic {
                     Long pplanId = planDatas.getJSONObject(i).getLong("planId");
                     for (int k = 0; k < targetDatas.size(); k++) {
                         Long tplanId = targetDatas.getJSONObject(k).getLong("planId");
-                        if (tplanId == pplanId) {
+                        if (tplanId.equals(pplanId)) {
                             sendData.add(targetDatas.getJSONObject(k));
                         }
                     }
@@ -282,7 +282,7 @@ public class MatchLogic {
                     Long pplanId = planDatas.getJSONObject(i).getLong("planId");
                     for (int k = 0; k < creativeDatas.size(); k++) {
                         Long cplanId = creativeDatas.getJSONObject(k).getLong("planId");
-                        if (cplanId == pplanId) {
+                        if (cplanId.equals(pplanId)) {
                             sendData.add(creativeDatas.getJSONObject(k));
                         }
                     }
@@ -292,7 +292,7 @@ public class MatchLogic {
                     Long tplanId = targetDatas.getJSONObject(i).getLong("planId");
                     for (int k = 0; k < creativeDatas.size(); k++) {
                         Long cplanId = creativeDatas.getJSONObject(k).getLong("planId");
-                        if (cplanId == tplanId) {
+                        if (cplanId.equals(tplanId)) {
                             sendData.add(creativeDatas.getJSONObject(k));
                         }
                     }
@@ -332,14 +332,14 @@ public class MatchLogic {
                         if (!Check.isNull(targetDatas) && Check.isNull(groupDatas)) {
                             for (int k = 0; k < targetDatas.size(); k++) {
                                 Long tgPlanId = targetDatas.getJSONObject(k).getLong("planId");
-                                if (tgPlanId == planId) {
+                                if (tgPlanId.equals(planId)) {
                                     sendData.add(creativeDatas.getJSONObject(k));
                                 }
                             }
                         } else if (Check.isNull(targetDatas) && !Check.isNull(groupDatas)) {
                             for (int k = 0; k < groupDatas.size(); k++) {
                                 Long tgPlanId = groupDatas.getJSONObject(k).getLong("planId");
-                                if (tgPlanId == planId) {
+                                if (tgPlanId.equals(planId)) {
                                     sendData.add(creativeDatas.getJSONObject(k));
                                 }
                             }

+ 1 - 1
module-common/src/main/java/cn/com/ctop/common/module/enums/SceneIdEnum.java

@@ -27,7 +27,7 @@ public enum SceneIdEnum {
 
     public static SceneIdEnum getEnumById(Integer id) {
         for (SceneIdEnum em : SceneIdEnum.values()) {
-            if (em.id == id) {
+            if (em.id.equals(id)) {
                 return em;
             }
         }

+ 3 - 3
module-common/src/main/java/cn/com/ctop/common/module/utils/ParseInstallPackageUtil.java

@@ -25,9 +25,9 @@ public class ParseInstallPackageUtil {
 
     private static final Logger log = LoggerFactory.getLogger(ParseInstallPackageUtil.class);
 
-    private static final float RADIX_MULTS[] = {0.00390625F, 3.051758E-005F, 1.192093E-007F, 4.656613E-010F};
-    private static final String DIMENSION_UNITS[] = {"px", "dip", "sp", "pt", "in", "mm", "", ""};
-    private static final String FRACTION_UNITS[] = {"%", "%p", "", "", "", "", "", ""};
+    private static final float[] RADIX_MULTS = {0.00390625F, 3.051758E-005F, 1.192093E-007F, 4.656613E-010F};
+    private static final String[] DIMENSION_UNITS = {"px", "dip", "sp", "pt", "in", "mm", "", ""};
+    private static final String[] FRACTION_UNITS = {"%", "%p", "", "", "", "", "", ""};
 
     /**
      * 解析apk文件

+ 4 - 4
module-common/src/main/java/cn/com/ctop/common/module/utils/QueryGenerator.java

@@ -115,7 +115,7 @@ public class QueryGenerator {
 		*/
 
         //区间条件组装 模糊查询 高级查询组装 简单排序 权限查询
-        PropertyDescriptor origDescriptors[] = PropertyUtils.getPropertyDescriptors(searchObj);
+        PropertyDescriptor[] origDescriptors = PropertyUtils.getPropertyDescriptors(searchObj);
         Map<String, SysPermissionDataRuleModel> ruleMap = getRuleMap();
 
         //权限规则自定义SQL表达式
@@ -691,7 +691,7 @@ public class QueryGenerator {
 
     private static String getInConditionValue(Object value, boolean isString) {
         if (isString) {
-            String temp[] = value.toString().split(",");
+            String[] temp = value.toString().split(",");
             String res = "";
             for (String string : temp) {
                 if (DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())) {
@@ -761,7 +761,7 @@ public class QueryGenerator {
         StringBuffer sb = new StringBuffer();
         //权限查询
         Map<String, SysPermissionDataRuleModel> ruleMap = getRuleMap();
-        PropertyDescriptor origDescriptors[] = PropertyUtils.getPropertyDescriptors(clazz);
+        PropertyDescriptor[] origDescriptors = PropertyUtils.getPropertyDescriptors(clazz);
         String sql_and = " and ";
         for (String c : ruleMap.keySet()) {
             if (oConvertUtils.isNotEmpty(c) && c.startsWith(SQL_RULES_COLUMN)) {
@@ -801,7 +801,7 @@ public class QueryGenerator {
     public static void installAuthMplus(QueryWrapper<?> queryWrapper, Class<?> clazz) {
         //权限查询
         Map<String, SysPermissionDataRuleModel> ruleMap = getRuleMap();
-        PropertyDescriptor origDescriptors[] = PropertyUtils.getPropertyDescriptors(clazz);
+        PropertyDescriptor[] origDescriptors = PropertyUtils.getPropertyDescriptors(clazz);
         for (String c : ruleMap.keySet()) {
             if (oConvertUtils.isNotEmpty(c) && c.startsWith(SQL_RULES_COLUMN)) {
                 queryWrapper.and(i -> i.apply(getSqlRuleValue(ruleMap.get(c).getRuleValue())));

+ 1 - 0
module-common/src/main/java/cn/com/ctop/common/module/utils/StatusCode.java

@@ -62,6 +62,7 @@ public enum StatusCode {
     KUAISHOU_SPEED_EXPLORE_FAIL("加速探索失败",-5003,false),
 
     KUAISHOU_AI_STRATEGY_HAS_NOT_EXIST("账户策略未配置或者已经被关闭",-6001,false),
+    KUAISHOU_AI_STRATEGY_HAS_NO_HISTORY_MATERIAL("历史素材不存在",-6002,false),
 
     KUAISHOU_CRAWLER_APP_SUCCESS("爬虫运行正常", 0, true),
     KUAISHOU_CRAWLER_APP_TASK_END("爬虫任务运行结束", 1, true),

+ 2 - 0
module-common/src/main/java/com/xxl/job/core/executor/impl/XxlJobSimpleExecutor.java

@@ -29,6 +29,7 @@ public class XxlJobSimpleExecutor extends XxlJobExecutor {
     }
 
 
+    @Override
     public void start() {
 
         // init JobHandler Repository (for method)
@@ -42,6 +43,7 @@ public class XxlJobSimpleExecutor extends XxlJobExecutor {
         }
     }
 
+    @Override
     public void destroy() {
         super.destroy();
     }

+ 1 - 7
module-crawler/src/main/java/cn/com/ctop/crawler/modules/taobao/service/impl/TaobaoJhsbybtServiceImpl.java

@@ -1,21 +1,15 @@
 package cn.com.ctop.crawler.modules.taobao.service.impl;
 
-import cn.com.ctop.common.module.entity.BindAccountLogin;
-import cn.com.ctop.common.module.utils.ChaojiyingUtils;
 import cn.com.ctop.common.module.utils.HttpUtils;
 import cn.com.ctop.common.module.utils.HttpUtils2;
 import cn.com.ctop.crawler.modules.taobao.service.TaobaoJhsbybtService;
-import com.alibaba.fastjson.JSONObject;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.gson.Gson;
 import org.apache.commons.codec.digest.DigestUtils;
 import org.apache.http.cookie.Cookie;
 import org.apache.http.impl.client.BasicCookieStore;
 import org.apache.http.impl.cookie.BasicClientCookie;
 import org.openqa.selenium.By;
-import org.openqa.selenium.OutputType;
 import org.openqa.selenium.WebDriver;
 import org.openqa.selenium.WebElement;
 import org.openqa.selenium.chrome.ChromeDriver;
@@ -95,7 +89,7 @@ public class TaobaoJhsbybtServiceImpl implements TaobaoJhsbybtService {
         Map<String, Object> paramMap = new HashMap<String, Object>();
         paramMap.put("jsv", "2.5.1");
         paramMap.put("appKey", "12574478");
-        paramMap.put("t", new Date().getTime());
+        paramMap.put("t", System.currentTimeMillis());
         paramMap.put("sign", "56b679fe3a6de0cd4ffa8ccb8680ff83");
         paramMap.put("timeout", 3000);
         paramMap.put("api", "mtop.tmall.kangaroo.core.service.route.AldLampServiceFixedRes");

+ 1 - 1
module-crawler/src/main/java/cn/com/ctop/crawler/modules/taobao/service/impl/TaobaoTttmServiceImpl.java

@@ -20,7 +20,7 @@ public class TaobaoTttmServiceImpl implements TaobaoTttmService {
         Map<String, Object> paramMap = new HashMap<String, Object>();
         paramMap.put("jsv", "2.6.0");
         paramMap.put("appKey", "12574478");
-        paramMap.put("t", new Date().getTime());
+        paramMap.put("t", System.currentTimeMillis());
         paramMap.put("sign", "56b679fe3a6de0cd4ffa8ccb8680ff83");
         paramMap.put("timeout", 3000);
         paramMap.put("api", "mtop.panama.fiona.commonbizservice");

+ 12 - 12
module-job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/handler/KuaishouAiAdsNewMaterialCreativityJob.java

@@ -1,7 +1,7 @@
 package cn.com.ctop.job.kuaishou.handler;
 
-import cn.com.ctop.kuaishou.modules.ai.entity.AiKuaishouAccountTargetTemplate;
-import cn.com.ctop.kuaishou.modules.ai.service.IAiKuaishouAccountTargetTemplateService;
+import cn.com.ctop.kuaishou.modules.ai.entity.AiKuaishouAdvertiserStrategy;
+import cn.com.ctop.kuaishou.modules.ai.service.IAiKuaishouAdvertiserStrategyService;
 import cn.com.ctop.kuaishou.modules.ai.service.IAiKuaishouNewCreateCampaign;
 import com.xxl.job.core.context.XxlJobHelper;
 import com.xxl.job.core.handler.annotation.XxlJob;
@@ -18,31 +18,31 @@ public class KuaishouAiAdsNewMaterialCreativityJob {
 
     @Autowired
     IAiKuaishouNewCreateCampaign aiKuaishouNewCreateCampaign;
+    @Autowired
+    private IAiKuaishouAdvertiserStrategyService aiKuaishouAdvertiserStrategyService;
     static ExecutorService executorService = Executors.newFixedThreadPool(5);
     static CountDownLatch countDownLatch = null;
 
-    @Autowired
-    private IAiKuaishouAccountTargetTemplateService aiKuaishouAccountTargetTemplateService;
     @XxlJob("kuaishouAiAdsNewMaterialCreativityJob")
     public void kuaishouAiAdsNewMaterialCreativityJob() {
-        List<AiKuaishouAccountTargetTemplate> accountTargetTemplates = aiKuaishouAccountTargetTemplateService.getAllEffectTemplate();
-        if(null==accountTargetTemplates||accountTargetTemplates.isEmpty()){
+        List<AiKuaishouAdvertiserStrategy> strategies = aiKuaishouAdvertiserStrategyService.getAllEffectStrategy();
+        if(null==strategies||strategies.isEmpty()){
             return;
         }
-        accountTargetTemplates.forEach(targetTemplate -> aiKuaishouNewCreateCampaign.kuaishouAiAdsNewMaterialCreativity(targetTemplate));
+        strategies.forEach(targetTemplate -> aiKuaishouNewCreateCampaign.kuaishouAiAdsNewMaterialCreativity(targetTemplate));
     }
 
 
-    @XxlJob("kuaishouAiAddNewMaterialCreativityJob")
-    public void kuaishouAiAddNewMaterialCreativityJob() {
-        List<AiKuaishouAccountTargetTemplate> accountTargetTemplates = aiKuaishouAccountTargetTemplateService.getAllEffectTemplate();
+    @XxlJob("kuaishouAiAddZeroMaterialCreativityJob")
+    public void kuaishouAiAddZeroMaterialCreativityJob() {
+        List<AiKuaishouAdvertiserStrategy> accountTargetTemplates = aiKuaishouAdvertiserStrategyService.getAllEffectStrategy();
         if(null==accountTargetTemplates||accountTargetTemplates.isEmpty()){
             return;
         }
         countDownLatch = new CountDownLatch(accountTargetTemplates.size());
         accountTargetTemplates.forEach(targetTemplate -> executorService.submit(()->{
             try {
-                aiKuaishouNewCreateCampaign.kuaishouAiAddNewMaterialCreativity(targetTemplate, 10);
+                aiKuaishouNewCreateCampaign.kuaishouAiAddZeroMaterialCreativity(targetTemplate, 10);
                 XxlJobHelper.log("账户上新结束=>accountId:{}",targetTemplate.getAccountId());
             }catch (Exception e) {
                 e.printStackTrace();
@@ -60,7 +60,7 @@ public class KuaishouAiAdsNewMaterialCreativityJob {
 
     @XxlJob("kuaishouAiAdsHotMaterialCreativityJob")
     public void kuaishouAiAdsHotMaterialCreativityJob() {
-        List<AiKuaishouAccountTargetTemplate> accountTargetTemplates = aiKuaishouAccountTargetTemplateService.getAllEffectTemplate();
+        List<AiKuaishouAdvertiserStrategy> accountTargetTemplates = aiKuaishouAdvertiserStrategyService.getAllEffectStrategy();
         if(null==accountTargetTemplates||accountTargetTemplates.isEmpty()){
             return;
         }

+ 1 - 0
module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/ai/service/IAiKuaiShouAppInfoService.java

@@ -19,4 +19,5 @@ public interface IAiKuaiShouAppInfoService extends IService<AiKuaiShouAppInfo> {
 
     void appCreative(Long accountId, String accessToken);
 
+    AiKuaiShouAppInfo getByParams(Long accountId,Long appId);
 }

+ 3 - 0
module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/ai/service/IAiKuaishouAdvertiserStrategyService.java

@@ -3,6 +3,7 @@ package cn.com.ctop.kuaishou.modules.ai.service;
 import cn.com.ctop.kuaishou.modules.ai.entity.AiKuaishouAdvertiserStrategy;
 import com.baomidou.mybatisplus.extension.service.IService;
 
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -23,4 +24,6 @@ public interface IAiKuaishouAdvertiserStrategyService extends IService<AiKuaisho
      * @return
      */
     Map<String, Object> aiHistoricalMissingMaterial(Long accountId);
+
+    List<AiKuaishouAdvertiserStrategy> getAllEffectStrategy();
 }

+ 9 - 0
module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/ai/service/IAiKuaishouCreateCreativeService.java

@@ -0,0 +1,9 @@
+package cn.com.ctop.kuaishou.modules.ai.service;
+
+import cn.com.ctop.kuaishou.modules.ai.entity.AiKuaishouAdvertiserStrategy;
+
+public interface IAiKuaishouCreateCreativeService {
+    void autoCreateCreative(AiKuaishouAdvertiserStrategy strategy);
+
+    void autoCreateProgramCreative(AiKuaishouAdvertiserStrategy strategy);
+}

+ 20 - 4
module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/ai/service/IAiKuaishouNewCreateCampaign.java

@@ -1,11 +1,27 @@
 package cn.com.ctop.kuaishou.modules.ai.service;
 
-import cn.com.ctop.kuaishou.modules.ai.entity.AiKuaishouAccountTargetTemplate;
+import cn.com.ctop.kuaishou.modules.ai.entity.AiKuaishouAdvertiserStrategy;
 
 public interface IAiKuaishouNewCreateCampaign {
-    void kuaishouAiAdsNewMaterialCreativity(AiKuaishouAccountTargetTemplate targetTemplate);
+    void kuaishouAiAdsNewMaterialCreativityMultileAppids(AiKuaishouAdvertiserStrategy strategy);
 
-    void kuaishouAiAdsHotMaterialCreativity(AiKuaishouAccountTargetTemplate targetTemplate);
+    /**
+     * 上新
+     * @param strategy
+     */
+    void kuaishouAiAdsNewMaterialCreativity(AiKuaishouAdvertiserStrategy strategy);
+
+    /**
+     * 爆款
+     * @param strategy
+     */
+    void kuaishouAiAdsHotMaterialCreativity(AiKuaishouAdvertiserStrategy strategy);
+
+    /**
+     *
+     * @param strategy
+     * @param matNum
+     */
+    void kuaishouAiAddZeroMaterialCreativity(AiKuaishouAdvertiserStrategy strategy,Integer matNum);
 
-    void kuaishouAiAddNewMaterialCreativity(AiKuaishouAccountTargetTemplate targetTemplate,Integer matNum);
 }

+ 13 - 0
module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/ai/service/impl/AiKuaiShouAppInfoServiceImpl.java

@@ -192,6 +192,19 @@ public class AiKuaiShouAppInfoServiceImpl extends ServiceImpl<AiKuaiShouAppInfoM
         }
     }
 
+    @Override
+    public AiKuaiShouAppInfo getByParams(Long accountId,Long appId) {
+        QueryWrapper<AiKuaiShouAppInfo>queryWrapper = new QueryWrapper<>();
+        if(null!=accountId&&accountId!=0){
+            queryWrapper.eq("account_id",accountId);
+        }
+        if(null!=appId&&appId!=0){
+            queryWrapper.eq("app_id",appId);
+        }
+        queryWrapper.last("limit 1");
+        return this.getOne(queryWrapper);
+    }
+
 
     private List<AiKuaiShouAppInfo> getAppListByStatus(Long accountId, Integer status) {
         QueryWrapper<AiKuaiShouAppInfo> queryWrapper = new QueryWrapper<>();

+ 51 - 2
module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/ai/service/impl/AiKuaishouAdvertiserStrategyServiceImpl.java

@@ -2,12 +2,15 @@ package cn.com.ctop.kuaishou.modules.ai.service.impl;
 
 import cn.com.ctop.common.module.entity.UserAllocation;
 import cn.com.ctop.common.module.service.IUserAllocationService;
+import cn.com.ctop.common.module.utils.Check;
 import cn.com.ctop.common.module.utils.HttpUtils;
 import cn.com.ctop.common.module.utils.ResultMapUtils;
 import cn.com.ctop.common.module.utils.StatusCode;
 import cn.com.ctop.kuaishou.modules.ai.entity.AiKuaishouAdvertiserStrategy;
 import cn.com.ctop.kuaishou.modules.ai.mapper.AiKuaishouAdvertiserStrategyMapper;
 import cn.com.ctop.kuaishou.modules.ai.service.IAiKuaishouAdvertiserStrategyService;
+import cn.com.ctop.kuaishou.modules.batch.service.IKuaiShouVideoGetService;
+import cn.com.ctop.kuaishou.modules.batch.service.IKuaishouVideoRelateCreativesService;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -15,6 +18,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -29,6 +33,11 @@ public class AiKuaishouAdvertiserStrategyServiceImpl extends ServiceImpl<AiKuais
     public static final String TEST_PROGRAM_CREATIVE_URL= "http://139.186.27.96:31012/ai_programme_new_material";
     @Autowired
     private IUserAllocationService userAllocationService;
+    @Autowired
+    private IKuaiShouVideoGetService videoGetService;
+    @Autowired
+    private IKuaishouVideoRelateCreativesService relateCreativesService;
+
     @Override
     public AiKuaishouAdvertiserStrategy getByAccountId(Long accountId) {
         QueryWrapper<AiKuaishouAdvertiserStrategy>queryWrapper =new QueryWrapper<>();
@@ -72,7 +81,6 @@ public class AiKuaishouAdvertiserStrategyServiceImpl extends ServiceImpl<AiKuais
         result.put("message",message);
         return result;
     }
-
     @Override
     public Map<String, Object> aiHistoricalMissingMaterial(Long accountId) {
         Map<String,Object>result = new HashMap<>();
@@ -85,8 +93,49 @@ public class AiKuaishouAdvertiserStrategyServiceImpl extends ServiceImpl<AiKuais
             ResultMapUtils.setResultMap(result,StatusCode.KUAISHOU_AI_STRATEGY_HAS_NOT_EXIST);
             return result;
         }
-
+        this.historicalMissingMaterialCreateCreative(strategy);
         ResultMapUtils.setResultMap(result,StatusCode.COMMON_SUCCESS);
         return result;
     }
+
+    @Override
+    public List<AiKuaishouAdvertiserStrategy> getAllEffectStrategy() {
+        QueryWrapper<AiKuaishouAdvertiserStrategy>queryWrapper= new QueryWrapper<>();
+        queryWrapper.eq("status",1);
+        queryWrapper.orderByDesc("id");
+        return this.list(queryWrapper);
+    }
+
+    private Map<String,Object> historicalMissingMaterialCreateCreative(AiKuaishouAdvertiserStrategy strategy) {
+        Map<String,Object>result =new HashMap<>();
+        //判定是否单一应用
+        if(strategy.getSingleAppid()==1){
+            //TODO 参数拼接
+            Map<String,Object>params =new HashMap<>();
+            //1:直接查询历史素材
+            List<JSONObject> materialList = relateCreativesService.getVideoZeroListByMap(params);
+            if (Check.isNull(materialList)) {
+                ResultMapUtils.setResultMap(result,StatusCode.KUAISHOU_AI_STRATEGY_HAS_NO_HISTORY_MATERIAL);
+                return result;
+            }
+            materialList = videoGetService.getVideoInfoAndImageList(materialList);
+            //补充遗漏素材
+            JSONObject hisMatParams = formatHisMatParams(strategy,materialList,"补充遗漏素材");
+        }else{
+            //
+
+        }
+        return result;
+    }
+
+    private JSONObject formatHisMatParams(AiKuaishouAdvertiserStrategy strategy, List<JSONObject> materialList, String fixString) {
+        JSONObject result = new JSONObject();
+        result.put("video",materialList);
+        result.put("operation_type",1);
+        result.put("account_id",strategy.getAccountId());
+        result.put("ai_strategy_remark",fixString);
+
+        return result;
+    }
+
 }

+ 838 - 0
module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/ai/service/impl/AiKuaishouCreateCreativeServiceImpl.java

@@ -0,0 +1,838 @@
+package cn.com.ctop.kuaishou.modules.ai.service.impl;
+
+import cn.com.ctop.common.module.entity.CtopOauthToken;
+import cn.com.ctop.common.module.entity.MaterialCutFrame;
+import cn.com.ctop.common.module.service.ICtopOauthTokenService;
+import cn.com.ctop.common.module.service.IMaterialCutFrameService;
+import cn.com.ctop.common.module.utils.Check;
+import cn.com.ctop.kuaishou.modules.ai.entity.AiKuaiShouAppInfo;
+import cn.com.ctop.kuaishou.modules.ai.entity.AiKuaishouAdvertiserStrategy;
+import cn.com.ctop.kuaishou.modules.ai.entity.AiKuaishouStrategyMapCreative;
+import cn.com.ctop.kuaishou.modules.ai.entity.KuaishouAccountCreativeOverrunInfo;
+import cn.com.ctop.kuaishou.modules.ai.service.IAiKuaiShouAppInfoService;
+import cn.com.ctop.kuaishou.modules.ai.service.IAiKuaishouCreateCreativeService;
+import cn.com.ctop.kuaishou.modules.ai.service.IAiKuaishouStrategyMapCreativeService;
+import cn.com.ctop.kuaishou.modules.ai.service.IKuaishouAccountCreativeOverrunInfoService;
+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.service.*;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.common.util.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+@Slf4j
+@Service
+public class AiKuaishouCreateCreativeServiceImpl implements IAiKuaishouCreateCreativeService {
+    @Autowired
+    private IKuaiShouGroupTemplateService groupTemplateService;
+    @Autowired
+    private ICtopOauthTokenService tokenService;
+    @Autowired
+    private IKuaishouInterfaceService kuaishouInterfaceService;
+    @Autowired
+    private IKuaiShouVideoGetService videoGetService;
+    @Autowired
+    private IAiKuaishouStrategyMapCreativeService mapCreativeService;
+    @Autowired
+    private IMaterialCutFrameService materialCutFrameService;
+    @Autowired
+    private IKuaiShouImageGetService imageGetService;
+    @Autowired
+    private IKuaiShouMaterialUploadService materialUploadService;
+    @Autowired
+    private IKuaishouAccountCreativeOverrunInfoService overrunInfoService;
+    @Autowired
+    private IAiKuaiShouAppInfoService appInfoService;
+
+
+    /**
+     * 创建自定义创意
+     * @param strategy
+     */
+    @Override
+    public void autoCreateCreative(AiKuaishouAdvertiserStrategy strategy){
+        strategy.setUnitType(4);
+        Long accountId = strategy.getAccountId();
+        CtopOauthToken token = tokenService.getOauthTokenByAccountId(accountId.toString());
+        if(null == token){
+            log.info("token获取失败=>accountId:{}",accountId);
+            return;
+        }
+        //1:获取视频信息
+        kuaishouInterfaceService.getVideoList(token, DateUtils.date2Str(),DateUtils.date2Str());
+        int timeStart = -10;
+        int timeEnd = -5;
+        Long now = System.currentTimeMillis();
+        String startTime = DateUtils.formatDate(new Date(now + timeStart*60*1000),"yyyy-MM-dd HH:mm:ss");
+        String endTime = DateUtils.formatDate(new Date(now + timeEnd*60*1000),"yyyy-MM-dd HH:mm:ss");
+
+        //2:判定账户是否单一应用
+        Integer singleAppid = strategy.getSingleAppid();
+        if(null!=singleAppid&&singleAppid==0){
+            //非单一应用
+            String appidString = strategy.getAppIdArray();
+            JSONArray appIdArray = JSONArray.parseArray(appidString);
+            if(null!=appIdArray&&!appIdArray.isEmpty()){
+                for(int i=0;i<appIdArray.size();i++){
+                    AiKuaiShouAppInfo appInfo = appInfoService.getByParams(strategy.getAccountId(),appIdArray.getLong(i));
+                    if(null == appInfo){
+                        log.info("账户:{},appid({}) 数据不存在",accountId, appIdArray.getLong(i));
+                        continue;
+                    }
+                    if(null!=strategy.getGeneralTrack()&&strategy.getGeneralTrack() == 0){
+                        strategy.setClickTrackUrl(appInfo.getTrackUrl());
+                        strategy.setImpressionUrl(appInfo.getTrackUrl());
+                    }
+                    String replaceString = appInfo.getAppVersion()+"自动上新";
+                    //1:查询通用素材
+                    List<KuaiShouVideoGet> allVideos = getVideosByParams(strategy,startTime,endTime,appInfo);
+                    if(null == allVideos||allVideos.isEmpty()){
+                        return;
+                    }
+                    Long newCampaignId = getCampaignId(strategy,token,replaceString,"ALL_CAMPAIGN");
+
+                    //开始创建组+创意
+                    String timestamp = DateUtils.formatDate(new Date(),"yyyyMMddHHmmss");
+                    String unitNamePrefix = strategy.getGroupName().replace("自定义",replaceString)+ timestamp;
+                    int unitCnt = 0;
+                    for(KuaiShouVideoGet videoItem: allVideos) {
+                        KuaishouAccountCreativeOverrunInfo overrunInfo = overrunInfoService.getByParams(accountId, DateUtils.formatDate(new Date()));
+                        if (null != overrunInfo) {
+                            log.info("该账户创意创建已超限=>accountId:{}",accountId);
+                            return;
+                        }
+                        unitCnt++;
+                        String unitName = unitNamePrefix + "-" + unitCnt;
+                        JSONObject unitParams = createUnitParams(token, newCampaignId, strategy, unitName,appInfo.getAppId());
+                        Map<String, Object> unitCreateResult = kuaishouInterfaceService.adUnitCreate(token.getAccessToken(), token.getAccountId(), unitParams, 1);
+                        Integer unitCode = (Integer) unitCreateResult.get("code");
+                        String unitMessage = (String) unitCreateResult.get("message");
+                        if (unitCode != 0) {
+                            log.info("组创建失败=>accountId:{};message:{}", accountId, unitMessage);
+                            continue;
+                        }
+                        Long unitId = (Long) unitCreateResult.get("unitId");
+
+                        // 每个组,搭配n个创意
+                        List<MaterialCutFrame> cutFrameList = materialCutFrameService.getListByVideoSignature(videoItem.getSignature());
+                        if ((null == cutFrameList || cutFrameList.isEmpty())) {
+                            log.info("未获取到视频封面=>videoSignature:{}", videoItem.getSignature());
+                            continue;
+                        }
+                        JSONObject creativeParams = creativeParams(token, unitId, videoItem, strategy);
+                        createCreativeByImage(cutFrameList, token, creativeParams, newCampaignId, unitId, videoItem, strategy.getImageCnt());
+                    }
+                }
+            }
+        }else{
+            //单一应用
+            List<KuaiShouVideoGet> newVideos = videoGetService.getNewVideoBetweenTime(accountId,startTime,endTime,strategy.getChannelType(),null);
+            if (null == newVideos ||newVideos.isEmpty()){
+                log.info("账户:{},{} 到 {} 这段时间没有上新素材",accountId, startTime, endTime);
+                return;
+            }
+
+            Long newCampaignId = getCampaignId(strategy,token,"素材上新","TODAY");
+            if(null== newCampaignId){
+                return;
+            }
+
+            //3、在“上新”计划中新增广告组,一个素材搭配n张封面,组成一个广告组
+            String timestamp = DateUtils.formatDate(new Date(),"yyyyMMddHHmmss");
+            String unitNamePrefix = strategy.getGroupName().replace("自定义","素材上新")+ timestamp;
+            int unitCnt = 0;
+            for(KuaiShouVideoGet videoItem: newVideos) {
+                KuaishouAccountCreativeOverrunInfo overrunInfo = overrunInfoService.getByParams(accountId, DateUtils.formatDate(new Date()));
+                if (null != overrunInfo) {
+                    return;
+                }
+                unitCnt++;
+                String unitName = unitNamePrefix + "-" + unitCnt;
+                Long appId = JSONArray.parseArray(strategy.getAppIdArray()).getLong(0);
+                JSONObject unitParams = createUnitParams(token, newCampaignId, strategy, unitName,appId);
+                Map<String, Object> unitCreateResult = kuaishouInterfaceService.adUnitCreate(token.getAccessToken(), token.getAccountId(), unitParams, 1);
+                Integer unitCode = (Integer) unitCreateResult.get("code");
+                String unitMessage = (String) unitCreateResult.get("message");
+                if (unitCode != 0) {
+                    log.info("组创建失败=>accountId:{};message:{}", accountId, unitMessage);
+                    continue;
+                }
+                Long unitId = (Long) unitCreateResult.get("unitId");
+
+                // 每个组,搭配5个创意
+                List<MaterialCutFrame> cutFrameList = materialCutFrameService.getListByVideoSignature(videoItem.getSignature());
+                if ((null == cutFrameList || cutFrameList.isEmpty())) {
+                    log.info("未获取到视频封面=>videoSignature:{}", videoItem.getSignature());
+                    continue;
+                }
+                JSONObject creativeParams = creativeParams(token, unitId, videoItem, strategy);
+                createCreativeByImage(cutFrameList, token, creativeParams, newCampaignId, unitId, videoItem, strategy.getImageCnt());
+            }
+        }
+    }
+
+    /**
+     * 创建程序化创意
+     * @param strategy
+     */
+    @Override
+    public void autoCreateProgramCreative(AiKuaishouAdvertiserStrategy strategy){
+        strategy.setUnitType(7);
+        Long accountId = strategy.getAccountId();
+        CtopOauthToken token = tokenService.getOauthTokenByAccountId(accountId.toString());
+        if(null == token){
+            log.info("token获取失败=>accountId:{}",accountId);
+            return;
+        }
+        //1:获取视频信息
+        kuaishouInterfaceService.getVideoList(token, DateUtils.date2Str(),DateUtils.date2Str());
+        int timeStart = -10;
+        int timeEnd = -5;
+        Long now = System.currentTimeMillis();
+        String startTime = DateUtils.formatDate(new Date(now + timeStart*60*1000),"yyyy-MM-dd HH:mm:ss");
+        String endTime = DateUtils.formatDate(new Date(now + timeEnd*60*1000),"yyyy-MM-dd HH:mm:ss");
+
+        //2:判定账户是否单一应用
+        Integer singleAppid = strategy.getSingleAppid();
+        if(null!=singleAppid&&singleAppid==0){
+            //非单一应用
+            String appidString = strategy.getAppIdArray();
+            JSONArray appIdArray = JSONArray.parseArray(appidString);
+            if(null!=appIdArray&&!appIdArray.isEmpty()){
+                for(int i=0;i<appIdArray.size();i++){
+                    AiKuaiShouAppInfo appInfo = appInfoService.getByParams(strategy.getAccountId(),appIdArray.getLong(i));
+                    if(null == appInfo){
+                        log.info("账户:{},appid({}) 数据不存在",accountId, appIdArray.getLong(i));
+                        continue;
+                    }
+                    String replaceString = appInfo.getAppVersion()+"程序化";
+                    //1:查询可用素材
+                    List<KuaiShouVideoGet> allVideos = getVideosByParams(strategy,startTime,endTime,appInfo);
+                    if(null == allVideos){
+                        return;
+                    }
+                    Long newCampaignId = getCampaignId(strategy,token,replaceString,"ALL_CAMPAIGN");
+                    //开始创建组+创意
+                    String timestamp = DateUtils.formatDate(new Date(),"yyyyMMddHHmmss");
+                    String unitNamePrefix = strategy.getGroupName().replace("自定义",replaceString)+ timestamp;
+                    int unitCnt = 0;
+                    for(KuaiShouVideoGet videoItem: allVideos) {
+                        KuaishouAccountCreativeOverrunInfo overrunInfo = overrunInfoService.getByParams(accountId, DateUtils.formatDate(new Date()));
+                        if (null != overrunInfo) {
+                            log.info("该账户创意创建已超限=>accountId:{}",accountId);
+                            return;
+                        }
+                        unitCnt++;
+                        String unitName = unitNamePrefix + "-" + unitCnt;
+                        JSONObject unitParams = createUnitParams(token, newCampaignId, strategy, unitName,appInfo.getAppId());
+                        Map<String, Object> unitCreateResult = kuaishouInterfaceService.adUnitCreate(token.getAccessToken(), token.getAccountId(), unitParams, 1);
+                        Integer unitCode = (Integer) unitCreateResult.get("code");
+                        String unitMessage = (String) unitCreateResult.get("message");
+                        if (unitCode != 0) {
+                            log.info("组创建失败=>accountId:{};message:{}", accountId, unitMessage);
+                            continue;
+                        }
+                        Long unitId = (Long) unitCreateResult.get("unitId");
+
+                        // 每个组,搭配n个创意
+                        List<MaterialCutFrame> cutFrameList = materialCutFrameService.getListByVideoSignature(videoItem.getSignature());
+                        if ((null == cutFrameList || cutFrameList.isEmpty())) {
+                            log.info("未获取到视频封面=>videoSignature:{}", videoItem.getSignature());
+                            continue;
+                        }
+                        JSONObject creativeParams = creativeParams(token, unitId, videoItem, strategy);
+                        createCreativeByImage(cutFrameList, token, creativeParams, newCampaignId, unitId, videoItem, strategy.getImageCnt());
+                    }
+                }
+            }
+        }else{
+            //单一应用
+            List<KuaiShouVideoGet> newVideos = videoGetService.getNewVideoBetweenTime(accountId,startTime,endTime,strategy.getChannelType(),null);
+            if (null == newVideos ||newVideos.isEmpty()){
+                log.info("账户:{},{} 到 {} 这段时间没有上新素材",accountId, startTime, endTime);
+                return;
+            }
+
+            Long newCampaignId = getCampaignId(strategy,token,"素材上新","TODAY");
+            if(null== newCampaignId){
+                return;
+            }
+
+            //3、在“上新”计划中新增广告组,一个素材搭配n张封面,组成一个广告组
+            String timestamp = DateUtils.formatDate(new Date(),"yyyyMMddHHmmss");
+            String unitNamePrefix = strategy.getGroupName().replace("自定义","素材上新")+ timestamp;
+            int unitCnt = 0;
+            for(KuaiShouVideoGet videoItem: newVideos) {
+                KuaishouAccountCreativeOverrunInfo overrunInfo = overrunInfoService.getByParams(accountId, DateUtils.formatDate(new Date()));
+                if (null != overrunInfo) {
+                    return;
+                }
+                unitCnt++;
+                String unitName = unitNamePrefix + "-" + unitCnt;
+                Long appId = JSONArray.parseArray(strategy.getAppIdArray()).getLong(0);
+                JSONObject unitParams = createUnitParams(token, newCampaignId, strategy, unitName,appId);
+                Map<String, Object> unitCreateResult = kuaishouInterfaceService.adUnitCreate(token.getAccessToken(), token.getAccountId(), unitParams, 1);
+                Integer unitCode = (Integer) unitCreateResult.get("code");
+                String unitMessage = (String) unitCreateResult.get("message");
+                if (unitCode != 0) {
+                    log.info("组创建失败=>accountId:{};message:{}", accountId, unitMessage);
+                    continue;
+                }
+                Long unitId = (Long) unitCreateResult.get("unitId");
+
+                // 每个组,搭配5个创意
+                List<MaterialCutFrame> cutFrameList = materialCutFrameService.getListByVideoSignature(videoItem.getSignature());
+                if ((null == cutFrameList || cutFrameList.isEmpty())) {
+                    log.info("未获取到视频封面=>videoSignature:{}", videoItem.getSignature());
+                    continue;
+                }
+                JSONObject creativeParams = creativeParams(token, unitId, videoItem, strategy);
+                createCreativeByImage(cutFrameList, token, creativeParams, newCampaignId, unitId, videoItem, strategy.getImageCnt());
+            }
+        }
+    }
+
+    private List<KuaiShouVideoGet> getVideosByParams(AiKuaishouAdvertiserStrategy strategy,String startTime,String endTime,AiKuaiShouAppInfo appInfo) {
+        List<KuaiShouVideoGet> generalVideos = videoGetService.getNewVideoBetweenTime(strategy.getAccountId(),startTime,endTime,strategy.getChannelType(),null);
+        //2:查询特定素材
+        List<KuaiShouVideoGet> customVideos = videoGetService.getNewVideoBetweenTime(strategy.getAccountId(),startTime,endTime,strategy.getChannelType(),appInfo.getAppVersion());
+        if(null == generalVideos||generalVideos.isEmpty()||null == customVideos||customVideos.isEmpty()){
+            log.info("账户:{},appId({}){}到{}这段时间没有上新素材",strategy.getAccountId(),appInfo.getAppId(),startTime, endTime);
+            return null;
+        }
+
+        //合并
+        if(null == generalVideos||generalVideos.isEmpty()){
+            return customVideos;
+        }else if(null == customVideos||customVideos.isEmpty()){
+            return generalVideos;
+        }else {
+            generalVideos.addAll(customVideos);
+            return generalVideos;
+        }
+    }
+
+    private Long getCampaignId(AiKuaishouAdvertiserStrategy strategy,CtopOauthToken token,String replaceString,String checkType) {
+        JSONArray campaignList = null;
+        Date campaignDate = new Date();
+        String timestamp = "";
+        if(null!=checkType&&checkType.equals("ALL_CAMPAIGN")){
+            campaignList = kuaishouInterfaceService.getCampaignList(token, null, null,1);
+        }else{
+            timestamp = DateUtils.formatDate(campaignDate,"yyyyMMddHHmmss");
+            campaignList = kuaishouInterfaceService.getCampaignList(token, new Date(), new Date(),1);
+        }
+        Long newCampaignId = 0L;
+        if (null!=campaignList&&campaignList.size()>0){
+            for(int i = 0;i<campaignList.size();i++){
+                JSONObject jsonObject = campaignList.getJSONObject(i);
+                if (jsonObject.getString("campaign_name").contains(replaceString)){
+                    newCampaignId = jsonObject.getLong("campaign_id");
+                    return newCampaignId;
+                }
+            }
+        }
+        // 不存在“上新”计划,则创建一个计划
+        JSONObject campaignParams = new JSONObject();
+        campaignParams.put("advertiser_id",token.getAccountId());
+        String campaignName = strategy.getCampaignName().replace("自定义",replaceString)+timestamp;
+        campaignParams.put("campaign_name",campaignName);
+        campaignParams.put("type",strategy.getCampaignType());
+        //TODO 目前设定为不限
+        campaignParams.put("day_budget",0L);
+        Map<String, Object> campaignCreateResult = kuaishouInterfaceService.campaignCreate(token.getAccessToken(), token.getAccountId(), campaignParams);
+        Integer code = (Integer) campaignCreateResult.get("code");
+        String message = (String) campaignCreateResult.get("message");
+        if(code != 0 ){
+            //TODO 写入日志信息表
+            log.info("计划创建失败=>message:{}",message);
+            return null;
+        }
+        newCampaignId = (Long) campaignCreateResult.get("campaignId");
+        return newCampaignId;
+    }
+
+
+    private JSONObject createUnitParams(CtopOauthToken token, Long campaignId,  AiKuaishouAdvertiserStrategy strategy,
+                                        String unitName,Long appId) {
+        // 拼装创建组的入参 json
+        JSONObject unitParams = new JSONObject();
+        Integer unitType = strategy.getUnitType();
+        //创意制作方式
+        unitParams.put("unit_type",unitType);
+        unitParams.put("advertiser_id",token.getAccountId());
+        unitParams.put("campaign_id",campaignId);
+        unitParams.put("unit_name", unitName);
+        //出价类型
+        unitParams.put("bid_type",strategy.getBidType());
+        // 优先从系统应用商店下载
+        if(null!=strategy.getUseAppMarket()){
+            unitParams.put("use_app_market",strategy.getUseAppMarket());
+        }
+        //应用商店列表
+        if(null!=strategy.getAppStore()&&!"".equals(strategy.getAppStore())){
+            unitParams.put("app_store",JSONArray.parseArray(strategy.getAppStore()));
+        }
+        unitParams.put("ocpx_action_type",strategy.getOcpxActionType());
+
+
+        // 在本策略中,都是 OCPM 的出价方式
+        //出价
+        if (null!=strategy.getBid()&&strategy.getBid()!=0) {
+            unitParams.put("bid", strategy.getBid());
+        }
+        if (null!=strategy.getCpaBid()&&strategy.getCpaBid()!=0) {
+            unitParams.put("cpa_bid", strategy.getCpaBid());
+        }
+        //优先低成本
+        if (null!=strategy.getSmartBid()&&strategy.getSmartBid()!=0) {
+            unitParams.put("smart_bid", strategy.getSmartBid());
+        }
+        //优化目标
+        if (!Check.isNull(strategy.getOcpxActionType())) {
+            unitParams.put("ocpx_action_type", strategy.getOcpxActionType());
+        }
+        //深度转化目标
+        if (!Check.isNull(strategy.getDeepConversionType())) {
+            unitParams.put("deep_conversion_type", strategy.getDeepConversionType());
+        }
+        //付费ROI系数
+        if (!Check.isNull(strategy.getRoiRatio())) {
+            unitParams.put("roi_ratio", strategy.getRoiRatio());
+        }
+        //深度转化目标出价
+        if (!Check.isNull(strategy.getDeepConversionBid())) {
+            unitParams.put("deep_conversion_bid", strategy.getDeepConversionBid());
+        }
+        //资源位置
+        Integer sceneId = null;
+        String scenceIdString = strategy.getSceneId();
+        if (null!=scenceIdString&&!scenceIdString.trim().equals(scenceIdString)&&Check.isNull(JSONArray.parseArray(scenceIdString))) {
+            sceneId = JSONArray.parseArray(strategy.getSceneId()).getInteger(0);
+            unitParams.put("scene_id", JSONArray.parseArray(strategy.getSceneId()));
+        }
+
+        //投放开始时间
+        if (!Check.isNull(strategy.getBeginTime())) {
+            unitParams.put("begin_time", strategy.getBeginTime());
+        }
+        //投放结束时间
+        if (!Check.isNull(strategy.getEndTime())) {
+            unitParams.put("end_time", strategy.getEndTime());
+        }
+        //投放时间段
+        if (!Check.isNull(strategy.getScheduleTime())) {
+            unitParams.put("schedule_time", strategy.getScheduleTime());
+        }
+//        if (!Check.isNull(strategy.getLong("day_budget"))) {
+//            unitParams.put("day_budget", groupCreateJson.getLong("day_budget")); //投放时间段
+//        }
+        //转化id
+        if (!Check.isNull(strategy.getConvertId())) {
+            unitParams.put("convert_id", strategy.getConvertId());
+        }
+        //url类型
+        if (!Check.isNull(strategy.getUrlType())) {
+            unitParams.put("url_type", strategy.getUrlType());
+        }
+        //url类型
+        if (!Check.isNull(strategy.getWebUriType())) {
+            unitParams.put("web_uri_type", strategy.getWebUriType());
+        }
+        //url
+        if (!Check.isNull(strategy.getUrl())) {
+            unitParams.put("url", strategy.getUrl());
+        }
+        //调起链接
+        if (!Check.isNull(strategy.getSchemaUri())) {
+            unitParams.put("schema_uri", strategy.getSchemaUri());
+        }
+        //应用ID
+        if (!Check.isNull(appId)) {
+            unitParams.put("app_id", appId);
+        }
+        //创意展现方式
+        if (!Check.isNull(strategy.getShowMode())) {
+            unitParams.put("show_mode", strategy.getShowMode());
+        }
+        //投放方式
+        if (!Check.isNull(strategy.getSpeed())) {
+            unitParams.put("speed", strategy.getSpeed());
+        }
+        //预约广告
+        if (!Check.isNull(strategy.getSiteType())) {
+            unitParams.put("site_type", strategy.getSiteType());
+        }
+//        if (!Check.isNull(strategy.getInteger("target_action_type")) || !Check.isNull(strategy.getString("code"))) {
+//            JSONObject gift_data = new JSONObject();
+//            if (!Check.isNull(groupCreateJson.getInteger("target_action_type"))) {
+//                gift_data.put("target_action_type", groupCreateJson.getInteger("target_action_type"));
+//            }
+//            if (!Check.isNull(groupCreateJson.getString("code"))) {
+//                gift_data.put("code", groupCreateJson.getString("code"));
+//            }
+//            unitParams.put("gift_data", gift_data); //游戏礼包码
+//        }
+//        if (!Check.isNull(groupCreateJson.getBoolean("video_landing_page"))) {
+//            unitParams.put("video_landing_page", groupCreateJson.getBoolean("video_landing_page")); //是否使用落地页前置功能
+//        }
+        //智能定向
+        if (!Check.isNull(strategy.getAutoTarget())) {
+            unitParams.put("auto_target", strategy.getAutoTarget());
+        }
+        //是否开启自动生成视频
+        if (!Check.isNull(strategy.getAutoCreatePhoto())) {
+            unitParams.put("auto_create_photo", strategy.getAutoCreatePhoto());
+        }
+//        if (!Check.isNull(strategy.getItemId())) {
+//            unitParams.put("item_id", groupCreateJson.getLong("item_id")); //电商关联Id (小店通)
+//        }
+//        if (!Check.isNull(groupCreateJson.getLong("merchant_item_put_type"))) {
+//            unitParams.put("merchant_item_put_type", groupCreateJson.getLong("merchant_item_put_type")); //电商广告投放类型(小店通)
+//        }
+//        if (!Check.isNull(groupCreateJson.getLong("fiction_id"))) {
+//            unitParams.put("fiction_id", groupCreateJson.getLong("fiction_id")); //小说ID
+//        }
+
+        if (unitType == 7) {
+            //是否开启智能抽帧
+            if (!Check.isNull(strategy.getSmartCover())) {
+                unitParams.put("smart_cover", strategy.getSmartCover());
+            }
+            //程序化创意2.0素材挖掘
+            if (!Check.isNull(strategy.getAssetMining())) {
+                unitParams.put("asset_mining", strategy.getAssetMining());
+            }
+        }
+        if (!Check.isNull(strategy.getTemplateId())) {
+            if (sceneId != 5) {
+                unitParams.put("template_id", strategy.getTemplateId()); //定向模板id
+            } else { // 联盟广告位 需要根据模板id 获取定向数据
+                JSONObject unionJson = groupTemplateService.getUnionJson(Long.parseLong(strategy.getTemplateId()+""));
+                Integer code = unionJson.getInteger("code");
+                if (code == 0) {
+                    JSONObject target = unionJson.getJSONObject("target");
+                    unitParams.put("target", target);
+                } else {
+                    log.info("组创建异常=》accountId({})联盟广告位定向模板错误",strategy.getAccountId());
+                    return null;
+                }
+            }
+        } else {
+            JSONObject target = getTarget(sceneId,strategy);
+            // 定向数据
+            unitParams.put("target", target);
+        }
+
+
+
+        // 设置定向内容
+        JSONObject targetJsonObject = new JSONObject();
+        if(null!=strategy.getRegion()&&!"".equals(strategy.getRegion())){
+            targetJsonObject.put("region",JSONArray.parseArray(strategy.getRegion()));
+        }
+        if(null!=strategy.getAgesRange()&&!"".equals(strategy.getAgesRange())){
+            targetJsonObject.put("ages_range",JSONArray.parseArray(strategy.getAgesRange()));
+        }
+        if(null!=strategy.getGender()){
+            targetJsonObject.put("gender",strategy.getGender());
+        }
+        if(null!=strategy.getPlatformOs()){
+            targetJsonObject.put("platform_os",strategy.getPlatformOs());
+        }
+        if(null!=strategy.getAndroidOsv()){
+            targetJsonObject.put("android_osv",strategy.getAndroidOsv());
+        }
+        if(null!=strategy.getIosOsv()){
+            targetJsonObject.put("ios_osv",strategy.getIosOsv());
+        }
+        if(null!=strategy.getDeviceBrand()&&!"".equals(strategy.getDeviceBrand())&&!"[]".equals(strategy.getDeviceBrand())){
+            targetJsonObject.put("device_brand",JSONArray.parseArray(strategy.getDeviceBrand()));
+        }
+        if(null!=strategy.getDevicePrice()&&!"".equals(strategy.getDevicePrice())&&!"[]".equals(strategy.getDevicePrice())){
+            targetJsonObject.put("device_price",JSONArray.parseArray(strategy.getDevicePrice()));
+        }
+        if(null!=strategy.getPopulation()&&!"".equals(strategy.getPopulation())){
+            JSONArray population = JSONArray.parseArray(strategy.getPopulation());
+            targetJsonObject.put("population",population);
+        }
+        if(null!=strategy.getFilterConvertedLevel()&&strategy.getFilterConvertedLevel()!=0){
+            targetJsonObject.put("filter_converted_level",strategy.getFilterConvertedLevel());
+        }
+        if(null!=strategy.getExcludePopulation()&&!"".equals(strategy.getExcludePopulation())){
+            JSONArray excludePopulation = JSONArray.parseArray(strategy.getExcludePopulation());
+            targetJsonObject.put("exclude_population",excludePopulation);
+        }
+        //是否开启智能扩量
+        if(null!=strategy.getIsOpen()&&strategy.getIsOpen().equals(1)){
+            JSONObject intelliExtend = new JSONObject();
+            intelliExtend.put("is_open",1);
+            if(null!=strategy.getNoAgeBreak()&&strategy.getNoAgeBreak().equals(1)){
+                intelliExtend.put("no_age_break",1);
+            }
+            if(null!=strategy.getNoGenderBreak()&&strategy.getNoGenderBreak().equals(1)){
+                intelliExtend.put("no_gender_break",1);
+            }
+            if(null!=strategy.getNoAreaBreak()&&strategy.getNoAreaBreak().equals(1)){
+                intelliExtend.put("no_area_break",1);
+            }
+            targetJsonObject.put("intelli_extend",intelliExtend);
+        }
+        unitParams.put("target",targetJsonObject);
+        return unitParams;
+    }
+
+    /**
+     * 获取定向包
+     *
+     * @param sceneId
+     * @param strategy
+     * @return
+     */
+    private JSONObject getTarget(Integer sceneId,AiKuaishouAdvertiserStrategy strategy) {
+        JSONObject target = new JSONObject();
+        // 地域
+        String regionString = strategy.getRegion();
+        if (null!=regionString&&!"".equals(regionString.trim())) {
+            target.put("region", JSONArray.parseArray(regionString));
+        }
+        String districtIdString = strategy.getDistrictIds();
+        // 商圈定向
+        if (null!=districtIdString&&!"".equals(districtIdString.trim())) {
+            target.put("district_ids", JSONArray.parseArray(districtIdString));
+        }
+        // 用户类型
+        if (null!=strategy.getUserType()) {
+            target.put("user_type", strategy.getUserType());
+        }
+        //自定义年龄段
+        if (null!=strategy.getAgeMin() || null!=strategy.getAgeMax()) {
+            JSONObject age = new JSONObject();
+            age.put("min", strategy.getAgeMin());
+            age.put("max", strategy.getAgeMax());
+            target.put("age", age);
+        }
+        // 固定年龄段
+        String ageRangeString = strategy.getAgesRange();
+        if (null!=ageRangeString&&!"".equals(ageRangeString.trim())) {
+            target.put("ages_range", JSONArray.parseArray(ageRangeString));
+        }
+        // 性别
+        if (null!=strategy.getGender()) {
+            target.put("gender", strategy.getGender());
+        }
+        // 操作系统
+        if (null!=strategy.getPlatformOs()) {
+            target.put("platform_os", strategy.getPlatformOs());
+        }
+        // Android版本
+        if (null!=strategy.getAndroidOsv()) {
+            target.put("android_osv", strategy.getAndroidOsv());
+        }
+        // Android版本
+        if (null!=strategy.getIosOsv()) {
+            target.put("ios_osv", strategy.getIosOsv());
+        }
+        // 网络环境
+        if (null!=strategy.getNetwork()) {
+            target.put("network",strategy.getNetwork());
+        }
+        // 设备品牌
+        String deviceBrandString = strategy.getDeviceBrand();
+        if (null != deviceBrandString&&!"".equals(deviceBrandString.trim())) {
+            target.put("device_brand", JSONArray.parseArray(deviceBrandString));
+        }
+        // 设备价格
+        String devicePriceString = strategy.getDevicePrice();
+        if (null != devicePriceString&&!"".equals(devicePriceString.trim())) {
+            target.put("device_price", JSONArray.parseArray(devicePriceString));
+        }
+        if (sceneId != 5) {
+            // 商业兴趣类型
+            if (null!=strategy.getBusinessInterestType()) {
+                target.put("business_interest_type", strategy.getBusinessInterestType());
+            }
+            // 商业兴趣
+            String businessInterestString = strategy.getBusinessInterest();
+            if (null != businessInterestString&&!"".equals(businessInterestString.trim())) {
+                target.put("business_interest", JSONArray.parseArray(businessInterestString));
+            }
+            // 网红粉丝
+            String fansStarString = strategy.getFansStar();
+            if (null != fansStarString&&!"".equals(fansStarString.trim())) {
+                target.put("fans_star", JSONArray.parseArray(fansStarString));
+            }
+            // 兴趣视频用户
+            String interestVideoString = strategy.getInterestVideo();
+            if (null != interestVideoString&&!"".equals(interestVideoString.trim())) {
+                target.put("interest_video", JSONArray.parseArray(interestVideoString));
+            }
+            // 过滤已转化人群
+            if (null!=strategy.getFilterConvertedLevel()) {
+                target.put("filter_converted_level", strategy.getFilterConvertedLevel());
+            }
+
+            // 开启智能扩量
+            if (null!=strategy.getIsOpen()&&strategy.getIsOpen() == 1) {
+                JSONObject intelli_extend = new JSONObject();
+                intelli_extend.put("is_open", strategy.getIsOpen());
+                //  不可突破年龄
+                if (!Check.isNull(strategy.getNoAgeBreak())) {
+                    intelli_extend.put("no_age_break", strategy.getNoAgeBreak());
+                }
+                //  不可突破性别
+                if (!Check.isNull(strategy.getNoGenderBreak())) {
+                    intelli_extend.put("no_gender_break", strategy.getNoGenderBreak());
+                }
+                //  不可突破地域
+                if (!Check.isNull(strategy.getNoAreaBreak())) {
+                    intelli_extend.put("no_area_break", strategy.getNoAreaBreak());
+                }
+                target.put("intelli_extend", intelli_extend); // 智能扩量
+            }
+
+        }
+        // APP行为-按分类
+        String appInterestString = strategy.getAppInterest();
+        if (null != appInterestString&&!"".equals(appInterestString.trim())) {
+            target.put("app_interest", JSONArray.parseArray(appInterestString));
+        }
+        // APP行为-按APP名称
+        String appIdsString = strategy.getAppIds();
+        if (null != appIdsString&&!"".equals(appIdsString.trim())) {
+            target.put("app_ids", JSONArray.parseArray(appIdsString));
+        }
+
+        // 人群包定向
+        String populationString = strategy.getPopulation();
+        if (null != populationString&&!"".equals(populationString.trim())) {
+            target.put("population", JSONArray.parseArray(populationString));
+        }
+        // 人群包排除
+        String excludePopulationString = strategy.getExcludePopulation();
+        if (null != excludePopulationString&&!"".equals(excludePopulationString.trim())) {
+            target.put("exclude_population", JSONArray.parseArray(excludePopulationString));
+        }
+        // 付费人群包id
+        String paidAudienceString = strategy.getPaidAudience();
+        if (null != paidAudienceString&&!"".equals(paidAudienceString.trim())) {
+            target.put("paid_audience", JSONArray.parseArray(paidAudienceString));
+        }
+        if (Check.isNull(strategy.getBehaviorInterest())){
+            // TODO 只是单独结构体 后续需要优化
+            target.put("behavior_interest", JSONObject.parseObject(strategy.getBehaviorInterest()));
+        }
+        return target;
+    }
+
+
+    private void createCreativeByImage(List<MaterialCutFrame> cutFrameList, CtopOauthToken token, JSONObject creativeParams,
+                                       Long campaignId, Long unitId, KuaiShouVideoGet videoItem,
+                                       int imageNumber){
+        int creativeCnt  = 1;
+
+        if ((null!=cutFrameList&&!cutFrameList.isEmpty())){
+            for (int i = 0; i < cutFrameList.size(); i++) {
+                String imageCode = cutFrameList.get(i).getSignature();
+                String imageUrl = cutFrameList.get(i).getUrl();
+                String imageToken = getImageToken(imageUrl,imageCode,token.getAccountId(),token.getAccessToken());
+                creativeParams.put("image_token",imageToken);
+                createCreative(token, creativeParams, campaignId, unitId, creativeCnt,videoItem);
+                creativeCnt ++;
+                if (creativeCnt > imageNumber) {
+                    break;
+                }
+            }
+        }
+    }
+
+    private String getImageToken(String imageUrl, String imageCode, Long accountId,String token){
+        // 根据imageUrl 和 imageCode,获取 imageToken (创建创意用)
+        KuaiShouImageGet imageGet = imageGetService.getOneByParams(null,imageCode);
+        if ((null == imageGet) || ("".equals(imageGet.getImageToken()))){
+            // 如果取不到image_token
+            // 则调用上传url的方法 kuauiShouImageUpload(url, signature, accountId, oauthToken.getAccessToken());
+            return materialUploadService.kuauiShouImageUpload(imageUrl,imageCode,accountId,token);
+        }
+        return imageGet.getImageToken();
+    }
+
+    private JSONObject creativeParams(CtopOauthToken token,Long unitId,KuaiShouVideoGet videoItem,AiKuaishouAdvertiserStrategy strategy){
+        JSONObject creativeParams = new JSONObject();
+        creativeParams.put("advertiser_id",token.getAccountId());
+        creativeParams.put("unit_id",unitId);
+        creativeParams.put("photo_id",videoItem.getPhotoId());
+        creativeParams.put("creative_material_type",videoItem.getMaterialType());
+        creativeParams.put("action_bar_text",strategy.getActionBarText());
+        creativeParams.put("description",strategy.getDescription());
+        // 封面广告语标题
+        if (!Check.isNull(strategy.getStickerTitle())) {
+            creativeParams.put("sticker_title", strategy.getStickerTitle());
+        }
+        // 贴纸样式类型
+        if (!Check.isNull(strategy.getOverlayType())) {
+            creativeParams.put("overlay_type", strategy.getOverlayType());
+        }
+        // 广告标签
+        if (!Check.isNull(strategy.getExposeTag())) {
+            creativeParams.put("expose_tag", strategy.getExposeTag());
+        }
+        // 广告标签2期
+        if (null!=strategy.getNewExposeTag()&&!"".equals(strategy.getNewExposeTag())) {
+            creativeParams.put("new_expose_tag", JSONArray.parseArray(strategy.getNewExposeTag()));
+        }
+        // 安卓下载中间页ID
+        if(null!=strategy.getSiteId()){
+            creativeParams.put("site_id",strategy.getSiteId());
+        }
+        if(null != strategy.getClickTrackUrl()&&!"".equals(strategy.getClickTrackUrl())){
+            creativeParams.put("click_track_url",strategy.getClickTrackUrl());
+        }
+        if(null != strategy.getImpressionUrl()&&!"".equals(strategy.getImpressionUrl())){
+            creativeParams.put("impression_url",strategy.getImpressionUrl());
+        }
+        // 第三方有效播放监测链接
+        if (!Check.isNull(strategy.getAdPhotoPlayedT3sUrl())) {
+            creativeParams.put("ad_photo_played_t3s_url", strategy.getAdPhotoPlayedT3sUrl());
+        }
+        if(null != strategy.getActionbarClickUrl()&&!"".equals(strategy.getActionbarClickUrl())){
+            creativeParams.put("actionbar_click_url",strategy.getActionbarClickUrl());
+        }
+        if(null!=strategy.getCreativeCategory()){
+            creativeParams.put("creative_category",strategy.getCreativeCategory());
+        }
+        if(null!=strategy.getCreativeTag()&&!"".equals(strategy.getCreativeTag())){
+            creativeParams.put("creative_tag",JSONArray.parseArray(strategy.getCreativeTag()));
+        }
+        return creativeParams;
+    }
+
+
+    private void createCreative(CtopOauthToken token,JSONObject creativeParams,Long campaignId,Long unitId,
+                                int creativeCnt,KuaiShouVideoGet videoGet){
+        creativeParams.put("creative_name","自定义创意_"+creativeCnt);
+        Map<String, Object> creativeCreateResult = kuaishouInterfaceService.creativeCreate
+                (token.getAccessToken(), token.getAccountId(), creativeParams,1);
+        Integer creativeCode = (Integer) creativeCreateResult.get("code");
+        String creativeMessage = (String) creativeCreateResult.get("message");
+        if(creativeCode != 0 ){
+            log.info("创意创建失败=>message:{}",creativeMessage);
+            return;
+        }
+        Long creativeId = (Long) creativeCreateResult.get("creativeId");
+        AiKuaishouStrategyMapCreative mapCreative = new AiKuaishouStrategyMapCreative();
+        mapCreative.setAccountId(token.getAccountId());
+        mapCreative.setCampaignId(campaignId);
+        mapCreative.setUnitId(unitId);
+        mapCreative.setVideoSignature(videoGet.getSignature());
+        mapCreative.setCreativeId(creativeId);
+        mapCreativeService.save(mapCreative);
+    }
+}

+ 222 - 86
module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/ai/service/impl/AiKuaishouNewCreateCampaignServiceImpl.java

@@ -6,7 +6,7 @@ import cn.com.ctop.common.module.entity.MaterialImageInfo;
 import cn.com.ctop.common.module.service.ICtopOauthTokenService;
 import cn.com.ctop.common.module.service.IMaterialCutFrameService;
 import cn.com.ctop.common.module.service.IMaterialImageInfoService;
-import cn.com.ctop.kuaishou.modules.ai.entity.AiKuaishouAccountTargetTemplate;
+import cn.com.ctop.kuaishou.modules.ai.entity.AiKuaishouAdvertiserStrategy;
 import cn.com.ctop.kuaishou.modules.ai.entity.AiKuaishouStrategyMapCreative;
 import cn.com.ctop.kuaishou.modules.ai.entity.KuaishouAccountCreativeOverrunInfo;
 import cn.com.ctop.kuaishou.modules.ai.service.IAiKuaishouNewCreateCampaign;
@@ -21,7 +21,6 @@ import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import lombok.extern.slf4j.Slf4j;
 import org.jeecg.common.util.DateUtils;
-import org.jeecg.common.util.JsonResourceUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -57,17 +56,19 @@ public class AiKuaishouNewCreateCampaignServiceImpl implements IAiKuaishouNewCre
     @Autowired
     private IKuaishouAccountCreativeOverrunInfoService overrunInfoService;
 
+    /**
+     * 单应用上新
+     * @param strategy
+     */
     @Override
-    public void kuaishouAiAdsNewMaterialCreativity(AiKuaishouAccountTargetTemplate targetTemplate) {
-        Long accountId = targetTemplate.getAccountId();
+    public void kuaishouAiAdsNewMaterialCreativityMultileAppids(AiKuaishouAdvertiserStrategy strategy) {
+        Long accountId = strategy.getAccountId();
         CtopOauthToken token = tokenService.getOauthTokenByAccountId(accountId.toString());
         if(null == token){
             log.info("token获取失败=>accountId:{}",accountId);
             return;
         }
 
-        // 2、执行素材的同步数据服务
-        // 2.1 执行 非素造的 视频拉取服务,时间过滤支持 yyyy-MM-dd, 拉取当天凌晨到此刻的数据
         kuaishouInterfaceService.getVideoList(token, DateUtils.date2Str(),DateUtils.date2Str());
 
         // 2.2 执行 素造的 视频拉取服务,时间过滤执行 yyyy-MM-dd HH:mm:ss
@@ -77,8 +78,11 @@ public class AiKuaishouNewCreateCampaignServiceImpl implements IAiKuaishouNewCre
         Long now = System.currentTimeMillis();
         String startTime = DateUtils.formatDate(new Date(now + timeStart*60*1000),"yyyy-MM-dd HH:mm:ss");
         String endTime = DateUtils.formatDate(new Date(now + timeEnd*60*1000),"yyyy-MM-dd HH:mm:ss");
+        if(null!=strategy.getSingleAppid()&&strategy.getSingleAppid() == 1){
+            //单一应用
+        }
         // 3、获取5分钟内,ctop_kuaishou_video_get 的视频数据,记为 N,如果有数据则执行下面步骤
-        List<KuaiShouVideoGet> newVideos = videoGetService.getNewVideoBetweenTime(accountId,startTime,endTime);
+        List<KuaiShouVideoGet> newVideos = videoGetService.getNewVideoBetweenTime(accountId,startTime,endTime,strategy.getChannelType(),null);
         int newVideosCnt = newVideos.size();
         if (newVideosCnt == 0){
             log.info("账户:{},{} 到 {} 这段时间没有上新素材",accountId, startTime, endTime);
@@ -106,14 +110,16 @@ public class AiKuaishouNewCreateCampaignServiceImpl implements IAiKuaishouNewCre
             String timestamp = DateUtils.formatDate(campaignDate,"yyyyMMddHHmmss");
             JSONObject campaignParams = new JSONObject();
             campaignParams.put("advertiser_id",token.getAccountId());
-            String campaignName = targetTemplate.getTitlePrefix() + "素材上新"+ targetTemplate.getTitleMiddle()+ timestamp;
+            String campaignName = strategy.getCampaignName().replace("自定义","素材上新")+timestamp;
             campaignParams.put("campaign_name",campaignName);
-            campaignParams.put("type",Integer.parseInt(targetTemplate.getMarketingGoal()));
+            campaignParams.put("type",strategy.getCampaignType());
+            //TODO 目前设定为不限
             campaignParams.put("day_budget",0L);
             Map<String, Object> campaignCreateResult = kuaishouInterfaceService.campaignCreate(token.getAccessToken(), token.getAccountId(), campaignParams);
             Integer code = (Integer) campaignCreateResult.get("code");
             String message = (String) campaignCreateResult.get("message");
             if(code != 0 ){
+                //TODO 写入日志信息表
                 log.info("计划创建失败=>message:{}",message);
                 return;
             }
@@ -122,7 +128,7 @@ public class AiKuaishouNewCreateCampaignServiceImpl implements IAiKuaishouNewCre
 
         //3、在“上新”计划中新增广告组,一个素材搭配5张封面,组成一个广告组
         String timestamp = DateUtils.formatDate(new Date(),"yyyyMMddHHmmss");
-        String unitNamePrefix = targetTemplate.getTitlePrefix() + "素材上新"+ targetTemplate.getTitleMiddle()+ timestamp;
+        String unitNamePrefix = strategy.getGroupName().replace("自定义","素材上新")+ timestamp;
         int unitCnt = 0;
         for(KuaiShouVideoGet videoItem: newVideos){
             KuaishouAccountCreativeOverrunInfo overrunInfo = overrunInfoService.getByParams(accountId,DateUtils.formatDate(new Date()));
@@ -131,7 +137,7 @@ public class AiKuaishouNewCreateCampaignServiceImpl implements IAiKuaishouNewCre
             }
             unitCnt ++;
             String unitName = unitNamePrefix + "-" + unitCnt;
-            JSONObject unitParams = createUnitParams(token, newCampaignId, targetTemplate, unitName);
+            JSONObject unitParams = createUnitParams(token, newCampaignId, strategy, unitName);
             Map<String, Object> unitCreateResult = kuaishouInterfaceService.adUnitCreate(token.getAccessToken(), token.getAccountId(), unitParams,1);
             Integer unitCode = (Integer) unitCreateResult.get("code");
             String unitMessage = (String) unitCreateResult.get("message");
@@ -143,19 +149,117 @@ public class AiKuaishouNewCreateCampaignServiceImpl implements IAiKuaishouNewCre
 
             // 每个组,搭配5个创意
             List<MaterialCutFrame> cutFrameList = materialCutFrameService.getListByVideoSignature(videoItem.getSignature());
-            List<MaterialImageInfo> orgFrameList = materialImageInfoService.getListByVideoSignature(videoItem.getSignature());
-            if ((null == cutFrameList||cutFrameList.isEmpty())&&(null == orgFrameList|| orgFrameList.isEmpty())){
+            if ((null == cutFrameList||cutFrameList.isEmpty())){
                 log.info("未获取到视频封面=>videoSignature:{}",videoItem.getSignature());
                 continue;
             }
-            JSONObject creativeParams = creativeParams(token, unitId, videoItem, targetTemplate);
-            createCreativeByImage(cutFrameList, orgFrameList,token, creativeParams, newCampaignId, unitId, videoItem,targetTemplate.getImageNumber());
+            JSONObject creativeParams = creativeParams(token, unitId, videoItem, strategy);
+            createCreativeByImage(cutFrameList,token, creativeParams, newCampaignId, unitId, videoItem,strategy.getImageCnt());
         }
     }
 
+    /**
+     * 单应用上新
+     * @param strategy
+     */
     @Override
-    public void kuaishouAiAdsHotMaterialCreativity(AiKuaishouAccountTargetTemplate targetTemplate) {
-        Long accountId = targetTemplate.getAccountId();
+    public void kuaishouAiAdsNewMaterialCreativity(AiKuaishouAdvertiserStrategy strategy) {
+        Long accountId = strategy.getAccountId();
+        CtopOauthToken token = tokenService.getOauthTokenByAccountId(accountId.toString());
+        if(null == token){
+            log.info("token获取失败=>accountId:{}",accountId);
+            return;
+        }
+
+        kuaishouInterfaceService.getVideoList(token, DateUtils.date2Str(),DateUtils.date2Str());
+
+        // 2.2 执行 素造的 视频拉取服务,时间过滤执行 yyyy-MM-dd HH:mm:ss
+        // 时间差,单位为分钟
+        int timeStart = -10;
+        int timeEnd = -5;
+        Long now = System.currentTimeMillis();
+        String startTime = DateUtils.formatDate(new Date(now + timeStart*60*1000),"yyyy-MM-dd HH:mm:ss");
+        String endTime = DateUtils.formatDate(new Date(now + timeEnd*60*1000),"yyyy-MM-dd HH:mm:ss");
+        // 3、获取5分钟内,ctop_kuaishou_video_get 的视频数据,记为 N,如果有数据则执行下面步骤
+        List<KuaiShouVideoGet> newVideos = videoGetService.getNewVideoBetweenTime(accountId,startTime,endTime,strategy.getChannelType(),null);
+        int newVideosCnt = newVideos.size();
+        if (newVideosCnt == 0){
+            log.info("账户:{},{} 到 {} 这段时间没有上新素材",accountId, startTime, endTime);
+            return;
+        }
+
+        //2、判断该账户下当天有没有“上新”计划,没有则创建一个“上新”计划
+        // time_filter_type 传入 "start_date",与 "end_date" 字段,且此字段为1时,按照创建时间进行筛选
+        JSONArray campaignList = kuaishouInterfaceService.getCampaignList(token, new Date(), new Date(),1);
+        boolean isHaveNewCampaign = false;
+        Long newCampaignId = 0L;
+        if (null!=campaignList&&campaignList.size()>0){
+            for(int i = 0;i<campaignList.size();i++){
+                JSONObject jsonObject = campaignList.getJSONObject(i);
+                if (jsonObject.getString("campaign_name").contains("素材上新")){
+                    isHaveNewCampaign = true;
+                    newCampaignId = jsonObject.getLong("campaign_id");
+                    break;
+                }
+            }
+        }
+        // 不存在“上新”计划,则创建一个计划
+        if (!isHaveNewCampaign){
+            Date campaignDate = new Date();
+            String timestamp = DateUtils.formatDate(campaignDate,"yyyyMMddHHmmss");
+            JSONObject campaignParams = new JSONObject();
+            campaignParams.put("advertiser_id",token.getAccountId());
+            String campaignName = strategy.getCampaignName().replace("自定义","素材上新")+timestamp;
+            campaignParams.put("campaign_name",campaignName);
+            campaignParams.put("type",strategy.getCampaignType());
+            //TODO 目前设定为不限
+            campaignParams.put("day_budget",0L);
+            Map<String, Object> campaignCreateResult = kuaishouInterfaceService.campaignCreate(token.getAccessToken(), token.getAccountId(), campaignParams);
+            Integer code = (Integer) campaignCreateResult.get("code");
+            String message = (String) campaignCreateResult.get("message");
+            if(code != 0 ){
+                //TODO 写入日志信息表
+                log.info("计划创建失败=>message:{}",message);
+                return;
+            }
+            newCampaignId = (Long) campaignCreateResult.get("campaignId");
+        }
+
+        //3、在“上新”计划中新增广告组,一个素材搭配5张封面,组成一个广告组
+        String timestamp = DateUtils.formatDate(new Date(),"yyyyMMddHHmmss");
+        String unitNamePrefix = strategy.getGroupName().replace("自定义","素材上新")+ timestamp;
+        int unitCnt = 0;
+        for(KuaiShouVideoGet videoItem: newVideos){
+            KuaishouAccountCreativeOverrunInfo overrunInfo = overrunInfoService.getByParams(accountId,DateUtils.formatDate(new Date()));
+            if(null!=overrunInfo){
+                return;
+            }
+            unitCnt ++;
+            String unitName = unitNamePrefix + "-" + unitCnt;
+            JSONObject unitParams = createUnitParams(token, newCampaignId, strategy, unitName);
+            Map<String, Object> unitCreateResult = kuaishouInterfaceService.adUnitCreate(token.getAccessToken(), token.getAccountId(), unitParams,1);
+            Integer unitCode = (Integer) unitCreateResult.get("code");
+            String unitMessage = (String) unitCreateResult.get("message");
+            if(unitCode != 0 ){
+                log.info("组创建失败=>accountId:{};message:{}",accountId,unitMessage);
+                continue;
+            }
+            Long unitId = (Long) unitCreateResult.get("unitId");
+
+            // 每个组,搭配5个创意
+            List<MaterialCutFrame> cutFrameList = materialCutFrameService.getListByVideoSignature(videoItem.getSignature());
+            if ((null == cutFrameList||cutFrameList.isEmpty())){
+                log.info("未获取到视频封面=>videoSignature:{}",videoItem.getSignature());
+                continue;
+            }
+            JSONObject creativeParams = creativeParams(token, unitId, videoItem, strategy);
+            createCreativeByImage(cutFrameList,token, creativeParams, newCampaignId, unitId, videoItem,strategy.getImageCnt());
+        }
+    }
+
+    @Override
+    public void kuaishouAiAdsHotMaterialCreativity(AiKuaishouAdvertiserStrategy strategy) {
+        Long accountId = strategy.getAccountId();
         CtopOauthToken token = tokenService.getOauthTokenByAccountId(accountId.toString());
         if(null == token){
             log.info("token获取失败=>accountId:{}",accountId);
@@ -189,9 +293,9 @@ public class AiKuaishouNewCreateCampaignServiceImpl implements IAiKuaishouNewCre
             String timestamp = DateUtils.formatDate(campaignDate,"yyyyMMddHHmmss");
             JSONObject campaignParams = new JSONObject();
             campaignParams.put("advertiser_id",token.getAccountId());
-            String campaignName = targetTemplate.getTitlePrefix() + "爆量素材"+ targetTemplate.getTitleMiddle() + timestamp;
+            String campaignName = strategy.getCampaignName().replace("自定义","爆量素材")+ timestamp;
             campaignParams.put("campaign_name",campaignName);
-            campaignParams.put("type",Integer.parseInt(targetTemplate.getMarketingGoal()));
+            campaignParams.put("type",strategy.getCampaignType());
             campaignParams.put("day_budget",0L);
             Map<String, Object> campaignCreateResult = kuaishouInterfaceService.campaignCreate(token.getAccessToken(), token.getAccountId(), campaignParams);
             Integer code = (Integer) campaignCreateResult.get("code");
@@ -205,7 +309,7 @@ public class AiKuaishouNewCreateCampaignServiceImpl implements IAiKuaishouNewCre
 
         //3、在“上新”计划中新增广告组,一个素材搭配5张封面,组成一个广告组
         String timestamp = DateUtils.formatDate(new Date(),"yyyyMMddHHmmss");
-        String unitNamePrefix = targetTemplate.getTitlePrefix() + "爆量素材"+ targetTemplate.getTitleMiddle()+timestamp;
+        String unitNamePrefix = strategy.getGroupName().replace("自定义","爆量素材")+timestamp;
         int unitCnt = 0;
         for(KuaiShouVideoGet videoItem: highQualityVideos){
             KuaishouAccountCreativeOverrunInfo overrunInfo  =  overrunInfoService.getByParams(accountId,DateUtils.formatDate(new Date()));
@@ -214,7 +318,7 @@ public class AiKuaishouNewCreateCampaignServiceImpl implements IAiKuaishouNewCre
             }
             unitCnt ++;
             String unitName = unitNamePrefix + "-" + unitCnt;
-            JSONObject unitParams = createUnitParams(token, newCampaignId, targetTemplate, unitName);
+            JSONObject unitParams = createUnitParams(token, newCampaignId, strategy, unitName);
             Map<String, Object> unitCreateResult = kuaishouInterfaceService.adUnitCreate(token.getAccessToken(), token.getAccountId(), unitParams,1);
             Integer unitCode = (Integer) unitCreateResult.get("code");
             String unitMessage = (String) unitCreateResult.get("message");
@@ -231,14 +335,15 @@ public class AiKuaishouNewCreateCampaignServiceImpl implements IAiKuaishouNewCre
                 log.info("未获取到视频封面=>videoSignature:{}",videoItem.getSignature());
                 continue;
             }
-            JSONObject creativeParams = creativeParams(token, unitId, videoItem, targetTemplate);
-            createCreativeByImage(cutFrameList, orgFrameList,token, creativeParams, newCampaignId, unitId, videoItem,targetTemplate.getImageNumber());
+            JSONObject creativeParams = creativeParams(token, unitId, videoItem, strategy);
+            createCreativeByImage(cutFrameList,token, creativeParams, newCampaignId, unitId, videoItem,strategy.getImageCnt());
         }
 
     }
+
     @Override
-    public void kuaishouAiAddNewMaterialCreativity(AiKuaishouAccountTargetTemplate targetTemplate,Integer matNum) {
-        Long accountId = targetTemplate.getAccountId();
+    public void kuaishouAiAddZeroMaterialCreativity(AiKuaishouAdvertiserStrategy strategy,Integer matNum) {
+        Long accountId = strategy.getAccountId();
         CtopOauthToken token = tokenService.getOauthTokenByAccountId(accountId.toString());
         if(null == token){
             log.info("token获取失败=>accountId:{}",accountId);
@@ -273,9 +378,9 @@ public class AiKuaishouNewCreateCampaignServiceImpl implements IAiKuaishouNewCre
             String timestamp = DateUtils.formatDate(campaignDate,"yyyyMMddHHmmss");
             JSONObject campaignParams = new JSONObject();
             campaignParams.put("advertiser_id",token.getAccountId());
-            String campaignName = targetTemplate.getTitlePrefix() + "素材上新"+ targetTemplate.getTitleMiddle()+ timestamp;
+            String campaignName = strategy.getCampaignName().replace("自定义","素材上新")+timestamp;
             campaignParams.put("campaign_name",campaignName);
-            campaignParams.put("type",Integer.parseInt(targetTemplate.getMarketingGoal()));
+            campaignParams.put("type",strategy.getCampaignType());
             campaignParams.put("day_budget",0L);
             Map<String, Object> campaignCreateResult = kuaishouInterfaceService.campaignCreate(token.getAccessToken(), token.getAccountId(), campaignParams);
             Integer code = (Integer) campaignCreateResult.get("code");
@@ -287,9 +392,9 @@ public class AiKuaishouNewCreateCampaignServiceImpl implements IAiKuaishouNewCre
             newCampaignId = (Long) campaignCreateResult.get("campaignId");
         }
 
-        //3、在“上新”计划中新增广告组,一个素材搭配5张封面,组成一个广告组
+        //3、在“上新”计划中新增广告组,一个素材搭配n张封面,组成一个广告组
         String timestamp = DateUtils.formatDate(new Date(),"yyyyMMddHHmmss");
-        String unitNamePrefix = targetTemplate.getTitlePrefix() + "素材上新"+ targetTemplate.getTitleMiddle()+ timestamp;
+        String unitNamePrefix = strategy.getGroupName().replace("自定义","素材上新")+timestamp;
         int unitCnt = 0;
         for(KuaishouVideoRelateCreatives videoItem: kuaishouVideoRelateCreatives){
             KuaishouAccountCreativeOverrunInfo overrunInfo  =  overrunInfoService.getByParams(accountId,DateUtils.formatDate(new Date()));
@@ -302,7 +407,7 @@ public class AiKuaishouNewCreateCampaignServiceImpl implements IAiKuaishouNewCre
                 log.info("未获取到视频信息=>photoId:{}",videoItem.getPhotoId());
                 continue;
             }
-            // 每个组,搭配5个创意
+            // 每个组,搭配n个创意
             List<MaterialCutFrame> cutFrameList = materialCutFrameService.getListByVideoSignature(videoGet.getSignature());
             List<MaterialImageInfo> orgFrameList = materialImageInfoService.getListByVideoSignature(videoGet.getSignature());
             if ((null == cutFrameList||cutFrameList.isEmpty())&&(null == orgFrameList|| orgFrameList.isEmpty())){
@@ -310,7 +415,7 @@ public class AiKuaishouNewCreateCampaignServiceImpl implements IAiKuaishouNewCre
                 continue;
             }
             String unitName = unitNamePrefix + "-" + unitCnt;
-            JSONObject unitParams = createUnitParams(token, newCampaignId, targetTemplate, unitName);
+            JSONObject unitParams = createUnitParams(token, newCampaignId, strategy, unitName);
             Map<String, Object> unitCreateResult = kuaishouInterfaceService.adUnitCreate(token.getAccessToken(), token.getAccountId(), unitParams,1);
             Integer unitCode = (Integer) unitCreateResult.get("code");
             String unitMessage = (String) unitCreateResult.get("message");
@@ -319,39 +424,40 @@ public class AiKuaishouNewCreateCampaignServiceImpl implements IAiKuaishouNewCre
                 continue;
             }
             Long unitId = (Long) unitCreateResult.get("unitId");
-            JSONObject creativeParams = creativeParams(token, unitId, videoGet, targetTemplate);
-            createCreativeByImage(cutFrameList, orgFrameList,token, creativeParams, newCampaignId, unitId, videoGet,targetTemplate.getImageNumber());
-            videoItem.setCreativeCount(5);
+            JSONObject creativeParams = creativeParams(token, unitId, videoGet, strategy);
+            createCreativeByImage(cutFrameList,token, creativeParams, newCampaignId, unitId, videoGet,strategy.getImageCnt());
+            videoItem.setCreativeCount(videoItem.getCreativeCount()+strategy.getImageCnt());
             relateCreativesService.updateById(videoItem);
         }
     }
 
 
-    private JSONObject creativeParams(CtopOauthToken token,Long unitId,KuaiShouVideoGet videoItem,AiKuaishouAccountTargetTemplate targetTemplate){
+    private JSONObject creativeParams(CtopOauthToken token,Long unitId,KuaiShouVideoGet videoItem,AiKuaishouAdvertiserStrategy strategy){
         JSONObject creativeParams = new JSONObject();
         creativeParams.put("advertiser_id",token.getAccountId());
         creativeParams.put("unit_id",unitId);
         creativeParams.put("photo_id",videoItem.getPhotoId());
         creativeParams.put("creative_material_type",videoItem.getMaterialType());
-        creativeParams.put("action_bar_text",targetTemplate.getActionBarText());
-        creativeParams.put("description",targetTemplate.getCreativeDescription());
+        creativeParams.put("action_bar_text",strategy.getActionBarText());
+        creativeParams.put("description",strategy.getDescription());
         // 安卓下载中间页ID
-        JSONArray siteIdArray = JSONArray.parseArray(targetTemplate.getSiteId());
-        if(null == siteIdArray||!siteIdArray.isEmpty()){
-            JSONObject siteObject = siteIdArray.getJSONObject(0);
-            Long siteId = siteObject.getLong("siteId");
-            if(null!=siteId){
-                creativeParams.put("site_id",siteId);
-            }
+        if(null!=strategy.getSiteId()){
+                creativeParams.put("site_id",strategy.getSiteId());
+        }
+        if(null != strategy.getClickTrackUrl()&&!"".equals(strategy.getClickTrackUrl())){
+            creativeParams.put("click_track_url",strategy.getClickTrackUrl());
         }
-        if(null != targetTemplate.getClickTrackUrl()&&!"".equals(targetTemplate.getClickTrackUrl())){
-            creativeParams.put("click_track_url",targetTemplate.getClickTrackUrl());
+        if(null != strategy.getImpressionUrl()&&!"".equals(strategy.getImpressionUrl())){
+            creativeParams.put("impression_url",strategy.getImpressionUrl());
         }
-        if(null != targetTemplate.getImpressionUrl()&&!"".equals(targetTemplate.getImpressionUrl())){
-            creativeParams.put("impression_url",targetTemplate.getImpressionUrl());
+        if(null != strategy.getActionbarClickUrl()&&!"".equals(strategy.getActionbarClickUrl())){
+            creativeParams.put("actionbar_click_url",strategy.getActionbarClickUrl());
         }
-        if(null != targetTemplate.getActionbarClickUrl()&&!"".equals(targetTemplate.getActionbarClickUrl())){
-            creativeParams.put("actionbar_click_url",targetTemplate.getActionbarClickUrl());
+        if(null!=strategy.getCreativeCategory()){
+            creativeParams.put("creative_category",strategy.getCreativeCategory());
+        }
+        if(null!=strategy.getCreativeTag()&&!"".equals(strategy.getCreativeTag())){
+            creativeParams.put("creative_tag",JSONArray.parseArray(strategy.getCreativeTag()));
         }
         return creativeParams;
     }
@@ -379,80 +485,110 @@ public class AiKuaishouNewCreateCampaignServiceImpl implements IAiKuaishouNewCre
     }
 
 
-    private JSONObject createUnitParams(CtopOauthToken token, Long campaignId,  AiKuaishouAccountTargetTemplate targetTemplate,
+    private JSONObject createUnitParams(CtopOauthToken token, Long campaignId,  AiKuaishouAdvertiserStrategy strategy,
                                         String unitName) {
         // 拼装创建组的入参 json
         JSONObject unitParams = new JSONObject();
         unitParams.put("advertiser_id",token.getAccountId());
         unitParams.put("campaign_id",campaignId);
         unitParams.put("unit_name", unitName);
-        unitParams.put("bid_type",targetTemplate.getBidType());
-        unitParams.put("ocpx_action_type",targetTemplate.getOcpxActionType());
+        unitParams.put("bid_type",strategy.getBidType());
+        unitParams.put("ocpx_action_type",strategy.getOcpxActionType());
 
-        if(null!=targetTemplate.getUseAppMarket()&&!"".equals(targetTemplate.getUseAppMarket())){
-            unitParams.put("use_app_market",Integer.parseInt(targetTemplate.getUseAppMarket()));
+        if(null!=strategy.getUseAppMarket()){
+            unitParams.put("use_app_market",strategy.getUseAppMarket());
         }
-        if(null!=targetTemplate.getAppStore()&&!"".equals(targetTemplate.getAppStore())){
-            unitParams.put("app_store",JSONArray.parseArray(targetTemplate.getAppStore()));
+        if(null!=strategy.getAppStore()&&!"".equals(strategy.getAppStore())){
+            unitParams.put("app_store",JSONArray.parseArray(strategy.getAppStore()));
         }
 
         // 在本策略中,都是 OCPM 的出价方式
-        unitParams.put("cpa_bid",targetTemplate.getCpaBid());
-        unitParams.put("scene_id",JSONArray.parseArray(targetTemplate.getSceneId()));
+        unitParams.put("cpa_bid",strategy.getCpaBid());
+        unitParams.put("scene_id",JSONArray.parseArray(strategy.getSceneId()));
         unitParams.put("unit_type",4);
 
         // 格式为yyyy-MM-dd,需大于等于当前时间
         unitParams.put("begin_time",DateUtils.formatDate(new Date()));
 
-        JSONArray appIds = JSONArray.parseArray(targetTemplate.getAppIds());
+        JSONArray appIds = JSONArray.parseArray(strategy.getAppIds());
         if(null!=appIds&&!appIds.isEmpty()){
             unitParams.put("app_id",appIds.getLong(0));
         }
         unitParams.put("show_mode",2);
         unitParams.put("speed",1);
+        //是否开启智能抽帧
+        if(null!=strategy.getSmartCover()){
+            unitParams.put("smart_cover",strategy.getSmartCover());
+        }
+        //是否开启素材挖掘
+        if(null!=strategy.getAssetMining()){
+            unitParams.put("asset_mining",strategy.getAssetMining());
+        }
+
 
         // 设置定向内容
         JSONObject targetJsonObject = new JSONObject();
-        targetJsonObject.put("region",JSONArray.parseArray(targetTemplate.getRegion()));
-        targetJsonObject.put("ages_range",JSONArray.parseArray(targetTemplate.getAgesRange()));
-        targetJsonObject.put("gender",targetTemplate.getGender());
-        targetJsonObject.put("platform_os",targetTemplate.getPlatformOs());
-        JSONArray population = JSONArray.parseArray(targetTemplate.getPopulation());
-        if(null!=population&&!population.isEmpty()){
+        if(null!=strategy.getRegion()&&!"".equals(strategy.getRegion())){
+            targetJsonObject.put("region",JSONArray.parseArray(strategy.getRegion()));
+        }
+        if(null!=strategy.getAgesRange()&&!"".equals(strategy.getAgesRange())){
+            targetJsonObject.put("ages_range",JSONArray.parseArray(strategy.getAgesRange()));
+        }
+        if(null!=strategy.getGender()){
+            targetJsonObject.put("gender",strategy.getGender());
+        }
+        if(null!=strategy.getPlatformOs()){
+            targetJsonObject.put("platform_os",strategy.getPlatformOs());
+        }
+        if(null!=strategy.getAndroidOsv()){
+            targetJsonObject.put("android_osv",strategy.getAndroidOsv());
+        }
+        if(null!=strategy.getIosOsv()){
+            targetJsonObject.put("ios_osv",strategy.getIosOsv());
+        }
+        if(null!=strategy.getDeviceBrand()&&!"".equals(strategy.getDeviceBrand())&&!"[]".equals(strategy.getDeviceBrand())){
+            targetJsonObject.put("device_brand",JSONArray.parseArray(strategy.getDeviceBrand()));
+        }
+        if(null!=strategy.getDevicePrice()&&!"".equals(strategy.getDevicePrice())&&!"[]".equals(strategy.getDevicePrice())){
+            targetJsonObject.put("device_price",JSONArray.parseArray(strategy.getDevicePrice()));
+        }
+        if(null!=strategy.getPopulation()&&!"".equals(strategy.getPopulation())){
+            JSONArray population = JSONArray.parseArray(strategy.getPopulation());
             targetJsonObject.put("population",population);
         }
-        if(null!=targetTemplate.getFilterConvertedLevel()&&targetTemplate.getFilterConvertedLevel()!=0){
-            targetJsonObject.put("filter_converted_level",targetTemplate.getFilterConvertedLevel());
+        if(null!=strategy.getFilterConvertedLevel()&&strategy.getFilterConvertedLevel()!=0){
+            targetJsonObject.put("filter_converted_level",strategy.getFilterConvertedLevel());
         }
-        JSONArray excludePopulation = JSONArray.parseArray(targetTemplate.getExcludePopulation());
-        if(null!=excludePopulation&&!excludePopulation.isEmpty()){
+        if(null!=strategy.getExcludePopulation()&&!"".equals(strategy.getExcludePopulation())){
+            JSONArray excludePopulation = JSONArray.parseArray(strategy.getExcludePopulation());
             targetJsonObject.put("exclude_population",excludePopulation);
         }
+        //是否开启智能扩量
+        if(null!=strategy.getIsOpen()&&strategy.getIsOpen().equals(1)){
+            JSONObject intelliExtend = new JSONObject();
+            intelliExtend.put("is_open",1);
+            if(null!=strategy.getNoAgeBreak()&&strategy.getNoAgeBreak().equals(1)){
+                intelliExtend.put("no_age_break",1);
+            }
+            if(null!=strategy.getNoGenderBreak()&&strategy.getNoGenderBreak().equals(1)){
+                intelliExtend.put("no_gender_break",1);
+            }
+            if(null!=strategy.getNoAreaBreak()&&strategy.getNoAreaBreak().equals(1)){
+                intelliExtend.put("no_area_break",1);
+            }
+            targetJsonObject.put("intelli_extend",intelliExtend);
+        }
         unitParams.put("target",targetJsonObject);
         return unitParams;
     }
 
 
-    private void createCreativeByImage(List<MaterialCutFrame> cutFrameList, List<MaterialImageInfo> orgFrameList,
-                                       CtopOauthToken token, JSONObject creativeParams,
+    private void createCreativeByImage(List<MaterialCutFrame> cutFrameList, CtopOauthToken token, JSONObject creativeParams,
                                        Long campaignId, Long unitId, KuaiShouVideoGet videoItem,
                                        int imageNumber){
         int creativeCnt  = 1;
-        if (null!=orgFrameList&&!orgFrameList.isEmpty()) {
-            for (int i = 0; i < orgFrameList.size(); i++) {
-                String imageCode = orgFrameList.get(i).getCode();
-                String imageUrl = orgFrameList.get(i).getUrl();
-                String imageToken = getImageToken(imageUrl,imageCode,token.getAccountId(),token.getAccessToken());
-                creativeParams.put("image_token",imageToken);
-                createCreative(token, creativeParams, campaignId, unitId, creativeCnt,videoItem);
-                creativeCnt++;
-                if (creativeCnt > imageNumber) {
-                    break;
-                }
-            }
-        }
 
-        if ((null!=cutFrameList&&!cutFrameList.isEmpty()) && (creativeCnt<=15)){
+        if ((null!=cutFrameList&&!cutFrameList.isEmpty())){
             for (int i = 0; i < cutFrameList.size(); i++) {
                 String imageCode = cutFrameList.get(i).getSignature();
                 String imageUrl = cutFrameList.get(i).getUrl();

+ 2 - 1
module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/ai/service/impl/AiStrategyServiceImpl.java

@@ -24,6 +24,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import javax.annotation.Resource;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -56,7 +57,7 @@ public class AiStrategyServiceImpl implements IAiStrategyService {
     private IKuaiShouImageGetService imageGetService;
     @Autowired
     private IKuaiShouMaterialUploadService materialUploadService;
-    @Autowired
+    @Resource
     private KuaiShouVideoGetMapper videoGetMapper;
 
     /**

+ 1 - 1
module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/batch/Enums/CampaignTypeEnum.java

@@ -20,7 +20,7 @@ public enum CampaignTypeEnum {
     public static String getNameByType(Integer type) {
         for (CampaignTypeEnum campaignType : CampaignTypeEnum.values()) {
 
-            if (campaignType.getType() == type) {
+            if (campaignType.getType().equals(type)) {
                 return campaignType.getValue();
             }
         }

+ 1 - 1
module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/batch/service/IKuaiShouVideoGetService.java

@@ -27,7 +27,7 @@ public interface IKuaiShouVideoGetService extends IService<KuaiShouVideoGet> {
 
     List<KuaiShouVideoGet> getNewVideoDescDate(Long accountId, Integer newVideoCnt);
 
-    List<KuaiShouVideoGet> getNewVideoBetweenTime(Long accountId, String startTime, String endTime);
+    List<KuaiShouVideoGet> getNewVideoBetweenTime(Long accountId, String startTime, String endTime,Integer channelType,String appVersion);
 
     List<JSONObject> getVideoListByMap(Map<String, Object> requestMap);
 

+ 8 - 1
module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/batch/service/impl/KuaiShouVideoGetServiceImpl.java

@@ -151,7 +151,7 @@ public class KuaiShouVideoGetServiceImpl extends ServiceImpl<KuaiShouVideoGetMap
 
 
     @Override
-    public List<KuaiShouVideoGet> getNewVideoBetweenTime(Long accountId, String startTime, String endTime) {
+    public List<KuaiShouVideoGet> getNewVideoBetweenTime(Long accountId, String startTime, String endTime,Integer channelType,String appVersion) {
         QueryWrapper<KuaiShouVideoGet> queryWrapper = new QueryWrapper<>();
         if (null != accountId && accountId != 0) {
             queryWrapper.eq("account_id", accountId);
@@ -160,6 +160,13 @@ public class KuaiShouVideoGetServiceImpl extends ServiceImpl<KuaiShouVideoGetMap
             queryWrapper.le("stat_date", endTime);
             queryWrapper.gt("stat_date", startTime);
         }
+        if(null!=channelType&&channelType!=2){
+            queryWrapper.eq("channel_type",channelType);
+        }
+
+        if(null!=appVersion&&!appVersion.trim().equals("")){
+            queryWrapper.likeLeft("photo_name",appVersion);
+        }
         return this.list(queryWrapper);
     }
 

+ 1 - 1
module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/batch/service/impl/KuaishouCampaignCopyDataServiceImpl.java

@@ -467,7 +467,7 @@ public class KuaishouCampaignCopyDataServiceImpl extends ServiceImpl<KuaishouCam
                 try {
                     log.info("开始多线程执行创建创意,accountId:{},新组:{},老组:{}", token.getAccountId(), unitId, copyUnitId);
                     kuaiShouGroupService.getCreativeByUnit(token.getAccessToken(), token.getAccountId(), copyUnitId);
-                    Thread.sleep(200l);
+                    Thread.sleep(200L);
                     batchService.copyCreative(token.getAccountId(), unitId, copyUnitId, null);
                 } catch (Exception e) {
                     e.printStackTrace();

+ 1 - 0
module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/batch/service/impl/KuaishouStrategyServiceImpl.java

@@ -122,6 +122,7 @@ public class KuaishouStrategyServiceImpl extends ServiceImpl<KuaishouStrategyMap
      * @throws
      * @author ZHAOXA
      */
+    @Override
     public Map<String, Object> createPlanLevelStrategy(CtopOauthToken oauthToken, JSONObject data) {
         JSONObject planJson = new JSONObject();
         /**计划类型

+ 1 - 0
module-toutiao/src/main/java/cn/com/ctop/toutiao/modules/adlab/service/impl/CtopAdlabProjectDetailServiceImpl.java

@@ -30,6 +30,7 @@ public class CtopAdlabProjectDetailServiceImpl extends ServiceImpl<CtopAdlabProj
     /**
      * 新建投放管家项目入库
      */
+    @Override
     public void putStorage(List<JSONObject> params){
         params.forEach(it->{
             JSONObject group = getProjectService.getGroup(ctopOauthTokenService.getTokenByAccountId(it.getLong("accountId")), it.getLong("accountId"), it.getLong("groupId"));

+ 6 - 6
module-toutiao/src/main/java/cn/com/ctop/toutiao/modules/report/utils/ApkUtils.java

@@ -128,13 +128,13 @@ public class ApkUtils {
         return (float) (complex & 0xFFFFFF00) * RADIX_MULTS[(complex >> 4) & 3];
     }
 
-    private static final float RADIX_MULTS[] =
+    private static final float[] RADIX_MULTS =
             {
                     0.00390625F, 3.051758E-005F,
                     1.192093E-007F, 4.656613E-010F
             };
-    private static final String DIMENSION_UNITS[] = { "px", "dip", "sp", "pt", "in", "mm", "", "" };
-    private static final String FRACTION_UNITS[] = { "%", "%p", "", "", "", "", "", "" };
+    private static final String[] DIMENSION_UNITS = { "px", "dip", "sp", "pt", "in", "mm", "", "" };
+    private static final String[] FRACTION_UNITS = { "%", "%p", "", "", "", "", "", "" };
 
     /**
      * 读取ipa
@@ -157,14 +157,14 @@ public class ApkUtils {
                     String name = ze.getName();
                     if (null != name &&
                             name.toLowerCase().contains(".app/info.plist")) {
-                        ByteArrayOutputStream _copy = new
+                        ByteArrayOutputStream copy = new
                                 ByteArrayOutputStream();
                         int chunk = 0;
                         byte[] data = new byte[1024];
                         while(-1!=(chunk=zipIns.read(data))){
-                            _copy.write(data, 0, chunk);
+                            copy.write(data, 0, chunk);
                         }
-                        infoIs = new ByteArrayInputStream(_copy.toByteArray());
+                        infoIs = new ByteArrayInputStream(copy.toByteArray());
                         rootDict = (NSDictionary) PropertyListParser.parse(infoIs);
 
                         //我们可以根据info.plist结构获取任意我们需要的东西