songyh преди 4 години
родител
ревизия
5894adb571
променени са 19 файла, в които са добавени 1245 реда и са изтрити 245 реда
  1. 29 129
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/dockapi/marketing.java
  2. 7 7
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/entity/AiBytedanceAdvertiserStrategy.java
  3. 50 0
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/entity/BytedanceVideoSlogenInfo.java
  4. 14 0
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/mapper/BytedanceVideoSlogenInfoMapper.java
  5. 5 0
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/mapper/xml/BytedanceVideoSlogenInfoMapper.xml
  6. 0 8
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/service/IAiBytedanceAdvertiserStrategyService.java
  7. 1 0
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/service/IByteDanceCampaignService.java
  8. 20 0
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/service/IBytedanceVideoSlogenInfoService.java
  9. 570 64
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/service/impl/AiBytedanceAdvertiserStrategyServiceImpl.java
  10. 15 0
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/service/impl/ByteDanceCampaignServiceImpl.java
  11. 46 0
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/service/impl/BytedanceVideoSlogenInfoServiceImpl.java
  12. 166 0
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/entity/MaterialInfo.java
  13. 38 0
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/mapper/MaterialInfoMapper.java
  14. 139 0
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/mapper/xml/MaterialInfoMapper.xml
  15. 15 0
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/service/IMaterialInfoService.java
  16. 2 14
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/service/impl/FileInfoServiceImpl.java
  17. 39 0
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/service/impl/MaterialInfoServiceImpl.java
  18. 63 0
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/utils/StringUtils.java
  19. 26 23
      jeecg-boot-bytedance/src/main/resources/bytedance_config.properties

+ 29 - 129
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/dockapi/marketing.java

@@ -35,8 +35,7 @@ import java.util.Map;
  **/
 
 @Slf4j
-public class marketing {
-
+public class Marketing {
     private static final String urlPath = PropertiesUtils.getValue("bytedance_config", "bytedance_api_url");
 
 
@@ -244,56 +243,48 @@ public class marketing {
 
     /**
      *
-     * @description: 创建广告组
-     * @param token
-     * @param campaignName 广告组名称
-     * @param budgetMode 广告组预算类型
-     *          //BUDGET_MODE_INFINITE 不限
-     *         //BUDGET_MODE_DAY 日预算
-     *         //BUDGET_MODE_TOTAL 总预算
-     * @param budget 广告组预算
-     *               取值范围: ≥ 0
-     *               当budget_mode为"BUDGET_MODE_DAY"时,必填,且日预算不少于300元
-     *  landingType 广告组推广目的 允许值:
-     *         "LINK","APP","DPA","GOODS","STORE","SHOP","AWEME"
-     * @return: org.jeecg.common.api.vo.Result
+     * 创建广告组
+     * @param token 授权信息
+     * @param params 广告组名称
+     * @return org.jeecg.common.api.vo.Result
      */
-    public static Result createCampaign(CtopOauthToken token,String campaignName,String budgetMode, Integer budget,String landingType) {
-        JSONObject param = new JSONObject();
-        //广告主id
-        param.put("advertiser_id",token.getAccountId());
-        //广告组名称,长度为1-100个字符,其中1个中文字符算2位
-        param.put("campaign_name",campaignName);
-        //广告组状态 "enable","disable"默认值:enable开启状态
-        param.put("operation","enable");
-        //广告组预算类型 BUDGET_MODE_INFINITE-不限  BUDGET_MODE_DAY-日预算  BUDGET_MODE_TOTAL-总预算
-        param.put("budget_mode", budgetMode);
-        //广告组预算
-        param.put("budget",budget);
-        //广告组推广目的
-        param.put("landing_type",landingType);
-        //移除key 为空的 json
-        param = Check.jsonRemoveEmpty(param);
-
+    public static Result createCampaign(CtopOauthToken token,JSONObject params) {
         // api创建组
         JSONObject data = HttpUtils.bytedancePostRequest(token.getAccessToken(),
                 urlPath+PropertiesUtils.getValue("bytedance_config", "bytedance_v2_campaign_create"),
-                param);
+                params);
         if(data == null){
-            log.error("创建广告组异常=>param:{}",param.toJSONString());
+            log.error("创建广告组异常=>param:{}",params.toJSONString());
             return Result.error("头条API创建广告组异常");
         }
         Integer code = data.getInteger("code");
         String message = data.getString("message");
         if(null == code||!code.equals(0)){
-            log.error("创建广告组数据异常=>{},parmas:{}",message,param.toJSONString());
+            log.error("创建广告组数据异常=>{},parmas:{}",message,params.toJSONString());
             return Result.error(message);
         }
         //广告组id
         return Result.successMsg("广告组创建成功",data.getJSONObject("data").getLong("campaign_id"));
     }
 
-
+    public static JSONObject videoCoverSuggest(CtopOauthToken token,JSONObject params){
+        // api创建获取视频推荐封面
+        JSONObject result = HttpUtils.bytedanceGetRequest(token.getAccessToken(),
+                urlPath+PropertiesUtils.getValue("bytedance_config", "bytedance_v2_tools_video_cover_suggest"),
+                params);
+        if(result == null){
+            log.error("获取视频推荐封面异常=>param:{}",params.toJSONString());
+            return null;
+        }
+        Integer code = result.getInteger("code");
+        String message = result.getString("message");
+        if(null == code||!code.equals(0)){
+            log.error("获取视频推荐封面异常=>{},parmas:{}",message,params.toJSONString());
+            return null;
+        }
+        //广告组id
+        return result.getJSONObject("data");
+    }
 
 
 
@@ -302,109 +293,18 @@ public class marketing {
      * @description: 创建广告计划
      *
      * @param token
-     * @param campaignId 广告组id
+     * @param params 广告组id
      * @param strategy 入参
      * @return: org.jeecg.common.api.vo.Result
      * @author: zianY
      */
-    public static Result createAdvertiserPlan(CtopOauthToken token, Long campaignId, AiBytedanceAdvertiserStrategy strategy) {
-
-        JSONObject params = new JSONObject();
-        //广告主ID
-        params.put("advertiser_id", strategy.getAccountId());
-        //广告组ID
-        params.put("campaign_id", campaignId);
-        //广告计划名称,长度为1-100个字符,其中1个中文字符算2位。名称不可重复,否则会报错
-        params.put("name", strategy.getAdName());
-        //计划状态 默认值: "enable"开启状态 允许值: "enable"开启,"disable"关闭
-        params.put("operation", BytedanceConstant.OPERATION_ENABLE);
-        // 投放范围  "DEFAULT"默认, "UNION"穿山甲
-        params.put("delivery_range", strategy.getAdDeliveryRange() == null ? "DEFAULT" : strategy.getAdDeliveryRange());
-        //投放形式(穿山甲视频创意类型) 当delivery_range为"UNION"时必填
-        // 允许值: "ORIGINAL_VIDEO"原生, "REWARDED_VIDEO"激励视频,"SPLASH_VIDEO"开屏
-       // params.put("union_video_type", byteDanceAdvertisePlan.getUnionVideoType() == null ? "ORIGINAL_VIDEO" : byteDanceAdvertisePlan.getUnionVideoType());
-        //投放内容
-        //推广目的 为应用推广(landing_type=APP)时投放目标参数
-        if ("APP".equals(strategy.getCampaignLandingType())) {
-            //下载方式  可选值:DOWNLOAD_URL下载链接,QUICK_APP_URL快应用+下载链接,EXTERNAL_URL落地页链接
-            params.put("download_type", strategy.getAdDownloadType());
-            //下载链接
-            // 类型为下载链接
-            if ("DOWNLOAD_URL".equals(strategy.getAdDownloadType())){
-                params.put("download_url", strategy.getAdDownloadUrl());
-                //下载的应用类型,当download_type为DOWNLOAD_URL时必填
-                //允许值: "APP_ANDROID"Android APP, "APP_IOS"IOS APP
-                params.put("app_type", strategy.getAdAppType());
-                params.put("package", strategy.getAdPackage());
-            }
-            // 类型为 快应用+下载链接
-            if ("QUICK_APP_URL".equals(strategy.getAdDownloadType())){
-                params.put("quick_app_url", strategy.getAdDownloadUrl());
-            }
-            // 类型为下载链接
-            if ("EXTERNAL_URL".equals(strategy.getAdDownloadType())){
-                params.put("external_url", strategy.getAdDownloadUrl());
-            }
-        }
-        //转化目标
-        params.put("convert_id", strategy.getAdConvertId());
-        //直达链接(点击唤起APP)
-        params.put("open_url", strategy.getAdOpenUrl());
-        //搜索快投功能,允许值:HAS_OPEN:启用,DISABLED:不启用
-        //params.put("feed_delivery_search", "");
-        //用户定向
-        //允许值: "CITY"省市, "COUNTY"区县, "BUSINESS_DISTRICT"商圈,"NONE"不限
-        params.put("district", strategy.getAdScheduleType());
-        //性别 允许值: "GENDER_FEMALE", "GENDER_MALE", "NONE"
-        params.put("gender", strategy.getAdGender());
-        //允许值: "AGE_BETWEEN_18_23", "AGE_BETWEEN_24_30","AGE_BETWEEN_31_40", "AGE_BETWEEN_41_49", "AGE_ABOVE_50"
-        //年龄不限 不传该字段
-        //params.put("age", strategy.getAge());
-       //自定义人群 不限 不传该字段
-        // 定向人群包列表(自定义人群)
-        //params.put("retargeting_tags_include", );
-        //排除人群包列表(自定义人群)
-        //params.put("retargeting_tags_exclude", );
-        //媒体定向
-        //params.put("superior_popularity_type", byteDanceAdvertisePlan.getSuperiorPopularityType());
-        //平台
-        //params.put("platform", byteDanceAdvertisePlan.getPlatform());
-        //最低安卓版本
-        params.put("android_osv", strategy.getAdAndroidOsv());
-        //网络
-        //params.put("ac", byteDanceAdvertisePlan.getAc());
-        //过滤已安装  当推广目标为安卓应用下载时可填 0表示不限,1表示过滤,2表示定向。默认为不限
-        params.put("hide_if_exists", strategy.getAdHideIfExists());
-        //过滤已转化用户 NO_EXCLUDE-不过滤;AD-广告计划(默认);CAMPAIGN-广告组; ADVERTISER-广告账户; APP-APP; CUSTOMER-公司账户
-        params.put("hide_if_converted", strategy.getAdHideIfConverted());
-        //是否启用智能放量 0、1。缺省为 0
-        params.put("auto_extend_enabled", strategy.getAdAutoExtendEnabled());
-        //预算与出价
-        //投放场景 允许值: 常规投放"SMART_BID_CUSTOM", 放量投放"SMART_BID_CONSERVATIVE"
-        params.put("smart_bid_type", strategy.getAdSmartBidType());
-        //预算类型 "BUDGET_MODE_DAY"日预算, "BUDGET_MODE_TOTAL"总预算
-        params.put("budget_mode", strategy.getAdBudgetMode());
-        //预算 出价方式为CPC、CPM、CPV时,不少于100元;出价方式为OCPM、OCPC时,不少于300元
-        params.put("budget", strategy.getAdBudget());
-        //投放时间类型 允许值: "SCHEDULE_FROM_NOW"从今天起长期投放, "SCHEDULE_START_END"设置开始和结束日期
-        params.put("schedule_type", strategy.getAdScheduleType());
-        //投放时段,默认全时段投放
-        params.put("schedule_time", strategy.getAdScheduleTime());
-        //付费方式(计划出价类型) 决定投放目标的类型,比如CPC表示点击量,OCPM表示转化量
-        params.put("pricing", strategy.getAdPricing());
-        //目标转化出价/预期成本, 当pricing为"OCPM"、"OCPC"出价方式时必填)
-        //pricing为"OCPC"时取值范围:0.1-10000元;
-        //pricing为"OCPM"时取值范围:0.1-10000元;
-        //出价不能大于预算否则会报错
-        params.put("cpa_bid", strategy.getAdCpaBid());
-
+    public static Result createAdvertiserPlan(CtopOauthToken token, JSONObject params, AiBytedanceAdvertiserStrategy strategy) {
         JSONObject jsonObject = HttpUtils.bytedancePostRequest(token.getAccessToken(),
                 urlPath + PropertiesUtils.getValue("bytedance_config", "bytedance_v2_ad_create"), params);
         Integer code = jsonObject.getInteger("code");
         if (null ==  code || !code.equals(0)) {
             log.error("广告计划创建失败==》accountId:{},message:{}", token.getAccountId(), jsonObject.getString("message"));
             Result.error(jsonObject.getString("message"));
-
         }
         //strategy.setId(jsonObject.getJSONObject("data").getLong("ad_id"));
         return Result.successMsg("广告计划创建成功",jsonObject.getJSONObject("data").getLong("ad_id"));

+ 7 - 7
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/entity/AiBytedanceAdvertiserStrategy.java

@@ -170,7 +170,7 @@ public class AiBytedanceAdvertiserStrategy{
 	/**手机品牌(用户定向)*/
 	private String adDeviceBrand;
 	/**手机价格(用户定向)*/
-	private java.math.BigDecimal adLaunchPrice;
+	private String adLaunchPrice;
 	/**是否启用智能放量(用户定向)*/
 	private String adAutoExtendEnabled;
 	/**可放开定向(用户定向)*/
@@ -196,25 +196,25 @@ public class AiBytedanceAdvertiserStrategy{
 	/**付费方式*/
 	private String adPricing;
 	/**转化出价*/
-	private java.math.BigDecimal adBid;
+	private BigDecimal adBid;
 	/**目标转化出价*/
-	private java.math.BigDecimal adCpaBid;
+	private BigDecimal adCpaBid;
 	/**深度优化方式*/
 	private String adDeepBidType;
 	/**深度优化出价*/
 	private BigDecimal adDeepCpabid;
 	/**鲁班目标ROI出价策略系数*/
-	private java.math.BigDecimal adLubanRoiGoal;
+	private BigDecimal adLubanRoiGoal;
 	/**深度转化ROI系数*/
-	private java.math.BigDecimal adRoiGoal;
+	private BigDecimal adRoiGoal;
 	/**广告位置*/
 	private String creativeInventoryType;
 	/**优选广告位*/
 	private Integer creativeSmartInventory;
 	/**场景广告位*/
-	private Object creativeSceneInventory;
+	private String creativeSceneInventory;
 	/**创意方式*/
-	private Object creativeMaterialMode;
+	private String creativeMaterialMode;
 	/**程序化创意包id*/
 	private Integer creativeProceduralPackageId;
 	/**自动生成视频素材*/

+ 50 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/entity/BytedanceVideoSlogenInfo.java

@@ -0,0 +1,50 @@
+package org.jeecg.modules.bytedance.advertise.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * 头条视频文案信息
+ * @author jeecg-boot
+ * 2021-04-19
+ * @version V1.0
+ */
+@Data
+@TableName("ctop_bytedance_video_slogen_info")
+public class BytedanceVideoSlogenInfo {
+
+	/**id*/
+	@TableId(type = IdType.AUTO)
+	private Long id;
+	/**videoCode*/
+	private String videoCode;
+	/**slogan*/
+	private String slogan;
+	/**createTime*/
+	private Date createTime;
+	/**updateTime*/
+	private Date updateTime;
+	/**createBy*/
+	private String createBy;
+	/**updateBy*/
+	private String updateBy;
+	/**status*/
+	private Integer status;
+
+	public BytedanceVideoSlogenInfo(String videoCode, String slogan, String userId) {
+		this.videoCode = videoCode;
+		this.slogan = slogan;
+		this.createBy = userId;
+		this.updateBy = userId;
+		this.createTime = new Date();
+		this.updateTime = new Date();
+		this.status = 1;
+	}
+
+	public BytedanceVideoSlogenInfo() {
+	}
+}

+ 14 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/mapper/BytedanceVideoSlogenInfoMapper.java

@@ -0,0 +1,14 @@
+package org.jeecg.modules.bytedance.advertise.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.jeecg.modules.bytedance.advertise.entity.BytedanceVideoSlogenInfo;
+
+/**
+ * 头条视频文案信息
+ * @author jeecg-boot
+ * 2021-04-19
+ * @version V1.0
+ */
+public interface BytedanceVideoSlogenInfoMapper extends BaseMapper<BytedanceVideoSlogenInfo> {
+
+}

+ 5 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/mapper/xml/BytedanceVideoSlogenInfoMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.jeecg.modules.bytedance.advertise.mapper.BytedanceVideoSlogenInfoMapper">
+
+</mapper>

+ 0 - 8
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/service/IAiBytedanceAdvertiserStrategyService.java

@@ -21,14 +21,6 @@ public interface IAiBytedanceAdvertiserStrategyService extends IService<AiByteda
     Long createCreative(AiBytedanceAdvertiserStrategy strategy,Integer createType, Long videoCnt);
 
     /**
-     *  创建 广告 组-计划-创意
-     * @param strategy
-     * @return
-     */
-    Result createADCreative(AiBytedanceAdvertiserStrategy strategy);
-
-
-    /**
      * 修改 广告 组-计划-创意
      * @param strategy
      * @param groupModifyTime 广告组 修改时间戳

+ 1 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/service/IByteDanceCampaignService.java

@@ -16,4 +16,5 @@ import java.util.Map;
 public interface IByteDanceCampaignService extends IService<ByteDanceCampaign> {
     Map<String, Object> getAdvertiserCampaign(CtopOauthToken token, String ids, String date);
     Map<String, Object> updateCampaign(BytedanceCampaignEditVo editVo);
+    ByteDanceCampaign getOneByParams(Long accountId, String campaignName);
 }

+ 20 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/service/IBytedanceVideoSlogenInfoService.java

@@ -0,0 +1,20 @@
+package org.jeecg.modules.bytedance.advertise.service;
+
+import com.alibaba.fastjson.JSONArray;
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.jeecg.modules.bytedance.advertise.entity.BytedanceVideoSlogenInfo;
+
+import java.util.List;
+
+/**
+ * 头条视频文案信息
+ * @author jeecg-boot
+ * 2021-04-19
+ * @version V1.0
+ */
+public interface IBytedanceVideoSlogenInfoService extends IService<BytedanceVideoSlogenInfo> {
+
+    void insertSlogans(String videoCode, JSONArray slogans, String userId);
+
+    List<BytedanceVideoSlogenInfo> listByParams(String code, Integer status);
+}

+ 570 - 64
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/service/impl/AiBytedanceAdvertiserStrategyServiceImpl.java

@@ -1,31 +1,34 @@
 package org.jeecg.modules.bytedance.advertise.service.impl;
 
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.extern.slf4j.Slf4j;
 import org.jeecg.common.api.vo.Result;
 import org.jeecg.common.util.DateUtils;
-import org.jeecg.modules.bytedance.advertise.dockapi.marketing;
-import org.jeecg.modules.bytedance.advertise.entity.AiBytedanceAdDplinkInfo;
-import org.jeecg.modules.bytedance.advertise.entity.AiBytedanceAdvertiserStrategy;
-import org.jeecg.modules.bytedance.advertise.entity.ByteDanceVideoInfo;
-import org.jeecg.modules.bytedance.advertise.entity.UpdAdStaOrCpaOrBudget;
+import org.jeecg.modules.bytedance.advertise.dockapi.Marketing;
+import org.jeecg.modules.bytedance.advertise.entity.*;
 import org.jeecg.modules.bytedance.advertise.enums.BytedanceCreativeMatTypeEnum;
 import org.jeecg.modules.bytedance.advertise.mapper.AiBytedanceAdvertiserStrategyMapper;
-import org.jeecg.modules.bytedance.advertise.service.IAiBytedanceAdDplinkInfoService;
-import org.jeecg.modules.bytedance.advertise.service.IAiBytedanceAdvertiserStrategyService;
-import org.jeecg.modules.bytedance.advertise.service.IByteDanceVideoInfoService;
+import org.jeecg.modules.bytedance.advertise.service.*;
 import org.jeecg.modules.bytedance.advertise.vo.AdConvertQueryVo;
 import org.jeecg.modules.bytedance.advertise.vo.AdGroupSearchVo;
 import org.jeecg.modules.bytedance.advertise.vo.PlanSearchVo;
 import org.jeecg.modules.bytedance.common.constant.BytedanceConstant;
 import org.jeecg.modules.bytedance.common.entity.CtopOauthToken;
+import org.jeecg.modules.bytedance.common.entity.MaterialInfo;
 import org.jeecg.modules.bytedance.common.entity.UserAllocation;
 import org.jeecg.modules.bytedance.common.service.ICtopOauthTokenService;
+import org.jeecg.modules.bytedance.common.service.IMaterialInfoService;
 import org.jeecg.modules.bytedance.common.service.IUserAllocationService;
+import org.jeecg.modules.bytedance.common.utils.Check;
+import org.jeecg.modules.bytedance.common.utils.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -93,16 +96,557 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
         }
         //根据dpLink获取组名称
         String campaignName = getCampaignName(dpIndex,strategy);
-        //2:创建计划
-        //3:创建创意
+        Long campaignId = getCampaignId(strategy,campaignName,token);
+        if(null == campaignId){
+            return videoCnt;
+        }
+        for (ByteDanceVideoInfo video:videoInfos) {
+            /**
+             * 2:创建计划
+             */
+            //1:应用直达链接
+            strategy.setAdOpenUrl(strategy.getAdOpenUrl().replace("{{dp链接下标}}",dpIndex.toString()));
+            String dplinkCode = StringUtils.getParamFromUrl(strategy.getAdOpenUrl(),"bc_fl_src");
+            String adName = getAdName(strategy,dplinkCode,video);
+            JSONObject adParams = getAdParams(strategy,adName,campaignId);
+            Long adId = createAdInfo(token,strategy,adParams);
+            if(null == adId){
+                continue;
+            }
+            //3:创建创意
+            JSONObject creativeParams = getCreativeParams(strategy,adId,video,token);
+
+        }
         return videoCnt;
     }
 
-    private String getCampaignName(Long dpIndex, AiBytedanceAdvertiserStrategy strategy) {
-        Long unitCreativeNum = strategy.getCampaignAdCnt();
+    private JSONObject getCreativeParams(AiBytedanceAdvertiserStrategy strategy, Long adId,ByteDanceVideoInfo videoInfo,CtopOauthToken token) {
+        JSONObject params = new JSONObject();
+        params.put("advertiser_id",strategy.getAccountId());
+        params.put("ad_id",adId);
+        String inventoryType = strategy.getCreativeInventoryType();
+        if(null!=inventoryType&&!"".equals(inventoryType)){
+            JSONArray inventoryTypeArray = JSON.parseArray(inventoryType);
+            if(!Check.isNull(inventoryTypeArray)){
+                params.put("inventory_type",inventoryTypeArray);
+            }
+        }
+        Integer smartInventory = strategy.getCreativeSmartInventory();
+        if(null!=smartInventory&&smartInventory!=0){
+            params.put("smart_inventory",smartInventory);
+        }
+
+        String sceneInventory = strategy.getCreativeSceneInventory();
+        if(!Check.isNull(sceneInventory)){
+            params.put("scene_inventory",sceneInventory);
+        }
+        //程序化创意 非dpa
+        params.put("creative_material_mode","STATIC_ASSEMBLE");
+        //是否自动生成视频素材
+        Integer isPresentedVideo = strategy.getCreativeIsPresentedVideo();
+        if(null!=isPresentedVideo&&isPresentedVideo!=0){
+            params.put("is_presented_video",isPresentedVideo);
+        }
+        //是否开启衍生计划
+        Integer generateDerivedAd = strategy.getCreativeGenerateDerivedAd();
+        if(null!=generateDerivedAd&&generateDerivedAd!=0){
+            params.put("generate_derived_ad",generateDerivedAd);
+        }
+        //视频素材
+        JSONArray imageArray = new JSONArray();
+        JSONObject imageObject = new JSONObject();
+        //视频类型
+        if(videoInfo.getType() == 1){
+            //横版视频
+            imageObject.put("image_mode","CREATIVE_IMAGE_MODE_VIDEO");
+        }
+        if(videoInfo.getType() == 2){
+            //竖版视频
+            imageObject.put("image_mode","CREATIVE_IMAGE_MODE_VIDEO_VERTICAL");
+        }
+        imageObject.put("video_id",videoInfo.getVid());
+        //获取视频封面id
+        String imageId = getSuggestImageId(token,videoInfo.getVid());
+        if(!Check.isNull(imageId)){
+            imageObject.put("image_id",imageId);
+        }
+        params.put("image_list",imageArray);
+        JSONArray titleArray = new JSONArray();
+        List<BytedanceVideoSlogenInfo>slogenInfos = slogenInfoService.listByParams(videoInfo.getSignature(),1);
+        if(!Check.isNull(slogenInfos)){
+            slogenInfos.forEach(slogenInfo->{
+                JSONObject titleObject = new JSONObject();
+                titleObject.put("title",slogenInfo.getSlogan());
+                titleArray.add(titleObject);
+            });
+        }
+        if(Check.isNull(titleArray)){
+            params.put("title_list",titleArray);
+        }
+        //广告来源
+        String source = strategy.getCreativeSource();
+        if(!Check.isNull(source)){
+            params.put("source",source);
+        }
+        //推广抖音号
+        String iesCoreUserId = strategy.getCreativeIesCoreUserId();
+        if(!Check.isNull(iesCoreUserId)){
+            params.put("ies_core_user_id",iesCoreUserId);
+        }
+        //主页作品列表隐藏广告内容
+        Integer isFeedAndFavSee = strategy.getCreativeIsFeedAndFavSee();
+        if(null!=isFeedAndFavSee&&isFeedAndFavSee!=0){
+            params.put("is_feed_and_fav_see",isFeedAndFavSee);
+        }
+        //是否开启自动生成素材
+        Integer creativeAutoGenerateSwitch = strategy.getCreativeAutoGenerateSwitch();
+        if(null!=creativeAutoGenerateSwitch&&creativeAutoGenerateSwitch!=1){
+            params.put("creative_auto_generate_switch",creativeAutoGenerateSwitch);
+        }
+        String appName = strategy.getCreativeAppName();
+        if(!Check.isNull(appName)){
+            params.put("app_name",appName);
+        }
+
+        String subTitle = strategy.getCreativeSubTitle();
+        if(!Check.isNull(subTitle)){
+            params.put("sub_title",subTitle);
+        }
+
+        String webUrl = strategy.getCreativeWebUrl();
+        if(!Check.isNull(webUrl)){
+            params.put("web_url",webUrl);
+        }
+
+        String actionText = strategy.getCreativeActionText();
+        if(!Check.isNull(actionText)){
+            params.put("action_text",actionText);
+        }
+
+        String playableUrl = strategy.getCreativePlayableUrl();
+        if(!Check.isNull(playableUrl)){
+            params.put("playable_url",playableUrl);
+        }
+
+        Integer isCommentDisable = strategy.getCreativeIsCommentDisable();
+        if(!Check.isNull(isCommentDisable)&&isCommentDisable!=0){
+            params.put("is_comment_disable",appName);
+        }
+        String creativeDisplayMode = strategy.getCreativeDisplayMode();
+        if(!Check.isNull(creativeDisplayMode)){
+            params.put("creative_display_mode",creativeDisplayMode);
+        }
+//        允许客户端下载视频功能
+//        Integer adDownloadStatus = strategy.getCreativeAdDownloadStatus();
+//        if(!Check.isNull(adDownloadStatus)&&adDownloadStatus!=0){
+//            params.put("ad_download_status",adDownloadStatus);
+//        }
+        //商品推广卡片
+
+        return params;
+
+    }
+
+    @Autowired
+    private IBytedanceVideoSlogenInfoService slogenInfoService;
+    private String getSuggestImageId(CtopOauthToken token, String vid) {
         return null;
     }
 
+    private Long createAdInfo(CtopOauthToken token, AiBytedanceAdvertiserStrategy strategy, JSONObject adParams) {
+        Result result = Marketing.createAdvertiserPlan(token,adParams,strategy);
+        if(result.getCode()!=200){
+            //TODO 计划创建异常 后续需要加日志
+            return null;
+        }
+        return (Long)result.getResult();
+    }
+
+    private JSONObject getAdParams(AiBytedanceAdvertiserStrategy strategy, String adName, Long campaignId) {
+        JSONObject params = new JSONObject();
+        //公共参数
+        params.put("advertiser_id",strategy.getAccountId());
+        params.put("campaign_id",campaignId);
+        params.put("name",adName);
+        //投放范围
+        params.put("delivery_range",strategy.getAdDeliveryRange());
+        if(!Check.isNull(strategy.getAdUnionVideoType())){
+            params.put("union_video_type",strategy.getAdUnionVideoType());
+        }
+        //投放目标
+        params.put("download_type",strategy.getAdDownloadType());
+        if(!Check.isNull(strategy.getAdDownloadUrl())){
+            params.put("download_url",strategy.getAdDownloadUrl());
+        }
+        if(!Check.isNull(strategy.getAdQuickAppUrl())){
+            params.put("quick_app_url",strategy.getAdQuickAppUrl());
+        }
+        if(!Check.isNull(strategy.getAdExternalUrl())){
+            params.put("external_url",strategy.getAdExternalUrl());
+        }
+        if(!Check.isNull(strategy.getAdAppType())){
+            params.put("app_type",strategy.getAdAppType());
+        }
+        if(!Check.isNull(strategy.getAdPackage())){
+            params.put("package",strategy.getAdPackage());
+        }
+        if(!Check.isNull(strategy.getAdDownloadMode())){
+            params.put("download_mode",strategy.getAdDownloadMode());
+        }
+        if(!Check.isNull(strategy.getAdConvertId())){
+            params.put("convert_id",strategy.getAdConvertId());
+        }
+        if(!Check.isNull(strategy.getAdOpenUrl())){
+            params.put("open_url",strategy.getAdOpenUrl());
+        }
+        if(!Check.isNull(strategy.getAdAdvancedCreativeType())){
+            params.put("advanced_creative_type",strategy.getAdAdvancedCreativeType());
+        }
+        if(!Check.isNull(strategy.getAdGamePackageDesc())){
+            params.put("game_package_desc",strategy.getAdGamePackageDesc());
+        }
+        if(!Check.isNull(strategy.getAdGamePackageBatchId())){
+            params.put("game_package_batch_id",strategy.getAdGamePackageBatchId());
+        }
+        if(!Check.isNull(strategy.getAdGamePackageThumbnailId())){
+            JSONArray ids = JSON.parseArray(strategy.getAdGamePackageThumbnailId());
+            if(null == ids&&!ids.isEmpty()){
+                params.put("game_package_thumbnail_ids",ids);
+            }
+        }
+        //用户定向
+        if(!Check.isNull(strategy.getAdAudiencePackageId())){
+            params.put("audience_package_id",strategy.getAdAudiencePackageId());
+        }
+        if(!Check.isNull(strategy.getAdDistrict())){
+            params.put("district",strategy.getAdDistrict());
+        }
+        if(!Check.isNull(strategy.getAdCity())){
+            JSONArray city = JSON.parseArray(strategy.getAdCity());
+            if(null == city&&!city.isEmpty()){
+                params.put("city",city);
+            }
+        }
+        if(!Check.isNull(strategy.getAdLocationType())){
+            params.put("location_type",strategy.getAdLocationType());
+        }
+        if(!Check.isNull(strategy.getAdGender())){
+            params.put("gender",strategy.getAdGender());
+        }
+        if(!Check.isNull(strategy.getAdAge())){
+            JSONArray age = JSON.parseArray(strategy.getAdAge());
+            if(null!=age&&!age.isEmpty()){
+                params.put("age",age);
+            }
+        }
+        if(!Check.isNull(strategy.getAdRetargetingTagsInclude())){
+            JSONArray retargetingTagsInclude = JSON.parseArray(strategy.getAdRetargetingTagsInclude());
+            if(null!=retargetingTagsInclude&&!retargetingTagsInclude.isEmpty()){
+                params.put("retargeting_tags_include",retargetingTagsInclude);
+            }
+        }
+        if(!Check.isNull(strategy.getAdRetargetingTagsExclude())){
+            JSONArray getAdRetargetingTagsExclude = JSON.parseArray(strategy.getAdRetargetingTagsExclude());
+            if(null!=getAdRetargetingTagsExclude&&!getAdRetargetingTagsExclude.isEmpty()){
+                params.put("retargeting_tags_exclude",getAdRetargetingTagsExclude);
+            }
+        }
+        if(!Check.isNull(strategy.getAdInterestActionMode())){
+            params.put("interest_action_mode",strategy.getAdInterestActionMode());
+        }
+        if(!Check.isNull(strategy.getAdActionScene())){
+            JSONArray actionScene = JSON.parseArray(strategy.getAdActionScene());
+            if(null!=actionScene&&!actionScene.isEmpty()){
+                params.put("action_scene",actionScene);
+            }
+        }
+        if(!Check.isNull(strategy.getAdActionDays())){
+            params.put("action_days",strategy.getAdActionDays());
+        }
+        if(!Check.isNull(strategy.getAdActionCategories())){
+            JSONArray actionCategories = JSON.parseArray(strategy.getAdActionCategories());
+            if(null!=actionCategories&&!actionCategories.isEmpty()){
+                params.put("action_categories",actionCategories);
+            }
+        }
+        if(!Check.isNull(strategy.getAdActionWords())){
+            JSONArray actionWords = JSON.parseArray(strategy.getAdActionWords());
+            if(null!=actionWords&&!actionWords.isEmpty()){
+                params.put("action_words",actionWords);
+            }
+        }
+        if(!Check.isNull(strategy.getAdInterestCategories())){
+            JSONArray interestCategories = JSON.parseArray(strategy.getAdInterestCategories());
+            if(null!=interestCategories&&!interestCategories.isEmpty()){
+                params.put("interest_categories",interestCategories);
+            }
+        }
+        if(!Check.isNull(strategy.getAdInterestWords())){
+            JSONArray interestWords = JSON.parseArray(strategy.getAdInterestWords());
+            if(null!=interestWords&&!interestWords.isEmpty()){
+                params.put("interest_words",interestWords);
+            }
+        }
+        if(!Check.isNull(strategy.getAdAwemeFanBehaviors())){
+            JSONArray awemeFanBehaviors = JSON.parseArray(strategy.getAdAwemeFanBehaviors());
+            if(null!=awemeFanBehaviors&&!awemeFanBehaviors.isEmpty()){
+                params.put("aweme_fan_behaviors",awemeFanBehaviors);
+            }
+        }
+        if(!Check.isNull(strategy.getAdAwemeFanCategories())){
+            JSONArray awemeFanCategories = JSON.parseArray(strategy.getAdAwemeFanCategories());
+            if(null!=awemeFanCategories&&!awemeFanCategories.isEmpty()){
+                params.put("aweme_fan_categories",awemeFanCategories);
+            }
+        }
+        if(!Check.isNull(strategy.getAdAwemeFanAccounts())){
+            JSONArray awemeFanAccount = JSON.parseArray(strategy.getAdAwemeFanAccounts());
+            if(null!=awemeFanAccount&&!awemeFanAccount.isEmpty()){
+                params.put("aweme_fan_accounts",awemeFanAccount);
+            }
+        }
+        if(!Check.isNull(strategy.getAdAwemeFansNumbers())){
+            JSONArray awemeFansNumbers = JSON.parseArray(strategy.getAdAwemeFansNumbers());
+            if(null!=awemeFansNumbers&&!awemeFansNumbers.isEmpty()){
+                params.put("aweme_fans_numbers",awemeFansNumbers);
+            }
+        }
+        if(!Check.isNull(strategy.getAdFilterAwemeAbnormalActive())){
+            params.put("filter_aweme_abnormal_active",strategy.getAdFilterAwemeAbnormalActive());
+        }
+        if(!Check.isNull(strategy.getAdFilterAwemeFansCount())){
+            params.put("filter_aweme_fans_count",strategy.getAdFilterAwemeFansCount());
+        }
+        if(!Check.isNull(strategy.getAdFilterOwnAwemeFans())){
+            params.put("filter_own_aweme_fans",strategy.getAdFilterOwnAwemeFans());
+        }
+        if(!Check.isNull(strategy.getAdSuperiorPopularityType())){
+            params.put("superior_popularity_type",strategy.getAdSuperiorPopularityType());
+        }
+        if(!Check.isNull(strategy.getAdFlowPackage())){
+            JSONArray flowPackage = JSON.parseArray(strategy.getAdFlowPackage());
+            if(null!=flowPackage&&!flowPackage.isEmpty()){
+                params.put("flow_package",flowPackage);
+            }
+        }
+        if(!Check.isNull(strategy.getAdExcludeFlowPackage())){
+            JSONArray excludeFlowPackage = JSON.parseArray(strategy.getAdExcludeFlowPackage());
+            if(null!=excludeFlowPackage&&!excludeFlowPackage.isEmpty()){
+                params.put("exclude_flow_package",excludeFlowPackage);
+            }
+        }
+        if(!Check.isNull(strategy.getAdPlatform())){
+            JSONArray platform = JSON.parseArray(strategy.getAdPlatform());
+            if(null!=platform&&!platform.isEmpty()){
+                params.put("platform",platform);
+            }
+        }
+
+        if(!Check.isNull(strategy.getAdAndroidOsv())){
+            params.put("android_osv",strategy.getAdAndroidOsv());
+        }
+
+        if(!Check.isNull(strategy.getAdAdIosOsv())){
+            params.put("ios_osv",strategy.getAdAdIosOsv());
+        }
+        if(!Check.isNull(strategy.getAdAc())){
+            JSONArray ac = JSON.parseArray(strategy.getAdAc());
+            if(null!=ac&&!ac.isEmpty()){
+                params.put("ac",ac);
+            }
+        }
+        if(!Check.isNull(strategy.getAdCarrier())){
+            JSONArray carrier = JSON.parseArray(strategy.getAdCarrier());
+            if(null!=carrier&&!carrier.isEmpty()){
+                params.put("carrier",carrier);
+            }
+        }
+        if(!Check.isNull(strategy.getAdDeviceType())){
+            JSONArray deviceType = JSON.parseArray(strategy.getAdDeviceType());
+            if(null!=deviceType&&!deviceType.isEmpty()){
+                params.put("device_type",deviceType);
+            }
+        }
+
+        if(!Check.isNull(strategy.getAdHideIfExists())){
+            params.put("hide_if_exists",strategy.getAdHideIfExists());
+        }
+        if(!Check.isNull(strategy.getAdConvertedTimeDuration())){
+            params.put("converted_time_duration",strategy.getAdConvertedTimeDuration());
+        }
+        if(!Check.isNull(strategy.getAdHideIfConverted())){
+            params.put("hide_if_converted",strategy.getAdHideIfConverted());
+        }
+
+        if(!Check.isNull(strategy.getAdActivateType())){
+            JSONArray activateType = JSON.parseArray(strategy.getAdActivateType());
+            if(null!=activateType&&!activateType.isEmpty()){
+                params.put("activate_type",activateType);
+            }
+        }
+        if(!Check.isNull(strategy.getAdArticleCategory())){
+            JSONArray articleCategory = JSON.parseArray(strategy.getAdArticleCategory());
+            if(null!=articleCategory&&!articleCategory.isEmpty()){
+                params.put("article_category",articleCategory);
+            }
+        }
+        if(!Check.isNull(strategy.getAdDeviceBrand())){
+            JSONArray deviceBrand = JSON.parseArray(strategy.getAdDeviceBrand());
+            if(null!=deviceBrand&&!deviceBrand.isEmpty()){
+                params.put("device_brand",deviceBrand);
+            }
+        }
+        if(!Check.isNull(strategy.getAdLaunchPrice())){
+            JSONArray launchPrice = JSON.parseArray(strategy.getAdLaunchPrice());
+            if(null!=launchPrice&&!launchPrice.isEmpty()){
+                params.put("launch_price",launchPrice);
+            }
+        }
+        if(!Check.isNull(strategy.getAdAutoExtendEnabled())){
+            params.put("auto_extend_enabled",strategy.getAdAutoExtendEnabled());
+        }
+        if(!Check.isNull(strategy.getAdAutoExtendTargets())){
+            JSONArray autoExtendTargets = JSON.parseArray(strategy.getAdAutoExtendTargets());
+            if(null!=autoExtendTargets&&!autoExtendTargets.isEmpty()){
+                params.put("auto_extend_targets",autoExtendTargets);
+            }
+        }
+        //预算与出价
+        if(!Check.isNull(strategy.getAdSmartBidType())){
+            params.put("smart_bid_type",strategy.getAdSmartBidType());
+        }
+        if(!Check.isNull(strategy.getAdAdjustCpa())){
+            params.put("adjust_cpa",strategy.getAdAdjustCpa());
+        }
+        if(!Check.isNull(strategy.getAdFlowControlMode())){
+            params.put("flow_control_mode",strategy.getAdFlowControlMode());
+        }
+        if(!Check.isNull(strategy.getAdBudgetMode())){
+            params.put("budget_mode",strategy.getAdBudgetMode());
+        }
+        if(!Check.isNull(strategy.getAdBudget())){
+            params.put("budget",strategy.getAdBudget());
+        }
+        if(!Check.isNull(strategy.getAdScheduleType())){
+            params.put("schedule_type",strategy.getAdScheduleType());
+        }
+        if(!Check.isNull(strategy.getAdStartTime())){
+            params.put("start_time",strategy.getAdStartTime());
+        }
+        if(!Check.isNull(strategy.getAdAdjustCpa())){
+            params.put("end_time",strategy.getAdEndTime());
+        }
+        if(!Check.isNull(strategy.getAdScheduleTime())){
+            params.put("schedule_time",strategy.getAdScheduleTime());
+        }
+        if(!Check.isNull(strategy.getAdPricing())){
+            params.put("pricing",strategy.getAdPricing());
+        }
+        if(!Check.isNull(strategy.getAdBid())){
+            params.put("bid",strategy.getAdBid());
+        }
+        if(!Check.isNull(strategy.getAdCpaBid())){
+            params.put("cpa_bid",strategy.getAdCpaBid());
+        }
+        if(!Check.isNull(strategy.getAdDeepBidType())){
+            params.put("deep_bid_type",strategy.getAdDeepBidType());
+        }
+        if(!Check.isNull(strategy.getAdDeepCpabid())){
+            params.put("deep_cpabid",strategy.getAdDeepCpabid());
+        }
+        if(!Check.isNull(strategy.getAdLubanRoiGoal())){
+            params.put("luban_roi_goal",strategy.getAdLubanRoiGoal());
+        }
+        if(!Check.isNull(strategy.getAdRoiGoal())){
+            params.put("roi_goal",strategy.getAdRoiGoal());
+        }
+        return params;
+    }
+
+    private String getAdName(AiBytedanceAdvertiserStrategy strategy, String dplinkCode, ByteDanceVideoInfo videoInfo) {
+        String adName = strategy.getAdName();
+        if(null == adName||adName.trim().equals("")){
+            return null;
+        }
+        if(adName.contains("{{日期}}")){
+            String date = DateUtils.formatDate(new Date(),"yyyyMMdd");
+            adName.replace("{{日期}}",date);
+        }
+        if(adName.contains("{{dp链接标识}}")){
+            adName.replace("{{dp链接标识}}",dplinkCode);
+        }
+        if(adName.contains("{{出价方式}}")){
+            String pricing = strategy.getAdPricing().replace("PRICING_","");
+            adName.replace("{{出价方式}}",pricing);
+        }
+        if(adName.contains("{{素材名称}}")){
+            MaterialInfo info = materialInfoService.getParams(videoInfo.getSignature(),1);
+            adName.replace("{{素材名称}}",info.getMaterialName());
+        }
+        return adName;
+    }
+
+    @Autowired
+    private IMaterialInfoService materialInfoService;
+
+    @Autowired
+    private IByteDanceCampaignService campaignService;
+    private Long getCampaignId(AiBytedanceAdvertiserStrategy strategy, String campaignName,CtopOauthToken token) {
+        ByteDanceCampaign campaign = campaignService.getOneByParams(strategy.getAccountId(),campaignName);
+        if(null != campaign){
+            return campaign.getId();
+        }
+        //创建组信息
+        JSONObject campaignParam = new JSONObject();
+        campaignParam.put("advertiser_id",strategy.getAccountId());
+        campaignParam.put("campaign_name",campaignName);
+        campaignParam.put("landing_type",strategy.getCampaignLandingType());
+
+        campaignParam.put("budget_mode",strategy.getCampaignBudgetMode());
+        //日预算必须设定预算金额
+        if(null!=strategy.getCampaignBudgetMode()&&strategy.getCampaignBudgetMode().equals("BUDGET_MODE_DAY")){
+            campaignParam.put("budget",strategy.getCampaignBudget());
+        }
+        if(!Check.isNull(strategy.getCampaignDeliveryRelatedNum())){
+            campaignParam.put("delivery_related_num",strategy.getCampaignDeliveryRelatedNum());
+        }
+        //创建组
+        Result campaignData = Marketing.createCampaign(token, campaignParam);
+        if(campaignData.getCode()!=200){
+            //TODO 组创建异常 后续需要加日志
+            return null;
+        }
+        return (Long)campaignData.getResult();
+    }
+
+    private String getCampaignName(Long dpIndex, AiBytedanceAdvertiserStrategy strategy) {
+        //根据每个组的计划个数计算目前计划所属的组下标范围 比如 1 则下标范围为 1/50 56则下标范围为 51/100
+        String rangeIndex = getRangeIndex(strategy.getDpLinkStartIndex(),strategy.getDpLinkEndIndex(),strategy.getCampaignAdCnt(),dpIndex);
+        if(null == rangeIndex||rangeIndex.equals("")){
+            return null;
+        }
+        return strategy.getCampaignName()+rangeIndex;
+    }
+
+    private String getRangeIndex(Long dpLinkStartIndex,Long dpLinkEndIndex, Long campaignAdCnt, Long dpIndex) {
+        if(dpIndex<dpLinkStartIndex||dpIndex>dpLinkEndIndex){
+            //超出下标范围
+            return null;
+        }
+        Long startIndex ;
+        Long endIndex ;
+        //计算当前下标值和范围区段的余数
+        Long yzIndex = (dpIndex-dpLinkStartIndex+1)%campaignAdCnt;
+        if(yzIndex == 0){
+            startIndex = dpIndex-campaignAdCnt+1;
+            endIndex = dpIndex;
+        }else{
+            startIndex = dpIndex-yzIndex+1;
+            endIndex = dpIndex-yzIndex+campaignAdCnt;
+        }
+        return "-("+startIndex+"/"+endIndex+")";
+    }
+
     @Autowired
     private IAiBytedanceAdDplinkInfoService adDplinkInfoService;
     @Autowired
@@ -121,7 +665,10 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
         return null;
     }
 
-
+    public static void main(String[] args) {
+        String url = "taobaolite://m.ltao.com/open/index.html?action=ali.open.nav&module=h5&bootImage=0&source=toutiao&packageName=com.taobao.litetao&h5Url=https%3A%2F%2Fpages.tmall.com%2Fwow%2Fz%2Fsale%2FdynamicSolution%2Fsfbthp%3FdisableNav%3DYES%26wh_kangarooprefetch%3Dtrue%26needLogin%3Dtrue&bc_fl_src=sf_jrtt_huichuangzh_ptbt_{{dp链接下标}}&backurl=__back_url__";
+        System.out.println(StringUtils.getParamFromUrl(url,"bc_fl_src"));
+    }
     /**
      *  修改状态 (0开-1关)
      * @param
@@ -150,7 +697,7 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
             priceList.add(mapPrice);
 
             // api 更新计划出价
-            updResult = marketing.updatePlanBid(token,updAdStaOrCpaOrBudget.getAccountId(),priceList);
+            updResult = Marketing.updatePlanBid(token,updAdStaOrCpaOrBudget.getAccountId(),priceList);
             if (!"200".equals(updResult.getCode())){
                 return Result.error(updResult.getMessage());
             }
@@ -165,7 +712,7 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
             mapPrice.put("budget",updAdStaOrCpaOrBudget.getBudget());
             priceList.add(mapPrice);
             // api 修改计划 预算
-            updResult = marketing.updatePlanBudget(token,updAdStaOrCpaOrBudget.getAccountId(),priceList);
+            updResult = Marketing.updatePlanBudget(token,updAdStaOrCpaOrBudget.getAccountId(),priceList);
             if (!"200".equals(updResult.getCode())){
                 return Result.error(updResult.getMessage());
             }
@@ -195,7 +742,7 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
             return Result.error("token获取失败====>>>>accountId:"+token.getAccountId());
         }
         // 获取行业列表
-        Result industryList = marketing.getToolIndustryList(token,type);
+        Result industryList = Marketing.getToolIndustryList(token,type);
         log.error("行业列表=======>>>>>>>>>>>", industryList.getResult());
         return Result.successMsg("获取行业列表成功。", industryList.getResult());
     }
@@ -221,7 +768,7 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
             return Result.error("token获取失败====>>>>accountId:"+token.getAccountId());
         }
         // 获取广告组
-        Result industryList = marketing.getCampaignGroupList(token,accountId,adGroupSearchVoList,pageNo,pageSize);
+        Result industryList = Marketing.getCampaignGroupList(token,accountId,adGroupSearchVoList,pageNo,pageSize);
         log.error("获取广告组=======>>>>>>>>>>>", industryList.getResult());
         return Result.successMsg("获取广告组成功。", industryList.getResult());
     }
@@ -247,7 +794,7 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
             return Result.error("token获取失败====>>>>accountId:"+token.getAccountId());
         }
         // 获取计划
-        Result industryList = marketing.getPlanList(token,adGroupSearchVoList,pageNo,pageSize);
+        Result industryList = Marketing.getPlanList(token,adGroupSearchVoList,pageNo,pageSize);
         log.error("获取广告计划=======>>>>>>>>>>>", industryList.getResult());
         return Result.successMsg("获取广告计划成功。", industryList.getResult());
     }
@@ -268,51 +815,10 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
             return Result.error("token获取失败====>>>>accountId:"+token.getAccountId());
         }
         // 获取 创意详细信息
-        Result industryList = marketing.creativeRead(token,accountId,adId);
+        Result industryList = Marketing.creativeRead(token,accountId,adId);
         log.error("获取创意详细信息=======>>>>>>>>>>>", industryList.getResult());
         return Result.successMsg("获取创意详细信息成功。", industryList.getResult());
     }
-
-
-
-
-
-
-    /**
-     * 创建 广告 组-计划-创意
-     * @param strategy
-     * @return
-     */
-    public Result createADCreative(AiBytedanceAdvertiserStrategy strategy) {
-        CtopOauthToken token = tokenService.getOauthTokenByAccountId(strategy.getAccountId()+"");
-        if (null == token) {
-            log.info("token获取失败=>accountId:{}", token.getAccountId());
-            return Result.error("token获取失败====>>>>accountId:"+token.getAccountId());
-        }
-        // 1:创建广告组
-        Result resultCampaign = marketing.createCampaign(token,
-                strategy.getCampaignName(),
-                strategy.getAdBudgetMode() == null ? BytedanceConstant.BUDGET_MODE_INFINITE : strategy.getAdBudgetMode(),
-                strategy.getAdBudget(),
-                strategy.getCampaignLandingType());
-        //广告组id
-        Long campaignId = (Long) resultCampaign.getResult();
-        // 2:创建广告计划
-        Result resultPlan = marketing.createAdvertiserPlan(token,campaignId,strategy);
-        //计划id
-        Long planId = (Long) resultPlan.getResult();
-        //3:创建创意
-        Result creativeInfo = marketing.creativeCreate(token, planId, strategy);
-
-        log.error("创意创建=======>>>>>>>>>>>", creativeInfo.getResult());
-        //数据入库
-        aiBytedanceAdvertiserStrategyMapper.insert(strategy);
-        return Result.successMsg("创建成功", strategy);
-    }
-
-
-
-
     /**
      *
      * @description: 修改 广告 组-计划-创意
@@ -329,17 +835,17 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
             return Result.error("token获取失败====>>>>accountId:"+token.getAccountId());
         }
         // 1:修改广告组
-        Result resultCampaign = marketing.updateCampaign(token,
+        Result resultCampaign = Marketing.updateCampaign(token,
                 "广告组id",groupModifyTime,
                 strategy.getCampaignName(),strategy.getCampaignBudgetMode(),strategy.getCampaignLandingType());
         //广告组id
         Long campaignId = (Long) resultCampaign.getResult();
         // 2:修改广告计划
-        Result resultPlan = marketing.updateAdvertiserPlan(token,"计划id",planModifyTime,strategy);
+        Result resultPlan = Marketing.updateAdvertiserPlan(token,"计划id",planModifyTime,strategy);
         //计划id
         Object planId = resultPlan.getResult();
         //3:修改创意 TODO 拼接创意参数
-        Result creativeInfo = marketing.creativeUpdate(token, "计划id","创意时间戳",null);
+        Result creativeInfo = Marketing.creativeUpdate(token, "计划id","创意时间戳",null);
         //数据修改
         aiBytedanceAdvertiserStrategyMapper.updateById(strategy);
         return Result.successMsg("修改成功", strategy);
@@ -360,7 +866,7 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
             log.info("token获取失败=>accountId:{}", token.getAccountId());
             return Result.error("token获取失败====>>>>accountId:"+token.getAccountId());
         }
-        Result resultCampaign = marketing.getToolConvertQuery(token,adConvertQueryVo);
+        Result resultCampaign = Marketing.getToolConvertQuery(token,adConvertQueryVo);
         return Result.successMsg("查询广告计划可用转化目标成功。", resultCampaign.getResult());
     }
 

+ 15 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/service/impl/ByteDanceCampaignServiceImpl.java

@@ -2,6 +2,7 @@ package org.jeecg.modules.bytedance.advertise.service.impl;
 
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.extern.slf4j.Slf4j;
 import org.jeecg.modules.bytedance.advertise.entity.ByteDanceCampaign;
@@ -56,6 +57,20 @@ public class ByteDanceCampaignServiceImpl extends ServiceImpl<ByteDanceCampaignM
         return null;
     }
 
+    @Override
+    public ByteDanceCampaign getOneByParams(Long accountId, String campaignName) {
+        QueryWrapper<ByteDanceCampaign> queryWrapper = new QueryWrapper<>();
+        if(null!=accountId&&accountId!=0){
+            queryWrapper.eq("account_id",accountId);
+        }
+        if(!Check.isNull(campaignName)){
+            queryWrapper.like("name",campaignName);
+        }
+        queryWrapper.orderByDesc("create_time").last("limit 1");
+        return this.getOne(queryWrapper);
+
+    }
+
     private void getAdvertiserCampaignByPageNumber(CtopOauthToken token, Integer pageNumber, String ids, String date) {
         //2: 根据token以及用户id获取用户信息数据
         String url = PropertiesUtils.getValue("bytedance_config", "bytedance_api_url") + PropertiesUtils.getValue("bytedance_config", "bytedance_v2_campaign_get");

+ 46 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/service/impl/BytedanceVideoSlogenInfoServiceImpl.java

@@ -0,0 +1,46 @@
+package org.jeecg.modules.bytedance.advertise.service.impl;
+
+import com.alibaba.fastjson.JSONArray;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.jeecg.modules.bytedance.advertise.entity.BytedanceVideoSlogenInfo;
+import org.jeecg.modules.bytedance.advertise.mapper.BytedanceVideoSlogenInfoMapper;
+import org.jeecg.modules.bytedance.advertise.service.IBytedanceVideoSlogenInfoService;
+import org.jeecg.modules.bytedance.common.utils.Check;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 头条视频文案信息
+ * @author jeecg-boot
+ * 2021-04-19
+ * @version V1.0
+ */
+@Service
+public class BytedanceVideoSlogenInfoServiceImpl extends ServiceImpl<BytedanceVideoSlogenInfoMapper, BytedanceVideoSlogenInfo> implements IBytedanceVideoSlogenInfoService {
+    @Override
+    public void insertSlogans(String videoCode, JSONArray slogans,String userId){
+        if(null==slogans||slogans.isEmpty()){
+            return;
+        }
+        for(int i=0;i<slogans.size();i++){
+            String slogan = slogans.getString(i);
+            BytedanceVideoSlogenInfo slogenInfo = new BytedanceVideoSlogenInfo(videoCode,slogan,userId);
+            this.save(slogenInfo);
+        }
+    }
+
+    @Override
+    public List<BytedanceVideoSlogenInfo> listByParams(String code, Integer status) {
+        QueryWrapper<BytedanceVideoSlogenInfo>queryWrapper =new QueryWrapper<>();
+        if(!Check.isNull(code)){
+            queryWrapper.eq("video_code",code);
+        }
+        if(!Check.isNull(status)){
+            queryWrapper.eq("status",status);
+        }
+        queryWrapper.orderByDesc("id");
+        return this.list(queryWrapper);
+    }
+}

+ 166 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/entity/MaterialInfo.java

@@ -0,0 +1,166 @@
+package org.jeecg.modules.bytedance.common.entity;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 素材信息
+ *
+ * @author jeecg-boot
+ * @version V1.0
+ * @date 2019-10-11
+ */
+@Data
+@TableName("ctop_material_info")
+public class MaterialInfo {
+
+    /**
+     * id
+     */
+    @TableId(type = IdType.UUID)
+    private String id;
+    /**
+     * code
+     */
+    private String code;
+    private String watermarkCode;
+    /**
+     * url
+     */
+    private String url;
+    /**
+     * 封面url
+     */
+    private String coverUrl;
+
+    /**
+     * 水印素材链接
+     */
+    private String watermarkUrl;
+
+    private String type;
+    /**
+     * 审核人id
+     */
+    private String auditorId;
+    /**
+     * status
+     * <p>
+     * 0-待审核 1-审核通过 2-审核拒绝
+     */
+    private Integer status;
+    /**
+     * userId
+     */
+    private String userId;
+
+
+    private String materialDescribe;
+
+
+    private Long projectId;
+
+    /**
+     * 素材名称
+     */
+    private String materialName;
+
+    /**
+     * 水印素材名称
+     */
+    private String watermarkMaterialName;
+
+    /**
+     * 拒绝原因
+     */
+    private String refuseReason;
+    /**
+     * 拒绝上传文件
+     */
+    private String refuseFile;
+
+    /**
+     * 创意文案
+     */
+    private String creativeCopywriter;
+
+    /**
+     * 是否优秀素材
+     */
+    private Integer excellent;
+    /**
+     * createTime
+     */
+    private Object createTime;
+    /**
+     * updateTime
+     */
+    private Date updateTime;
+
+    //判断是否为头条有效素材0否_1是
+    private Integer toutiaoEffiType;
+    // 素造供应商
+    private String supplierCode;
+
+    //判断是否为快手有效素材0否_1是
+    private Integer kuaishouEffiType;
+
+    //判断是否已经同步到快手平台0否_1是
+    @TableField(exist = false)
+    private Integer kuaishouVideoIsUp;
+
+    //判断是否已经同步到头条平台0否_1是
+    @TableField(exist = false)
+    private Integer toutiaoVideoIsUp;
+
+    @TableField(exist = false)
+    private JSONObject byteDance;
+
+    @TableField(exist = false)
+    private JSONObject kuaiShou;
+
+    //拍摄时候担任的角色
+    @TableField(exist = false)
+    private String videoRoleCode;
+
+    //原本的角色
+    @TableField(exist = false)
+    private String originRoleName;
+
+    @TableField(exist = false)
+    private BigDecimal cost;
+
+    @TableField(exist = false)
+    private BigDecimal bytedanceCost;
+
+    @TableField(exist = false)
+    private String realname;
+
+    // 是否有未审核封面
+    @TableField(exist = false)
+    private Boolean whetherUnaudited;
+
+    @TableField(exist = false)
+    private String mediaId;  // 是否有未审核封面
+
+    @TableField(exist = false)
+    private String projectName;  // 是否有未审核封面
+
+    @TableField(exist = false)
+    private String startDate;  // 是否有未审核封面
+
+    @TableField(exist = false)
+    private String endDate;  // 是否有未审核封面
+
+    //视频关联广告语信息--头条
+    @TableField(exist = false)
+    private JSONArray slogans;
+}

+ 38 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/mapper/MaterialInfoMapper.java

@@ -0,0 +1,38 @@
+package org.jeecg.modules.bytedance.common.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
+import org.jeecg.modules.bytedance.common.entity.MaterialInfo;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 素材信息
+ *
+ * @author: jeecg-boot
+ * @date: 2019-10-11
+ * @cersion: V1.0
+ */
+public interface MaterialInfoMapper extends BaseMapper<MaterialInfo> {
+
+    String selectUserNameById(@Param("auditorId") String auditorId);
+
+    Integer selectCountByMap(Map<String, Object> requestMap);
+
+    Integer getKuaishouUpVideoCount(@Param("code") String code);
+
+    Integer getToutiaoUpVideoCount(@Param("code") String code);
+
+
+
+    List<String> getEffiSignature();
+
+    MaterialInfo getMaterialInfoByCode(@Param("code") String code);
+
+    Long getProjectIdByAccountId(@Param("accountId") Long accountId);
+
+    List<MaterialInfo> getListByDate(@Param("startDate") String startDate,@Param("endDate") String endDate);
+
+    List<MaterialInfo> getListByParams(@Param("tagCode")String tagCode,@Param("type")String type, @Param("status")Integer status, @Param("projectIds")List<Long> projectIds, @Param("materialName")String materialName, @Param("code")String code, @Param("startDate")String startDate, @Param("endDate")String endDate, @Param("userId")String userId);
+}

+ 139 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/mapper/xml/MaterialInfoMapper.xml

@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.jeecg.modules.bytedance.common.mapper.MaterialInfoMapper">
+
+
+    <select id="getProjectIdByAccountId" resultType="java.lang.Long">
+
+       select
+       project_id
+       from ctop_user_allocation
+       where  account_id = #{accountId}
+
+    </select>
+
+    <select id="selectUserNameById" resultType="java.lang.String">
+   select realname from  sys_user where  id = #{auditorId}
+    </select>
+
+
+    <select id="selectCountByMap" parameterType="java.util.Map" resultType="java.lang.Integer">
+
+        select count(1)
+        from ctop_material_info
+        where 1 = 1
+        <if test="userId != null">
+            and user_id = #{userId}
+        </if>
+
+        <if test="status != null">
+            and status = #{status}
+        </if>
+
+
+    </select>
+
+    <select id="getKuaishouUpVideoCount" resultType="java.lang.Integer">
+        select
+        count(1)
+        from
+        ctop_kuaishou_video_get v
+        where
+        v.signature = #{code}
+    </select>
+
+    <select id="getToutiaoUpVideoCount" resultType="java.lang.Integer">
+        select
+        count(1)
+        from
+        ctop_bytedance_video_info v
+        where
+        v.signature = #{code}
+    </select>
+
+
+
+    <select id="getEffiSignature" resultType="string">
+        select
+        efficient_video_signature
+        from ctop_user_efficient_video_map
+        where company_id is not null
+        group by efficient_video_signature
+
+    </select>
+
+    <select id="getMaterialInfoByCode" resultType="org.jeecg.modules.bytedance.common.entity.MaterialInfo">
+            select
+            id,
+            code,
+            url,
+            watermark_code as watermarkCode,
+            material_name as materialName,
+            watermark_url as watermarkUrl,
+            watermark_material_name as watermarkMaterialName,
+            user_id as userId,
+            auditor_id as auditorId,
+            status as status,
+            material_describe as materialDescribe,
+            project_id as projectId,
+            refuse_reason as refuseReason,
+            creative_copywriter as creativeCopywriter,
+            refuse_file as refuseFile,
+            excellent,
+            type
+        from
+        ctop_material_info
+        where code = #{code}
+        limit 1
+    </select>
+
+    <select id="getListByParams" resultType="org.jeecg.modules.bytedance.common.entity.MaterialInfo">
+        select
+        distinct matInfo.code,
+        matInfo.project_id,
+        matInfo.id
+        from ctop_material_info matInfo
+        <if test="tagCode!=null">
+            left join ctop_material_tag_info tagInfo on tagInfo.code = matInfo.code
+        </if>
+        where 1=1
+        <if test="tagCode!=null">
+            and tagInfo.tag_code like concat(#{tagCode},'%')
+        </if>
+        <if test="status!=null">
+            and matInfo.status = #{status}
+        </if>
+        <if test="userId!=null">
+            and matInfo.user_id = #{userId}
+        </if>
+        <if test="code!=null">
+            and matInfo.code = #{code}
+        </if>
+        <if test="materialName!=null">
+            and matInfo.material_name like concat('%',#{materialName},'%')
+        </if>
+        <if test="projectIds!=null">
+            and matInfo.project_id in
+            <foreach item="item" index="index" collection="projectIds" open="(" separator="," close=")">
+                #{item}
+            </foreach>
+        </if>
+        <if test="startDate!=null">
+            and matInfo.create_time &gt;= #{startDate}
+        </if>
+        <if test="endDate!=null">
+            and matInfo.create_time &lt;= #{endDate}
+        </if>
+        order by matInfo.create_time desc
+
+    </select>
+    <select id="getListByDate" resultType="org.jeecg.modules.bytedance.common.entity.MaterialInfo">
+        select  *  from
+        ctop_material_info
+        where  1 = 1
+        and DATE_FORMAT(create_time,'%Y-%m-%d') &gt;= #{startDate}
+        and DATE_FORMAT(create_time,'%Y-%m-%d') &lt;= #{endDate}
+    </select>
+
+
+</mapper>

+ 15 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/service/IMaterialInfoService.java

@@ -0,0 +1,15 @@
+package org.jeecg.modules.bytedance.common.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.jeecg.modules.bytedance.common.entity.MaterialInfo;
+
+/**
+ * 素材信息
+ *
+ * @author jeecg-boot
+ * @version V1.0
+ * @date 2019-10-11
+ */
+public interface IMaterialInfoService extends IService<MaterialInfo> {
+    MaterialInfo getParams(String signature, Integer status);
+}

+ 2 - 14
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/service/impl/FileInfoServiceImpl.java

@@ -3,28 +3,16 @@ package org.jeecg.modules.bytedance.common.service.impl;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.http.HttpEntity;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.entity.mime.MultipartEntityBuilder;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClientBuilder;
-import org.jeecg.modules.bytedance.advertise.dockapi.marketing;
-import org.jeecg.modules.bytedance.common.constant.BytedanceConstant;
+import org.jeecg.modules.bytedance.advertise.dockapi.Marketing;
 import org.jeecg.modules.bytedance.common.entity.CtopOauthToken;
 import org.jeecg.modules.bytedance.common.entity.FileInfo;
 import org.jeecg.modules.bytedance.common.mapper.FileInfoMapper;
 import org.jeecg.modules.bytedance.common.service.ICtopOauthTokenService;
 import org.jeecg.modules.bytedance.common.service.IFileInfoService;
-import org.jeecg.modules.bytedance.common.utils.PropertiesUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Primary;
 import org.springframework.stereotype.Service;
 
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.URI;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -55,7 +43,7 @@ public class FileInfoServiceImpl extends ServiceImpl<FileInfoMapper, FileInfo> i
         Map<String, Object> resultMap = new HashMap<>();
         try {
             CtopOauthToken token = ctopOauthTokenService.getOauthTokenByAccountId(accountId);
-            JSONObject jsonObject = marketing.imageUpload(token, String.valueOf(token.getAccountId()), imageUrl);
+            JSONObject jsonObject = Marketing.imageUpload(token, String.valueOf(token.getAccountId()), imageUrl);
             log.info("头条上传图片素材返回信息:{},accountId:{}", jsonObject, accountId);
         } catch (Exception e) {
             log.error("头条上传图片文件失败,accountId:{}", accountId);

+ 39 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/service/impl/MaterialInfoServiceImpl.java

@@ -0,0 +1,39 @@
+package org.jeecg.modules.bytedance.common.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.modules.bytedance.common.entity.MaterialInfo;
+import org.jeecg.modules.bytedance.common.mapper.MaterialInfoMapper;
+import org.jeecg.modules.bytedance.common.service.IMaterialInfoService;
+import org.springframework.stereotype.Service;
+
+/**
+ * 素材信息
+ *
+ * @author jeecg-boot
+ * @version V1.0
+ * @date 2019-10-11
+ */
+@Slf4j
+@Service
+public class MaterialInfoServiceImpl extends ServiceImpl<MaterialInfoMapper, MaterialInfo> implements IMaterialInfoService {
+
+    @Override
+    public MaterialInfo getParams(String signature, Integer status) {
+        QueryWrapper<MaterialInfo>queryWrapper = new QueryWrapper<>();
+        if(null!=signature&&!signature.trim().equals("")){
+            queryWrapper.eq("code",signature);
+        }
+        if(null!=status){
+            queryWrapper.eq("status",status);
+        }
+        queryWrapper.orderByDesc("create_time").last("limit 1");
+        return this.getOne(queryWrapper);
+    }
+}
+
+
+
+
+

+ 63 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/utils/StringUtils.java

@@ -1,6 +1,8 @@
 package org.jeecg.modules.bytedance.common.utils;
 
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -13,6 +15,67 @@ public class StringUtils {
     private static final Pattern HUMP_PATTERN = Pattern.compile("[A-Z]");
     public static final String COMMA = ",";
 
+    /**
+     * 获取请求地址中的某个参数
+     * @param url
+     * @param name
+     * @return
+     */
+    public static String getParamFromUrl(String url, String name) {
+        return urlSplit(url).get(name);
+    }
+
+    /**
+     * 去掉url中的路径,留下请求参数部分
+     * @param url url地址
+     * @return url请求参数部分
+     */
+    private static String truncateUrlPage(String url) {
+        String strAllParam = null;
+        String[] arrSplit = null;
+        url = url.trim().toLowerCase();
+        arrSplit = url.split("[?]");
+        if (url.length() > 1) {
+            if (arrSplit.length > 1) {
+                for (int i = 1; i < arrSplit.length; i++) {
+                    strAllParam = arrSplit[i];
+                }
+            }
+        }
+        return strAllParam;
+    }
+
+    /**
+     * 将参数存入map集合
+     * @param url  url地址
+     * @return url请求参数部分存入map集合
+     */
+    public static Map<String, String> urlSplit(String url) {
+        Map<String, String> mapRequest = new HashMap<String, String>();
+        String[] arrSplit = null;
+        String strUrlParam = truncateUrlPage(url);
+        if (strUrlParam == null) {
+            return mapRequest;
+        }
+        arrSplit = strUrlParam.split("[&]");
+        for (String strSplit : arrSplit) {
+            String[] arrSplitEqual = null;
+            arrSplitEqual = strSplit.split("[=]");
+            //解析出键值
+            if (arrSplitEqual.length > 1) {
+                //正确解析
+                mapRequest.put(arrSplitEqual[0], arrSplitEqual[1]);
+            } else {
+                if (arrSplitEqual[0] != "") {
+                    //只有参数没有值,不加入
+                    mapRequest.put(arrSplitEqual[0], "");
+                }
+            }
+        }
+        return mapRequest;
+    }
+
+
     public static ArrayList<String> stringCutFromBrace(String origin) {
         String pattern = "(?<=\\{)(.+?)(?=\\})";
         Pattern p = Pattern.compile(pattern);

+ 26 - 23
jeecg-boot-bytedance/src/main/resources/bytedance_config.properties

@@ -15,63 +15,66 @@ bytedance_v2_advertiser_info=/2/advertiser/public_info/
 bytedance_v2_ad_get=/2/ad/get/
 
 
-#创建广告计划
+#锟斤拷锟斤拷锟斤拷锟狡伙拷
 bytedance_v2_ad_create=/2/ad/create/
-#获取广告计划
+#锟斤拷取锟斤拷锟狡伙拷
 bytedance_v2_ad_get_plan=/2/ad/get/
-#获取计划审核建议
+#��ȡ�ƻ���˽���
 bytedance_v2_ad_create_reasion=/2/ad/reject_reason/
-#更新计划状态
+#锟斤拷锟铰计伙拷状态
 bytedance_v2_ad_update_status=/2/ad/update/status/
-#修改广告计划
+#锟睫改癸拷锟狡伙拷
 bytedance_v2_ad_update=/2/ad/update/
 
-#更新计划出价
+#锟斤拷锟铰计伙拷锟斤拷锟斤拷
 bytedance_v2_ad_update_bid=/2/ad/update/bid/
 
 bytedance_v2_ad_update_budget_plan=/2/ad/update/budget/
 
-#获取账户日预算
+#锟斤拷取锟剿伙拷锟斤拷预锟斤拷
 bytedance_v2_ad_get_budget=/2/advertiser/update/budget/
-#更新广告主账号设置的预算类型与预算
+#���¹�����˺����õ�Ԥ��������Ԥ��
 bytedance_v2_ad_update_budget=/2/advertiser/update/budget/
-#查询广告主下存在的的人群包列表和信
+#锟斤拷询锟斤拷锟斤拷锟斤拷麓锟斤拷诘牡锟斤拷锟饺猴拷锟斤拷斜锟斤拷锟斤拷
 bytedance_v2_dmp_custom_audience_select=/2/dmp/custom_audience/select/
-#获取创意审核建议
+#��ȡ������˽���
 bytedance_v2_create_reject_reason=/2/creative/reject_reason/
-#获取广告组
+#��ȡ�����
 bytedance_v2_campaign_get=/2/campaign/get/
-#创建广告组
+#���������
 bytedance_v2_campaign_create=/2/campaign/create/
-#广告组更新状态
+#锟斤拷锟斤拷锟斤拷锟斤拷状态
 bytedance_v2_campaign_update_status=/2/campaign/update/status/
-#修改广告组
+#�޸Ĺ����
 bytedance_v2_campaign_update=/2/campaign/update/
 
 bytedance_v2_file_video_ad=/2/file/video/ad/
 
 
-#图片上传平台
+#图片锟较达拷平台
 bytedance_v2_file_image_ad=/2/file/image/ad/
 
-#更改创意状态
+#锟斤拷锟侥达拷锟斤拷状态
 bytedance_v2_creative_update_status=/2/creative/update/status/
-#获取创意素材信
+#锟斤拷取锟斤拷锟斤拷锟截诧拷锟斤拷
 bytedance_v2_creative_material_get=/2/creative/material/read/
-#创意详细信
+#锟斤拷锟斤拷锟斤拷细锟斤拷
 bytedance_v2_creative_read=/2/creative/read_v2/
-#创建广告创意
+#������洴��
 bytedance_v2_creative_create_v2=/2/creative/create_v2/
-#获取创意列表
+#锟斤拷取锟斤拷锟斤拷锟叫憋拷
 bytedance_v2_creative_get=/2/creative/get/
-#修改创意信
+#锟睫改达拷锟斤拷锟斤拷
 bytedance_v2_creative_update_v2=/2/creative/update_v2/
 
 
-#获取行业列表
+#锟斤拷取锟斤拷业锟叫憋拷
 bytedance_v2_tools_industry_get=/2/tools/industry/get/
-#查询广告计划可用转化目标
+#锟斤拷询锟斤拷锟狡伙拷锟斤拷锟斤拷转锟斤拷目锟斤拷
 bytedance_v2_tools_ad_convert_query=/2/tools/ad_convert/query/
+#鑾峰彇瑙嗛�鎺ㄨ崘灏侀潰鎺ュ彛
+bytedance_v2_tools_video_cover_suggest=/2/tools/video_cover/suggest/
+
 
 bytedance_v2_advertiser_report_get=/2/report/advertiser/get/
 bytedance_v2_campaign_report_get=/2/report/campaign/get/