朱鑫波 4 rokov pred
rodič
commit
71aead6b3d
32 zmenil súbory, kde vykonal 24586 pridanie a 171 odobranie
  1. 19777 0
      package-lock.json
  2. BIN
      src/assets/down.png
  3. BIN
      src/assets/up.png
  4. 2 4
      src/views/modules/Statistics/components/customColumn.vue
  5. 1 1
      src/views/modules/Statistics/components/selectComponent.vue
  6. 1 0
      src/views/modules/Statistics/materialReport/marterialDetail.vue
  7. 42 17
      src/views/modules/Statistics/videoStatics/KSvideoStatics.vue
  8. 582 115
      src/views/modules/autoLaunch/configLaunchInfo.vue
  9. 1 1
      src/views/modules/autoLaunch/newAppId.vue
  10. 65 0
      src/views/modules/crowd-control/components/tree-select/tree-select.less
  11. 272 0
      src/views/modules/crowd-control/components/tree-select/tree-select.vue
  12. 221 0
      src/views/modules/crowd-control/crowd-control-service.js
  13. 110 0
      src/views/modules/crowd-control/crowd-control.less
  14. 669 0
      src/views/modules/crowd-control/crowd-control.vue
  15. 15 3
      src/views/modules/kuaishouapp/batchCreation/creat/creatUnit.vue
  16. 92 2
      src/views/modules/material/accountCheckBytedance.vue
  17. 13 6
      src/views/modules/material/videoMaterial.vue
  18. 31 21
      src/views/modules/stockWatch/accountPage.vue
  19. 3 0
      src/views/modules/stockWatch/keep-market.less
  20. 27 0
      src/views/modules/stockWatch/keep-market.vue
  21. 109 0
      src/views/modules/stockWatch/modules/custom-columns/custom-columns.less
  22. 149 0
      src/views/modules/stockWatch/modules/custom-columns/custom-columns.vue
  23. 261 0
      src/views/modules/stockWatch/modules/keep-manage/keep-manage-data.js
  24. 158 0
      src/views/modules/stockWatch/modules/keep-manage/keep-manage.less
  25. 819 0
      src/views/modules/stockWatch/modules/keep-manage/keep-manage.vue
  26. 162 0
      src/views/modules/stockWatch/modules/keep-person/keep-person-data.js
  27. 120 0
      src/views/modules/stockWatch/modules/keep-person/keep-person.less
  28. 424 0
      src/views/modules/stockWatch/modules/keep-person/keep-person.vue
  29. 156 0
      src/views/modules/taobao-plan-daily/BytedanceCustomerDdTbtjDataList.vue
  30. 148 0
      src/views/modules/taobao-plan-daily/modules/BytedanceCustomerDdTbtjDataModal.vue
  31. 155 0
      src/views/modules/taobao-plan-daily/modules/BytedanceCustomerDdTbtjDataModal__Style#Drawer.vue
  32. 1 1
      vue.config.js

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 19777 - 0
package-lock.json


BIN
src/assets/down.png


BIN
src/assets/up.png


+ 2 - 4
src/views/modules/Statistics/components/customColumn.vue

@@ -90,7 +90,6 @@ export default {
     },
     listNum: {
       handler(newValue, oldValue) {
-        console.log(newValue, oldValue)
         this.mylistNum = newValue
       },
       immediate: true
@@ -120,7 +119,6 @@ export default {
         return
       }
       const newItems = [...this.mylistNum]
-      console.log(newItems)
       const src = newItems.findIndex(v => v.dataIndex === this.dragging)
       const dst = newItems.findIndex(v => v.dataIndex === item)
 
@@ -195,14 +193,14 @@ export default {
             index = ind
           }
         })
-        console.log(index)
         this.mylistNum.splice(index, 1)
       } else {
         this.mylistNum.push(val)
       }
     }
   },
-  mounted() {}
+  mounted() {
+  }
 }
 </script>
 

+ 1 - 1
src/views/modules/Statistics/components/selectComponent.vue

@@ -120,7 +120,7 @@ export default {
     })
 
 
-    // console.log(this.customFields);
+    console.log(this.customFields, 'customFields-customFields');
     
   },
   methods: {

+ 1 - 0
src/views/modules/Statistics/materialReport/marterialDetail.vue

@@ -209,6 +209,7 @@
               color: rgba(0, 0, 0, 0.85);
               font-weight: bold;
               font-size: 16px;
+               
               line-height: 1.5;
             "
           >

+ 42 - 17
src/views/modules/Statistics/videoStatics/KSvideoStatics.vue

@@ -5,20 +5,25 @@
         <Treeselect  :appId.sync="appId" request="2,4"   style="display: inline-block;position: relative;margin-left: 0px;"/>
     </div>
     <div class="timeDiv">
-      <div style='display:flex;align-items: center;'>
-        <span>时间范围:</span>
-        <span  @click="opendate">
-          <DatePicker :openOptions='openOptions'  :parentDate='dateValue' left='-100px'></DatePicker>
-        </span> 
-        <span style="margin-left:15px">设计负责人:</span> 
-        <span  >
+      <div style='display:flex;align-items: center;flex-wrap:wrap;'>
+        <div style="dispaly:inline-block;margin-bottom:15px;"> 
+          <span>时间范围:</span>
+          <span style="display: inline-block;"  @click="opendate">
+            <DatePicker :openOptions='openOptions'  :parentDate='dateValue' left='-100px'></DatePicker>
+          </span>
+        </div>
+        <div style="dispaly:inline-block;margin-bottom:15px;">
+        <span style="margin-left:15px;">设计负责人:</span> 
+        <span>
             <!-- <a-input placeholder="请输入剪辑的名字" v-model="clip" style="width:140px"  /> -->
             <a-select v-model="leaderId" style="width: 140px" allowClear  show-search :filter-option="filterOption">
               <a-select-option v-for="item in designList" :key="item.userId" :value='item.userId'>
                 {{item.companyName +'_'+item.userName  }}
               </a-select-option>
             </a-select>
-        </span>         
+        </span>   
+        </div>      
+        <div style="dispaly:inline-block;margin-bottom:15px;">
         <span style="margin-left:15px">剪辑:</span> 
         <span  >
             <!-- <a-input placeholder="请输入剪辑的名字" v-model="clip" style="width:140px"  /> -->
@@ -27,7 +32,9 @@
                 {{item.companyName +'_'+item.userName  }}
               </a-select-option>
             </a-select>
-        </span>         
+        </span>     
+        </div>    
+        <div style="dispaly:inline-block;margin-bottom:15px;">
         <span style="margin-left:15px">拍摄:</span> 
         <span  >
             <!-- <a-input placeholder="请输入拍摄的名字" v-model="shot" style="width:140px" /> -->
@@ -36,7 +43,9 @@
                 {{item.companyName +'_'+item.userName  }}
               </a-select-option>
             </a-select>
-        </span>         
+        </span>   
+        </div>      
+        <div style="dispaly:inline-block;margin-bottom:15px;">
         <span style="margin-left:15px">编导:</span> 
         <span  >
             <!-- <a-input placeholder="请输入编导的名字" v-model="plan" style="width:140px"  /> -->
@@ -45,7 +54,18 @@
                  {{item.companyName +'_'+item.userName  }}
               </a-select-option>
             </a-select>
-        </span>         
+        </span>     
+        </div>
+        <div style="dispaly:inline-block;margin-bottom:15px;">
+        <span style="margin-left:15px">素材渠道:</span> 
+        <span>
+            <!-- <a-input placeholder="请输入编导的名字" v-model="plan" style="width:140px"  /> -->
+            <a-select v-model="material" style="width: 140px" allowClear>
+              <a-select-option value="0">内部</a-select-option>
+              <a-select-option value="1">素造</a-select-option>
+            </a-select>
+        </span>    
+        </div> 
       </div>
       <a-button type="primary" @click="searchRes" :loading='searchLoading'>查询</a-button>
     </div>
@@ -504,6 +524,7 @@ let detailColumn=[
 export default {
   data() {
     return {
+      material: '',
       searchLoading:false,
 
       designList:[],
@@ -621,6 +642,7 @@ export default {
             item.key = index
           })
           this.detailData = result
+          console.log(this.detailData, 'detail----detail');
         }
       })
     },
@@ -744,7 +766,8 @@ export default {
         clipId:this.clip?this.clip:'',
         shotId:this.shot?this.shot:'',
         planId:this.plan?this.plan:'',
-        leaderId:this.leaderId?this.leaderId:''
+        leaderId:this.leaderId?this.leaderId:'',
+        channelType: this.material ? Number(this.material) : ''
       }).then(res => {
         let resArr = []
         this.data=[];
@@ -792,7 +815,8 @@ export default {
         clipId:this.clip?this.clip:'',
         shotId:this.shot?this.shot:'',
         planId:this.plan?this.plan:'',
-        leaderId:this.leaderId?this.leaderId:''
+        leaderId:this.leaderId?this.leaderId:'',
+        channelType: this.material ? Number(this.material) : ''
       }).then(res => {
         this.exportLoading=false;
         let blob = new Blob([res], {
@@ -831,6 +855,7 @@ export default {
     customColumns() {
       this.visible = true
       this.listNum = [...this.columns]
+      console.log(this.listNum, 'this.listNum-this.listNum');
     },
     
 
@@ -898,7 +923,7 @@ export default {
     // 获取设计人员
     getDesignList(){
       postAction('/ctop/kuaishou/videoReport/getDesignList').then(res=>{
-        console.log(res);
+        console.log(res, '设计人员');
         if(res.success){
             this.designList=res.result
         }
@@ -917,9 +942,9 @@ export default {
     postAction('/toutiao/videoReportDaily/getColumnJson', {
       columnType: 4
     }).then(res => {
-      // console.log(res)
+      console.log(res, 'activated--activated')
       if (res.success) {
-        // console.log(JSON.parse(res.result))
+        console.log(JSON.parse(res.result), '-------')
         if(res.result){
             let columns = JSON.parse(res.result)
             if (columns.length) {
@@ -1069,7 +1094,7 @@ filters: {
       this.getDesignList()
     //请求自定义列的数据
     postAction('/toutiao/videoReportDaily/videoInfoListTotalExportExcelPermission').then(res => {
-      console.log(res)
+      console.log(res, 'mounted-mounted')
       if (res.success) {
         if (res.result) {
           this.exportExcelIsOk = true

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 582 - 115
src/views/modules/autoLaunch/configLaunchInfo.vue


+ 1 - 1
src/views/modules/autoLaunch/newAppId.vue

@@ -34,7 +34,7 @@
                 <div class="input-item">
                     <a-form-item>
                           <a-radio-group  v-model="platform" >
-                            <a-radio-button :value="1">Android应用下载</a-radio-button>
+                            <a-radio-button :value="1">Android应用下载</a-radio-button>
                             <a-radio-button :value="3">IOS应用下载</a-radio-button>
                         </a-radio-group>
                     </a-form-item>

+ 65 - 0
src/views/modules/crowd-control/components/tree-select/tree-select.less

@@ -0,0 +1,65 @@
+
+.tree-select-content {
+    .input-search {
+        width: 240px;
+        margin: 10px 0 10px 0;
+    }
+    .tree-select-class {
+        display: flex;
+        justify-content: space-between;
+        .class-left-header {
+            height: 50px;
+            line-height: 50px;
+            background-color: #f9fafd;
+            border-bottom: 1px solid #eee;
+            text-indent: 10px;
+        }
+        .select-class-left {
+            width: 60%;
+            height: 400px;
+            border: 1px solid #eee;
+            .class-left-content {
+                overflow-y: auto;
+                height: 340px;
+            }
+            .example {
+                text-align: center;
+                line-height: 200px;
+            }
+        }
+        .select-class-right {
+            width: 35%;
+            height: 400px;
+            border: 1px solid #eee;
+            .class-left-content {
+                padding: 0 10px;
+                height: 348px;
+                overflow-y: auto;
+                .apply-right-tree {
+                    display: flex;
+                    justify-content: space-between;
+                    align-items: baseline;
+                    .left-content-p {
+                        display: inline-block;
+                        width: 85%;
+                        height: 25px;
+                        line-height: 25px;
+                        margin: 0;
+                        overflow: hidden;
+                        text-overflow: ellipsis;
+                        white-space: nowrap;
+                    }
+                    .delete-type-class {
+                        color: #1890ff;
+                        cursor: pointer;
+                    }
+                }
+            }
+            .no-data-class {
+                height: 340px;
+                line-height: 340px;
+                text-align: center;
+            }
+        }
+    }
+}

+ 272 - 0
src/views/modules/crowd-control/components/tree-select/tree-select.vue

@@ -0,0 +1,272 @@
+<template>
+    <div class="tree-select-content">
+        <a-input-search class="input-search" placeholder="请输入账户名或ID" @change="onChange" />
+        <div class="tree-select-class">
+            <div class="select-class-left">
+                <div class="class-left-header">选择分享的账户名称</div>
+                <div class="class-left-content">
+                    <template>
+                        <a-tree
+                            v-model="checkedKeys"
+                            checkable
+                            :expanded-keys="expandedKeys"
+                            :auto-expand-parent="autoExpandParent"
+                            :selected-keys="selectedKeys"
+                            :tree-data="treeData"
+                            @check="onCheck"
+                            @expand="onExpand"
+                        />
+                    </template>
+                    <div class="example">
+                        <a-spin :spinning="spinning"/>
+                        <span v-if="leftTreeNoData">暂无数据</span>
+                    </div>
+                </div>
+            </div>
+            <div class="select-class-right">
+                <div class="class-left-header">
+                    已选 ({{ applyTypeOption.length ? applyTypeOption.length : 0}}/100)
+                    <a-popover placement="topRight">
+                        <template slot="content">
+                            <p>1、输入账户超出推送范围,请检查是否同主体账户</p>
+                            <p>2、有效账户将不会重复推送,请登录该账户查看使用</p>
+                        </template>
+                        <span><a-icon type="question-circle" /></span>
+                    </a-popover>
+                </div>
+                <div v-if="applyTypeOption.length" class="class-left-content">
+                    <div class="apply-right-tree" v-for="item in applyTypeOption" :key="item.key">
+                        <p class="left-content-p">
+                            <a-tooltip placement="left">
+                                <template slot="title">
+                                    <span>{{ item.title }}</span>
+                                </template>
+                                {{ item.title }}
+                            </a-tooltip>
+                        </p>
+                        <a-icon type="delete" class="delete-type-class" @click="handleDelTree(item)" />
+                    </div>
+                </div>
+                <div v-else class="no-data-class">暂无数据</div>
+            </div>
+        </div>
+    </div>
+</template>
+<script>
+import {mapGetters} from 'vuex';
+import {postAction} from '@/api/manage';
+
+export default {
+    name: 'tree-select',
+    data() {
+        return {
+            expandedKeys: [],
+            autoExpandParent: true,
+            checkedKeys: [],
+            selectedKeys: [],
+            treeData: [],
+            updateTreeData: [],
+            applyTypeOption: [],
+            selectRightData: new Set(),
+            spinning: true,
+            leftTreeNoData: false
+        };
+    },
+    mounted() {
+        this.getAccountId();
+    },
+    methods: {
+        ...mapGetters(['userInfo']),
+        getAccountId() {
+            postAction('/ctop/projectMember/participateListByMediaId', {
+                userId: this.userInfo().id,
+                type: 'kuaishou'
+            }).then(result => {
+                if (result.result.length) {
+                    this.spinning = false;
+                    this.treeData = result.result.map(item => {
+                        return {
+                            key: item.projectId + 'projectId',
+                            title: item.projectName + '\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0' + item.advertiserName,
+                            children: item.accountList
+                            ? item.accountList.map(i => {
+                                return {
+                                    key: i.accountId,
+                                    title:
+                                    (i.userName.length === 2
+                                        ? i.userName + '\xa0\xa0\xa0\xa0\xa0'
+                                        : i.userName.length === 3
+                                        ? i.userName + '\xa0\xa0\xa0\xa0'
+                                        : i.userName)
+                                        + '\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0'
+                                        + i.accountId
+                                        + '\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0'
+                                        + i.authName
+                                };
+                            }) : []
+                        };
+                    });
+                    this.updateTreeData = [...this.treeData];
+                }
+                else {
+                    this.spinning = false;
+                    this.leftTreeNoData = true;
+                }
+            });
+        },
+        handleDelTree(list) {
+            const defaultTypeOption = JSON.parse(JSON.stringify(this.applyTypeOption));
+            const defaultCheckKey = JSON.parse(JSON.stringify(this.checkedKeys));
+            const len = defaultTypeOption.length;
+            const keysLen = defaultCheckKey.length;
+            for(let i = len - 1; i >= 0; i--) {
+                if(defaultTypeOption[i].key === list.key) {
+                    defaultTypeOption.splice(i, 1);
+                }
+            }
+            this.applyTypeOption = defaultTypeOption;
+            this.selectRightData = new Set(defaultTypeOption);
+            const txt = this.handleDelFindId(this.treeData, list.key);
+            const lastIndex = defaultCheckKey.findIndex(item => item === txt);
+            let value = null;
+            if (lastIndex > -1) {
+                value = defaultCheckKey.findIndex(item => item === txt);
+                for(let i = keysLen - 1; i >= 0; i--) {
+                    if(defaultCheckKey[i] === list.key) {
+                        defaultCheckKey.splice(i, 1);
+                    }
+                }
+            }
+            else {
+                value = defaultCheckKey.findIndex(item => item === list.key);
+            }
+            defaultCheckKey.splice(value, 1);
+            this.checkedKeys = defaultCheckKey;
+        },
+        onChange(e) {
+            const value = e.target.value;
+            this.treeData = value !== '' ? this.getNewTreeData(this.updateTreeData, value) : [...this.updateTreeData];
+            if (!this.treeData.length) {
+                this.spinning = false;
+                this.leftTreeNoData = true;
+            }
+            else {
+                this.leftTreeNoData = false;
+            }
+        },
+        handleDelFindId(treeData, value) {
+            if (!treeData) {
+                return null;
+            }
+            let node = null;
+            let children = null;
+            let text = '';
+            for (let i = 0; i < treeData.length; i++) {
+                node = treeData[i];
+                if (node.children) {
+                    children = node.children;
+                    text = node.key;
+                    for (let j = 0; j < children.length; j++) {
+                        if (children[j].key === value) {
+                            return text;
+                        }
+                    }
+                }
+            }
+        },
+        // 根据关键词查询所有相关的tree节点
+        getNewTreeData(treeData, value) {
+            if (!treeData) {
+                return null;
+            }
+            let newTreeData = new Array();
+            let node = null;
+            let children = null;
+            let text = '';
+            for (let i = 0; i < treeData.length; i++) { // 多个根节点开始遍历
+                node = treeData[i];
+                if (node.children) {
+                    children = node.children;
+                }
+                text = node.title;
+                if (text.indexOf(value) > -1) {
+                    newTreeData.push(node);
+                    continue;
+                }
+                else {
+                    if (children) {
+                        let newNodes = this.getNewTreeData(node.children, value);
+                        if (newNodes.length > 0) {
+                            node.children = newNodes;
+                            newTreeData.push(node);
+                        }
+                    }
+                }
+
+            }
+            return newTreeData;
+        },
+        onExpand(expandedKeys) {
+            this.expandedKeys = expandedKeys;
+            this.autoExpandParent = false;
+        },
+        // 去重的方法
+        Es6duplicate(arr, type) {
+            if (!arr.length){
+                return arr;
+            }
+            else {
+                if (type) {
+                    let obj = {};
+                    let newArr = arr.reduce((cur, next) => {
+                        obj[next.key] ? '' : obj[next.key] = true && cur.push(next);
+                        return cur;
+                    }, []);
+                    return newArr;
+                }
+                else {
+                    return Array.from(new Set(arr));
+                }
+            }
+        },
+        onCheck(checkedKeys) {
+            // this.checkedKeys = checkedKeys;
+            this.nodes(this.treeData, checkedKeys);
+            const filterCheckKey = this.checkedKeys.filter(item=>typeof item ==='number');
+            let filterCheckKeySet = new Set(filterCheckKey);
+            let selectRightDataSet = new Set(this.selectRightData);
+            let difference = new Set([...selectRightDataSet].filter((item) => !filterCheckKeySet.has(item.key)));
+            this.selectRightData.delete(...difference);
+            this.applyTypeOption = this.Es6duplicate([...this.selectRightData], 'key');
+            const changeSelectData = this.applyTypeOption.map(item => item.key);
+            this.checkedKeys = changeSelectData;
+              
+            if (this.applyTypeOption.length > 100) {
+                const lastOptionKey = this.applyTypeOption[99].key;
+                const lastIndex = changeSelectData.findIndex(item => item === lastOptionKey);
+                this.checkedKeys = changeSelectData.slice(0, lastIndex + 1);
+                this.applyTypeOption = [...this.selectRightData].slice(0, 100);
+            }
+            this.$emit('applyType', this.applyTypeOption);
+        },
+        nodes(data, checkedKeys) {
+            data.forEach(item => {
+                if (item.children) {
+                    this.nodes(item.children, checkedKeys);
+                }
+                else {
+                    if (checkedKeys.indexOf(item.key) !== -1) {
+                        this.selectRightData.add(item);
+                    }
+                    else {
+                        this.selectRightData.delete(item);
+                    }
+                }
+            });
+        }
+    }
+};
+</script>
+<style lang="less" scoped>
+    @import 'tree-select';
+</style>

+ 221 - 0
src/views/modules/crowd-control/crowd-control-service.js

@@ -0,0 +1,221 @@
+/**
+ * @file 人群包管理基础服务
+ * @author jiayufei(jiayufei@c-top.com.cn)
+ */
+
+class AppMarketService {
+    constructor() {}
+
+    // 相关账户的table列表
+    setAcountColumns() {
+        return [
+            {
+                title: '账户名称',
+                dataIndex: 'accountName',
+                width: '30%'
+            },
+            {
+                title: '所属项目',
+                dataIndex: 'projectName',
+                width: '30%'
+            },
+            {
+                title: '人群包数量',
+                dataIndex: 'count',
+                width: '20%'
+            },
+            {
+                title: '状态',
+                dataIndex: 'statusStr',
+                width: '20%'
+            }
+        ]
+    }
+
+    // 原因的table列表
+    setCauseColumns() {
+        return [
+            {
+                title: '项目名称',
+                dataIndex: 'projectName',
+                width: '30%'
+            },
+            {
+                title: '账户名称',
+                dataIndex: 'accountName',
+                width: '30%'
+            },
+            {
+                title: '原因',
+                dataIndex: 'message',
+                width: '40%'
+            }
+        ]
+    }
+
+    // 相关项目的table列表
+    setDepColumns() {
+        return [
+            {
+                title: '项目名称',
+                dataIndex: 'projectName',
+                width: '40%'
+            },
+            {
+                title: '账户数量',
+                dataIndex: 'accountCount',
+                width: '20%'
+            },
+            {
+                title: '人群包数量',
+                dataIndex: 'count',
+                width: '20%'
+            }
+        ]
+    }
+
+    // 状态枚举
+    setStatusTasks() {
+        return [
+            {
+                label: 0,
+                value: '计算中'
+            },
+            {
+                label: 1,
+                value: '已生效'
+            },
+            {
+                label: 3,
+                value: '推送中'
+            },
+            {
+                label: 4,
+                value: '已推送'
+            },
+            {
+                label: 5,
+                value: '计算失败'
+            },
+            {
+                label: 6,
+                value: '推送失败'
+            },
+            {
+                label: 7,
+                value: '已失效'
+            }
+        ]
+    }
+
+    // 上传人去报的校验规则
+    setPersonRules() {
+        return {
+            name: [
+                {required: true, message: '人群包名称不能为空', trigger: 'blur'},
+                {min: 1, max: 20, message: '人群包名称不能超过20个字符', trigger: 'blur'}
+            ],
+            resource: [
+                {required: true, message: '请选择匹配类型', trigger: 'change'}
+            ]
+        }
+    }
+
+    // 人群包类型枚举值
+    setPopulationTypeTasks() {
+        return [
+            {
+                label: 1,
+                value: '上传人群'
+            }, {
+                label: 2,
+                value: '广告人群'
+            }, {
+                label: 3,
+                value: '主题专区'
+            }, {
+                label: 4,
+                value: '逻辑规则'
+            }, {
+                label: 5,
+                value: '人群扩展'
+            }, {
+                label: 6,
+                value: '平台制定'
+            }, {
+                label: 7,
+                value: '定制付费'
+            }, {
+                label: 8,
+                value: '网红粉丝类别'
+            }, {
+                label: 9,
+                value: '内容付费行为'
+            }, {
+                label: 10,
+                value: '移动应用安装'
+            }, {
+                label: 11,
+                value: '快手使用活跃度'
+            }, {
+                label: 12,
+                value: '行业分类'
+            }, {
+                label: 13,
+                value: '商业兴趣'
+            }, {
+                label: 14,
+                value: '固话标签'
+            }, {
+                label: 15,
+                value: '行业偏好'
+            }, {
+                label: 16,
+                value: '第三方标签'
+            }, {
+                label: 17,
+                value: '产品关键词'
+            }, {
+                label: 19,
+                value: '应用渗透率'
+            }, {
+                label: 22,
+                value: '指定网红'
+            }, {
+                label: 23,
+                value: '行业分类'
+            }
+        ]
+    }
+
+    // 匹配类型枚举值
+    setMateTypeTasks() {
+        return [
+            {
+                label: 1,
+                value: 'IMEI'
+            }, {
+                label: 2,
+                value: 'IDFA'
+            }, {
+                label: 3,
+                value: 'IMEI_MD5'
+            }, {
+                label: 4,
+                value: 'IDFA_MD5'
+            }, {
+                label: 5,
+                value: '手机号-MD5'
+            }, {
+                label: 7,
+                value: 'OAID'
+            }, {
+                label: 8,
+                value: 'OAID_MD5'
+            }
+        ]
+    }
+
+}
+
+export default new AppMarketService();

+ 110 - 0
src/views/modules/crowd-control/crowd-control.less

@@ -0,0 +1,110 @@
+.crowd-control-content {
+    background: #fff;
+    height: calc(100vh - 137px);
+    padding: 20px;
+    overflow-y: auto;
+    .control-con-header {
+        margin-bottom: 20px;
+        position: relative;
+        /deep/ .ant-form-inline .ant-form-item > .ant-form-item-control-wrapper, .ant-form-inline .ant-form-item > .ant-form-item-label {
+            width: 200px !important;
+        }
+        .reset-class {
+            margin-right: 10px !important;
+        }
+        .upload-person {
+            position: absolute;
+            right: 10px;
+            top: 0;
+        }
+    }
+    .cause-text-class {
+        cursor: pointer;
+    }
+    .pagin-table-class {
+        display: flex;
+        justify-content: flex-end;
+        margin-top: 20px;
+    }
+    .acount-search-class {
+        width: 200% !important;
+    }
+    .grid-form-type {
+        margin-left: 210px;
+    }
+}
+/deep/ .push-modal {
+    width: 600px !important;
+    .acount-title {
+        display: flex;
+        font-size: 14px;
+        height: 40px;
+        line-height: 40px;
+        .acount-title-left {
+            margin-right: 20px;
+            width: 100px;
+        }
+    }
+    .push-plate {
+        margin-bottom: 20px;
+    }
+}
+.person-modal {
+    width: 500px;
+    /deep/ .ant-form-item {
+        display: flex;
+    }
+    /deep/ .ant-form-item-label {
+        width: 20%;
+    }
+    /deep/ .ant-form-item-control-wrapper {
+        width: 80%;
+    }
+    .acount-search-class {
+        width: 100% !important;
+    }
+    .upload-txt-rules {
+        margin-top: 10px;
+        margin-bottom: 10px;
+        line-height: 1.5;
+    }
+    /deep/ .ant-radio-group {
+        line-height: 30px;
+    }
+}
+/deep/ .cause-modal {
+    width: 600px !important;
+    .cause-modal-table-class {
+        height: 500px;
+        overflow-y: auto;
+    }
+    .pagin-table-class {
+        display: flex;
+        justify-content: flex-end;
+        margin-top: 20px;
+    }
+}
+/deep/ .relax-modal {
+    width: 600px !important;
+    .acount-title {
+        display: flex;
+        font-size: 14px;
+        height: 40px;
+        line-height: 40px;
+        .acount-title-left {
+            margin-right: 20px;
+            width: 100px;
+        }
+    }
+    .push-plate {
+        margin-bottom: 20px;
+    }
+}
+
+.grid-form-item-account {
+    /deep/ .ant-form-item-control {
+        line-height: inherit;
+    }
+}
+
+

+ 669 - 0
src/views/modules/crowd-control/crowd-control.vue

@@ -0,0 +1,669 @@
+<template>
+    <div class="crowd-control-content">
+        <div class="control-con-header">
+            <a-form
+                class="grid-form" layout="inline"
+                :form="form"
+                hide-required-mark
+                @submit="handleQueryList"
+            >
+                <a-row class="grid-form-options">
+                    <a-form-item
+                        class="grid-form-item"
+                        label="名称"
+                        :colon="false"
+                    >
+                        <a-input
+                            v-decorator="['name']" type="text"
+                            placeholder="请输入"
+                        />
+                    </a-form-item>
+                    <a-form-item
+                        class="grid-form-item grid-form-item-account" label="账户"
+                        :colon="false"
+                    >
+                        <acount-search class="acount-search-class" :appId.sync="acountId" :multiple="false"></acount-search>
+                    </a-form-item>
+                    <a-form-item
+                        class="grid-form-item grid-form-type" label="状态"
+                        :colon="false"
+                    >
+                        <a-select
+                            v-decorator="['status']"
+                            placeholder="请选择"
+                            allow-clear
+                        >
+                            <a-select-option v-for="item in statusTasks" :key="item.label">
+                                {{ item.value }}
+                            </a-select-option>
+                        </a-select>
+                    </a-form-item>
+                    <a-form-item class="form-handle-btn">
+                        <a-button type="default" class="reset-class" @click="handleResetForm">重置</a-button>
+                        <a-button type="primary" html-type="submit">查询</a-button>
+                    </a-form-item>
+                </a-row>
+            </a-form>
+            <a-button type="primary" class="upload-person" @click="handleUploadPerson">
+                上传人群包
+            </a-button>
+        </div>
+        <div class="control-con-table">
+            <a-table
+                ref="table"
+                size="middle"
+                bordered
+                :columns="columns"
+                :dataSource="dataSource"
+                :pagination="false"
+            >
+                <span slot="action" slot-scope="text, record">
+                    <a @click="handleEdit(record)" :disabled="record.status !== 4">推送</a>
+                    <a-divider type="vertical" />
+                    <a @click="handleDelete(record)">删除</a>
+                </span>
+                <span slot="cause" slot-scope="text, record">
+                    <a class="cause-text-class" @click="handleCause(record)">失败原因</a>
+                </span>
+                <span slot="depRelax" slot-scope="text, record">
+                    <a @click="handleAcountRelax('dep', record)">{{ text }}</a>
+                </span>
+                <span slot="acountRelax" slot-scope="text, record">
+                    <a @click="handleAcountRelax('acount', record)">{{ text }}</a>
+                </span>
+            </a-table>
+            <a-pagination
+                class="pagin-table-class"
+                :total="totalAll"
+                :show-total="total => `共 ${totalAll} 条`"
+                size="small"
+                show-size-changer
+                show-quick-jumper
+                @change="onShowSizeChange"
+                @showSizeChange="onShowSizeChange"
+            />
+        </div>
+        <a-modal
+            v-if="personVisible"
+            title="上传人群包"
+            class="person-modal"
+            :visible="personVisible"
+            :confirm-loading="confirmLoading"
+            @ok="handleOk"
+            @cancel="handleCancel"
+        >
+            <div>
+                <a-form-model
+                    ref="ruleForm"
+                    :model="personForm"
+                    :rules="personRules"
+                    :label-col="labelCol"
+                    :wrapper-col="wrapperCol"
+                >
+                    <a-form-model-item label="匹配类型" prop="resource">
+                        <a-radio-group v-model="personForm.resource" :disabled="personResourceDisabled">
+                            <a-radio v-for="item in mateTypeTasks" :key="item.label" :value="item.label">{{ item.value }}</a-radio>
+                        </a-radio-group>
+                    </a-form-model-item>
+                    <a-form-model-item ref="name" label="人群包名称" prop="name">
+                        <a-input
+                            v-model="personForm.name"
+                            placeholder="请输入人群包名称"
+                            :disabled="personNameDisabled"
+                        />
+                    </a-form-model-item>
+                    <a-form-model-item label="选择账户" class="grid-form-item-account">
+                        <acount-search class="acount-search-class" :appId.sync="uploadAcountIds" :multiple="false"></acount-search>
+                    </a-form-model-item>
+                    <a-form-model-item label="上传人群包">
+                        <a-upload
+                            name="file"
+                            :file-list="fileList"
+                            :before-upload="beforeUpload"
+                            @change="handleChange"
+                        >
+                            <a-button><a-icon type="upload" />文件上传</a-button>
+                        </a-upload>
+                        <p class="upload-txt-rules">
+                            1、文件格式:支持上传*.txt(utf-8)文本;也支持将单个/多个*.txt文件经过Zip格式压缩上传
+                        </p>
+                        <p class="upload-txt-rules">2、文件大小:单个文件大小不能超过1G</p>
+                        <p class="upload-txt-rules">3、内容编排:每行一条记录</p>
+                    </a-form-model-item>
+                </a-form-model>
+            </div>
+        </a-modal>
+        <a-modal
+            title="推送账户"
+            v-if="pushVisible"
+            :visible="pushVisible"
+            :confirm-loading="pushConfirmLoading"
+            dialog-class="push-modal"
+            @ok="handlePushSure"
+            @cancel="handlePushCancel"
+        >
+            <div>
+                <div class="acount-title">
+                    <div class="acount-title-left">已选人群包</div>
+                    <div class="acount-title-right">{{ tableSelectList.orientationName }} (ID: {{ tableSelectList.id }})</div>
+                </div>
+                <div class="acount-title push-plate">
+                    <div class="acount-title-left">推送平台</div>
+                    <div class="acount-title-right">
+                        <a-radio-group default-value="a" button-style="solid">
+                            <a-radio-button value="a">效果</a-radio-button>
+                            <a-radio-button value="b" disabled>品牌</a-radio-button>
+                        </a-radio-group>
+                    </div>
+                </div>
+                <tree-select @applyType="handleApplyType"></tree-select>
+            </div>
+        </a-modal>
+        <a-modal
+            title="失败原因"
+            v-if="causeVisible"
+            :visible="causeVisible"
+            :confirm-loading="causeConfirmLoading"
+            :footer="null"
+            dialog-class="cause-modal"
+            @cancel="handleCauseCancel"
+        >
+            <div>
+                <div class="cause-modal-table-class">
+                    <a-table :columns="causeColumns" :data-source="causeData" bordered :pagination="false"></a-table>
+                </div>
+                <a-pagination
+                    class="pagin-table-class"
+                    :total="totalAllCause"
+                    size="small"
+                    @change="handleCauseSizeChange"
+                />
+            </div>
+        </a-modal>   
+        <a-modal
+            :title="relaxStatus === 'dep' ? '相关项目' : '相关账户'"
+            v-if="relaxVisible"
+            :visible="relaxVisible"
+            :confirm-loading="relaxConfirmLoading"
+            :footer="null"
+            dialog-class="relax-modal"
+            @cancel="handleRelaxCancel"
+        >
+            <div>
+                <div class="acount-title">
+                    <div class="acount-title-left">人群包名称</div>
+                    <div class="acount-title-right">{{ acountRelaxDetail.orientationName }}</div>
+                </div>
+                <div class="acount-title push-plate">
+                    <div class="acount-title-left">目标账户</div>
+                    <div class="acount-title-right">{{ acountRelaxDetail.accountName }}</div>
+                </div>
+                <template v-if="relaxStatus === 'dep'">
+                    <a-table :columns="depColumns" :data-source="depData" bordered>
+                    </a-table>
+                </template>
+                <template v-if="relaxStatus === 'acount'">
+                    <a-table :columns="acountColumns" :data-source="acountData" bordered></a-table>
+                </template>
+            </div>
+        </a-modal>
+    </div>
+</template>
+<script>
+import TreeSelect from './components/tree-select/tree-select';
+import {getAction, postAction} from '@/api/manage';
+import AcountSearch from '@/views/modules/Statistics/components/Treeselect.vue';
+import AppMarketService from './crowd-control-service';
+import BMF from 'browser-md5-file';
+
+let COS = require('cos-js-sdk-v5');
+let cos = new COS({
+    SecretId: 'AKIDE6IpMi8fJQRCg1iuWzFajjRs43kbbets',
+    SecretKey: 'tXzuwMfplTTK3c9GFUyETilasvQfePu9'
+});
+export default {
+    name: 'crowd-control',
+    components: {
+        TreeSelect,
+        AcountSearch
+    },
+    data() {
+        let that = this;
+        return {
+            personResourceDisabled: false,
+            personNameDisabled: false,
+            totalAllCause: 0,
+            acountId: undefined, // 搜索的账户ID
+            uploadAcountIds: '',
+            totalAll: 10,
+            finallyRightTree: [],
+            fileList: [],
+            relaxVisible: false,
+            relaxConfirmLoading: false,
+            pushVisible: false,
+            pushConfirmLoading: false,
+            causeVisible: false,
+            causeConfirmLoading: false,
+            labelCol: {span: 4},
+            wrapperCol: {span: 14},
+            personVisible: false,
+            confirmLoading: false,
+            mateTypeTasks: AppMarketService.setMateTypeTasks(), // 匹配类型
+            populationTypeTasks: AppMarketService.setPopulationTypeTasks(), // 人群包类型
+            statusTasks: AppMarketService.setStatusTasks(), // 状态枚举
+            relaxStatus: '',
+            causeData: [], // 原因的table列表数据,
+            depData: [], // 相关项目的table列表数据,
+            acountData: [], // 相关账户的table列表数据,
+            acountColumns: AppMarketService.setAcountColumns(), // 相关账户的table列表
+            depColumns: AppMarketService.setDepColumns(), // 相关项目的table列表
+            causeColumns: AppMarketService.setCauseColumns(), // 原因的table列表
+            dataSource: [],
+            columns: [
+                {
+                    title: '人群包名称',
+                    align: 'center',
+                    width: 200,
+                    ellipsis: true,
+                    dataIndex: 'orientationName'
+                },
+                {
+                    title: '人群包类型',
+                    align: 'center',
+                    dataIndex: 'populationType',
+                    customRender(t) {
+                        return t ? that.populationTypeTasks.find(item => item.label === Number(t)).value : '-';
+                    }
+                },
+                {
+                    title: '匹配类型',
+                    align: 'center',
+                    dataIndex: 'typeStr'
+                },
+                {
+                    title: '上传时间',
+                    dataIndex: 'statDate',
+                    align: 'center'
+                },
+                {
+                    title: '覆盖数量',
+                    dataIndex: 'coverNum',
+                    align: 'center'
+                },
+                {
+                    title: '状态',
+                    dataIndex: 'statusStr',
+                    align: 'center'
+                },
+                {
+                    title: '原因',
+                    dataIndex: '',
+                    align: 'center',
+                    scopedSlots: {customRender: 'cause'}
+                },
+                {
+                    title: '目标账户',
+                    dataIndex: 'accountName',
+                    align: 'center',
+                    ellipsis: true
+                },
+                {
+                    title: '相关项目',
+                    dataIndex: 'projectCount',
+                    align: 'center',
+                    scopedSlots: {customRender: 'depRelax'}
+                },
+                {
+                    title: '相关账户',
+                    dataIndex: 'accountCount',
+                    align: 'center',
+                    scopedSlots: {customRender: 'acountRelax'}
+                },
+                {
+                    title: '操作',
+                    dataIndex: 'action',
+                    align: 'center',
+                    scopedSlots: {customRender: 'action'}
+                }
+            ],
+            personForm: {
+                name: '',
+                resource: ''
+            },
+            personRules: AppMarketService.setPersonRules(), // 上传人群包表单校验规则
+            tablePag: {
+                page: 1,
+                size: 10
+            },
+            // table 原因的分页
+            causePag: {
+                page: 1,
+                size: 10
+            },
+            tableSelectList: {},
+            acountRelaxDetail: {},
+            causeDetailData: {}
+        };
+    },
+    created() {
+        this.form = this.$form.createForm(this);
+    },
+    mounted() {
+        this.handleGetTableList({});
+    },
+    methods: {
+        onShowSizeChange(current, pageSize) {
+            const paramsData = this.form.getFieldsValue();
+            this.tablePag = {
+                page: current,
+                size: pageSize
+            };
+            this.handleGetTableList(paramsData);
+        },
+        handleCauseSizeChange(current, pageSize) {
+            this.causePag = {
+                page: current,
+                size: pageSize
+            };
+            this.handleCauseTableData();
+        },
+        handleGetTableList(data) {
+            const paramsData = {
+                orientationName: data.name,
+                accountId: this.acountId,
+                status: data.status,
+                pageNo: this.tablePag.page,
+                pageSize: this.tablePag.size
+            };
+            this.dataSource = []
+            getAction('/kuaishouCrowdPack/queryPageList', paramsData).then(result => {
+                if (result.code === 200) {
+                    this.dataSource = result.result.list || [];
+                    this.totalAll = result.result.total || 0;
+                }
+                else {
+                    this.$message.error(result.message);
+                }
+            }).catch(error => {
+                console.log(error, 'eeee');
+            });
+        },
+        handleDelete(data) {
+            let that = this
+            this.$confirm({
+                title: '删除提示',
+                content: '确定要删除这一条吗?',
+                onOk() {
+                    getAction('/kuaishouCrowdPack/delete', {id: data.id}).then(result => {
+                        if (result.code === 200) {
+                            that.handleGetTableList({});
+                            that.$message.success('删除成功');
+                        }
+                        else {
+                            that.$message.error(result.message);
+                        }
+                    }).catch(error => {
+                        console.log(error, 'eeee');
+                    });
+                }
+            });
+        },
+        handleAcountRelaxTable() {
+            const paramsData = {
+                signature: this.acountRelaxDetail.signature,
+                accountId: this.acountRelaxDetail.accountId,
+                type: this.relaxStatus === 'dep' ? 1 : 2
+            };
+            getAction('/kuaishouCrowdPack/queryRel', paramsData).then(result => {
+                if (result.code === 200) {
+                    if (this.relaxStatus === 'dep') {
+                        this.depData = result.result.list;
+                    }
+                    else if (this.relaxStatus === 'acount') {
+                        this.acountData = result.result.list;
+                    }
+                }
+                else {
+                    this.$message.error(result.message);
+                }
+            }).catch(error => {
+                console.log(error, 'eeee');
+            });
+        },
+        handleAcountRelax(txt, recd) {
+            if (txt === 'dep') {
+                this.relaxStatus = 'dep';
+            }
+            else if (txt === 'acount') {
+                this.relaxStatus = 'acount';
+            }
+            this.acountRelaxDetail = recd;
+            this.handleAcountRelaxTable();
+            this.relaxVisible = true;
+        },
+        handleRelaxCancel() {
+            this.relaxVisible = false;
+        },
+        handleCause(list) {
+            this.causeVisible = true;
+            this.causeDetailData = list;
+            this.handleCauseTableData();
+        },
+        handleCauseTableData() {
+            const paramsData = {
+                signature: this.causeDetailData.signature,
+                pageNo: this.causePag.page,
+                pageSize: this.causePag.size
+            };
+            getAction('/kuaishouCrowdPack/queryFailReason', paramsData).then(result => {
+                if (result.code === 200) {
+                    this.causeData = result.result.list || [];
+                    this.totalAllCause = result.result.total || 0;
+                }
+                else {
+                    this.$message.error(result.message);
+                }
+            }).catch(error => {
+                console.log(error, 'eeee');
+            });
+        },
+        handleApplyType(list) {
+            this.finallyRightTree = list;
+        },
+        handleEdit(val) {
+            this.tableSelectList = val;
+            this.pushVisible = true;
+        },
+        handleCauseCancel() {
+            this.causeVisible = false;
+        },
+        handlePushSure() {
+            const paramsData = {
+                accountIds: this.finallyRightTree.map(item => item.key),
+                signature: this.tableSelectList.signature,
+                accountId: this.tableSelectList.accountId
+            };
+            postAction('/kuaishouCrowdPack/accountPush', paramsData).then(result => {
+                if (result.code === 200) {
+                    this.pushVisible = false;
+                    this.handleGetTableList({});
+                }
+                else {
+                    this.$message.error(result.message);
+                }
+            }).catch(error => {
+                console.log(error, 'eeeeeee');
+            });
+        },
+        handlePushCancel() {
+            this.pushVisible = false;
+        },
+        beforeUpload(file) {
+            this.cosUpload(file);
+        },
+        handleMd5(file) {
+            let bmf = new BMF();
+            let that = this;
+            return new Promise(function (resolve, reject) {
+                bmf.md5(file, (err, md5) => {
+                    getAction('/kuaishouCrowdPack/checkCrowdPackage', {signature: md5}).then(result => {
+                        if (result.code === 200) {
+                            that.personNameDisabled = false;
+                            that.personResourceDisabled = false;
+                            resolve();
+                        }
+                        else if (result.code === 201) {
+                            that.$message.error(result.message);
+                            that.personForm.name = result.result.orientationName;
+                            that.personForm.resource = result.result.type;
+                            that.personNameDisabled = true;
+                            that.personResourceDisabled = true;
+                            reject();
+                        }
+                    }).catch(error => {
+                        console.log(error, 'eeee');
+                        reject();
+                    });
+                })
+            })
+        },
+        handleChange(info) {
+            this.fileList = info.fileList;
+        },
+        cosUpload(file) {
+            let that = this;
+            let date = new Date();
+            let y = date.getFullYear();
+            let MM = date.getMonth() + 1;
+            MM = MM < 10 ? '0' + MM : MM;
+            let d = date.getDate();
+            d = d < 10 ? '0' + d : d;
+            let timeElse = new Date().getTime();
+            let arr = file.name.split('.');
+            let str = '';
+            for (let i = 0; i < arr.length; i++) {
+                if (i === arr.length - 1) {
+                }
+                else {
+                    if (i === arr.length - 2) {
+                        str += arr[i];
+                    }
+                    else {
+                        str += arr[i] + '.';
+                    }
+                }
+            }
+            cos.putObject(
+                {
+                    Bucket: 'media-1301855440',
+                    Region: 'ap-chongqing',
+                    // 存储桶所在地域,必须字段
+                    Key: that.uploadType + '/' + y + '-' + MM + '-' + d + '/' + str + '-' + timeElse + '.' + arr[arr.length - 1],
+                    StorageClass: 'STANDARD',
+                    Body: file // 上传文件对象
+                },
+                function (err, data) {
+                    if (err) {
+                        that.$message.error('上传失败!!!' + err);
+                        return;
+                    }
+                    that.loadingElse = false;
+                    that.fileList.push({
+                        uid: file.name,
+                        name: file.name,
+                        status: 'done',
+                        url: '//' + data.Location
+                    });
+                    if (that.fileList.length > 1) {
+                        that.fileList = that.fileList.slice(-1);
+                    }
+                    const isZip = file.type.includes('zip') || file.type.includes('text');
+                    const fileOvesize = file.size > (1024 * 1024 * 1024);
+                    if (!isZip) {
+                        that.$message.error('只能上传zip格式的文件或者txt文件');
+                        return;
+                    }
+                    if (fileOvesize) {
+                        that.$message.error('文件大小不能超过1G');
+                        return;
+                    }
+                    that.handleMd5(file);
+                }
+            );
+        },
+        handleQueryList(event) {
+            event.preventDefault();
+            const paramsData = this.form.getFieldsValue();
+            this.handleGetTableList(paramsData);
+        },
+        handleResetForm() {
+            this.form.resetFields();
+            this.acountId = undefined;
+            this.handleGetTableList({});
+        },
+        handleUploadPerson() {
+            this.personVisible = true;
+        },
+        handleOk() {
+            this.$refs.ruleForm.validate(valid => {
+                if (valid) {
+                    if (!this.uploadAcountIds) {
+                        this.$message.error('请选择账户');
+                        return;
+                    }
+                    if (!this.fileList.length) {
+                        this.$message.error('请上传文件');
+                        return;
+                    }
+                    this.confirmLoading = true
+                    this.handleUploadRuleForm();
+                }
+                else {
+                    return false;
+                }
+            });
+        },
+        handleUploadRuleForm() {
+            const paramsData = {
+                type: this.personForm.resource,
+                orientationName: this.personForm.name,
+                accountId: this.uploadAcountIds,
+                url: this.fileList[0].url
+            };
+            postAction('/kuaishouCrowdPack/uploadCrowdPack', paramsData).then(result => {
+                this.confirmLoading = false
+                if (result.code === 200) {
+                    this.personVisible = false;
+                    this.personResourceDisabled = false;
+                    this.personNameDisabled = false;
+                    this.$message.success('上传成功');
+                    this.handleGetTableList({});
+                    this.fileList = [];
+                    this.personForm.name = '';
+                    this.personForm.resource = '';
+                    this.uploadAcountIds = undefined;
+                }
+                else {
+                    this.$message.error(result.message);
+                }
+            }).catch(error => {
+                console.log(error, 'eeee');
+            });
+        },
+        handleCancel() {
+            this.confirmLoading = false
+            this.personVisible = false;
+            this.personResourceDisabled = false;
+            this.personNameDisabled = false;
+            this.$refs.ruleForm.resetFields();
+            this.uploadAcountIds = '';
+            this.personForm.name = '';
+            this.personForm.resource = '';
+            this.fileList = [];
+        }
+    }
+};
+</script>
+<style lang="less" scoped>
+    @import "crowd-control";
+</style>

+ 15 - 3
src/views/modules/kuaishouapp/batchCreation/creat/creatUnit.vue

@@ -111,7 +111,7 @@
       <a-modal v-model="convert" title="选择转化目标">
         <template slot="footer">
           <a-button key="back" @click="convert = false">取消</a-button>
-          <a-button key="submit" type="primary" @click="convert = false"> 确定 </a-button>
+          <a-button key="submit" type="primary" @click="convertOk"> 确定 </a-button>
         </template>
         <a-form-item
           label="追踪方式"
@@ -1197,7 +1197,7 @@ export default {
       checkVideo: [],
       checkVideoAll: [],
       checkVideoWai: [],
-      checkVideoWhole:[],
+      checkVideoWhole: [],
       dataSource: [],
       active: 0,
       time: [],
@@ -1274,6 +1274,7 @@ export default {
         description: '',
       },
       convertType: '1',
+      convertAllList: [],
       dataList: [],
       clickTrackUrlShow: false,
       clickTrackUrlShowType: '1',
@@ -1896,6 +1897,16 @@ export default {
         }
       })
     },
+    convertOk() {
+      var dataLink = []
+      dataLink = this.convertAllList.filter((item) => {
+        return item.convert_id == this.convertId.key
+      })
+      if (dataLink.length > 0) {
+        this.form.setFieldsValue({ clickTrackUrl: dataLink[0].click_url })
+        this.convert = false
+      }
+    },
     showConvert() {
       this.convertChange()
       if (this.campaignType == 2) {
@@ -1930,6 +1941,7 @@ export default {
               convert_id: item.convert_id + '',
             }
           })
+          this.convertAllList.push(...this.convertList)
         }
       })
     },
@@ -1947,7 +1959,7 @@ export default {
         unitNameCheck: false,
         deepConversionType: '',
         deepConversionBid: '',
-        ocpxActionType:  this.allForm.groupTypeData.isActivate == '1' ? 180 : 2,
+        ocpxActionType: this.allForm.groupTypeData.isActivate == '1' ? 180 : 2,
       })
     },
     resData(index) {

+ 92 - 2
src/views/modules/material/accountCheckBytedance.vue

@@ -2,11 +2,100 @@
 .select-project {
   width: 50%;
 }
+.row-item {
+  display: flex;
+  justify-content: flex-start;
+  align-items: center;
+}
+.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: 9px;
+}
+.row-item .label-item {
+  position: relative;
+  align-items: flex-start;
+  align-self: flex-start;
+  line-height: 20px;
+  height: 20px;
+  margin-top: 10px;
+  width: 140px;
+  //   min-width: 80px;
+  .text-item {
+    font-size: 14px;
+    width: 120px;
+  }
+}
+.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;
+  }
+  .inventory-tags-lists-header {
+    background-color: #F8F9FA;
+    border: 1px solid #E4E9ED;
+    height: 36px;
+    line-height: 33px;
+    border-radius: 4px 4px 0 0;
+    font-weight: bold;
+    display: flex;
+  }
+
+  .inventory-tags-lists-container {
+    border: 1px solid #E4E9ED;
+    margin-top: -1px;
+    height: 100%;
+    padding: 4px 0px;
+    border-radius: 0 0 4px 4px;
+  }
+
+  .inventory-tags-lists-item {
+    width: 100%;
+    height: 37px;
+    line-height: 37px;
+    padding-left: 12px;
+    padding-right: 12px;
+    display: flex;
+    font-size: 14px;
+    color: #333;
+  }
+}
 </style>
 <template>
   <div class="select-project">
     <a-modal title="账户选择" v-model="showEdit" @ok="handleOk" @cancel="close" width="80%">
-      {{ value }}
+      <!-- <span style="margin-bottom:15px">是否同步快手主页</span> -->
+      <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-switch v-model="shieldBackwardSwitch" />
+          </a-form-item>
+        </div>
+      </div>
       <!-- <treeselect
         :multiple="multiple"
         :disable-branch-nodes="!multiple"
@@ -67,6 +156,7 @@ export default {
       label: 'label',
       id: 'id',
     },
+    shieldBackwardSwitch: true,
     showEdit: false,
     value: null,
     valueConsistsOf: 'LEAF_PRIORITY',
@@ -123,7 +213,7 @@ export default {
       console.log(e)
       var data = this.$refs.tree.getCheckedKeys()
       this.showEdit = false
-      this.$emit('synchro', data)
+      this.$emit('synchro', {treeData:data,shieldBackwardSwitch:this.shieldBackwardSwitch})
     },
     close() {
       this.showEdit = false

+ 13 - 6
src/views/modules/material/videoMaterial.vue

@@ -2207,10 +2207,15 @@ export default {
       })
     },
     implement(data) {
+      // {treeData:data,shieldBackwardSwitch:this.shieldBackwardSwitch}
       var params = {}
       params.mediaId = this.mediaId
       params.materialArray = JSON.stringify(this.checkArr)
-      params.accountArray = JSON.stringify(data)
+      params.accountArray = data.treeData?JSON.stringify(data.treeData):JSON.stringify(data)
+      if(this.mediaId == '2'){
+        params.shieldBackwardSwitch = data.shieldBackwardSwitch
+      }
+      
       postAction('/ctop/materialUpload/uploadAccount', params).then((res) => {
         if (res.code == 0) {
           this.checkArr = []
@@ -2498,12 +2503,14 @@ export default {
       getAction('/ctop/materialInfo/getDetail', {
         materialId: item.id,
       }).then((res) => {
-        this.formPerson.setFieldsValue({
-          clipId: res.ascription.clipId,
-          planId: res.ascription.planId,
-          shotId: res.ascription.shotId,
-        })
         this.code = item.code
+        if (res.ascription) {
+          this.formPerson.setFieldsValue({
+            clipId: res.ascription.clipId,
+            planId: res.ascription.planId,
+            shotId: res.ascription.shotId,
+          })
+        }
       })
     },
     edit(item, status, editStatus) {

+ 31 - 21
src/views/modules/stockWatch/accountPage.vue

@@ -1017,15 +1017,15 @@ const columns=[
                 return current  && !(current > (moment().subtract(1,'months')) && current < moment())
             }, 
             onChange(date, dateString) {                
-                console.log(date, dateString);
+                // console.log(date, dateString);
                 this.getAllIndex();
                 this.getAccountIndexData();
 
                 if(dateString.length>0&&dateString[0]!=dateString[1]){
                     let interval=date[1].diff(date[0],'days')
-                    console.log(interval);
+                    // console.log(interval);
                     this.dateStringShow=`${moment(date[0]).subtract(1+interval,'days').format('YYYY-MM-DD')}~${moment(date[0]).subtract(1,'days').format('YYYY-MM-DD')}`
-                    console.log(this.dateStringShow)
+                    // console.log(this.dateStringShow)
                 }
             },
             materialDataChange(date, dateString){
@@ -1147,7 +1147,7 @@ const columns=[
                     ]
                 };
                 //单一天数
-                console.log(data)
+                // console.log(data)
                 
                 if(this.dateValue[0].format('YYYY-MM-DD')==this.dateValue[1].format('YYYY-MM-DD')){
                     option.xAxis[0].data=data.xData;
@@ -1159,12 +1159,12 @@ const columns=[
                     option.xAxis[0].data=data.xData?data.xData.yesterday:[]
                     option.xAxis[1].data=data.xData?data.xData.today:[]
                    
-                }
+                } 
                 option.series[0].name=data.yData?data.yData.yesterday.name:''
                 option.series[1].name=data.yData?data.yData.today.name:''
                 option.series[0].data=data.yData?data.yData.yesterday.data:[]
                 option.series[1].data=data.yData?data.yData.today.data:[] 
-                console.log(option)
+                // console.log(option)
                 return option
             },  
 
@@ -2112,7 +2112,7 @@ const columns=[
                         data.legend.push(item.type)
                     }   
                 });
-                console.log(data)
+                // console.log(data)
                 data.legend.forEach((item,index)=>{
                     data.yData.push({
                         name:item,
@@ -2130,7 +2130,7 @@ const columns=[
                          
                     });
                 })
-                console.log(data)
+                // console.log(data)
                 return data       
             },
             // 性别对应数据图
@@ -2294,19 +2294,29 @@ const columns=[
             //         this.accountPageSpinning=false 
             //     }
             // })
-            getAction('/etl/reportAccountHourly/getMaxChargeAccountIdByUser',{                
-                userId:this.userInfo().id,
-            }).then(res=>{
-                if(res.success){
-                    // this.currentAccount=res.result;
-                    this.accountId=res.result;
-                    this.selectaccountId=res.result;
-                    this.accountPageSpinning=false;
-                }else{
-                    // this.$message.error(res.message)
-                    this.accountPageSpinning=false; 
-                }
-            })
+            if(localStorage.getItem('stockWatchAccountId')) {
+                let data = JSON.parse(localStorage.getItem('stockWatchAccountId'));
+                this.accountId = data.accountId;
+                this.selectaccountId = data.accountId;
+                this.dateValue = [moment(data.timeRange[0]),moment(data.timeRange[1])];
+                this.accountPageSpinning = false;
+            }
+            else {
+                getAction('/etl/reportAccountHourly/getMaxChargeAccountIdByUser',{                
+                    userId:this.userInfo().id,
+                }).then(res=>{
+                    if(res.success){
+                        // this.currentAccount=res.result;
+                        this.accountId=res.result;
+                        this.selectaccountId=res.result;
+                        this.accountPageSpinning=false;
+                    }else{
+                        // this.$message.error(res.message)
+                        this.accountPageSpinning=false; 
+                    }
+                })
+            }
+            
          
         },
         filters:{

+ 3 - 0
src/views/modules/stockWatch/keep-market.less

@@ -0,0 +1,3 @@
+.keep-market-content {
+    
+}

+ 27 - 0
src/views/modules/stockWatch/keep-market.vue

@@ -0,0 +1,27 @@
+<template>
+    <div class="keep-market-content"></div>
+</template>
+<script>
+export default {
+    name: 'keep-market',
+    data() {
+        return {
+            rotureType: 'person'
+        };
+    },
+    mounted() {
+        if (this.rotureType === 'person') {
+            this.$router.push('/modules/stockWatch/modules/keep-person/keep-person');
+        }
+        else if (this.rotureType === 'manage') {
+            this.$router.push('/modules/stockWatch/modules/keep-manage/keep-manage');
+        }
+    },
+    methods: {
+
+    }
+};
+</script>
+<style lang="less" scoped>
+    @import "keep-market";
+</style>

+ 109 - 0
src/views/modules/stockWatch/modules/custom-columns/custom-columns.less

@@ -0,0 +1,109 @@
+/deep/ .custom-columns-modal {
+    width: 800px !important;
+    .custom-modal-content {
+        .input-search {
+            width: 200px;
+            margin: 10px 0 10px 0;
+        }
+        .class-left-header {
+            height: 50px;
+            line-height: 50px;
+            background-color: #ccc;
+            padding: 0 10px;
+            display: flex;
+            justify-content: space-between;
+        }
+        .active {
+            background: #ccc;
+            color:cyan;
+            cursor: pointer;
+        }
+        .modal-content-table {
+            display: flex;
+            justify-content: space-between;
+            .select-class-left {
+                width: 65%;
+                height: 400px;
+                border: 1px solid #ccc;
+                .class-left-main {
+                    display: flex;
+                    .left-main-left {
+                        width: 140px;
+                        border-right: 1px solid #ccc;
+                        .main-left-select {
+                            height: 40px;
+                            line-height: 40px;
+                            text-align: center;
+                        }
+                    }
+                    .left-main-right {
+                        width: 100%;
+                        height: 348px;
+                        overflow-y: auto;
+                        padding: 10px;
+                        .main-right-class {
+                            height: 200px;
+                            .check-box-p {
+                                height: 20px;
+                                line-height: 20px;
+                            }
+                            .check-box-select-muster {
+                                .check-box-class {
+                                    display: inline-block;
+                                    width: 50%;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            .select-class-right {
+                width: 30%;
+                height: 400px;
+                border: 1px solid #ccc;
+                .class-left-content {
+                    padding: 0 10px;
+                    height: 348px;
+                    overflow-y: auto;
+                    .apply-right-tree {
+                        display: flex;
+                        justify-content: space-between;
+                        align-items: baseline;
+                        .left-content-p {
+                            display: inline-block;
+                            width: 85%;
+                            height: 25px;
+                            line-height: 25px;
+                            margin: 0;
+                            overflow: hidden;
+                            text-overflow: ellipsis;
+                            white-space: nowrap;
+                        }
+                        .delete-type-class {
+                            color: #1890ff;
+                            cursor: pointer;
+                        }
+                    }
+                }
+                .no-data-class {
+                    height: 340px;
+                    line-height: 340px;
+                    text-align: center;
+                }
+            }
+        }
+    }
+    // .acount-title {
+    //     display: flex;
+    //     font-size: 14px;
+    //     height: 40px;
+    //     line-height: 40px;
+    //     .acount-title-left {
+    //         margin-right: 20px;
+    //         width: 100px;
+    //     }
+    // }
+    // .push-plate {
+    //     margin-bottom: 20px;
+    // }
+}

+ 149 - 0
src/views/modules/stockWatch/modules/custom-columns/custom-columns.vue

@@ -0,0 +1,149 @@
+<template>
+    <a-modal
+        title="自定义列表"
+        :visible="visible"
+        dialog-class="custom-columns-modal"
+        @ok="handleOk"
+        @cancel="handleCancel"
+    >
+        <div class="custom-modal-content">
+            <a-input-search class="input-search" placeholder="请输入指标名称" @change="onChange" />
+            <div class="modal-content-table">
+                <div class="select-class-left">
+                    <div class="class-left-header">可添加的列</div>
+                    <div class="class-left-main">
+                        <div class="left-main-left">
+                            <div
+                                class="main-left-select"
+                                v-for="(item, index) in selectLeftList"
+                                :key="index"
+                                :class="{active: cur === index}"
+                                @click="handleSelectNum(index)"
+                            >
+                                {{item}}
+                            </div>
+                        </div>
+                        <div class="left-main-right">
+                            <div v-show="isConNumOne" class="main-right-class">
+                                <p class="check-box-p">展示数据</p>
+                                <div class="check-box-select-muster">
+                                    <a-checkbox-group @change="handleChangeBox">
+                                        <span
+                                            class="check-box-class"
+                                            v-for="(item, index) in selectCheckboxData"
+                                            :key="index"
+                                        >
+                                            <a-checkbox :value="item">{{ item }}</a-checkbox>
+                                        </span>
+                                    </a-checkbox-group>
+                                </div>
+                            </div>
+                            <div v-show="isConNumTwo" class="main-right-class">内容二</div>
+                            <div v-show="isConNumThree" class="main-right-class">内容三</div>
+                            <div v-show="isConNumFour" class="main-right-class">内容四</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="select-class-right">
+                    <div class="class-left-header">
+                        <span>已选100个</span>
+                        <span><a @click="handleClearAll">清空全部</a></span>
+                    </div>
+                    <div v-if="applyTypeOption.length" class="class-left-content">
+                        <div class="apply-right-tree" v-for="(item, index) in applyTypeOption" :key="index">
+                            <p class="left-content-p">
+                                <a-tooltip placement="left">
+                                    <template slot="title">
+                                        <span>{{ item }}</span>
+                                    </template>
+                                    {{ item }}
+                                </a-tooltip>
+                            </p>
+                            <a-icon type="delete" class="delete-type-class" @click="handleDelTree(item)" />
+                        </div>
+                    </div>
+                    <div v-else class="no-data-class">暂无数据</div>
+                </div>
+            </div>
+        </div>
+    </a-modal>
+</template>
+<script>
+export default {
+    name: 'custom-columns',
+    props: {
+        visible: {
+            type: Boolean,
+            default: false
+        }
+    },
+    data() {
+        return {
+            selectCheckboxData: ['花费', '封面曝光数', '行为数', '举报书', '拉黑数', '评论数'],
+            selectLeftList: ['111', '222', '333', '444'],
+            cur: 0,
+            isConNumOne: true,
+            isConNumTwo: true,
+            isConNumThree: true,
+            isConNumFour: true,
+            applyTypeOption: []
+        };
+    },
+    mounted() {
+
+    },
+    methods: {
+        handleDelTree(item) {
+            console.log(item, 'item');
+            this.applyTypeOption = [];
+        },
+        handleChangeBox(val) {
+            console.log(val, 'checkboc111');
+            this.applyTypeOption = val;
+        },
+        handleSelectNum(index) {
+            this.cur = index;
+            if (index === 0) {
+                this.isConNumOne = true;
+                this.isConNumTwo = true;
+                this.isConNumThree = true;
+                this.isConNumFour = true;
+            }
+            else if (index === 1) {
+                this.isConNumOne = false;
+                this.isConNumTwo = true;
+                this.isConNumThree = true;
+                this.isConNumFour = true;
+            }
+            else if (index === 2) {
+                this.isConNumOne = false;
+                this.isConNumTwo = false;
+                this.isConNumThree = true;
+                this.isConNumFour = true;
+            }
+            else if (index === 3) {
+                this.isConNumOne = false;
+                this.isConNumTwo = false;
+                this.isConNumThree = false;
+                this.isConNumFour = true;
+            }
+        },
+        handleOk() {
+            console.log('这个是确定按钮');
+        },
+        handleCancel() {
+            console.log('这个是取消按钮');
+            this.$emit('cancelClick', false);
+        },
+        onChange(e) {
+            console.log(e.target.value, '---------');
+        },
+        handleClearAll() {
+            console.log('清空全部按钮事件');
+        }
+    }
+};
+</script>
+<style lang="less" scoped>
+    @import "custom-columns";
+</style>

+ 261 - 0
src/views/modules/stockWatch/modules/keep-manage/keep-manage-data.js

@@ -0,0 +1,261 @@
+/**
+ * @file 盯盘基础展示数据
+ * @author zhuxinbo(zhuxinbo@c-top.com.cn)
+ */
+import moment from 'moment'
+class keepPersonServer {
+    constructor() {}
+
+    // 固定不可删除的列-账户
+    setNoDeleteColumns() {
+        return [
+            {
+                title: '账户名称',
+                dataIndex: 'authName',
+                scopedSlots: { customRender: 'authName' },
+                align: 'center',
+                key: 'date',
+                width: 200,
+                fixed: 'left',
+            },
+            {
+                title: '运营人员',
+                dataIndex: 'realname',
+                align: 'center',
+                width: 100,
+                fixed: 'left',
+            },
+            {
+                title: '消耗',
+                dataIndex: 'cost',
+                scopedSlots: { customRender: 'cost' },
+                align: 'center',
+                width: 100,
+                fixed: 'left',
+                sorter: () => {},
+            },
+            {
+                title: '余额',
+                dataIndex: 'totalBalance',
+                align: 'center',
+                width: 100,
+                fixed: 'left',
+                sorter: () => {},
+            },
+            {
+                title: '预算',
+                dataIndex: 'budget',
+                width: 150,
+                tip: '广告在投放期间的花费总额',
+                align: 'center',
+                customRender: function (text) {
+                    if (text>0) {
+                        return text
+                    } else {
+                        return '不限制预算'
+                    }
+                },
+            }
+        ]
+    }
+
+    // 固定不可删除的列-项目
+    setNoDeleteProjectColumns() {
+        return [
+            {
+                title: '项目名称',
+                dataIndex: 'projectName',
+                scopedSlots: { customRender: 'projectName' },
+                align: 'center',
+                key: 'date',
+                width: 200,
+                fixed: 'left',
+            },
+            {
+                title: '账户数量',
+                dataIndex: 'accountCount',
+                align: 'center',
+                width: 100,
+                fixed: 'left',
+            },
+            {
+                title: '运营人数',
+                dataIndex: 'userCount',
+                scopedSlots: { customRender: 'userCount' },
+                align: 'center',
+                width: 100,
+                fixed: 'left',
+            },
+            {
+                title: '花费',
+                dataIndex: 'cost',
+                align: 'center',
+                width: 100,
+                fixed: 'left',
+                sorter: () => {},
+            }
+        ]
+    }
+
+    // 默认初始展示列
+    setDefaultColumns() {
+        return [
+            {
+                title: '封面曝光数',
+                dataIndex: 'photoShow',
+                tip: '广告在瀑布流被观看次数',
+                align: 'center',
+                scopedSlots: { customRender: 'photoShow' },
+                sorter: () => {},
+            },
+            {
+                title: '封面点击数',
+                dataIndex: 'photoClick',
+                tip: '用户点击封面进入视频播放页的次数(数据会进行反作弊去重)',
+                align: 'center',
+        
+                scopedSlots: { customRender: 'photoClick' },
+                sorter: () => {},
+            },
+            {
+                title: '封面点击率',
+                dataIndex: 'clickRate',
+                tip: '封面点击数占封面展示数百分比',
+                align: 'center',
+                scopedSlots: { customRender: 'clickRate' },
+                sorter: () => {},
+            },
+            {
+                title: '素材曝光数',
+                dataIndex: 'aClick',
+                tip: '用户进入视频播放页观看的次数(数据会进行反作弊去重)',
+                align: 'center',
+        
+                scopedSlots: { customRender: 'aClick' },
+                sorter: () => {},
+            },
+            {
+                title: '行为数',
+                dataIndex: 'bClick',
+                tip: '用户在视频播放页单击转化按钮的次数/展示数*100%',
+                align: 'center',
+        
+                scopedSlots: { customRender: 'bClick' },
+                sorter: () => {},
+            },
+        
+            {
+                title: '行为率',
+                dataIndex: 'bClickRate',
+                tip: '行为数占素材曝光数百分比',
+                align: 'center',
+                scopedSlots: { customRender: 'bClickRate' },
+                sorter: () => {},
+            },
+            {
+                title: '平均千次封面曝光花费(元)',
+                dataIndex: 'cpm',
+                tip: '花费/封面曝光数*1000',
+                align: 'center',
+                scopedSlots: { customRender: 'cpm' },
+                sorter: () => {},
+            },
+            {
+                title: '平均封面点击单价(元)',
+                dataIndex: 'cpc',
+                tip: '花费/封面点击数',
+                align: 'center',
+                scopedSlots: { customRender: 'cpc' },
+                sorter: () => {},
+            },
+            {
+                title: '平均行为单价(元)',
+                dataIndex: 'cpb',
+                tip: '总花费/行为数',
+                align: 'center',
+                scopedSlots: { customRender: 'cpb' },
+                sorter: () => {},
+            },
+        ]
+    }
+
+    //时间段筛选
+    setTimeRange() {
+        return {
+            昨天: [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
+            // 今天: [moment(), moment()],
+    
+            近三天: [moment().subtract(3, 'days'), moment().subtract(1, 'days')],
+            近一周: [moment().subtract(7, 'days'), moment().subtract(1, 'days')],
+            近14天: [moment().subtract(14, 'days'), moment().subtract(1, 'days')],
+            近一月: [moment().subtract(1, 'months'), moment().subtract(1, 'days')],
+            近半年: [moment().subtract(6, 'months'), moment().subtract(1, 'days')],
+            近一年: [moment().subtract(12, 'months'), moment().subtract(1, 'days')],
+        }
+    }
+
+    //运营人员表格字段
+    setOperateField() {
+        return  [
+            {
+                title: '运营人员',
+                dataIndex: 'realName',
+                scopedSlots: { customRender: 'realName' },
+                align: 'center',
+                key: 'date',
+                width: 100,
+            },
+            {
+                title: '账户数量',
+                dataIndex: 'accountCount',
+                align: 'center',
+                width: 100,
+            },
+            {
+                title: '消耗',
+                dataIndex: 'charge',
+                scopedSlots: { customRender: 'charge' },
+                align: 'center',
+                width: 150,
+            },
+            {
+                title: '本周消耗',
+                dataIndex: 'weekCharge',
+                align: 'center',
+                width: 150,
+            },
+            {
+                title: '消耗环比',
+                dataIndex: 'grew',
+                width: 150,
+                tip: '广告在投放期间的花费总额',
+                align: 'center',
+            },
+            {
+                title: '有效素材数',
+                dataIndex: 'effectiveCount',
+                width: 150,
+                tip: '广告在投放期间的花费总额',
+                align: 'center',
+            },
+            {
+                title: '新上计划数',
+                dataIndex: 'campaignCount',
+                width: 150,
+                tip: '广告在投放期间的花费总额',
+                align: 'center',
+            },
+            {
+                title: '新上组数',
+                dataIndex: 'unitCount',
+                width: 150,
+                tip: '广告在投放期间的花费总额',
+                align: 'center',
+            }
+        ]
+    }
+
+
+}
+
+export default new keepPersonServer();

+ 158 - 0
src/views/modules/stockWatch/modules/keep-manage/keep-manage.less

@@ -0,0 +1,158 @@
+.keep-manage-content {
+    /deep/ .keep-manage-col {
+        min-height: 300px;
+        margin-bottom: 20px;
+    }
+    .echarts-card {
+        /deep/  .ant-card-body {
+            padding: 0;
+        }
+    }
+    .keep-person-content {
+        .person-content-title {
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            height: 60px;
+            background: #fff;
+            padding: 0 20px;
+            .content-title-acount {
+                font-size: 20px;
+            }
+            .content-title-checkout {
+                .title-checkout-custom {
+                    cursor: pointer;
+                }
+                .title-checkout-time {
+                    margin-left: 20px;
+                }
+            }
+        }
+        .pagin-table-class {
+            display: flex;
+            justify-content: flex-end;
+            margin-top: 20px;
+        }
+    }
+    .title-checkout-select {
+        /deep/ .ant-select-enabled {
+            width: 150px;
+            margin-left: 10px;
+        }
+        
+    }
+    .accountIndexEchart {
+        width: 100%;
+        height: 315px;
+        margin: 0 auto;
+    }
+    .card-content {
+        min-height: 400px;
+        max-height: 400px;
+        h2 {
+            display: flex;
+            justify-content: space-between;
+            .no-person {
+                color: rgb(0,153,255);
+                font-size: 36px;
+                font-weight: bold;
+                line-height: 37px;
+            }
+        }
+        h1 {
+            text-align: center;
+            font-size: 40px;
+        }
+        .header-left-title {
+            height: 50px;
+            line-height: 50px;
+            font-size: 20px;
+            .left-title-radio {
+                margin-left: 30px;
+                color: #1afa29;
+                .title-radio-img {
+                    width: 25px;
+                    height: 25px;
+                    margin-bottom: 5px;
+                    margin-right: 5px;
+                    transform: rotate(180deg);
+                }
+            }
+            .left-title-radio-down {
+                margin-left: 30px;
+                color: #d81e06;
+                .title-radio-img {
+                    width: 25px;
+                    height: 25px;
+                    margin-bottom: 5px;
+                    margin-right: 5px;
+                    transform: rotate(180deg);
+                }
+            }
+        }
+        @media (max-width: 1450px) {
+            .left-title-radio { 
+                margin-left: -15px!important;
+            }
+            .left-title-radio-down {
+                margin-left: -15px!important;
+            }
+            .no-person {
+                color: rgb(0,153,255);
+                font-size: 25px!important;
+                font-weight: bold;
+                line-height: 35px!important;
+            }
+        }
+        .header-left-title-else {
+            font-size: 16px;
+            display: flex;
+            line-height: 30px;
+            /deep/ .anticon {
+                line-height: 37px;
+            }
+            .title-label {
+                width: 100px;
+                text-align: right;
+                margin-right: 30px;
+            }
+            .left-title-radio {
+                color: #1afa29;
+                .title-radio-img {
+                    width: 25px;
+                    height: 25px;
+                    margin-bottom: 5px;
+                    margin-right: 5px;
+                    transform: rotate(180deg);
+                }
+            }
+            .left-title-radio-down {
+                color: #d81e06;
+                .title-radio-img {
+                    width: 25px;
+                    height: 25px;
+                    margin-bottom: 5px;
+                    margin-right: 5px;
+                    transform: rotate(180deg);
+                }
+            }
+        }
+    }
+    .between-row {
+        margin-bottom: 20px;
+    }
+}
+
+#outTable {
+    /deep/ .ant-table-header-column {
+        word-break: break-all; 
+        font-size: 14px; 
+        font-weight: 600
+    }
+   
+}
+/deep/ .ant-card-extra {
+    padding: 0!important;
+}
+
+

+ 819 - 0
src/views/modules/stockWatch/modules/keep-manage/keep-manage.vue

@@ -0,0 +1,819 @@
+<template>
+    <div class="keep-manage-content">
+        <a-spin :spinning="accountPageSpinning">
+            <a-row :gutter="24">
+                <a-col :sm="18" :md="18" :xl="18" class="keep-manage-col">
+                    <a-card title="数据趋势" class="card-content echarts-card">
+                        <div class="person-content-title" slot="extra">
+                            <div class="content-title-acount"></div>
+                            <div class="content-title-checkout">
+                                <span class="title-checkout-time">
+                                    <a-range-picker
+                                    v-model="dateEchart"
+                                    :ranges="dateRanges"
+                                    :disabled-date="disabledDate"
+                                    @change="setDataQuery"
+                                    />
+                                </span>
+                                <span class="title-checkout-select">
+                                    <a-select v-model="selectValue" @change="getQueryNewlyData">
+                                        <a-select-option value="charge">花费</a-select-option>
+                                        <a-select-option value="campaign" :disabled="checkDisabled">新上计划数</a-select-option>
+                                        <a-select-option value="unit" :disabled="checkDisabled">新上组数</a-select-option>
+                                    </a-select>
+                                </span>
+                            </div>
+                        </div>
+                        <div style="float:right;margin:10px">
+                            更新时间:{{updateAccountEchart||'-'}}
+                        </div>
+                        <div class="accountIndexEchart" id="accountIndexEchart" ref="accountIndexEchart" :style="{ width: (clientWidth / 24) * 18 - 48 - 24 + 'px' }">
+                            <a-empty  />
+                        </div>
+                    
+                    </a-card>
+                </a-col>
+                <a-col :sm="6" :md="6" :xl="6"  class="keep-manage-col">
+                    <a-card class="card-content" v-if="personData">
+                        <h2>
+                            <span>你好!{{personData.realName||'-'}}</span>
+                            <span class="no-person">NO.{{personData.rank||'-'}}</span>
+                        </h2>
+                        <div class="header-left-title">
+                            <span>
+                                今日消耗:
+                            </span>
+                            <span class="left-title-radio" v-if="personData && personData.grew < 0">
+                                <img class="title-radio-img" src="@/assets/up.png" alt="">
+                                {{  personData.grew + '%'  }}
+                            </span>
+                            <!-- TODO 这个是下降的样式,后续优化  -->
+                            <span class="left-title-radio-down" v-else-if="personData && personData.grew >= 0">
+                                <img class="title-radio-img" src="@/assets/down.png" alt="">
+                                {{ personData.grew + '%' }}
+                            </span>
+                            <a-tooltip class="">
+                                <template slot="title">
+                                截止此时今日与昨日的花费同比
+                                </template>
+                                <a-icon type="question-circle" />
+                            </a-tooltip>
+                        </div>
+                        <h1><span v-if="personData">{{personData.charge | decimalsHandle}}</span><span v-else>-</span></h1>
+                        <div class="header-left-title-else">
+                            <span class="title-label">账户数:</span>
+                            <span>
+                                {{ personData.accouuntCount }}
+                            </span>
+                        </div>
+                        <div class="header-left-title-else">
+                            <span class="title-label">本周消耗:</span>
+                            <span>
+                                {{ personData.weekCharge }}
+                            </span>
+                        </div>
+                        <div class="header-left-title-else">
+                            <span class="title-label">上周消耗:</span>
+                            <span>
+                                {{ personData.lweekCharge }}
+                            </span>
+                        </div>
+                        <div class="header-left-title-else">
+                            <span class="title-label">
+                                周消耗环比:
+                            </span>
+                            <span class="left-title-radio" v-if="personData && personData.weekGrew < 0">
+                                {{ personData.weekGrew + '%'  }}
+                                <img class="title-radio-img" src="@/assets/up.png" alt="">
+                            </span>
+                            <!-- TODO 这个是下降的样式,后续优化  -->
+                            <span class="left-title-radio-down" v-else-if="personData && personData.weekGrew >= 0">
+                                {{ personData.weekGrew + '%' }}
+                                <img class="title-radio-img" src="@/assets/down.png" alt="">
+                            </span>
+                        </div>
+                    </a-card>
+                </a-col>
+            </a-row>
+            <a-row :gutter="24" class="between-row">
+                <a-col>
+                    <a-card title="运营数据详情">
+                        <div class="person-content-title" slot="extra">
+                            <div class="content-title-acount"></div>
+                            <div class="content-title-checkout">
+                                <span class="title-checkout-time">
+                                    <a-range-picker
+                                    v-model="dateMiddle"
+                                    :ranges="dateRanges"
+                                    :disabled-date="disabledDate"
+                                    @change="getOperatingStaffDataList"
+                                    />
+                                </span>
+                            </div>
+                        </div>
+                        <a-table
+                        size="middle"
+                        :dataSource="echartsData"
+                        bordered
+                        id="outTable"
+                        :pagination="echartsIpagination"
+                        :loading="echartsLoading"
+                        ref="accountTable"
+                        >
+                            <a-table-column key="realName" data-index="realName" title="运营人员" align="center">
+                                <template slot-scope="tags,records">
+                                    <a @click="toPerson(records)">
+                                        {{ tags }}
+                                    </a>
+                                </template>
+                            </a-table-column>
+                            <a-table-column key="accountCount" data-index="accountCount" title="账户数量"  align="center"/>
+                            <a-table-column key="charge" data-index="charge" title="花费"  align="center"/>
+                            <a-table-column key="weekCharge" data-index="weekCharge"  align="center">
+                                <span slot="title">本周花费 
+                                    <a-tooltip>
+                                        <template slot="title">
+                                        最近本周(周一到周日)广告账户花费
+                                        </template>
+                                        <a-icon type="question-circle" />
+                                    </a-tooltip>
+                                </span>
+                            </a-table-column>
+                            <a-table-column key="grew" data-index="grew"  align="center">
+                                <span slot="title">花费环比 
+                                    <a-tooltip>
+                                        <template slot="title">
+                                        本周与上周的消耗环比
+                                        </template>
+                                        <a-icon type="question-circle" />
+                                    </a-tooltip>
+                                </span>
+                            </a-table-column>
+                            <a-table-column key="effectiveCount" data-index="effectiveCount" title="有效素材数"  align="center"/>
+                            <a-table-column key="campaignCount" data-index="campaignCount"  align="center">
+                                <span slot="title">新上计划数 
+                                    <a-tooltip>
+                                        <template slot="title">
+                                        显示数据为昨日新建计划数
+                                        </template>
+                                        <a-icon type="question-circle" />
+                                    </a-tooltip>
+                                </span>
+                            </a-table-column>
+                            <a-table-column key="unitCount" data-index="unitCount"  align="center">
+                                <span slot="title">新上组数 
+                                    <a-tooltip>
+                                        <template slot="title">
+                                        显示数据为昨日新建广告组数
+                                        </template>
+                                        <a-icon type="question-circle" />
+                                    </a-tooltip>
+                                </span>
+                            </a-table-column>
+                        </a-table>
+                    </a-card>
+                </a-col>
+            </a-row>
+            <a-card :title="typeValue === 'project' ? '项目列表' : '账户列表'">
+                <div class="keep-person-content" slot="extra">
+                    <div class="person-content-title">
+                        <div class="content-title-acount"></div>
+                        <div class="content-title-checkout">
+                            <span class="title-checkout-custom"><a @click="handleCustomClick">自定义列</a></span>
+                            <span class="title-checkout-time">
+                                <a-range-picker
+                                v-model="dateValue"
+                                :ranges="dateRanges"
+                                :disabled-date="disabledDate"
+                                @change="getPersonList()"
+                                />
+                            </span>
+                            <span class="title-checkout-time">
+                                <a-radio-group v-model="typeValue" @change="checkOutType">
+                                    <a-radio-button value="project">
+                                    项目
+                                    </a-radio-button>
+                                    <a-radio-button value="account">
+                                    账户
+                                    </a-radio-button>
+                                </a-radio-group>
+                            </span>
+                        </div>
+                    </div>
+                </div>
+                <a-table
+                    size="middle"
+                    :columns="columns"
+                    :dataSource="dataSource"
+                    bordered
+                    id="outTable"
+                    :pagination="ipagination"
+                    :scroll="{ x: scrollX }"
+                    :loading="loading"
+                    ref="accountTable"
+                    @change="sort"
+                    v-if="showChange"
+                >
+                <!-- style="word-break: break-all; font-size: 16px; font-weight: 600" -->
+                    <a slot="projectName" slot-scope="text,records" @click="toAccount(records)">{{ text }}</a>
+                    <a slot="authName" slot-scope="text,records" @click="toDetail(records)">{{ text }}</a>
+                    <span slot="ctr" slot-scope="ctr">{{ ctr | toPercentage }}</span>
+                    <span slot="cost" slot-scope="cost">{{ cost | decimalsHandle }}</span>
+                    <span slot="clickMaterial" slot-scope="clickMaterial">{{ clickMaterial | formatCurrency }}</span>
+                    <span slot="showMaterial" slot-scope="showMaterial">{{ showMaterial | formatCurrency }}</span>
+                    <span slot="convertMaterial" slot-scope="convertMaterial">{{ convertMaterial | formatCurrency }}</span>
+                    <span slot="play25FeedBreak" slot-scope="play25FeedBreak">{{ play25FeedBreak | formatCurrency }}</span>
+                    <span slot="play50FeedBreak" slot-scope="play50FeedBreak">{{ play50FeedBreak | formatCurrency }}</span>
+                    <span slot="play75FeedBreak" slot-scope="play75FeedBreak">{{ play75FeedBreak | formatCurrency }}</span>
+                    <span slot="play100FeedBreak" slot-scope="play100FeedBreak">{{ play100FeedBreak | formatCurrency }}</span>
+                    <span slot="nextDayOpen" slot-scope="nextDayOpen">{{ nextDayOpen | formatCurrency }}</span>
+                    <span slot="downloadFinish" slot-scope="downloadFinish">{{ downloadFinish | formatCurrency }}</span>
+                    <span slot="downloadStart" slot-scope="downloadStart">{{ downloadStart | formatCurrency }}</span>
+                    <span slot="likeMaterial" slot-scope="likeMaterial">{{ likeMaterial | formatCurrency }}</span>
+                    <span slot="shareMaterial" slot-scope="shareMaterial">{{ shareMaterial | formatCurrency }}</span>
+                    <span slot="register" slot-scope="register">{{ register | formatCurrency }}</span>
+                    <span slot="follow" slot-scope="follow">{{ follow | formatCurrency }}</span>
+                    <span slot="formCount" slot-scope="formCount">{{ formCount | formatCurrency }}</span>
+                    <span slot="formCountCost" slot-scope="formCountCost">{{ formCountCost | decimalsHandle }}</span>
+                    <span slot="aClick" slot-scope="aClick">{{ aClick | formatCurrency }}</span>
+                    <span slot="photoShow" slot-scope="photoShow">{{ photoShow | formatCurrency }}</span>
+                    <span slot="photoClick" slot-scope="photoClick">{{ photoClick | formatCurrency }}</span>
+                    <span slot="bClick" slot-scope="bClick">{{ bClick | formatCurrency }}</span>
+                    <span slot="active" slot-scope="active">{{ active | formatCurrency }}</span>
+                    <span slot="submit" slot-scope="submit">{{ submit | formatCurrency }}</span>
+                    <span slot="nextDayOpen" slot-scope="nextDayOpen">{{ nextDayOpen | formatCurrency }}</span>
+                    <span slot="eventCreditGrantLandingPage" slot-scope="eventCreditGrantLandingPage">{{
+                    eventCreditGrantLandingPage | formatCurrency
+                    }}</span>
+                    <span slot="submitCost" slot-scope="submitCost">{{ submitCost | decimalsHandle }}</span>
+                    <span slot="eventCreditGrantLandingPageCost" slot-scope="eventCreditGrantLandingPageCost">{{
+                    eventCreditGrantLandingPageCost | decimalsHandle
+                    }}</span>
+                    <span slot="submitRate" slot-scope="submitRate">{{ submitRate | toPercentage }}</span>
+                    <span slot="eventCreditGrantLandingPageRate" slot-scope="eventCreditGrantLandingPageRate">{{
+                    eventCreditGrantLandingPageRate | toPercentage
+                    }}</span>
+                    <span slot="play25FeedBreakRate" slot-scope="play25FeedBreakRate">{{
+                    play25FeedBreakRate | toPercentage
+                    }}</span>
+                    <span slot="playOverRate" slot-scope="playOverRate">{{ playOverRate | toPercentage }}</span>
+
+                    <span slot="convertRate" slot-scope="convertRate">{{ convertRate | toPercentage }}</span>
+                    <span slot="nextDayOpenRate" slot-scope="nextDayOpenRate">{{ nextDayOpenRate | toPercentage }}</span>
+                    <span slot="ctr" slot-scope="ctr">{{ ctr | toPercentage }}</span>
+                    <span slot="cpc" slot-scope="cpc">{{ cpc | decimalsHandle }}</span>
+                    <span slot="cpm" slot-scope="cpm">{{ cpm | decimalsHandle }}</span>
+                    <span slot="activeRate" slot-scope="activeRate">{{ activeRate | toPercentage }}</span>
+                    <span slot="installFinishRate" slot-scope="installFinishRate">{{ installFinishRate | toPercentage }}</span>
+                    <span slot="validPlayRate" slot-scope="validPlayRate">{{ validPlayRate | toPercentage }}</span>
+                    <span slot="activePayCost" slot-scope="activePayCost">{{ activePayCost | decimalsHandle }}</span>
+                    <span slot="nextDayOpenCost" slot-scope="nextDayOpenCost">{{ nextDayOpenCost | decimalsHandle }}</span>
+                    <span slot="validPlayCost" slot-scope="validPlayCost">{{ validPlayCost | decimalsHandle }}</span>
+                    <span slot="activeCost" slot-scope="activeCost">{{ activeCost | decimalsHandle }}</span>
+                    <span slot="nextDayOpenCost" slot-scope="nextDayOpenCost">{{ nextDayOpenCost | decimalsHandle }}</span>
+                    <span slot="gameAddictionCost" slot-scope="gameAddictionCost">{{
+                    gameAddictionCost | decimalsHandle
+                    }}</span>
+                    <span slot="downloadFinishCost" slot-scope="downloadFinishCost">{{
+                    downloadFinishCost | decimalsHandle
+                    }}</span>
+                    <span slot="downloadStartCost" slot-scope="downloadStartCost">{{
+                    downloadStartCost | decimalsHandle
+                    }}</span>
+                    <span slot="installFinishCost" slot-scope="installFinishCost">{{
+                    installFinishCost | decimalsHandle
+                    }}</span>
+                    <span slot="convertCost" slot-scope="convertCost">{{ convertCost | decimalsHandle }}</span>
+
+                    <span slot="downloadStartRate" slot-scope="downloadStartRate">{{ downloadStartRate | toPercentage }}</span>
+                    <span slot="downloadFinishRate" slot-scope="downloadFinishRate">{{
+                    downloadFinishRate | toPercentage
+                    }}</span>
+                    <span slot="activeRate" slot-scope="activeRate">{{ activeRate | toPercentage }}</span>
+                    <span slot="activeRegisterRate" slot-scope="activeRegisterRate">{{
+                    activeRegisterRate | toPercentage
+                    }}</span>
+                    <span slot="gameAddictionRate" slot-scope="gameAddictionRate">{{ gameAddictionRate | toPercentage }}</span>
+                    <span slot="nextDayOpenRate" slot-scope="nextDayOpenRate">{{ nextDayOpenRate | toPercentage }}</span>
+                </a-table>
+            </a-card>
+        </a-spin>
+        <customColumn
+            :visible="visible"
+            :listNum="listNum"
+            :fiexColumn="columnsFixd"
+            :mediaType="2"
+            @closeCustomColumn="closeCustomColumn"
+            @changeColumn="changeColumn"
+        />
+    </div>
+</template>
+<script>
+import customColumn from '@/views/modules/Statistics/components/customColumn.vue'
+import keepPersonData from './keep-manage-data';
+import { mapGetters } from 'vuex';
+import moment from 'moment';
+// 引入基本模板
+var echarts = require('echarts');
+// 引入柱状图组件
+require('echarts/lib/chart/line');
+// 引入提示框和title组件
+require('echarts/lib/component/tooltip');
+require('echarts/lib/component/title');
+require('echarts/lib/component/graphic');
+require('echarts/lib/component/toolbox');
+require('echarts/lib/component/legend');
+export default {
+    name: 'keep-manage',
+    components: {
+        customColumn
+    },
+    data() {
+        return {
+            accountPageSpinning: false,
+            typeValue: 'project',
+            selectValue: 'charge',
+            loading: false,
+            totalAll: 100,
+            projectId: null,
+            dataSource: [],
+            showChange: true,
+            url: '/etl/reportAccountHourly/projectList',
+            listNum: [],
+            visible: false,
+            columns: [...keepPersonData.setNoDeleteProjectColumns() , ...keepPersonData.setDefaultColumns()],
+            echartsColumns: [...keepPersonData.setOperateField()],
+            echartsData: [],
+            columnsFixd: keepPersonData.setNoDeleteProjectColumns(),
+            scrollX: 1500,
+            personData: null,
+            dateEchart: [moment(), moment()],
+            dateMiddle: [moment(), moment()],
+            dateValue: [moment(), moment()],
+            dateRanges: keepPersonData.setTimeRange(),
+            target: 'cost',
+            order: 'descend',
+            clientWidth: 0,
+            updateAccountEchart: null,
+            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
+                },
+            },
+            echartsLoading: false,
+            echartsIpagination: {
+                current: 1,
+                pageSize: 5,
+                //   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.echartsIpagination.current = current
+                    this.echartsIpagination.pageSize = pageSize
+                },
+            },
+        }
+    },
+    computed: {
+        checkDisabled() {
+            if(this.dateEchart.length === 2&&
+            moment(this.dateEchart[0]).format('YYYY-MM-DD') === moment(this.dateEchart[1]).format('YYYY-MM-DD')) {
+               return true
+            }
+            else {
+                return false
+            }
+        }
+    },
+    methods: {
+        ...mapGetters(["userInfo"]),
+        
+        sort(pagination, filters, sorter, { currentDataSource }) {
+            // console.log(pagination, filters, sorter)
+            this.ipagination.current = pagination.current
+            this.ipagination.pageSize = pagination.pageSize
+            if (sorter.order) {
+                this.order = sorter.order ? sorter.order : 'descend'
+                this.target = sorter.columnKey
+                this.getPersonList({ target: sorter.columnKey, order: sorter.order ? sorter.order : 'descend' })
+            }
+        },
+        disabledDate(current) {
+            return current && current > moment().endOf('day')
+        },
+        handleDataPicker(date, dateString) {
+            console.log(date, dateString, '-------');
+        },
+        handleCustomClick () {
+            this.visible = true
+            this.listNum = [...this.columns]
+        },
+        onShowSizeChange(current, pageSize) {
+            console.log(current, pageSize, 'current, pageSize');
+        },
+        handleCauseSizeChange(current, pageSize) {
+            console.log(current, pageSize, 'size-size');
+        },
+        handleCancelClick(status) {
+            this.isCustomVisible = status;
+        },
+        //自定义列相关
+        closeCustomColumn() {
+            this.visible = false
+        },
+        changeColumn(val) {
+            this.columns = [...val]
+            if (this.columns.length > this.columnsFixd.length && this.columns.length < 8) {
+                this.columns.forEach((element, index) => {
+                if (index < this.columns.length - 1) {
+                   
+                    element.width = 'auto'
+                    element.fixed = false
+                    
+                }
+                })
+
+                this.scrollX = 0
+            } 
+            else if (this.columns.length >= 8) {
+                this.columns.forEach((element, index) => {
+                    if (index < this.columnsFixd.length) {
+                        element.width = 150
+                        element.fixed = 'left'
+                    }
+                })
+
+                this.scrollX = 1000 + 150 * (this.columns.length - this.columnsFixd.length)
+            } 
+            else {
+                this.scrollX = 0
+                this.columns.forEach((element) => {
+
+                    element.width = 'auto'
+                    element.fixed = false
+                    
+                })
+            }
+
+            let arr = JSON.stringify(this.columns)
+            this.postDataAction('/toutiao/videoReportDaily/saveOrUpdateColumnJson', {
+                json: arr,
+                columnType: this.typeValue === 'project' ? 15 : 16,
+            }).then((res) => {
+            })
+        },
+        showColumn() {
+            this.postDataAction('/toutiao/videoReportDaily/getColumnJson', {
+                columnType: this.typeValue === 'project' ? 15 : 16,
+            }).then((res) => {
+                // console.log(res)
+                if (res.success) {
+                // console.log(JSON.parse(res.result))
+                if (res.result) {
+                    let columns = JSON.parse(res.result)
+                    if (columns.length) {
+                    if (columns.length >= this.columnsFixd.length) {
+                        columns.map((item, index) => {
+                        if (index > this.columnsFixd.length - 1) {
+                            item.sorter = function (a, b) {}
+                        }
+                        })
+                        columns = columns.slice(this.columnsFixd.length)
+                        this.columns = [...this.columnsFixd, ...columns]
+
+                        // this.tableHandle()
+                    }
+
+                    // console.log(this.columns)
+                    }
+                }
+
+                this.changeColumn(this.columns)
+                }
+            })
+        },
+        //自定义列结束
+
+        //获取个人绩效
+        getPersonAchievements() {
+            let params = {};
+            params.userId = this.userInfo().id;
+            this.getAction('/etl/reportAccountHourly/personalAchievements', params).then(res => {
+                this.accountPageSpinning = false;
+                if(res.success) {
+                    this.personData = res.result;
+                }
+                else {
+                    this.$message.error(res.message);
+                }
+            }).catch(error => {
+                this.accountPageSpinning = false;
+                console.log(error, 'eeee');
+            });
+        },
+
+        //切换列表账户项目选项
+        checkOutType() {
+            this.showChange = false;
+            this.projectId = null;
+            this.ipagination.current = 1
+            if(this.typeValue === 'account') {
+                this.url = '/etl/reportAccountHourly/leaderAccountPageList';
+                this.columns = [...keepPersonData.setNoDeleteColumns() , ...keepPersonData.setDefaultColumns()];
+                this.columnsFixd = keepPersonData.setNoDeleteColumns();
+            }
+            else {
+                this.url = '/etl/reportAccountHourly/projectList';
+                this.columns = [...keepPersonData.setNoDeleteProjectColumns() , ...keepPersonData.setDefaultColumns()];
+                this.columnsFixd = keepPersonData.setNoDeleteProjectColumns();
+            }
+            this.showChange = true;
+            this.showColumn();
+            this.getPersonList();
+        },
+
+        //点击项目查看账户
+        toAccount(item) {
+            this.showChange = false;
+            this.projectId = item.projectId;
+            this.ipagination.current = 1
+            this.typeValue = 'account';
+            this.url = '/etl/reportAccountHourly/leaderAccountPageList';
+            this.columns = [...keepPersonData.setNoDeleteColumns() , ...keepPersonData.setDefaultColumns()];
+            this.columnsFixd = keepPersonData.setNoDeleteColumns();
+            this.showChange = true;
+            this.getPersonList();
+        },
+
+        //跳转个人页面
+        toPerson(records) {
+            let params = {};
+            params.person = records.userId;
+            params.timeRange = this.dateMiddle;
+            localStorage.setItem('stockWatchUserId',JSON.stringify(params));
+            this.$nextTick(() => {
+                this.$router.push('/modules/stockWatch/modules/keep-person/keep-person?person=' + records.userId );
+            })
+        },
+
+        //点击跳转盯盘详情页
+        toDetail(item) {
+            let params = {};
+            params.accountId = item.accountId;
+            params.timeRange = this.dateValue;
+            localStorage.setItem('stockWatchAccountId',JSON.stringify(params));
+            this.$nextTick(() => {
+                this.$router.push('/modules/stockWatch/accountPage');
+            })
+            
+        },
+
+        //获取列表
+        getPersonList(data) {
+            this.loading = true;
+            let params = {};
+            params.userId = this.userInfo().id;
+            params.startTime = this.dateValue.length === 2 ? moment(this.dateValue[0]).format('YYYY-MM-DD') : null;
+            params.endTime = this.dateValue.length === 2 ? moment(this.dateValue[1]).format('YYYY-MM-DD') : null;
+            params.pageNo = this.ipagination.current;
+            params.pageSize = this.ipagination.pageSize;
+            
+            if( this.typeValue === 'account' ) {
+                params.projectId = this.projectId
+            }
+
+            if (data) {
+                params.sortCode = data.target
+                if (data.order == 'descend') {
+                    params.sortType = 'DESC'
+                } 
+                else {
+                    params.sortType = 'ASC'
+                }
+            } 
+            else {
+                params.sortCode = this.target
+                params.sortType = this.order == 'descend' ? 'DESC' : 'ASC'
+            }
+            this.postDataAction(this.url,params).then(res => {
+                this.loading = false;
+                if(res.success) {
+                    this.dataSource = res.result.list
+                    this.ipagination.total = res.result.total
+                }
+            })
+        },
+
+        //获取运营人员详情列表
+        getOperatingStaffDataList() {
+            this.echartsLoading = true;
+            let params = {};
+            params.startTime = this.dateMiddle.length === 2 ? moment(this.dateMiddle[0]).format('YYYY-MM-DD') : null;
+            params.endTime = this.dateMiddle.length === 2 ? moment(this.dateMiddle[1]).format('YYYY-MM-DD') : null;
+            params.pageNo = this.echartsIpagination.current;
+            params.pageSize = this.echartsIpagination.pageSize;
+            params.userId = this.userInfo().id;
+            // echartsData
+            this.postDataAction('/etl/reportAccountHourly/operatingStaffDataList',params).then(res => {
+                this.echartsLoading = false;
+                if(res.success) {
+                    this.echartsData = res.result.list
+                    this.echartsIpagination.total = res.result.total
+                }
+                else {
+                    this.$message.error(res.message)
+                }
+            }).catch(error => {
+                this.echartsLoading = false;
+                console.log(error)
+            })
+        },
+
+        //单日数据只查询花费判断
+        setDataQuery() {
+            if(this.dateEchart.length === 2
+            &&
+            moment(this.dateEchart[0]).format('YYYY-MM-DD') === moment(this.dateEchart[1]).format('YYYY-MM-DD')) {
+                this.$message.warning('单日数据只查询花费')
+                this.selectValue = 'charge'
+            }
+            this.getQueryNewlyData()
+        },
+
+
+
+        //趋势图数据接口
+        getQueryNewlyData() {
+            let params = {};
+            params.userId = this.userInfo().id;
+            params.parameterCode = this.selectValue;
+            params.startTime = this.dateEchart.length === 2 ? moment(this.dateEchart[0]).format('YYYY-MM-DD') : null;
+            params.endTime = this.dateEchart.length === 2 ? moment(this.dateEchart[1]).format('YYYY-MM-DD') : null;
+            this.postDataAction('/etl/reportAccountHourly/queryNewlyData',params).then(res => {
+                if(res.success){
+                    this.initEchart('accountIndexEchart',this.initAccountIndexEchart(res.result.data))
+                    this.updateAccountEchart = res.result.updateTime
+                }
+            }).catch(error => {
+                console.log(error)
+            })
+        },
+
+        //趋势图echarts配置
+        initAccountIndexEchart(data){
+            // let type='激活'
+            // console.log(res);(data)
+            let option = {
+                tooltip: {
+                    trigger: 'axis',
+                    
+                },
+                grid:{
+                    x: this.clientWidth>1100?'6%':'8%',
+                    width: '90%',
+                    y: '12%',
+                    bottom: '25px',
+                    right: '15px'
+
+                },
+                xAxis: [{
+                    data: data.map(item => {
+                        if(this.checkDisabled) {
+                            return (item.time >= 10 ? item.time: '0' + item.time)+ ':00'
+                        }
+                        else {
+                            return item.time
+                        }
+                        
+                    }), 
+                    axisLine: {
+                        lineStyle: {
+                            color: '#ddd'
+                        }
+                    },
+                    axisTick: {
+                        show: true
+                    },
+                    axisLabel: {
+                        show:true,
+                        textStyle: {
+                            color: '#c56790'
+                        },
+                    },
+                    boundaryGap: true
+                    
+      
+                }],
+                yAxis: [{
+                    type: 'value',
+                    show:true,
+                }],
+                series: [
+                    {
+                        name: this.selectValue === 'campaign'
+                        ?'上新计划数':this.selectValue === 'unit'
+                        ?'上新组数':'花费',
+                        data: data.map(item => {
+                            return item.value
+                        }),
+                        type: 'line',
+                        smooth: true,
+                        symbol: 'circle',
+                        lineStyle: {                               
+                            color: '#007AFF',   
+                            width: 3,
+                        },
+                        itemStyle:{
+                            color:'#007AFF',
+                            borderWidth:2,
+                            borderColor:'#fff'
+                        },
+                        areaStyle: {
+                            color:{
+                                type: 'linear',
+                                x: 0,
+                                y: 0,
+                                x2: 0,
+                                y2: 1,
+                                colorStops: [{
+                                    offset: 0, color: '#007AFF' // 0% 处的颜色
+                                }, {
+                                    offset: 1, color: 'white' // 100% 处的颜色
+                                }],
+                            }
+                        }
+                    },
+                
+                ]
+            };
+
+            return option
+        },  
+        //获取echart的值
+        initEchart(idName, optionName) {
+            let that = this;
+            const chart = this.$refs[idName]
+            //   // console.log(res);(chart)
+            if (chart) {
+                const myChart = echarts.init(document.getElementById(idName))
+                // myChart.showLoading({
+                //     text: "图表数据正在努力加载..."
+                // });
+                myChart.clear()
+                myChart.setOption(optionName)
+                window.addEventListener('resize', function() {
+                    that.clientWidth = document.documentElement.clientWidth - 224
+                    myChart.resize()
+                })
+            }
+        },
+    },
+    watch: {
+        'ipagination.current':function(n,o) {
+            if(n !== o) {
+                this.getPersonList()
+            }
+        },
+        'echartsIpagination.current':function(n,o) {
+            if(n !== o) {
+                this.getOperatingStaffDataList()
+            }
+        }
+    },
+    mounted() {
+        this.$nextTick(() => {
+            this.accountPageSpinning = true
+            this.clientWidth = document.documentElement.clientWidth - 224
+            this.showColumn();
+            this.getPersonAchievements();
+            this.getPersonList();
+            this.getQueryNewlyData();
+            this.getOperatingStaffDataList();
+           
+        })
+    }
+};
+</script>
+<style lang="less" scoped>
+    @import "keep-manage";
+</style>

+ 162 - 0
src/views/modules/stockWatch/modules/keep-person/keep-person-data.js

@@ -0,0 +1,162 @@
+/**
+ * @file 盯盘基础展示数据
+ * @author zhuxinbo(zhuxinbo@c-top.com.cn)
+ */
+import moment from 'moment'
+class keepPersonServer {
+    constructor() {}
+
+    // 固定不可删除的列
+    setNoDeleteColumns() {
+        return [
+            {
+                title: '账户名称',
+                dataIndex: 'authName',
+                scopedSlots: { customRender: 'authName' },
+                align: 'center',
+                key: 'date',
+                width: 200,
+                fixed: 'left',
+            },
+            {
+                title: '运营人员',
+                dataIndex: 'realname',
+                align: 'center',
+                width: 100,
+                fixed: 'left',
+            },
+            {
+                title: '消耗',
+                dataIndex: 'cost',
+                scopedSlots: { customRender: 'cost' },
+                align: 'center',
+                width: 100,
+                fixed: 'left',
+                sorter: () => {},
+            },
+            {
+                title: '余额',
+                dataIndex: 'totalBalance',
+                align: 'center',
+                width: 100,
+                fixed: 'left',
+                sorter: () => {},
+            },
+            {
+                title: '预算',
+                dataIndex: 'budget',
+                width: 150,
+                tip: '广告在投放期间的花费总额',
+                align: 'center',
+                customRender: function (text) {
+                    if (text>0) {
+                        return text
+                    } else {
+                        return '不限制预算'
+                    }
+                },
+            }
+        ]
+    }
+
+    // 默认初始展示列
+    setDefaultColumns() {
+        return [
+            {
+                title: '封面曝光数',
+                dataIndex: 'photoShow',
+                tip: '广告在瀑布流被观看次数',
+                align: 'center',
+                scopedSlots: { customRender: 'photoShow' },
+                sorter: () => {},
+            },
+            {
+                title: '封面点击数',
+                dataIndex: 'photoClick',
+                tip: '用户点击封面进入视频播放页的次数(数据会进行反作弊去重)',
+                align: 'center',
+        
+                scopedSlots: { customRender: 'photoClick' },
+                sorter: () => {},
+            },
+            {
+                title: '封面点击率',
+                dataIndex: 'clickRate',
+                tip: '封面点击数占封面展示数百分比',
+                align: 'center',
+                scopedSlots: { customRender: 'clickRate' },
+                sorter: () => {},
+            },
+            {
+                title: '素材曝光数',
+                dataIndex: 'aClick',
+                tip: '用户进入视频播放页观看的次数(数据会进行反作弊去重)',
+                align: 'center',
+        
+                scopedSlots: { customRender: 'aClick' },
+                sorter: () => {},
+            },
+            {
+                title: '行为数',
+                dataIndex: 'bClick',
+                tip: '用户在视频播放页单击转化按钮的次数/展示数*100%',
+                align: 'center',
+        
+                scopedSlots: { customRender: 'bClick' },
+                sorter: () => {},
+            },
+        
+            {
+                title: '行为率',
+                dataIndex: 'bClickRate',
+                tip: '行为数占素材曝光数百分比',
+                align: 'center',
+                scopedSlots: { customRender: 'bClickRate' },
+                sorter: () => {},
+            },
+            {
+                title: '平均千次封面曝光花费(元)',
+                dataIndex: 'cpm',
+                tip: '花费/封面曝光数*1000',
+                align: 'center',
+                scopedSlots: { customRender: 'cpm' },
+                sorter: () => {},
+            },
+            {
+                title: '平均封面点击单价(元)',
+                dataIndex: 'cpc',
+                tip: '花费/封面点击数',
+                align: 'center',
+                scopedSlots: { customRender: 'cpc' },
+                sorter: () => {},
+            },
+            {
+                title: '平均行为单价(元)',
+                dataIndex: 'cpb',
+                tip: '总花费/行为数',
+                align: 'center',
+                scopedSlots: { customRender: 'cpb' },
+                sorter: () => {},
+            },
+        ]
+    }
+
+    //时间段筛选
+    setTimeRange() {
+        return {
+            昨天: [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
+            // 今天: [moment(), moment()],
+    
+            近三天: [moment().subtract(3, 'days'), moment().subtract(1, 'days')],
+            近一周: [moment().subtract(7, 'days'), moment().subtract(1, 'days')],
+            近14天: [moment().subtract(14, 'days'), moment().subtract(1, 'days')],
+            近一月: [moment().subtract(1, 'months'), moment().subtract(1, 'days')],
+            近半年: [moment().subtract(6, 'months'), moment().subtract(1, 'days')],
+            近一年: [moment().subtract(12, 'months'), moment().subtract(1, 'days')],
+        }
+    }
+
+
+}
+
+export default new keepPersonServer();

+ 120 - 0
src/views/modules/stockWatch/modules/keep-person/keep-person.less

@@ -0,0 +1,120 @@
+.keep-person-main {
+    .keep-person-header {
+        display: flex;
+        justify-content: space-between;
+        height: 120px;
+        background: #fff;
+        margin-bottom: 15px;
+        .person-header-left {
+            display: flex;
+            align-items: center;
+            .header-left-img {
+                margin-left: 20px;
+                margin-right: 20px;
+                width: 60px;
+                height:60px;
+                img {
+                    width: 100%;
+                }
+            }
+            .header-left-title {
+                height: 50px;
+                line-height: 50px;
+                font-size: 20px;
+                .left-title-radio {
+                    margin-left: 30px;
+                    color: #1afa29;
+                    .title-radio-img {
+                        width: 25px;
+                        height: 25px;
+                        margin-bottom: 5px;
+                        margin-right: 5px;
+                        transform: rotate(180deg);
+                    }
+                }
+                .left-title-radio-down {
+                    margin-left: 30px;
+                    color: #d81e06;
+                    .title-radio-img {
+                        width: 25px;
+                        height: 25px;
+                        margin-bottom: 5px;
+                        margin-right: 5px;
+                        transform: rotate(180deg);
+                    }
+                }
+            }
+        }
+        .person-header-right {
+            display: flex;
+            align-items: center;
+            text-align: center;
+            margin-right: 20px;
+            .header-right-msg {
+                font-size: 20px;
+                margin-right: 60px;
+                .right-msg-class {
+                    height: 50px;
+                    line-height: 50px;
+                    .title-radio-img {
+                        width: 25px;
+                        height: 25px;
+                        margin-bottom: 5px;
+                        margin-right: 5px;
+                        transform: rotate(180deg);
+                    }
+                    .msg-ranking {
+                        font-size: 30px;
+                    }
+                }
+                .msg-class-up {
+                    color: #1afa29;
+                }
+                .msg-class-down {
+                    color: #d81e06;
+                }
+            }
+        }
+    }
+    .keep-person-content {
+        .person-content-title {
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            height: 60px;
+            background: #fff;
+            padding: 0 20px;
+            .content-title-acount {
+                font-size: 20px;
+            }
+            .content-title-checkout {
+                .title-checkout-custom {
+                    cursor: pointer;
+                }
+                .title-checkout-time {
+                    margin-left: 20px;
+                }
+            }
+        }
+        .pagin-table-class {
+            display: flex;
+            justify-content: flex-end;
+            margin-top: 20px;
+        }
+
+    }
+}
+
+#outTable {
+    /deep/ .ant-table-header-column {
+        word-break: break-all; 
+        font-size: 14px; 
+        font-weight: 600
+    }
+   
+}
+/deep/ .ant-card-extra {
+    padding: 0!important;
+}
+
+

+ 424 - 0
src/views/modules/stockWatch/modules/keep-person/keep-person.vue

@@ -0,0 +1,424 @@
+<template>
+    <div class="keep-person-main">
+        <div class="keep-person-header">
+            <div class="person-header-left">
+                <div class="header-left-img"><img src="@/assets/touxiang.png" alt=""></div>
+                <div>
+                    <div class="header-left-title">你好,{{ personData ? personData.realName : 'admin' }},祝你开心每一天</div>
+                    <div class="header-left-title">
+                        <span>今日消耗:</span>
+                        <span>{{ personData ? personData.charge : '-' }}</span>
+                        <span class="left-title-radio" v-if="personData && personData.grew < 0">
+                            <img class="title-radio-img" src="@/assets/up.png" alt="">
+                            {{ personData.grew ? personData.grew + '%' : '-' }}
+                        </span>
+                        <!-- TODO 这个是下降的样式,后续优化  -->
+                        <span class="left-title-radio-down" v-else-if="personData && personData.grew >= 0">
+                            <img class="title-radio-img" src="@/assets/down.png" alt="">
+                            {{personData.grew ? personData.grew + '%':'-'}}
+                        </span>
+                        <a-tooltip>
+                            <template slot="title">
+                            截止此时今日与昨日的消耗同比
+                            </template>
+                            <a-icon type="question-circle" />
+                        </a-tooltip>
+                    </div>
+                </div>
+            </div>
+            <div class="person-header-right">
+                <div class="header-right-msg">
+                    <div class="right-msg-class">周消耗环比
+                        <a-tooltip>
+                            <template slot="title">
+                            本周与上周的消耗环比
+                            </template>
+                            <a-icon type="question-circle" />
+                        </a-tooltip>
+                    </div>
+                    <div class="right-msg-class msg-class-up" v-if="personData && personData.weekGrew < 0">
+                        <img class="title-radio-img" src="@/assets/up.png" alt="">
+                        {{ personData.weekGrew ? personData.weekGrew + '%' : '-' }}
+                    </div>
+                    <div class="right-msg-class msg-class-down" v-else-if="personData && personData.weekGrew >= 0">
+                        <img class="title-radio-img" src="@/assets/down.png" alt="">
+                        {{ personData.weekGrew ? personData.weekGrew + '%' : '-' }}
+                    </div>
+                </div>
+                <div class="header-right-msg">
+                    <div class="right-msg-class">本周消耗</div>
+                    <div class="right-msg-class">{{ personData ? personData.weekCharge : '-' }}</div>
+                </div>
+                <div class="header-right-msg">
+                    <div class="right-msg-class">上周消耗</div>
+                    <div class="right-msg-class">{{ personData ? personData.lweekCharge : '-' }}</div>
+                </div>
+                <div class="header-right-msg">
+                    <div class="right-msg-class">团队内排名</div>
+                    <div class="right-msg-class">
+                        <span class="msg-ranking">{{ personData ? personData.rank : '-' }}</span> 
+                        /{{ personData ? personData.total : '-' }}
+                    </div>
+                </div>
+            </div>
+        </div>
+        <a-card title="账户列表">
+            <div class="keep-person-content" slot="extra">
+                <div class="person-content-title" >
+                    <div class="content-title-acount"></div>
+                    <div class="content-title-checkout">
+                        <span class="title-checkout-custom"><a @click="handleCustomClick">自定义列</a></span>
+                        <span class="title-checkout-time">
+                            <a-range-picker
+                            v-model="dateValue"
+                            :ranges="dateRanges"
+                            :disabled-date="disabledDate"
+                            @change="getPersonList()"
+                            />
+                        </span>
+                    </div>
+                </div>
+
+            </div>
+            <a-table
+                size="middle"
+                :columns="columns"
+                :dataSource="dataSource"
+                bordered
+                id="outTable"
+                :pagination="ipagination"
+                :scroll="{ x: scrollX }"
+                :loading="loading"
+                ref="accountTable"
+                @change="sort"
+            >
+            <!-- style="word-break: break-all; font-size: 16px; font-weight: 600" -->
+                <a slot="authName" slot-scope="text,records" @click="toDetail(records)">{{ text }}</a>
+                <span slot="ctr" slot-scope="ctr">{{ ctr | toPercentage }}</span>
+                <span slot="cost" slot-scope="cost">{{ cost | decimalsHandle }}</span>
+                <span slot="clickMaterial" slot-scope="clickMaterial">{{ clickMaterial | formatCurrency }}</span>
+                <span slot="showMaterial" slot-scope="showMaterial">{{ showMaterial | formatCurrency }}</span>
+                <span slot="convertMaterial" slot-scope="convertMaterial">{{ convertMaterial | formatCurrency }}</span>
+                <span slot="play25FeedBreak" slot-scope="play25FeedBreak">{{ play25FeedBreak | formatCurrency }}</span>
+                <span slot="play50FeedBreak" slot-scope="play50FeedBreak">{{ play50FeedBreak | formatCurrency }}</span>
+                <span slot="play75FeedBreak" slot-scope="play75FeedBreak">{{ play75FeedBreak | formatCurrency }}</span>
+                <span slot="play100FeedBreak" slot-scope="play100FeedBreak">{{ play100FeedBreak | formatCurrency }}</span>
+                <span slot="nextDayOpen" slot-scope="nextDayOpen">{{ nextDayOpen | formatCurrency }}</span>
+                <span slot="downloadFinish" slot-scope="downloadFinish">{{ downloadFinish | formatCurrency }}</span>
+                <span slot="downloadStart" slot-scope="downloadStart">{{ downloadStart | formatCurrency }}</span>
+                <span slot="likeMaterial" slot-scope="likeMaterial">{{ likeMaterial | formatCurrency }}</span>
+                <span slot="shareMaterial" slot-scope="shareMaterial">{{ shareMaterial | formatCurrency }}</span>
+                <span slot="register" slot-scope="register">{{ register | formatCurrency }}</span>
+                <span slot="follow" slot-scope="follow">{{ follow | formatCurrency }}</span>
+                <span slot="formCount" slot-scope="formCount">{{ formCount | formatCurrency }}</span>
+                <span slot="formCountCost" slot-scope="formCountCost">{{ formCountCost | decimalsHandle }}</span>
+                <span slot="aClick" slot-scope="aClick">{{ aClick | formatCurrency }}</span>
+                <span slot="photoShow" slot-scope="photoShow">{{ photoShow | formatCurrency }}</span>
+                <span slot="photoClick" slot-scope="photoClick">{{ photoClick | formatCurrency }}</span>
+                <span slot="bClick" slot-scope="bClick">{{ bClick | formatCurrency }}</span>
+                <span slot="active" slot-scope="active">{{ active | formatCurrency }}</span>
+                <span slot="submit" slot-scope="submit">{{ submit | formatCurrency }}</span>
+                <span slot="nextDayOpen" slot-scope="nextDayOpen">{{ nextDayOpen | formatCurrency }}</span>
+                <span slot="eventCreditGrantLandingPage" slot-scope="eventCreditGrantLandingPage">{{
+                eventCreditGrantLandingPage | formatCurrency
+                }}</span>
+                <span slot="submitCost" slot-scope="submitCost">{{ submitCost | decimalsHandle }}</span>
+                <span slot="eventCreditGrantLandingPageCost" slot-scope="eventCreditGrantLandingPageCost">{{
+                eventCreditGrantLandingPageCost | decimalsHandle
+                }}</span>
+                <span slot="submitRate" slot-scope="submitRate">{{ submitRate | toPercentage }}</span>
+                <span slot="eventCreditGrantLandingPageRate" slot-scope="eventCreditGrantLandingPageRate">{{
+                eventCreditGrantLandingPageRate | toPercentage
+                }}</span>
+                <span slot="play25FeedBreakRate" slot-scope="play25FeedBreakRate">{{
+                play25FeedBreakRate | toPercentage
+                }}</span>
+                <span slot="playOverRate" slot-scope="playOverRate">{{ playOverRate | toPercentage }}</span>
+
+                <span slot="convertRate" slot-scope="convertRate">{{ convertRate | toPercentage }}</span>
+                <span slot="nextDayOpenRate" slot-scope="nextDayOpenRate">{{ nextDayOpenRate | toPercentage }}</span>
+                <span slot="ctr" slot-scope="ctr">{{ ctr | toPercentage }}</span>
+                <span slot="cpc" slot-scope="cpc">{{ cpc | decimalsHandle }}</span>
+                <span slot="cpm" slot-scope="cpm">{{ cpm | decimalsHandle }}</span>
+                <span slot="activeRate" slot-scope="activeRate">{{ activeRate | toPercentage }}</span>
+                <span slot="installFinishRate" slot-scope="installFinishRate">{{ installFinishRate | toPercentage }}</span>
+                <span slot="validPlayRate" slot-scope="validPlayRate">{{ validPlayRate | toPercentage }}</span>
+                <span slot="activePayCost" slot-scope="activePayCost">{{ activePayCost | decimalsHandle }}</span>
+                <span slot="nextDayOpenCost" slot-scope="nextDayOpenCost">{{ nextDayOpenCost | decimalsHandle }}</span>
+                <span slot="validPlayCost" slot-scope="validPlayCost">{{ validPlayCost | decimalsHandle }}</span>
+                <span slot="activeCost" slot-scope="activeCost">{{ activeCost | decimalsHandle }}</span>
+                <span slot="nextDayOpenCost" slot-scope="nextDayOpenCost">{{ nextDayOpenCost | decimalsHandle }}</span>
+                <span slot="gameAddictionCost" slot-scope="gameAddictionCost">{{
+                gameAddictionCost | decimalsHandle
+                }}</span>
+                <span slot="downloadFinishCost" slot-scope="downloadFinishCost">{{
+                downloadFinishCost | decimalsHandle
+                }}</span>
+                <span slot="downloadStartCost" slot-scope="downloadStartCost">{{
+                downloadStartCost | decimalsHandle
+                }}</span>
+                <span slot="installFinishCost" slot-scope="installFinishCost">{{
+                installFinishCost | decimalsHandle
+                }}</span>
+                <span slot="convertCost" slot-scope="convertCost">{{ convertCost | decimalsHandle }}</span>
+
+                <span slot="downloadStartRate" slot-scope="downloadStartRate">{{ downloadStartRate | toPercentage }}</span>
+                <span slot="downloadFinishRate" slot-scope="downloadFinishRate">{{
+                downloadFinishRate | toPercentage
+                }}</span>
+                <span slot="activeRate" slot-scope="activeRate">{{ activeRate | toPercentage }}</span>
+                <span slot="activeRegisterRate" slot-scope="activeRegisterRate">{{
+                activeRegisterRate | toPercentage
+                }}</span>
+                <span slot="gameAddictionRate" slot-scope="gameAddictionRate">{{ gameAddictionRate | toPercentage }}</span>
+                <span slot="nextDayOpenRate" slot-scope="nextDayOpenRate">{{ nextDayOpenRate | toPercentage }}</span>
+            </a-table>
+        </a-card>
+
+        <customColumn
+            :visible="visible"
+            :listNum="listNum"
+            :fiexColumn="columnsFixd"
+            :mediaType="2"
+            @closeCustomColumn="closeCustomColumn"
+            @changeColumn="changeColumn"
+        />
+    </div>
+</template>
+<script>
+import customColumn from '@/views/modules/Statistics/components/customColumn.vue'
+import keepPersonData from './keep-person-data';
+import { mapGetters } from 'vuex';
+import moment from 'moment'
+export default {
+    name: 'keep-person',
+    components: {
+        customColumn
+    },
+    data() {
+        return {
+            isCustomVisible: false,
+            loading: false,
+            totalAll: 100,
+            dataSource: [],
+            listNum: [],
+            visible: false,
+            columns: [...keepPersonData.setNoDeleteColumns() , ...keepPersonData.setDefaultColumns()],
+            columnsFixd: keepPersonData.setNoDeleteColumns(),
+            scrollX: 1500,
+            personData: null,
+            dateValue: [moment(), moment()],
+            dateRanges: keepPersonData.setTimeRange(),
+            target: 'cost',
+            order: 'descend',
+            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
+                },
+            },
+        };
+    },
+    watch: {
+        'ipagination.current':function(n,o) {
+            if(n !== o) {
+                this.getPersonList()
+            }
+        }
+    },
+    methods: {
+        ...mapGetters(["userInfo"]),
+        //点击跳转盯盘详情页
+        toDetail(item) {
+            let params = {};
+            params.accountId = item.accountId;
+            params.timeRange = this.dateValue;
+            localStorage.setItem('stockWatchAccountId',JSON.stringify(params));
+            this.$nextTick(() => {
+                this.$router.push('/modules/stockWatch/accountPage');
+            })
+            
+        },
+        sort(pagination, filters, sorter, { currentDataSource }) {
+            // console.log(pagination, filters, sorter)
+            this.ipagination.current = pagination.current
+            this.ipagination.pageSize = pagination.pageSize
+            if (sorter.order) {
+                this.order = sorter.order ? sorter.order : 'descend'
+                this.target = sorter.columnKey
+                this.getPersonList({ target: sorter.columnKey, order: sorter.order ? sorter.order : 'descend' })
+            }
+        },
+        disabledDate(current) {
+            return current && current > moment().endOf('day')
+        },
+        handleDataPicker(date, dateString) {
+            console.log(date, dateString, '-------');
+        },
+        handleCustomClick () {
+            this.visible = true
+            this.listNum = [...this.columns]
+        },
+        onShowSizeChange(current, pageSize) {
+            console.log(current, pageSize, 'current, pageSize');
+        },
+        handleCauseSizeChange(current, pageSize) {
+            console.log(current, pageSize, 'size-size');
+        },
+        handleCancelClick(status) {
+            this.isCustomVisible = status;
+        },
+        //自定义列相关
+        closeCustomColumn() {
+            this.visible = false
+        },
+        changeColumn(val) {
+            this.columns = [...val]
+            if (this.columns.length > this.columnsFixd.length && this.columns.length < 8) {
+                this.columns.forEach((element, index) => {
+                if (index < this.columns.length - 1) {
+                   
+                    element.width = 'auto'
+                    element.fixed = false
+                    
+                }
+                })
+
+                this.scrollX = 0
+            } 
+            else if (this.columns.length >= 8) {
+                this.columns.forEach((element, index) => {
+                    if (index < this.columnsFixd.length) {
+                        element.width = 150
+                        element.fixed = 'left'
+                    }
+                })
+
+                this.scrollX = 1000 + 150 * (this.columns.length - this.columnsFixd.length)
+            } 
+            else {
+                this.scrollX = 0
+                this.columns.forEach((element) => {
+
+                    element.width = 'auto'
+                    element.fixed = false
+                    
+                })
+            }
+
+            let arr = JSON.stringify(this.columns)
+            this.postDataAction('/toutiao/videoReportDaily/saveOrUpdateColumnJson', {
+                json: arr,
+                columnType: 13,
+            }).then((res) => {
+                // console.log(res)
+            })
+        },
+        showColumn() {
+            this.postDataAction('/toutiao/videoReportDaily/getColumnJson', {
+                columnType: 13,
+            }).then((res) => {
+                // console.log(res)
+                if (res.success) {
+                // console.log(JSON.parse(res.result))
+                if (res.result) {
+                    let columns = JSON.parse(res.result)
+                    if (columns.length) {
+                    if (columns.length >= this.columnsFixd.length) {
+                        columns.map((item, index) => {
+                        if (index > this.columnsFixd.length - 1) {
+                            item.sorter = function (a, b) {}
+                        }
+                        })
+                        columns = columns.slice(this.columnsFixd.length)
+                        this.columns = [...this.columnsFixd, ...columns]
+
+                        // this.tableHandle()
+                    }
+
+                    // console.log(this.columns)
+                    }
+                }
+
+                this.changeColumn(this.columns)
+                }
+            })
+        },
+        //自定义列结束
+
+        //获取个人绩效
+        getPersonAchievements() {
+            let params = {}
+            params.userId = this.$route.query.person ? this.$route.query.person : this.userInfo().id;
+            this.getAction('/etl/reportAccountHourly/personalAchievements', params).then(res => {
+                if(res.success) {
+                    this.personData = res.result
+                }
+                else {
+                    this.$message.error(res.message);
+                }
+            }).catch(error => {
+                console.log(error, 'eeee');
+            });
+        },
+
+        //获取列表
+        getPersonList(data) {
+            this.loading = true;
+            let params = {};
+            params.userId = this.$route.query.person ? this.$route.query.person : this.userInfo().id;;
+            params.startTime = this.dateValue.length === 2 ? moment(this.dateValue[0]).format('YYYY-MM-DD') : null;
+            params.endTime = this.dateValue.length === 2 ? moment(this.dateValue[1]).format('YYYY-MM-DD') : null;
+            params.pageNo = this.ipagination.current;
+            params.pageSize = this.ipagination.pageSize;
+
+            if (data) {
+                params.sortCode = data.target
+                if (data.order == 'descend') {
+                    params.sortType = 'DESC'
+                } 
+                else {
+                    params.sortType = 'ASC'
+                }
+            } 
+            else {
+                params.sortCode = this.target
+                params.sortType = this.order == 'descend' ? 'DESC' : 'ASC'
+            }
+            this.postDataAction('/etl/reportAccountHourly/accountPageList',params).then(res => {
+                this.loading = false;
+                if(res.success) {
+                    this.dataSource = res.result.list
+                    this.ipagination.total = res.result.total
+                }
+            })
+        }
+    },
+    mounted() {
+        this.$nextTick(() => {
+            if(localStorage.getItem('stockWatchUserId')&&this.$route.query.person) {
+                let data = JSON.parse(localStorage.getItem('stockWatchUserId'));
+                this.dateValue = [moment(data.timeRange[0]),moment(data.timeRange[1])];
+            }
+            this.showColumn();
+            this.getPersonAchievements();
+            this.getPersonList();
+        })
+    }
+};
+</script>
+<style lang="less" scoped>
+    @import "keep-person";
+</style>

+ 156 - 0
src/views/modules/taobao-plan-daily/BytedanceCustomerDdTbtjDataList.vue

@@ -0,0 +1,156 @@
+<template>
+  <a-card :bordered="false">
+
+    <!-- 查询区域 -->
+    <!-- <div class="table-page-search-wrapper">
+      <a-form layout="inline">
+        <a-row :gutter="24">
+          <a-col :md="6" :sm="8">
+            <a-form-item label="日期">
+              <a-input placeholder="请输入" v-model="queryParam.stateDate"></a-input>
+            </a-form-item>
+          </a-col>
+          <a-col :md="6" :sm="8" >
+            <span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
+              <a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
+              <a-button type="primary" @click="searchReset" icon="reload" style="margin-left: 8px">重置</a-button>
+            </span>
+          </a-col>
+
+        </a-row>
+      </a-form>
+    </div> -->
+
+    <!-- 操作按钮区域 -->
+    <div class="table-operator">
+       <a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
+      <a-upload name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader" :action="importExcelUrl" @change="handleImportExcel">
+        <a-button type="primary" icon="import">导入</a-button>
+      </a-upload>
+      <a target="_blank" href="http://139.186.29.76:8804/jeecg-boot/ureport/preview?_u=mysql:%E6%B7%98%E7%89%B9%E8%AE%A1%E5%88%92%E6%97%A5%E6%8A%A5-%E5%A4%B4%E6%9D%A1.ureport.xml">手淘日报预览</a>
+      <a-dropdown v-if="selectedRowKeys.length > 0">
+        <a-menu slot="overlay">
+          <a-menu-item key="1" @click="batchDel"><a-icon type="delete"/>删除</a-menu-item>
+        </a-menu>
+      </a-dropdown>
+    </div>
+
+    <!-- table区域-begin -->
+    <div>
+      <div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
+        <i class="anticon anticon-info-circle ant-alert-icon"></i> 已选择 <a style="font-weight: 600">{{ selectedRowKeys.length }}</a>项
+        <a style="margin-left: 24px" @click="onClearSelected">清空</a>
+      </div>
+
+      <a-table
+        ref="table"
+        size="middle"
+        bordered
+        rowKey="id"
+        :columns="columns"
+        :dataSource="dataSource"
+        :pagination="ipagination"
+        :loading="loading"
+        :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
+        @change="handleTableChange">
+
+        <span slot="action" slot-scope="text, record">
+          <a @click="handleEdit(record)">编辑</a>
+
+          <a-divider type="vertical" />
+          <a-dropdown>
+            <a class="ant-dropdown-link">更多 <a-icon type="down" /></a>
+            <a-menu slot="overlay">
+              <a-menu-item>
+                <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
+                  <a>删除</a>
+                </a-popconfirm>
+              </a-menu-item>
+            </a-menu>
+          </a-dropdown>
+        </span>
+
+      </a-table>
+    </div>
+    <!-- table区域-end -->
+
+    <!-- 表单区域 -->
+    <bytedanceCustomerDdTbtjData-modal ref="modalForm" @ok="modalFormOk"></bytedanceCustomerDdTbtjData-modal>
+  </a-card>
+</template>
+
+<script>
+  import BytedanceCustomerDdTbtjDataModal from './modules/BytedanceCustomerDdTbtjDataModal'
+  import { JeecgListMixin } from '@/mixins/JeecgListMixin'
+
+  export default {
+    name: "BytedanceCustomerDdTbtjDataList",
+    mixins:[JeecgListMixin],
+    components: {
+      BytedanceCustomerDdTbtjDataModal
+    },
+    data () {
+      return {
+        description: '淘宝特价版客户反馈数据管理页面',
+        // 表头
+        columns: [
+          {
+            title: '#',
+            dataIndex: '',
+            key:'rowIndex',
+            width:60,
+            align:"center",
+            customRender:function (t,r,index) {
+              return parseInt(index)+1;
+            }
+           },
+		   {
+            title: '计划ID',
+            align:"center",
+            dataIndex: 'adId'
+           },
+		   {
+            title: '日期',
+            align:"center",
+            dataIndex: 'stateDate'
+           },
+		   {
+            title: '登录数',
+            align:"center",
+            dataIndex: 'loginCnt'
+           },
+		   {
+            title: '首购买人数',
+            align:"center",
+            dataIndex: 'buyerCnt'
+           },
+		   {
+            title: '次留数',
+            align:"center",
+            dataIndex: 'nextDayStay'
+           }
+        ],
+		url: {
+          list: "/ctop/bytedanceCustomerDdTbtjData/list",
+          delete: "/ctop/bytedanceCustomerDdTbtjData/delete",
+          deleteBatch: "/ctop/bytedanceCustomerDdTbtjData/deleteBatch",
+          exportXlsUrl: "ctop/bytedanceCustomerDdTbtjData/exportXls",
+          importExcelUrl: "ctop/bytedanceCustomerDdTbtjData/importExcel",
+       },
+    }
+  },
+  computed: {
+    importExcelUrl: function(){
+      return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;
+    }
+  },
+    methods: {
+     handleShouTaoPreview() {
+       window.open('www.baidu.com', '_blank');
+     }
+    }
+  }
+</script>
+<style scoped>
+  @import '~@assets/less/common.less'
+</style>

+ 148 - 0
src/views/modules/taobao-plan-daily/modules/BytedanceCustomerDdTbtjDataModal.vue

@@ -0,0 +1,148 @@
+<template>
+  <a-modal
+    :title="title"
+    :width="800"
+    :visible="visible"
+    :confirmLoading="confirmLoading"
+    @ok="handleOk"
+    @cancel="handleCancel"
+    cancelText="关闭">
+    
+    <a-spin :spinning="confirmLoading">
+      <a-form :form="form">
+      
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="adId">
+          <a-input placeholder="请输入adId" v-decorator="['adId', {}]" />
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="stateDate">
+          <a-input placeholder="请输入stateDate" v-decorator="['stateDate', {}]" />
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="loginCnt">
+          <a-input-number v-decorator="[ 'loginCnt', {}]" />
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="bugerCnt">
+          <a-input-number v-decorator="[ 'bugerCnt', {}]" />
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="nextDayStay">
+          <a-input-number v-decorator="[ 'nextDayStay', {}]" />
+        </a-form-item>
+		
+      </a-form>
+    </a-spin>
+  </a-modal>
+</template>
+
+<script>
+  import { httpAction } from '@/api/manage'
+  import pick from 'lodash.pick'
+  import moment from "moment"
+
+  export default {
+    name: "BytedanceCustomerDdTbtjDataModal",
+    data () {
+      return {
+        title:"操作",
+        visible: false,
+        model: {},
+        labelCol: {
+          xs: { span: 24 },
+          sm: { span: 5 },
+        },
+        wrapperCol: {
+          xs: { span: 24 },
+          sm: { span: 16 },
+        },
+
+        confirmLoading: false,
+        form: this.$form.createForm(this),
+        validatorRules:{
+        },
+        url: {
+          add: "/ctop/bytedanceCustomerDdTbtjData/add",
+          edit: "/ctop/bytedanceCustomerDdTbtjData/edit",
+        },
+      }
+    },
+    created () {
+    },
+    methods: {
+      add () {
+        this.edit({});
+      },
+      edit (record) {
+        this.form.resetFields();
+        this.model = Object.assign({}, record);
+        this.visible = true;
+        this.$nextTick(() => {
+          this.form.setFieldsValue(pick(this.model,'adId','stateDate','loginCnt','bugerCnt','nextDayStay'))
+		  //时间格式化
+        });
+
+      },
+      close () {
+        this.$emit('close');
+        this.visible = false;
+      },
+      handleOk () {
+        const that = this;
+        // 触发表单验证
+        this.form.validateFields((err, values) => {
+          if (!err) {
+            that.confirmLoading = true;
+            let httpurl = '';
+            let method = '';
+            if(!this.model.id){
+              httpurl+=this.url.add;
+              method = 'post';
+            }else{
+              httpurl+=this.url.edit;
+               method = 'put';
+            }
+            let formData = Object.assign(this.model, values);
+            //时间格式化
+            
+            console.log(formData)
+            httpAction(httpurl,formData,method).then((res)=>{
+              if(res.success){
+                that.$message.success(res.message);
+                that.$emit('ok');
+              }else{
+                that.$message.warning(res.message);
+              }
+            }).finally(() => {
+              that.confirmLoading = false;
+              that.close();
+            })
+
+
+
+          }
+        })
+      },
+      handleCancel () {
+        this.close()
+      },
+
+
+    }
+  }
+</script>
+
+<style lang="less" scoped>
+
+</style>

+ 155 - 0
src/views/modules/taobao-plan-daily/modules/BytedanceCustomerDdTbtjDataModal__Style#Drawer.vue

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

+ 1 - 1
vue.config.js

@@ -84,7 +84,7 @@ module.exports = {
         // target: 'https://trac.tjyourong.com.cn', //请求本地 需要jeecg-boot后台项目
         // target: 'http://39.106.184.70:8088/', //请求本地 需要jeecg-boot后台项目
         //  target: 'http://adsp.tjyourong.com.cn/', //请求本地 需要jeecg-boot后台项目
-        // target: 'http://192.168.1.251/', //请求本地 需要jeecg-boot后台项目
+        // target: 'http://192.168.1.251/', //请求本地 需要jeecg-boot后台项目 
         // target:'http://118.24.244.213:8804',
       //  target:'http://139.186.165.84:8806', //测试