瀏覽代碼

'wzj改投放管家'

魏志佳 4 年之前
父節點
當前提交
4129fec78b
共有 28 個文件被更改,包括 7000 次插入98 次删除
  1. 3 1
      public/color.less
  2. 5 0
      src/App.vue
  3. 二進制
      src/assets/logoNew.png
  4. 二進制
      src/assets/logoNew1.png
  5. 58 26
      src/components/menu/SideMenu.vue
  6. 12 6
      src/components/page/GlobalHeader.vue
  7. 11 2
      src/components/page/GlobalLayout.vue
  8. 27 4
      src/components/tools/Logo.vue
  9. 14 0
      src/views/dashboard/Analysis.vue
  10. 2 8
      src/views/modules/BatchCreate/TouTiaoBatch.vue
  11. 8 1
      src/views/modules/BatchCreate/components/material.vue
  12. 1 1
      src/views/modules/BatchCreate/linkMultiSelect.vue
  13. 671 0
      src/views/modules/LaunchHousekeeper/LaunchHousekeeperList.vue
  14. 1029 0
      src/views/modules/LaunchHousekeeper/material.vue
  15. 661 0
      src/views/modules/LaunchHousekeeper/newProject.vue
  16. 237 0
      src/views/modules/LaunchHousekeeper/radioCheck.vue
  17. 620 0
      src/views/modules/LaunchHousekeeper/setProjectBudget.vue
  18. 697 0
      src/views/modules/LaunchHousekeeper/setProjectConvert.vue
  19. 1295 0
      src/views/modules/LaunchHousekeeper/setProjectCreate.vue
  20. 1054 0
      src/views/modules/LaunchHousekeeper/setProjectDirectional.vue
  21. 127 13
      src/views/modules/Statistics/Statistics.vue
  22. 4 4
      src/views/modules/Statistics/accountReport.vue
  23. 209 0
      src/views/modules/Statistics/components/datePick.vue
  24. 4 1
      src/views/modules/Statistics/components/lifting.vue
  25. 53 0
      src/views/modules/Statistics/effectReport.vue
  26. 57 30
      src/views/modules/Statistics/newHome.vue
  27. 1 1
      vue.config.js
  28. 140 0
      投放管家创建接口

+ 3 - 1
public/color.less

@@ -2216,7 +2216,9 @@ this.tinycolor = tinycolor;
 }
 
 .layout .header {
-  background-color: @primary-color !important;
+  // background-color:#0B2040  !important;
+  background:#0B2040  !important;
+  
 }
 
 i.trigger:hover {

+ 5 - 0
src/App.vue

@@ -60,4 +60,9 @@
     height: 39px !important;
     border-bottom:1px solid #1890ff !important;
   }
+  .layout .header {
+ background-color:#0B2040  !important;
+  background:#0B2040  !important;
+  
+}
 </style>

二進制
src/assets/logoNew.png


二進制
src/assets/logoNew1.png


+ 58 - 26
src/components/menu/SideMenu.vue

@@ -146,32 +146,64 @@
 
 <!-- update_begin author:sunjianlei date:20190530 for: 选中首页的时候不显示背景颜色 -->
 <style lang="less">
-  .ant-menu.ant-menu-root {
-    & > .ant-menu-item:first-child {
-      background-color: transparent;
-
-    //   & > a, & > a:hover {
-    //     color: rgba(0, 0, 0, 0.65);
-    //   }
-
-    //   &.ant-menu-item-selected {
-    //     & > a, & > a:hover {
-    //       color: @primary-color;
-    //     }
-    //   }
-    }
+  // .ant-menu.ant-menu-root {
+  //   & > .ant-menu-item:first-child {
+  //     background-color: transparent;
+
+  //   //   & > a, & > a:hover {
+  //   //     color: rgba(0, 0, 0, 0.65);
+  //   //   }
+
+  //   //   &.ant-menu-item-selected {
+  //   //     & > a, & > a:hover {
+  //   //       color: @primary-color;
+  //   //     }
+  //   //   }
+  //   }
+
+  //   &.ant-menu-dark > .ant-menu-item:first-child {
+  //     & > a, & > a:hover {
+  //       color: rgba(255, 255, 255, 0.65);
+  //     }
+
+  //     &.ant-menu-item-selected {
+  //       & > a, & > a:hover {
+  //         color: rgba(255, 255, 255, 1);
+  //       }
+  //     }
+  //   }
+  // }
+</style>
+<!-- update_end author:sunjianlei date:20190530 for: 选中首页的时候不显示背景颜色 -->
 
-    &.ant-menu-dark > .ant-menu-item:first-child {
-      & > a, & > a:hover {
-        color: rgba(255, 255, 255, 0.65);
-      }
+<!--侧边栏的选中after显示在左侧 -->
 
-      &.ant-menu-item-selected {
-        & > a, & > a:hover {
-          color: rgba(255, 255, 255, 1);
-        }
-      }
-    }
+<style lang="less">
+  ul.ant-menu-inline li.ant-menu-selected::after, ul.ant-menu-vertical li.ant-menu-selected::after,ul.ant-menu-vertical li.ant-menu-item-selected::after,ul.ant-menu-inline li.ant-menu-item-selected::after {
+      -webkit-transform: scaleY(1);
+      transform: scaleY(1);
+      opacity: 1;
+      -webkit-transition: opacity 0.15s cubic-bezier(0.645, 0.045, 0.355, 1), -webkit-transform 0.15s cubic-bezier(0.645, 0.045, 0.355, 1);
+      transition: opacity 0.15s cubic-bezier(0.645, 0.045, 0.355, 1), -webkit-transform 0.15s cubic-bezier(0.645, 0.045, 0.355, 1);
+      transition: transform 0.15s cubic-bezier(0.645, 0.045, 0.355, 1), opacity 0.15s cubic-bezier(0.645, 0.045, 0.355, 1);
+      transition: transform 0.15s cubic-bezier(0.645, 0.045, 0.355, 1), opacity 0.15s cubic-bezier(0.645, 0.045, 0.355, 1), -webkit-transform 0.15s cubic-bezier(0.645, 0.045, 0.355, 1);
   }
-</style>
-<!-- update_end author:sunjianlei date:20190530 for: 选中首页的时候不显示背景颜色 -->
+  .ant-menu-inline li.ant-menu-item::after ,.ant-menu-vertical li.ant-menu-item::after ,.ant-menu-vertical li.ant-menu-item::after{
+    display: block;
+    position: absolute;
+    top: 0;
+    left: 0px;
+    right: 0;
+    bottom: 0;
+    border-left: 3px solid #1890ff;
+    border-right: 0px ;
+    -webkit-transform: scaleY(0.0001);
+    transform: scaleY(0.0001);
+    opacity: 0;
+    -webkit-transition: opacity 0.15s cubic-bezier(0.215, 0.61, 0.355, 1), -webkit-transform 0.15s cubic-bezier(0.215, 0.61, 0.355, 1);
+    transition: opacity 0.15s cubic-bezier(0.215, 0.61, 0.355, 1), -webkit-transform 0.15s cubic-bezier(0.215, 0.61, 0.355, 1);
+    transition: transform 0.15s cubic-bezier(0.215, 0.61, 0.355, 1), opacity 0.15s cubic-bezier(0.215, 0.61, 0.355, 1);
+    transition: transform 0.15s cubic-bezier(0.215, 0.61, 0.355, 1), opacity 0.15s cubic-bezier(0.215, 0.61, 0.355, 1), -webkit-transform 0.15s cubic-bezier(0.215, 0.61, 0.355, 1);
+    content: '';
+}
+</style>

+ 12 - 6
src/components/page/GlobalHeader.vue

@@ -17,8 +17,8 @@
         :type="collapsed ? 'menu-unfold' : 'menu-fold'"
         @click.native="toggle"/>
 
-      <span v-if="device === 'desktop'">欢迎使用汇创投放助手</span>
-      <span v-else>汇创投放助手</span>
+      <!-- <span v-if="device === 'desktop'">欢迎使用汇创投放助手</span> -->
+      <!-- <span v-else>汇创投放助手</span> -->
 
 
       <user-menu :theme="theme"/>
@@ -166,7 +166,12 @@
   /* update_begin author:scott date:20190220 for: 缩小首页布局顶部的高度*/
 
   $height: 59px;
-
+    .layout .header .user-wrapper .action .anticon, .layout .top-nav-header-index .user-wrapper .action .anticon {
+        color: #999;
+    }
+    .layout .header .user-wrapper .action .anticon, .layout .top-nav-header-index .user-wrapper .action .anticon {
+        color: #999;
+    }
   .layout {
 
     .top-nav-header-index {
@@ -181,8 +186,8 @@
       }
 
       .trigger {
-        line-height: 64px;
-
+        line-height: 48px;
+        font-size: 17px;
         &:hover {
           background: rgba(0, 0, 0, 0.05);
         }
@@ -191,7 +196,7 @@
 
     .header {
       z-index: 2;
-      color: white;
+      color: #999;
       height: $height;
       background-color: #1890ff;
       transition: background 300ms;
@@ -202,6 +207,7 @@
         box-shadow: 0 0 4px rgba(0, 0, 0, 0.2);
         background-color: white !important;
       }
+
     }
 
     .header, .top-nav-header-index {

+ 11 - 2
src/components/page/GlobalLayout.vue

@@ -181,7 +181,15 @@
       filter: invert(80%);
     }
   }
-
+  .layout .header .user-wrapper .action i.anticon, .layout .top-nav-header-index .user-wrapper .action i.anticon {
+        color: #999;
+  }
+  .layout .header .user-wrapper .action:hover i.anticon, .layout .top-nav-header-index .user-wrapper .action:hover i.anticon {
+        color: #fff;
+  }
+  .layout .header .user-wrapper .action:hover, .layout .top-nav-header-index .user-wrapper .action:hover {
+        color: #fff;
+  }
   .layout {
     min-height: 100vh !important;
     overflow-x: hidden;
@@ -239,7 +247,7 @@
     }
 
     .trigger {
-      font-size: 22px;
+      font-size: 17px;
       line-height: 42px;
       padding: 0 18px;
       cursor: pointer;
@@ -247,6 +255,7 @@
 
       &:hover {
         background: rgba(255, 255, 255, 0.3);
+        color:#fff
       }
     }
 

+ 27 - 4
src/components/tools/Logo.vue

@@ -1,8 +1,9 @@
 <template>
   <div class="logo">
     <router-link :to="{name:'dashboard'}">
-      <img src="~@/assets/logo.png" alt="logo">
-      <h1 v-if="showTitle">{{ title }}</h1>
+      <img src="~@/assets/logoNew1.png" alt="logo">
+      <span class="name">有腾投放管家</span>
+      <!-- <h1 v-if="showTitle">{{ 有腾管家 }}</h1> -->
     </router-link>
   </div>
 </template>
@@ -49,7 +50,29 @@
     }
 
     &.light .logo {
-      background-color: #1890ff;
+      background-color: #0B2040;
     }
   }
-</style>
+.logo{
+  .name{
+    font-size: 14px;
+    font-family: PingFangSC-Medium, PingFang SC;
+    font-weight: 500;
+    color: #CED2D9;
+    // line-height: 22px;
+    margin-left: 20px;
+    padding-left: 21px;
+    position: relative;
+  }
+  .name::before{
+    content: '';
+    width: 1px;
+    height: 18px;
+    background: rgba(255, 255, 255, 0.31);
+    position: absolute;
+    left: 0;
+    top: 50%;
+    margin-top: -9px;
+  }
+}
+</style>

+ 14 - 0
src/views/dashboard/Analysis.vue

@@ -1,6 +1,10 @@
 <style lang='scss'>
     .only-there .ant-tabs-bar{
         background: white;
+        padding: 0 24px;
+    }
+    .ant-card-head .ant-tabs-bar{
+      padding: 0;
     }
     #updateInfo .ant-modal-content,#updateInfo .ant-modal-body {
       
@@ -516,4 +520,14 @@
       }
     }
   }
+</style>
+<style lang="less">
+  .ant-tabs-bar {
+    margin: 0 0 12px 0;
+    /* height: 55px; */
+    border-bottom: 1px solid #e8e8e8;
+    outline: none;
+    -webkit-transition: padding 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
+    transition: padding 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
+}
 </style>

+ 2 - 8
src/views/modules/BatchCreate/TouTiaoBatch.vue

@@ -607,7 +607,7 @@ export default {
 
             spinning:false,
             moment,
-            loading:false,
+           
             accountID:undefined,
             openID:undefined,
             treeData:[],
@@ -631,7 +631,7 @@ export default {
             columns,
             selectedRowKeys:[],
             selectedRows:[],
-
+            loading:false,
             editID:0,
             //批量修改里的表格
             typeValue,
@@ -945,12 +945,6 @@ export default {
                 this.$message.error('请选择账户后重试')
             }
 
-
-            // postAction('',{
-
-            // }).then((res)=>{
-            //     console.log(res)
-            // })
         },
         //点击分页
         sort(pagination, filters, sorter, { currentDataSource }){

+ 8 - 1
src/views/modules/BatchCreate/components/material.vue

@@ -733,8 +733,15 @@
       getTags() {
         let accountInfo = localStorage.getItem('accountInfo')
         // console.log(groupInfo)
+        let LHKaccountInfo=sessionStorage.getItem('LHKaccountInfo');
+        
+        if(accountInfo){
+          this.accountInfo=JSON.parse(accountInfo)
+        }else if(LHKaccountInfo){
+          this.accountInfo=JSON.parse(LHKaccountInfo)[1]
+        }
 
-        this.accountInfo=JSON.parse(accountInfo)
+        
 
         getAction('/bytedance/batch/creative/words/get', {
           accountId: this.accountInfo.value

+ 1 - 1
src/views/modules/BatchCreate/linkMultiSelect.vue

@@ -569,7 +569,7 @@
                 parentCode:0,
                 level:this.maxLayers
             }).then((res)=>{
-                // console.log(res);
+                console.log(res);
                 if(res.success){
                     res.data.forEach((item,index)=>{
                         item.value=item.code

+ 671 - 0
src/views/modules/LaunchHousekeeper/LaunchHousekeeperList.vue

@@ -0,0 +1,671 @@
+<template>
+    <div class="housekeeper">
+         <div class="topOptions">
+            <span class="OptinItem topOpt">
+                <!-- <Treeselect :appId.sync="accountID" :multiple="false" request="2,4" reqUrl='/ctop/projectMember/getProjectAccountByUserId' ref="treeSelect" style="margin-bottom:8px " /> -->
+
+                <a-tree-select
+                    v-model="accountIds"
+                    show-search
+                    style="width: 600px;height:30px"
+                    :dropdownMatchSelectWidth='true'
+                    :dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"              
+                    tree-checkable
+                    searchPlaceholder='请输入账户关键字搜索'
+                    :show-checked-strategy="SHOW_PARENT"
+                    placeholder="请选择项目和账户或搜索账户关键字"
+                    treeNodeFilterProp="title"
+                    :allowClear="true"
+                    @change="treeChange"
+                                       
+                    :maxTagCount='1'    
+                    :tree-data="treeData"
+                    :filterOption='filterOption'
+                >
+              
+                </a-tree-select>
+            </span>
+            <span class="OptinItem">
+                <a-select  style="width: 120px" v-model="statusValue" @change="statusChange" placeholder="请选择状态">
+                    <a-select-option :value="0" >
+                        不限
+                    </a-select-option>
+                    <a-select-option :value="1" >
+                        启用
+                    </a-select-option>
+                    <a-select-option :value="2" >
+                        暂停
+                    </a-select-option>
+                </a-select>
+            </span>
+
+            <span class="OptinItem">
+                <!-- <a-date-picker @change="dateChange" /> -->
+                 <a-range-picker v-model="dateValue" :disabled-date="disabledDate"  style="width: 250px;" format="YYYY-MM-DD" @change="dateChange" />
+            </span>
+            <span class="OptinItem">
+                <a-input-search placeholder="请输入投放项目的名称" v-model="optionId" style="width: 200px"  />
+            </span>
+            <span class="optionBtn">
+                <a-button type='primary' @click="search" class="searchBtn">查询</a-button>
+                <!-- <a-button type='default' @click="reset">重置</a-button> -->
+            </span>
+        </div>
+        <div class="tableArea">
+            <div class="tableOption">
+                <span class="OptinItem" style="margin-right:20px">
+                    <a-button type='primary' @click="addNewProject">
+                        <a-icon type="plus" />
+                        新增投放项目
+                    </a-button>
+                </span>
+                <span class="OptinItem">
+                    <a-tooltip>
+                        <template slot="title" >
+                            这里可以批量启动、暂停、删除你的选择哦~
+                        </template>
+                        <!-- <a-button type="link" @click="changeSelectStatus">批量操作</a-button> -->
+                        <span >批量操作:</span>
+                    </a-tooltip>
+                </span>
+                <span class="OptinItem">
+                    <a-select  style="width: 120px" @change="optChange" v-model="optValue" placeholder="请选择状态" :disabled='selectedRowKeys.length<=0'>
+                        <a-select-option value="open" >
+                            启动
+                        </a-select-option>
+                        <a-select-option value="pause">
+                            暂停
+                        </a-select-option>
+                        <a-select-option value="delete">
+                            删除
+                        </a-select-option>
+                    </a-select>
+                </span>
+                 <span class="OptinItem">
+                    <a-popconfirm
+                        title="确定要删除选择的内容吗?"
+                        ok-text="删除"
+                        cancel-text="取消"
+                        @confirm="confirm"
+                        @cancel="cancel"
+                        v-if="optValue=='delete'"
+                    >
+                        <a-button type='primary' @click="isOkHandle" class="ok">确定</a-button>
+                    </a-popconfirm>
+                    <a-button type='primary' @click="isOkHandle" class="ok" v-else>确定</a-button>
+
+                 </span>
+                <!-- <span class="optionBtn">
+                    <a-button type='primary' @click="reset">自定义列</a-button>
+                </span> -->
+            </div>
+            <div class="table">
+                <a-table
+                    :columns="columns"
+                    :data-source="data"
+                    :rowSelection="{selectedRowKeys: selectedRowKeys,...rowSelection}"
+                    bordered
+                    :pagination="ipagination"
+                    :loading="loading"
+                    @change="sort"
+                    
+                >
+                   
+
+                    <span slot="checkedStatus" slot-scope="text,record">
+                        <a-spin :spinning="record.spin" size="small" >
+                            <div class="spin-content">
+                                <a-switch size="default" :checked=text  @change="switchChange(text,record)"/>
+                            </div>
+                        </a-spin>    
+                        <!-- <a-switch size="default" :checked=text  @change="switchChange(text,record)"/>                     -->
+                    </span>
+
+                    <span slot="budgetMode" slot-scope="text">
+                        <span v-if="text=='DAILY'">日预算</span>
+                        <span v-if="text=='TOTAL'">总预算</span>
+                    </span>
+                    
+                  
+                    <span slot="parentGroup" slot-scope="text">
+                        <a href="javascript:;" >{{text}}</a>
+                    </span>
+                    <span slot="parentPlan" slot-scope="text">
+                        <a href="javascript:;" >{{text}}</a>
+                    </span>
+                    <span slot="time" slot-scope="text,record">
+                        {{record.startTime}}至{{record.endTime}}
+                    </span>
+                    <span slot="flowControlMode" slot-scope="text">
+                        <span v-if="text=='FLOW_CONTROL_MODE_FAST'">优先跑量</span>
+                        <span v-if="text=='FLOW_CONTROL_MODE_SMOOTH'">优先低成本</span>
+                        <span v-if="text=='FLOW_CONTROL_MODE_BALANCE'">均衡投放</span>
+                    </span>
+
+                    <span slot="options" slot-scope="text,record">
+                        <a href="javascript:;" @click="editProject(record)">编辑</a>
+                        <a-divider type="vertical" />
+                        <a href="javascript:;" @click="planAnalysis(record)">计划分析</a>
+                        <a-divider type="vertical" />
+                        <a href="javascript:;" @click="deleteProject(record)">删除</a>
+                    </span>
+                </a-table>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import moment from 'moment';
+import { getAction, postAction, downFile, downFilePost } from '@/api/manage';
+const SHOW_PARENT = TreeSelect.SHOW_PARENT;
+import { TreeSelect } from 'ant-design-vue';
+import qs from 'qs'
+const columns = [
+  {
+    title: '开关',
+    dataIndex: 'checkedStatus',
+    key: 'checkedStatus',
+    align: 'center',
+    scopedSlots: { customRender: 'checkedStatus' }
+  },
+  {
+    title: '投放项目名称',
+    dataIndex: 'name',
+    key: 'name',
+    align: 'center',
+    scopedSlots: { customRender: 'name' }
+  },
+  {
+    title: '投放项目状态',
+    dataIndex: 'statusName',
+    key: 'statusName',
+    align: 'center',
+  },
+    //   {
+    //     title: '建议',
+    //     dataIndex: 'landingType_dictText',
+    //     key: 'landingType_text',
+    //     align: 'center',
+    //   },
+  {
+    title: '投放项目预算类型',
+    dataIndex: 'budgetMode',
+    key: 'budgetMode',
+    align: 'center',
+    width:250,
+    scopedSlots: { customRender: 'budgetMode' }
+  },
+  {
+    title: '投放项目预算(元)',
+    dataIndex: 'budget',
+    key: 'budget',
+    align: 'center',
+    scopedSlots: { customRender: 'budget' }
+  },
+  {
+    title: '投放时间',
+    dataIndex: 'time',
+    key: 'time',
+    align: 'center',
+    scopedSlots: { customRender: 'time' }
+  },
+  {
+    title: '投放项目ID',
+    dataIndex: 'id',
+    key: 'id',
+    align: 'center',
+    scopedSlots: { customRender: 'id' }
+  },
+  {
+    title: '所属账户ID',
+    dataIndex: 'accountId',
+    key: 'accountId',
+    align: 'center',
+    scopedSlots: { customRender: 'accountId' }
+  },
+  {
+    title: '操作',
+    dataIndex: 'options',
+    key: 'options',
+    align: 'center',
+    width:200,
+    scopedSlots: { customRender: 'options' }
+  },
+];
+
+export default {
+    data() {
+        return {
+            treeData: [],
+            SHOW_PARENT,
+            accountIds:[],
+            ipagination: {
+                current: 1,
+                pageSize: 10,
+                //   pageSizeOptions: ['10', '20', '30'],
+                showTotal: (total, range) => {
+                    return range[0] + "-" + range[1] + " 共" + total + "条"
+                },
+                showQuickJumper: true,
+                showSizeChanger:true,
+                pageSizeOptions: ['10', '30', '50'],
+                total: 0,
+                onChange: (current, pageSize) => {
+                    // 切换分页时的回调,
+                    // 当在页面定义change事件时,切记要把此处的事件清除,因为这两个事件重叠了,可能到时候会导致一些莫名的bug
+                    this.ipagination.current = current;
+                    this.ipagination.pageSize= pageSize;
+                }
+            },
+
+            accountID:undefined,
+            treeData:[],
+            dateValue:[],//日期选择框选择
+            dateString:[],//--我赋值的是dateString
+
+
+            statusValue:undefined,
+            optionId:'',//input输入的id或关键词
+            optValue:undefined,
+
+            data:[],
+            columns,
+            selectedRowKeys:[],
+            selectedRows:[],
+            loading:false,
+            userInfo:{},
+        }
+    },
+    computed: {
+        rowSelection(){
+            return {
+                onChange: (selectedRowKeys, selectedRows) => {
+                    // console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
+                    this.selectedRowKeys=selectedRowKeys;
+                    this.selectedRows=selectedRows;
+                },
+                onSelect: (record, selected, selectedRows) => {
+                    // console.log(record, selected, selectedRows);
+                    this.modifyTableData=selectedRows;
+
+                    this.selectedRows=selectedRows;
+                },
+                onSelectAll: (selected, selectedRows, changeRows) => {
+                    // console.log(selected, selectedRows, changeRows);
+                    this.modifyTableData=selectedRows
+                    this.selectedRows=selectedRows;
+                },
+            }
+
+        },
+    },
+    methods:{
+         // //项目改变后的事件
+        treeChange(val) {
+        // console.log(this.treeData)
+        console.log(val)
+        this.accountIds = [];
+        //选择一个后禁用其他
+        if(val.length==1){
+            if(val[0]*1){
+                let selectindex=0
+                this.treeData.forEach((ele,index)=>{                   
+                    if(ele.children){
+                        ele.children.map((item,ind)=>{
+                                if(item.value==val[0]){
+                                    selectindex=index;
+                                }
+                        })
+                    }                   
+                });
+                // console.log(selectindex)
+                if(selectindex ||selectindex==0){
+                    this.treeData.forEach((ele,index)=>{
+                        if(index!=selectindex){
+                            ele.disableCheckbox = true;
+                            if(ele.children){
+                                ele.children.map((item,ind)=>{
+                                    item.disableCheckbox = true;
+                                })
+                            }
+                        }
+                    })
+                }
+                
+            }else{
+                //  console.log(1)
+                this.treeData.forEach((ele,index)=>{
+                        if(ele.value!=val[0]){
+                            ele.disableCheckbox = true;
+                            
+                            if(ele.children){
+                                ele.children.forEach((item,ind)=>{
+                                    item.disableCheckbox = true;
+                                })
+                            }
+                        }
+                        
+                })
+            }
+            // console.log(this.mediaId)
+            
+        }
+
+            if(val.length==0){
+                this.treeData.forEach((ele,index)=>{              
+                        ele.disableCheckbox = false;
+                        
+                        if(ele.children){
+                            ele.children.forEach((item,ind)=>{
+                                item.disableCheckbox = false;
+                            })
+                        }
+                    
+                });
+                
+            }
+        if(val){
+            val.forEach((ele,index)=>{
+            if(ele*1){
+                this.accountIds.push(ele)
+            }else{              
+                let projectArr=this.treeData.filter((item)=>{
+                    return item.value==ele
+                });
+                // console.log(projectArr)
+                projectArr[0].children.forEach((element)=>{
+                    this.accountIds.push(element.value)
+                })
+            }
+
+
+            })       
+        }
+        
+        console.log(this.accountIds);
+        let LHKaccountInfo=[]
+        this.accountIds.forEach(item=>{
+            this.treeData.forEach(element=>{
+                element.children.forEach(ele=>{
+                if(item==ele.value){
+                    LHKaccountInfo.push(ele)
+                }
+                })
+            })
+        })
+
+        
+        },
+        
+        
+        filterOption(input, option){
+        console.log(input, option)
+        return (
+            option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
+            );
+        },
+    
+        //请求项目和账户内容
+        accountHttp(){
+            this.treeData=[];
+            this.accountIds=[];
+            getAction('/ctop/projectMember/getProjectAccountByUserId?mediaType=1', {}).then(res => {
+            if(res.success){
+                    // console.log(res);
+                    if(res.result){
+                        res.result.forEach((element,index) => {
+                        if(element){                  
+                            this.treeData.push({});                    
+                            this.treeData[index].title=element.project.projectName +'_('+ element.project.advertiserName +')';
+                            this.treeData[index].value='project'+element.project.projectId;
+                            this.treeData[index].key=element.project.projectId;
+                            this.treeData[index].mediaId=element.project.mediaId;
+                            this.treeData[index].children=[];
+                                                
+                            if(element.account.length){
+                            element.account.forEach((ele,i)=>{
+                                this.treeData[index].children.push({});
+                                this.treeData[index].children[i].title=ele.userName+'_'+ele.authName;
+                                this.treeData[index].children[i].value=ele.accountId;
+                                this.treeData[index].children[i].key=ele.accountId;
+                            })
+                                
+                            }                           
+                        }      
+                        });
+                        // console.log(this.treeData)
+                        
+                    }
+            }
+            })
+        },
+
+        //状态改变
+        statusChange(value){
+            console.log(value);
+
+        },
+
+        disabledDate(current) {
+            // console.log(current)
+            return current && current > moment().subtract(1, 'day')
+        },
+
+        dateChange(date, dateString) {
+            console.log(date, dateString);
+            this.dateString=dateString;
+        },
+
+        search(){
+            // console.log(this.accountID,this.dateString,this.statusValue,this.optionId);
+
+            if(this.accountIds.length>0){
+                this.loading=true
+                
+                this.tableListHttp()
+                
+            }else{
+                this.$message.error('请选择账户后重试')
+            }
+
+        },
+
+           //批量操作下的启动 删除 暂停
+        optChange(value){
+            // console.log(value)
+            this.optValue=value;
+        },
+
+         //确定删除
+        confirm(e) {
+            // console.log(e);
+            this.loading=true;
+            if(this.optValue=='delete'){
+                
+                let params=[];
+                params=this.selectedRows.map(item=>{
+                    return {
+                        accountId:record.accountId,
+                        groupId:record.id,
+                        
+                    }
+                })
+            }
+        },
+
+         //批量操作的确定按钮
+        isOkHandle(){
+            console.log(this.optValue,this.selectedRows)
+            if(this.optValue&&this.selectedRowKeys.length>0){
+                let params=[];
+                params=this.selectedRows.map(item=>{
+                    return {
+                        accountId:record.accountId,
+                        groupId:record.id,
+                        optStatus:'DELETE',
+                    }
+                })
+            
+                if(this.optValue=='pause'){   
+                    this.loading=true;
+                    params.forEach(item=>{
+                        item.optStatus='ENABLE';
+                    })
+                    // this.batchEditStatus(params)
+                }else if(this.optValue=='open'){
+                   params.forEach(item=>{
+                        item.optStatus='DISABLED';
+                    })
+                    // this.batchEditStatus(params)
+                }
+              
+                this.batchEditStatus(params)
+                
+            }
+            
+        },
+
+        sort(pagination, filters, sorter, { currentDataSource }){
+            
+            this.ipagination.current=pagination.current;
+
+            this.ipagination.pageSize=pagination.pageSize;
+            this.search()
+        },
+
+        batchEditStatus(params){
+            postAction('/adlab/ctopAdlabProjectDetail/edit',params).then(res=>{
+                console.log(res)
+                if(res.success){
+                    this.$message.success('修改成功');
+                    this.tableListHttp();
+                }else{
+                    this.$message.success('修改失败')
+                }
+            })
+        },
+         //状态改变
+        switchChange(text,record){
+            // this.spinning=true;
+            console.log(text,record);
+            let recordData=JSON.parse(JSON.stringify(record))
+            record.spin=true;
+
+            let params=[];
+            params.push({
+                accountId:record.accountId,
+                groupId:record.id,
+                optStatus:record.optStatus=="DISABLED"?'ENABLE':'DISABLED'
+            })
+            postAction('/adlab/ctopAdlabProjectDetail/edit',params).then(res=>{
+                console.log(res)
+                record.spin=false;
+                if(res.success){
+                    this.$message.success('修改成功');
+                    record.checkedStatus=!record.checkedStatus
+                }else{
+                    this.$message.success('修改失败')
+                }
+            })
+
+        },
+
+        // 新增投放项目
+        addNewProject(){
+            this.$router.push({path:'/LaunchHousekeeper/newProject'})
+        },
+
+        editProject(records){
+            console.log(records);
+            sessionStorage.setItem('editLHKProjectInfo',JSON.stringify(records));
+            this.$router.push({path:'/LaunchHousekeeper/setProjectBudget'})
+        },
+        planAnalysis(records){
+            console.log(records)
+        },
+        deleteProject(records){
+            console.log(records)
+        },
+
+        // 请求账户的列表
+        tableListHttp(){
+            // let accountIds=JSON.stringify(this.accountIds)     
+            // let createTime=JSON.stringify(this.dateString)      
+            postAction('/adlab/ctopAdlabProjectDetail/list',{
+                accountIds:this.accountIds,
+                userId:this.userInfo.value.id,
+                createTime:this.dateString,
+                optStatus:this.statusValue==undefined?0:this.statusValue,
+                name:this.name==undefined?'':this.name,
+                pageNo:this.ipagination.current,
+                pageSize:this.ipagination.pageSize
+            }).then(res=>{
+                console.log(res);
+                this.loading=false;
+                if(res.success){
+                    this.data=res.result.records.map(item=>{
+                        return {
+                            ...item,
+                            spin:false,
+                            checkedStatus:item.optStatus=='DISABLED'?false:true,
+                        }
+                    });
+                    this.ipagination.total=res.result.total;
+
+                    console.log(this.data)
+                }
+            })
+        },
+    },
+    mounted() {
+        this.accountHttp()
+        let userInfo=localStorage.getItem('pro__Login_Userinfo')
+        if(userInfo){
+            this.userInfo=JSON.parse(userInfo)        
+        }
+        this.tableListHttp();
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+.housekeeper{
+    .OptinItem{
+        display: inline-block;
+        margin-right: 15px;
+        .ok{
+            margin-right: 15px;
+        }
+    }
+    .OptinItem:first-child{
+        margin-right: 10px;
+    }
+    .topOptions{
+        padding: 15px 20px;
+        background: white;
+        border-radius: 2px;;
+        .topOpt{
+            width: 100%;
+            margin-bottom: 10px;
+        }
+    }
+    .optionBtn{
+        // display: inline-block;
+        
+        float: right;
+        .searchBtn{
+            margin-right: 10px;
+        }
+    }
+    .tableArea{
+        margin-top: 12px;
+        border-radius: 2px;
+        padding: 0px 20px;
+        background: white;
+        .tableOption{
+            padding: 20px 0;
+        }
+    }
+}
+</style>

File diff suppressed because it is too large
+ 1029 - 0
src/views/modules/LaunchHousekeeper/material.vue


+ 661 - 0
src/views/modules/LaunchHousekeeper/newProject.vue

@@ -0,0 +1,661 @@
+<template>
+  <div class="newPlan">
+    <a-form :form="form">
+      <div class="moduler">
+        <div class="moduler-title">选择账户</div>
+        <div>
+          <div class="row-item">
+            <div class="hint-item"></div>
+            <div class="label-item">
+              <div class="text-item">账户</div>
+              <div class="required-item"></div>
+            </div>
+            <div class="input-item">
+                <a-tree-select
+                    v-model="accountIds"
+                    show-search
+                    style="width: 600px;height:30px"
+                    :dropdownMatchSelectWidth='true'
+                    :dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"              
+                    tree-checkable
+                    searchPlaceholder='请输入账户关键字搜索'
+                    :show-checked-strategy="SHOW_PARENT"
+                    placeholder="请选择项目和账户或搜索账户关键字"
+                    treeNodeFilterProp="title"
+                    :allowClear="true"
+                    @change="treeChange"
+                    @search="treeSearch"
+                    @select="treeSelect"                        
+                    :maxTagCount='1'    
+                    :tree-data="treeData"
+                    :filterOption='filterOption'
+                >
+              
+                </a-tree-select>
+            </div>
+          </div>
+        </div>
+      </div>
+      <!-- 投放范围 -->
+      <div class="moduler">
+        <div class="moduler-title">请选择投放媒体</div>
+        <div class="ad-range">
+          <div class="row-item">
+            <div class="hint-item"></div>
+            <div class="label-item">
+              <div class="text-item">投放媒体</div>
+              <div class="required-item"></div>
+            </div>
+            <div class="input-item">
+              <a-form-item>
+                <a-radio-group v-decorator="['deliveryRange', { initialValue:'DEFAULT' }]">
+                  <a-radio-button value="DEFAULT">默认</a-radio-button>
+                  <a-radio-button value="UNION">
+                    穿山甲
+                    <a-tooltip>
+                      <template slot="title">基于4亿日活跃用户大数据积累,顶尖AI智能推荐技术,今日头条与最广泛的合作伙伴携手打造全新移动生态联盟</template>
+                      <a-icon type="question-circle" />
+                    </a-tooltip>
+                  </a-radio-button>
+                </a-radio-group>
+              </a-form-item>
+            </div>
+          </div>        
+        </div>
+      </div>
+        <!-- 推广目的 -->
+        <div class="moduler">
+            <div class="moduler-title">请选择推广目的</div>
+            
+            <div class="row-item">
+                <div class="hint-item">
+                    <a-tooltip>
+                    <template slot="title">
+                        <span>应用推广:提升应用的下载、安装、激活、付费</span>
+                        <span>销售线索收集:提升销售线索的获取量</span>
+                    </template>
+                    <a-icon type="question-circle" />
+                </a-tooltip>
+                </div>
+                <div class="label-item">
+                <div class="text-item">推广目的</div>
+                <div class="required-item"></div>
+                </div>
+                <div class="input-item">
+                <a-form-item >
+                    <a-radio-group   v-decorator="['landingType',{initialValue:'APP' }]" @change="landingTypeChange">
+                        <a-radio-button value="APP">应用推广</a-radio-button>
+                        <a-radio-button value="LINK">销售线索收集</a-radio-button>                                   
+                    </a-radio-group>
+                    </a-form-item>
+                </div>
+            </div>        
+           
+        </div>
+        <!-- 投放方式 -->
+        <div class="moduler">
+            <div class="moduler-title">请选择投放方式</div>
+            
+            <div class="row-item">
+            <div class="hint-item">
+                <a-tooltip>
+                    <template slot="title">
+                        <span>根据您的投放方式,为您提供包括计划启停、预算分配、出价调整、素材优选等一站式解决方案</span>
+                    </template>
+                    <a-icon type="question-circle" />
+                </a-tooltip>
+            </div>
+            <div class="label-item">
+              <div class="text-item">投放方式</div>
+              <div class="required-item"></div>
+            </div>
+            <div class="input-item">
+              <a-form-item>
+                <a-radio-group v-decorator="['adTarget', { initialValue:'CPA' }]">
+                  <a-radio-button value="CPA" >优先成本</a-radio-button>
+                  <a-radio-button value="COST">优先跑量</a-radio-button>
+                  <a-radio-button value="PUSH">激进抢量</a-radio-button>
+                 </a-radio-group> 
+              </a-form-item>
+            </div>
+          </div>  
+            
+        </div>
+        <!-- 基础信息 -->
+        <div class="moduler">
+            <div class="moduler-title">请设置基本信息</div>
+            
+            <div class="row-item">
+            <div class="hint-item"> </div>
+            <div class="label-item">
+              <div class="text-item">项目名称</div>
+              <div class="required-item"></div>
+            </div>
+            <div class="input-item">
+              <a-form-item>                
+                <a-input v-model="name"  allow-clear />
+               </a-form-item>
+            </div>
+          </div>  
+            
+        </div>
+    
+      <!-- 操作 -->
+      <div class="moduler">
+        <!-- <div class="moduler-title">计划名称</div> -->
+        <div class="opt">
+          <a-button type="default" style="margin-right:15px" @click="goBack">取消</a-button>
+         
+          <a-button type="primary" @click="goNext"  :loading="goNextloading">下一步</a-button>
+        </div>
+      </div>
+    </a-form>
+    <div class="infoModal">
+         <a-modal v-model="visible" title="提示"  @ok="handleOk" :keyboard='false' :maskClosable='false'>
+            <ul>
+              <li v-for="(item,index) in errorInfo" :key="index">
+                  <span>账户id{{item.accountId}}:</span>{{item.message || '创建成功'}}
+              </li>
+            </ul>
+            <template slot="footer">
+              <a-button key="back" @click="handleCancel">
+                返回本页
+              </a-button>
+              <a-button key="submit" type="primary"  @click="handleOk">
+                下一步
+              </a-button>
+            </template>
+          </a-modal>
+    </div>
+  </div>
+</template>
+
+<script>
+import moment from 'moment'
+import { getAction, postAction, downFile, downFilePost } from '@/api/manage'
+
+import { TreeSelect } from 'ant-design-vue';
+import qs from 'qs'
+const SHOW_PARENT = TreeSelect.SHOW_PARENT;
+// import selectCheckAll from './toutiaoTime'
+
+var str = ""
+for (let i = 0; i < 7*48; i++) {
+ str+='0'
+  
+}
+export default {
+  components: {
+    // selectCheckAll,
+    // newDirectedPackage,
+  },
+  data() {
+    return {
+        treeValue: [],
+        treeData: [],
+        SHOW_PARENT,
+        accountIds:[],
+        name: '',
+        form: this.$form.createForm(this),
+
+        goNextloading:false,
+        goPlanShowloading:false,
+        
+        
+        dateRange: [moment(), moment()],
+
+        visible:false,
+        errorInfo:[],
+       
+        validationRules: {
+            url: [   
+            {          
+                required: true,
+                validator: this.validateURL,
+            },
+            ],
+            name:[{
+            required: true,
+            validator: this.validateName,
+            }],
+            bid:[{
+            required: true,
+            message:'出价信息必须填写',
+            // validator: this.validateBid,
+            }],
+            roi:[{
+            required: true,
+            message:'ROI系数必须填写',
+            // validator: this.validateBid,
+            }],
+        },
+        
+    }
+  },
+  watch: {
+    
+  },
+  methods: {
+    // //项目改变后的事件
+    treeChange(val) {
+      // console.log(this.treeData)
+      console.log(val)
+      this.accountIds = [];
+      //选择一个后禁用其他
+      if(val.length==1){
+          if(val[0]*1){
+            let selectindex=0
+              this.treeData.forEach((ele,index)=>{                   
+                  if(ele.children){
+                     ele.children.map((item,ind)=>{
+                            if(item.value==val[0]){
+                                selectindex=index;
+                            }
+                      })
+                  }                   
+              });
+              // console.log(selectindex)
+              if(selectindex ||selectindex==0){
+                this.treeData.forEach((ele,index)=>{
+                    if(index!=selectindex){
+                         ele.disableCheckbox = true;
+                         if(ele.children){
+                              ele.children.map((item,ind)=>{
+                                   item.disableCheckbox = true;
+                              })
+                         }
+                    }
+                })
+              }
+              
+          }else{
+            //  console.log(1)
+              this.treeData.forEach((ele,index)=>{
+                    if(ele.value!=val[0]){
+                         ele.disableCheckbox = true;
+                         
+                         if(ele.children){
+                              ele.children.forEach((item,ind)=>{
+                                   item.disableCheckbox = true;
+                              })
+                         }
+                    }
+                    
+              })
+          }
+          // console.log(this.mediaId)
+          
+      }
+
+        if(val.length==0){
+            this.treeData.forEach((ele,index)=>{              
+                    ele.disableCheckbox = false;
+                    
+                    if(ele.children){
+                        ele.children.forEach((item,ind)=>{
+                            item.disableCheckbox = false;
+                        })
+                    }
+                
+            });
+            
+        }
+      if(val){
+        val.forEach((ele,index)=>{
+          if(ele*1){
+              this.accountIds.push(ele)
+          }else{              
+              let projectArr=this.treeData.filter((item)=>{
+                  return item.value==ele
+              });
+              // console.log(projectArr)
+              projectArr[0].children.forEach((element)=>{
+                 this.accountIds.push(element.value)
+              })
+          }
+
+
+        })       
+      }
+      
+     console.log(this.accountIds);
+      let LHKaccountInfo=[]
+      this.accountIds.forEach(item=>{
+          this.treeData.forEach(element=>{
+            element.children.forEach(ele=>{
+              if(item==ele.value){
+                LHKaccountInfo.push(ele)
+              }
+            })
+          })
+      })
+
+      sessionStorage.setItem('LHKaccountInfo',JSON.stringify(LHKaccountInfo))
+    },
+    treeSearch(){
+    },
+    treeSelect(){
+    },
+    
+    filterOption(input, option){
+      console.log(input, option)
+      return (
+          option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
+        );
+    },
+ 
+
+    //请求项目和账户内容
+    accountHttp(){
+        this.treeData=[];
+        this.accountIds=[];
+        getAction('/ctop/projectMember/getProjectAccountByUserId?mediaType=1', {}).then(res => {
+        if(res.success){
+                // console.log(res);
+                if(res.result){
+                    res.result.forEach((element,index) => {
+                    if(element){                  
+                        this.treeData.push({});                    
+                        this.treeData[index].title=element.project.projectName +'_('+ element.project.advertiserName +')';
+                        this.treeData[index].value='project'+element.project.projectId;
+                        this.treeData[index].key=element.project.projectId;
+                        this.treeData[index].mediaId=element.project.mediaId;
+                        this.treeData[index].children=[];
+                                            
+                        if(element.account.length){
+                        element.account.forEach((ele,i)=>{
+                            this.treeData[index].children.push({});
+                            this.treeData[index].children[i].title=ele.userName+'_'+ele.authName;
+                            this.treeData[index].children[i].value=ele.accountId;
+                            this.treeData[index].children[i].key=ele.accountId;
+                        })
+                            
+                        }                           
+                    }      
+                    });
+                    // console.log(this.treeData)
+                    
+                }
+        }
+        })
+    },
+
+    
+    handleOk(e) {
+        this.visible=false;
+        this.$router.replace({path:'/LaunchHousekeeper/setProjectConvert'})
+        
+        
+    },
+    handleCancel(e) {
+        this.visible = false;
+    },
+    
+   
+    //获取表单的某一个属性值
+    getFormData(className) {
+      return this.form.getFieldValue(className)
+    },
+    dateChange(date, dateString) {
+      // console.log(date,dateString)
+      this.form.getFieldDecorator('startTime')
+      this.form.getFieldDecorator('endTime')
+      this.form.setFieldsValue({
+        startTime: date[0].format('YYYY-MM-DD HH:mm'),
+        endTime:  date[1].format('YYYY-MM-DD HH:mm'),
+      })
+    },
+    
+    //推广目的改变
+    landingTypeChange(e){
+        console.log(e.target)
+        if(e.target.value=='APP'){            
+            this.name=`应用推广_${moment().format('MM_DD_HH:SS')}`           
+        }else if(e.target.value=='LINK'){            
+            this.name=`销售线索收集_${moment().format('MM_DD_HH:SS')}`           
+        }
+    },
+    
+    // 验证网址
+    IsURL(res) {
+      //   var strRegex = /^([hH][tT]{2}[pP]:\/\/|[hH][tT]{2}[pP][sS]:\/\/|www\.)(([A-Za-z0-9-~]+)\.)+([A-Za-z0-9-~\/])+$/
+      var strRegex = /^([hH][tT]{2}[pP]:\/\/|[hH][tT]{2}[pP][sS]:\/\/)(([A-Za-z0-9-~]+)\.)+([A-Za-z0-9-~\/])+(.+[A-Za-z0-9-~\/])+$/
+      var re = new RegExp(strRegex)
+      // console.log(re.test(res))
+      if (re.test(res)) {
+        return true
+      } else {
+        return false
+      }
+    },
+    validateURL(rule, value, callback) {
+      // console.log(rule, value, callback);
+
+      if (this.IsURL(value)) {
+        callback()
+      } else if (value && !this.IsURL(value)) {
+        callback('链接地址无法访问,请正确输入')
+      } else {
+          callback('链接必须填写')
+      }
+    },
+    validateName(rule, value, callback){
+      // console.log(rule, value, callback);
+
+        if (value) {
+          callback()
+        } else {
+              callback('应用包名称必须填写')
+        }
+    },
+    validateBid(rule, value, callback){
+      // console.log(rule, value, callback);
+        if (value) {
+          callback()
+        } else {
+            callback('出价必须填写')
+        }
+    },
+
+   
+    
+    goBack() {
+      this.$router.replace('/modules/LaunchHousekeeper/LaunchHousekeeperList')
+      this.$bus.$emit('remove', '/LaunchHousekeeper/newProject')
+    },
+    
+    // 保存并新建创意
+    goNext() {
+      this.$nextTick(()=>{
+        if (this.name) {
+          this.form.validateFields((err, values) => {
+            if (!err) {
+
+              console.log('Received values of form: ', values)
+              // console.log(this.names)
+              this.goNextloading=true;
+              values.accountIds = this.accountIds
+              values.name=this.name
+              postAction('/adlab/Project/create', {                
+                ...values,
+              }).then((res) => {
+                console.log(res)
+                if (res.success) {
+                  this.goNextloading=false;
+                
+                    if(res.result){
+                        this.errorInfo=res.result;
+                        this.visible=true;
+
+                        let projectInfo=[]
+                        res.result.forEach(item=>{
+                            if(item.code==0){
+                              projectInfo.push(item)
+                            }
+                        })
+
+                        sessionStorage.setItem('projectInfo',JSON.stringify(projectInfo))
+                    }
+                 
+                } else {
+                   this.goNextloading=false;
+                  this.$message.error('网络开小差了,等会再试试')
+                }
+              })
+            }else{
+              this.$message.error('请正确填写必填项目')
+            }
+          })
+        }else{
+            this.$message.error('请输入投放项目名称')
+        }
+      })
+      
+    },
+    
+
+    
+  },
+  
+  mounted() {
+    this.accountHttp()
+    // this.$bus.$emit('remove', '/modules/BatchCreate/newGroup')
+    let namepart='';
+    if(this.getFormData('landingType')=='APP'){
+        namepart='应用推广'
+    }else{
+        namepart='销售线索收集'
+    }
+    
+    this.name ='[项目]'+ namepart + moment().format('MM_DD_hh:mm') ;
+
+    
+  },
+}
+</script>
+<style lang="scss">
+.newPlan{
+  .ant-btn-danger {
+    background-color: #ff4d4f !important; 
+  }
+}
+
+
+.ant-tooltip-inner,
+.ant-tooltip,
+.ant-tooltip-arrow::before {
+  background-color: #fff;
+  color: #333;
+}
+.ant-tooltip-inner {
+  span {
+    display: block;
+  }
+}
+.ant-tooltip {
+  max-width: 450px;
+}
+.newPlan {
+  .ant-radio-button-wrapper {
+    min-width: 80px;
+    text-align: center;
+  }
+  .ant-form-item {
+    -webkit-box-sizing: border-box;
+    box-sizing: border-box;
+    margin: 0;
+    padding: 0;
+    color: rgba(0, 0, 0, 0.65);
+    font-size: 14px;
+    font-variant: tabular-nums;
+    line-height: 1.5;
+    list-style: none;
+    -webkit-font-feature-settings: 'tnum';
+    font-feature-settings: 'tnum';
+    vertical-align: top;
+  }
+  .directedBody {
+    .ant-form-item {
+      margin-bottom: 20px;
+    }
+  }
+}
+</style>
+<style lang="scss" scoped>
+.newPlan {
+  font-family: PingFangSC-Regular, tahoma, arial, 'Hiragino Sans GB', 'Microsoft yahei', sans-serif;
+  color: #333;
+  ul,
+  li {
+    margin: 0;
+    padding: 0;
+  }
+  .moduler {
+    background: #fff;
+    margin-bottom: 16px;
+    position: relative;
+    padding: 32px 24px 48px 32px;
+    border-radius: 4px;
+    box-shadow: 0px 1px 6px 0px rgba(0, 0, 0, 0.05);
+    .moduler-title {
+      display: flex;
+      align-items: center;
+      font-size: 22px;
+      margin-bottom: 20px;
+    }
+    .row-item {
+      display: flex;
+      justify-content: flex-start;
+      align-items: center;
+      margin-bottom: 32px;
+    }
+    .row-item:last-of-type {
+      margin-bottom: 0;
+    }
+    .row-item .hint-item {
+      width: 24px;
+      min-width: 24px;
+      align-self: flex-start;
+      line-height: 20px;
+      height: 20px;
+      margin-top: 5px;
+    }
+    .row-item .label-item {
+      position: relative;
+      align-items: flex-start;
+      align-self: flex-start;
+      line-height: 20px;
+      height: 20px;
+      margin-top: 7px;
+      width: 80px;
+      min-width: 80px;
+      .text-item {
+        font-size: 14px;
+        width: 60px;
+      }
+    }
+    .row-item .required-item {
+      width: 4px;
+      height: 4px;
+      border-radius: 2px;
+      background: #f45858;
+      position: absolute;
+      right: 10px;
+      top: 50%;
+      transform: translateY(-50%);
+    }
+    .row-item .input-item {
+      min-width: 480px;
+      position: relative;
+      // height: 35px;
+      .tip {
+        font-size: 12px;
+        color: tomato;
+      }
+    }
+  }
+  .opt {
+    text-align: right;
+  }
+}
+</style>

+ 237 - 0
src/views/modules/LaunchHousekeeper/radioCheck.vue

@@ -0,0 +1,237 @@
+<template>
+    <div class="radioCheck" >
+        
+            <label :class="{'item':true,'selection': selectValue.indexOf(item.value)>-1,'bgcolor':item.disabled}" v-for="(item,index) in checkArr" :key="index">
+                
+                <span>
+                    <input type="checkbox" :value="item.value"  class="checkbox-button-input" @click="radioCheckChange($event,item)">
+                </span>
+                <span>{{item.title}}</span>
+                
+            </label>
+            <!-- <label :class="{'item':true,'selection': selectValue.indexOf(item.value)>-1}" v-for="(item,index) in checkArr" :key="index" :disabled='item.disabled'>               
+                <span>
+                    <input type="checkbox" :value="item.value"  class="checkbox-button-input" @click="radioCheckChange">
+                </span>
+                <span>{{item.title}}</span>               
+            </label>        -->
+    </div>
+</template>
+
+<script>
+export default {
+    data() {
+        return {
+            selectValue:[''],
+            currentSelect:'',
+        }
+    },
+   
+    props:['checkArr','selectArr'],
+    watch:{
+        checkArr:{
+            handler(n,o){
+                // console.log(n,o)
+                this.selectValue=[];
+                let i=0;
+                this.checkArr.forEach((item,index)=>{
+                    // console.log(item)
+                    if(item.disabled==false){
+                        i++;
+                        this.selectValue[0]=item.value;
+                        // console.log(this.selectValue)
+                    }else if(item.disabled==undefined){
+                        if(item.checked){
+                            this.selectValue.push(item.value)
+                        }
+                        
+                    }
+                })
+                if(this.selectValue.length==0){
+                    this.selectValue=[''];
+                }
+                if(i==3){
+                    this.selectValue[0]='';
+                }
+                // console.log(this.selectValue)
+                this.$emit('getSonValue',this.selectValue)
+            },
+            deep:true,
+            // immediate: true
+
+        },
+        
+    },
+    methods: {
+        //单选多选的事件
+        radioCheckChange(e,item){
+            console.log(e.target,item,!item.disabled);
+            
+            this.currentSelect=e.target.value;
+            if(!item.disabled){
+
+                if(e.target.value=='' || this.selectValue.length==0 ){
+                    this.selectValue=[''];
+                }else{
+                    if(this.selectValue.indexOf('')>-1){
+                        let i=this.selectValue.indexOf('');
+                        this.selectValue.splice(0,1)
+                    }
+                    
+                    if(this.selectValue.indexOf(e.target.value)==-1){
+                        this.selectValue.push(e.target.value)
+                    }else if(this.selectValue.indexOf(e.target.value)>-1){
+                        this.selectValue=this.selectValue.filter((item)=>{
+                            return item!=e.target.value
+                        })  
+                    }
+
+                    if(this.selectValue.length==0){
+                        this.selectValue=[''];
+                    }
+                    
+                }
+            // console.log(this.currentSelect,this.selectValue);
+            }
+            this.$emit('getSonValue',this.selectValue)
+        },
+    },
+    mounted() {
+        // this.selectValue=[]
+        // console.log(this.checkArr)
+        this.checkArr.forEach((item,index)=>{
+            
+            if(item.disabled&&item.disabled!=undefined){
+                this.selectValue[0]=item.value
+            }else{
+                this.selectValue=['']
+            }
+        })
+        this.$emit('getSonValue',this.selectValue)
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+.radioCheck{        
+    border-radius: 5px;
+    height: 32px;
+    padding: 0;
+    margin: 0;
+    border: none;
+    background: transparent;
+    .btn{
+        background: transparent;
+        padding: 0;
+        margin: 0;
+        border: none;
+    }
+    .item{
+        min-width: 80px;
+        padding: 0px 15px;
+        text-align: center;
+        display: inline-block;
+        border: 1px solid #ccc;
+        border-left: 0;
+        height: 32px;
+        line-height: 32px;
+        cursor: pointer;
+        .checkbox-button-input{
+            width: 0;
+            height: 0;
+            opacity: 0;
+        }
+
+    }
+    .bgcolor{
+        color:rgba(0, 0, 0, 0.25);
+        background-color: #f5f5f5;
+        border-color: #d9d9d9;
+        cursor: not-allowed;
+    }
+    .item::after{
+        content: "";
+        position: absolute;
+        right: 1px;
+        top: -2px;
+        width: 0;
+        height: 0;
+        border-top: 6px solid transparent;
+        border-bottom: 6px solid transparent;
+        border-left: 6px solid;
+        border-left-color: #e0e0e0;
+        -webkit-transform: rotate(-45deg);
+        -ms-transform: rotate(-45deg);
+        transform: rotate(-45deg);
+        border-radius: 2px;
+    }
+    .item:hover{
+        color: #1890ff;
+    }
+    .selection{
+        color: #1890ff;
+        background: #fff;
+        border-color: #1890ff;
+    }
+    .item.selection:hover{
+        // color: #1890ff;
+        color: #40a9ff;
+        background: #fff;
+        border-color: #40a9ff;
+    }
+    .item.selection:after{
+        border-left: 6px solid #1890ff;
+    }
+    .item:hover::after{
+        // border-color: #40a9ff;
+        border-left: 6px solid #40a9ff;
+    }
+    .bgcolor:hover{
+        color:rgba(0, 0, 0, 0.25);
+        background-color: #f5f5f5;
+        border-color: #d9d9d9;
+        cursor: not-allowed;
+    }
+    .bgcolor:hover::after{
+        // border-color: #40a9ff;
+        border-left: 6px solid #e0e0e0;
+    }
+    .bgcolor.selection:after{
+        border-left: 6px solid #e0e0e0;
+    }
+    .bgcolor.selection{
+        color:rgba(0, 0, 0, 0.25);
+        background-color: #f5f5f5;
+        border-color: #d9d9d9;
+        cursor: not-allowed;
+    }
+    .bgcolor.selection:hover{
+        // color: #1890ff;
+        color:rgba(0, 0, 0, 0.25);
+        background-color: #f5f5f5;
+        border-color: #d9d9d9;
+        cursor: not-allowed;
+    }
+    .bgcolor.selection:after{
+        border-left: 6px solid #e0e0e0;
+    }
+}
+.radioCheck .item:first-child {
+    border-radius: 5px 0 0 5px;
+    border-left: 1px solid #ccc;
+}
+.radioCheck .item.selection:first-child {
+    border-radius: 5px 0 0 5px;
+    border-left: 1px solid #1890ff;
+}
+.radioCheck .item.selection:nth-child(2) {
+    
+    border-left: 1px solid #1890ff;
+}
+.radioCheck .item:first-child:after{
+    border-left: 0;
+}
+.radioCheck .item:last-child {
+    border-radius: 0px 5px 5px 0px;
+}
+</style>

+ 620 - 0
src/views/modules/LaunchHousekeeper/setProjectBudget.vue

@@ -0,0 +1,620 @@
+<template>
+  <div class="newPlan">
+    
+    <div class="moduler">
+        <div v-if="projectInfo.length>0">
+         <span style="margin-right:8px"> 项目:<strong>{{projectInfo[0].name||''}}</strong></span>
+         <span style="margin-right:8px"> 推广目的:<strong>{{projectInfo[0].landingType=='APP'?'应用推广':'销售线索收集'||''}}</strong></span>
+         <span style="margin-right:8px"> 投放媒体:<strong>{{projectInfo[0].deliveryRange=="DEFAULT"?'默认':'穿山甲'||''}}</strong></span>
+         <span style="margin-right:8px"> 投放方式:
+             <strong v-if="projectInfo[0].adTarget=='CPA'">优先成本</strong>
+             <strong v-if="projectInfo[0].adTarget=='COST'">优先跑量</strong>
+             <strong v-if="projectInfo[0].adTarget=='PUSH'">激进抢量</strong>
+        </span>
+          
+        </div>
+    </div>
+   
+        
+        <div class="moduler">
+            
+            <a-form :form="form">
+                <div class="moduler-title">预算与出价</div>
+                <div class="ad-range">
+                    <div class="row-item" >
+                        <div class="hint-item"></div>
+                        <div class="label-item">
+                        <div class="text-item">投放时间</div>
+                        <!-- <div class="required-item"></div> -->
+                        </div>
+                        <div class="input-item">
+                        <a-form-item>
+                            <a-radio-group v-decorator="['scheduleType', { initialValue:'SCHEDULE_FROM_NOW' }]">
+                            <a-radio-button value="SCHEDULE_FROM_NOW">从今天起长期投放</a-radio-button>
+                            <a-radio-button value="SCHEDULE_START_END">设置开始和结束时间</a-radio-button>
+                            </a-radio-group>
+                            <p style="margin-top:15px">
+                            <a-range-picker
+                                @change="dateChange"
+                                v-model="dateRange"
+                                v-if="getFormData('scheduleType')=='SCHEDULE_START_END'"
+                            />
+                            </p>
+                        </a-form-item>
+                        </div>
+                    </div>
+                    <div class="row-item">
+                        <div class="hint-item"></div>
+                        <div class="label-item">
+                        <div class="text-item">投放时段</div>
+                        <!-- <div class="required-item"></div> -->
+                        </div>
+                        <div class="input-item">
+                        <a-form-item>
+                            <a-radio-group v-decorator="['scheduleTime', { initialValue:'' }]">
+                            <a-radio-button value=''>不限</a-radio-button>
+                            <a-radio-button value="SpecifiedTImePeriod">指定时间段</a-radio-button>
+                            </a-radio-group>
+                            <div
+                            v-show="getFormData('scheduleTime')=='SpecifiedTImePeriod'"
+                            style="margin-top:15px"
+                            >
+                            <selectCheckAll
+                                style="width:100%"
+                                :scheduleTime.sync="scheduleTimeData"
+                                ref="selectCheck"
+                            />
+                            </div>
+                        </a-form-item>
+                        </div>
+                    </div>
+                    <div class="row-item">
+                      <div class="hint-item">
+                        <a-tooltip>
+                          <template slot="title">
+                            <span>单次预算修改幅度不小于100元,日修改预算不超过20次。如果是总预算广告,且设了起始日期,将要求您预算设置需要大于或等于[投放天数 * 100],即满足每日最低预算300的要求</span>
+                          </template>
+                          <a-icon type="question-circle" />
+                        </a-tooltip>
+                      </div>
+                      <div class="label-item">
+                        <div class="text-item">预算</div>
+                        <div class="required-item"></div>
+                      </div>
+                      <div class="input-item">
+                        <a-form-item>
+                          <a-input-group compact>
+                            <a-select :disabled="true" v-decorator="['budgetMode', { initialValue:'BUDGET_MODE_DAY' }]">
+                              <a-select-option value="BUDGET_MODE_DAY" >日预算</a-select-option>
+                              <!-- <a-select-option
+                                value="BUDGET_MODE_TOTAL"
+                                v-if="getFormData('smartBidType')=='SMART_BID_CUSTOM'"
+                              >总预算</a-select-option> -->
+                            </a-select>
+                            <a-input style="width: 25%" v-decorator="['budget', { initialValue:300 }]" />
+                          </a-input-group>
+                          <span class="tip" v-if="getFormData('budget')<300">请输入预算,不少于300元,不超过9999999.99元</span>
+                        </a-form-item>
+                      </div>
+                    </div>
+                    <div class="row-item" >
+                        <div class="hint-item"></div>
+                        <div class="label-item">
+                        <div class="text-item">付费方式</div>
+                        <div class="required-item"></div>
+                        </div>
+                        <div class="input-item">
+                        <a-form-item>
+                            <a-radio-group v-decorator="['pricing', { initialValue:'PRICING_OCPM' }]">
+                              <a-radio-button value="PRICING_OCPM" >按展示付费(oCPM)</a-radio-button>
+                              <!-- <a-radio-button value="PRICING_CPC" >按点击付费(CPC)</a-radio-button>
+                              <a-radio-button value="PRICING_CPM" >按展示付费(CPM)</a-radio-button>
+                              <a-radio-button value="PRICING_CPA">按转化付费(CPA)</a-radio-button>
+                              <a-radio-button  value="PRICING_OCPC">按点击付费(oCPC)</a-radio-button> -->
+                            </a-radio-group>
+                        </a-form-item>
+                        </div>
+                    </div>
+                    <div class="row-item" >
+                      <div class="hint-item">
+                        <a-tooltip>
+                          <template slot="title">
+                            <span>请填入您当前预算下,每个转化事件的真实预期成本,预期成本过低可能影响模型的优化能力。此成本仅作为投放参考,实际扣费仍以后台展示为准。</span>
+                          </template>
+                          <a-icon type="question-circle" />
+                        </a-tooltip>
+                      </div>
+                      <div class="label-item">
+                        <div class="text-item">预期成本</div>
+                        <div class="required-item"></div>
+                      </div>
+                      <div class="input-item">
+                        <a-form-item>
+                          <a-input-number
+                            style="width:200px"
+                            :max="1500"
+                            :step="0.1"
+                            v-decorator="['bid', {rules:validationRules.bid} ]"
+                          />
+                          <span style="margin-left:5px">元</span>
+                          <!-- <span style="margin-left:20px">请填入必填字段,获取建议出价</span> -->
+                        </a-form-item>
+                        <span
+                          class="tip"
+                          v-if="getFormData('bid')<0.1"
+                        >请输入预期成本,不少于0.1元,不超过10000元</span>
+                      </div>
+                    </div>
+
+                    <div class="row-item" >
+                      <div class="hint-item"> </div>
+                      <div class="label-item">
+                        <div class="text-item">深度优化方式</div>
+                        <div class="required-item"></div>
+                      </div>
+                      <div class="input-item">
+                        <a-form-item>
+                          <a-radio-group
+                            v-decorator="['deepBidType', { initialValue:'DEEP_BID_MIN' }]"
+                          >                            
+                            <a-radio-button value="DEEP_BID_MIN" >自定义双出价</a-radio-button>
+                          </a-radio-group>
+                        </a-form-item>
+                      </div>
+                    </div>
+                    <div class="row-item" >
+                      <div class="hint-item"> </div>
+                      <div class="label-item">
+                        <div class="text-item">深度转化出价</div>
+                        <div class="required-item"></div>
+                      </div>
+                      <div class="input-item">
+                        <a-form-item>
+                          <a-input-number
+                            style="width:200px"
+                            :max="10000"
+                            :step="0.1"
+                            :min='0.1'
+                            v-decorator="['deepBid', {rules:validationRules.bid} ]"                 
+                          />
+          
+                          <span style="margin-left:5px">元</span>
+                        </a-form-item>
+                        <span
+                          class="tip"
+                          v-if="getFormData('pricing')!='PRICING_CPA'&&getFormData('deepCpabid')<0.1"
+                        >请输入深度转化出价,不少于0.1元,不超过10000元</span>
+                      </div>
+                    </div>
+                    <div class="row-item">
+                        <div class="hint-item"></div>
+                        <div class="label-item">
+                        <div class="text-item">超成本自动暂停</div>
+                        <div class="required-item"></div>
+                        </div>
+                        <div class="input-item">
+                        <a-form-item>
+                            <a-radio-group v-decorator="['autoStop', { initialValue:0 }]">
+                              <a-radio-button :value="1">开启</a-radio-button>
+                              <a-radio-button :value="0">关闭</a-radio-button>
+                            </a-radio-group>
+                        </a-form-item>
+                        </div>
+                    </div>
+                </div>
+            </a-form>  
+        </div>
+            
+            <!-- 当前账户 -->
+            <div class="moduler">
+                <div class="adName">
+                    <span>当前账户:</span> 
+                    <div class="nameList">
+                        <strong v-for="item in LHKaccountInfo" :key="item.value" class="item">{{item.title+'('+item.value+')'}}</strong>
+                    </div>
+                </div>
+            </div>
+            <!-- 操作 -->
+            <div class="moduler">
+                <!-- <div class="moduler-title">计划名称</div> -->
+                <div class="opt">
+                <a-button type="default" style="margin-right:15px" @click="goBack">取消</a-button>
+                
+                <a-button type="primary" @click="goNext"  :loading="goNextloading">下一步</a-button>
+                </div>
+            </div>
+        
+      <!-- 投放链接 -->
+    
+    <div class="infoModal">
+         <a-modal v-model="visible" title="提示"  @ok="handleOk" :keyboard='false' :maskClosable='false'>
+            <ul>
+              <li v-for="(item,index) in errorInfo" :key="index">
+                  <span>账户{{LHKaccountInfo[index].title}}:</span>{{item.message || '设置转化信息成功'}}
+              </li>
+            </ul>
+            <template slot="footer">
+              <a-button key="back" @click="handleCancel">
+                返回本页
+              </a-button>
+              <a-button key="submit" type="primary"  @click="handleOk">
+                下一步
+              </a-button>
+            </template>
+          </a-modal>
+    </div>
+  </div>
+</template>
+
+<script>
+import moment from 'moment'
+import { getAction, postAction, downFile, downFilePost } from '@/api/manage'
+import selectCheckAll from '../BatchCreate/toutiaoTime'
+import qs from 'qs'
+var str = ""
+for (let i = 0; i < 7*48; i++) {
+ str+='0'
+  
+}
+export default {
+  components: {
+    selectCheckAll,
+    // newDirectedPackage,
+  },
+  data() {
+    return {
+        projectInfo:[],
+        LHKaccountInfo:[],
+        
+        form: this.$form.createForm(this),
+
+        showIndex:0,
+
+        goNextloading:false,
+        goPlanShowloading:false,
+        
+        
+        dateRange: [moment(), moment()],
+        scheduleTime: '',
+        scheduleTimeData:str,
+
+        visible:false,
+        errorInfo:[],
+       
+        validationRules: {
+            url: [   
+            {          
+                required: true,
+                validator: this.validateURL,
+            },
+            ],
+            name:[{
+            required: true,
+            validator: this.validateName,
+            }],
+            bid:[{
+            required: true,
+            message:'出价信息必须填写',
+            // validator: this.validateBid,
+            }],
+            roi:[{
+            required: true,
+            message:'ROI系数必须填写',
+            // validator: this.validateBid,
+            }],
+        },
+
+        currentConvertTypes:[],
+        convertIds:[],
+    }
+  },
+  watch: {
+    
+  },
+  methods: {
+    
+    callback(val) {
+      console.log(val);
+    },
+
+    
+    
+    handleOk(e) {
+        this.visible=false;
+      // this.$router.push('/LaunchHousekeeper/setProjectDirectional')
+        this.$router.push({path:'/LaunchHousekeeper/setProjectDirectional'})
+        this.$bus.$emit('remove', '/LaunchHousekeeper/setProjectConvert')
+        
+    },
+    handleCancel(e) {
+        this.visible = false;
+    },
+   
+   
+    
+   
+    //获取表单的某一个属性值
+    getFormData(className) {
+      return this.form.getFieldValue(className)
+    },
+    dateChange(date, dateString) {
+      // console.log(date,dateString)
+      this.form.getFieldDecorator('startTime')
+      this.form.getFieldDecorator('endTime')
+      this.form.setFieldsValue({
+        startTime: date[0].format('YYYY-MM-DD HH:mm'),
+        endTime:  date[1].format('YYYY-MM-DD HH:mm'),
+      })
+    },
+    
+    
+    
+    
+    // 验证网址
+    IsURL(res) {
+      //   var strRegex = /^([hH][tT]{2}[pP]:\/\/|[hH][tT]{2}[pP][sS]:\/\/|www\.)(([A-Za-z0-9-~]+)\.)+([A-Za-z0-9-~\/])+$/
+      var strRegex = /^([hH][tT]{2}[pP]:\/\/|[hH][tT]{2}[pP][sS]:\/\/)(([A-Za-z0-9-~]+)\.)+([A-Za-z0-9-~\/])+(.+[A-Za-z0-9-~\/])+$/
+      var re = new RegExp(strRegex)
+      // console.log(re.test(res))
+      if (re.test(res)) {
+        return true
+      } else {
+        return false
+      }
+    },
+    validateURL(rule, value, callback) {
+      // console.log(rule, value, callback);
+
+      if (this.IsURL(value)) {
+        callback()
+      } else if (value && !this.IsURL(value)) {
+        callback('链接地址无法访问,请正确输入')
+      } else {
+          callback('链接必须填写')
+      }
+    },
+    validateName(rule, value, callback){
+      // console.log(rule, value, callback);
+
+        if (value) {
+          callback()
+        } else {
+              callback('应用包名称必须填写')
+        }
+    },
+    validateBid(rule, value, callback){
+      // console.log(rule, value, callback);
+        if (value) {
+          callback()
+        } else {
+            callback('出价必须填写')
+        }
+    },
+
+   
+    
+    goBack() {
+      this.$router.replace('/modules/LaunchHousekeeper/LaunchHousekeeperList')
+      this.$bus.$emit('remove', '/LaunchHousekeeper/setProjectConvert')
+    },
+    
+    // 保存并新建创意
+    goNext() {
+      this.$nextTick(()=>{
+        
+          this.form.validateFields((err, values) => {
+            if (!err) {
+
+              console.log('Received values of form: ', values)
+              
+              this.goNextloading=true;
+              if(this.getFormData('scheduleTime')!=''){
+                  values.weekTime=this.scheduleTimeData
+              }
+              
+              values.startTime=this.dateRange[0].format('YYYY-MM-DD HH:mm');
+              values.endTime= this.dateRange[1].format('YYYY-MM-DD HH:mm');
+
+              let params=[];
+              params=this.projectInfo.map((item,index)=>{
+                return {
+                  ...item,
+                  ...values,
+                }
+              })
+              console.log(values)
+              postAction('/adlab/Project/setBudget', params).then((res) => {
+                console.log(res)
+                if (res.success) {
+                  this.goNextloading=false;
+                
+                    if(res.result){
+                        // this.errorInfo=res.result;
+                        // this.visible=true;
+
+                        // let projectInfo=[]
+                        // res.result.forEach(item=>{
+                        //     if(item.code==0){
+                        //       projectInfo.push(item)
+                        //     }
+                        // })
+
+                        //  sessionStorage.setItem('projectInfo',JSON.stringify(projectInfo))
+                    }
+                 
+                } else {
+                   this.goNextloading=false;
+                  this.$message.error(res.message)
+                }
+              })
+            }else{
+              this.$message.error('请正确填写必填项目')
+            }
+          })
+        
+      })
+      
+    },
+    
+    EchoPageInfo(){
+
+    },
+    
+  },
+  
+  mounted() {
+      this.$bus.$emit('remove', '/LaunchHousekeeper/setProjectCreate')
+        let projectInfo=sessionStorage.getItem('projectInfo');
+        if(projectInfo){
+            this.projectInfo=JSON.parse(projectInfo)
+        }
+        let LHKaccountInfo=sessionStorage.getItem('LHKaccountInfo');
+        if(LHKaccountInfo){
+            this.LHKaccountInfo=JSON.parse(LHKaccountInfo)
+        }
+        let editLHKProjectInfo=sessionStorage.getItem('editLHKProjectInfo');
+        if(editLHKProjectInfo){
+          this.LHKaccountInfo.push(editLHKProjectInfo);
+        }
+        
+  },
+}
+</script>
+<style lang="scss">
+.newPlan{
+  .ant-btn-danger {
+    background-color: #ff4d4f !important; 
+  }
+}
+
+
+.ant-tooltip-inner,
+.ant-tooltip,
+.ant-tooltip-arrow::before {
+  background-color: #fff;
+  color: #333;
+}
+.ant-tooltip-inner {
+  span {
+    display: block;
+  }
+}
+.ant-tooltip {
+  max-width: 450px;
+}
+.newPlan {
+  .ant-radio-button-wrapper {
+    min-width: 80px;
+    text-align: center;
+  }
+  .ant-form-item {
+    -webkit-box-sizing: border-box;
+    box-sizing: border-box;
+    margin: 0;
+    padding: 0;
+    color: rgba(0, 0, 0, 0.65);
+    font-size: 14px;
+    font-variant: tabular-nums;
+    line-height: 1.5;
+    list-style: none;
+    -webkit-font-feature-settings: 'tnum';
+    font-feature-settings: 'tnum';
+    vertical-align: top;
+  }
+  .directedBody {
+    .ant-form-item {
+      margin-bottom: 20px;
+    }
+  }
+}
+</style>
+<style lang="scss" scoped>
+.newPlan {
+  font-family: PingFangSC-Regular, tahoma, arial, 'Hiragino Sans GB', 'Microsoft yahei', sans-serif;
+  color: #333;
+  ul,
+  li {
+    margin: 0;
+    padding: 0;
+  }
+  .moduler {
+    background: #fff;
+    margin-bottom: 16px;
+    position: relative;
+    padding: 32px 24px 48px 32px;
+    border-radius: 4px;
+    box-shadow: 0px 1px 6px 0px rgba(0, 0, 0, 0.05);
+    .moduler-title {
+      display: flex;
+      align-items: center;
+      font-size: 22px;
+      margin-bottom: 20px;
+    }
+    .row-item {
+      display: flex;
+      justify-content: flex-start;
+      align-items: center;
+      margin-bottom: 32px;
+    }
+    .row-item:last-of-type {
+      margin-bottom: 0;
+    }
+    .row-item .hint-item {
+      width: 24px;
+      min-width: 24px;
+      align-self: flex-start;
+      line-height: 20px;
+      height: 20px;
+      margin-top: 5px;
+    }
+    .row-item .label-item {
+      position: relative;
+      align-items: flex-start;
+      align-self: flex-start;
+      line-height: 20px;
+      height: 20px;
+      margin-top: 7px;
+      width: 80px;
+      min-width: 80px;
+      .text-item {
+        font-size: 14px;
+        width: 60px;
+      }
+    }
+    .row-item .required-item {
+      width: 4px;
+      height: 4px;
+      border-radius: 2px;
+      background: #f45858;
+      position: absolute;
+      right: 10px;
+      top: 50%;
+      transform: translateY(-50%);
+    }
+    .row-item .input-item {
+      min-width: 480px;
+      position: relative;
+      // height: 35px;
+      .tip {
+        font-size: 12px;
+        color: tomato;
+      }
+    }
+    .adName{
+      display: flex;
+      .nameList{
+        width: 90%;
+      }
+      .item{
+        display: inline-block;
+        width: 30%;
+        margin-left: 15px;
+        margin-bottom: 10px;
+      }
+    }
+  }
+  .opt {
+    text-align: right;
+  }
+}
+</style>

+ 697 - 0
src/views/modules/LaunchHousekeeper/setProjectConvert.vue

@@ -0,0 +1,697 @@
+<template>
+  <div class="newPlan">
+    
+    <div class="moduler">
+        <div v-if="projectInfo.length>0">
+         <span style="margin-right:8px"> 项目:<strong>{{projectInfo[0].name||''}}</strong></span>
+         <span style="margin-right:8px"> 推广目的:<strong>{{projectInfo[0].landingType=='APP'?'应用推广':'销售线索收集'||''}}</strong></span>
+         <span style="margin-right:8px"> 投放媒体:<strong>{{projectInfo[0].deliveryRange=="DEFAULT"?'默认':'穿山甲'||''}}</strong></span>
+         <span style="margin-right:8px"> 投放方式:
+             <strong v-if="projectInfo[0].adTarget=='CPA'">优先成本</strong>
+             <strong v-if="projectInfo[0].adTarget=='COST'">优先跑量</strong>
+             <strong v-if="projectInfo[0].adTarget=='PUSH'">激进抢量</strong>
+        </span>
+          
+        </div>
+    </div>
+   
+        
+        <div class="moduler">
+            
+            <a-form :form="form">
+                <div class="moduler-title">投放链接</div>
+                <div class="ad-range">
+                    <div class="row-item">
+                        <div class="hint-item"></div>
+                        <div class="label-item">
+                            <div class="text-item">下载方式</div>              
+                            <div class="required-item"></div>
+                        </div>
+                        <div class="input-item">
+                            <a-form-item>
+                                <a-radio-group
+                                v-decorator="['downloadType',{ initialValue:'DOWNLOAD_URL' }]"
+                                v-if="projectInfo.length>0&&projectInfo[0].landingType=='APP'"  @change="downloadTypeChange">
+                                    <a-radio-button value="DOWNLOAD_URL">下载链接</a-radio-button>
+                                    <a-radio-button value="EXTERNAL_URL">落地页</a-radio-button>
+                                </a-radio-group>
+                            </a-form-item>
+                        </div>
+                    </div>    
+                    <div class="row-item">
+                        <div class="hint-item"></div>
+                        <div class="label-item">
+                            <div class="text-item">投放平台</div>              
+                            <div class="required-item"></div>
+                        </div>
+                        <div class="input-item">
+                            <a-form-item>
+                                <a-radio-group v-decorator="['appType', { initialValue:'APP_IOS' }]" @change="appTypeChange">
+                                <a-radio-button value="" v-if="getFormData('downloadType')=='EXTERNAL_URL'">不限</a-radio-button>
+                                <a-radio-button value="APP_IOS">IOS</a-radio-button>
+                                <a-radio-button value="APP_ANDROID">安卓</a-radio-button>
+                                
+                                </a-radio-group>
+                            </a-form-item>
+                        </div>
+                    </div>    
+                    <div class="row-item">
+                        <div class="hint-item"></div>
+                        <div class="label-item">
+                            <div class="text-item">链接地址</div>              
+                            <div class="required-item"></div>
+                        </div>
+                        <div class="input-item">
+                            <a-form-item>
+                                <a-input v-decorator="['url', {rules:validationRules.url}]" />
+                            </a-form-item>
+                        </div>
+                    </div>    
+                    <div class="row-item" v-if="getFormData('downloadType')=='DOWNLOAD_URL'&&getFormData('appType')=='APP_ANDROID'">
+                        <div class="hint-item"></div>
+                        <div class="label-item">
+                        <div class="text-item">应用包名</div>
+                        <div class="required-item"></div>
+                        </div>
+                        <div class="input-item">
+                        <a-form-item>
+                            <a-input v-decorator="['adlabPackage', {rules:validationRules.name}]" />
+                        </a-form-item>
+                        </div>
+                    </div>
+                    <div class="row-item" v-if="getFormData('downloadType')=='DOWNLOAD_URL'&&getFormData('appType')=='APP_ANDROID'">
+                        <div class="hint-item"></div>
+                        <div class="label-item">
+                        <div class="text-item">应用下载详情页</div>
+                        <div class="required-item"></div>
+                        </div>
+                        <div class="input-item">
+                        <a-form-item>
+                            <a-input v-decorator="['webUrl', {rules:validationRules.url}]" />
+                        </a-form-item>
+                        </div>
+                    </div>
+                    <div class="row-item" v-show="getFormData('downloadType')=='EXTERNAL_URL'">
+                        <div class="hint-item"></div>
+                        <div class="label-item">
+                        <div class="text-item">直达链接</div>
+                        <div class="required-item"></div>
+                        </div>
+                        <div class="input-item">
+                        <a-form-item>
+                            <a-radio-group v-decorator="['useOpenUrl', { initialValue:'NO' }]" @change="useOpenUrlChange">
+                            <a-radio-button value="NO">不启用</a-radio-button>
+                            <a-radio-button value="YES">启用</a-radio-button>
+                            </a-radio-group>
+                        </a-form-item>
+                        </div>
+                    </div>
+                    <div class="row-item" v-show="getFormData('downloadType')=='EXTERNAL_URL'&&getFormData('useOpenUrl')=='YES'">
+                        <div class="hint-item"></div>
+                        <div class="label-item">
+                        <div class="text-item">跳转APP链接</div>
+                        <div class="required-item"></div>
+                        </div>
+                        <div class="input-item">
+                        <a-form-item>
+                            <a-input v-decorator="['openUrl']" />
+                        </a-form-item>
+                        </div>
+                    </div>
+                    <div class="row-item">
+                        <div class="hint-item"></div>
+                        <div class="label-item">
+                            <div class="text-item">转化目标</div>              
+                            <div class="required-item"></div>
+                        </div>
+                        <div class="input-item"   >
+                            <a-form-item style="margin-bottom:15px" v-for="(item,index) in LHKaccountInfo" :key="index">
+                                <a-radio-button
+                                    value="SelectConversionTarget"
+                                    @click="SelectConversionTarget(item,index)"
+                                    :disabled="!IsURL(getFormData('url'))"
+                                    v-show="showIndex<=index"
+                                >选择转化目标</a-radio-button>
+                                <a-select  style="width: 335px"     v-show="showIndex>index"  @change="APIChange($event,index)">
+                                    <a-select-option v-for="item in currentConvertTypes[index]" :key="item.convertId" :value='item.convertId'>
+                                        {{item.external_name}}
+                                    </a-select-option>
+                                </a-select>
+                                <span style="margin-left:20px">账户:{{item.title}} </span>
+                            </a-form-item>
+                        </div>
+                    </div>    
+                </div>
+            </a-form>  
+        </div>
+            
+            <!-- 当前账户 -->
+            <div class="moduler">
+                <div class="adName">
+                    <span>当前账户:</span> 
+                    <div class="nameList">
+                        <strong v-for="item in LHKaccountInfo" :key="item.value" class="item">{{item.title+'('+item.value+')'}}</strong>
+                    </div>
+                </div>
+            </div>
+            <!-- 操作 -->
+            <div class="moduler">
+                <!-- <div class="moduler-title">计划名称</div> -->
+                <div class="opt">
+                <a-button type="default" style="margin-right:15px" @click="goBack">取消</a-button>
+                
+                <a-button type="primary" @click="goNext"  :loading="goNextloading">下一步</a-button>
+                </div>
+            </div>
+        
+      <!-- 投放链接 -->
+    
+    <div class="infoModal">
+         <a-modal v-model="visible" title="提示"  @ok="handleOk" :keyboard='false' :maskClosable='false'>
+            <ul>
+              <li v-for="(item,index) in errorInfo" :key="index">
+                  <span>账户{{LHKaccountInfo[index].title}}:</span>{{item.message || '设置转化信息成功'}}
+              </li>
+            </ul>
+            <template slot="footer">
+              <a-button key="back" @click="handleCancel">
+                返回本页
+              </a-button>
+              <a-button key="submit" type="primary"  @click="handleOk">
+                下一步
+              </a-button>
+            </template>
+          </a-modal>
+    </div>
+  </div>
+</template>
+
+<script>
+import moment from 'moment'
+import { getAction, postAction, downFile, downFilePost } from '@/api/manage'
+import qs from 'qs'
+var str = ""
+for (let i = 0; i < 7*48; i++) {
+ str+='0'
+  
+}
+export default {
+  components: {
+    // selectCheckAll,
+    // newDirectedPackage,
+  },
+  data() {
+    return {
+        projectInfo:[],
+        LHKaccountInfo:[],
+        
+        form: this.$form.createForm(this),
+
+        showIndex:0,
+
+        goNextloading:false,
+        goPlanShowloading:false,
+        
+        
+        dateRange: [moment(), moment()],
+
+        visible:false,
+        errorInfo:[],
+       
+        validationRules: {
+            url: [   
+            {          
+                required: true,
+                validator: this.validateURL,
+            },
+            ],
+            name:[{
+            required: true,
+            validator: this.validateName,
+            }],
+            bid:[{
+            required: true,
+            message:'出价信息必须填写',
+            // validator: this.validateBid,
+            }],
+            roi:[{
+            required: true,
+            message:'ROI系数必须填写',
+            // validator: this.validateBid,
+            }],
+        },
+
+        currentConvertTypes:[],
+        convertIds:[],
+        convertInfo:[],
+    }
+  },
+  watch: {
+    
+  },
+  methods: {
+    
+    callback(val) {
+      console.log(val);
+    },
+
+    
+    
+    handleOk(e) {
+        this.visible=false;
+      // this.$router.push('/LaunchHousekeeper/setProjectDirectional')
+        this.$router.push({path:'/LaunchHousekeeper/setProjectDirectional'})
+       
+        
+    },
+    handleCancel(e) {
+        this.visible = false;
+    },
+    // 直达链接是否启用
+    useOpenUrlChange(){
+      this.form.setFieldsValue({
+        openUrl:''
+      })
+    },
+    // 下载方式改变
+    downloadTypeChange(val){
+        console.log(val)
+        this.showIndex=0;
+        if(val.target.value=="EXTERNAL_URL"){
+            this.form.setFieldsValue({
+                appType:'',
+                url:'',
+                adlabPackage:'',
+                webUrl:'',
+            })
+        }else{
+           this.form.setFieldsValue({
+                appType:'APP_IOS',
+                url:'',
+                adlabPackage:'',
+                useOpenUrl:'NO',
+                openUrl:'',
+            }) 
+        }
+    },
+    // 投放平台改变
+    appTypeChange(val){
+        this.showIndex=0;
+        if(val.target.value=="APP_IOS"){
+            this.form.setFieldsValue({
+                url:'',
+                adlabPackage:'',
+                webUrl:'',
+            })
+        }else{
+           this.form.setFieldsValue({               
+                url:'',
+                     
+            }) 
+        }
+    },
+    //  转化目标显示
+    SelectConversionTarget(item,index) {
+        
+        
+        let downloadType=this.getFormData('downloadType');
+       
+        let adlabPackage=this.getFormData('adlabPackage');
+        let appType=this.getFormData('appType');
+
+        let downloadUrl='';
+        let externalUrl='';
+        if(downloadType=='DOWNLOAD_URL'){
+            downloadUrl=this.getFormData('url');
+            externalUrl='';
+        }else{
+            externalUrl=this.getFormData('url');
+            downloadUrl='';
+        }
+        if(downloadType=='DOWNLOAD_URL'&&appType=='APP_ANDROID'){
+            if(adlabPackage){
+            postAction('/ctop/queryTool/queryConvert',qs.stringify({
+                accountId:this.LHKaccountInfo[index].value,
+                landingType:this.projectInfo[index].landingType,
+                downloadType,
+                downloadUrl,
+                externalUrl,
+                toutiaoPackage:adlabPackage,
+                appType,
+                
+            })).then(res=>{
+                console.log(res)
+                if(res.success){
+                  this.showIndex=index+1
+                  this.currentConvertTypes[index]=[];
+                  res.result.data.forEach(ele=>{
+                    if(ele.external_actions.length>0){
+                      ele.external_actions.forEach(element=>{
+                        if(element.deep_external_action){
+                          element.deep_external_action.forEach(i=>{
+                            this.currentConvertTypes[index].push(i)
+                          })
+                        }else{
+                          this.currentConvertTypes[index].push(element)
+                        }
+                      })
+                    }
+                      
+                  })
+                
+                }else{
+                  this.$message.error('网络异常,数据获取失败')
+                }
+            })
+            }else{
+                this.$message.error('请先输入应用包名称!')
+            }
+        }else{
+            postAction('/ctop/queryTool/queryConvert',qs.stringify({
+                accountId:this.LHKaccountInfo[index].value,
+                landingType:this.projectInfo[index].landingType,
+                downloadType,
+                downloadUrl,
+                externalUrl,
+                toutiaoPackage:adlabPackage,
+                appType,
+                
+            })).then(res=>{
+                console.log(res);
+                if(res.success){
+                  this.showIndex=index+1;
+                  this.currentConvertTypes[index]=[];
+                  res.result.data.forEach(ele=>{
+                    if(ele.external_actions.length>0){
+                      ele.external_actions.forEach(element=>{
+                        if(element.deep_external_action){
+                          element.deep_external_action.forEach(i=>{
+                            this.currentConvertTypes[index].push(i)
+                          })
+                        }else{
+                          this.currentConvertTypes[index].push(element)
+                        }
+                      })
+                    }
+                      
+                  })
+                
+                }else{
+                  this.$message.error('网络异常,数据获取失败')
+                }
+            })
+        }
+
+        
+    },
+
+    // 转化目标改变
+    APIChange(val,index,item){
+      console.log(val,index,item);
+      this.convertIds[index]={
+        accountId:this.LHKaccountInfo[index].value,
+        convertId:val,
+
+      }
+      
+      // this.convertInfo[index]={
+      //   accountId:this.LHKaccountInfo[index].value,
+      //   ...item
+      // }
+    },
+   
+    //获取表单的某一个属性值
+    getFormData(className) {
+      return this.form.getFieldValue(className)
+    },
+    dateChange(date, dateString) {
+      // console.log(date,dateString)
+      this.form.getFieldDecorator('startTime')
+      this.form.getFieldDecorator('endTime')
+      this.form.setFieldsValue({
+        startTime: date[0].format('YYYY-MM-DD HH:mm'),
+        endTime:  date[1].format('YYYY-MM-DD HH:mm'),
+      })
+    },
+    
+    
+    
+    
+    // 验证网址
+    IsURL(res) {
+      //   var strRegex = /^([hH][tT]{2}[pP]:\/\/|[hH][tT]{2}[pP][sS]:\/\/|www\.)(([A-Za-z0-9-~]+)\.)+([A-Za-z0-9-~\/])+$/
+      var strRegex = /^([hH][tT]{2}[pP]:\/\/|[hH][tT]{2}[pP][sS]:\/\/)(([A-Za-z0-9-~]+)\.)+([A-Za-z0-9-~\/])+(.+[A-Za-z0-9-~\/])+$/
+      var re = new RegExp(strRegex)
+      // console.log(re.test(res))
+      if (re.test(res)) {
+        return true
+      } else {
+        return false
+      }
+    },
+    validateURL(rule, value, callback) {
+      // console.log(rule, value, callback);
+
+      if (this.IsURL(value)) {
+        callback()
+      } else if (value && !this.IsURL(value)) {
+        callback('链接地址无法访问,请正确输入')
+      } else {
+          callback('链接必须填写')
+      }
+    },
+    validateName(rule, value, callback){
+      // console.log(rule, value, callback);
+
+        if (value) {
+          callback()
+        } else {
+              callback('应用包名称必须填写')
+        }
+    },
+    validateBid(rule, value, callback){
+      // console.log(rule, value, callback);
+        if (value) {
+          callback()
+        } else {
+            callback('出价必须填写')
+        }
+    },
+
+   
+    
+    goBack() {
+      this.$router.replace('/modules/LaunchHousekeeper/LaunchHousekeeperList')
+      this.$bus.$emit('remove', '/LaunchHousekeeper/setProjectConvert')
+    },
+    
+    // 保存并新建创意
+    goNext() {
+      this.$nextTick(()=>{
+        
+          this.form.validateFields((err, values) => {
+            if (!err) {
+
+              console.log('Received values of form: ', values)
+              
+              this.goNextloading=true;
+              let params=[];
+              params=this.convertIds.map((item,index)=>{
+                return {
+                  ...item,
+                  ...values,
+                  ...this.projectInfo[index]
+                }
+              })
+              console.log(params)
+              postAction('/adlab/Project/setConvert', params).then((res) => {
+                console.log(res)
+                if (res.success) {
+                  this.goNextloading=false;
+                
+                    if(res.result){
+                        this.errorInfo=res.result;
+                        this.visible=true;
+
+                        let projectInfo=[]
+                        res.result.forEach(item=>{
+                            if(item.code==0){
+                              projectInfo.push(item)
+                            }
+                        })
+
+                         sessionStorage.setItem('projectInfo',JSON.stringify(projectInfo))
+                    }
+                 
+                } else {
+                   this.goNextloading=false;
+                  this.$message.error(res.message)
+                }
+              })
+            }else{
+              this.$message.error('请正确填写必填项目')
+            }
+          })
+        
+      })
+      
+    },
+    
+
+    
+  },
+  destroyed() {
+     sessionStorage.setItem('convertInfo',JSON.stringify(this.convertInfo))
+  },
+  mounted() {
+    this.$bus.$emit('remove', '/LaunchHousekeeper/newProject')
+        let projectInfo=sessionStorage.getItem('projectInfo');
+        if(projectInfo){
+            this.projectInfo=JSON.parse(projectInfo)
+        }
+        let LHKaccountInfo=sessionStorage.getItem('LHKaccountInfo');
+        if(LHKaccountInfo){
+            this.LHKaccountInfo=JSON.parse(LHKaccountInfo)
+        }
+    
+  },
+}
+</script>
+<style lang="scss">
+.newPlan{
+  .ant-btn-danger {
+    background-color: #ff4d4f !important; 
+  }
+}
+
+
+.ant-tooltip-inner,
+.ant-tooltip,
+.ant-tooltip-arrow::before {
+  background-color: #fff;
+  color: #333;
+}
+.ant-tooltip-inner {
+  span {
+    display: block;
+  }
+}
+.ant-tooltip {
+  max-width: 450px;
+}
+.newPlan {
+  .ant-radio-button-wrapper {
+    min-width: 80px;
+    text-align: center;
+  }
+  .ant-form-item {
+    -webkit-box-sizing: border-box;
+    box-sizing: border-box;
+    margin: 0;
+    padding: 0;
+    color: rgba(0, 0, 0, 0.65);
+    font-size: 14px;
+    font-variant: tabular-nums;
+    line-height: 1.5;
+    list-style: none;
+    -webkit-font-feature-settings: 'tnum';
+    font-feature-settings: 'tnum';
+    vertical-align: top;
+  }
+  .directedBody {
+    .ant-form-item {
+      margin-bottom: 20px;
+    }
+  }
+}
+</style>
+<style lang="scss" scoped>
+.newPlan {
+  font-family: PingFangSC-Regular, tahoma, arial, 'Hiragino Sans GB', 'Microsoft yahei', sans-serif;
+  color: #333;
+  ul,
+  li {
+    margin: 0;
+    padding: 0;
+  }
+  .moduler {
+    background: #fff;
+    margin-bottom: 16px;
+    position: relative;
+    padding: 32px 24px 48px 32px;
+    border-radius: 4px;
+    box-shadow: 0px 1px 6px 0px rgba(0, 0, 0, 0.05);
+    .moduler-title {
+      display: flex;
+      align-items: center;
+      font-size: 22px;
+      margin-bottom: 20px;
+    }
+    .row-item {
+      display: flex;
+      justify-content: flex-start;
+      align-items: center;
+      margin-bottom: 32px;
+    }
+    .row-item:last-of-type {
+      margin-bottom: 0;
+    }
+    .row-item .hint-item {
+      width: 24px;
+      min-width: 24px;
+      align-self: flex-start;
+      line-height: 20px;
+      height: 20px;
+      margin-top: 5px;
+    }
+    .row-item .label-item {
+      position: relative;
+      align-items: flex-start;
+      align-self: flex-start;
+      line-height: 20px;
+      height: 20px;
+      margin-top: 7px;
+      width: 80px;
+      min-width: 80px;
+      .text-item {
+        font-size: 14px;
+        width: 60px;
+      }
+    }
+    .row-item .required-item {
+      width: 4px;
+      height: 4px;
+      border-radius: 2px;
+      background: #f45858;
+      position: absolute;
+      right: 10px;
+      top: 50%;
+      transform: translateY(-50%);
+    }
+    .row-item .input-item {
+      min-width: 480px;
+      position: relative;
+      // height: 35px;
+      .tip {
+        font-size: 12px;
+        color: tomato;
+      }
+    }
+    .adName{
+      display: flex;
+      .nameList{
+        width: 90%;
+      }
+      .item{
+        display: inline-block;
+        width: 30%;
+        margin-left: 15px;
+        margin-bottom: 10px;
+      }
+    }
+  }
+  .opt {
+    text-align: right;
+  }
+}
+</style>

File diff suppressed because it is too large
+ 1295 - 0
src/views/modules/LaunchHousekeeper/setProjectCreate.vue


File diff suppressed because it is too large
+ 1054 - 0
src/views/modules/LaunchHousekeeper/setProjectDirectional.vue


+ 127 - 13
src/views/modules/Statistics/Statistics.vue

@@ -1,6 +1,13 @@
-<style>
+<style lang='less'>
+.ant-card-head .ant-tabs-bar{
+  padding: 0;
+}
 .search-box .ant-card-body {
   padding: 5px 15px;
+
+}
+.search-box{
+  padding: 15px 10px;
 }
 .search-box p {
   display: inline-block;
@@ -34,6 +41,26 @@
   top: 65px;
   right: 10px;
 }
+.statistics{
+  .ant-card-bordered {
+     border: none; 
+  }
+  .ant-card-head .ant-tabs {
+    clear: both;
+    margin-bottom: -13px;
+    color: rgba(0, 0, 0, 0.65);
+    font-weight: normal;
+    font-size: 14px;
+}
+.duibi{
+  position: absolute;
+  right: 24px;
+  top: 15px;
+}
+p{
+  margin-bottom: 0;
+}
+}
 </style>
 <template>
   <div class="statistics">
@@ -41,7 +68,7 @@
       <a-col :span="24">
         <a-card :bordered="false" class="search-box">
           <time-check @getAdd="getAdd" :startValue.sync="startValue"></time-check>
-          <p @click="visible = true">对比</p>
+          <!-- <p>对比</p> -->
         </a-card>
       </a-col>
     </a-row>
@@ -86,12 +113,13 @@
     <a-row :gutter="10">
       <a-col :span="24">
         <a-card
-          style="width:100%"
+          style="width:100%;position:relative"
           :tabList="tabListNoTitle"
           :activeTabKey="noTitleKey"
           @tabChange="key => onTabChange(key, 'noTitleKey')"
         >
           <div id="chart" style="width:100%;height:500px"></div>
+          <a-button class="duibi" type='primary'  @click="visible = true">数据对比</a-button>
         </a-card>
       </a-col>
     </a-row>
@@ -275,14 +303,22 @@
         </a-col>
       </a-row>
     </a-modal>
-    <a-row style="margin-bottom:15px;margin-top:15px">
+    <a-row style="margin-bottom:15px;margin-top:12px">
       <a-col :span="24">
         <a-card
           :tabList="tableNowCard"
+
           :activeTabKey="noTitleKeyTable"
           @tabChange="key => onTabChange(key, 'noTitleKeyTable')"
+           style="word-break: break-all;font-size:16px;font-weight:600"
         >
-          <a-table :columns="columns" :dataSource="dataTable" :pagination="false" :loading="loading" bordered></a-table>
+          <a-table :columns="columns" :dataSource="dataTable" :pagination="false" :loading="loading" bordered>
+            <!-- <span slot="cost" slot-scope="cost">{{ cost | decimalsHandle }}</span> -->
+            <span slot="cost" slot-scope="cost">{{ cost | decimalsHandle }}</span>
+            <span slot="photoClick" slot-scope="photoClick">{{ photoClick | formatCurrency }}</span>
+            <span slot="photoShow" slot-scope="photoShow">{{ photoShow | formatCurrency }}</span>
+            <span slot="aclick" slot-scope="aclick">{{ aclick | formatCurrency }}</span>
+          </a-table>
         </a-card>
       </a-col>
     </a-row>
@@ -335,35 +371,35 @@ export default {
           scopedSlots: { customRender: 'yesCost' },
           align: 'center'
         },
-        { title: '总消耗', dataIndex: 'cost', align: 'center' },
+        { title: '总消耗', dataIndex: 'cost', align: 'center' , scopedSlots: { customRender: 'cost' },},
         {
           title: '封面点击数环比',
           dataIndex: 'yesPhotoClick',
           scopedSlots: { customRender: 'photoClickProportion' },
           align: 'center'
         },
-        { title: '封面点击数', dataIndex: 'photoClick', align: 'center' },
+        { title: '封面点击数', dataIndex: 'photoClick', align: 'center', scopedSlots: { customRender: 'photoClick' }, },
         {
           title: '封面曝光数环比',
           dataIndex: 'yesPhotoShow',
           scopedSlots: { customRender: 'photoShowProportion' },
           align: 'center'
         },
-        { title: '封面曝光数', dataIndex: 'photoShow', align: 'center' },
+        { title: '封面曝光数', dataIndex: 'photoShow', align: 'center' , scopedSlots: { customRender: 'photoShow' },},
         {
           title: '素材曝光数环比',
           dataIndex: 'yesAclick',
           scopedSlots: { customRender: 'aclickProportion' },
           align: 'center'
         },
-        { title: '素材曝光数', dataIndex: 'aclick', align: 'center' }
+        { title: '素材曝光数', dataIndex: 'aclick', align: 'center', scopedSlots: { customRender: 'aclick' }, }
       ],
       columnsDb: [
         { title: '时间', dataIndex: 'statDate', align: 'center' },
-        { title: '总消耗', dataIndex: 'cost', align: 'center' },
-        { title: '封面点击数', dataIndex: 'photoClick', align: 'center' },
-        { title: '封面曝光数', dataIndex: 'photoShow', align: 'center' },
-        { title: '素材曝光数', dataIndex: 'aclick', align: 'center' }
+        { title: '总消耗', dataIndex: 'cost', align: 'center' , scopedSlots: { customRender: 'cost' },},
+        { title: '封面点击数', dataIndex: 'photoClick', align: 'center', scopedSlots: { customRender: 'photoClick' }, },
+        { title: '封面曝光数', dataIndex: 'photoShow', align: 'center', scopedSlots: { customRender: 'photoShow' }, },
+        { title: '素材曝光数', dataIndex: 'aclick', align: 'center', scopedSlots: { customRender: 'aclick' }, }
       ],
       dataTable: [],
       dataTableTwo: [],
@@ -1492,6 +1528,84 @@ export default {
   },
   deactivated() {
     window.clearTimeout(upDate)
+  },
+  filters: {
+    toPercentage(val) {
+      if(typeof val != 'string'){
+          return (val * 100).toFixed(2) + '%'
+      }else{
+        return val
+      }
+      
+    },
+    //保留两位小数并且变成货币格式
+    decimalsHandle(val){
+        
+        if(val && typeof val !='string'){
+            if(val>=0){
+                val=parseFloat(val).toFixed(2);
+                let numberStr = val.toString()
+                let str = numberStr.split('.')
+                
+                let str0=str[0].split('').reverse();
+                for (let i = 0; i < str0.length; i++) {
+                    if ((i + 1) % 4 === 0) {
+                        str0.splice(i, 0, ',')
+                    }
+                }
+                str0.reverse()
+                let handleResult = ''
+                for (let j = 0; j < str0.length; j++) {
+                    handleResult += str0[j]
+                }
+                
+                return handleResult+'.'+str[1]
+            }else{
+                val=parseFloat(val).toFixed(2);
+                let numberStr = val.toString()
+                let str = numberStr.split('.')
+                
+                let str0=str[0].substr(1).split('').reverse();
+                for (let i = 0; i < str0.length; i++) {
+                    if ((i + 1) % 4 === 0) {
+                        str0.splice(i, 0, ',')
+                    }
+                }
+                str0.reverse()
+                let handleResult = ''
+                for (let j = 0; j < str0.length; j++) {
+                    handleResult += str0[j]
+                }
+                
+                return '-'+handleResult+'.'+str[1]
+            }
+            
+        }else if(typeof val =='string'){
+            return val
+        }
+        else{
+            return 0
+        }           
+    },
+    //变成货币格式
+    formatCurrency(val){
+      if(val){
+          let numberStr = val.toString()
+        let str = numberStr.split('').reverse()
+        for (let i = 0; i < str.length; i++) {
+            if ((i + 1) % 4 === 0) {
+            str.splice(i, 0, ',')
+            }
+        }
+        str.reverse()
+        let handleResult = ''
+        for (let j = 0; j < str.length; j++) {
+            handleResult += str[j]
+        }
+        return handleResult
+      }
+        
+    }
   }
 }
 </script>

+ 4 - 4
src/views/modules/Statistics/accountReport.vue

@@ -19,7 +19,7 @@
             @change="treeChange"
             @search="treeSearch"
             @select="treeSelect"                        
-             :maxTagCount='1'    
+            :maxTagCount='1'    
             :tree-data="treeData"
             :filterOption='filterOption'
           >
@@ -90,7 +90,7 @@
                   </span>
                 </a-tooltip>
             </div>
-            <div class="infoNum">
+            <div class="infoNum">
                 <span class="red">{{clickLink.click | formatCurrency }}</span> 
                 <span class="green" v-if="dateValue[0].format('YYYY-MM-DD')==dateValue[1].format('YYYY-MM-DD')"><span class="huanbi">环比: </span> {{ clickLink.clickLink|toPercentage  }}</span> 
             </div>
@@ -105,7 +105,7 @@
                   </span>
                 </a-tooltip>
             </div>
-            <div class="infoNum"> 
+            <div class="infoNum"> 
                 <span class="red">{{showNumLink.showNum | formatCurrency }}</span> 
                 <span class="green" v-if="dateValue[0].format('YYYY-MM-DD')==dateValue[1].format('YYYY-MM-DD')"><span class="huanbi">环比: </span> {{ showNumLink.showNumLink|toPercentage  }}</span> 
             </div>
@@ -120,7 +120,7 @@
                   </span>
                 </a-tooltip>
             </div>
-            <div class="infoNum">
+            <div class="infoNum">
                 <span class="red">{{convertNumLink.convertNum | formatCurrency }}</span> 
                 <span class="green" v-if="dateValue[0].format('YYYY-MM-DD')==dateValue[1].format('YYYY-MM-DD')"><span class="huanbi">环比: </span> {{ convertNumLink.convertNumLink|toPercentage  }}</span> 
             </div>

+ 209 - 0
src/views/modules/Statistics/components/datePick.vue

@@ -0,0 +1,209 @@
+<template>
+  
+  <div class="datePicker" >
+      <p
+      :style="active == item.value ? 'color:cornflowerblue;background:#f2f2f2' : ''"
+      v-for="(item, index) of pickOptions"
+      :key="index"
+      @click="changeDate(item)"
+    >
+      {{ item.title }}
+    </p>
+   
+    <a-range-picker v-clickoutside="handleClose"
+      v-model="mydateValue"
+      style="width:250px;"
+      :allowClear=false      
+      :disabled-date="disabledDate"
+      :openChange="openChange"
+      @change="onChange"
+    />
+    
+  </div>
+</template>
+
+
+<script>
+const clickoutside = {
+  // 初始化指令
+  bind(el, binding, vnode) {
+    function documentHandler(e) {
+      // 这里判断点击的元素是否是本身,是本身,则返回
+      if (el.contains(e.target)) {
+        return false
+      }
+      // 判断指令中是否绑定了函数
+      if (binding.expression) {
+        // 如果绑定了函数 则调用那个函数,此处binding.value就是handleClose方法
+        binding.value(e)
+      }
+    }
+    // 给当前元素绑定个私有变量,方便在unbind中可以解除事件监听
+    el.__vueClickOutside__ = documentHandler
+    document.addEventListener('click', documentHandler)
+  },
+  update() {},
+  unbind(el, binding) {
+    // 解除事件监听
+    document.removeEventListener('click', el.__vueClickOutside__)
+    delete el.__vueClickOutside__
+  }
+}
+import moment from 'moment'
+let pickOptions = [
+  {
+    title: '今天',
+    key: '1',
+    value: 1,
+    dateValue: [moment(), moment()]
+  },
+  {
+    title: '昨天',
+    key: '2',
+    value: 2,
+    dateValue: [moment().subtract(1, 'days'), moment().subtract(1, 'days')]
+  },
+  {
+    title: '一周',
+    key: '3',
+    value: 3,
+    dateValue: [moment().subtract(7, 'days'), moment().subtract(1, 'days')]
+  },
+  {
+    title: '一个月',
+    key: '5',
+    value: 5,
+    dateValue: [
+      moment()
+        .subtract(1, 'days')
+        .subtract(1, 'months'),
+      moment().subtract(1, 'days')
+    ]
+  },
+  {
+    title: '三个月',
+    key: '6',
+    value: 6,
+    dateValue: [
+      moment()
+        .subtract(1, 'days')
+        .subtract(3, 'months'),
+      moment().subtract(1, 'days')
+    ]
+  },
+  {
+    title: '六个月',
+    key: '7',
+    value: 7,
+    dateValue: [
+      moment()
+        .subtract(1, 'days')
+        .subtract(6, 'months'),
+      moment().subtract(1, 'days')
+    ]
+  },
+  {
+    title: '一年',
+    key: '8',
+    value: 8,
+    dateValue: [
+      moment().subtract(1, 'days').subtract(1, 'years'),
+      moment().subtract(1, 'days')
+    ]
+  }
+]
+
+export default {
+  props: ['dateValue','type'],
+  data() {
+    return {
+      moment,
+      mydateValue: [moment(),moment()],
+      pickOptions,
+      active:1
+      // pickOptions:JSON.parse(JSON.stringify(pickOptions))
+    }
+  },
+  directives: { clickoutside },
+  watch: {
+    parentDate(n,o){
+        if(n[0].format('YYYY-MM-DD')!=this.mydateValue[0].format('YYYY-MM-DD')){
+              this.mydateValue=n
+        } 
+    }
+  },
+  methods: {
+    //日期改变事件
+    onChange(date, dateString) {
+      this.mydateValue = date
+      this.active=9;
+      console.log(this.mydateValue)
+      if (dateString.length == 2) {   
+        this.$emit('update:dateValue', this.mydateValue)
+        this.$emit('update:type', 9)
+      }
+    },
+    //侧边的按钮点击事件
+    changeDate(val) {
+        console.log(val);
+        this.active=val.value;
+        this.mydateValue = val.dateValue
+      
+        this.$emit('update:dateValue', this.mydateValue)
+        this.$emit('update:type', val.value)
+    },
+    handleClose(e) {
+        // console.log(e)
+        if(e.target.className){
+            if(e.target.className.indexOf('ant-calendar')==-1){
+                // this.$parent.opendateClose()
+            }
+        }
+            
+      
+    },
+    disabledDate(current) {
+      // console.log(current)
+
+      return current && current > moment().subtract(1, 'day')
+    },
+    openChange(open) {
+      // console.log(open)
+    }
+  },
+  mounted() {
+    this.mydateValue = [moment(), moment()]    
+    // console.log(this.$refs.pickOptions.style.left)
+  }
+
+}
+</script>
+
+<style lang="scss" scoped>
+.datePicker {
+  position: relative;
+  p{
+      margin-bottom: 0;
+  }
+  .pickOptions {
+    width: 100px;
+    background-color: #fff;
+    height: 302px;
+    position: absolute;
+    top: -2px;
+    left: -402px;
+    border-right: 1px solid #999;
+    box-shadow: 0 0 15px rgba(0, 0, 0, 0.1);
+    cursor: pointer;
+    z-index: 3;
+    div {
+      height: 43px;
+      padding: 10px 15px;
+      box-sizing: border-box;
+    }
+    .btn:hover{
+        color: #1890ff;
+    }
+  }
+}
+</style>

+ 4 - 1
src/views/modules/Statistics/components/lifting.vue

@@ -11,10 +11,13 @@
   padding: 5px 10px;
   cursor: pointer;
 }
+p{
+  margin-bottom: 0px;
+}
 </style>
 <style>
 .data-display-statistics{
-  margin: 10px 0;
+  margin: 12px 0;
 }
 .data-display-statistics .ant-card-body {
   display: flex;

+ 53 - 0
src/views/modules/Statistics/effectReport.vue

@@ -15,6 +15,7 @@
       </a-select>     
       <a-range-picker v-model="dateRange" @change="dateChange" style="width:200px" />      
       <div class="opt">
+        <!-- <a-button type='primary' @click="exportExcel" style="margin-right:15px">导出报表</a-button> -->
         <a-button type='primary' @click="(ipagination.current=1);(projectId = null);( unitId = null );(campaignId = null);(accountId = null) ;search()">查询</a-button>
       </div>
     </div>
@@ -25,6 +26,7 @@
             <a-tab-pane :key="3" tab="广告计划"> </a-tab-pane>
             <a-tab-pane :key="4" tab="广告组"> </a-tab-pane>
             <a-tab-pane :key="5" tab="广告创意"> </a-tab-pane>
+            <a-button slot="tabBarExtraContent" type='primary' @click="exportExcel"  :loading="exportLoading">导出报表</a-button>
         </a-tabs>
         <div class="tableBody">
           <a-spin :spinning="spinning">
@@ -480,9 +482,59 @@ export default {
         visible:false,
         imgSrc:undefined,
         currentRecords:{},
+        projectRecord:{},
+        exportLoading:false,
       }
     },
     methods: {
+      //导出报表
+        exportExcel() {
+          if(this.projectValue.length>0){
+            this.exportLoading=true;
+            let type='';
+           if(this.tabKey==1){
+              type='project'
+            }else if(this.tabKey==2){
+              type='account'
+            }else if(this.tabKey==3){
+              type='campaign'
+            }else if(this.tabKey==4){
+              type='group'
+            }else if(this.tabKey==5){
+              type='creative'
+            }
+
+          var name =`${this.dateRange[0].format('YYYY_MM_DD')}~${this.dateRange[1].format('YYYY_MM_DD')}_效果报表`;
+            
+          downFilePost(`/ctop/advertiser/exportKuaishouProjectInfo`, {
+            startDate:this.dateRange[0].format('YYYY-MM-DD'),
+            endDate:this.dateRange[1].format('YYYY-MM-DD'),
+            projectList:this.projectValue,
+            projectId:this.projectId,
+            accountId:this.accountId,
+            campaignId:this.campaignId,
+            unitId:this.unitId,
+            type,
+          }).then(res => {
+                // console.log(res)
+                this.exportLoading=false;
+                let blob = new Blob([res], {
+                    type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
+                })
+                // console.log(blob)
+                let downloadElement = document.createElement('a')
+                let href = window.URL.createObjectURL(blob) //创建下载的链接
+                downloadElement.href = href
+                downloadElement.download = name+'.xlsx'    //下载后文件名
+                document.body.appendChild(downloadElement)
+                downloadElement.click() //点击下载
+                document.body.removeChild(downloadElement) //下载完成移除元素
+                window.URL.revokeObjectURL(href) //释放掉blob对象
+            })
+          }else{
+            this.$message.error('请选择项目!')
+          }
+        },
       handleOk(e) {
         // console.log(e);
         this.visible = false;
@@ -553,6 +605,7 @@ export default {
       // 从项目跳转到账户,并获取账户的table值
       goAccount(records){
         console.log(records,'--account');
+        this.projectRecord=records
         this.projectId=records.projectId 
         this.getTableAccountList()
 

+ 57 - 30
src/views/modules/Statistics/newHome.vue

@@ -2,7 +2,13 @@
   <div class="homePage">
     <div>
       <a-row :gutter="16">
-       
+       <a-col :span="24">
+        <a-card :bordered="false" class="search-box">
+          <div class="time"  @click="opendate" >
+            <datePick  :dateValue.sync='dateValue'   :type.sync='type'   />
+          </div>
+        </a-card>
+      </a-col>
         <a-col :sm="24" :md="12" :xl="6" :xxl="6" class="topBox">
           <div class="showBox">
             <div class="title">
@@ -105,6 +111,9 @@
     </div>
     <!-- 折线图模块 -->
     <div class="section">
+      <a-spin :spinning="spinning">
+     
+    
         <a-tabs default-active-key="cost" @change="callback" >
             <a-tab-pane key="cost" tab="总消耗"> 
             </a-tab-pane>
@@ -114,10 +123,8 @@
             </a-tab-pane>
         </a-tabs>
         <div id="sectionChart" style='width:100%;height:300px' ref="sectionChart"></div>
-        <a-button class="duibi" @click="comparehandle" type='default' >对比</a-button>
-        <div class="time"  @click="opendate" >
-            <DatePicker :openOptions='openOptions' :left='0' :parentDate='dateValue' />
-        </div>
+        <a-button class="duibi" @click="comparehandle" type='primary' >数据对比</a-button>
+      </a-spin>
     </div>
 
 
@@ -151,8 +158,9 @@
 <script>
 import moment from 'moment'
 import DatePicker from '@/components/DatePicker.vue'
+import datePick from './components/datePick'
 import CompareData from './CompareData.vue'
-
+import timeCheck from './components/timeCheck'
 import { getAction, postAction, downFile, downFilePost } from '@/api/manage'
 // import vueEchart from './components/vueEchart'
 // 引入基本模板
@@ -378,7 +386,9 @@ export default {
   
     components:{
         DatePicker,
-        CompareData
+        CompareData,
+        timeCheck,
+        datePick
     },
   data() {
     return {
@@ -407,16 +417,16 @@ export default {
       //子元素的数据存储
     
         type:1,
-        dateValue:[moment(),moment()],
+        dateValue:[moment(), moment()],
         
       //日期矿打开
       openOptions:false,
-
+      spinning:false,
     }
   },
   watch:{
     type(n,o){
-      // console.log(n,o)
+      console.log(n,o)
         // console.log(this.type)
         if(this.type<9){
             this.sectionHttp({type:this.type})
@@ -430,17 +440,20 @@ export default {
         }
     },
     dateValue: {
-    handler(newName, oldName) {
-      // console.log(newName,oldName)
-        this.sectionHttp({
-            type:this.type,
-            startDate:this.dateValue[0].format('YYYY-MM-DD'),
-            endDate:this.dateValue[1].format('YYYY-MM-DD')
-            })
-    },
-    immediate: true,
-    deep: true
-  }
+      handler(newName, oldName) {
+        console.log(newName,oldName)
+        if(newName.length>1){
+          this.sectionHttp({
+              type:this.type,
+              startDate:this.dateValue[0].format('YYYY-MM-DD'),
+              endDate:this.dateValue[1].format('YYYY-MM-DD')
+          })
+        }
+          
+      },
+      immediate: true,
+      deep: true
+    }
   },
   methods: {
     //获取echart的值
@@ -499,13 +512,15 @@ export default {
     },
     //处理echart
     sectionHttp(params) {
-      this.loading = true
+      this.loading = true;
+      this.spinning=true;
       this.sectionOption=JSON.parse(JSON.stringify(sectionOption));
       return new Promise((resolve, reject) => {
         postAction('/ctop/byteDance/homePage/report/chart', params).then(res => {
           // console.log(res)
           if (res.success) {
             this.loading = false
+            this.spinning=false;
             //处理今天
             if(res.result){
 
@@ -867,16 +882,21 @@ export default {
 
 <style lang="scss" scoped>
 .homePage {
+    p {
+     margin-bottom: 0;
+    }
     .topBox{
-        margin-bottom: 20px;
+        margin-bottom: 12px;
+        margin-top: 12px;
+        border-radius: 2px;
     }
   .showBox {
-    width: 98%;
+    width: 100%;
     box-sizing: border-box;
     margin-right: 20px;
     padding: 25px 25px 0;
     background-color: #fff;
-    
+    border-radius: 2px;
     .title {
       color: #999;
       font-size: 16px;
@@ -903,7 +923,9 @@ export default {
       margin-bottom: 0;
     }
   }
-
+  .topBox:last-child{
+    margin-right: 0;
+  }
   .footerInfo {
     margin-top: 10px;
     border-top: 1px solid #eee;
@@ -945,19 +967,23 @@ export default {
   }
 
   .section{
+    #sectionChart{
+      padding: 0px  30px;
+    }
       width: 100%;
       background-color: #fff;
-      padding: 10px 15px 20px;
+      padding: 10px 0 20px;
       position: relative;
-      margin-bottom: 20px;;
+      margin-bottom: 12px;;
+       border-radius: 2px;
       .duibi{
           position: absolute;
           
           height: 30px;
           line-height: 30px;
           padding: 0 15px;
-          top: 15px;
-          right: 300px;
+          top: 8px;
+          right: 20px;
           // border: 1px solid #666;
           cursor: pointer;
       }
@@ -976,6 +1002,7 @@ export default {
     width: 100%;
     padding: 20px 15px;
     background-color: #fff;
+     border-radius: 2px;
     p{
       width: 100%;
       border-bottom: 1px solid #ccc;

+ 1 - 1
vue.config.js

@@ -66,7 +66,7 @@ module.exports = {
         // target: 'http://192.168.0.230:8088', //请求本地 需要jeecg-boot后台项目  孙震
         // target: 'http://192.168.1.51:8080', //请求本地 需要jeecg-boot后台项目  毕洁泉
 
-        target: 'http://192.168.1.51:8098', //请求本地 需要jeecg-boot后台项目  毕洁泉
+        target: 'http://192.168.1.74:8098', //请求本地 需要jeecg-boot后台项目  毕洁泉
         // target: 'http://192.168.0.252:8098', //请求本地 需要jeecg-boot后台项目  毕洁泉
         // target: 'http://192.168.0.170:8088', //请求本地 需要jeecg-boot后台项目  毕洁泉
         //  target: 'http://api.tjyourong.com.cn', //请求本地 需要jeecg-boot后台项目 

+ 140 - 0
投放管家创建接口

@@ -0,0 +1,140 @@
+step1:创建项目 post /adlab/Project/create
+入参{
+     "accountId":"",账户id
+	 "name":"",项目名称,不允许超过100个字
+	 "scenario":"",项目场景
+	 "adTarget":"",投放方式
+	 "deliveryRange":"",投放媒体
+	 "landingType":""推广目的
+}
+step2:设置项目转化信息 post /adlab/Project/setConvert
+入参{
+     "accountId":"",账户id
+	 "groupId":"",项目id
+	 "platform":"",
+	 "adTarget":"",
+	 "url":"",
+	 "downloadMode":"",
+	 "adlabPackage":"",
+	 "webUrl":"",
+	 "convertId":"",
+	 "openUrl":"",
+	 "downloadType":"",
+	 "appType":""
+}
+step3:设置项目定向信息 post /adlab/Project/setAudience
+入参{
+     "accountId":"",
+	 "groupId":"",
+	 "inventoryType":[],
+	 "unionVideoType":"",
+	 "age":"",
+	 "city":"",
+	 "district":"",
+	 "gender":"",
+	 "retargetingTagsExclude":"",
+	 "retargetingTagsInclude":"",
+	 "superiorPopularityType":"",
+	 "excludeFlowPackage":"",
+	 "flowPackage":"",
+	 "autoExtendEnabled":"",
+	 "autoExtendTargets":"",
+	 "inventoryTypes":"",
+}
+step4:设置项目创意信息 post /adlab/Project/setCreative
+入参{
+     "accountId":"",
+	 "groupId":"",
+	 "imageInfo":[
+	 {
+	   "web_uri":"",
+	   "height":"",
+	   "width":""},
+	 {
+	   "web_uri":"",
+	   "height":"",
+	   "width":""},
+	 {
+	   "web_uri":"",
+	   "height":"",
+	   "width":""},
+	 ],
+	 "video_info":[
+	 {
+	   "video_id":"",
+	   "url":"",
+	   "during":""
+	   "height":"",
+	   "width":"",
+	   "size":""},
+	 {
+	   "video_id":"",
+	   "url":"",
+	   "during":""
+	   "height":"",
+	   "width":"",
+	   "size":""},
+	 {
+	   "video_id":"",
+	   "url":"",
+	   "during":""
+	   "height":"",
+	   "width":"",
+	   "size":""},
+	 ],
+	 "title":"",
+	 "appName":"",
+	 "source":"",
+	 "isFollowMaterial":"",
+	 "thirdIndustryId":"",
+	 "adKeywords":[],
+	 "playableUrl":"",
+	 "actionTrackUrl":"",
+	 "trackUrl":"",
+	 "videoPlayTrackUrl":"",
+	 "videoPlayDoneTrackUrl":"",
+	 "videoPlayEffectiveTrackUrl":"",
+	 "creativeAutoGenerateSwitch":"",
+}
+step5:设置项目预算信息 post /adlab/Project/setBudget
+入参{
+     "accountId":"",
+	 "groupId":"",
+	 "bid":"",
+	 "budgetMode":"",
+	 "budget":"",
+	 "autoStop":"",
+	 "deepBid":"",
+	 "startTime":"",
+	 "endTime":"",
+	 "weekTime":number[number[]],
+}
+
+/ctop/queryTool/parseInstallPackage
+入参 表单
+@RequestParam String installUrl,
+@RequestParam String appType
+
+
+post
+
+
+ANDROID  IOS
+
+
+
+系统推荐标题
+/ctop/creativeTitle/getTitleLabel
+
+/ctop/creativeTitle/titleSearch
+入参:{firstCategory: 
+1
+secondCategory: 
+65
+keywords: 
+波波
+}
+
+
+投放管家的列表
+/adlab/ctopAdlabProjectDetail/list