syh 6 роки тому
батько
коміт
a8543f1373

+ 6 - 4
src/views/model/model/Campaign.vue

@@ -62,8 +62,8 @@
         budgetDaily:0,
         form: this.$form.createForm(this),
         url: {
-          dictListUrl: 'toutiao/dictItem/list',
-          insertTemplateUrl:'toutiao/campaignModel/insert'
+          dictListUrl: 'toutiao/dictitem/list',
+          insertTemplateUrl:'toutiao/campaign/template/insert'
         }
       }
     },
@@ -81,13 +81,15 @@
             console.log(params)
             postAction(this.url.insertTemplateUrl,params).then((res)=>{
               console.log(res)
+              if(res.success){
+                alert("广告组模板创建成功");
+              }
             });
           }
         })
       },
       onChange(value) {
-        console.log(value)
-        this.value = value
+        console.log(value);
       },
       showBudgetStatusChange(){
         if(this.campaignBudget == 'UNLIMITED'){

+ 93 - 12
src/views/model/model/DeliveryTarget.vue

@@ -5,7 +5,7 @@
         label="投放目标"
         :labelCol="{lg: {span: 7}, sm: {span: 7}}"
         :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
-        <a-radio-group @change="onChange" v-model="value">
+        <a-radio-group @change="onChangeDeliveryTarget" v-model="deliveryTarget">
           <a-radio-button value="a">转化量</a-radio-button>
           <a-radio-button value="b">点击量</a-radio-button>
           <a-radio-button value="c">展示量</a-radio-button>
@@ -16,21 +16,22 @@
         label="下载方式"
         :labelCol="{lg: {span: 7}, sm: {span: 7}}"
         :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
-        <a-radio-group @change="onChange" v-model="value">
-          <a-radio-button value="1">下载链接</a-radio-button>
-          <a-radio-button value="2">落地页</a-radio-button>
+        <a-radio-group @change="onChangeDownloadType" v-model="downloadType">
+          <a-radio-button value="DOWNLOAD_URL">下载链接</a-radio-button>
+          <a-radio-button value="EXTERNAL_URL">落地页</a-radio-button>
         </a-radio-group>
       </a-form-item>
 
       <a-form-item
         label="下载链接"
+        v-if="showDownloadUrl"
         :labelCol="{lg: {span: 7}, sm: {span: 7}}"
         :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
         <a-input placeholder="请输入网址或从之前网站选择"/>
       </a-form-item>
 
-      <!-- TODO 选择已有尚未完成-->
       <a-form-item
+        v-if="showExternalUrl"
         label="链接地址"
         :labelCol="{lg: {span: 7}, sm: {span: 7}}"
         :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
@@ -38,16 +39,51 @@
       </a-form-item>
 
       <a-form-item
-        label="高级功能"
+        v-if="showConvertTarget"
+        label="转化目标"
         :labelCol="{lg: {span: 7}, sm: {span: 7}}"
         :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
-        <a-radio-group :options="optionsWithDisabled" disabled @change="onChange" v-model="value">
-          <a-radio-button value="as">不启用</a-radio-button>
-          <a-radio-button value="sd">直达链接</a-radio-button>
+        <a-input placeholder="请输入网址或从之前网站选择"/>
+      </a-form-item>
+
+      <a-form-item
+        label="应用包名"
+        v-if="showPackageName"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+        <a-input v-model="packageName"></a-input>
+      </a-form-item>
+
+      <a-form-item
+        label="直达链接"
+        v-if="showOpenUrlStatus"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+        <a-radio-group @change="onChangeOpenUrlStatus" v-model="openUrlStatus">
+          <a-radio-button value="disabled">不启用</a-radio-button>
+          <a-radio-button value="enabled">启用</a-radio-button>
         </a-radio-group>
       </a-form-item>
 
       <a-form-item
+        label="直达链接生成方式"
+        v-if="showOpenUrlCreateMode&&showOpenUrlStatus"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+        <a-radio-group v-model="openUrlCreateMode">
+          <a-radio-button value="auto_create" disabled>自动生成</a-radio-button>
+          <a-radio-button value="hand_create">手动生成</a-radio-button>
+        </a-radio-group>
+      </a-form-item>
+      <a-form-item
+        label="跳转app链接"
+        v-if="showToAppUrl&&showOpenUrlStatus"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+        <a-input v-model="redirectUrl"></a-input>
+      </a-form-item>
+
+      <a-form-item
         :wrapperCol="{ span: 24 }"
         style="text-align: center"
       >
@@ -63,9 +99,19 @@
     name: 'BaseForm',
     data() {
       return {
-        description: '表单页用于向用户收集或验证信息,基础表单常见于数据项较少的表单场景。',
-        value: 1,
-
+        deliveryTarget:'a',
+        packageName:'',
+        downloadType:'DOWNLOAD_URL',
+        showDownloadUrl:true,
+        showExternalUrl:false,
+        showConvertTarget:true,
+        showPackageName:true,
+        showOpenUrlStatus:false,
+        openUrlStatus:'disabled',
+        redirectUrl:'',
+        showToAppUrl:false,
+        showOpenUrlCreateMode:false,
+        openUrlCreateMode:'hand_create',
         // form
         form: this.$form.createForm(this),
 
@@ -82,6 +128,41 @@
             console.log('Received values of form: ', values)
           }
         })
+      },
+      onChange(value) {
+        console.log(value);
+      },
+      onChangeDownloadType(value){
+        console.log(value);
+        if(this.downloadType == 'DOWNLOAD_URL'){
+          this.showDownloadUrl = true;
+          this.showExternalUrl = false;
+          this.showPackageName=true;
+          this.showOpenUrlStatus=false;
+
+        }else{
+          this.showDownloadUrl = false;
+          this.showExternalUrl = true;
+          this.showPackageName=false;
+          this.showOpenUrlStatus=true;
+        }
+      },
+      onChangeDeliveryTarget(value){
+        console.log(value);
+        if(this.deliveryTarget == 'a'){
+          this.showConvertTarget = true;
+        }else {
+          this.showConvertTarget = false;
+        }
+      },
+      onChangeOpenUrlStatus(){
+        if(this.openUrlStatus=='disabled'){
+          this.showOpenUrlCreateMode = false;
+          this.showToAppUrl = false;
+        }else{
+          this.showOpenUrlCreateMode = true;
+          this.showToAppUrl = true;
+        }
       }
     }
   }

+ 599 - 41
src/views/model/model/budget.vue

@@ -4,8 +4,8 @@
       <a-form-item
         label="出价方式"
         :labelCol="{lg: {span: 7}, sm: {span: 7}}"
-        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
-        <a-radio-group @change="onChange" v-model="setBidType">
+        :wrapperCol="{lg: {span: 15}, sm: {span: 17} }">
+        <a-radio-group @change="onChange" v-model="bidType">
           <a-radio-button v-for="bidType in bidTypeList" :key="bidType.itemValue" :value="bidType.itemValue">
             {{bidType.itemText}}
           </a-radio-button>
@@ -15,8 +15,8 @@
       <a-form-item
         label="投放方式"
         :labelCol="{lg: {span: 7}, sm: {span: 7}}"
-        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
-        <a-radio-group @change="onChange" v-model="setFlowControlMode">
+        :wrapperCol="{lg: {span: 15}, sm: {span: 17} }">
+        <a-radio-group @change="onChange" v-model="flowControlMode">
           <a-radio-button v-for="flowControlMode in flowControlModeList" :key="flowControlMode.itemValue"
                           :value="flowControlMode.itemValue">
             {{flowControlMode.itemText}}
@@ -26,12 +26,12 @@
       <a-form-item
         label="预算"
         :labelCol="{lg: {span: 7}, sm: {span: 7}}"
-        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
-        <a-input v-model="setBudgetPrice"
+        :wrapperCol="{lg: {span: 15}, sm: {span: 17} }">
+        <a-input v-model="budgetPrice"
                  style="width: 70%">
           <a-select
             slot="addonBefore"
-            v-model="setBudgetMode"
+            v-model="budgetPriceMode"
             v-decorator="['prefix',{ initialValue: 'BUDGET_MODE_DAY' }]"
             style="width: 100px">
             <a-select-option value="BUDGET_MODE_DAY">日预算</a-select-option>
@@ -44,36 +44,51 @@
       <a-form-item
         label="投放时间"
         :labelCol="{lg: {span: 7}, sm: {span: 7}}"
-        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
-        <a-radio-group @change="onChangeFlowDate" v-model="setFlowDate">
+        :wrapperCol="{lg: {span: 15}, sm: {span: 17} }">
+        <a-radio-group @change="onChangeFlowDate" v-model="flowDate">
           <a-radio-button v-for="flowDate in flowDateList" :key="flowDate.itemValue" :value="flowDate.itemValue">
             {{flowDate.itemText}}
           </a-radio-button>
         </a-radio-group>
-        <br>
-        <a-range-picker @change="onChange" v-if="showDateFlow" v-model="setDateFlowRange"/>
       </a-form-item>
 
+      <a-form-item label="起始时间"
+                   v-if="showDateFlowRange"
+                   :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+                   :wrapperCol="{lg: {span: 15}, sm: {span: 17} }">
+        开始时间:
+        <a-date-picker v-model="startDate"
+                       format="YYYY-MM-DD"
+                       :disabledDate="disabledDate"
+        />
+        结束时间:
+        <a-date-picker v-model="endDate"
+                       format="YYYY-MM-DD"
+                       :disabledDate="disabledDate"
+        />
+      </a-form-item>
       <a-form-item
         label="投放时段"
         :labelCol="{lg: {span: 7}, sm: {span: 7}}"
-        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
-        <a-radio-group v-model="setDateQuantum">
+        :wrapperCol="{lg: {span: 15}, sm: {span: 17} }">
+        <a-radio-group @change="dateQuantumChange" v-model="dateQuantum">
           <a-radio-button value="date_unlimited">不限</a-radio-button>
           <a-radio-button value="date_appoint">指定时间段</a-radio-button>
         </a-radio-group>
       </a-form-item>
       <a-form-item
+        v-if="showDateQuantumRange"
         label="设置时间段"
         :labelCol="{lg: {span: 7}, sm: {span: 7}}"
-        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
-        <a-range-picker @change="onChange"/>
+        :wrapperCol="{lg: {span: 15}, sm: {span: 17} }">
+        <div id="table_time_selected1" class="table_time_selected1">
+        </div>
       </a-form-item>
       <a-form-item
         label="付费方式"
         :labelCol="{lg: {span: 7}, sm: {span: 7}}"
-        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
-        <a-radio-group @change="onChange" v-model="setPriceType">
+        :wrapperCol="{lg: {span: 15}, sm: {span: 17} }">
+        <a-radio-group @change="onChange" v-model="priceType">
           <a-radio-button value="PRICING_OCPM">按展示付费(oCPM)</a-radio-button>
           <a-radio-button value="PRICING_OCPC">按点击付费(oCPC)</a-radio-button>
         </a-radio-group>
@@ -82,15 +97,15 @@
       <a-form-item
         label="目标转化出价"
         :labelCol="{lg: {span: 7}, sm: {span: 7}}"
-        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
-        <a-input-number v-model="setConvertPrice" :min="0" :max="10" @change="onChange"/>
+        :wrapperCol="{lg: {span: 15}, sm: {span: 17} }">
+        <a-input-number v-model="convertPrice" :min="0" :max="10" @change="onChange"/>
       </a-form-item>
       <a-form-item
         label="过滤已转化用户"
         :labelCol="{lg: {span: 7}, sm: {span: 7}}"
-        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
-        <a-radio-group v-model="setFilterType">
+        :wrapperCol="{lg: {span: 15}, sm: {span: 17} }">
+        <a-radio-group v-model="filterType">
           <a-radio-button v-for="filterType in filterTypeList" :key="filterType.itemValue"
                           :value="filterType.itemValue">
             {{filterType.itemText}}
@@ -111,52 +126,71 @@
 
 <script>
   import {deleteAction, postAction, getAction} from '@/api/manage'
+  import $ from 'jquery'
+  import moment from 'moment';
 
   export default {
     name: 'BaseForm',
     data() {
       return {
-        setConvertPrice: 0,
-        setBudgetPrice: 0,
-        setBudgetMode: 'BUDGET_MODE_DAY',
-        showDateFlow: false,
-        setFlowControlMode: 'FLOW_CONTROL_MODE_FAST',
-        setFlowDate: 'SCHEDULE_FROM_NOW',
-        setDateQuantum: 'date_unlimited',
-        setBidType: 'SMART_BID_CUSTOM',
+        startDate:moment(new Date(), "YYYY-MM-dd"),
+        endDate:moment(new Date(), "YYYY-MM-dd"),
+        convertPrice: 0,
+        budgetPrice: 0,
+        budgetPriceMode: 'BUDGET_MODE_DAY',
+        showDateFlowRange: false,
+        showDateQuantumRange:false,
+        flowControlMode: 'FLOW_CONTROL_MODE_FAST',
+        flowDate: 'SCHEDULE_FROM_NOW',
+        dateQuantum: 'date_unlimited',
+        dateQuantumRange: '',
+        bidType: 'SMART_BID_CUSTOM',
         bidTypeList: {},
-        value: {},
-        setPriceType: 'PRICING_OCPM',
+        priceType: 'PRICING_OCPM',
         flowControlModeList: {},
         filterTypeList: {},
         price: 0,
-        setFilterType: "NO_EXCLUDE",
+        filterType: "NO_EXCLUDE",
         flowDateList: {},
         form: this.$form.createForm(this),
         url: {
-          dictListUrl: 'toutiao/dictItem/list'
+          dictListUrl: 'toutiao/dictitem/list'
         }
       }
     },
     methods: {
+      moment,
+      disabledDate(current) {
+        return current <moment().endOf('day');
+      },
       handleSubmit(e) {
         e.preventDefault()
         this.form.validateFields((err, values) => {
           if (!err) {
-            console.log('Received values of form: ', values)
+            console.log('Received values of form: ', values);
+            this.dateQuantumRange = $("#table_time_selected1_time_num").val();
+            alert(this.dateQuantumRange);
+
           }
         })
       },
       onChange(value) {
         console.log(value)
-        this.value = value
       },
-      onChangeFlowDate(value) {
-        console.log(this.setFlowDate)
-        if (this.setFlowDate == 'date_unlimited') {
-          this.showDateFlow = false;
+      dateQuantumChange(){
+        console.log(this.dateQuantum)
+        if (this.dateQuantum == 'date_unlimited') {
+          this.showDateQuantumRange = true;
+        } else {
+          this.showDateQuantumRange = true;
+        }
+      },
+      onChangeFlowDate() {
+        console.log(this.flowDate)
+        if (this.flowDate == 'SCHEDULE_FROM_NOW') {
+          this.showDateFlowRange = false;
         } else {
-          this.showDateFlow = true;
+          this.showDateFlowRange = true;
         }
       }
     },
@@ -208,8 +242,532 @@
           this.filterTypeList = res.result.records
         }
       });
+    }
+  }
+
+  var box_id;
+  var StartTD = null;
+  var StartIndex = null;
+  var EndTD = null;
+  var EndIndex = null;
+  var Selected = 'Selected';
+  var Start_x = null;
+  var Start_y = null;
+  //点击中表格的小时值
+  var hour;
+  //点击选中的星期值
+  var week;
+  //1为这个格子在此次鼠标拖拽过程中被选中(不执行选中方法),0为没选中过
+  var td_state = 0;
+  //生成星期数组
+  var num = ['一','二','三','四','五','六','日'];
+  //生成时间值数组
+  var arr_hour = get_hour_arr();
+
+
+  //按下鼠标左键拖动选中单元格
+  function SelectTD(StartIndex, EndIndex,Selected) {
+
+    var MinX = null;
+    var MaxX = null;
+    var MinY = null;
+    var MaxY = null;
+
+    var coordinate = get_coordinate(StartIndex, EndIndex);
+    MinX = coordinate[0];
+    MaxX = coordinate[1];
+    MinY = coordinate[2];
+    MaxY = coordinate[3];
+
+    for (var i = MinY; i <= MaxY; i++) {
+
+      for (var j = MinX; j <= MaxX; j++) {
+
+        var SelectTR = $('#' + box_id + ' table tbody tr ').eq(i);
+        var td_class = $("td", SelectTR).eq(j).attr('class');
+        td_state = $("td", SelectTR).eq(j).attr("td_state");
+
+        //在同一次鼠标按下的过程中,选中过的表格不进行选中或取消操作
+        if (!td_state) {
+          if (td_class == Selected) {
+            $("td", SelectTR).eq(j).removeClass(Selected);
+          }else{
+            //筛选掉标明为星期的表格
+            $("td", SelectTR).eq(j).attr("class", Selected);
+          }
+          $("td", SelectTR).eq(j).attr("td_state", '1');
+        }
 
+      }
 
     }
+
+    //改变二进制值
+    get_time_val();
+    //改变日期显示
+    convert_date();
+
+  }
+
+  //点击选中或去掉选中整行、整列
+  function SelectTD_click(StartIndex, EndIndex,Selected) {
+
+    var MinX = null;
+    var MaxX = null;
+    var MinY = null;
+    var MaxY = null;
+    var Selected_true = 0;
+    var Selected_false = 0;
+
+    var coordinate = get_coordinate(StartIndex, EndIndex);
+    MinX = coordinate[0];
+    MaxX = coordinate[1];
+    MinY = coordinate[2];
+    MaxY = coordinate[3];
+
+    //列出此列当中的表格选中状态
+    for (var i = MinY; i <= MaxY; i++) {
+
+      for (var j = MinX; j <= MaxX; j++) {
+
+        var SelectTR = $('#' + box_id + ' table tbody tr ').eq(i);
+        var td_class = $("td", SelectTR).eq(j).attr('class');
+
+        if (td_class == Selected) {
+          //表格里存在已选中的元素
+          Selected_true = 1;
+        }else{
+          //表格里存在未选中的元素
+          Selected_false = 1;
+        }
+
+      }
+
+    }
+
+    //执行选中或去掉选中方法
+    for (var i = MinY; i <= MaxY; i++) {
+
+      for (var j = MinX; j <= MaxX; j++) {
+
+        var SelectTR = $('#' + box_id + ' table tbody tr ').eq(i);
+        var td_class = $("td", SelectTR).eq(j).attr('class');
+
+        //一列当中存在已选中与未选中的表格处理:整列全部选中
+        if (Selected_true == 1 && Selected_false == 1) {
+          $("td", SelectTR).eq(j).attr("class", Selected);
+        }else if(Selected_false == 1){
+          //一列当中只存在未选中的表格处理:整列全部选中
+          $("td", SelectTR).eq(j).attr("class", Selected);
+        }else{
+          //一列当中只存在已选中的表格处理:整列全部去掉选中
+          $("td", SelectTR).eq(j).removeClass(Selected);
+        }
+
+      }
+
+    }
+    //改变二进制值
+    get_time_val();
+    //改变日期显示
+    convert_date();
+  }
+
+  //获取选中范围的开始与结束的坐标
+  function get_coordinate(StartIndex, EndIndex){
+    var MinX = null;
+    var MaxX = null;
+    var MinY = null;
+    var MaxY = null;
+
+    if (StartIndex.x < EndIndex.x) {
+      MinX = StartIndex.x; MaxX = EndIndex.x;
+    }else {
+      MinX = EndIndex.x; MaxX = StartIndex.x;
+    }
+    if (StartIndex.y < EndIndex.y) {
+      MinY = StartIndex.y; MaxY = EndIndex.y;
+    } else {
+      MinY = EndIndex.y; MaxY = StartIndex.y;
+    }
+    return [MinX, MaxX, MinY, MaxY];
+  }
+
+  //改变二进制值
+  function get_time_val(){
+    var time_type = '';
+    $('#' + box_id + ' table tbody').find('td').each(function(k){
+      var Selected_type = $(this).attr('class');
+      var week = $(this).attr('week');
+
+      if (Selected_type == Selected && !week) {
+        time_type +="1";
+      }else if(!week){
+        time_type +="0";
+      }
+    });
+    $('#'+box_id+'_time_num').val(time_type);
+    // convert_date();
+  }
+  //二进制数转换日期
+  function convert_date(external_binary){
+    //初始化周数数组
+    var time_week_arr = [];
+    if (!external_binary) {
+      //内部调用,进行选中表格和输出时间操作。
+      var binary = $('#'+box_id+'_time_num').val();
+    }else{
+      //存在外部参入传入,此函数进行返回时间操作。
+      var date_html = '';
+      var binary = external_binary;
+    }
+
+    for (var y = 0; y < 7; y++) {
+      //初始化小时数组
+      var time_hour_arr = [];
+
+      for (var x = 0; x < 48; x++) {
+
+        //获取当前点击元素的位置
+        if (y==0) {
+          var index = x;
+        }else{
+          var index = (y*48)+x;
+        }
+        //获取td对应的二进制值
+        var Selected_val = binary.charAt(index);
+
+        if (Selected_val ==1) {
+          //组装保存进数组里
+          if (time_hour_arr == []) {
+            //表格的第一个位置的值
+            time_hour_arr = arr_hour[x];
+          }else if(binary.charAt(index-1) == 1 && binary.charAt(index-2) == 1 ){
+            //此位置(包含上一行)的前两个都为选中时
+
+            if (x==0 && binary.charAt(index+1) == 0) {
+              //选中行里第一个,后一个表格没选中,加逗号
+              time_hour_arr[time_hour_arr.length] = arr_hour[x] + ', ';
+            }else if(x==0 && binary.charAt(index+1) == 1){
+              //选中行里第一个,后一个表格已选中,不加逗号
+              time_hour_arr[time_hour_arr.length] = arr_hour[x];
+            }else if(x==1 && binary.charAt(index-1) == 0){
+              //选中行里第二个,上一个表格没选中,加逗号
+              time_hour_arr[time_hour_arr.length] = arr_hour[x] +', ';
+            }else if(x==1 && binary.charAt(index-1) == 1){
+              //选中行里第二个,上一个表格已选中,前加-号,后加逗号
+              time_hour_arr[time_hour_arr.length] = '-' + arr_hour[x] +', ';
+            }else{
+              //选中行里除第一、二的表格以外,前一个表格已经选中,此元素前加- 后加逗号
+              time_hour_arr[time_hour_arr.length-1] = '-' + arr_hour[x] +', ';
+            }
+
+          }else if(binary.charAt(index-1) == 1 && x>0){
+            //选中的前一个已选中,且此次选中的不是行里第一个,此次选中的元素前加-后加逗号
+            time_hour_arr[time_hour_arr.length] = '-' + arr_hour[x] + ', ';
+          }else if(binary.charAt(index+1) != 1 || x==47){
+            //选中的后一个没选中,或者此次选中的是行里最后一个,此次选中的元素加逗号
+            time_hour_arr[time_hour_arr.length] = arr_hour[x] + ', ';
+          }else{
+            //选中的后一已选中,此次选中的元素不加逗号
+            time_hour_arr[time_hour_arr.length] = arr_hour[x] ;
+          }
+        }
+      }
+
+      time_week_arr[y] = time_hour_arr;
+
+    }
+// console.info(box_id);
+    if (!external_binary) {
+      $('#'+box_id+'_time_seled').html('');
+    }
+    //再次组装并输出数组
+    var time_html = [];
+    for(var y = 0; y < 7; y++){
+
+      for(var x = 0; x < time_week_arr[y].length; x++){
+
+        if (!time_html[y]) {
+          time_html[y] = time_week_arr[y][x];
+        }else{
+          time_html[y] += time_week_arr[y][x];
+        }
+
+      }
+
+      if (time_html[y]) {
+        time_html[y]=  time_html[y].substring(0,time_html[y].length-2);
+
+        if (!external_binary) {
+          $('#'+box_id+'_time_seled').append('<div>星期'+num [y] + ' (' +time_html[y] + ')' + '</div>');
+        }else{
+          date_html += '星期'+num [y] + ' (' +time_html[y] + ')' + ', ';
+        }
+      }
+    }
+
+    if (external_binary) {
+      return date_html;
+    }
+    // console.info(time_html);
+  }
+
+  //生成时间值数组
+  function get_hour_arr(){
+    var arr_hour = [];
+    var oDate = new Date("2016/07/01 00:00:00"); //实例一个时间对象;
+    var oDate_hour = oDate.getHours();
+    var oDate_minute = oDate.getMinutes();
+    for(var i=0; i<48; i++){
+      if(oDate_minute<10){
+        var oDate_minute = "0"+oDate_minute;
+      }
+      if (i >=1) {
+        oDate.setMinutes(oDate.getMinutes() + 30);
+        oDate_hour = oDate.getHours();
+        oDate_minute = oDate.getMinutes();
+        if(oDate_minute<10){
+          var oDate_minute = "0"+oDate_minute;
+        }
+      }
+      arr_hour[i] = oDate_hour + ':' + oDate_minute;
+      // alert(oDate_hour + ':' + oDate.getMinutes());
+    }
+    return arr_hour;
+  }
+
+  //更新操作
+  function renewal(id){
+    if (id) {
+      box_id = id;
+    }
+    //解绑鼠标移动监听事件
+    $('#' + box_id + ' table tbody tr td').unbind("mouseover");
+    //初始化表格的在此次选中状态
+    $('#' + box_id + ' table tbody tr td').attr("td_state", '');
+    //改变二进制值
+    get_time_val();
+    //改变日期显示
+    convert_date();
+  }
+
+  //二进制数赋值选中表格
+  function binary_selected(){
+    var default_time_val = $('#'+box_id+' .default_time_val').val();
+    if (default_time_val) {
+      for(i=0 ; i<336; i++){
+        var td_selected = default_time_val.charAt(i);
+        if (td_selected != 0 ) {
+          $('#' + box_id + ' table tbody tr td').eq(i).attr('class','Selected');
+          //更新操作,显示文字形日期
+          renewal();
+        }
+
+      }
+    }
+  }
+
+
+  //实例化程序
+  function load_time_table(id){
+    //包住table的元素id
+    box_id = id;
+    var html;
+    html = '<table cellspacing="0" cellpadding="0" border="0" class="plug-timer-grid"  onselectstart="return false" onselect="document.selection.empty()">';
+    html += '<thead>';
+    html += '<tr>';
+    html += '<th></th>';
+    html += '<th colSpan="24">上午</th>';
+    html += '<th colSpan="24">下午</th>';
+    html += '</tr>';
+    html += '<tr class="hour">';
+    html += '<th></th>';
+    html += '</tr>';
+    html += '</thead>';
+    html += '<tbody></tbody>';
+    html += '</table>';
+    html += '<input class="focus" style="opacity: 0;">';
+    html += '<div id="'+box_id+'_time_seled"></div>';
+    html += '<input v-model="dateQuantumRange" type="hidden" id="'+box_id+'_time_num" name="time" caption="每日投放时段" switchname="selectTime"  value="">';
+    $('#'+box_id).append(html);
+    var html_tbody_td = '';
+    var html_thead_td = '';
+
+    //创建表格
+    for (var i = 0; i < 7; i++) {
+      var week = i+1;
+      html_tbody_td += '<tr>';
+      for (var j = 0; j < 49; j++){
+        if (j==0) {
+          html_tbody_td += '<th week="'+week+'">周' + num[i] +  '</th>';
+        }else{
+          html_tbody_td += '<td>'  +  '</td>';
+        }
+      }
+      html_tbody_td += '</tr>';
+    }
+
+    //创建表格小时栏目
+    for(var i =0; i<= 23; i++){
+      html_thead_td += '<td colSpan="2" hour="'+i+'">'+ i + '</td>';
+    }
+    $('#' + box_id + ' table thead .hour').append(html_thead_td);
+    $('#' + box_id + ' table tbody').html(html_tbody_td);
+
+    //检查是否有赋有二进制值,如有,将选中相应的表格
+    binary_selected();
+
+    //控制器,控制当前在哪个表格进行操作
+    $('.plug-timer-grid').hover(function (e) {
+      if(1 != e.which){    //判断是否为左击
+        var id = $(this).parent().attr('id');
+        box_id = id;
+      }
+    });
+
+    //清除所有选中项
+    $('.clear').click(function(){
+      $(this).parent().find('td').removeClass(Selected);
+      var id =$(this).parent().attr('id');
+      renewal(id);
+    });
+
+    //点击小时选中或去掉整列处理块
+    $('#' + box_id + ' table thead tr td').click(function(){
+      hour = $(this).attr('hour');
+      if (hour>=0) {
+        var rows = $('#' + box_id + ' table tbody tr').length;
+        Start_x = ($(this).index())*2-1;
+        Start_y = 0;
+
+        StartIndex = { x: Start_x, y: Start_y };
+
+        EndTD = $(this);
+        var x = ($(this).index())*2-2;
+        var y = rows -1;    //为了配合for计算公式-1
+
+        EndIndex = { x: x, y: y };
+        //改变第一次按下鼠标时候的改变选中状态
+        SelectTD_click(StartIndex, EndIndex, Selected);
+      }
+    });
+
+    //点击星期选中或去掉整行处理块
+    $('#' + box_id + ' table tbody tr th').click(function(){
+      var week = $(this).attr('week');
+      if (week>=0) {
+        var line = $('#' + box_id + ' table tbody tr td').length/$('#' + box_id + ' table tbody tr').length;
+
+        Start_x = 0;
+        Start_y = $(this).parent().index();
+
+        StartIndex = { x: Start_x, y: Start_y };
+
+        EndTD = $(this);
+        var y = $(this).parent().index();
+        var x = line-1;     //为了配合for计算公式-1
+
+        EndIndex = { x: x, y: y };
+
+        //改变第一次按下鼠标时候的改变选中状态
+        SelectTD_click(StartIndex, EndIndex, Selected);
+      }
+    });
+
+    //监听鼠标按下事件(鼠标按下左键拖动选中处理块)
+    $('#' + box_id + ' table tbody tr td').unbind("mousedown").bind("mousedown", function () {
+      //记录刚开始点击的元素位置
+      Start_x = $(this).index()-1;
+      Start_y = $(this).parent().index();
+      StartIndex = { x: Start_x, y: Start_y };
+
+      EndTD = $(this);
+      var x = $(this).index()-1;
+      var y = $(this).parent().index();
+      EndIndex = { x: x, y: y };
+      //改变第一次按下鼠标时候的改变选中状态
+      SelectTD(StartIndex, EndIndex, Selected);
+
+      StartTD = $(this);
+
+      StartIndex = { x: Start_x, y: Start_y };
+
+      //监听鼠标移动事件,实现改变后续鼠标拖拽时候的表格选中状态
+      $('#' + box_id + ' table tbody tr td').mouseover(function(e){
+        EndTD = $(this);
+        var x = $(this).index()-1;
+        var y = $(this).parent().index();
+        EndIndex = { x: x, y: y };
+        if(1 != e.which){    //判断是否为左击
+          $('#' + box_id + ' table tbody tr td').unbind("mouseover");
+        }
+        //去除停留在td上的光标
+        $('#' + box_id + ' .focus').focus();
+        SelectTD(StartIndex, EndIndex, Selected);
+      });
+
+
+      //放开鼠标左键时,初始化相关参数和解绑相关监听
+      $('html').unbind("mouseup").bind("mouseup", function () {
+        renewal();
+      });
+
+    });
+
+  }
+
+  /*外部调用接口*/
+
+  //解绑鼠标松开监听事件
+  function unbundle_mouseover(){
+    $('html').unbind("mouseup");
+  }
+
+  /*二进制获取转换后的时间*/
+  function get_time_html(binary){
+    return convert_date(binary);
+  }
+
+  $(function(){
+    load_time_table('table_time_selected1');
+  });
+
+</script>
+<style type="text/css">
+  .plug-timer-grid{width: 80%;}
+  .plug-timer-grid td, .plug-timer-grid th{border: 1px solid #97B4D1;text-align: center; /*cursor:pointer;*/}
+  .Selected{background-color: rgb(102,162,243);opacity: 0.5;}
+
+  .plug-timer-grid {
+    border-collapse: collapse;
+    z-index: 4;
+  }
+  .plug-timer-grid thead tr{
+    display: table-row;
+    vertical-align: inherit;
+    border-color: inherit;
+  }
+
+  table td{
+    height: 30px;
+    max-width: 5px;
+    border: 1px solid #dfe6ec;
+    font-size: 12px;
+    text-align: center;
+    vertical-align: middle;
+    overflow: hidden;
+    transition: background .5s;
+    -webkit-transition: background .5s;
+  }
+
+  .plug-timer-grid tbody th{
+    width: 4%;
+  }
+  .plug-timer-grid tbody tr td{
+    width: 2%;
+  }
+  .clear{
+    margin:20px 0px 20px 0px;
   }
-</script>
+</style>

+ 794 - 0
src/views/template/budget/create.vue

@@ -0,0 +1,794 @@
+<template>
+  <a-card :body-style="{padding: '24px 32px'}" :bordered="false">
+    <a-form @submit="handleSubmit" :form="form">
+      <a-form-item
+        label="出价方式"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 15}, sm: {span: 17} }">
+        <a-radio-group v-model="bidType">
+          <a-radio-button v-for="bidType in bidTypeList" :key="bidType.itemValue" :value="bidType.itemValue">
+            {{bidType.itemText}}
+          </a-radio-button>
+        </a-radio-group>
+      </a-form-item>
+
+      <a-form-item
+        label="投放方式"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 15}, sm: {span: 17} }">
+        <a-radio-group v-model="flowControlMode">
+          <a-radio-button v-for="flowControlMode in flowControlModeList" :key="flowControlMode.itemValue"
+                          :value="flowControlMode.itemValue">
+            {{flowControlMode.itemText}}
+          </a-radio-button>
+        </a-radio-group>
+      </a-form-item>
+      <a-form-item
+        label="预算"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 15}, sm: {span: 17} }">
+        <a-input v-model="budgetPrice"
+                 style="width: 70%">
+          <a-select
+            slot="addonBefore"
+            v-model="budgetPriceMode"
+            v-decorator="['prefix',{ initialValue: 'BUDGET_MODE_DAY' }]"
+            style="width: 100px">
+            <a-select-option value="BUDGET_MODE_DAY">日预算</a-select-option>
+            <a-select-option value="BUDGET_MODE_TOTAL">总预算</a-select-option>
+          </a-select>
+        </a-input>
+        元
+      </a-form-item>
+
+      <a-form-item
+        label="投放时间"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 15}, sm: {span: 17} }">
+        <a-radio-group @change="onChangeFlowDate" v-model="flowDateType">
+          <a-radio-button v-for="flowDate in flowDateList" :key="flowDate.itemValue" :value="flowDate.itemValue">
+            {{flowDate.itemText}}
+          </a-radio-button>
+        </a-radio-group>
+      </a-form-item>
+
+      <a-form-item label="起始时间"
+                   v-if="showDateFlowRange"
+                   :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+                   :wrapperCol="{lg: {span: 15}, sm: {span: 17} }">
+        开始时间:
+        <a-date-picker v-model="startDate"
+                       format="YYYY-MM-DD"
+                       :disabledDate="disabledDate"
+        />
+        结束时间:
+        <a-date-picker v-model="endDate"
+                       format="YYYY-MM-DD"
+                       :disabledDate="disabledDate"
+        />
+      </a-form-item>
+      <a-form-item
+        label="投放时段"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 15}, sm: {span: 17} }">
+        <a-radio-group @change="dateQuantumChange" v-model="dateQuantum">
+          <a-radio-button value="date_unlimited">不限</a-radio-button>
+          <a-radio-button value="date_appoint">指定时间段</a-radio-button>
+        </a-radio-group>
+      </a-form-item>
+      <a-form-item
+        v-if="showDateQuantumRange"
+        label="设置时间段"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 15}, sm: {span: 17} }">
+        <div id="table_time_selected1" class="table_time_selected1">
+        </div>
+      </a-form-item>
+      <a-form-item
+        label="付费方式"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 15}, sm: {span: 17} }">
+        <a-radio-group v-model="priceType">
+          <a-radio-button value="PRICING_OCPM">按展示付费(oCPM)</a-radio-button>
+          <a-radio-button value="PRICING_OCPC">按点击付费(oCPC)</a-radio-button>
+        </a-radio-group>
+      </a-form-item>
+
+      <a-form-item
+        label="目标转化出价"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 15}, sm: {span: 17} }">
+        <a-input-number v-model="convertPrice" :min="0" :max="10" @change="onChange"/>
+        元
+      </a-form-item>
+      <a-form-item
+        label="过滤已转化用户"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 15}, sm: {span: 17} }">
+        <a-radio-group v-model="filterType">
+          <a-radio-button v-for="filterType in filterTypeList" :key="filterType.itemValue"
+                          :value="filterType.itemValue">
+            {{filterType.itemText}}
+          </a-radio-button>
+        </a-radio-group>
+      </a-form-item>
+
+      <a-form-item
+        :wrapperCol="{ span: 24 }"
+        style="text-align: center"
+      >
+        <a-button htmlType="submit" type="primary">提交</a-button>
+        <a-button style="margin-left: 8px">保存</a-button>
+      </a-form-item>
+    </a-form>
+  </a-card>
+</template>
+
+<script>
+  import {deleteAction, postAction, getAction} from '@/api/manage'
+  import $ from 'jquery'
+  import moment from 'moment';
+
+  export default {
+    name: 'BaseForm',
+    data() {
+      return {
+        startDate:moment(new Date(), "YYYY-MM-dd"),
+        endDate:moment(new Date(), "YYYY-MM-dd"),
+        convertPrice: 0,
+        budgetPrice: 0,
+        budgetPriceMode: 'BUDGET_MODE_DAY',
+        showDateFlowRange: false,
+        showDateQuantumRange:true,
+        flowControlMode: 'FLOW_CONTROL_MODE_FAST',
+        flowDateType: 'SCHEDULE_FROM_NOW',
+        dateQuantum: 'date_unlimited',
+        dateQuantumRange: '',
+        bidType: 'SMART_BID_CUSTOM',
+        bidTypeList: {},
+        priceType: 'PRICING_OCPM',
+        flowControlModeList: {},
+        filterTypeList: {},
+        price: 0,
+        filterType: "NO_EXCLUDE",
+        flowDateList: {},
+        form: this.$form.createForm(this),
+        url: {
+          dictListUrl: 'toutiao/dictitem/list',
+          insertUrl:'toutiao/budget/template/insert'
+        }
+      }
+    },
+    methods: {
+      moment,
+      disabledDate(current) {
+        return current <moment().endOf('day');
+      },
+      handleSubmit(e) {
+        e.preventDefault()
+        this.form.validateFields((err, values) => {
+          if (!err) {
+            console.log('Received values of form: ', values);
+
+            let params = {};
+            this.dateQuantumRange = $("#table_time_selected1_time_num").val();
+            params.bidType = this.bidType;
+            params.flowControlMode = this.flowControlMode;
+            params.budgetPrice = this.budgetPrice;
+            params.budgetPriceMode = this.budgetPriceMode;
+            params.flowDateType = this.flowDateType;
+            params.startDate = this.startDate;
+            params.endDate = this.endDate;
+            params.dateQuantum = this.dateQuantum;
+            params.priceType = this.priceType;
+            params.convertPrice = this.convertPrice;
+            params.filterType = this.filterType;
+            params.dateQuantumRange = this.dateQuantumRange;
+            console.log(params)
+            postAction(this.url.insertUrl,params).then((res)=>{
+              console.log(res)
+              if(res.success){
+                alert("预算模板创建成功");
+              }
+            });
+
+          }
+        })
+      },
+      onChange(value) {
+        console.log(value)
+      },
+      dateQuantumChange(value){
+        console.log(this.dateQuantum);
+        if (this.dateQuantum == 'date_unlimited') {
+          this.showDateQuantumRange = true;
+        } else {
+          this.showDateQuantumRange = true;
+        }
+      },
+      onChangeFlowDate() {
+        console.log(this.flowDate)
+        if (this.flowDate == 'SCHEDULE_FROM_NOW') {
+          this.showDateFlowRange = false;
+        } else {
+          this.showDateFlowRange = true;
+        }
+      }
+    },
+    created: function () {
+      //出价方式
+      let params = {};
+      params.dictId = '35c0634f642a0da32dcd2c75b4f03ad9';
+      params.pageSize = '1000';
+      getAction(this.url.dictListUrl, params).then((res) => {
+        if (res.success) {
+          this.bidTypeList = res.result.records
+        }
+      });
+      //投放方式(计划投放速度类型)
+      params = {};
+      params.dictId = '46e24e805d5cd0356a9f4560d987a276';
+      params.pageSize = '1000';
+      getAction(this.url.dictListUrl, params).then((res) => {
+        if (res.success) {
+          this.flowControlModeList = res.result.records
+        }
+      });
+      //投放时间类型
+      params = {};
+      params.dictId = '4c5bb1a99115c6130d6f71b3784a99ab';
+      params.pageSize = '1000';
+      getAction(this.url.dictListUrl, params).then((res) => {
+        if (res.success) {
+          this.flowDateList = res.result.records
+        }
+      });
+
+      // //付费方式类型
+      // params = {};
+      // params.dictId = '46e24e805d5cd0356a9f4560d987a276';
+      // params.pageSize = '1000';
+      // getAction(this.url.dictListUrl,params).then((res) => {
+      //   if (res.success) {
+      //     this.flowControlModeList = res.result.records
+      //   }
+      // });
+
+      //过滤已转化用户
+      params = {};
+      params.dictId = 'd06027ca9be05d60b2946e5276fa1cba';
+      params.pageSize = '1000';
+      getAction(this.url.dictListUrl, params).then((res) => {
+        if (res.success) {
+          this.filterTypeList = res.result.records
+        }
+      });
+    }
+  }
+
+  var box_id;
+  var StartTD = null;
+  var StartIndex = null;
+  var EndTD = null;
+  var EndIndex = null;
+  var Selected = 'Selected';
+  var Start_x = null;
+  var Start_y = null;
+  //点击中表格的小时值
+  var hour;
+  //点击选中的星期值
+  var week;
+  //1为这个格子在此次鼠标拖拽过程中被选中(不执行选中方法),0为没选中过
+  var td_state = 0;
+  //生成星期数组
+  var num = ['一','二','三','四','五','六','日'];
+  //生成时间值数组
+  var arr_hour = get_hour_arr();
+
+
+  //按下鼠标左键拖动选中单元格
+  function SelectTD(StartIndex, EndIndex,Selected) {
+
+    var MinX = null;
+    var MaxX = null;
+    var MinY = null;
+    var MaxY = null;
+
+    var coordinate = get_coordinate(StartIndex, EndIndex);
+    MinX = coordinate[0];
+    MaxX = coordinate[1];
+    MinY = coordinate[2];
+    MaxY = coordinate[3];
+
+    for (var i = MinY; i <= MaxY; i++) {
+
+      for (var j = MinX; j <= MaxX; j++) {
+
+        var SelectTR = $('#' + box_id + ' table tbody tr ').eq(i);
+        var td_class = $("td", SelectTR).eq(j).attr('class');
+        td_state = $("td", SelectTR).eq(j).attr("td_state");
+
+        //在同一次鼠标按下的过程中,选中过的表格不进行选中或取消操作
+        if (!td_state) {
+          if (td_class == Selected) {
+            $("td", SelectTR).eq(j).removeClass(Selected);
+          }else{
+            //筛选掉标明为星期的表格
+            $("td", SelectTR).eq(j).attr("class", Selected);
+          }
+          $("td", SelectTR).eq(j).attr("td_state", '1');
+        }
+
+      }
+
+    }
+
+    //改变二进制值
+    get_time_val();
+    //改变日期显示
+    convert_date();
+
+  }
+
+  //点击选中或去掉选中整行、整列
+  function SelectTD_click(StartIndex, EndIndex,Selected) {
+
+    var MinX = null;
+    var MaxX = null;
+    var MinY = null;
+    var MaxY = null;
+    var Selected_true = 0;
+    var Selected_false = 0;
+
+    var coordinate = get_coordinate(StartIndex, EndIndex);
+    MinX = coordinate[0];
+    MaxX = coordinate[1];
+    MinY = coordinate[2];
+    MaxY = coordinate[3];
+
+    //列出此列当中的表格选中状态
+    for (var i = MinY; i <= MaxY; i++) {
+
+      for (var j = MinX; j <= MaxX; j++) {
+
+        var SelectTR = $('#' + box_id + ' table tbody tr ').eq(i);
+        var td_class = $("td", SelectTR).eq(j).attr('class');
+
+        if (td_class == Selected) {
+          //表格里存在已选中的元素
+          Selected_true = 1;
+        }else{
+          //表格里存在未选中的元素
+          Selected_false = 1;
+        }
+
+      }
+
+    }
+
+    //执行选中或去掉选中方法
+    for (var i = MinY; i <= MaxY; i++) {
+
+      for (var j = MinX; j <= MaxX; j++) {
+
+        var SelectTR = $('#' + box_id + ' table tbody tr ').eq(i);
+        var td_class = $("td", SelectTR).eq(j).attr('class');
+
+        //一列当中存在已选中与未选中的表格处理:整列全部选中
+        if (Selected_true == 1 && Selected_false == 1) {
+          $("td", SelectTR).eq(j).attr("class", Selected);
+        }else if(Selected_false == 1){
+          //一列当中只存在未选中的表格处理:整列全部选中
+          $("td", SelectTR).eq(j).attr("class", Selected);
+        }else{
+          //一列当中只存在已选中的表格处理:整列全部去掉选中
+          $("td", SelectTR).eq(j).removeClass(Selected);
+        }
+
+      }
+
+    }
+    //改变二进制值
+    get_time_val();
+    //改变日期显示
+    convert_date();
+  }
+
+  //获取选中范围的开始与结束的坐标
+  function get_coordinate(StartIndex, EndIndex){
+    var MinX = null;
+    var MaxX = null;
+    var MinY = null;
+    var MaxY = null;
+
+    if (StartIndex.x < EndIndex.x) {
+      MinX = StartIndex.x; MaxX = EndIndex.x;
+    }else {
+      MinX = EndIndex.x; MaxX = StartIndex.x;
+    }
+    if (StartIndex.y < EndIndex.y) {
+      MinY = StartIndex.y; MaxY = EndIndex.y;
+    } else {
+      MinY = EndIndex.y; MaxY = StartIndex.y;
+    }
+    return [MinX, MaxX, MinY, MaxY];
+  }
+
+  //改变二进制值
+  function get_time_val(){
+    var time_type = '';
+    $('#' + box_id + ' table tbody').find('td').each(function(k){
+      var Selected_type = $(this).attr('class');
+      var week = $(this).attr('week');
+
+      if (Selected_type == Selected && !week) {
+        time_type +="1";
+      }else if(!week){
+        time_type +="0";
+      }
+    });
+    $('#'+box_id+'_time_num').val(time_type);
+    // convert_date();
+  }
+  //二进制数转换日期
+  function convert_date(external_binary){
+    //初始化周数数组
+    var time_week_arr = [];
+    if (!external_binary) {
+      //内部调用,进行选中表格和输出时间操作。
+      var binary = $('#'+box_id+'_time_num').val();
+    }else{
+      //存在外部参入传入,此函数进行返回时间操作。
+      var date_html = '';
+      var binary = external_binary;
+    }
+
+    for (var y = 0; y < 7; y++) {
+      //初始化小时数组
+      var time_hour_arr = [];
+
+      for (var x = 0; x < 48; x++) {
+
+        //获取当前点击元素的位置
+        if (y==0) {
+          var index = x;
+        }else{
+          var index = (y*48)+x;
+        }
+        //获取td对应的二进制值
+        var Selected_val = binary.charAt(index);
+
+        if (Selected_val ==1) {
+          //组装保存进数组里
+          if (time_hour_arr == []) {
+            //表格的第一个位置的值
+            time_hour_arr = arr_hour[x];
+          }else if(binary.charAt(index-1) == 1 && binary.charAt(index-2) == 1 ){
+            //此位置(包含上一行)的前两个都为选中时
+
+            if (x==0 && binary.charAt(index+1) == 0) {
+              //选中行里第一个,后一个表格没选中,加逗号
+              time_hour_arr[time_hour_arr.length] = arr_hour[x] + ', ';
+            }else if(x==0 && binary.charAt(index+1) == 1){
+              //选中行里第一个,后一个表格已选中,不加逗号
+              time_hour_arr[time_hour_arr.length] = arr_hour[x];
+            }else if(x==1 && binary.charAt(index-1) == 0){
+              //选中行里第二个,上一个表格没选中,加逗号
+              time_hour_arr[time_hour_arr.length] = arr_hour[x] +', ';
+            }else if(x==1 && binary.charAt(index-1) == 1){
+              //选中行里第二个,上一个表格已选中,前加-号,后加逗号
+              time_hour_arr[time_hour_arr.length] = '-' + arr_hour[x] +', ';
+            }else{
+              //选中行里除第一、二的表格以外,前一个表格已经选中,此元素前加- 后加逗号
+              time_hour_arr[time_hour_arr.length-1] = '-' + arr_hour[x] +', ';
+            }
+
+          }else if(binary.charAt(index-1) == 1 && x>0){
+            //选中的前一个已选中,且此次选中的不是行里第一个,此次选中的元素前加-后加逗号
+            time_hour_arr[time_hour_arr.length] = '-' + arr_hour[x] + ', ';
+          }else if(binary.charAt(index+1) != 1 || x==47){
+            //选中的后一个没选中,或者此次选中的是行里最后一个,此次选中的元素加逗号
+            time_hour_arr[time_hour_arr.length] = arr_hour[x] + ', ';
+          }else{
+            //选中的后一已选中,此次选中的元素不加逗号
+            time_hour_arr[time_hour_arr.length] = arr_hour[x] ;
+          }
+        }
+      }
+
+      time_week_arr[y] = time_hour_arr;
+
+    }
+// console.info(box_id);
+    if (!external_binary) {
+      $('#'+box_id+'_time_seled').html('');
+    }
+    //再次组装并输出数组
+    var time_html = [];
+    for(var y = 0; y < 7; y++){
+
+      for(var x = 0; x < time_week_arr[y].length; x++){
+
+        if (!time_html[y]) {
+          time_html[y] = time_week_arr[y][x];
+        }else{
+          time_html[y] += time_week_arr[y][x];
+        }
+
+      }
+
+      if (time_html[y]) {
+        time_html[y]=  time_html[y].substring(0,time_html[y].length-2);
+
+        if (!external_binary) {
+          $('#'+box_id+'_time_seled').append('<div>星期'+num [y] + ' (' +time_html[y] + ')' + '</div>');
+        }else{
+          date_html += '星期'+num [y] + ' (' +time_html[y] + ')' + ', ';
+        }
+      }
+    }
+
+    if (external_binary) {
+      return date_html;
+    }
+    // console.info(time_html);
+  }
+
+  //生成时间值数组
+  function get_hour_arr(){
+    var arr_hour = [];
+    var oDate = new Date("2016/07/01 00:00:00"); //实例一个时间对象;
+    var oDate_hour = oDate.getHours();
+    var oDate_minute = oDate.getMinutes();
+    for(var i=0; i<48; i++){
+      if(oDate_minute<10){
+        var oDate_minute = "0"+oDate_minute;
+      }
+      if (i >=1) {
+        oDate.setMinutes(oDate.getMinutes() + 30);
+        oDate_hour = oDate.getHours();
+        oDate_minute = oDate.getMinutes();
+        if(oDate_minute<10){
+          var oDate_minute = "0"+oDate_minute;
+        }
+      }
+      arr_hour[i] = oDate_hour + ':' + oDate_minute;
+      // alert(oDate_hour + ':' + oDate.getMinutes());
+    }
+    return arr_hour;
+  }
+
+  //更新操作
+  function renewal(id){
+    if (id) {
+      box_id = id;
+    }
+    //解绑鼠标移动监听事件
+    $('#' + box_id + ' table tbody tr td').unbind("mouseover");
+    //初始化表格的在此次选中状态
+    $('#' + box_id + ' table tbody tr td').attr("td_state", '');
+    //改变二进制值
+    get_time_val();
+    //改变日期显示
+    convert_date();
+  }
+
+  //二进制数赋值选中表格
+  function binary_selected(){
+    var default_time_val = $('#'+box_id+' .default_time_val').val();
+    if (default_time_val) {
+      for(i=0 ; i<336; i++){
+        var td_selected = default_time_val.charAt(i);
+        if (td_selected != 0 ) {
+          $('#' + box_id + ' table tbody tr td').eq(i).attr('class','Selected');
+          //更新操作,显示文字形日期
+          renewal();
+        }
+
+      }
+    }
+  }
+
+
+  //实例化程序
+  function load_time_table(id){
+    //包住table的元素id
+    box_id = id;
+    var html;
+    html = '<table cellspacing="0" cellpadding="0" border="0" class="plug-timer-grid"  onselectstart="return false" onselect="document.selection.empty()">';
+    html += '<thead>';
+    html += '<tr>';
+    html += '<th></th>';
+    html += '<th colSpan="24">上午</th>';
+    html += '<th colSpan="24">下午</th>';
+    html += '</tr>';
+    html += '<tr class="hour">';
+    html += '<th></th>';
+    html += '</tr>';
+    html += '</thead>';
+    html += '<tbody></tbody>';
+    html += '</table>';
+    html += '<input class="focus" style="opacity: 0;">';
+    html += '<div id="'+box_id+'_time_seled"></div>';
+    html += '<input v-model="dateQuantumRange" type="hidden" id="'+box_id+'_time_num" name="time" caption="每日投放时段" switchname="selectTime"  value="">';
+    $('#'+box_id).append(html);
+    var html_tbody_td = '';
+    var html_thead_td = '';
+
+    //创建表格
+    for (var i = 0; i < 7; i++) {
+      var week = i+1;
+      html_tbody_td += '<tr>';
+      for (var j = 0; j < 49; j++){
+        if (j==0) {
+          html_tbody_td += '<th week="'+week+'">周' + num[i] +  '</th>';
+        }else{
+          html_tbody_td += '<td>'  +  '</td>';
+        }
+      }
+      html_tbody_td += '</tr>';
+    }
+
+    //创建表格小时栏目
+    for(var i =0; i<= 23; i++){
+      html_thead_td += '<td colSpan="2" hour="'+i+'">'+ i + '</td>';
+    }
+    $('#' + box_id + ' table thead .hour').append(html_thead_td);
+    $('#' + box_id + ' table tbody').html(html_tbody_td);
+
+    //检查是否有赋有二进制值,如有,将选中相应的表格
+    binary_selected();
+
+    //控制器,控制当前在哪个表格进行操作
+    $('.plug-timer-grid').hover(function (e) {
+      if(1 != e.which){    //判断是否为左击
+        var id = $(this).parent().attr('id');
+        box_id = id;
+      }
+    });
+
+    //清除所有选中项
+    $('.clear').click(function(){
+      $(this).parent().find('td').removeClass(Selected);
+      var id =$(this).parent().attr('id');
+      renewal(id);
+    });
+
+    //点击小时选中或去掉整列处理块
+    $('#' + box_id + ' table thead tr td').click(function(){
+      hour = $(this).attr('hour');
+      if (hour>=0) {
+        var rows = $('#' + box_id + ' table tbody tr').length;
+        Start_x = ($(this).index())*2-1;
+        Start_y = 0;
+
+        StartIndex = { x: Start_x, y: Start_y };
+
+        EndTD = $(this);
+        var x = ($(this).index())*2-2;
+        var y = rows -1;    //为了配合for计算公式-1
+
+        EndIndex = { x: x, y: y };
+        //改变第一次按下鼠标时候的改变选中状态
+        SelectTD_click(StartIndex, EndIndex, Selected);
+      }
+    });
+
+    //点击星期选中或去掉整行处理块
+    $('#' + box_id + ' table tbody tr th').click(function(){
+      var week = $(this).attr('week');
+      if (week>=0) {
+        var line = $('#' + box_id + ' table tbody tr td').length/$('#' + box_id + ' table tbody tr').length;
+
+        Start_x = 0;
+        Start_y = $(this).parent().index();
+
+        StartIndex = { x: Start_x, y: Start_y };
+
+        EndTD = $(this);
+        var y = $(this).parent().index();
+        var x = line-1;     //为了配合for计算公式-1
+
+        EndIndex = { x: x, y: y };
+
+        //改变第一次按下鼠标时候的改变选中状态
+        SelectTD_click(StartIndex, EndIndex, Selected);
+      }
+    });
+
+    //监听鼠标按下事件(鼠标按下左键拖动选中处理块)
+    $('#' + box_id + ' table tbody tr td').unbind("mousedown").bind("mousedown", function () {
+      //记录刚开始点击的元素位置
+      Start_x = $(this).index()-1;
+      Start_y = $(this).parent().index();
+      StartIndex = { x: Start_x, y: Start_y };
+
+      EndTD = $(this);
+      var x = $(this).index()-1;
+      var y = $(this).parent().index();
+      EndIndex = { x: x, y: y };
+      //改变第一次按下鼠标时候的改变选中状态
+      SelectTD(StartIndex, EndIndex, Selected);
+
+      StartTD = $(this);
+
+      StartIndex = { x: Start_x, y: Start_y };
+
+      //监听鼠标移动事件,实现改变后续鼠标拖拽时候的表格选中状态
+      $('#' + box_id + ' table tbody tr td').mouseover(function(e){
+        EndTD = $(this);
+        var x = $(this).index()-1;
+        var y = $(this).parent().index();
+        EndIndex = { x: x, y: y };
+        if(1 != e.which){    //判断是否为左击
+          $('#' + box_id + ' table tbody tr td').unbind("mouseover");
+        }
+        //去除停留在td上的光标
+        $('#' + box_id + ' .focus').focus();
+        SelectTD(StartIndex, EndIndex, Selected);
+      });
+
+
+      //放开鼠标左键时,初始化相关参数和解绑相关监听
+      $('html').unbind("mouseup").bind("mouseup", function () {
+        renewal();
+      });
+
+    });
+
+  }
+
+  /*外部调用接口*/
+
+  //解绑鼠标松开监听事件
+  function unbundle_mouseover(){
+    $('html').unbind("mouseup");
+  }
+
+  /*二进制获取转换后的时间*/
+  function get_time_html(binary){
+    return convert_date(binary);
+  }
+
+  $(function(){
+    load_time_table('table_time_selected1');
+  });
+
+</script>
+<style type="text/css">
+  .plug-timer-grid{width: 80%;}
+  .plug-timer-grid td, .plug-timer-grid th{border: 1px solid #97B4D1;text-align: center; /*cursor:pointer;*/}
+  .Selected{background-color: rgb(102,162,243);opacity: 0.5;}
+
+  .plug-timer-grid {
+    border-collapse: collapse;
+    z-index: 4;
+  }
+  .plug-timer-grid thead tr{
+    display: table-row;
+    vertical-align: inherit;
+    border-color: inherit;
+  }
+
+  table td{
+    height: 30px;
+    max-width: 5px;
+    border: 1px solid #dfe6ec;
+    font-size: 12px;
+    text-align: center;
+    vertical-align: middle;
+    overflow: hidden;
+    transition: background .5s;
+    -webkit-transition: background .5s;
+  }
+
+  .plug-timer-grid tbody th{
+    width: 4%;
+  }
+  .plug-timer-grid tbody tr td{
+    width: 2%;
+  }
+  .clear{
+    margin:20px 0px 20px 0px;
+  }
+</style>

+ 244 - 0
src/views/template/budget/list.vue

@@ -0,0 +1,244 @@
+<template>
+  <a-card :bordered="false">
+
+    <!-- 查询区域 -->
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline">
+        <a-row :gutter="24">
+
+          <a-col :md="6" :sm="8">
+            <a-form-item label="广告主id">
+              <a-input placeholder="请输入广告主id" v-model="queryParam.advertiserId"></a-input>
+            </a-form-item>
+          </a-col>
+          <a-col :md="6" :sm="8">
+            <a-form-item label="头条账号id">
+              <a-input placeholder="请输入头条账号id" v-model="queryParam.toutiaoId"></a-input>
+            </a-form-item>
+          </a-col>
+          <template v-if="toggleSearchStatus">
+            <a-col :md="6" :sm="8">
+              <a-form-item label="bidType">
+                <a-input placeholder="请输入bidType" v-model="queryParam.bidType"></a-input>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="8">
+              <a-form-item label="flowControlMode">
+                <a-input placeholder="请输入flowControlMode"
+                         v-model="queryParam.flowControlMode"></a-input>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="8">
+              <a-form-item label="budgetPrice">
+                <a-input placeholder="请输入budgetPrice" v-model="queryParam.budgetPrice"></a-input>
+              </a-form-item>
+            </a-col>
+          </template>
+          <a-col :md="6" :sm="8">
+            <span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
+              <a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
+              <a-button type="primary" @click="searchReset" icon="reload" style="margin-left: 8px">重置</a-button>
+              <a @click="handleToggleSearch" style="margin-left: 8px">
+                {{ toggleSearchStatus ? '收起' : '展开' }}
+                <a-icon :type="toggleSearchStatus ? 'up' : 'down'"/>
+              </a>
+            </span>
+          </a-col>
+
+        </a-row>
+      </a-form>
+    </div>
+
+    <!-- 操作按钮区域 -->
+    <div class="table-operator">
+      <a-button @click="handleAdd" type="primary" icon="plus">新增</a-button>
+      <a-button type="primary" icon="download" @click="handleExportXls('今日头条预算模板信息')">导出</a-button>
+      <a-upload name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader"
+                :action="importExcelUrl" @change="handleImportExcel">
+        <a-button type="primary" icon="import">导入</a-button>
+      </a-upload>
+      <a-dropdown v-if="selectedRowKeys.length > 0">
+        <a-menu slot="overlay">
+          <a-menu-item key="1" @click="batchDel">
+            <a-icon type="delete"/>
+            删除
+          </a-menu-item>
+        </a-menu>
+        <a-button style="margin-left: 8px"> 批量操作
+          <a-icon type="down"/>
+        </a-button>
+      </a-dropdown>
+    </div>
+
+    <!-- table区域-begin -->
+    <div>
+      <div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
+        <i class="anticon anticon-info-circle ant-alert-icon"></i> 已选择 <a style="font-weight: 600">{{
+        selectedRowKeys.length }}</a>项
+        <a style="margin-left: 24px" @click="onClearSelected">清空</a>
+      </div>
+
+      <a-table
+        ref="table"
+        size="middle"
+        bordered
+        rowKey="id"
+        :columns="columns"
+        :dataSource="dataSource"
+        :pagination="ipagination"
+        :loading="loading"
+        :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
+        @change="handleTableChange">
+
+        <span slot="action" slot-scope="text, record">
+          <a @click="handleEdit(record)">编辑</a>
+
+          <a-divider type="vertical"/>
+          <a-dropdown>
+            <a class="ant-dropdown-link">更多 <a-icon type="down"/></a>
+            <a-menu slot="overlay">
+              <a-menu-item>
+                <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
+                  <a>删除</a>
+                </a-popconfirm>
+              </a-menu-item>
+            </a-menu>
+          </a-dropdown>
+        </span>
+
+      </a-table>
+    </div>
+    <!-- table区域-end -->
+
+    <!-- 表单区域 -->
+    <byteDanceBudgetTemplate-modal ref="modalForm" @ok="modalFormOk"></byteDanceBudgetTemplate-modal>
+  </a-card>
+</template>
+
+<script>
+  import ByteDanceBudgetTemplateModal from './modules/ByteDanceBudgetTemplateModal'
+  import {JeecgListMixin} from '@/mixins/JeecgListMixin'
+
+  export default {
+    name: "ByteDanceBudgetTemplateList",
+    mixins: [JeecgListMixin],
+    components: {
+      ByteDanceBudgetTemplateModal
+    },
+    data() {
+      return {
+        description: '今日头条预算模板信息管理页面',
+        // 表头
+        columns: [
+          {
+            title: '#',
+            dataIndex: '',
+            key: 'rowIndex',
+            width: 60,
+            align: "center",
+            customRender: function (t, r, index) {
+              return parseInt(index) + 1;
+            }
+          },
+          {
+            title: '广告主id',
+            align: "center",
+            dataIndex: 'advertiserId'
+          },
+          {
+            title: '头条账号id',
+            align: "center",
+            dataIndex: 'toutiaoId'
+          },
+          {
+            title: '出价方式',
+            align: "center",
+            dataIndex: 'bidType'
+          },
+          {
+            title: '投放方式',
+            align: "center",
+            dataIndex: 'flowControlMode'
+          },
+          {
+            title: '预算价格',
+            align: "center",
+            dataIndex: 'budgetPrice'
+          },
+          {
+            title: '预算类型',
+            align: "center",
+            dataIndex: 'budgetPriceMode'
+          },
+          {
+            title: '投放时间模式',
+            align: "center",
+            dataIndex: 'flowDateType'
+          },
+          {
+            title: '开始时间',
+            align: "center",
+            dataIndex: 'startDate'
+          },
+          {
+            title: '结束时间',
+            align: "center",
+            dataIndex: 'endDate'
+          },
+          {
+            title: '投放时间段方式',
+            align: "center",
+            dataIndex: 'dateQuantum'
+          },
+          {
+            title: '投放时间段',
+            align: "center",
+            dataIndex: 'dateQuantumRange'
+          },
+          {
+            title: '付费方式',
+            align: "center",
+            dataIndex: 'priceType'
+          },
+          {
+            title: '目标转化出价',
+            align: "center",
+            dataIndex: 'convertPrice'
+          },
+          {
+            title: '过滤已转化用户',
+            align: "center",
+            dataIndex: 'filterType'
+          },
+          {
+            title: '状态',
+            align: "center",
+            dataIndex: 'status'
+          },
+          {
+            title: '操作',
+            dataIndex: 'action',
+            align: "center",
+            scopedSlots: {customRender: 'action'},
+          }
+        ],
+        url: {
+          list: "/ctop/byteDanceBudgetTemplate/list",
+          delete: "/ctop/byteDanceBudgetTemplate/delete",
+          deleteBatch: "/ctop/byteDanceBudgetTemplate/deleteBatch",
+          exportXlsUrl: "ctop/byteDanceBudgetTemplate/exportXls",
+          importExcelUrl: "ctop/byteDanceBudgetTemplate/importExcel",
+        },
+      }
+    },
+    computed: {
+      importExcelUrl: function () {
+        return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;
+      }
+    },
+    methods: {}
+  }
+</script>
+<style scoped>
+  @import '~@assets/less/common.less'
+</style>

+ 209 - 0
src/views/template/budget/modules/ByteDanceBudgetTemplateModal.vue

@@ -0,0 +1,209 @@
+<template>
+    <a-modal
+            :title="title"
+            :width="800"
+            :visible="visible"
+            :confirmLoading="confirmLoading"
+            @ok="handleOk"
+            @cancel="handleCancel"
+            cancelText="关闭">
+
+        <a-spin :spinning="confirmLoading">
+            <a-form :form="form">
+
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="广告主id">
+                    <a-input placeholder="请输入广告主id" v-decorator="['advertiserId', validatorRules.advertiserId ]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="头条账号id">
+                    <a-input placeholder="请输入头条账号id" v-decorator="['toutiaoId', validatorRules.toutiaoId ]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="bidType">
+                    <a-input placeholder="请输入bidType" v-decorator="['bidType', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="flowControlMode">
+                    <a-input placeholder="请输入flowControlMode" v-decorator="['flowControlMode', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="budgetPrice">
+                    <a-input placeholder="请输入budgetPrice" v-decorator="['budgetPrice', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="budgetPriceMode">
+                    <a-input placeholder="请输入budgetPriceMode" v-decorator="['budgetPriceMode', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="flowDateType">
+                    <a-input placeholder="请输入flowDateType" v-decorator="['flowDateType', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="startDate">
+                    <a-input placeholder="请输入startDate" v-decorator="['startDate', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="endDate">
+                    <a-input placeholder="请输入endDate" v-decorator="['endDate', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="dateQuantum">
+                    <a-input placeholder="请输入dateQuantum" v-decorator="['dateQuantum', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="dateQuantumRange">
+                    <a-input placeholder="请输入dateQuantumRange" v-decorator="['dateQuantumRange', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="priceType">
+                    <a-input placeholder="请输入priceType" v-decorator="['priceType', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="convertPrice">
+                    <a-input placeholder="请输入convertPrice" v-decorator="['convertPrice', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="filterType">
+                    <a-input placeholder="请输入filterType" v-decorator="['filterType', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="status">
+                    <a-input-number v-decorator="[ 'status', {}]"/>
+                </a-form-item>
+
+            </a-form>
+        </a-spin>
+    </a-modal>
+</template>
+
+<script>
+    import {httpAction} from '@/api/manage'
+    import pick from 'lodash.pick'
+    import moment from "moment"
+
+    export default {
+        name: "ByteDanceBudgetTemplateModal",
+        data() {
+            return {
+                title: "操作",
+                visible: false,
+                model: {},
+                labelCol: {
+                    xs: {span: 24},
+                    sm: {span: 5},
+                },
+                wrapperCol: {
+                    xs: {span: 24},
+                    sm: {span: 16},
+                },
+
+                confirmLoading: false,
+                form: this.$form.createForm(this),
+                validatorRules: {
+                    advertiserId: {rules: [{required: true, message: '请输入广告主id!'}]},
+                    toutiaoId: {rules: [{required: true, message: '请输入头条账号id!'}]},
+                },
+                url: {
+                    add: "/ctop/byteDanceBudgetTemplate/add",
+                    edit: "/ctop/byteDanceBudgetTemplate/edit",
+                },
+            }
+        },
+        created() {
+        },
+        methods: {
+            add() {
+                this.edit({});
+            },
+            edit(record) {
+                this.form.resetFields();
+                this.model = Object.assign({}, record);
+                this.visible = true;
+                this.$nextTick(() => {
+                    this.form.setFieldsValue(pick(this.model, 'advertiserId', 'toutiaoId', 'bidType', 'flowControlMode', 'budgetPrice', 'budgetPriceMode', 'flowDateType', 'startDate', 'endDate', 'dateQuantum', 'dateQuantumRange', 'priceType', 'convertPrice', 'filterType', 'status'))
+                    //时间格式化
+                });
+
+            },
+            close() {
+                this.$emit('close');
+                this.visible = false;
+            },
+            handleOk() {
+                const that = this;
+                // 触发表单验证
+                this.form.validateFields((err, values) => {
+                    if (!err) {
+                        that.confirmLoading = true;
+                        let httpurl = '';
+                        let method = '';
+                        if (!this.model.id) {
+                            httpurl += this.url.add;
+                            method = 'post';
+                        } else {
+                            httpurl += this.url.edit;
+                            method = 'put';
+                        }
+                        let formData = Object.assign(this.model, values);
+                        //时间格式化
+
+                        console.log(formData)
+                        httpAction(httpurl, formData, method).then((res) => {
+                            if (res.success) {
+                                that.$message.success(res.message);
+                                that.$emit('ok');
+                            } else {
+                                that.$message.warning(res.message);
+                            }
+                        }).finally(() => {
+                            that.confirmLoading = false;
+                            that.close();
+                        })
+
+
+                    }
+                })
+            },
+            handleCancel() {
+                this.close()
+            },
+
+
+        }
+    }
+</script>
+
+<style lang="less" scoped>
+
+</style>

+ 216 - 0
src/views/template/budget/modules/ByteDanceBudgetTemplateModal__Style#Drawer.vue

@@ -0,0 +1,216 @@
+<template>
+    <a-drawer
+            :title="title"
+            :width="800"
+            placement="right"
+            :closable="false"
+            @close="close"
+            :visible="visible"
+    >
+
+        <a-spin :spinning="confirmLoading">
+            <a-form :form="form">
+
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="广告主id">
+                    <a-input placeholder="请输入广告主id" v-decorator="['advertiserId', validatorRules.advertiserId ]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="头条账号id">
+                    <a-input placeholder="请输入头条账号id" v-decorator="['toutiaoId', validatorRules.toutiaoId ]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="bidType">
+                    <a-input placeholder="请输入bidType" v-decorator="['bidType', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="flowControlMode">
+                    <a-input placeholder="请输入flowControlMode" v-decorator="['flowControlMode', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="budgetPrice">
+                    <a-input placeholder="请输入budgetPrice" v-decorator="['budgetPrice', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="budgetPriceMode">
+                    <a-input placeholder="请输入budgetPriceMode" v-decorator="['budgetPriceMode', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="flowDateType">
+                    <a-input placeholder="请输入flowDateType" v-decorator="['flowDateType', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="startDate">
+                    <a-input placeholder="请输入startDate" v-decorator="['startDate', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="endDate">
+                    <a-input placeholder="请输入endDate" v-decorator="['endDate', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="dateQuantum">
+                    <a-input placeholder="请输入dateQuantum" v-decorator="['dateQuantum', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="dateQuantumRange">
+                    <a-input placeholder="请输入dateQuantumRange" v-decorator="['dateQuantumRange', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="priceType">
+                    <a-input placeholder="请输入priceType" v-decorator="['priceType', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="convertPrice">
+                    <a-input placeholder="请输入convertPrice" v-decorator="['convertPrice', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="filterType">
+                    <a-input placeholder="请输入filterType" v-decorator="['filterType', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="status">
+                    <a-input-number v-decorator="[ 'status', {}]"/>
+                </a-form-item>
+
+            </a-form>
+        </a-spin>
+        <a-button type="primary" @click="handleOk">确定</a-button>
+        <a-button type="primary" @click="handleCancel">取消</a-button>
+    </a-drawer>
+</template>
+
+<script>
+    import {httpAction} from '@/api/manage'
+    import pick from 'lodash.pick'
+    import moment from "moment"
+
+    export default {
+        name: "ByteDanceBudgetTemplateModal",
+        data() {
+            return {
+                title: "操作",
+                visible: false,
+                model: {},
+                labelCol: {
+                    xs: {span: 24},
+                    sm: {span: 5},
+                },
+                wrapperCol: {
+                    xs: {span: 24},
+                    sm: {span: 16},
+                },
+
+                confirmLoading: false,
+                form: this.$form.createForm(this),
+                validatorRules: {
+                    advertiserId: {rules: [{required: true, message: '请输入广告主id!'}]},
+                    toutiaoId: {rules: [{required: true, message: '请输入头条账号id!'}]},
+                },
+                url: {
+                    add: "/ctop/byteDanceBudgetTemplate/add",
+                    edit: "/ctop/byteDanceBudgetTemplate/edit",
+                },
+            }
+        },
+        created() {
+        },
+        methods: {
+            add() {
+                this.edit({});
+            },
+            edit(record) {
+                this.form.resetFields();
+                this.model = Object.assign({}, record);
+                this.visible = true;
+                this.$nextTick(() => {
+                    this.form.setFieldsValue(pick(this.model, 'advertiserId', 'toutiaoId', 'bidType', 'flowControlMode', 'budgetPrice', 'budgetPriceMode', 'flowDateType', 'startDate', 'endDate', 'dateQuantum', 'dateQuantumRange', 'priceType', 'convertPrice', 'filterType', 'status'))
+                    //时间格式化
+                });
+
+            },
+            close() {
+                this.$emit('close');
+                this.visible = false;
+            },
+            handleOk() {
+                const that = this;
+                // 触发表单验证
+                this.form.validateFields((err, values) => {
+                    if (!err) {
+                        that.confirmLoading = true;
+                        let httpurl = '';
+                        let method = '';
+                        if (!this.model.id) {
+                            httpurl += this.url.add;
+                            method = 'post';
+                        } else {
+                            httpurl += this.url.edit;
+                            method = 'put';
+                        }
+                        let formData = Object.assign(this.model, values);
+                        //时间格式化
+
+                        console.log(formData)
+                        httpAction(httpurl, formData, method).then((res) => {
+                            if (res.success) {
+                                that.$message.success(res.message);
+                                that.$emit('ok');
+                            } else {
+                                that.$message.warning(res.message);
+                            }
+                        }).finally(() => {
+                            that.confirmLoading = false;
+                            that.close();
+                        })
+
+
+                    }
+                })
+            },
+            handleCancel() {
+                this.close()
+            },
+
+
+        }
+    }
+</script>
+
+<style lang="less" scoped>
+    /** Button按钮间距 */
+    .ant-btn {
+        margin-left: 30px;
+        margin-bottom: 30px;
+        float: right;
+    }
+</style>

+ 118 - 0
src/views/template/campaign/create.vue

@@ -0,0 +1,118 @@
+<template>
+  <a-card :body-style="{padding: '24px 32px'}" :bordered="false">
+    <a-form @submit="handleSubmit" :form="form">
+      <a-form-item
+        label="推广目的"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+        <a-radio-group @change="promotionPurposeChange" v-model="promotionPurpose">
+          <a-radio-button v-for="purpose in promotionPurposeList" :key="purpose.itemText" :value="purpose.itemValue">
+            {{purpose.itemText}}
+          </a-radio-button>
+        </a-radio-group>
+      </a-form-item>
+
+      <a-form-item
+        label="广告组预算"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+        <a-radio-group @change="showBudgetStatusChange" v-model="campaignBudget">
+          <a-radio-button value="UNLIMITED">不限</a-radio-button>
+          <a-radio-button value="AS_BUDGET">按预算</a-radio-button>
+        </a-radio-group>
+      </a-form-item>
+      <a-form-item
+        label="日预算"
+        v-if="showBudgetDaily"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+        <a-input v-model="budgetDaily" style="width: 70%"></a-input>元
+      </a-form-item>
+
+      <a-form-item
+        label="广告组名称"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+          <a-input v-model="campaignName"></a-input>
+      </a-form-item>
+
+      <a-form-item
+        :wrapperCol="{ span: 24 }"
+        style="text-align: center"
+      >
+        <a-button htmlType="submit" type="primary">提交</a-button>
+        <a-button style="margin-left: 8px">保存</a-button>
+      </a-form-item>
+    </a-form>
+  </a-card>
+</template>
+
+<script>
+  import {deleteAction, postAction, getAction} from '@/api/manage'
+  import moment from "moment"
+  export default {
+    name: 'BaseForm',
+    data() {
+      return {
+        promotionPurpose:'APP',
+        promotionPurposeList: {},
+        showBudgetDaily:false,
+        campaignName:'APP_'+moment(new Date()),
+        campaignBudget:'UNLIMITED',
+        budgetDaily:0,
+        form: this.$form.createForm(this),
+        url: {
+          dictListUrl: 'toutiao/dictitem/list',
+          insertTemplateUrl:'toutiao/campaign/template/insert'
+        }
+      }
+    },
+    methods: {
+      handleSubmit(e) {
+        e.preventDefault()
+        this.form.validateFields((err, values) => {
+          if (!err) {
+            console.log('Received values of form: ', values);
+            let params = {};
+            params.promotionPurpose = this.promotionPurpose;
+            params.campaignBudget = this.campaignBudget;
+            params.budgetDaily = this.budgetDaily;
+            params.campaignName = this.campaignName;
+            console.log(params)
+            postAction(this.url.insertTemplateUrl,params).then((res)=>{
+              console.log(res)
+              if(res.success){
+                alert("广告组模板创建成功");
+              }
+            });
+          }
+        })
+      },
+      onChange(value) {
+        console.log(value);
+      },
+      showBudgetStatusChange(){
+        if(this.campaignBudget == 'UNLIMITED'){
+          this.showBudgetDaily = false;
+        }else{
+          this.showBudgetDaily = true;
+        }
+      },
+      promotionPurposeChange(){
+        this.campaignName = this.promotionPurpose +'_'+moment(new Date());
+      }
+    },
+    created: function () {
+      //出价方式
+      let params = {};
+      params.dictId = '181afbae847dd3bc7e27795d89538c9c';
+      params.pageSize = '1000';
+      getAction(this.url.dictListUrl, params).then((res) => {
+        if (res.success) {
+          this.promotionPurposeList = res.result.records
+        }
+      });
+
+    }
+  }
+</script>

+ 198 - 0
src/views/template/campaign/list.vue

@@ -0,0 +1,198 @@
+<template>
+  <a-card :bordered="false">
+
+    <!-- 查询区域 -->
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline">
+        <a-row :gutter="24">
+
+          <a-col :md="6" :sm="8">
+            <a-form-item label="accountId">
+              <a-input placeholder="请输入accountId" v-model="queryParam.accountId"></a-input>
+            </a-form-item>
+          </a-col>
+          <a-col :md="6" :sm="8">
+            <a-form-item label="投放目标">
+              <a-input placeholder="请输入投放目标" v-model="queryParam.promotionPurpuse"></a-input>
+            </a-form-item>
+          </a-col>
+          <template v-if="toggleSearchStatus">
+            <a-col :md="6" :sm="8">
+              <a-form-item label="投放方式">
+                <a-input placeholder="请输入投放方式" v-model="queryParam.campaignBudget"></a-input>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="8">
+              <a-form-item label="日预算">
+                <a-input placeholder="请输入日预算" v-model="queryParam.budgetDaily"></a-input>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="8">
+              <a-form-item label="广告组名称">
+                <a-input placeholder="请输入广告组名称" v-model="queryParam.campaignName"></a-input>
+              </a-form-item>
+            </a-col>
+          </template>
+          <a-col :md="6" :sm="8">
+            <span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
+              <a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
+              <a-button type="primary" @click="searchReset" icon="reload" style="margin-left: 8px">重置</a-button>
+              <a @click="handleToggleSearch" style="margin-left: 8px">
+                {{ toggleSearchStatus ? '收起' : '展开' }}
+                <a-icon :type="toggleSearchStatus ? 'up' : 'down'"/>
+              </a>
+            </span>
+          </a-col>
+
+        </a-row>
+      </a-form>
+    </div>
+
+    <!-- 操作按钮区域 -->
+    <div class="table-operator">
+      <a-button @click="handleAdd" type="primary" icon="plus">新增</a-button>
+      <a-button type="primary" icon="download" @click="handleExportXls('今日头条广告组模板信息')">导出</a-button>
+      <a-upload name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader"
+                :action="importExcelUrl" @change="handleImportExcel">
+        <a-button type="primary" icon="import">导入</a-button>
+      </a-upload>
+      <a-dropdown v-if="selectedRowKeys.length > 0">
+        <a-menu slot="overlay">
+          <a-menu-item key="1" @click="batchDel">
+            <a-icon type="delete"/>
+            删除
+          </a-menu-item>
+        </a-menu>
+        <a-button style="margin-left: 8px"> 批量操作
+          <a-icon type="down"/>
+        </a-button>
+      </a-dropdown>
+    </div>
+
+    <!-- table区域-begin -->
+    <div>
+      <div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
+        <i class="anticon anticon-info-circle ant-alert-icon"></i> 已选择 <a style="font-weight: 600">{{
+        selectedRowKeys.length }}</a>项
+        <a style="margin-left: 24px" @click="onClearSelected">清空</a>
+      </div>
+
+      <a-table
+        ref="table"
+        size="middle"
+        bordered
+        rowKey="id"
+        :columns="columns"
+        :dataSource="dataSource"
+        :pagination="ipagination"
+        :loading="loading"
+        :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
+        @change="handleTableChange">
+
+        <span slot="action" slot-scope="text, record">
+          <a @click="handleEdit(record)">编辑</a>
+
+          <a-divider type="vertical"/>
+          <a-dropdown>
+            <a class="ant-dropdown-link">更多 <a-icon type="down"/></a>
+            <a-menu slot="overlay">
+              <a-menu-item>
+                <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
+                  <a>删除</a>
+                </a-popconfirm>
+              </a-menu-item>
+            </a-menu>
+          </a-dropdown>
+        </span>
+
+      </a-table>
+    </div>
+    <!-- table区域-end -->
+
+    <!-- 表单区域 -->
+    <byteDanceCampaignTemplate-modal ref="modalForm" @ok="modalFormOk"></byteDanceCampaignTemplate-modal>
+  </a-card>
+</template>
+
+<script>
+  import ByteDanceCampaignTemplateModal from './modules/ByteDanceCampaignTemplateModal'
+  import {JeecgListMixin} from '@/mixins/JeecgListMixin'
+
+  export default {
+    name: "ByteDanceCampaignTemplateList",
+    mixins: [JeecgListMixin],
+    components: {
+      ByteDanceCampaignTemplateModal
+    },
+    data() {
+      return {
+        description: '今日头条广告组模板信息管理页面',
+        // 表头
+        columns: [
+          {
+            title: '#',
+            dataIndex: '',
+            key: 'rowIndex',
+            width: 60,
+            align: "center",
+            customRender: function (t, r, index) {
+              return parseInt(index) + 1;
+            }
+          },
+          {
+            title: 'accountId',
+            align: "center",
+            dataIndex: 'accountId'
+          },
+          {
+            title: '投放目标',
+            align: "center",
+            dataIndex: 'promotionPurpuse'
+          },
+          {
+            title: '投放方式',
+            align: "center",
+            dataIndex: 'campaignBudget'
+          },
+          {
+            title: '日预算',
+            align: "center",
+            dataIndex: 'budgetDaily'
+          },
+          {
+            title: '广告组名称',
+            align: "center",
+            dataIndex: 'campaignName'
+          },
+          {
+            title: '模板状态',
+            align: "center",
+            dataIndex: 'status'
+          },
+          {
+            title: '操作',
+            dataIndex: 'action',
+            align: "center",
+            scopedSlots: {customRender: 'action'},
+          }
+        ],
+        url: {
+          list: "/ctop/byteDanceCampaignTemplate/list",
+          delete: "/ctop/byteDanceCampaignTemplate/delete",
+          deleteBatch: "/ctop/byteDanceCampaignTemplate/deleteBatch",
+          exportXlsUrl: "ctop/byteDanceCampaignTemplate/exportXls",
+          importExcelUrl: "ctop/byteDanceCampaignTemplate/importExcel",
+        },
+      }
+    },
+    computed: {
+      importExcelUrl: function () {
+        return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;
+      }
+    },
+    methods: {}
+  }
+</script>
+<style scoped>
+  @import '~@assets/less/common.less'
+</style>

+ 155 - 0
src/views/template/campaign/modules/ByteDanceCampaignTemplateModal.vue

@@ -0,0 +1,155 @@
+<template>
+    <a-modal
+            :title="title"
+            :width="800"
+            :visible="visible"
+            :confirmLoading="confirmLoading"
+            @ok="handleOk"
+            @cancel="handleCancel"
+            cancelText="关闭">
+
+        <a-spin :spinning="confirmLoading">
+            <a-form :form="form">
+
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="accountId">
+                    <a-input placeholder="请输入accountId" v-decorator="['accountId', validatorRules.accountId ]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="投放目标">
+                    <a-input placeholder="请输入投放目标" v-decorator="['promotionPurpuse', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="投放方式">
+                    <a-input placeholder="请输入投放方式" v-decorator="['campaignBudget', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="日预算">
+                    <a-input placeholder="请输入日预算" v-decorator="['budgetDaily', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="广告组名称">
+                    <a-input placeholder="请输入广告组名称" v-decorator="['campaignName', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="模板状态">
+                    <a-input-number v-decorator="[ 'status', validatorRules.status ]"/>
+                </a-form-item>
+
+            </a-form>
+        </a-spin>
+    </a-modal>
+</template>
+
+<script>
+    import {httpAction} from '@/api/manage'
+    import pick from 'lodash.pick'
+    import moment from "moment"
+
+    export default {
+        name: "ByteDanceCampaignTemplateModal",
+        data() {
+            return {
+                title: "操作",
+                visible: false,
+                model: {},
+                labelCol: {
+                    xs: {span: 24},
+                    sm: {span: 5},
+                },
+                wrapperCol: {
+                    xs: {span: 24},
+                    sm: {span: 16},
+                },
+
+                confirmLoading: false,
+                form: this.$form.createForm(this),
+                validatorRules: {
+                    accountId: {rules: [{required: true, message: '请输入accountId!'}]},
+                    status: {rules: [{required: true, message: '请输入模板状态!'}]},
+                },
+                url: {
+                    add: "/ctop/byteDanceCampaignTemplate/add",
+                    edit: "/ctop/byteDanceCampaignTemplate/edit",
+                },
+            }
+        },
+        created() {
+        },
+        methods: {
+            add() {
+                this.edit({});
+            },
+            edit(record) {
+                this.form.resetFields();
+                this.model = Object.assign({}, record);
+                this.visible = true;
+                this.$nextTick(() => {
+                    this.form.setFieldsValue(pick(this.model, 'accountId', 'promotionPurpuse', 'campaignBudget', 'budgetDaily', 'campaignName', 'status'))
+                    //时间格式化
+                });
+
+            },
+            close() {
+                this.$emit('close');
+                this.visible = false;
+            },
+            handleOk() {
+                const that = this;
+                // 触发表单验证
+                this.form.validateFields((err, values) => {
+                    if (!err) {
+                        that.confirmLoading = true;
+                        let httpurl = '';
+                        let method = '';
+                        if (!this.model.id) {
+                            httpurl += this.url.add;
+                            method = 'post';
+                        } else {
+                            httpurl += this.url.edit;
+                            method = 'put';
+                        }
+                        let formData = Object.assign(this.model, values);
+                        //时间格式化
+
+                        console.log(formData)
+                        httpAction(httpurl, formData, method).then((res) => {
+                            if (res.success) {
+                                that.$message.success(res.message);
+                                that.$emit('ok');
+                            } else {
+                                that.$message.warning(res.message);
+                            }
+                        }).finally(() => {
+                            that.confirmLoading = false;
+                            that.close();
+                        })
+
+
+                    }
+                })
+            },
+            handleCancel() {
+                this.close()
+            },
+
+
+        }
+    }
+</script>
+
+<style lang="less" scoped>
+
+</style>

+ 162 - 0
src/views/template/campaign/modules/ByteDanceCampaignTemplateModal__Style#Drawer.vue

@@ -0,0 +1,162 @@
+<template>
+    <a-drawer
+            :title="title"
+            :width="800"
+            placement="right"
+            :closable="false"
+            @close="close"
+            :visible="visible"
+    >
+
+        <a-spin :spinning="confirmLoading">
+            <a-form :form="form">
+
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="accountId">
+                    <a-input placeholder="请输入accountId" v-decorator="['accountId', validatorRules.accountId ]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="投放目标">
+                    <a-input placeholder="请输入投放目标" v-decorator="['promotionPurpuse', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="投放方式">
+                    <a-input placeholder="请输入投放方式" v-decorator="['campaignBudget', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="日预算">
+                    <a-input placeholder="请输入日预算" v-decorator="['budgetDaily', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="广告组名称">
+                    <a-input placeholder="请输入广告组名称" v-decorator="['campaignName', {}]"/>
+                </a-form-item>
+                <a-form-item
+                        :labelCol="labelCol"
+                        :wrapperCol="wrapperCol"
+                        label="模板状态">
+                    <a-input-number v-decorator="[ 'status', validatorRules.status ]"/>
+                </a-form-item>
+
+            </a-form>
+        </a-spin>
+        <a-button type="primary" @click="handleOk">确定</a-button>
+        <a-button type="primary" @click="handleCancel">取消</a-button>
+    </a-drawer>
+</template>
+
+<script>
+    import {httpAction} from '@/api/manage'
+    import pick from 'lodash.pick'
+    import moment from "moment"
+
+    export default {
+        name: "ByteDanceCampaignTemplateModal",
+        data() {
+            return {
+                title: "操作",
+                visible: false,
+                model: {},
+                labelCol: {
+                    xs: {span: 24},
+                    sm: {span: 5},
+                },
+                wrapperCol: {
+                    xs: {span: 24},
+                    sm: {span: 16},
+                },
+
+                confirmLoading: false,
+                form: this.$form.createForm(this),
+                validatorRules: {
+                    accountId: {rules: [{required: true, message: '请输入accountId!'}]},
+                    status: {rules: [{required: true, message: '请输入模板状态!'}]},
+                },
+                url: {
+                    add: "/ctop/byteDanceCampaignTemplate/add",
+                    edit: "/ctop/byteDanceCampaignTemplate/edit",
+                },
+            }
+        },
+        created() {
+        },
+        methods: {
+            add() {
+                this.edit({});
+            },
+            edit(record) {
+                this.form.resetFields();
+                this.model = Object.assign({}, record);
+                this.visible = true;
+                this.$nextTick(() => {
+                    this.form.setFieldsValue(pick(this.model, 'accountId', 'promotionPurpuse', 'campaignBudget', 'budgetDaily', 'campaignName', 'status'))
+                    //时间格式化
+                });
+
+            },
+            close() {
+                this.$emit('close');
+                this.visible = false;
+            },
+            handleOk() {
+                const that = this;
+                // 触发表单验证
+                this.form.validateFields((err, values) => {
+                    if (!err) {
+                        that.confirmLoading = true;
+                        let httpurl = '';
+                        let method = '';
+                        if (!this.model.id) {
+                            httpurl += this.url.add;
+                            method = 'post';
+                        } else {
+                            httpurl += this.url.edit;
+                            method = 'put';
+                        }
+                        let formData = Object.assign(this.model, values);
+                        //时间格式化
+
+                        console.log(formData)
+                        httpAction(httpurl, formData, method).then((res) => {
+                            if (res.success) {
+                                that.$message.success(res.message);
+                                that.$emit('ok');
+                            } else {
+                                that.$message.warning(res.message);
+                            }
+                        }).finally(() => {
+                            that.confirmLoading = false;
+                            that.close();
+                        })
+
+
+                    }
+                })
+            },
+            handleCancel() {
+                this.close()
+            },
+
+
+        }
+    }
+</script>
+
+<style lang="less" scoped>
+    /** Button按钮间距 */
+    .ant-btn {
+        margin-left: 30px;
+        margin-bottom: 30px;
+        float: right;
+    }
+</style>

+ 193 - 0
src/views/template/deliverytarget/create.vue

@@ -0,0 +1,193 @@
+<template>
+  <a-card :body-style="{padding: '24px 32px'}" :bordered="false">
+    <a-form @submit="handleSubmit" :form="form">
+      <a-form-item
+        label="投放目标"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+        <a-radio-group @change="onChangeDeliveryTarget" v-model="deliveryTarget">
+          <a-radio-button value="a">转化量</a-radio-button>
+          <a-radio-button value="b">点击量</a-radio-button>
+          <a-radio-button value="c">展示量</a-radio-button>
+        </a-radio-group>
+      </a-form-item>
+
+      <a-form-item
+        label="下载方式"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+        <a-radio-group @change="onChangeDownloadType" v-model="downloadType">
+          <a-radio-button value="DOWNLOAD_URL">下载链接</a-radio-button>
+          <a-radio-button value="EXTERNAL_URL">落地页</a-radio-button>
+        </a-radio-group>
+      </a-form-item>
+
+      <a-form-item
+        label="下载链接"
+        v-if="showDownloadUrl"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+        <a-input placeholder="请输入网址或从之前网站选择" v-model="downloadUrl"/>
+      </a-form-item>
+
+      <a-form-item
+        v-if="showExternalUrl"
+        label="链接地址"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+        <a-input placeholder="请输入网址或从之前网站选择" v-model="externalUrl"/>
+      </a-form-item>
+
+      <a-form-item
+        v-if="showConvertTarget"
+        label="转化目标"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+        <a-input placeholder="请输入网址或从之前网站选择" v-model="convertTarget"/>
+      </a-form-item>
+
+      <a-form-item
+        label="应用包名"
+        v-if="showPackageName"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+        <a-input v-model="packageName"></a-input>
+      </a-form-item>
+
+      <a-form-item
+        label="直达链接"
+        v-if="showOpenUrlStatus"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+        <a-radio-group @change="onChangeOpenUrlStatus" v-model="openUrlStatus">
+          <a-radio-button value="disabled">不启用</a-radio-button>
+          <a-radio-button value="enabled">启用</a-radio-button>
+        </a-radio-group>
+      </a-form-item>
+
+      <a-form-item
+        label="直达链接生成方式"
+        v-if="showOpenUrlCreateMode&&showOpenUrlStatus"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+        <a-radio-group v-model="openUrlCreateMode">
+          <a-radio-button value="auto_create" disabled>自动生成</a-radio-button>
+          <a-radio-button value="hand_create">手动生成</a-radio-button>
+        </a-radio-group>
+      </a-form-item>
+      <a-form-item
+        label="跳转app链接"
+        v-if="showToAppUrl&&showOpenUrlStatus"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+        <a-input v-model="redirectUrl"></a-input>
+      </a-form-item>
+
+      <a-form-item
+        :wrapperCol="{ span: 24 }"
+        style="text-align: center"
+      >
+        <a-button htmlType="submit" type="primary">提交</a-button>
+        <a-button style="margin-left: 8px">保存</a-button>
+      </a-form-item>
+    </a-form>
+  </a-card>
+</template>
+
+<script>
+  import {deleteAction, postAction, getAction} from '@/api/manage'
+  import $ from 'jquery'
+  import moment from 'moment';
+  export default {
+    name: 'BaseForm',
+    data() {
+      return {
+        deliveryTarget:'a',
+        packageName:'',
+        downloadType:'DOWNLOAD_URL',
+        downloadUrl:'',
+        externalUrl:'',
+        convertTarget:'',
+        showDownloadUrl:true,
+        showExternalUrl:false,
+        showConvertTarget:true,
+        showPackageName:true,
+        showOpenUrlStatus:false,
+        openUrlStatus:'disabled',
+        redirectUrl:'',
+        showToAppUrl:false,
+        showOpenUrlCreateMode:false,
+        openUrlCreateMode:'hand_create',
+        // form
+        form: this.$form.createForm(this),
+        url: {
+          dictListUrl: 'toutiao/dictitem/list',
+          insertUrl:'toutiao/deliverytarget/template/insert'
+        }
+      }
+    },
+    methods: {
+      // handler
+      handleSubmit(e) {
+        e.preventDefault()
+        this.form.validateFields((err, values) => {
+          if (!err) {
+            console.log('Received values of form: ', values);
+            let params = {};
+            params.deliveryTarget = this.deliveryTarget;
+            params.downloadType = this.downloadType;
+            params.downloadUrl = this.downloadUrl;
+            params.externalUrl = this.externalUrl;
+            params.convertTarget = this.convertTarget;
+            params.packageName = this.packageName;
+            params.openUrlStatus = this.openUrlStatus;
+            params.openUrlCreateMode = this.openUrlCreateMode;
+            params.redirectUrl = this.redirectUrl;
+            console.log(params)
+            postAction(this.url.insertUrl,params).then((res)=>{
+              console.log(res)
+              if(res.success){
+                alert("投放目标-模板创建成功");
+              }
+            });
+          }
+        })
+      },
+      onChange(value) {
+        console.log(value);
+      },
+      onChangeDownloadType(value){
+        console.log(value);
+        if(this.downloadType == 'DOWNLOAD_URL'){
+          this.showDownloadUrl = true;
+          this.showExternalUrl = false;
+          this.showPackageName=true;
+          this.showOpenUrlStatus=false;
+
+        }else{
+          this.showDownloadUrl = false;
+          this.showExternalUrl = true;
+          this.showPackageName=false;
+          this.showOpenUrlStatus=true;
+        }
+      },
+      onChangeDeliveryTarget(value){
+        console.log(value);
+        if(this.deliveryTarget == 'a'){
+          this.showConvertTarget = true;
+        }else {
+          this.showConvertTarget = false;
+        }
+      },
+      onChangeOpenUrlStatus(){
+        if(this.openUrlStatus=='disabled'){
+          this.showOpenUrlCreateMode = false;
+          this.showToAppUrl = false;
+        }else{
+          this.showOpenUrlCreateMode = true;
+          this.showToAppUrl = true;
+        }
+      }
+    }
+  }
+</script>

+ 223 - 0
src/views/template/deliverytarget/list.vue

@@ -0,0 +1,223 @@
+<template>
+  <a-card :bordered="false">
+
+    <!-- 查询区域 -->
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline">
+        <a-row :gutter="24">
+
+          <a-col :md="6" :sm="8">
+            <a-form-item label="头条平台id">
+              <a-input placeholder="请输入头条平台id" v-model="queryParam.accountId"></a-input>
+            </a-form-item>
+          </a-col>
+          <a-col :md="6" :sm="8">
+            <a-form-item label="平台账号id">
+              <a-input placeholder="请输入平台账号id" v-model="queryParam.advertiserId"></a-input>
+            </a-form-item>
+          </a-col>
+          <template v-if="toggleSearchStatus">
+            <a-col :md="6" :sm="8">
+              <a-form-item label="投放目标">
+                <a-input placeholder="请输入投放目标" v-model="queryParam.deliveryTarget"></a-input>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="8">
+              <a-form-item label="下载方式">
+                <a-input placeholder="请输入下载方式" v-model="queryParam.downloadType"></a-input>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="8">
+              <a-form-item label="下载链接">
+                <a-input placeholder="请输入下载链接" v-model="queryParam.downloadUrl"></a-input>
+              </a-form-item>
+            </a-col>
+          </template>
+          <a-col :md="6" :sm="8" >
+            <span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
+              <a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
+              <a-button type="primary" @click="searchReset" icon="reload" style="margin-left: 8px">重置</a-button>
+              <a @click="handleToggleSearch" style="margin-left: 8px">
+                {{ toggleSearchStatus ? '收起' : '展开' }}
+                <a-icon :type="toggleSearchStatus ? 'up' : 'down'"/>
+              </a>
+            </span>
+          </a-col>
+
+        </a-row>
+      </a-form>
+    </div>
+
+    <!-- 操作按钮区域 -->
+    <div class="table-operator">
+      <a-button @click="handleAdd" type="primary" icon="plus">新增</a-button>
+      <a-button type="primary" icon="download" @click="handleExportXls('投放目标模板信息')">导出</a-button>
+      <a-upload name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader" :action="importExcelUrl" @change="handleImportExcel">
+        <a-button type="primary" icon="import">导入</a-button>
+      </a-upload>
+      <a-dropdown v-if="selectedRowKeys.length > 0">
+        <a-menu slot="overlay">
+          <a-menu-item key="1" @click="batchDel"><a-icon type="delete"/>删除</a-menu-item>
+        </a-menu>
+        <a-button style="margin-left: 8px"> 批量操作 <a-icon type="down" /></a-button>
+      </a-dropdown>
+    </div>
+
+    <!-- table区域-begin -->
+    <div>
+      <div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
+        <i class="anticon anticon-info-circle ant-alert-icon"></i> 已选择 <a style="font-weight: 600">{{ selectedRowKeys.length }}</a>项
+        <a style="margin-left: 24px" @click="onClearSelected">清空</a>
+      </div>
+
+      <a-table
+        ref="table"
+        size="middle"
+        bordered
+        rowKey="id"
+        :columns="columns"
+        :dataSource="dataSource"
+        :pagination="ipagination"
+        :loading="loading"
+        :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
+        @change="handleTableChange">
+
+        <span slot="action" slot-scope="text, record">
+          <a @click="handleEdit(record)">编辑</a>
+
+          <a-divider type="vertical" />
+          <a-dropdown>
+            <a class="ant-dropdown-link">更多 <a-icon type="down" /></a>
+            <a-menu slot="overlay">
+              <a-menu-item>
+                <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
+                  <a>删除</a>
+                </a-popconfirm>
+              </a-menu-item>
+            </a-menu>
+          </a-dropdown>
+        </span>
+
+      </a-table>
+    </div>
+    <!-- table区域-end -->
+
+    <!-- 表单区域 -->
+    <bytedanceDeliveryTargetTemplate-modal ref="modalForm" @ok="modalFormOk"></bytedanceDeliveryTargetTemplate-modal>
+  </a-card>
+</template>
+
+<script>
+  import BytedanceDeliveryTargetTemplateModal from './modules/BytedanceDeliveryTargetTemplateModal'
+  import { JeecgListMixin } from '@/mixins/JeecgListMixin'
+
+  export default {
+    name: "BytedanceDeliveryTargetTemplateList",
+    mixins:[JeecgListMixin],
+    components: {
+      BytedanceDeliveryTargetTemplateModal
+    },
+    data () {
+      return {
+        description: '投放目标模板信息管理页面',
+        // 表头
+        columns: [
+          {
+            title: '#',
+            dataIndex: '',
+            key:'rowIndex',
+            width:60,
+            align:"center",
+            customRender:function (t,r,index) {
+              return parseInt(index)+1;
+            }
+          },
+          {
+            title: '头条平台id',
+            align:"center",
+            dataIndex: 'accountId'
+          },
+          {
+            title: '平台账号id',
+            align:"center",
+            dataIndex: 'advertiserId'
+          },
+          {
+            title: '投放目标',
+            align:"center",
+            dataIndex: 'deliveryTarget'
+          },
+          {
+            title: '下载方式',
+            align:"center",
+            dataIndex: 'downloadType'
+          },
+          {
+            title: '下载链接',
+            align:"center",
+            dataIndex: 'downloadUrl'
+          },
+          {
+            title: '落地页链接',
+            align:"center",
+            dataIndex: 'externalUrl'
+          },
+          {
+            title: '转化目标',
+            align:"center",
+            dataIndex: 'convertTarget'
+          },
+          {
+            title: '应用包名',
+            align:"center",
+            dataIndex: 'packageName'
+          },
+          {
+            title: '直达链接启用状态',
+            align:"center",
+            dataIndex: 'openUrlStatus'
+          },
+          {
+            title: '直达链接生成方式',
+            align:"center",
+            dataIndex: 'openUrlCreateMode'
+          },
+          {
+            title: '跳转app链接',
+            align:"center",
+            dataIndex: 'redirectUrl'
+          },
+          {
+            title: 'status',
+            align:"center",
+            dataIndex: 'status'
+          },
+          {
+            title: '操作',
+            dataIndex: 'action',
+            align:"center",
+            scopedSlots: { customRender: 'action' },
+          }
+        ],
+        url: {
+          list: "/ctop/bytedanceDeliveryTargetTemplate/list",
+          delete: "/ctop/bytedanceDeliveryTargetTemplate/delete",
+          deleteBatch: "/ctop/bytedanceDeliveryTargetTemplate/deleteBatch",
+          exportXlsUrl: "ctop/bytedanceDeliveryTargetTemplate/exportXls",
+          importExcelUrl: "ctop/bytedanceDeliveryTargetTemplate/importExcel",
+        },
+      }
+    },
+    computed: {
+      importExcelUrl: function(){
+        return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;
+      }
+    },
+    methods: {
+
+    }
+  }
+</script>
+<style scoped>
+  @import '~@assets/less/common.less'
+</style>

+ 191 - 0
src/views/template/deliverytarget/modules/BytedanceDeliveryTargetTemplateModal.vue

@@ -0,0 +1,191 @@
+<template>
+  <a-modal
+    :title="title"
+    :width="800"
+    :visible="visible"
+    :confirmLoading="confirmLoading"
+    @ok="handleOk"
+    @cancel="handleCancel"
+    cancelText="关闭">
+    
+    <a-spin :spinning="confirmLoading">
+      <a-form :form="form">
+      
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="头条平台id">
+          <a-input placeholder="请输入头条平台id" v-decorator="['accountId', {}]" />
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="平台账号id">
+          <a-input placeholder="请输入平台账号id" v-decorator="['advertiserId', {}]" />
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="投放目标">
+          <a-input placeholder="请输入投放目标" v-decorator="['deliveryTarget', {}]" />
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="下载方式">
+          <a-input placeholder="请输入下载方式" v-decorator="['downloadType', {}]" />
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="下载链接">
+          <a-input placeholder="请输入下载链接" v-decorator="['downloadUrl', {}]" />
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="落地页链接">
+          <a-input placeholder="请输入落地页链接" v-decorator="['externalUrl', {}]" />
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="转化目标">
+          <a-input placeholder="请输入转化目标" v-decorator="['convertTarget', {}]" />
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="应用包名">
+          <a-input placeholder="请输入应用包名" v-decorator="['packageName', {}]" />
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="直达链接启用状态">
+          <a-input placeholder="请输入直达链接启用状态" v-decorator="['openUrlStatus', {}]" />
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="直达链接生成方式">
+          <a-input placeholder="请输入直达链接生成方式" v-decorator="['openUrlCreateMode', {}]" />
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="跳转app链接">
+          <a-input placeholder="请输入跳转app链接" v-decorator="['redirectUrl', {}]" />
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="status">
+          <a-input-number v-decorator="[ 'status', validatorRules.status ]" />
+        </a-form-item>
+		
+      </a-form>
+    </a-spin>
+  </a-modal>
+</template>
+
+<script>
+  import { httpAction } from '@/api/manage'
+  import pick from 'lodash.pick'
+  import moment from "moment"
+
+  export default {
+    name: "BytedanceDeliveryTargetTemplateModal",
+    data () {
+      return {
+        title:"操作",
+        visible: false,
+        model: {},
+        labelCol: {
+          xs: { span: 24 },
+          sm: { span: 5 },
+        },
+        wrapperCol: {
+          xs: { span: 24 },
+          sm: { span: 16 },
+        },
+
+        confirmLoading: false,
+        form: this.$form.createForm(this),
+        validatorRules:{
+        status:{rules: [{ required: true, message: '请输入status!' }]},
+        },
+        url: {
+          add: "/ctop/bytedanceDeliveryTargetTemplate/add",
+          edit: "/ctop/bytedanceDeliveryTargetTemplate/edit",
+        },
+      }
+    },
+    created () {
+    },
+    methods: {
+      add () {
+        this.edit({});
+      },
+      edit (record) {
+        this.form.resetFields();
+        this.model = Object.assign({}, record);
+        this.visible = true;
+        this.$nextTick(() => {
+          this.form.setFieldsValue(pick(this.model,'accountId','advertiserId','deliveryTarget','downloadType','downloadUrl','externalUrl','convertTarget','packageName','openUrlStatus','openUrlCreateMode','redirectUrl','status'))
+		  //时间格式化
+        });
+
+      },
+      close () {
+        this.$emit('close');
+        this.visible = false;
+      },
+      handleOk () {
+        const that = this;
+        // 触发表单验证
+        this.form.validateFields((err, values) => {
+          if (!err) {
+            that.confirmLoading = true;
+            let httpurl = '';
+            let method = '';
+            if(!this.model.id){
+              httpurl+=this.url.add;
+              method = 'post';
+            }else{
+              httpurl+=this.url.edit;
+               method = 'put';
+            }
+            let formData = Object.assign(this.model, values);
+            //时间格式化
+            
+            console.log(formData)
+            httpAction(httpurl,formData,method).then((res)=>{
+              if(res.success){
+                that.$message.success(res.message);
+                that.$emit('ok');
+              }else{
+                that.$message.warning(res.message);
+              }
+            }).finally(() => {
+              that.confirmLoading = false;
+              that.close();
+            })
+
+
+
+          }
+        })
+      },
+      handleCancel () {
+        this.close()
+      },
+
+
+    }
+  }
+</script>
+
+<style lang="less" scoped>
+
+</style>

+ 198 - 0
src/views/template/deliverytarget/modules/BytedanceDeliveryTargetTemplateModal__Style#Drawer.vue

@@ -0,0 +1,198 @@
+<template>
+  <a-drawer
+      :title="title"
+      :width="800"
+      placement="right"
+      :closable="false"
+      @close="close"
+      :visible="visible"
+  >
+
+    <a-spin :spinning="confirmLoading">
+      <a-form :form="form">
+      
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="头条平台id">
+          <a-input placeholder="请输入头条平台id" v-decorator="['accountId', {}]" />
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="平台账号id">
+          <a-input placeholder="请输入平台账号id" v-decorator="['advertiserId', {}]" />
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="投放目标">
+          <a-input placeholder="请输入投放目标" v-decorator="['deliveryTarget', {}]" />
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="下载方式">
+          <a-input placeholder="请输入下载方式" v-decorator="['downloadType', {}]" />
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="下载链接">
+          <a-input placeholder="请输入下载链接" v-decorator="['downloadUrl', {}]" />
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="落地页链接">
+          <a-input placeholder="请输入落地页链接" v-decorator="['externalUrl', {}]" />
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="转化目标">
+          <a-input placeholder="请输入转化目标" v-decorator="['convertTarget', {}]" />
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="应用包名">
+          <a-input placeholder="请输入应用包名" v-decorator="['packageName', {}]" />
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="直达链接启用状态">
+          <a-input placeholder="请输入直达链接启用状态" v-decorator="['openUrlStatus', {}]" />
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="直达链接生成方式">
+          <a-input placeholder="请输入直达链接生成方式" v-decorator="['openUrlCreateMode', {}]" />
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="跳转app链接">
+          <a-input placeholder="请输入跳转app链接" v-decorator="['redirectUrl', {}]" />
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="status">
+          <a-input-number v-decorator="[ 'status', validatorRules.status ]" />
+        </a-form-item>
+		
+      </a-form>
+    </a-spin>
+    <a-button type="primary" @click="handleOk">确定</a-button>
+    <a-button type="primary" @click="handleCancel">取消</a-button>
+  </a-drawer>
+</template>
+
+<script>
+  import { httpAction } from '@/api/manage'
+  import pick from 'lodash.pick'
+  import moment from "moment"
+
+  export default {
+    name: "BytedanceDeliveryTargetTemplateModal",
+    data () {
+      return {
+        title:"操作",
+        visible: false,
+        model: {},
+        labelCol: {
+          xs: { span: 24 },
+          sm: { span: 5 },
+        },
+        wrapperCol: {
+          xs: { span: 24 },
+          sm: { span: 16 },
+        },
+
+        confirmLoading: false,
+        form: this.$form.createForm(this),
+        validatorRules:{
+        status:{rules: [{ required: true, message: '请输入status!' }]},
+        },
+        url: {
+          add: "/ctop/bytedanceDeliveryTargetTemplate/add",
+          edit: "/ctop/bytedanceDeliveryTargetTemplate/edit",
+        },
+      }
+    },
+    created () {
+    },
+    methods: {
+      add () {
+        this.edit({});
+      },
+      edit (record) {
+        this.form.resetFields();
+        this.model = Object.assign({}, record);
+        this.visible = true;
+        this.$nextTick(() => {
+          this.form.setFieldsValue(pick(this.model,'accountId','advertiserId','deliveryTarget','downloadType','downloadUrl','externalUrl','convertTarget','packageName','openUrlStatus','openUrlCreateMode','redirectUrl','status'))
+		  //时间格式化
+        });
+
+      },
+      close () {
+        this.$emit('close');
+        this.visible = false;
+      },
+      handleOk () {
+        const that = this;
+        // 触发表单验证
+        this.form.validateFields((err, values) => {
+          if (!err) {
+            that.confirmLoading = true;
+            let httpurl = '';
+            let method = '';
+            if(!this.model.id){
+              httpurl+=this.url.add;
+              method = 'post';
+            }else{
+              httpurl+=this.url.edit;
+               method = 'put';
+            }
+            let formData = Object.assign(this.model, values);
+            //时间格式化
+            
+            console.log(formData)
+            httpAction(httpurl,formData,method).then((res)=>{
+              if(res.success){
+                that.$message.success(res.message);
+                that.$emit('ok');
+              }else{
+                that.$message.warning(res.message);
+              }
+            }).finally(() => {
+              that.confirmLoading = false;
+              that.close();
+            })
+
+
+
+          }
+        })
+      },
+      handleCancel () {
+        this.close()
+      },
+
+
+    }
+  }
+</script>
+
+<style lang="less" scoped>
+/** Button按钮间距 */
+  .ant-btn {
+    margin-left: 30px;
+    margin-bottom: 30px;
+    float: right;
+  }
+</style>

+ 492 - 0
src/views/template/userorientation/create.vue

@@ -0,0 +1,492 @@
+<template>
+  <a-card :body-style="{padding: '24px 32px'}" :bordered="false">
+    <a-form :form="form">
+      <a-form-item
+        label="地域"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+        <a-radio-group v-model="area" :defaultValue="0">
+          <a-radio-button value="0">不限</a-radio-button>
+          <a-radio-button value="按省市">按省市</a-radio-button>
+          <a-radio-button value="按区县">按区县</a-radio-button>
+          <a-radio-button value="按商圈">按商圈</a-radio-button>
+        </a-radio-group>
+      </a-form-item>
+      <a-form-item
+        label="按区县"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+        <a-tree-select
+          showSearch
+          style="width: 300px"
+          :value="value"
+          :dropdownStyle="{ maxHeight: '400px', overflow: 'auto' }"
+          placeholder='Please select'
+          allowClear
+          multiple
+          treeDefaultExpandAll
+          @change="onChange"
+          @search="onSearch"
+          @select="onSelect"
+        >
+          <a-tree-select-node value='parent 1' title='parent 1' key='0-1'>
+            <a-tree-select-node value='parent 1-0' title='parent 1-0' key='0-1-1'>
+              <a-tree-select-node value='leaf1' title='my leaf' key='random'/>
+              <a-tree-select-node value='leaf2' title='your leaf' key='random1'/>
+            </a-tree-select-node>
+            <a-tree-select-node value='parent 1-1' title='parent 1-1' key='random2'>
+              <a-tree-select-node value='sss' key='random3'>
+                <b style="color: #08c" slot="title">sss</b>
+              </a-tree-select-node>
+            </a-tree-select-node>
+          </a-tree-select-node>
+        </a-tree-select>
+      </a-form-item>
+
+      <a-form-item
+        label="性别"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+        <a-radio-group v-model="gender">
+          <a-radio-button v-for="sex in toutiaoSex" :key="sex.itemValue" :value="sex.itemValue">{{sex.description}}
+          </a-radio-button>
+        </a-radio-group>
+      </a-form-item>
+
+      <a-form-item
+        label="年龄"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+        <a-checkbox value="">不限</a-checkbox>
+        <a-checkbox-group v-model="ageRange">
+          <a-checkbox v-for="age in toutiaoAgeRange" :key="age.itemValue" :value="age.itemValue">{{age.description}}
+          </a-checkbox>
+        </a-checkbox-group>
+      </a-form-item>
+
+      <a-form-item
+        label="自定义人群"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+        <a-radio-group v-model="zdyrq">
+          <a-radio-button value="as">不限</a-radio-button>
+          <a-radio-button value="sd">自定义人群</a-radio-button>
+        </a-radio-group>
+      </a-form-item>
+
+      <a-form-item
+        label="定向逻辑"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+        <a-tabs defaultActiveKey="1">
+          <a-tab-pane tab="定向" key="1">
+            <a-table
+              ref="table2"
+              bordered
+              size="middle"
+              rowKey="id"
+              :columns="columns2"
+              :dataSource="dataSource2"
+              :pagination="ipagination2"
+              :loading="loading2"
+              :rowSelection="{selectedRowKeys: selectedRowKeys2, onChange: onSelectChange2}"
+              @change="handleTableChange2">
+              <span slot="action" slot-scope="text, record"></span>
+            </a-table>
+          </a-tab-pane>
+          <a-tab-pane tab="排除" key="2" forceRender>
+            <a-table
+              ref="table2"
+              bordered
+              size="middle"
+              rowKey="id"
+              :columns="columns2"
+              :dataSource="dataSource2"
+              :pagination="ipagination2"
+              :loading="loading2"
+              :rowSelection="{selectedRowKeys: selectedRowKeys2, onChange: onSelectChange2}"
+              @change="handleTableChange2">
+              <span slot="action" slot-scope="text, record"></span>
+            </a-table>
+          </a-tab-pane>
+          <a-tab-pane tab="同时定向排除" key="3">
+            <a-tabs defaultActiveKey="1">
+              <a-tab-pane tab="定向" key="1">
+                <a-table
+                  ref="table2"
+                  bordered
+                  size="middle"
+                  rowKey="id"
+                  :columns="columns2"
+                  :dataSource="dataSource2"
+                  :pagination="ipagination2"
+                  :loading="loading2"
+                  :rowSelection="{selectedRowKeys: selectedRowKeys2, onChange: onSelectChange2}"
+                  @change="handleTableChange2">
+                  <span slot="action" slot-scope="text, record"></span>
+                </a-table>
+              </a-tab-pane>
+              <a-tab-pane tab="排除" key="2" forceRender>
+                <a-table
+                  ref="table2"
+                  bordered
+                  size="middle"
+                  rowKey="id"
+                  :columns="columns2"
+                  :dataSource="dataSource2"
+                  :pagination="ipagination2"
+                  :loading="loading2"
+                  :rowSelection="{selectedRowKeys: selectedRowKeys2, onChange: onSelectChange2}"
+                  @change="handleTableChange2">
+           <span slot="action" slot-scope="text, record">
+        </span>
+                </a-table>
+              </a-tab-pane>
+            </a-tabs>
+          </a-tab-pane>
+        </a-tabs>
+      </a-form-item>
+
+      <a-form-item
+        label="兴趣定向"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+        <a-radio-group>
+          <a-radio-button value="as">不限</a-radio-button>
+          <a-radio-button value="sd">系统推荐</a-radio-button>
+          <a-radio-button value="zdy">自定义</a-radio-button>
+        </a-radio-group>
+      </a-form-item>
+
+      <a-form-item
+        label="兴趣分类"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+        <a-tree-select
+          showSearch
+          style="width: 300px"
+          :value="value"
+          :dropdownStyle="{ maxHeight: '400px', overflow: 'auto' }"
+          placeholder='Please select'
+          allowClear
+          multiple
+          treeDefaultExpandAll
+          @change="onChange"
+          @search="onSearch"
+          @select="onSelect"
+        >
+          <a-tree-select-node value='parent 1' title='parent 1' key='0-1'>
+            <a-tree-select-node value='parent 1-0' title='parent 1-0' key='0-1-1'>
+              <a-tree-select-node value='leaf1' title='my leaf' key='random'/>
+              <a-tree-select-node value='leaf2' title='your leaf' key='random1'/>
+            </a-tree-select-node>
+            <a-tree-select-node value='parent 1-1' title='parent 1-1' key='random2'>
+              <a-tree-select-node value='sss' key='random3'>
+                <b style="color: #08c" slot="title">sss</b>
+              </a-tree-select-node>
+            </a-tree-select-node>
+          </a-tree-select-node>
+        </a-tree-select>
+      </a-form-item>
+
+
+      <a-form-item
+        label="精选流量包"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+        <a-radio-group>
+          <a-radio-button value="llb_bx">不限</a-radio-button>
+          <a-radio-button value="rjjx">应用软件精选</a-radio-button>
+          <a-radio-button value="yxjx">游戏精选</a-radio-button>
+        </a-radio-group>
+      </a-form-item>
+
+      <a-form-item
+        label="平台"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+        <a-radio-group>
+          <a-radio-button value="as">不限</a-radio-button>
+          <a-radio-button value="sd">IOS</a-radio-button>
+          <a-radio-button value="sd">Android</a-radio-button>
+        </a-radio-group>
+      </a-form-item>
+
+      <a-form-item
+        label="网络"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+        <a-checkbox-group v-model="ageRange">
+          <a-checkbox value="">不限</a-checkbox>
+          <a-checkbox v-for="netType in toutiaoNetType" :key="netType.itemValue" :value="netType.itemValue">
+            {{netType.description}}
+          </a-checkbox>
+        </a-checkbox-group>
+      </a-form-item>
+
+      <a-form-item
+        label="app行为"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+        <a-radio-group>
+          <a-radio-button value="as">不限</a-radio-button>
+          <a-radio-button value="sd">按分类</a-radio-button>
+          <a-radio-button value="sd">按app</a-radio-button>
+        </a-radio-group>
+      </a-form-item>
+
+      <a-form-item
+        label="文章分类"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+        <a-radio-group v-model="isArticleCategory" @change="changeArticleCategoryType">
+          <a-radio-button value="unlimit_category">不限</a-radio-button>
+          <a-radio-button value="category">文章分类</a-radio-button>
+        </a-radio-group>
+        <br>
+        <a-select
+          mode="tags"
+          placeholder="选择文章分类"
+          style="width: 600px"
+          @change="onChange"
+          v-if="showArticleCategory"
+        >
+          <a-select-option v-for="articleCategory in articleCategoryList" :key="articleCategory.itemValue"
+                           :value="articleCategory.itemValue">{{articleCategory.itemText}}
+          </a-select-option>
+        </a-select>
+      </a-form-item>
+
+      <a-form-item
+        label="手机品牌"
+        :labelCol="{lg: {span: 7}, sm: {span: 7}}"
+        :wrapperCol="{lg: {span: 10}, sm: {span: 17} }">
+        <a-radio-group @change="changeMobileBrandType" v-model="isMobileBrand">
+          <a-radio-button value="unlimit_brand">不限</a-radio-button>
+          <a-radio-button value="brand">按品牌</a-radio-button>
+        </a-radio-group>
+        <br>
+        <a-select
+          mode="tags"
+          placeholder="选择手机品牌"
+          style="width: 600px"
+          @change="onChange"
+          v-if="showMobileBrand"
+        >
+          <a-select-option v-for="mobileBrand in mobileBrandList" :key="mobileBrand.itemValue"
+                           :value="mobileBrand.itemValue">{{mobileBrand.itemText}}
+          </a-select-option>
+        </a-select>
+      </a-form-item>
+
+
+      <a-form-item
+        :wrapperCol="{ span: 24 }"
+        style="text-align: center"
+      >
+        <a-button htmlType="submit" type="primary">提交</a-button>
+        <a-button style="margin-left: 8px">保存</a-button>
+      </a-form-item>
+    </a-form>
+  </a-card>
+</template>
+
+<script>
+  import {deleteAction, postAction, getAction} from '@/api/manage'
+
+  export default {
+    data() {
+      return {
+        form: this.$form.createForm(this),
+        gender: {},
+        toutiaoSex: {},
+        ageRange: [],
+        toutiaoAgeRange: {},
+        toutiaoNetType: {},
+        isMobileBrand: '',
+        showMobileBrand: false,
+        mobileBrandList: {},
+        showArticleCategory: false,
+        articleCategoryList: [],
+        isArticleCategory: {},
+        zdyrq: [],
+        area: [],
+        value: undefined,
+        model1: {},
+        model2: {},
+        currentRoleId: '',
+        queryParam1: {},
+        queryParam2: {},
+        dataSource1: [],
+        dataSource2: [],
+        ipagination1: {
+          current: 1,
+          pageSize: 10,
+          pageSizeOptions: ['10', '20', '30'],
+          showTotal: (total, range) => {
+            return range[0] + '-' + range[1] + ' 共' + total + '条'
+          },
+          showQuickJumper: true,
+          showSizeChanger: true,
+          total: 0
+        },
+        ipagination2: {
+          current: 1,
+          pageSize: 10,
+          pageSizeOptions: ['10', '20', '30'],
+          showTotal: (total, range) => {
+            return range[0] + '-' + range[1] + ' 共' + total + '条'
+          },
+          showQuickJumper: true,
+          showSizeChanger: true,
+          total: 0
+        },
+        isorter1: {
+          column: 'createTime',
+          order: 'desc'
+        },
+        isorter2: {
+          column: 'createTime',
+          order: 'desc'
+        },
+        filters1: {},
+        filters2: {},
+        loading1: false,
+        loading2: false,
+        selectedRowKeys1: [],
+        selectedRowKeys2: [],
+        selectionRows1: [],
+        selectionRows2: [],
+        columns2: [{
+          title: '人群',
+          align: 'center',
+          dataIndex: 'username',
+          width: 120
+        },
+          {
+            title: '属性',
+            align: 'center',
+            width: 100,
+            dataIndex: 'realname'
+          },
+          {
+            title: '创建时间',
+            align: 'center',
+            width: 80,
+            dataIndex: 'status_dictText'
+          }],
+        url: {
+          dictListUrl: 'toutiao/dictitem/list'
+        }
+      }
+    },
+    methods: {
+      onSelectChange2(selectedRowKeys, selectionRows) {
+        this.selectedRowKeys2 = selectedRowKeys
+        this.selectionRows2 = selectionRows
+      },
+      onClearSelected2() {
+        this.selectedRowKeys2 = []
+        this.selectionRows2 = []
+      },
+      onChange(value) {
+        console.log(value)
+        this.value = value
+      },
+      changeMobileBrandType(value) {
+        console.log(this.isMobileBrand);
+        if (this.isMobileBrand == 'brand') {
+          this.showMobileBrand = true;
+        } else {
+          this.showMobileBrand = false;
+        }
+      },
+      changeArticleCategoryType(value) {
+        console.log(this.isMobileBrand);
+        if (this.isArticleCategory == 'category') {
+          this.showArticleCategory = true;
+        } else {
+          this.showArticleCategory = false;
+        }
+      },
+      onSearch() {
+        console.log(...arguments)
+      },
+      onSelect() {
+        console.log(...arguments)
+      },
+      loadData2(arg) {
+        if (!this.url.list2) {
+          this.$message.error('请设置url.list2属性!')
+          return
+        }
+        //加载数据 若传入参数1则加载第一页的内容
+        if (arg === 1) {
+          this.ipagination2.current = 1
+        }
+        if (this.currentRoleId === '') return
+        let params = this.getQueryParams2()//查询条件
+        params.roleId = this.currentRoleId
+        this.loading2 = true
+        getAction(this.url.list2, params).then((res) => {
+          if (res.success) {
+            this.dataSource2 = res.result.records
+            this.ipagination2.total = res.result.total
+
+          }
+          this.loading2 = false
+        })
+      },
+      handleTableChange2(pagination, filters, sorter) {
+        if (Object.keys(sorter).length > 0) {
+          this.isorter2.column = sorter.field
+          this.isorter2.order = 'ascend' == sorter.order ? 'asc' : 'desc'
+        }
+        this.ipagination2 = pagination
+        this.loadData2()
+      }
+    },
+    created: function () {
+      let params = {};
+      params.dictId = '2f7d1020ae8c4a1f8af66087d9319139';
+      params.pageSize = '1000';
+      getAction(this.url.dictListUrl, params).then((res) => {
+        if (res.success) {
+          this.toutiaoSex = res.result.records
+        }
+      });
+      params = {};
+      params.dictId = '2b7fe41318c0f0fb4ae5a3cf5269ab04';
+      params.pageSize = '1000';
+      getAction(this.url.dictListUrl, params).then((res) => {
+        if (res.success) {
+          this.toutiaoAgeRange = res.result.records
+        }
+      });
+      params = {};
+      params.dictId = 'c6c75514b5fa17b25dde56d8e7bbc4e9';
+      params.pageSize = '1000';
+      getAction(this.url.dictListUrl, params).then((res) => {
+        if (res.success) {
+          this.toutiaoNetType = res.result.records
+        }
+      });
+      params = {};
+      params.dictId = '7f907c1dab0a65ce6d115e082cd79acf';
+      params.pageSize = '1000';
+      getAction(this.url.dictListUrl, params).then((res) => {
+        if (res.success) {
+          this.mobileBrandList = res.result.records
+        }
+      });
+      params = {};
+      params.dictId = 'defad85851bf6b1751a49b33d8b13b3b';
+      params.pageSize = '1000';
+      getAction(this.url.dictListUrl, params).then((res) => {
+        if (res.success) {
+          this.articleCategoryList = res.result.records
+        }
+      });
+    }
+  }
+</script>

+ 328 - 0
src/views/template/userorientation/list.vue

@@ -0,0 +1,328 @@
+<template>
+  <a-card :bordered="false">
+
+    <!-- 查询区域 -->
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline">
+        <a-row :gutter="24">
+
+          <a-col :md="6" :sm="8">
+            <a-form-item label="头条账号id">
+              <a-input placeholder="请输入头条账号id" v-model="queryParam.accountId"></a-input>
+            </a-form-item>
+          </a-col>
+          <a-col :md="6" :sm="8">
+            <a-form-item label="广告主id">
+              <a-input placeholder="请输入广告主id" v-model="queryParam.advertiserId"></a-input>
+            </a-form-item>
+          </a-col>
+          <template v-if="toggleSearchStatus">
+            <a-col :md="6" :sm="8">
+              <a-form-item label="定向人群包列表">
+                <a-input placeholder="请输入定向人群包列表" v-model="queryParam.retargetingTagsInclude"></a-input>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="8">
+              <a-form-item label="排除人群包列表">
+                <a-input placeholder="请输入排除人群包列表" v-model="queryParam.retargetingTagsExclude"></a-input>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="8">
+              <a-form-item label="受众性别">
+                <a-input placeholder="请输入受众性别" v-model="queryParam.gender"></a-input>
+              </a-form-item>
+            </a-col>
+          </template>
+          <a-col :md="6" :sm="8" >
+            <span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
+              <a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
+              <a-button type="primary" @click="searchReset" icon="reload" style="margin-left: 8px">重置</a-button>
+              <a @click="handleToggleSearch" style="margin-left: 8px">
+                {{ toggleSearchStatus ? '收起' : '展开' }}
+                <a-icon :type="toggleSearchStatus ? 'up' : 'down'"/>
+              </a>
+            </span>
+          </a-col>
+
+        </a-row>
+      </a-form>
+    </div>
+
+    <!-- 操作按钮区域 -->
+    <div class="table-operator">
+      <a-button @click="handleAdd" type="primary" icon="plus">新增</a-button>
+      <a-button type="primary" icon="download" @click="handleExportXls('今日头条受众模板信息')">导出</a-button>
+      <a-upload name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader" :action="importExcelUrl" @change="handleImportExcel">
+        <a-button type="primary" icon="import">导入</a-button>
+      </a-upload>
+      <a-dropdown v-if="selectedRowKeys.length > 0">
+        <a-menu slot="overlay">
+          <a-menu-item key="1" @click="batchDel"><a-icon type="delete"/>删除</a-menu-item>
+        </a-menu>
+        <a-button style="margin-left: 8px"> 批量操作 <a-icon type="down" /></a-button>
+      </a-dropdown>
+    </div>
+
+    <!-- table区域-begin -->
+    <div>
+      <div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
+        <i class="anticon anticon-info-circle ant-alert-icon"></i> 已选择 <a style="font-weight: 600">{{ selectedRowKeys.length }}</a>项
+        <a style="margin-left: 24px" @click="onClearSelected">清空</a>
+      </div>
+
+      <a-table
+        ref="table"
+        size="middle"
+        bordered
+        rowKey="id"
+        :columns="columns"
+        :dataSource="dataSource"
+        :pagination="ipagination"
+        :loading="loading"
+        :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
+        @change="handleTableChange">
+
+        <span slot="action" slot-scope="text, record">
+          <a @click="handleEdit(record)">编辑</a>
+
+          <a-divider type="vertical" />
+          <a-dropdown>
+            <a class="ant-dropdown-link">更多 <a-icon type="down" /></a>
+            <a-menu slot="overlay">
+              <a-menu-item>
+                <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
+                  <a>删除</a>
+                </a-popconfirm>
+              </a-menu-item>
+            </a-menu>
+          </a-dropdown>
+        </span>
+
+      </a-table>
+    </div>
+    <!-- table区域-end -->
+
+    <!-- 表单区域 -->
+    <byteDanceUserOrientationTemplate-modal ref="modalForm" @ok="modalFormOk"></byteDanceUserOrientationTemplate-modal>
+  </a-card>
+</template>
+
+<script>
+  import ByteDanceUserOrientationTemplateModal from './modules/ByteDanceUserOrientationTemplateModal'
+  import { JeecgListMixin } from '@/mixins/JeecgListMixin'
+
+  export default {
+    name: "ByteDanceUserOrientationTemplateList",
+    mixins:[JeecgListMixin],
+    components: {
+      ByteDanceUserOrientationTemplateModal
+    },
+    data () {
+      return {
+        description: '今日头条受众模板信息管理页面',
+        // 表头
+        columns: [
+          {
+            title: '#',
+            dataIndex: '',
+            key:'rowIndex',
+            width:60,
+            align:"center",
+            customRender:function (t,r,index) {
+              return parseInt(index)+1;
+            }
+          },
+          {
+            title: '头条账号id',
+            align:"center",
+            dataIndex: 'accountId'
+          },
+          {
+            title: '广告主id',
+            align:"center",
+            dataIndex: 'advertiserId'
+          },
+          {
+            title: '定向人群包列表',
+            align:"center",
+            dataIndex: 'retargetingTagsInclude'
+          },
+          {
+            title: '排除人群包列表',
+            align:"center",
+            dataIndex: 'retargetingTagsExclude'
+          },
+          {
+            title: '受众性别',
+            align:"center",
+            dataIndex: 'gender'
+          },
+          {
+            title: '年龄',
+            align:"center",
+            dataIndex: 'age'
+          },
+          {
+            title: '受众最低android版本',
+            align:"center",
+            dataIndex: 'androidOsv'
+          },
+          {
+            title: '受众最低ios版本',
+            align:"center",
+            dataIndex: 'iosOsv'
+          },
+          {
+            title: '运营商类型',
+            align:"center",
+            dataIndex: 'carrier'
+          },
+          {
+            title: '受众网络类型',
+            align:"center",
+            dataIndex: 'ac'
+          },
+          {
+            title: '手机品牌',
+            align:"center",
+            dataIndex: 'deviceBrand'
+          },
+          {
+            title: '受众文章分类',
+            align:"center",
+            dataIndex: 'articleCategory'
+          },
+          {
+            title: '用户首次激活时间',
+            align:"center",
+            dataIndex: 'activateType'
+          },
+          {
+            title: '受众平台',
+            align:"center",
+            dataIndex: 'platform'
+          },
+          {
+            title: '地域定向城市或者区县列表',
+            align:"center",
+            dataIndex: 'city'
+          },
+          {
+            title: '商圈ID数组',
+            align:"center",
+            dataIndex: 'businessIds'
+          },
+          {
+            title: '地域类型',
+            align:"center",
+            dataIndex: 'district'
+          },
+          {
+            title: '受众位置类型',
+            align:"center",
+            dataIndex: 'locationType'
+          },
+          {
+            title: '兴趣分类',
+            align:"center",
+            dataIndex: 'adTag'
+          },
+          {
+            title: '兴趣关键词, 传入具体的词id,非兴趣词包id',
+            align:"center",
+            dataIndex: 'interestTags'
+          },
+          {
+            title: '行为定向',
+            align:"center",
+            dataIndex: 'appBehaviorTarget'
+          },
+          {
+            title: 'APP行为定向,分类集合',
+            align:"center",
+            dataIndex: 'appCategory'
+          },
+          {
+            title: 'APP行为定向,APP集合',
+            align:"center",
+            dataIndex: 'appIds'
+          },
+          {
+            title: '产品目录ID(ID由查询产品目录接口得到)',
+            align:"center",
+            dataIndex: 'productPlatformId'
+          },
+          {
+            title: 'H5地址参数',
+            align:"center",
+            dataIndex: 'externalUrlParams'
+          },
+          {
+            title: '直达链接参数',
+            align:"center",
+            dataIndex: 'openUrlParams'
+          },
+          {
+            title: '是否自定义商品定向',
+            align:"center",
+            dataIndex: 'dpaLocalAudience'
+          },
+          {
+            title: '排除人群包',
+            align:"center",
+            dataIndex: 'excludeCustomActions'
+          },
+          {
+            title: '包含人群包',
+            align:"center",
+            dataIndex: 'includeCustomActions'
+          },
+          {
+            title: '精选流量包',
+            align:"center",
+            dataIndex: 'superiorPopularityType'
+          },
+          {
+            title: '定向流量包ID数组',
+            align:"center",
+            dataIndex: 'flowPackage'
+          },
+          {
+            title: '排除流量包ID数组',
+            align:"center",
+            dataIndex: 'excludeFlowPackage'
+          },
+          {
+            title: 'status',
+            align:"center",
+            dataIndex: 'status'
+          },
+          {
+            title: '操作',
+            dataIndex: 'action',
+            align:"center",
+            scopedSlots: { customRender: 'action' },
+          }
+        ],
+        url: {
+          list: "/ctop/byteDanceUserOrientationTemplate/list",
+          delete: "/ctop/byteDanceUserOrientationTemplate/delete",
+          deleteBatch: "/ctop/byteDanceUserOrientationTemplate/deleteBatch",
+          exportXlsUrl: "ctop/byteDanceUserOrientationTemplate/exportXls",
+          importExcelUrl: "ctop/byteDanceUserOrientationTemplate/importExcel",
+        },
+      }
+    },
+    computed: {
+      importExcelUrl: function(){
+        return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;
+      }
+    },
+    methods: {
+
+    }
+  }
+</script>
+<style scoped>
+  @import '~@assets/less/common.less'
+</style>

Різницю між файлами не показано, бо вона завелика
+ 317 - 0
src/views/template/userorientation/modules/ByteDanceUserOrientationTemplateModal.vue


Різницю між файлами не показано, бо вона завелика
+ 324 - 0
src/views/template/userorientation/modules/ByteDanceUserOrientationTemplateModal__Style#Drawer.vue