Ver código fonte

报表完版

朱鑫波 3 anos atrás
pai
commit
a9345455d3
32 arquivos alterados com 11167 adições e 911 exclusões
  1. 3 1
      .env.production
  2. 72 32
      src/components/formComponents/selectAccount.vue
  3. 1 1
      src/utils/request.js
  4. 1 1
      src/views/modules/Statistics/KSAccountReport.vue
  5. 0 1
      src/views/modules/Statistics/components/Treeselect.vue
  6. 4 0
      src/views/modules/Statistics/components/selectPagination.vue
  7. 1673 0
      src/views/modules/Statistics/kuaishouReport/accountReport.vue
  8. 1298 0
      src/views/modules/Statistics/kuaishouReport/components/selectComponent.vue
  9. 222 0
      src/views/modules/Statistics/kuaishouReport/kuaishouReport-service.js
  10. 265 0
      src/views/modules/Statistics/kuaishouReport/kuaishouReport.less
  11. 1310 0
      src/views/modules/Statistics/kuaishouReport/videoReport.vue
  12. 0 1
      src/views/modules/Statistics/newPlanStatic/newPlanStatic.vue
  13. 121 0
      src/views/modules/autoLaunch/auto-copy-library/auto-copy-library.less
  14. 487 0
      src/views/modules/autoLaunch/auto-copy-library/auto-copy-library.vue
  15. 1138 0
      src/views/modules/autoLaunch/channelManage/channelDetailList.vue
  16. 17 1
      src/views/modules/autoLaunch/channelManage/channelManage.less
  17. 534 0
      src/views/modules/autoLaunch/channelManage/components/creatApplication.vue
  18. 244 0
      src/views/modules/autoLaunch/channelManage/components/treeSelectAccount.vue
  19. 228 0
      src/views/modules/autoLaunch/channelManage/components/treeSelectProject.vue
  20. 365 0
      src/views/modules/autoLaunch/channelManage/components/uploadFile.vue
  21. 1031 0
      src/views/modules/autoLaunch/channelManage/createChannel.vue
  22. 327 837
      src/views/modules/autoLaunch/channelManage/index.vue
  23. 951 0
      src/views/modules/autoLaunch/channelManage/itemList.vue
  24. 166 15
      src/views/modules/autoLaunch/configLaunchInfo.vue
  25. 6 3
      src/views/modules/autoLaunch/configLaunchList.vue
  26. 12 14
      src/views/modules/autoLaunch/material-pool/material.vue
  27. 426 0
      src/views/modules/earlyWarningRules/configurationList.vue
  28. 257 0
      src/views/modules/earlyWarningRules/whitelist.vue
  29. 1 1
      src/views/modules/headline-view/headline-view-server.js
  30. 4 0
      src/views/modules/material/comment/selectTable.vue
  31. 1 1
      src/views/modules/material/videoMaterial.vue
  32. 2 2
      vue.config.js

+ 3 - 1
.env.production

@@ -2,4 +2,6 @@
 VUE_APP_BASE_API_URL = http://118.24.244.213:3030
 
 #账户报表/素材报表接口地址
-VUE_APP_BASE_REPORT_URL = http://api.tjyourong.com.cn/reportModule
+VUE_APP_BASE_REPORT_URL = http://api.tjyourong.com.cn/reportModule
+# 测试地址 http://gateway.tjyourong.com.cn
+# 线上地址 http://api.tjyourong.com.cn

+ 72 - 32
src/components/formComponents/selectAccount.vue

@@ -2,6 +2,9 @@
 .select-project {
     width: 50%;
 }
+/deep/.vue-treeselect__control {
+    line-height: 20px !important;
+}
 </style>
 <template>
     <div class="select-project">
@@ -40,12 +43,17 @@ import { mapGetters } from 'vuex'
 // instead of requesting a real API server for demo purpose.
 export default {
     data: () => ({
-        value: null,
         valueConsistsOf: 'LEAF_PRIORITY',
         options: [],
         showLoading: 'loading...'
     }),
     props: {
+        value: {
+            type: [Number, Array, String],
+            default() {
+                return undefined
+            }
+        },
         //是否展示一个默认值
         oneData: {
             type: Boolean,
@@ -98,8 +106,11 @@ export default {
                 return this.value
             },
             set: function(val) {
-                this.$emit('input', val)
-                this.$emit('change', val)
+                this.$nextTick(() => {
+                    this.$emit('input', val)
+                    this.$emit('change', val)
+                    this.$emit('value');
+                })
             }
         }
     },
@@ -125,43 +136,72 @@ export default {
             params.type = this.type
             this.postDataAction(this.reqUrl, params).then(res => {
                 if (res.success) {
-                    this.options = res.result.map(item => {
-                        return {
-                            id: item.projectId + 'projectId',
-                            label: item.projectName,
-                            children: item.accountList
-                                ? item.accountList.map(c => {
-                                      return {
-                                          id: c.accountId,
-                                          label:
-                                              (c.userName && c.userName.length == 2
-                                                  ? c.userName + '\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0'
-                                                  : c.userName && c.userName.length == 3
-                                                  ? c.userName + '\xa0\xa0\xa0\xa0'
-                                                  : c.userName) +
-                                              '\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0' +
-                                              c.accountId +
-                                              '\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0' +
-                                              c.authName
-                                      }
-                                  })
-                                : []
-                        }
-                    })
-                    if (this.oneData && !this.multiple) {
-                        var data = this.options.filter(item => {
-                            if (item.children && item.children.length > 0) {
-                                return { ...item }
+                    this.options = res.data
+                        ? res.data.map(item => {
+                              return {
+                                  id: item.projectId + 'projectId',
+                                  label: item.projectName,
+                                  children: item.accountList
+                                      ? item.accountList.map(c => {
+                                            return {
+                                                id: c.accountId,
+                                                label:
+                                                    (c.userName && c.userName.length == 2
+                                                        ? c.userName + '\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0'
+                                                        : c.userName && c.userName.length == 3
+                                                        ? c.userName + '\xa0\xa0\xa0\xa0'
+                                                        : c.userName) +
+                                                    '\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0' +
+                                                    c.accountId +
+                                                    '\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0' +
+                                                    c.authName
+                                            }
+                                        })
+                                      : []
+                              }
+                          })
+                        : res.result.map(item => {
+                              return {
+                                  id: item.projectId + 'projectId',
+                                  label: item.projectName,
+                                  children: item.accountList
+                                      ? item.accountList.map(c => {
+                                            return {
+                                                id: c.accountId,
+                                                label:
+                                                    (c.userName && c.userName.length == 2
+                                                        ? c.userName + '\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0'
+                                                        : c.userName && c.userName.length == 3
+                                                        ? c.userName + '\xa0\xa0\xa0\xa0'
+                                                        : c.userName) +
+                                                    '\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0' +
+                                                    c.accountId +
+                                                    '\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0' +
+                                                    c.authName
+                                            }
+                                        })
+                                      : []
+                              }
+                          })
+                    if (this.oneData) {
+                        this.$nextTick(() => {
+                            if (this.multiple) {
+                                this.selectedVal.push(this.options[0].children[0].id)
+                            } else {
+                                this.selectedVal = this.options[0].children[0].id
                             }
                         })
-                        this.selectedVal = data[0].children[0].id
+
+                        // this.value = this.options[0].children[0].id
+                        // this.$emit('input', this.options[0].children[0].id)
+                        // this.$emit('change', this.options[0].children[0].id)
                     }
                 }
             })
         }
     },
 
-    mounted() {
+    created() {
         this.getParticipateList()
     }
 }

+ 1 - 1
src/utils/request.js

@@ -144,4 +144,4 @@ const installer = {
 export {
 	installer as VueAxios,
 	service as axios
-};
+};

+ 1 - 1
src/views/modules/Statistics/KSAccountReport.vue

@@ -151,7 +151,7 @@
                   日期选择具体某一天之后,这里可以查看具体的时间段数据哦~
                 </template>
                 <!-- v-show="dateValue[0].format('YYYY-MM-DD')==dateValue[1].format('YYYY-MM-DD')" -->
-                  <a-select  placeholder="请选择具体时间段" style="width: 160px" @change="timeChange"  v-model='timeDefaultValue'  label-in-value class="selectTime" v-show="dateValue[1].format('YYYY-MM-DD')==moment().format('YYYY-MM-DD')" :disabled='accountId.length==0'>
+                  <a-select  placeholder="请选择具体时间段" style="width: 160px" @change="timeChange"  v-model='timeDefaultValue'  label-in-value class="selectTime" v-show="dateValue[1].format('YYYY-MM-DD')==moment().format('YYYY-MM-DD')">
                     <a-select-option v-for="(i,index) in 24 " :key="index" :value="index" >{{index>=10 ? `00:00-${index}:59` :`00:00-0${index}:59`}}</a-select-option>
                   </a-select>
               </a-tooltip>

+ 0 - 1
src/views/modules/Statistics/components/Treeselect.vue

@@ -105,7 +105,6 @@ export default {
     $route(n, o) {},
     appId: {
       handler(n, o) {
-        console.log(n)
         if (n.length == 0) {
           if (this.multiple) {
             this.value = []

+ 4 - 0
src/views/modules/Statistics/components/selectPagination.vue

@@ -283,6 +283,10 @@ export default {
     },
     handleClose() {
       this.topMiddle = false
+      if(!!!this.projectId){
+        this.keyValue = ''
+        this.getData(this.productId)
+      }
     },
     // allData() {
     //   getAction('/ctop/projectMember/participateListV2', {

Diferenças do arquivo suprimidas por serem muito extensas
+ 1673 - 0
src/views/modules/Statistics/kuaishouReport/accountReport.vue


Diferenças do arquivo suprimidas por serem muito extensas
+ 1298 - 0
src/views/modules/Statistics/kuaishouReport/components/selectComponent.vue


+ 222 - 0
src/views/modules/Statistics/kuaishouReport/kuaishouReport-service.js

@@ -0,0 +1,222 @@
+/**
+ * @file 人群包管理基础服务
+ * @author jiayufei(jiayufei@c-top.com.cn)
+ */
+
+ class AppMarketService {
+    constructor() {}
+
+    // 相关账户的table列表
+    setAcountColumns() {
+        return [
+            {
+                title: '账户名称',
+                dataIndex: 'authName',
+                width: '50%',
+                align: 'center'
+            },
+           
+            {
+                title: '应用数量',
+                dataIndex: 'appCount',
+                width: '50%',
+                align: 'center'
+            },
+        ]
+            
+    }
+
+    // 原因的table列表
+    setCauseColumns() {
+        return [
+            {
+                title: '账户名称',
+                dataIndex: 'authName',
+                width: '25%',
+                align: 'center'
+            },
+            {
+                title: '推送结果',
+                dataIndex: 'result',
+                width: '25%',
+                align: 'center'
+            },
+            {
+                title: '失败原因',
+                dataIndex: 'message',
+                width: '25%',
+                align: 'center',
+                customRender(t) {
+                    if(t === 'OK') {
+                        return '-';
+                    }
+                    else {
+                        return t;
+                    }
+                }
+            },
+            {
+                title: '操作',
+                dataIndex: 'action',
+                scopedSlots: {customRender: 'action'},
+                width: '25%',
+                align: 'center'
+            }
+        ]
+    }
+
+    // 相关项目的table列表
+    setDepColumns() {
+        return [
+            {
+                title: '广告组名称',
+                dataIndex: 'unitName',
+                width: '50%',
+                align: 'center'
+            },
+            {
+                title: '所属账户',
+                dataIndex: 'authName',
+                width: '50%',
+                align: 'center'
+            }
+        ]
+    }
+
+    // 状态枚举
+    setPlatform() {
+        return [
+            {
+                label: '',
+                value: '不限'
+            },
+            {
+                label: 1,
+                value: 'Android 应用下载'
+            },
+            {
+                label: 2,
+                value: 'Android 网页游戏'
+            },
+            {
+                label: 3,
+                value: 'iOS 应用下载'
+            },
+            {
+                label: 4,
+                value: 'iOS 网页游戏'
+            }
+        ]
+    }
+
+    // 上传人去报的校验规则
+    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();

+ 265 - 0
src/views/modules/Statistics/kuaishouReport/kuaishouReport.less

@@ -0,0 +1,265 @@
+.account-report {
+    .directional-content {
+        background: #fff;
+        // height: calc(100vh - 137px);
+        padding: 20px;
+        margin-bottom: 15px;
+        /deep/.table-page-search-wrapper {
+            /deep/.ant-form-inline {
+                .ant-form-item {
+                    display: flex;
+                    margin-bottom: 24px;
+                    margin-right: 0;
+
+                    .ant-form-item-control-wrapper {
+                        flex: 1 1;
+                        display: inline-block;
+                        vertical-align: middle;
+                    }
+
+                    > .ant-form-item-label {
+                        line-height: 32px;
+                        padding-right: 8px;
+                        width: auto;
+                    }
+
+                    /deep/.ant-form-item-control {
+                        height: auto;
+                        line-height: 32px;
+                    }
+                }
+            }
+
+            .table-page-search-submitButtons {
+                display: block;
+                margin-bottom: 24px;
+                white-space: nowrap;
+            }
+        }
+
+        .middle-button {
+            margin: 0 8px;
+        }
+        .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;
+        }
+    }
+    .show {
+        // background-color: #fff;
+        width: 100%;
+        display: flex;
+        justify-content: space-between;
+        // padding: 0px 15px;
+        box-sizing: border-box;
+        margin-bottom: 15px;
+
+        .showBox {
+            width: 19%;
+            box-sizing: border-box;
+            padding: 15px 15px;
+            background-color: #fff;
+
+            .title {
+                color: #999;
+                font-size: 16px;
+                position: relative;
+                text-align: center;
+                .infotitle {
+                    padding: 8px 0;
+                }
+
+                span {
+                    font-size: 1rem;
+                    // color: #1890ff;
+                    position: absolute;
+                    top: 0;
+                    right: 0;
+                    cursor: pointer;
+                }
+            }
+            .infoNum {
+                padding: 10px 0;
+                text-align: center;
+                font-weight: 600;
+                font-size: 20px;
+                span {
+                    font-weight: 600;
+                    font-size: 16px;
+                }
+                .red {
+                    font-size: 20px;
+                    font-weight: 600;
+                    color: red;
+                }
+                .green {
+                    display: block;
+                    text-align: center;
+                    margin-left: 0.2rem;
+                    font-size: 14px;
+                    font-weight: 700;
+                    color: #32cd32;
+                    .huanbi {
+                        // color:#999;
+                        font-weight: 400;
+                        font-size: 14px;
+                    }
+                }
+            }
+        }
+    }
+    .chartBox {
+        background-color: #fff;
+        margin: 15px 0px;
+        padding: 2px 10px 30px;
+    }
+    .tableBox {
+        background-color: #fff;
+        margin: 15px 0px;
+        padding: 15px 10px;
+        .tableTop {
+            position: relative;
+            padding-bottom: 15px;
+            border-bottom: 1px solid #e0e0e0;
+            .selectTime {
+                margin-right: 20px;
+            }
+            .add {
+                position: absolute;
+                top: 0;
+                right: 0;
+            }
+        }
+    }
+    /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 {
+                width: 80px;
+            }
+            .acount-title-left::after {
+                content: ' : ';
+            }
+        }
+        .push-plate {
+            margin-bottom: 20px;
+        }
+    }
+
+    .grid-form-item-account {
+        /deep/ .ant-form-item-control {
+            line-height: inherit;
+        }
+    }
+}
+
+.video-report {
+    .directional-content {
+        background: #fff;
+        // height: calc(100vh - 137px);
+        padding: 20px;
+        margin-bottom: 15px;
+        .middle-button {
+            margin: 0 8px;
+        }
+    }
+    .tableBox {
+        background-color: #fff;
+        margin: 15px 0px;
+        padding: 15px 10px;
+        .tableTop {
+            position: relative;
+            padding-bottom: 15px;
+            border-bottom: 1px solid #e0e0e0;
+            .selectTime {
+                margin-right: 20px;
+            }
+            .add {
+                position: absolute;
+                top: 0;
+                right: 0;
+            }
+        }
+    }
+}

Diferenças do arquivo suprimidas por serem muito extensas
+ 1310 - 0
src/views/modules/Statistics/kuaishouReport/videoReport.vue


+ 0 - 1
src/views/modules/Statistics/newPlanStatic/newPlanStatic.vue

@@ -1318,7 +1318,6 @@ export default {
 	},
 	watch: {
 		dateValue(newName,oldName){
-		
 			this.search()
 		},
 	},

+ 121 - 0
src/views/modules/autoLaunch/auto-copy-library/auto-copy-library.less

@@ -0,0 +1,121 @@
+.auto-copylibrary-content {
+    background: #fff;
+    // height: calc(100vh - 320px);
+    padding: 20px;
+    overflow-y: auto;
+    .control-con-header {
+        margin-bottom: 20px;
+        position: relative;
+        .grid-form-options {
+            margin-top: 15px;
+        }
+        .common-input-long,
+        .acount-search-class {
+            width: 625px;
+        }
+        .common-input-long {
+            margin-left: 10px;
+        }
+        .reset-class {
+            margin-right: 10px !important;
+        }
+        .upload-person {
+            position: absolute;
+            right: 10px;
+            top: 0;
+        }
+    }
+    .pagin-table-class {
+        display: flex;
+        justify-content: flex-end;
+        margin-top: 20px;
+    }
+}
+/deep/ .auto-copy-library-modal {
+    width: 700px !important;
+    .ant-modal-body {
+        height: 380px !important;
+        overflow-y: auto;
+    }
+    .ad-name-tags-class {
+        width: 500px;
+        display: flex;
+        .name-tags-left {
+            width: 350px;
+        }
+    }
+    .acount-title {
+        display: flex;
+        font-size: 14px;
+        margin-top: 20px;
+        line-height: 32px;
+        .acount-title-left {
+            margin-right: 20px;
+            width: 70px;
+        }
+        .only-title-mater {
+            width: 400px;
+            .upload-prompt-information {
+                height: 20px;
+                line-height: 20px;
+            }
+            .special-number-line {
+                margin-top: 20px;
+            }
+            .select-project {
+                width: 100%;
+            }
+            .mater-list-name {
+                display: flex;
+                height: 30px;
+                margin: 0;
+                .mater-list-show {
+                    display: inline-block;
+                    width: 400px;
+                    white-space: nowrap;
+                    overflow: hidden;
+                    text-overflow: ellipsis;
+                }
+                .mater-list-icon {
+                    margin-left: 10px;
+                    color: #1890ff;
+                    cursor: pointer;
+                }
+            }
+        }
+        .examin-form-model {
+            width: 500px;
+            position: relative;
+            .examin-form-num {
+                position: absolute;
+                top: -10px;
+                right: -50px;
+            }
+            .examin-form-icon {
+                position: absolute;
+                top: 0px;
+                right: -85px;
+                font-size: 18px;
+                color: #1890ff;
+                cursor: pointer;
+            }
+        }
+        .examin-form-input {
+            width: 380px;
+        }
+    }
+    .push-plate {
+        margin-bottom: 20px;
+        .examin-select-title {
+            margin: 0 20px 0 20px;
+        }
+    }
+}
+/deep/ .reject-ideas-modal {
+    width: 900px !important;
+    .pagin-table-class {
+        display: flex;
+        justify-content: flex-end;
+        margin-top: 20px;
+    }
+}

+ 487 - 0
src/views/modules/autoLaunch/auto-copy-library/auto-copy-library.vue

@@ -0,0 +1,487 @@
+<template>
+    <div class="auto-copylibrary-content">
+        <div class="control-con-header">
+            <a-form
+                class="grid-form"
+                layout="inline"
+                hide-required-mark
+            >
+                <a-row>
+                    <a-form-item
+                        class="grid-form-item"
+                        label="账户:"
+                        :colon="false"
+                    >
+                        <acount-search
+                            class="acount-search-class"
+                            :appId.sync="configForm.acountId"
+                            :multiple="false"
+                            request="2,4"
+                        >
+                        </acount-search>
+                    </a-form-item>
+                    <a-form-item label="状态">
+                        <a-select v-model="configForm.searchStatus" style="width: 100px">
+                            <a-select-option :value="2">不限</a-select-option>
+                            <a-select-option :value="0">可投放</a-select-option>
+                            <a-select-option :value="1">已下架</a-select-option>
+                        </a-select>
+                    </a-form-item>
+                </a-row>
+                <a-row class="grid-form-options">
+                    <a-form-item
+                        class="grid-form-item"
+                        label="关键词:"
+                        :colon="false"
+                    >
+                        <a-input v-model="configForm.num" placeholder="请输入关键词"/>
+                    </a-form-item>
+                    <a-form-item
+                        class="grid-form-item"
+                        label="选择时间:"
+                        :colon="false"
+                    >
+                        <a-range-picker
+                            v-model="configForm.launchDateRange"
+                            format="YYYY-MM-DD"
+                            @change="handleLaunchData"
+                        />
+                    </a-form-item>
+                    <a-form-item class="form-handle-btn">
+                        <a-button type="primary" class="reset-class" icon="reload" @click="handleResetList">重置</a-button>
+                        <a-button type="primary" class="reset-class" icon="search" @click="handleQueryList">查询</a-button>
+                        <a-button type="primary" @click="handleAddAccountConfig">新增文案</a-button>
+                    </a-form-item>
+                </a-row>
+            </a-form>
+        </div>
+        <div class="control-con-table">
+            <a-table
+                ref="table"
+                size="middle"
+                bordered
+                :columns="currencyColumns"
+                :dataSource="currencyData"
+                :pagination="false"
+                :loading="controlLoading"
+            >
+                <span slot="action" slot-scope="text, record">
+                    <a @click="handleEditCopyLibrary(record)" :disabled="record.status !== 0">编辑</a>
+                    <a-divider type="vertical"/>
+                    <a @click="handleOffSheif(record)" :disabled="record.status !== 0">下架</a>
+                </span>
+                <span slot="reason" slot-scope="text, record">
+                    <a @click="handleRejectionReason(record)">被拒创意详情</a>
+                </span>
+            </a-table>
+            <a-pagination
+                class="pagin-table-class"
+                v-model="currencyPag.page"
+                :page-size="currencyPag.size"
+                :total="currencyTotalAll"
+                :show-total="total => `共 ${currencyTotalAll} 条`"
+                size="small"
+                show-size-changer
+                show-quick-jumper
+                @change="handleCurrentPage"
+                @showSizeChange="handleCurrentPage"
+            />
+        </div>
+        <a-modal
+            v-if="causeVisible"
+            :title="copywritingType === 'add' ? '新建文案' : '编辑文案'"
+            :visible="causeVisible"
+            :confirmLoading="confirmLoading"
+            dialog-class="auto-copy-library-modal"
+            @ok="handleCauseSure"
+            @cancel="handleCauseCancel"
+        >
+            <div>
+                <div class="acount-title">
+                    <div class="acount-title-left">广告账户</div>
+                    <div class="acount-title-right">
+                        <div class="only-title-mater">
+                            <acount-search :appId.sync="advertisingAccount" request="2,4"></acount-search>
+                        </div>
+                    </div>
+                </div>
+                <div v-if="copywritingType === 'add'" class="acount-title">
+                    <div class="acount-title-left">批量上传</div>
+                    <div class="acount-title-right">
+                        <div class="only-title-mater">
+                            <a-upload
+                                name="file"
+                                :file-list="fileList"
+                                :customRequest="handleCustomRequest"
+                                :remove="handleRemoveUpload"
+                            >
+                                <a-button><a-icon type="upload"/>文件上传</a-button>
+                            </a-upload>
+                            <p class="upload-prompt-information special-number-line">1、 文件格式为xls或xlsx,每行一条文案,每条文案不多于30字</p>
+                            <p class="upload-prompt-information">2、 请将文案写在Excel表的第一列,否则将无法上传</p>
+                        </div>
+                    </div>
+                </div>
+                <div v-if="copywritingType === 'edit'" class="acount-title">
+                    <div class="acount-title-left">文案</div>
+                    <div class="acount-title-right">
+                        <div class="only-title-mater">
+                            <a-input v-model="editTextShow.copy_writer" disabled/>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </a-modal>
+        <a-modal
+            v-if="rejectIdeasVisible"
+            title="被拒创意详情"
+            dialog-class="reject-ideas-modal"
+            :visible="rejectIdeasVisible"
+            :footer="null"
+            @cancel="handleRejectIdeasCancel"
+        >
+            <div>
+                <a-table
+                    ref="table"
+                    size="middle"
+                    bordered
+                    :columns="rejectIdeasColumns"
+                    :dataSource="rejectIdeasData"
+                    :pagination="false"
+                >
+                </a-table>
+                <a-pagination
+                    class="pagin-table-class"
+                    v-model="rejectIdeasPag.page"
+                    size="small"
+                    :page-size="rejectIdeasPag.size"
+                    :total="rejectIdeasTotalAll"
+                    :show-total="total => `共 ${rejectIdeasTotalAll} 条`"
+                    @change="handleRejectIdeasPage"
+                    @showSizeChange="handleRejectIdeasPage"
+                />
+            </div>
+        </a-modal>
+    </div>
+</template>
+<script>
+
+import AcountSearch from '@/views/modules/Statistics/components/Treeselect.vue';
+import {getAction, postAction} from '@/api/manage';
+import {mapGetters} from 'vuex';
+
+export default {
+    name: 'autoCopyLibrary',
+    components: {
+        AcountSearch
+    },
+    data() {
+        return {
+            editShowAccountList: [],
+            confirmLoading: false,
+            controlLoading: false,
+            refusedReasonList: {},
+            rejectIdeasVisible: false,
+            rejectIdeasPag: {
+                page: 1,
+                size: 10
+            },
+            rejectIdeasTotalAll: 0,
+            rejectIdeasColumns: [
+                {
+                    title: '账户名称',
+                    align: 'center',
+                    dataIndex: 'accountName'
+                },
+                {
+                    title: '广告组ID',
+                    align: 'center',
+                    dataIndex: 'unitId'
+                },
+                {
+                    title: '创意名称',
+                    align: 'center',
+                    dataIndex: 'creativeName'
+                },
+                {
+                    title: '被拒原因',
+                    align: 'center',
+                    dataIndex: 'reviewDetail'
+                }
+            ],
+            rejectIdeasData: [],
+            editTextShow: {},
+            fileList: [],
+            advertisingAccount: [],
+            currencyData: [],
+            currencyTotalAll: 0,
+            currencyPag: {
+                page: 1,
+                size: 20
+            },
+            currencyColumns: [
+                {
+                    title: '文案',
+                    align: 'center',
+                    dataIndex: 'copy_writer'
+                },
+                {
+                    title: '相关创意数',
+                    align: 'center',
+                    dataIndex: 'relatedSize'
+                },
+                {
+                    title: '被拒创意数',
+                    align: 'center',
+                    dataIndex: 'refusedSize'
+                },
+                {
+                    title: '状态',
+                    align: 'center',
+                    dataIndex: 'status',
+                    customRender(d) {
+                        return d === 0 ? '可投放' : '已下架'
+                    }
+                },
+                {
+                    title: '操作',
+                    dataIndex: 'action',
+                    align: 'center',
+                    scopedSlots: {customRender: 'action'}
+                },
+                {
+                    title: '更多',
+                    dataIndex: 'reason',
+                    align: 'center',
+                    scopedSlots: {customRender: 'reason'}
+                }
+            ],
+            causeVisible: false,
+            copywritingType: 'add',
+            configForm: {
+                acountId: '',
+                num: '',
+                adConvertId: undefined,
+                launchDateRange: [],
+                searchStatus: 2
+            }
+        };
+    },
+    mounted() {
+        this.handleInitTable();
+    },
+    methods: {
+        ...mapGetters(['userInfo']),
+        handleInitTable() {
+            this.controlLoading = true;
+            const paramsData = {
+                accountIds: this.configForm.acountId,
+                status: this.configForm.searchStatus,
+                keywords: this.configForm.num,
+                startDate: this.configForm.launchDateRange[0] || '',
+                endDate: this.configForm.launchDateRange[1] || '',
+                pageNumber: this.currencyPag.page,
+                pageSize: this.currencyPag.size
+            };
+            getAction('/document/library/getDocumentList', paramsData).then(result => {
+                if (result.code === 0) {
+                    this.currencyData = result.result.list;
+                    this.currencyTotalAll = result.result.total;
+                }
+                else {
+                    this.$message.error(result.message);
+                }
+            }).catch(error => {
+                console.log(error, 'eeee');
+            }).finally(() => {
+                this.controlLoading = false;
+            });
+        },
+        handleRejectIdeasCancel() {
+            this.refusedReasonList = {};
+            this.rejectIdeasVisible = false;
+        },
+        handleRejectIdeasPage(current, pageSize) {
+            this.currencyPag = {
+                page: current,
+                size: pageSize
+            };
+            this.handleGetRefusedList(this.refusedReasonList);
+        },
+        handleCustomRequest(info) {
+            const isZip = info.file.name.indexOf('xlsx') !== -1 || info.file.name.indexOf('xls') !== -1;
+            if (!isZip) {
+                this.$message.error('文件上传格式只能是xls、xlsx !');
+                return;
+            }
+            this.fileList = [];
+            this.$nextTick(() => {
+                this.fileList.push(info.file);
+            });
+        },
+        handleRemoveUpload(data) {
+            let index = this.fileList.indexOf(data);
+            let newUploadFile = this.fileList;
+            newUploadFile.splice(index, 1);
+            this.fileList = newUploadFile;
+        },
+        handleCauseSure() {
+            if (!this.advertisingAccount.length) {
+                this.$message.error('请选择账户');
+                return;
+            }
+            let paramsData = new FormData();
+            paramsData.append('accountIds', [...this.advertisingAccount, ...this.editShowAccountList]);
+            if (this.copywritingType === 'add') {
+                if (!this.fileList.length) {
+                    this.$message.error('请上传文件');
+                    return;
+                }
+                this.confirmLoading = true;
+                paramsData.append('file', this.fileList[0]);
+                this.handleSubmitOperation(paramsData, '/document/library/createdocument');
+            }
+            else if (this.copywritingType === 'edit') {
+                this.confirmLoading = true;
+                paramsData.append('copyWriterId', this.editTextShow.copyWriterId);
+                paramsData.append('copyWriter', this.editTextShow.copy_writer);
+                this.handleSubmitOperation(paramsData, '/document/library/updateDocument');
+            }
+        },
+        handleSubmitOperation(data, url) {
+            postAction(url, data).then(result => {
+                if (result.code === 200) {
+                    this.$message.success(result.message);
+                    this.advertisingAccount = [];
+                    this.fileList = [];
+                    this.editShowAccountList = [];
+                    this.causeVisible = false;
+                    this.currencyPag = {
+                        page: 1,
+                        size: 10
+                    };
+                    this.handleInitTable();
+                }
+                else {
+                    this.$message.error(result.message);
+                }
+            }).catch(error => {
+                console.log(error, 'eeee');
+            }).finally(() => {
+                this.confirmLoading = false;
+            });
+        },
+        handleCauseCancel() {
+            this.advertisingAccount = [];
+            this.fileList = [];
+            this.editShowAccountList = [];
+            this.causeVisible = false;
+        },
+        handleEditCopyLibrary(list) {
+            const defaultData = list;
+            this.editTextShow = defaultData;
+            this.handleGetAcoountId(list);
+            this.copywritingType = 'edit';
+            this.$nextTick(() => {
+                this.causeVisible = true;
+            });
+        },
+        handleGetAcoountId(list) {
+            getAction('/document/library/getAcoountId', {copyWriterId: list.copyWriterId}).then(result => {
+                if (result.code === 0) {
+                    const defaultData = result.result.map(item => Number(item));
+                    this.editShowAccountList = defaultData;
+                    this.advertisingAccount = defaultData;
+                }
+                else {
+                    this.$message.error(result.message);
+                }
+            }).catch(error => {
+                console.log(error, 'eeee');
+            });
+        },
+        handleOffSheif(list) {
+            let that = this;
+            this.$confirm({
+                title: '提示',
+                content: '是否确认下架该条文案',
+                onOk() {
+                    const params = {
+                        copyWriterId: list.copyWriterId,
+                        status: 1
+                    };
+                    getAction('/document/library/updateStatus', params).then(result => {
+                        if (result.code === 200) {
+                            that.$message.success(result.message);
+                            that.handleInitTable();
+                        }
+                        else {
+                            that.$message.error(result.message);
+                        }
+                    }).catch(error => {
+                        console.log(error, 'eeee');
+                    });
+                }
+            });
+        },
+        handleCurrentPage(current, pageSize) {
+            this.currencyPag = {
+                page: current = pageSize !== this.currencyPag.size ? 1 : current,
+                size: pageSize
+            };
+            this.handleInitTable();
+        },
+        // 被拒理由的操作
+        handleRejectionReason(list) {
+            this.refusedReasonList = list;
+            this.handleGetRefusedList(list);
+            this.rejectIdeasVisible = true;
+        },
+        handleGetRefusedList(list) {
+            const paramsData = {
+                copyWriterId: list.copyWriterId,
+                pageNumber: this.rejectIdeasPag.page,
+                pageSize: this.rejectIdeasPag.size
+            };
+            getAction('/document/library/getRefusedList', paramsData).then(result => {
+                if (result.code === 0) {
+                    this.rejectIdeasData = result.result.list;
+                    this.rejectIdeasTotalAll = result.result.total;
+                }
+                else {
+                    this.$message.error(result.message);
+                }
+            }).catch(error => {
+                console.log(error, 'eeee');
+            });
+        },
+        handleAddAccountConfig() {
+            this.causeVisible = true;
+            this.copywritingType = 'add';
+        },
+        handleResetList() {
+            this.configForm = {
+                acountId: '',
+                num: '',
+                adConvertId: undefined,
+                launchDateRange: [],
+                searchStatus: 2
+            };
+            this.currencyPag = {
+                page: 1,
+                size: 20
+            };
+            this.handleInitTable();
+        },
+        handleQueryList() {
+            this.handleInitTable();
+        },
+        handleLaunchData(date, dateString) {
+            this.configForm.launchDateRange = dateString;
+        }
+    }
+}
+</script>
+<style lang="less" scoped>
+    @import "auto-copy-library";
+</style>

Diferenças do arquivo suprimidas por serem muito extensas
+ 1138 - 0
src/views/modules/autoLaunch/channelManage/channelDetailList.vue


+ 17 - 1
src/views/modules/autoLaunch/channelManage/channelManage.less

@@ -1,4 +1,3 @@
-
 .channelManage {
     .middle-button {
         margin: 0 8px;
@@ -41,3 +40,20 @@
         padding: 20px;
     }
 }
+.channel-modal-content {
+    width: 100%;
+    height: 300px;
+    display: flex;
+    flex-direction: column;
+    .channel-modal-content-button {
+        width: 100%;
+        height: 100%;
+        margin: 10px;
+        display: flex;
+        align-items: center;
+        .introduce{
+            margin-left: 10px;
+        }
+
+    }
+}

+ 534 - 0
src/views/modules/autoLaunch/channelManage/components/creatApplication.vue

@@ -0,0 +1,534 @@
+<style lang="less" scoped>
+.require-class {
+    /deep/ .ant-form-item-label {
+        label::before {
+            display: inline-block;
+            margin-right: 4px;
+            color: #f5222d;
+            font-size: 14px;
+            font-family: SimSun, sans-serif;
+            line-height: 1;
+            content: '*';
+        }
+    }
+}
+</style>
+<template>
+    <div>
+        <a-modal
+            title="添加应用"
+            :visible="application"
+            @ok="handleSubmit"
+            :confirmLoading="confirmLoading"
+            @cancel="handleCancel"
+            width="800px"
+        >
+            <a-card :body-style="{ padding: '24px 32px' }" :bordered="false">
+                <a-form :form="form">
+                    <a-form-item
+                        label="下载链接"
+                        :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
+                        :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
+                    >
+                        <a-input
+                            placeholder="请填写应用下载链接"
+                            v-decorator="[
+                                'url',
+                                {
+                                    rules: [{ required: true, validator: handleConfirmValue }]
+                                }
+                            ]"
+                            id="url"
+                        />
+                        <a-tag
+                            color="#2db7f5"
+                            @click="getChangeAll('渠道号', 'form', 'url')"
+                            v-if="createTypeData && createTypeData.createType == '1'"
+                            >+渠道号</a-tag
+                        >
+                    </a-form-item>
+
+                    <a-form-item
+                        label="应用包名"
+                        v-if="uploadType == '2' && appType == 'android'"
+                        :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
+                        :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
+                    >
+                        <a-input
+                            v-decorator="[
+                                'packageName',
+                                {
+                                    rules: [{ required: true, message: '请填写正确的应用包名称' }]
+                                }
+                            ]"
+                            placeholder="请填写包名称,如com.smile.gifmaker"
+                        />
+                    </a-form-item>
+
+                    <a-form-item
+                        label="应用名称"
+                        :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
+                        :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
+                    >
+                        <a-input
+                            v-decorator="[
+                                'appName',
+                                {
+                                    rules: [{ required: true, message: '请填写应用名称' }]
+                                }
+                            ]"
+                            placeholder="请填写应用名称"
+                        />
+                    </a-form-item>
+
+                    <a-form-item
+                        label="上传图标"
+                        :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
+                        :wrapperCol="{ xs: { span: 24 }, sm: { span: 19 } }"
+                        v-if="application"
+                        class="require-class"
+                    >
+                        <uploadFile
+                            v-if="application"
+                            :value.sync="fileUrl"
+                            :multiple="false"
+                            :fileCount="1"
+                            uploadType="image"
+                            @overUpload="overUpload"
+                            :size="100"
+                        ></uploadFile>
+                        <p class="upload-txt-rules">文件格式:支持上传png/jpg/jpeg图片,尺寸450*450,小于100kb</p>
+                    </a-form-item>
+                    <a-form-item
+                        label="应用标记"
+                        :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
+                        :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
+                    >
+                        <a-input
+                            v-decorator="[
+                                'appVersion',
+                                {
+                                    rules: [{ required: true, message: '应用标记必填' }]
+                                }
+                            ]"
+                            placeholder="请填写应用标记,必填且不可重复,如快手-5.6.1.66"
+                            id="appVersion"
+                        />
+                        <a-tag
+                            color="#2db7f5"
+                            @click="getChangeAll('渠道号', 'form', 'appVersion')"
+                            v-if="createTypeData && createTypeData.createType == '1'"
+                            >+渠道号</a-tag
+                        >
+                    </a-form-item>
+                    <a-form-item
+                        label="隐私政策链接"
+                        :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
+                        :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
+                    >
+                        <a-input
+                            v-decorator="[
+                                'appPrivacyUrl',
+                                {
+                                    rules: [
+                                        { required: true, message: '请填写隐私政策链接' },
+                                        { validator: handleConfirmValue }
+                                    ]
+                                }
+                            ]"
+                            placeholder="请填写隐私政策链接"
+                        />
+                    </a-form-item>
+                </a-form>
+            </a-card>
+        </a-modal>
+    </div>
+</template>
+
+<script>
+import Vue from 'vue'
+import { ACCESS_TOKEN } from '@/store/mutation-types'
+import { deleteAction, postAction, getAction, downFilePost, downFile } from '@/api/manage'
+import uploadFile from './uploadFile.vue'
+import { mapActions, mapGetters } from 'vuex'
+import BMF from 'browser-md5-file'
+import selectTable from '@/views/modules/Statistics/components/selectPagination.vue'
+import $ from 'jquery'
+const fileSuffix = ['xlsx', 'xls', 'zip']
+export default {
+    name: 'BaseForm',
+    components: {
+        uploadFile,
+        selectTable
+    },
+    data() {
+        return {
+            useSdk: [],
+            loadDisabled: false,
+            projectId: '',
+            accountId: '',
+            fileList: [],
+            fileUrl: '',
+            accountList: {},
+            appType: 'android', //设备类型
+            platform: '1', //应用类型   : 1 Android 应用下载,2: Android 网页游戏,3: iOS 应用下载, 4:iOS 网页游戏
+            uploadType: '2', //上传类型 1 本地上传 2 填写链接
+            appVersion: '', //应用标记
+            appName: '', // 应用名称
+            packageName: '', //应用包名
+            file: '', // 上传文件
+            imageUrl: '', // 上传图标链接链接
+            downloadUrl: '', //下载链接
+            showUploadFile: true,
+            showDownLoad: false,
+            showUpload: true,
+            showAndroid: true,
+            showIOS: false,
+            customDomain: '',
+            acceptVideo: '/*.apk,/*.png,/*.jpg,/*.jpeg,/*.mp4',
+            accessKeyId: 'LTAIbNbqWzSOklQV',
+            accessKeySecret: '1rkPz7JNoXk8sJevPaeYHWqfkQXBGh',
+            region: 'oss-cn-beijing',
+            bucket: 'ctop-media',
+            form: this.$form.createForm(this),
+            url: {
+                insertTemplateUrl: '/kuaishouAppPackage/fillInLink',
+                userAllocationList: '/ctop/userAllocation/list'
+            },
+            application: false,
+            confirmLoading: false,
+            imageToken: '',
+            // uploadAction: '/kuaishouAppPackage/importAppExcel',
+            tokenHeader: { 'X-Access-Token': Vue.ls.get(ACCESS_TOKEN) },
+            okCreated: false,
+            dataFile: null,
+            createTypeData: null
+        }
+    },
+    methods: {
+        getChangeAll(type, form, field) {
+            var node = document.getElementById(field)
+            var v = ''
+            if (field == 'url') {
+                v = '{{' + type + '}}'
+            }else{
+                v = '-{{' + type + '}}-'
+            }
+            if (document.selection) {
+                //IE
+                node.focus()
+                var sel = document.selection.createRange()
+                sel.text = v
+                sel.select()
+                if (field == 'channelName') {
+                    this[form].setFieldsValue({ channelName: sel.text })
+                } else if (field == 'channelCode') {
+                    this[form].setFieldsValue({ channelCode: sel.text })
+                } else if (field == 'url') {
+                    this[form].setFieldsValue({ url: sel.text })
+                } else if (field == 'clickTrackUrl') {
+                    this[form].setFieldsValue({ clickTrackUrl: sel.text })
+                } else if (field == 'actionbarClickUrl') {
+                    this[form].setFieldsValue({ actionbarClickUrl: sel.text })
+                } else if (field == 'appVersion') {
+                    this[form].setFieldsValue({ appVersion: sel.text })
+                }
+            } else if (node.selectionStart || node.selectionStart == '0') {
+                //MOZILLA/GOOGLE
+                var startPos = node.selectionStart
+                var endPos = node.selectionEnd
+                var restoreTop = node.scrollTop
+                node.value = node.value.substring(0, startPos) + v + node.value.substring(endPos, node.value.length)
+                if (restoreTop > 0) {
+                    node.scrollTop = restoreTop
+                }
+                if (field == 'channelName') {
+                    this[form].setFieldsValue({ channelName: node.value })
+                } else if (field == 'channelCode') {
+                    this[form].setFieldsValue({ channelCode: node.value })
+                } else if (field == 'url') {
+                    this[form].setFieldsValue({ url: node.value })
+                } else if (field == 'clickTrackUrl') {
+                    this[form].setFieldsValue({ clickTrackUrl: node.value })
+                } else if (field == 'actionbarClickUrl') {
+                    this[form].setFieldsValue({ actionbarClickUrl: node.value })
+                } else if (field == 'appVersion') {
+                    this[form].setFieldsValue({ appVersion: node.value })
+                }
+                node.focus()
+                node.selectionStart = startPos + v.length
+                node.selectionEnd = startPos + v.length
+                // this.channelName = node.value
+            } else {
+                //OTHER
+                node.value += v
+                // console.log(node.value)
+                if (field == 'channelName') {
+                    this[form].setFieldsValue({ channelName: node.value })
+                } else if (field == 'channelCode') {
+                    this[form].setFieldsValue({ channelCode: node.value })
+                } else if (field == 'url') {
+                    this[form].setFieldsValue({ url: node.value })
+                } else if (field == 'clickTrackUrl') {
+                    this[form].setFieldsValue({ clickTrackUrl: node.value })
+                } else if (field == 'actionbarClickUrl') {
+                    this[form].setFieldsValue({ actionbarClickUrl: node.value })
+                } else if (field == 'appVersion') {
+                    this[form].setFieldsValue({ appVersion: node.value })
+                }
+
+                node.focus()
+                // this.channelName = node.value
+            }
+        },
+        overUpload(file) {},
+        downLoadFile() {
+            downFile('/kuaishouAppPackage/exportAppTemplate').then(res => {
+                let blob = new Blob([res], {
+                    type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
+                })
+                let downloadElement = document.createElement('a')
+                let href = window.URL.createObjectURL(blob) //创建下载的链接
+                downloadElement.href = href
+                downloadElement.download = '应用模板' //下载后文件名
+                document.body.appendChild(downloadElement)
+                downloadElement.click() //点击下载
+                document.body.removeChild(downloadElement) //下载完成移除元素
+                window.URL.revokeObjectURL(href) //释放掉blob对象
+            })
+        },
+        handleChange(info) {
+            this.loadDisabled = false
+            this.$message.success('文件导入成功')
+        },
+        beforeUpload(file) {
+            this.dataFile = $('.fileUpload')
+                .eq(0)
+                .find('input')[0].files[0]
+            this.loadDisabled = true
+            const size = (Number(file.size) / (1024 * 1024)).toFixed(2)
+            const fileName = file.name
+            const fileStrArr = fileName.split('.')
+            const suffix = fileStrArr[fileStrArr.length - 1]
+
+            let result = fileSuffix.some(item => {
+                return item === suffix
+            })
+
+            if (!result) {
+                this.$message.error('不支持该文件类型')
+                this.loadDisabled = false
+                return false
+            }
+        },
+        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.appType +
+                        '/' +
+                        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)
+                }
+            )
+        },
+        handleMd5(file) {
+            let bmf = new BMF()
+            let that = this
+            return new Promise(function(resolve, reject) {
+                bmf.md5(file, (err, md5) => {
+                    // getAction('kuaishouPopulationPackage/checkPopulationPackage', { signature: md5 })
+                    //   .then((result) => {
+                    //     if (result.code === 200) {
+                    that.personNameDisabled = false
+                    that.personResourceDisabled = false
+                    resolve()
+                })
+            })
+        },
+        handleOk() {
+            this.handleSubmit()
+        },
+        handleCancel() {
+            this.dataFile = null
+            this.appType = 'android'
+            this.okCreated = false
+            this.form.resetFields()
+            this.fileUrl = ''
+            this.file = ''
+            this.platform = '1'
+            this.application = false
+        },
+        showApplication() {
+            this.application = true
+        },
+        handleConfirmValue(rule, value, callback) {
+            if (/(http|https):\/\/([\w.]+\/?)\S*/.test(value) && value != '') {
+                callback()
+            } else {
+                callback('链接不能为空且开头为http://或https://')
+            }
+        },
+        ...mapGetters(['nickname', 'avatar', 'userInfo']),
+        changePlatform() {
+            this.form.resetFields()
+            if (this.appType == 'android') {
+                this.showAndroid = true
+                this.showIOS = false
+                this.platform = '1'
+            } else {
+                this.showAndroid = false
+                this.showIOS = true
+                this.showDownLoad = true
+                this.platform = '1'
+            }
+        },
+        changeShowUpload() {
+            this.form.resetFields()
+            this.fileUrl = ''
+        },
+        changeShowUploadType() {
+            this.form.resetFields()
+            if (this.platform == '2') {
+                this.showUpload = false
+                this.showUploadFile = false
+                this.showDownLoad = true
+                this.uploadType = '1'
+            } else {
+                this.showUpload = true
+                this.showUploadFile = true
+                this.showDownLoad = false
+            }
+        },
+
+        handleSubmit() {
+            //   console.log('设备类型:' + this.appType)
+            //   console.log('应用类型:' + this.platform)
+            //   console.log('上传类型:' + this.uploadType)
+            //   console.log('应用标记:' + this.appVersion)
+            //   console.log('应用名称:' + this.appName)
+            //   console.log('包名称:' + this.packageName)
+            //   console.log('文件地址:' + this.file)
+            //   console.log('图片地址:' + this.imageUrl)
+            //   e.preventDefault()
+
+            this.form.validateFields((err, values) => {
+                if (!err) {
+                    if (this.fileUrl) {
+                        this.confirmLoading = true
+                        let params = {}
+                        var reg = RegExp(/{{渠道号}}/)
+                        if(reg.test(values.url)&&reg.test(values.appVersion)){
+                            this.url.insertTemplateUrl = '/kuaishouAppPackage/fillInLink'
+                            params = { ...values }
+                            params.appIconUrl = this.fileUrl
+                            this.confirmLoading = false
+                            this.$emit('getDataList', params)
+                            this.handleCancel()
+                        }else if(!reg.test(values.url)&&!reg.test(values.appVersion)){
+                            this.url.insertTemplateUrl = '/kuaishouAppPackage/fillInLink'
+                            params = { ...values }
+                            params.appIconUrl = this.fileUrl
+                            this.confirmLoading = false
+                            this.$emit('getDataList', params)
+                            this.handleCancel()
+                        }else{
+                            this.confirmLoading = false
+                            this.$message.error('下载链接必须和应用标记的通配符保持一致')
+                        }
+
+                        // postAction(this.url.insertTemplateUrl, params).then(res => {
+                        //     this.confirmLoading = false
+                        //     if (res.success) {
+                        //         this.$message.success('创建成功')
+                        //         this.handleCancel()
+                        //         this.$emit('getDataList')
+                        //     } else {
+                        //         this.$message.error(res.message)
+                        //     }
+                        // })
+                    } else {
+                        this.confirmLoading = false
+                        this.$message.error('请填写必填项')
+                    }
+                }
+            })
+        },
+
+        onChange(value) {}
+    },
+    created: function() {
+        this.createTypeData = JSON.parse(localStorage.getItem('createTypeData'))
+        let params = {}
+        params.pageSize = '1000'
+        params.mediaId = '2'
+        params.userId = this.userInfo().id
+        getAction(this.url.userAllocationList, params).then(res => {
+            if (res.success) {
+                this.accountList = res.result.records
+            }
+        })
+    }
+}
+</script>

+ 244 - 0
src/views/modules/autoLaunch/channelManage/components/treeSelectAccount.vue

@@ -0,0 +1,244 @@
+<style lang="scss" scoped>
+.select-project {
+    width: 50%;
+}
+</style>
+<template>
+    <div class="select-project">
+        <treeselect
+            :multiple="multiple"
+            :disable-branch-nodes="!multiple"
+            :disable-fuzzy-matching="true"
+            :options="options"
+            :load-options="loadOptions"
+            placeholder="请选择项目以及账户"
+            v-model="selectedVal"
+            :value-consists-of="valueConsistsOf"
+            :auto-load-root-options="false"
+            @select="update"
+            @input="emitValue"
+            :limit="limit"
+            :default-options="true"
+            :disabled="disabled"
+            :limitText="
+                count => {
+                    return '隐藏' + count + '条'
+                }
+            "
+            noChildrenText="该项目下暂无账号"
+            :noOptionsText="showLoading"
+        />
+    </div>
+</template>
+
+<script>
+//   @open="getParticipateList"
+// import the component
+import Treeselect from '@riophae/vue-treeselect'
+// import the styles
+import '@riophae/vue-treeselect/dist/vue-treeselect.css'
+import { LOAD_CHILDREN_OPTIONS } from '@riophae/vue-treeselect'
+
+import { getAction, postAction } from '@/api/manage'
+import { mapGetters } from 'vuex'
+// We just use `setTimeout()` here to simulate an async operation
+// instead of requesting a real API server for demo purpose.
+let called = false
+export default {
+    data: () => ({
+        value: null,
+        valueConsistsOf: 'LEAF_PRIORITY',
+        options: [],
+        showLoading: 'loading...'
+    }),
+    props: {
+        oneData: {
+            type: Boolean,
+            default() {
+                return false
+            }
+        },
+        //是否多选
+        multiple: {
+            type: Boolean,
+            default() {
+                return false
+            }
+        },
+        appId: {
+            default() {
+                return ''
+            }
+        },
+        //判断媒体类型
+        request: {
+            type: String,
+            default() {
+                return '2,4'
+            }
+        },
+        //一级请求接口
+        reqUrl: {
+            type: String,
+            default() {
+                return '/ctop/projectMember/getProductProjectAndAccountList'
+            }
+        },
+        // 展示条数
+        limit: {
+            type: Number,
+            default() {
+                return 2
+            }
+        },
+        disabled: {
+            type: Boolean,
+            default() {
+                return false
+            }
+        }
+    },
+    components: {
+        Treeselect
+    },
+    computed: {
+        selectedVal: {
+            get: function() {
+                return this.value
+            },
+            set: function(val) {
+                console.log(val)
+                this.$emit('input', val)
+                this.$emit('change', val)
+            }
+        }
+    },
+    watch: {
+        $route(n, o) {}
+        // appId: {
+        //     handler(n, o) {
+        //         console.log(n)
+        //         if (n.length == 0) {
+        //             if (this.multiple) {
+        //                 this.value = []
+        //             } else {
+        //                 this.value = undefined
+        //             }
+        //         } else {
+        //             this.value = this.appId
+        //         }
+        //     },
+        //     deep: true,
+        //     immediate: true
+        // }
+    },
+    methods: {
+        ...mapGetters(['nickname', 'avatar', 'userInfo']),
+        update(node, id) {
+            this.$emit('select-value', node)
+            // getAction('/ctop/userAllocation/getAccountListByProjectId', {
+            //   projectId: node.id,
+            // }).then((res) => {
+            //   // console.log(res)
+            //   if (res.code == 0) {
+            //     if (res.result.length > 0) {
+            //       node.children = res.result.map((item) => {
+            //         return {
+            //           id: item.accountId,
+            //           label: item.userName + '         ' + item.authName,
+            //         }
+            //       })
+            //     } else {
+            //     }
+            //   } else {
+            //     new Error('Failed to load options: network error.')
+            //   }
+            // })
+        },
+        emitValue() {
+            this.$emit('update:appId', this.value)
+        },
+        loadOptions({ action, parentNode, callback }) {
+            // Typically, do the AJAX stuff here.
+            // Once the server has responded,
+            // assign children options to the parent node & call the callback.
+            if (action === LOAD_CHILDREN_OPTIONS) {
+                // getAction('/ctop/userAllocation/getAccountListByProjectId', {
+                //   projectId: parentNode.id,
+                // }).then((res) => {
+                //   if (res.code == 0) {
+                //     if (res.result.length > 0) {
+                //       parentNode.children = res.result.map((item) => {
+                //         return {
+                //           id: item.accountId,
+                //           label: item.userName + '\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0' + item.authName,
+                //         }
+                //       })
+                //       callback()
+                //     } else {
+                //       parentNode.children = []
+                //       callback()
+                //     }
+                //   } else {
+                //     callback(new Error('Failed to load options: network error.'))
+                //   }
+                // })
+            }
+        },
+        getParticipateList() {
+            //我参与的
+            //   toutiaoParticipateList
+            var params = {}
+            params.userId = this.userInfo().id
+            postAction(this.reqUrl, params).then(res => {
+                if (res.success) {
+                    console.log(res)
+                    this.options = res.result.map(item => {
+                        return {
+                            id: item.productId + 'productId',
+                            label: item.productName,
+                            children: item.projectList
+                                ? item.projectList.map(i => {
+                                      return {
+                                          id: i.projectId,
+                                          label: i.projectName,
+                                          children: i.accountList
+                                              ? i.accountList.map(c => {
+                                                    return {
+                                                        id: c.accountId,
+                                                        label:
+                                                            (c.userName && c.userName.length == 2
+                                                                ? c.userName + '\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0'
+                                                                : c.userName && c.userName.length == 3
+                                                                ? c.userName + '\xa0\xa0\xa0\xa0'
+                                                                : c.userName) +
+                                                            '\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0' +
+                                                            c.accountId +
+                                                            '\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0' +
+                                                            c.authName
+                                                    }
+                                                })
+                                              : []
+                                      }
+                                  })
+                                : []
+                        }
+                    })
+                    if (this.oneData && !this.multiple) {
+                        var data = this.options.filter(item => {
+                            if (item.children && item.children.length > 0) {
+                                return { ...item }
+                            }
+                        })
+                        this.$emit('update:appId', data[0].children[0].id)
+                    }
+                }
+            })
+        }
+    },
+
+    mounted() {
+        this.getParticipateList()
+    }
+}
+</script>

+ 228 - 0
src/views/modules/autoLaunch/channelManage/components/treeSelectProject.vue

@@ -0,0 +1,228 @@
+<style lang="scss" scoped>
+.select-project {
+    width: 50%;
+}
+</style>
+<template>
+    <div class="select-project">
+        <treeselect
+            :multiple="multiple"
+            :disable-branch-nodes="!multiple"
+            :disable-fuzzy-matching="true"
+            :options="options"
+            :load-options="loadOptions"
+            placeholder="请选择项目以及账户"
+            v-model="selectedVal"
+            :value-consists-of="valueConsistsOf"
+            :auto-load-root-options="false"
+            @select="update"
+            @input="emitValue"
+            :limit="limit"
+            :default-options="true"
+            :disabled="disabled"
+            :limitText="
+                count => {
+                    return '隐藏' + count + '条'
+                }
+            "
+            noChildrenText="该项目下暂无账号"
+            :noOptionsText="showLoading"
+        />
+    </div>
+</template>
+
+<script>
+//   @open="getParticipateList"
+// import the component
+import Treeselect from '@riophae/vue-treeselect'
+// import the styles
+import '@riophae/vue-treeselect/dist/vue-treeselect.css'
+import { LOAD_CHILDREN_OPTIONS } from '@riophae/vue-treeselect'
+
+import { getAction, postAction } from '@/api/manage'
+import { mapGetters } from 'vuex'
+// We just use `setTimeout()` here to simulate an async operation
+// instead of requesting a real API server for demo purpose.
+let called = false
+export default {
+    data: () => ({
+        value: null,
+        valueConsistsOf: 'LEAF_PRIORITY',
+        options: [],
+        showLoading: 'loading...'
+    }),
+    props: {
+        oneData: {
+            type: Boolean,
+            default() {
+                return false
+            }
+        },
+        //是否多选
+        multiple: {
+            type: Boolean,
+            default() {
+                return false
+            }
+        },
+        appId: {
+            type: [Number, Array, String],
+            default() {
+                return ""
+            }
+        },
+        //判断媒体类型
+        request: {
+            type: String,
+            default() {
+                return '2,4'
+            }
+        },
+        //一级请求接口
+        reqUrl: {
+            type: String,
+            default() {
+                return '/ctop/projectMember/getProductProjectList'
+            }
+        },
+        // 展示条数
+        limit: {
+            type: Number,
+            default() {
+                return 2
+            }
+        },
+        disabled: {
+            type: Boolean,
+            default() {
+                return false
+            }
+        }
+    },
+    components: {
+        Treeselect
+    },
+    computed: {
+        selectedVal: {
+            get: function() {
+                return this.value
+            },
+            set: function(val) {
+                console.log(val)
+                this.$emit('input', val)
+                this.$emit('change', val)
+            }
+        }
+    },
+    watch: {
+        $route(n, o) {},
+        // appId: {
+        //     handler(n, o) {
+        //         console.log(n)
+        //         if (n.length == 0) {
+        //             if (this.multiple) {
+        //                 this.value = []
+        //             } else {
+        //                 this.value = undefined
+        //             }
+        //         } else {
+        //             this.value = this.appId
+        //         }
+        //     },
+        //     deep: true,
+        //     immediate: true
+        // }
+    },
+    methods: {
+        ...mapGetters(['nickname', 'avatar', 'userInfo']),
+        update(node, id) {
+            this.$emit('select-value', node)
+            // getAction('/ctop/userAllocation/getAccountListByProjectId', {
+            //   projectId: node.id,
+            // }).then((res) => {
+            //   // console.log(res)
+            //   if (res.code == 0) {
+            //     if (res.result.length > 0) {
+            //       node.children = res.result.map((item) => {
+            //         return {
+            //           id: item.accountId,
+            //           label: item.userName + '         ' + item.authName,
+            //         }
+            //       })
+            //     } else {
+            //     }
+            //   } else {
+            //     new Error('Failed to load options: network error.')
+            //   }
+            // })
+        },
+        emitValue() {
+            // this.$emit('update:appId', this.value)
+        },
+        loadOptions({ action, parentNode, callback }) {
+            // Typically, do the AJAX stuff here.
+            // Once the server has responded,
+            // assign children options to the parent node & call the callback.
+            if (action === LOAD_CHILDREN_OPTIONS) {
+                // getAction('/ctop/userAllocation/getAccountListByProjectId', {
+                //   projectId: parentNode.id,
+                // }).then((res) => {
+                //   if (res.code == 0) {
+                //     if (res.result.length > 0) {
+                //       parentNode.children = res.result.map((item) => {
+                //         return {
+                //           id: item.accountId,
+                //           label: item.userName + '\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0' + item.authName,
+                //         }
+                //       })
+                //       callback()
+                //     } else {
+                //       parentNode.children = []
+                //       callback()
+                //     }
+                //   } else {
+                //     callback(new Error('Failed to load options: network error.'))
+                //   }
+                // })
+            }
+        },
+        getParticipateList() {
+            //我参与的
+            //   toutiaoParticipateList
+            var params = {}
+            params.userId = this.userInfo().id
+            postAction(this.reqUrl, params).then(res => {
+                if (res.success) {
+                    console.log(res)
+                    this.options = res.result.map(item => {
+                        return {
+                            id: item.productId + 'productId',
+                            label: item.productName,
+                            children: item.projectList
+                                ? item.projectList.map(i => {
+                                      return {
+                                          id: i.projectId,
+                                          label: i.projectName
+                                      }
+                                  })
+                                : []
+                        }
+                    })
+                    if (this.oneData && !this.multiple) {
+                        var data = this.options.filter(item => {
+                            if (item.children && item.children.length > 0) {
+                                return { ...item }
+                            }
+                        })
+                        this.$emit('update:appId', data[0].children[0].id)
+                    }
+                }
+            })
+        }
+    },
+
+    mounted() {
+        this.getParticipateList()
+    }
+}
+</script>

+ 365 - 0
src/views/modules/autoLaunch/channelManage/components/uploadFile.vue

@@ -0,0 +1,365 @@
+<style>
+</style>
+<style lang="scss" scoped>
+</style>
+<template>
+  <div class="upload-file">
+    <a-upload
+      name="file"
+      :multiple="multiple"
+      list-type="picture-card"
+      class="avatar-uploader"
+      action="https://media-1301855440.cos.ap-chongqing.myqcloud.com/"
+      :before-upload="beforeUpload"
+      @change="handleChange"
+      :accept="uploadType + '/' + (uploadType == 'image' ? 'jpeg,image/*' : 'mp4')"
+      :file-list="fileList"
+      :remove="removeFile"
+      @preview="handlePreview"
+      :disabled="loadingElse || disabled"
+    >
+      <div v-if="fileList.length < fileCount || fileList.length < 1">
+        <a-progress v-if="loadingElse" :percent="percent" :show-info="false" />
+        <div class="ant-upload-text">点击上传</div>
+      </div>
+    </a-upload>
+    <!-- <div style="color: red" v-if="sizeCheck">
+      {{ uploadType == 'image' ? '请上传jpg格式的图片,并且大小在2m之内' : '请上传mp4格式,大小在'+(size/1024)+'m之内' }}
+    </div> -->
+    <a-modal :visible="previewVisible" :footer="null" @cancel="handleCancel">
+      <img alt="example" style="width: 100%" :src="previewImage" v-if="uploadType == 'image'" />
+      <video :src="previewImage" v-else style="width: 100%" controls="controls">您的浏览器不支持 video 标签。</video>
+    </a-modal>
+  </div>
+</template>
+
+<script>
+import { stopOtherVideo, closeAllVideoFun } from '@/utils/videoControl' // 停止除当前外的其他视频播放,及停止所有视频播放的方法
+import { mapGetters } from 'vuex'
+import moment from 'moment'
+
+import BMF from 'browser-md5-file'
+
+import qs from 'qs'
+var COS = require('cos-js-sdk-v5')
+var cos = new COS({
+  SecretId: 'AKIDE6IpMi8fJQRCg1iuWzFajjRs43kbbets',
+  SecretKey: 'tXzuwMfplTTK3c9GFUyETilasvQfePu9',
+})
+var i = 0
+const oneKB = 1024
+
+function getBase64(file) {
+  return new Promise((resolve, reject) => {
+    const reader = new FileReader()
+    reader.readAsDataURL(file)
+    reader.onload = () => resolve(reader.result)
+    reader.onerror = (error) => reject(error)
+  })
+}
+export default {
+  name: 'upload-file',
+  components: {},
+  props: {
+    uploadType: {
+      //上传类型  值为  image/video,同时目录名称也是这样
+      type: String,
+      default() {
+        return 'image'
+      },
+    },
+    multiple: {
+      // true 可以批量上传  false 不可以
+      type: Boolean,
+      default() {
+        return true
+      },
+    },
+    fileCount: {
+      //最大上传数量
+      type: Number,
+      default() {
+        return 10
+      },
+    },
+    checkFile: {
+      //返回promise方法,判读文件是否上传过,进行上传拦截
+      type: Function,
+      default() {
+        return Promise.resolve()
+      },
+    },
+    disabled: {
+      type: Boolean,
+      default() {
+        return false
+      },
+    },
+    value: {
+      required: true,
+      default() {
+        return ''
+      },
+    },
+    size: {
+      type: Number,
+      default() {
+        if (this.sizeCheck) {
+          if (this.uploadType == 'image') {
+            return 2048
+          } else {
+            return 102400
+          }
+        }
+      },
+    },
+    sizeCheck: {
+      type: Boolean,
+      default() {
+        return true
+      },
+    },
+    onOversize: {
+      type: Function,
+      default() {
+        alert(`请选择${this.size}KB内的文件!`)
+      },
+    },
+  },
+  data() {
+    return {
+      fileList: [],
+      loadingElse: false,
+      imageUrl: '',
+      percent: 0,
+      previewVisible: false,
+      previewImage: '',
+    }
+  },
+  filters: {},
+  computed: {},
+  mounted() {},
+  watch: {
+    //    fileListAll
+    value: {
+      immediate: true,
+      handler(n, o) {
+        this.$nextTick(() => {
+          if (this.fileList && this.fileList.length == 0) {
+            if (typeof n == 'object') {
+              this.fileList = n.map((item, index) => {
+                return {
+                  uid: index + 1,
+                  name: index + 1,
+                  status: 'done',
+                  url: item,
+                }
+              })
+            } else {
+              if (n === '') {
+                this.fileList = []
+              } else {
+                this.fileList = []
+                var data = {
+                  uid: 1,
+                  name: '回显',
+                  status: 'done',
+                  url: n,
+                }
+                this.fileList.push(data)
+              }
+            }
+          } else {
+            if (n.length == 0 || n == '') {
+              this.clearAll()
+            }
+          }
+        })
+      },
+      deep: true,
+    },
+  },
+  methods: {
+    handleCancel() {
+      closeAllVideoFun()
+      this.previewVisible = false
+    },
+    handleChange(info) {
+      if (info.file.status === 'uploading') {
+        this.loading = true
+        return
+      }
+      if (info.file.status === 'done') {
+        // Get this url from response in real world.
+        getBase64(info.file.originFileObj, (imageUrl) => {
+          this.imageUrl = imageUrl
+          this.loading = false
+        })
+      }
+    },
+    removeFile(file) {
+      // console.log(file)
+      var index = this.fileList.findIndex((v) => v.uid === file.uid)
+      this.fileList.splice(index, 1)
+      this.$emit('removeUpload', file)
+    },
+    async handlePreview(file) {
+      if (!file.url && !file.preview) {
+        file.preview = await getBase64(file.originFileObj)
+      }
+      this.previewImage = file.url || file.preview
+      this.previewVisible = true
+    },
+    beforeUpload(file) {
+      this.percent = 0
+      this.loadingElse = true
+      const fileOvesize = file.size > this.size * oneKB
+      console.log(file)
+      var image = new Image()
+      var reader = new FileReader()
+      var height = 0
+      var width = 0
+      reader.readAsDataURL(file)
+      //文件读取结束时间
+      reader.onload = function (e) {
+        image.src = reader.result
+      }
+      var that = this
+      //图片读取事件
+      image.onload = function () {
+        height = image.naturalHeight
+        width = image.naturalWidth
+      }
+      if (image.complete) {
+        height = image.naturalHeight
+        width = image.naturalWidth
+      }
+
+      setTimeout(() => {
+        if (height != 450 || width != 450) {
+          that.$message.error('请上传450*450大小的图片')
+          this.loadingElse = false
+          return
+        }
+        // console.log(fileOvesize)
+        if (fileOvesize && this.sizeCheck) {
+          this.onOversize()
+          this.loadingElse = false
+          return
+        } else {
+          if (file.type.includes('jpg') || file.type.includes('png') || file.type.includes('jpeg')) {
+            this.checkFile(file)
+              .then((res) => {
+                this.cosUpload(file)
+              })
+              .catch(() => {
+                this.loadingElse = false
+              })
+          } else {
+            this.$message.error('请上传正确格式')
+            this.loadingElse = false
+          }
+
+          return new Promise(function (resolve, reject) {
+            reject()
+          })
+        }
+      }, 200)
+    },
+    clearAll() {
+      this.fileList = []
+    },
+    cosUpload(file) {
+      var 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
+      var timeElse = new Date().getTime()
+      var arr = file.name.split('.')
+
+      var 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] + '.'
+          }
+        }
+      }
+      // console.log(str + '-' + timeElse + '.' + arr[arr.length - 1])
+      cos.putObject(
+        {
+          Bucket: 'media-1301855440',
+          /* 必须 */
+          Region: 'ap-chongqing',
+          /* 存储桶所在地域,必须字段 */
+          Key: that.uploadType + '/' + y + '-' + MM + '-' + d + '/' + str + '-' + timeElse + '.' + arr[arr.length - 1],
+          /* 必须 */
+          StorageClass: 'STANDARD',
+          Body: file, // 上传文件对象
+          onProgress: function (progressData) {
+            //进度条方法
+
+            that.percent = progressData.percent * 100
+          },
+          onTaskReady: function (tid) {
+            // console.log('onTaskReady', tid);
+          },
+          onTaskStart: function (info) {
+            //开始上传
+            // console.log('onTaskStart', info);
+          },
+        },
+        function (err, data) {
+          if (err) {
+            that.loadingElse = false
+            that.$message.error('上传失败!!!' + err)
+            return
+          }
+          // alert('成功')
+          that.loadingElse = false
+          if (that.fileList.length < that.fileCount) {
+            that.fileList.push({
+              uid: file.name,
+              name: file.name,
+              status: 'done',
+              url: '//' + data.Location,
+            })
+
+            // that.$emit('overUpload', that.fileList.map(item => {
+            //                 return item.url
+            //               }))
+            that.$emit('overUpload', that.fileList)
+
+            if (that.multiple) {
+              that.$emit(
+                'update:value',
+                that.fileList.map((item) => {
+                  return item.url
+                })
+              )
+            } else {
+              that.$emit(
+                'update:value',
+                that.fileList.map((item) => {
+                  return item.url
+                })[0]
+              )
+            }
+          } else {
+            that.$message.error('上传已达上限' + that.fileCount + '张')
+          }
+        }
+      )
+    },
+  },
+}
+</script>
+<style scoped>
+@import '~@assets/less/common.less';
+</style>

Diferenças do arquivo suprimidas por serem muito extensas
+ 1031 - 0
src/views/modules/autoLaunch/channelManage/createChannel.vue


Diferenças do arquivo suprimidas por serem muito extensas
+ 327 - 837
src/views/modules/autoLaunch/channelManage/index.vue


+ 951 - 0
src/views/modules/autoLaunch/channelManage/itemList.vue

@@ -0,0 +1,951 @@
+<style lang="scss" scoped>
+/deep/.vue-treeselect__control {
+    line-height: 36px !important;
+}
+/deep/ .ant-collapse-item,
+/deep/.ant-collapse-content {
+    overflow: inherit !important;
+}
+.search-bar {
+    display: flex;
+    align-items: center;
+}
+.search-box p {
+    display: inline-block;
+    border: 1px solid #f2f2f2;
+    border-radius: 5px;
+    margin-right: 10px;
+    padding: 5px 10px;
+    cursor: pointer;
+}
+</style>
+<style scoped>
+.showNumBox {
+    margin: 10px 0;
+}
+.showNumBox .ant-card-body {
+    display: flex;
+    justify-content: center;
+}
+.showNumBox p,
+.showNumBox span {
+    text-align: center;
+    line-height: 40px;
+    font-size: 30px;
+    font-weight: 600;
+    color: red;
+    margin: 0;
+}
+.search-box .ant-card-body {
+    padding: 5px 15px;
+}
+.showNumBox .ant-card-body .styleElse {
+    line-height: 60px;
+    height: 40px;
+    font-size: 16px;
+    font-weight: 400;
+    margin-left: 10px;
+}
+.ant-modal-wrap .yincang .ant-modal-content .ant-modal-footer {
+    display: none !important;
+}
+.yincang .ant-col-6 p {
+    text-align: left;
+    color: red;
+    font-size: 16px;
+    font-weight: 500;
+}
+.ant-table-thead div {
+    font-weight: 700;
+}
+.tool-tip {
+    position: absolute;
+    top: 65px;
+    right: 10px;
+}
+</style>
+<style lang="less" scoped>
+.ant-card-head .ant-tabs-bar {
+    padding: 0;
+}
+.search-box .ant-card-body {
+    padding: 5px 15px;
+}
+.search-box {
+    padding: 15px 10px;
+}
+.search-box p {
+    display: inline-block;
+    border: 1px solid #f2f2f2;
+    border-radius: 5px;
+    margin-right: 10px;
+    padding: 5px 10px;
+    cursor: pointer;
+}
+.statistics .ant-col-6 .ant-card-body .styleElse {
+    line-height: 60px;
+    height: 40px;
+    font-size: 16px;
+    font-weight: 400;
+    margin-left: 10px;
+}
+.ant-modal-wrap .yincang .ant-modal-content .ant-modal-footer {
+    display: none !important;
+}
+.yincang .ant-col-6 p {
+    text-align: left;
+    color: red;
+    font-size: 16px;
+    font-weight: 500;
+}
+.ant-table-thead div {
+    font-weight: 700;
+}
+.tool-tip {
+    position: absolute;
+    top: 65px;
+    right: 10px;
+}
+.statistics {
+    .ant-card-bordered {
+        border: none;
+    }
+    .ant-card-head .ant-tabs {
+        clear: both;
+        margin-bottom: -13px;
+        color: rgba(0, 0, 0, 0.65);
+        font-weight: normal;
+        font-size: 14px;
+    }
+    .duibi {
+        position: absolute;
+        right: 24px;
+        top: 15px;
+    }
+    p {
+        margin-bottom: 0;
+    }
+}
+</style>
+
+<style lang="less" scoped>
+@import 'channelManage';
+</style>
+<template>
+    <div class="channelManage config-project">
+        <a-card>
+            <div class="table-page-search-wrapper">
+                <a-form layout="inline" :form="form" hide-required-mark :selfUpdate="true" @submit="handleQueryList">
+                    <a-row :gutter="24">
+                        <!-- <a-col :md="8" :sm="8" :xxl="6">
+                            <selectTable :projectId.sync="productId" ref="selectTable"></selectTable>
+                        </a-col> -->
+
+                        <a-col :md="8" :sm="8" :xxl="6">
+                            <selectTableProject
+                                :projectId.sync="projectId"
+                                :productId="productId"
+                                ref="selectTableProject"
+                            ></selectTableProject>
+                        </a-col>
+                        <!--  -->
+                        <a-col :md="8" :sm="8" :xxl="6">
+                            <a-form-item label="素材关键字">
+                                <a-input placeholder="请输入素材关键字" v-decorator="['keyword']"></a-input>
+                            </a-form-item>
+                        </a-col>
+                        <a-col :md="8" :sm="8" :xxl="6">
+                            <a-form-item label="单品名称">
+                                <a-input placeholder="请输入单品名称" v-decorator="['itemName']"></a-input>
+                            </a-form-item>
+                        </a-col>
+                        <a-col :md="8" :sm="8" :xxl="6">
+                            <span style="float: left; overflow: hidden" class="table-page-search-submitButtons">
+                                <a-button type="primary" icon="search" @click="handleQueryList">查询</a-button>
+                                <a-button type="primary" @click="handleResetForm" icon="reload" class="middle-button"
+                                    >重置</a-button
+                                >
+                                <a-button type="primary" @click="visibleAddItem = true">添加单品</a-button>
+                                <a-button type="primary" @click="visibleDownLoad = true" class="middle-button"
+                                    >批量导入单品</a-button
+                                >
+                            </span>
+                        </a-col>
+                    </a-row>
+                </a-form>
+            </div>
+        </a-card>
+
+        <a-row style="margin-bottom:15px;margin-top:12px">
+            <a-col :span="24">
+                <div class="tableBody" style="min-height:200px;padding-bottom: 50px">
+                    <a-table
+                        :columns="columns"
+                        :dataSource="dataSource"
+                        :pagination="false"
+                        :loading="dataLoading"
+                        bordered
+                        @change="tableChange"
+                        size="middle"
+                        style="word-break: break-all;font-size:16px;font-weight:600"
+                        id="outTable"
+                        ref="accountTable"
+                    >
+                        <span slot="state" slot-scope="text, record">
+                            <a-switch :checked="text" @change="handleSwitchChang($event, record)" />
+                        </span>
+                        <span slot="action" slot-scope="text, record">
+                            <a-popover
+                                v-model="record.visible"
+                                trigger="click"
+                                placement="topLeft"
+                                @visibleChange="visibleChange"
+                            >
+                                <span slot="title">关键词</span>
+                                <template slot="content" style="width:300px;">
+                                    <div style="margin:5px">
+                                        <span
+                                            ><a-input
+                                                v-model="keyWord"
+                                                size="small"
+                                                style="margin-right:20px;width:120px"
+                                        /></span>
+                                    </div>
+
+                                    <div>
+                                        <a-button
+                                            type="default"
+                                            @click="bidChangeCancel(record)"
+                                            size="small"
+                                            style="margin-right:10px"
+                                            >取消</a-button
+                                        >
+                                        <a-button type="primary" @click="bidChangeOk(record)" size="small" class="ok"
+                                            >修改</a-button
+                                        >
+                                    </div>
+                                </template>
+                                <a
+                                    @click="
+                                        () => {
+                                            record.visible = true
+                                        }
+                                    "
+                                    >编辑素材关键词</a
+                                >
+                            </a-popover>
+                        </span>
+                    </a-table>
+                    <a-pagination
+                        size="small"
+                        :showTotal="ipagination.showTotal"
+                        style="float: right;margin-top:10px"
+                        v-if="dataSource.length > 0"
+                        showQuickJumper
+                        :pageSize.sync="ipagination.pageSize"
+                        :total="ipagination.total"
+                        v-model="ipagination.current"
+                        @change="getDataSource"
+                    />
+                </div>
+            </a-col>
+        </a-row>
+
+        <a-modal
+            title="下载模板"
+            :width="800"
+            ref="modal"
+            :visible="visibleDownLoad"
+            @ok="handleOkImport"
+            @cancel="
+                downLoading = false
+                visibleDownLoad = false
+                projectIdDownLoad = ''
+                cancel()
+            "
+            okText="提交"
+            :confirmLoading="downLoading"
+        >
+            <selectTableProject
+                :projectId.sync="projectIdDownLoad"
+                ref="selectTableProjectDownLoad"
+            ></selectTableProject>
+            <a-button type="primary" @click="handleOkDownLoad" style="margin-left:85px;margin-bottom:15px"
+                >导出单品模板</a-button
+            >
+            <a-form :form="formDownLoad">
+                <a-form-item
+                    label="上传文件"
+                    v-if="visibleDownLoad"
+                    :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
+                    :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
+                    class="require-class fileUpload"
+                    id="fileUpload"
+                >
+                    <a-upload
+                        name="file"
+                        :multiple="false"
+                        :headers="tokenHeader"
+                        :file-list="fileList"
+                        :showUploadList="false"
+                        :beforeUpload="beforeUpload"
+                        @change="handleChange"
+                        style="margin-right: 20px"
+                    >
+                        <a-button>
+                            <a-icon type="upload" />
+                            {{ loadDisabled ? '上传中,请稍后' : '文件上传' }}
+                        </a-button>
+                    </a-upload>
+                </a-form-item>
+            </a-form>
+        </a-modal>
+
+        <a-modal
+            title="添加单品"
+            :width="800"
+            ref="modal"
+            :visible="visibleAddItem"
+            @cancel="visibleAddItem = false"
+            @ok="handleOk"
+            :confirmLoading="confirmLoading"
+        >
+            <a-button type="primary" @click="addOneItem" style="margin-bottom:10px">添加单品信息</a-button>
+            <a-form-model ref="ruleForm" :model="addItemForm" v-bind="formItemLayout">
+                <a-collapse accordion v-model="activeKey" ref="collapse" v-if="visibleAddItem">
+                    <template v-for="(item, index) in addItemForm.items">
+                        <a-collapse-panel
+                            :forceRender="true"
+                            :header="item.itemName"
+                            style="background: #f9f9fa;border-radius: 4px;margin-bottom:15px;overflow: hidden;border: 1px solid #d9d9d9;"
+                        >
+                            <span slot="extra">
+                                <a-popconfirm :title="`确定删除吗?`" @confirm="deleteRule($event, item, index)">
+                                    <a-icon type="delete" @click="deleteIcon($event)" />
+                                </a-popconfirm>
+                            </span>
+                            <a-form-model-item
+                                label="项目"
+                                ref="projectId"
+                                :prop="'items.' + index + '.projectId'"
+                                :rules="[{ required: true, message: '请选择项目', trigger: 'change' }]"
+                            >
+                                <!-- <a-input v-model="item.projectId" placeholder="请输入规则名称" /> -->
+                                <Treeselect v-model="item.projectId" style="width:100%" />
+                            </a-form-model-item>
+                            <a-form-model-item
+                                label="素材关键字"
+                                ref="keyword"
+                                :prop="'items.' + index + '.keyword'"
+                                :rules="[
+                                    { required: true, message: '请填写素材关键字', trigger: 'blur' },
+                                    { min: 1, max: 15, message: '长度不得小于1,最大长度为15', trigger: 'blur' }
+                                ]"
+                            >
+                                <a-input v-model="item.keyword" placeholder="请输入素材关键字" />
+                            </a-form-model-item>
+                            <a-form-model-item
+                                label="单品名称"
+                                ref="itemName"
+                                :prop="'items.' + index + '.itemName'"
+                                :rules="[
+                                    { required: true, message: '请填写单品名称', trigger: 'blur' },
+                                    { min: 1, max: 10, message: '长度不得小于1,最大长度为10', trigger: 'blur' }
+                                ]"
+                            >
+                                <a-input v-model="item.itemName" placeholder="请输入单品名称" />
+                            </a-form-model-item>
+                        </a-collapse-panel>
+                    </template>
+                </a-collapse>
+            </a-form-model>
+        </a-modal>
+    </div>
+</template>
+
+<script>
+import ARow from 'ant-design-vue/es/grid/Row'
+import ACol from 'ant-design-vue/es/grid/Col'
+import moment from 'moment'
+import { getAction, postAction, downFile, downFilePost } from '@/api/manage'
+import selectTable from '@/views/modules/material/comment/selectTable.vue'
+import selectTableProject from '@/views/modules/Statistics/components/selectPagination.vue'
+import Treeselect from './components/treeSelectProject.vue'
+import qs from 'qs'
+import { mapGetters } from 'vuex'
+import uploadFile from './components/uploadFile.vue'
+import Vue from 'vue'
+import { ACCESS_TOKEN } from '@/store/mutation-types'
+import $ from 'jquery'
+const fileSuffix = ['xlsx', 'xls', 'zip']
+let TTcolumns = [
+    {
+        title: '开关',
+        dataIndex: 'state',
+        scopedSlots: { customRender: 'state' },
+        align: 'center',
+        key: 'state'
+    },
+    {
+        title: '项目名称',
+        dataIndex: 'project_name',
+        scopedSlots: { customRender: 'project_name' },
+        align: 'center',
+        key: 'project_name'
+    },
+
+    {
+        title: '单品名称',
+        dataIndex: 'item_name',
+        scopedSlots: { customRender: 'item_name' },
+        align: 'center',
+        key: 'item_name'
+    },
+    {
+        title: '素材关键字',
+        dataIndex: 'keyword',
+        scopedSlots: { customRender: 'keyword' },
+        align: 'center',
+        key: 'keyword'
+    },
+    {
+        title: '操作',
+        dataIndex: 'action',
+        scopedSlots: { customRender: 'action' },
+        align: 'center',
+        key: 'action'
+    }
+]
+
+export default {
+    components: {
+        ACol,
+        ARow,
+        selectTable,
+        selectTableProject,
+        uploadFile,
+        Treeselect
+    },
+
+    data() {
+        return {
+            visibleAddItem: false,
+            confirmLoading: false,
+            activeKey: '0',
+            addItemForm: {
+                items: [{ projectId: '', keyWord: '', itemName: '默认名称-单品1' }]
+            },
+            formItemLayout: {
+                labelCol: { span: 4 },
+                wrapperCol: { span: 20 }
+            },
+            tokenHeader: { 'X-Access-Token': Vue.ls.get(ACCESS_TOKEN) },
+            fileList: [],
+            dataFile: null,
+            loadDisabled: false,
+            productId: '',
+            projectId: '',
+            accountId: '',
+            visibleChannel: false,
+            visibleDownLoad: false,
+            downLoading: false,
+            fileUrl: '',
+            projectIdDownLoad: '',
+            channelType: 'a',
+            createType: 1,
+            indexAll: 0,
+            spinning: false,
+            form: this.$form.createForm(this),
+            formDownLoad: this.$form.createForm(this),
+            exportloading: false,
+            dateRange: [moment().subtract(1, 'weeks'), moment()],
+            noImg: require('@/assets/noImg.png'),
+            validationRules: {
+                bid: [
+                    {
+                        required: true,
+                        message: '出价信息必须填写'
+                        // validator: this.validateBid,
+                    }
+                ]
+            },
+            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
+                }
+            },
+            value: 'valid',
+            KSaccountList: [],
+            TTaccountList: [],
+
+            KSdesignList: [],
+            TTdesignList: [],
+
+            operateDisabled: false,
+            duration: 1000,
+            //treeselect的参数
+            treeValue: [],
+            treeData: [],
+
+            type: 3,
+
+            operate: '',
+            designList: [],
+
+            tabKey: 1,
+
+            loading: false,
+            columns: [...TTcolumns],
+            dataSource: [],
+
+            tableTab: 1,
+
+            newPlan: 0,
+            effectPlan: 0,
+
+            openOptions: false,
+
+            target: 'createTime',
+            order: 'descend',
+            dataLoading: false,
+            url: '/channelItem/queryChannelItemList',
+            modifyPriceVisible: false,
+            modifyPriceLoading: false,
+            modifyPriceDetail: null,
+            accountVisible: false,
+            againLoading: false,
+            accountProjectDetail: null,
+            accountProjectList: [],
+            keyWord: undefined
+        }
+    },
+    methods: {
+        moment,
+        deleteIcon(event) {
+            event.stopPropagation()
+        },
+        deleteRule(event, item, index) {
+            event.stopPropagation()
+            this.addItemForm.items.splice(index, 1)
+        },
+        visibleChange() {
+            this.keyWord = undefined
+        },
+        bidChangeCancel(record) {
+            record.visible = false
+            this.keyWord = undefined
+        },
+        bidChangeOk(record) {
+            if (this.keyWord.length > 15) {
+                this.$message.error('素材关键字最多15个字')
+                return
+            }
+            record.visible = false
+            const paramsData = {
+                id: record.id,
+                keyword: this.keyWord
+            }
+            getAction('/channelItem/updateChannelItems', paramsData)
+                .then(result => {
+                    if (result.code === 200) {
+                        record.visible = false
+                        this.keyWord = undefined
+                        const paramsData = this.form.getFieldsValue()
+                        this.handleGetTableList(paramsData)
+                    } else {
+                        this.$message.error(result.message)
+                    }
+                })
+                .catch(error => {
+                    console.log(error, 'eeee')
+                })
+        },
+        handleSwitchChang(checked, data) {
+            const paramsData = {
+                id: data.id,
+                state: checked ? 1 : 0
+            }
+            getAction('/channelItem/updateChannelItems', paramsData)
+                .then(result => {
+                    if (result.code === 200) {
+                        const paramsData = this.form.getFieldsValue()
+                        this.handleGetTableList(paramsData)
+                    } else {
+                        this.$message.error(result.message)
+                    }
+                })
+                .catch(error => {
+                    console.log(error, 'eeee')
+                })
+        },
+        overUpload(file) {},
+        handleChange() {
+            this.loadDisabled = false
+            this.$message.success('文件导入成功')
+        },
+        beforeUpload(file) {
+            // this.cosUpload(file)
+            // if (process.env.NODE_ENV == 'development') {
+            //   this.uploadAction = `/jeecg-boot/kuaishouAppPackage/importAppExcel?projectId=${this.projectId}&platform=${
+            //     this.appType == 'ios' ? +this.platform + 2 : +this.platform
+            //   }&imageUrl=${this.fileUrl}`
+            // } else if (process.env.NODE_ENV == 'debug') {
+            // } else if (process.env.NODE_ENV == 'production') {
+            //   this.uploadAction = `${this.axios.defaults.baseURL}/kuaishouAppPackage/importAppExcel?projectId=${
+            //     this.projectId
+            //   }&platform=${this.appType == 'ios' ? +this.platform + 2 : +this.platform}&imageUrl=${this.fileUrl}`
+            // }
+            // this.dataFile = file
+            this.dataFile = $('.fileUpload')
+                .eq(0)
+                .find('input')[0].files[0]
+            this.loadDisabled = true
+            const size = (Number(file.size) / (1024 * 1024)).toFixed(2)
+            const fileName = file.name
+            const fileStrArr = fileName.split('.')
+            const suffix = fileStrArr[fileStrArr.length - 1]
+
+            let result = fileSuffix.some(item => {
+                return item === suffix
+            })
+
+            if (!result) {
+                this.$message.error('不支持该文件类型')
+                this.loadDisabled = false
+                return Promise.reject()
+            }
+        },
+        ...mapGetters(['userInfo']),
+        toDetailList(item) {},
+
+        cpaBidValid(rule, value, callback) {
+            let z = /-/g
+            let a = /\//g
+            let d = /\./g
+            if (value === '' || value === undefined) {
+                callback('出价必须填写')
+            } else if (value.startsWith('.') || value.endsWith('.')) {
+                callback('请填写正确出价')
+            } else if (value.startsWith('-') || value.endsWith('-')) {
+                callback('请填写正确出价')
+            } else if (value.match(a) && value.match(z)) {
+                callback('不允许出现除"-"和"/"之外的所有字符,并且二者不可同时出现')
+            } else if (value.match(/[^0-9+-\/]/g)) {
+                callback('请填写正确出价')
+            } else {
+                callback()
+            }
+        },
+        addOneItem() {
+            this.addItemForm.items.push({
+                projectId: '',
+                keyWord: '',
+                itemName: '默认名称-单品' + (this.addItemForm.items.length + 1)
+            })
+        },
+        handleOk() {
+            this.$refs.ruleForm.validate(valid => {
+                if (valid) {
+                    this.confirmLoading = true
+                    postAction('/channelItem/addChannelItem', this.addItemForm.items).then(res => {
+                        this.confirmLoading = false
+                        if (res.success) {
+                            this.visibleAddItem = false
+                            this.addItemForm.items = [{ projectId: '', keyWord: '', itemName: '默认名称-单品1' }]
+                            this.handleResetForm()
+                        } else {
+                            this.$message.error(res.message)
+                        }
+                    })
+                }
+            })
+        },
+        handleOkImport() {
+            this.downLoading = true
+            let params = {}
+            if (this.dataFile) {
+                let formData = new FormData()
+                formData.append('file', this.dataFile)
+
+                postAction('/channelItem/importItemExcel', formData).then(res => {
+                    this.downLoading = false
+                    if (res.code === 200) {
+                        this.$message.success(res.message)
+                        this.visibleDownLoad = false
+                        this.projectIdDownLoad = ''
+                        this.handleResetForm()
+                    } else {
+                        this.$message.error(res.message)
+                    }
+                })
+            } else {
+                this.downLoading = false
+                this.$message.error('请上传文件')
+            }
+
+            return
+        },
+        handleOkDownLoad() {
+            if (!!this.projectIdDownLoad) {
+                let params = {}
+                params.projectId = this.projectIdDownLoad
+                params.userId = this.userInfo().id
+                downFile('/channelItem/exportItemTemplate', params).then(res => {
+                    let blob = new Blob([res], {
+                        type: 'application/vnd.openxmlformats-officedocument.spre1adsheetml.sheet'
+                    })
+                    let downloadElement = document.createElement('a')
+                    let href = window.URL.createObjectURL(blob) //创建下载的链接
+                    downloadElement.href = href
+                    downloadElement.download = '单品模板.xlsx' //下载后文件名
+                    document.body.appendChild(downloadElement)
+                    downloadElement.click() //点击下载
+                    document.body.removeChild(downloadElement) //下载完成移除元素
+                    window.URL.revokeObjectURL(href) //释放掉blob对象
+                })
+            } else {
+                this.$message.error('请选择项目')
+            }
+        },
+        handleCancel() {
+            this.visibleChannel = false
+        },
+        addNewChannel() {
+            this.visibleChannel = true
+        },
+        getDataSource(current, pageSize) {
+            // 切换分页时的回调,
+            // 当在页面定义change事件时,切记要把此处的事件清除,因为这两个事件重叠了,可能到时候会导致一些莫名的bug
+            this.ipagination.current = current
+            this.ipagination.pageSize = pageSize
+            const paramsData = this.form.getFieldsValue()
+            this.handleGetTableList(paramsData)
+        },
+        handleQueryList(event) {
+            this.ipagination.current = 1
+            event.preventDefault()
+            const paramsData = this.form.getFieldsValue()
+            this.handleGetTableList(paramsData)
+        },
+        handleResetForm() {
+            this.ipagination.current = 1
+            this.form.resetFields()
+            this.$refs.selectTableProject.keyValue = ''
+            this.$refs.selectTableProject.getData()
+            const paramsData = this.form.getFieldsValue()
+            this.handleGetTableList(paramsData)
+        },
+        handleGetTableList(data) {
+            let paramsData = {
+                projectId: this.projectId,
+                keyword: data.keyword,
+                itemName: data.itemName,
+                pageNo: this.ipagination.current,
+                pageSize: this.ipagination.pageSize,
+                userId: this.userInfo().id
+            }
+            this.dataSource = []
+            this.dataLoading = true
+            this.getAction(this.url, paramsData)
+                .then(result => {
+                    this.dataLoading = false
+                    if (result.code === 200) {
+                        this.dataSource =
+                            result.result.list.map(item => {
+                                return {
+                                    ...item,
+                                    visible: false
+                                }
+                            }) || []
+                        this.ipagination.total = result.result.total || 0
+                        // result.result.total
+                    } else {
+                        this.$message.error(result.message)
+                    }
+                })
+                .catch(error => {
+                    this.dataLoading = false
+                    console.log(error, 'eeee')
+                })
+        },
+        getAccountNoProject() {
+            this.projectId = undefined
+            const paramsData = this.form.getFieldsValue()
+            this.handleGetTableList(paramsData)
+        },
+        disabledDate(current) {
+            // Can not select days before today and today
+            return current && current > moment().endOf('day')
+        },
+        dateChange(date, dateString) {
+            // console.log(date,dateString)
+        },
+
+        filterOption(input, option) {
+            // console.log(input, option)
+            return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
+        },
+        operateChange(value) {
+            console.log(value)
+            if (value) {
+                this.accountDisabled = true
+                this.accountId = ''
+            } else {
+                this.accountDisabled = false
+            }
+        },
+
+        tableChange(pagination, filters, sorter, { currentDataSource }) {
+            this.ipagination.current = pagination.current
+            this.ipagination.pageSize = pagination.pageSize
+            if (sorter.order) {
+                this.order = sorter.order ? sorter.order : 'descend'
+                this.target = sorter.columnKey
+                const paramsData = this.form.getFieldsValue()
+                this.handleGetTableList({
+                    ...paramsData,
+                    target: sorter.columnKey,
+                    order: sorter.order ? sorter.order : 'descend'
+                })
+            }
+        },
+
+        // 获取所有运营
+        getAllOperator(key) {
+            let url = '/sys/user/getAllUserListV1'
+            this.designList = []
+
+            getAction(url, {}).then(res => {
+                if (res.success) {
+                    this.designList = res.result
+                }
+            })
+        }
+    },
+    watch: {
+        productId: function(n, o) {
+            if (n != '') {
+                this.$refs.selectTableProject.keyValue = ''
+                this.$refs.selectTableProject.getData(n)
+            }
+        },
+        visibleAddItem: function(n, o) {
+            if (!n) {
+                this.addItemForm = {
+                    items: [{ projectId: '', keyWord: '', itemName: '默认名称-单品1' }]
+                }
+                this.addItemForm.items[0].projectId = ''
+            }
+        }
+    },
+    computed: {
+        newDate() {
+            var myDate = new Date()
+            myDate.getYear() //获取当前年份(2位)
+            var n = myDate.getFullYear() //获取完整的年份(4位,1970-????)
+            var m = myDate.getMonth() //获取当前月份(0-11,0代表1月)
+            var d = myDate.getDate() //获取当前日(1-31)
+            var day = myDate.getHours()
+            return day
+        }
+    },
+    mounted() {
+        const paramsData = this.form.getFieldsValue()
+        this.handleGetTableList(paramsData)
+        this.getAllOperator()
+    },
+    activated: function() {},
+
+    filters: {
+        toPercentage(val) {
+            if (typeof val != 'string') {
+                return (val * 100).toFixed(2) + '%'
+            } else {
+                return val
+            }
+        },
+        //保留两位小数并且变成货币格式
+        decimalsHandle(val) {
+            if (val && typeof val != 'string') {
+                if (val >= 0) {
+                    val = parseFloat(val).toFixed(2)
+                    let numberStr = val.toString()
+                    let str = numberStr.split('.')
+
+                    let str0 = str[0].split('').reverse()
+                    for (let i = 0; i < str0.length; i++) {
+                        if ((i + 1) % 4 === 0) {
+                            str0.splice(i, 0, ',')
+                        }
+                    }
+                    str0.reverse()
+                    let handleResult = ''
+                    for (let j = 0; j < str0.length; j++) {
+                        handleResult += str0[j]
+                    }
+
+                    return handleResult + '.' + str[1]
+                } else {
+                    val = parseFloat(val).toFixed(2)
+                    let numberStr = val.toString()
+                    let str = numberStr.split('.')
+
+                    let str0 = str[0]
+                        .substr(1)
+                        .split('')
+                        .reverse()
+                    for (let i = 0; i < str0.length; i++) {
+                        if ((i + 1) % 4 === 0) {
+                            str0.splice(i, 0, ',')
+                        }
+                    }
+                    str0.reverse()
+                    let handleResult = ''
+                    for (let j = 0; j < str0.length; j++) {
+                        handleResult += str0[j]
+                    }
+
+                    return '-' + handleResult + '.' + str[1]
+                }
+            } else if (typeof val == 'string') {
+                return val
+            } else {
+                return 0
+            }
+        },
+        //变成货币格式
+        formatCurrency(val) {
+            if (val) {
+                let numberStr = val.toString()
+                let str = numberStr.split('').reverse()
+                for (let i = 0; i < str.length; i++) {
+                    if ((i + 1) % 4 === 0) {
+                        str.splice(i, 0, ',')
+                    }
+                }
+                str.reverse()
+                let handleResult = ''
+                for (let j = 0; j < str.length; j++) {
+                    handleResult += str[j]
+                }
+                return handleResult
+            } else {
+                return '-'
+            }
+        }
+    }
+}
+</script>

+ 166 - 15
src/views/modules/autoLaunch/configLaunchInfo.vue

@@ -84,12 +84,12 @@
                    <a-tag color="#2db7f5" @click="getChangeAll('日期', 'form', 'campaignName')"
                 >+日期</a-tag
               >
-              <!-- <a-tag color="#2db7f5" @click="getChangeAll('应用包名', 'form', 'campaignName')"
-                >+应用包名</a-tag
+              <a-tag color="#2db7f5" @click="getChangeAll('渠道号', 'form', 'campaignName')"
+                >+渠道号</a-tag
+              >
+              <a-tag color="#2db7f5" @click="getChangeAll('渠道号名称', 'form', 'campaignName')"
+                >+渠道号名称</a-tag
               >
-              <a-tag color="#2db7f5" @click="getChangeAll('自定义', 'form', 'campaignName')"
-                >+自定义</a-tag
-              > -->
                 </a-form-item>
                 </div>
             </div>  
@@ -186,9 +186,12 @@
                <a-tag color="#2db7f5" @click="getChangeAll('广告位置', 'form', 'groupName')"
                 >+广告位置</a-tag
               >
-               <!-- <a-tag color="#2db7f5" @click="getChangeAll('自定义', 'form', 'groupName')"
-                >+自定义</a-tag
-              > -->
+              <a-tag color="#2db7f5" @click="getChangeAll('渠道号', 'form', 'groupName')"
+                >+渠道号</a-tag
+              >
+              <a-tag color="#2db7f5" @click="getChangeAll('渠道号名称', 'form', 'groupName')"
+                >+渠道号名称</a-tag
+              >
                 </a-form-item>
                 </div>
             </div>  
@@ -307,9 +310,9 @@
                         </div>
                     </div>
                     <div class="row-item">
-                    <div class="hint-item"></div>
-                    <div class="label-item">
-                        <div class="text-item">调起链接</div>
+                        <div class="hint-item"></div>
+                        <div class="label-item">
+                            <div class="text-item">调起链接</div>
                         </div>
                         <div class="input-item">
                             <a-form-item>
@@ -317,13 +320,100 @@
                                 <span style="color:red"> 需加白使用</span>
                                 <div v-if="uriCheck">
                                     <a-input placeholder="请填写链接" v-decorator="['schemaUri', { rules: [{ message:'链接不能为空'}] }]" />
-                                   
+                                
                                 </div>
                                 
                             </a-form-item>
                         </div>
                     </div>
 
+                    <div class="row-item">
+                        <div class="hint-item"></div>
+                        <div class="label-item">
+                            <div class="text-item">是否使用渠道号</div>
+                            <div class="required-item"></div>
+                        </div>
+                        
+                        <div class="input-item">
+                            <a-form-item>
+                                <a-switch default-checked v-model="useChannel" @change="changeChannel"/>
+                            </a-form-item>
+                        </div>
+                    </div>
+                    <div class="row-item" v-if="channelData&&channelData.channel.isHaveItem">
+                        <div class="hint-item"></div>
+                        <div class="label-item">
+                            <div class="text-item">是否使用单品</div>
+                            <div class="required-item"></div>
+                        </div>
+                        
+                        <div class="input-item">
+                            <a-form-item>
+                                <a-radio-group v-model="channelData.channel.isHaveItem" disabled>
+                                    <a-radio-button :value="1">是</a-radio-button>
+                                    <a-radio-button :value="0">否</a-radio-button>
+                                </a-radio-group>
+                            </a-form-item>
+                        </div>
+                    </div>
+                    <div class="row-item" v-if="channelData&&channelData.channel.usageLevel">
+                        <div class="hint-item"></div>
+                        <div class="label-item">
+                            <div class="text-item">渠道号作用维度</div>
+                            <div class="required-item"></div>
+                        </div>
+                        
+                        <div class="input-item">
+                            <a-form-item>
+                               <a-radio-group
+                                    button-style="solid"
+                                    v-model="channelData.channel.usageLevel"
+                                    disabled
+                                >
+                                    <a-radio-button value="account">账户</a-radio-button>
+                                    <a-radio-button value="plan">计划</a-radio-button>
+                                    <a-radio-button value="group">组</a-radio-button>
+                                </a-radio-group>
+                            </a-form-item>
+                        </div>
+                    </div>
+
+                    <div class="row-item" v-if="channelData&&channelData.channel.usageLevel&&channelData.list&&channelData.list.length>0">
+                        <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-collapse accordion ref="collapse">
+                                    <template v-for="(item, index) in channelData.list">
+                                        <a-collapse-panel
+                                            :forceRender="true"
+                                            :header="item.appName+'(应用标记)'"
+                                            style="background: #f9f9fa;border-radius: 4px;margin-bottom:15px;overflow: hidden;border: 1px solid #d9d9d9;"
+                                        >
+                                            <a-form-item
+                                                label="渠道号"
+                                                v-bind="formItemLayout"
+                                            >
+                                                {{item.channelCode}}
+                                            </a-form-item>
+                                           <a-form-item
+                                                label="素材关键字"
+                                                v-bind="formItemLayout"
+                                            >
+                                                {{item.keyword}}
+                                            </a-form-item>
+                                        </a-collapse-panel>
+                                    </template>
+                                </a-collapse>
+                            </a-form-item>
+                        </div>
+                    </div>
+
+
                     <div class="row-item" v-if="getFormData('singleAppid')==0">
                     <div class="hint-item"></div>
                     <div class="label-item">
@@ -1653,7 +1743,7 @@
                             </a-radio-group>
                         </a-form-item>
                         </div>
-                    </div> 
+                    </div>
                     <div class="row-item">
                         <div class="hint-item"> </div>
                         <div class="label-item">
@@ -1896,10 +1986,15 @@ export default {
     },
     data() {
         return {
+            formItemLayout: {
+                labelCol: { span: 5 },
+                wrapperCol: { span: 19 }
+            },
             getProjectIdAccount: '',
             checkCpaBidBloon:false,
             appType: '0',
             uriCheck: false,
+            useChannel:false,
             programUnitCnt:300,
             customUnitCnt:400,
             customUnitCntMax:400,
@@ -2052,7 +2147,8 @@ export default {
             checkAllApp: false,
             optionsAll: [],
             multipleBidData:[],
-            descriptionList:[{value:""}]
+            descriptionList:[{value:""}],
+            channelData:null
            
             
         }
@@ -2167,6 +2263,50 @@ export default {
     },
     methods: {
         ...mapGetters(['userInfo']),
+        changeChannel(checked) {
+            if(checked){
+                if(!!this.accountId){
+                    if(!!this.getFormData('appId')){
+                        var paramsData = {}
+                        paramsData.appIdArray = this.getFormData('appId') instanceof Array?this.getFormData('appId').map(item=>{return item.key}):[this.getFormData('appId').key]
+                        postAction('/kuaishou/kuaiShouAppList/getAppNames',paramsData).then(result=>{
+                            var params = {}
+                            params.appNameArray = result.result.map(item=>{
+                                return item.appName
+                            })
+                            params.accountId = this.accountId
+                            postAction('/channel/queryChannelLevel', params).then(res=>{
+                                console.log(res)
+                                if(res.code === 200) {
+                                    if(res.result){
+                                        this.channelData = res.result
+                                    }else{
+                                        this.useChannel = false
+                                        this.$message.error(res.message) 
+                                    }
+                                    
+                                }else{
+                                    this.useChannel = false
+                                    this.$message.error('该账户不能使用渠道号')
+                                }
+                            })
+                        })
+                       
+                    }else{
+                        this.useChannel = false
+                        this.$message.error('未选择应用不可开启')
+                    }
+                    
+                  
+                }else{
+                    this.useChannel = false
+                    this.$message.error('未选择账户不可开启')
+                }
+               
+            }else{
+                this.channelData = null
+            }
+        },
         handleGetAcoountId(list) {
             getAction('/estimatePeopleNumber/getProjectId', {accountId: list}).then(result => {
                 if (result.code === 0) {
@@ -2689,6 +2829,9 @@ export default {
                     
                 }
                
+           }else{
+               this.useChannel = false
+               this.channelData = null
            }
         },
         disabledDate(current) {
@@ -3100,6 +3243,9 @@ export default {
 
                     values.campaignDayBudget = this.budgetType =='1'?0: values.campaignDayBudget*1000
                     values.unitDayBudget = this.dayBudgetType =='1'?0: values.unitDayBudget*1000
+
+                    values.usageLevel = this.channelData&&this.channelData.channel?this.channelData.channel.usageLevel:null
+                    values.useChannel = this.useChannel?1:0
                     let url=''
                     if(this.editRecordId){
                         url='/ctop/aiKuaishouAdvertiserStrategy/edit';
@@ -3428,7 +3574,7 @@ export default {
                         this.scheduleTimeType = ''
                         this.scheduleTimeData = str
                    }
-                   
+
                     this.multipleBidData = res.result.appInfoList ? res.result.appInfoList.map(item=>{
                         
                         return {
@@ -3478,6 +3624,11 @@ export default {
                             siteId:res.result.siteId,
                         })
                         
+                        this.useChannel = res.result.useChannel?res.result.useChannel==1?true:false:false
+
+                        if(this.useChannel){
+                            this.changeChannel(this.useChannel)
+                        }
                     },100)
 
                     

+ 6 - 3
src/views/modules/autoLaunch/configLaunchList.vue

@@ -165,6 +165,7 @@ import { getAction, postAction, downFile, downFilePost,deleteAction } from '@/ap
 import Treeselect from '@/views/modules/Statistics/components/Treeselect.vue'
 import configLaunchExploreDrawer from './components/configLaunchExploreDrawer.vue'
 import qs from 'qs'
+import { mapActions, mapGetters } from 'vuex'
 let typeValue='预算'
 
 
@@ -332,6 +333,7 @@ export default {
         },
     },
     methods: {
+        ...mapGetters(['userInfo']),
         goExplore(item) {
             this.exploreVisible = true
             this.exploreKey = '1'
@@ -505,7 +507,8 @@ export default {
                 strategyId:this.strategyId==undefined?null:this.strategyId,
                 accountId:this.accountId,
                 pageNo:this.ipagination.current,
-                pageSize:this.ipagination.pageSize
+                pageSize:this.ipagination.pageSize,
+                userId:this.userInfo().id
             }).then((res)=>{
                 this.data=[]
                 console.log(res)
@@ -514,7 +517,7 @@ export default {
 
                     this.ipagination.total = res.result.total
                     
-                    res.result.records.forEach((item)=>{
+                    res.result.list.forEach((item)=>{
                         item.key=item.id;
                         item.show=false;
                         item.visible=false;
@@ -522,7 +525,7 @@ export default {
                         item.openProgramCreateSpin=false;
                     })
 
-                    this.data = res.result.records;
+                    this.data = res.result.list;
                     this.selectedRowKeys=[];
                 }
             })

+ 12 - 14
src/views/modules/autoLaunch/material-pool/material.vue

@@ -7,52 +7,50 @@
     >
         <component v-bind:is="currentTabComponent"></component>
     </a-card>
-        
-    
 </template>
-
 <script>
-import moment from 'moment';
-
 export default {
     components:{
         directional: () => import('../directional/directional'),
         person: () => import('@/views/modules/crowd-control/crowd-control.vue'),
         url: () => import('../url/url'),
         application: () => import('../application/application'),
+        autoCopyLibrary: () => import('../auto-copy-library/auto-copy-library.vue'),
     },
     data() {
         return {
-            currentTabComponent:'directional',//当前加载的组件名称
+            currentTabComponent: 'directional', // 当前加载的组件名称
             tabListNoTitle: [
                 {
                     key: 'directional',
-                    tab: '定向包管理',
+                    tab: '定向包管理'
                 },
                 {
                     key: 'person',
-                    tab: '人群包管理',
+                    tab: '人群包管理'
                 },
                 {
                     key: 'url',
-                    tab: '落地页管理',
+                    tab: '落地页管理'
                 },
                 {
                     key: 'application',
-                    tab: '应用包管理',
+                    tab: '应用包管理'
                 },
-            ], 
+                {
+                    key: 'autoCopyLibrary',
+                    tab: '文案库管理'
+                }
+            ]
         }
     },
     methods: {
         onTabChange(key, type) {
             this.currentTabComponent = key;
-        },
+        }
     },
     created() {
         this.currentTabComponent = 'directional';
     }
-   
 }
-
 </script>

+ 426 - 0
src/views/modules/earlyWarningRules/configurationList.vue

@@ -0,0 +1,426 @@
+<style lang="scss" scoped>
+.tableBox {
+    background-color: #fff;
+    margin: 15px 0px;
+    padding: 15px 10px;
+    .tableTop {
+        position: relative;
+        padding-bottom: 15px;
+        border-bottom: 1px solid #e0e0e0;
+        .selectTime {
+            margin-right: 20px;
+        }
+        .add {
+            position: absolute;
+            top: 0;
+            right: 0;
+        }
+    }
+}
+</style>
+<template>
+    <div class="video-report">
+        <!-- 报表区域 -->
+
+        <div class="tableBox">
+            <div style="display:flex">
+                <selectTreeAccount
+                    v-model="searchAccountId"
+                    style="display: inline-block;position: relative;margin-left: 0px;width:30%;margin-bottom:15px"
+                    reqUrl="/monitor/projectMonitorWhiteList/getProjectAndAccountIds"
+                />
+                <a-button type="primary" @click="search" style="position:relative;top:2px">搜索</a-button>
+            </div>
+
+            <div class="tableTop" style="display:flex;justify-content: flex-end;">
+                <a-button type="primary" @click="addWhite">添加</a-button>
+            </div>
+            <a-table
+                size="middle"
+                :columns="columns"
+                :dataSource="data"
+                bordered
+                id="outTable"
+                :pagination="ipagination"
+                :loading="loading"
+                ref="accountTable"
+            >
+                <a slot="action" slot-scope="text, records" @click="editConfiguration(records)">
+                    编辑
+                </a>
+                <span slot="status" slot-scope="text, record">
+                    <a-switch :checked="text == 0" @change="handleSwitchChang($event, record)" />
+                </span>
+            </a-table>
+        </div>
+        <a-modal
+            v-model="whiteVisible"
+            title="添加配置"
+            @ok="whiteListOk"
+            @cancel="handleCancel"
+            :width="1000"
+            :confirmLoading="confirmLoading"
+        >
+            <a-form layout="horizontal" :form="form" hide-required-mark :selfUpdate="true" v-bind="formItemLayout">
+                <a-row :gutter="24">
+                    <a-col :md="24" :sm="24" :xxl="24">
+                        <a-form-item label="选择账户">
+                            <selectTreeAccount
+                                v-if="whiteVisible"
+                                v-model="accountId"
+                                style="display: inline-block;position: relative;margin-left: 0px;width:100%;margin-bottom:15px"
+                                reqUrl="/monitor/projectMonitorWhiteList/getProjectAndAccountIds"
+                            />
+                        </a-form-item>
+                    </a-col>
+                </a-row>
+                <a-row :gutter="24">
+                    <a-col :md="24" :sm="24" :xxl="24">
+                        <a-form-item label="第三方点击监测链接">
+                            <a-input
+                                v-decorator="[
+                                    'clickTrackUrl',
+                                    {
+                                        rules: [
+                                            { required: true, message: '请填写第三方点击监测链接' },
+                                            { validator: handleConfirmValue }
+                                        ]
+                                    }
+                                ]"
+                                allow-clear
+                            />
+                        </a-form-item>
+                    </a-col>
+                </a-row>
+                <a-row :gutter="24">
+                    <a-col :md="24" :sm="24" :xxl="24">
+                        <a-form-item label="第三方点击按钮监测链接(ab监测)">
+                            <a-input
+                                v-decorator="[
+                                    'actionbarClickUrl',
+                                    {
+                                        rules: [{ validator: handleConfirmValueOkUndefind }]
+                                    }
+                                ]"
+                                allow-clear
+                            />
+                            <span style="color:red">需媒体加白使用</span>
+                        </a-form-item>
+                    </a-col>
+                </a-row>
+            </a-form>
+        </a-modal>
+    </div>
+</template>
+
+<script>
+import moment from 'moment'
+import { JeecgListMixin } from '@/mixins/ipagination'
+import { getAction, postAction, downFile, downFilePost, deleteAction } from '@/api/manage'
+import { mapGetters } from 'vuex'
+import selectTreeAccount from '@/components/formComponents/selectAccount.vue'
+import pick from 'lodash.pick'
+const columnsFixd = [
+    {
+        title: '监测状态',
+        dataIndex: 'status',
+        align: 'center',
+        key: 'status',
+        scopedSlots: { customRender: 'status' }
+    },
+    {
+        title: '项目名称',
+        dataIndex: 'projectName',
+        align: 'center',
+        key: 'projectName',
+        scopedSlots: { customRender: 'projectName' }
+    },
+    {
+        title: '账户ID',
+        dataIndex: 'accountId',
+        align: 'center',
+        key: 'accountId',
+        scopedSlots: { customRender: 'accountId' }
+    },
+    {
+        title: '账户名称',
+        dataIndex: 'accountName',
+        align: 'center',
+        key: 'accountName',
+        scopedSlots: { customRender: 'accountName' }
+    },
+
+    {
+        title: '三方点击监测链接',
+        dataIndex: 'clickTrackUrl',
+        align: 'center',
+        width: 350,
+        key: 'clickTrackUrl',
+        scopedSlots: { customRender: 'clickTrackUrl' }
+    },
+    {
+        title: '三方点击按钮监测链接(ab监测)',
+        dataIndex: 'actionbarClickUrl',
+        align: 'center',
+        width: 350,
+        key: 'actionbarClickUrl',
+        scopedSlots: { customRender: 'actionbarClickUrl' }
+    },
+    {
+        title: '配置人',
+        dataIndex: 'userName',
+        align: 'center',
+        key: 'userName',
+        scopedSlots: { customRender: 'userName' }
+    },
+    {
+        title: '账户状态',
+        dataIndex: 'accountStatus',
+        align: 'center',
+        key: 'accountStatus',
+        customRender: function(t, r, index) {
+            if (t == 0 || t == '0') {
+                return '投放中'
+            } else if (t == 1 || t == '1') {
+                return '暂停'
+            }
+        }
+    },
+    {
+        title: '操作',
+        align: 'center',
+        dataIndex: 'action',
+        scopedSlots: { customRender: 'action' }
+    }
+]
+const columnsWhite = [
+    {
+        title: '项目名称',
+        dataIndex: 'projectName',
+        align: 'center',
+        key: 'projectName',
+        scopedSlots: { customRender: 'projectName' }
+    },
+    {
+        title: '运营负责人',
+        align: 'center',
+        dataIndex: 'responsibleId_dictText'
+    },
+    {
+        title: '设计负责人',
+        align: 'center',
+        dataIndex: 'designResponsibleId_dictText'
+    },
+    {
+        title: '操作',
+        align: 'center',
+        dataIndex: 'action',
+        scopedSlots: { customRender: 'action' }
+    }
+]
+
+export default {
+    data() {
+        return {
+            columns: [...columnsFixd], //table的表头
+            columnsWhite: columnsWhite,
+            whiteVisible: false,
+            loading: false,
+            whiteLoading: false,
+            confirmLoading: false,
+            addColumns: [],
+            data: [],
+            dataWhiteList: [],
+            accountId: undefined,
+            searchAccountId: undefined,
+            form: this.$form.createForm(this),
+            ipagination: {
+                current: 1,
+                pageSize: 10,
+
+                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
+                    this.handleGetTableList()
+                }
+            },
+            ipaginationWhite: {
+                current: 1,
+                pageSize: 10,
+
+                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.ipaginationWhite.current = current
+                    this.ipaginationWhite.pageSize = pageSize
+                    this.getWhiteList()
+                }
+            },
+            projectName: '',
+            whiteListRul: '/monitor/trackMonitorConfigure/list',
+            formItemLayout: {
+                labelCol: { span: 6 },
+                wrapperCol: { span: 16 }
+            },
+            type: 'add',
+            editId: undefined
+            // '/monitor/projectMonitorWhiteList/getProjectAndAccountIds'
+        }
+    },
+    watch: {},
+    components: {
+        selectTreeAccount
+    },
+    methods: {
+        ...mapGetters(['userInfo']),
+        handleConfirmValue(rule, value, callback) {
+            if (/(http|https):\/\/([\w.]+\/?)\S*/.test(value) && value != '') {
+                callback()
+            } else {
+                callback('链接不能为空且开头为http://或https://')
+            }
+        },
+        handleConfirmValueOkUndefind(rule, value, callback) {
+            if (!!!value) {
+                callback()
+            } else if (/(http|https):\/\/([\w.]+\/?)\S*/.test(value)) {
+                callback()
+            } else {
+                callback('链接开头为http://或https://')
+            }
+        },
+        handleSwitchChang(checked, data) {
+            const paramsData = {
+                id: data.id,
+                status: checked ? 0 : 1
+            }
+            postAction('/monitor/trackMonitorConfigure/edit', paramsData)
+                .then(result => {
+                    if (result.code === 200) {
+                        this.handleGetTableList()
+                    } else {
+                        this.$message.error(result.message)
+                    }
+                })
+                .catch(error => {
+                    console.log(error, 'eeee')
+                })
+        },
+        editConfiguration(item) {
+            this.whiteVisible = true
+            this.$nextTick(() => {
+                this.type = 'edit'
+                setTimeout(() => {
+                    this.accountId = item.accountId
+                }, 100)
+                // this.accountId = item.accountId
+                this.editId = item.id
+                this.form.setFieldsValue(pick(item, 'clickTrackUrl', 'actionbarClickUrl'))
+                //时间格式化
+            })
+        },
+        handleGetTableList() {
+            this.loading = true
+            const params = {
+                pageSize: this.ipaginationWhite.pageSize,
+                pageNo: this.ipaginationWhite.current,
+                userId: this.userInfo().id,
+                accountId: this.searchAccountId
+            }
+            getAction(this.whiteListRul, params).then(res => {
+                this.loading = false
+                if (res.success) {
+                    // let result = res.result
+                    // this.data.push({ ...result, key: 1 })
+                    // result.map((item, index) => {
+                    //   item.key = index
+                    // })
+                    this.data = res.result.records.map((item, index) => {
+                        return {
+                            ...item,
+                            key: index
+                        }
+                    })
+                    this.ipagination.total = res.result.total
+                } else {
+                    this.$message.error(res.message)
+                    this.loading = false
+                }
+            })
+        },
+        addWhite() {
+            this.whiteVisible = true
+        },
+        search() {
+            this.ipaginationWhite.current = 1
+            this.handleGetTableList()
+        },
+        handleCancel() {
+            this.form.resetFields()
+            this.accountId = ''
+            this.whiteVisible = false
+        },
+        whiteListOk() {
+            this.form.validateFields((err, values) => {
+                if (!err) {
+                    if (this.accountId) {
+                        this.confirmLoading = true
+                        var params = { ...values }
+                        params.accountId = this.accountId
+                        params.userId = this.userInfo().id
+                        if (this.type == ' add') {
+                        } else {
+                            params.id = this.editId
+                        }
+                        var url =
+                            this.type == 'add'
+                                ? '/monitor/trackMonitorConfigure/add'
+                                : '/monitor/trackMonitorConfigure/edit'
+                        postAction(url, params).then(res => {
+                            this.confirmLoading = false
+                            if (res.success) {
+                                this.handleCancel()
+                                this.handleGetTableList()
+                            } else {
+                                this.$message.error(res.message)
+                            }
+                        })
+                    }
+                }
+            })
+        },
+        deleteWhite(id) {
+            deleteAction('/monitor/projectMonitorWhiteList/delete', { id: id }).then(res => {
+                if (res.success) {
+                    this.handleGetTableList()
+                } else {
+                    this.$message.error(res.message)
+                }
+            })
+        },
+        filterOption(input, option) {
+            return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
+        }
+    },
+
+    mounted() {
+        this.handleGetTableList()
+    }
+}
+</script>

+ 257 - 0
src/views/modules/earlyWarningRules/whitelist.vue

@@ -0,0 +1,257 @@
+<style lang="scss" scoped>
+.tableBox {
+    background-color: #fff;
+    margin: 15px 0px;
+    padding: 15px 10px;
+    .tableTop {
+        position: relative;
+        padding-bottom: 15px;
+        border-bottom: 1px solid #e0e0e0;
+        .selectTime {
+            margin-right: 20px;
+        }
+        .add {
+            position: absolute;
+            top: 0;
+            right: 0;
+        }
+    }
+}
+</style>
+<template>
+    <div class="video-report">
+        <!-- 报表区域 -->
+
+        <div class="tableBox">
+            <div class="tableTop" style="display:flex;    justify-content: flex-end;">
+                <a-button type="primary" @click="addWhite">添加白名单</a-button>
+            </div>
+            <a-table
+                size="middle"
+                :columns="columns"
+                :dataSource="data"
+                bordered
+                id="outTable"
+                :pagination="ipagination"
+                :loading="loading"
+                ref="accountTable"
+            >
+                <a slot="action" slot-scope="text, records" @click="deleteWhite(records.id)">
+                    删除
+                </a>
+            </a-table>
+        </div>
+        <a-modal v-model="whiteVisible" title="添加白名单" @ok="whiteListOk" :footer="null" width="50%">
+            <div class="tableTop" style="margin-bottom:10px;width:300px">
+                <a-input-search
+                    placeholder="请输入项目名称"
+                    v-model="projectName"
+                    enter-button
+                    @search="getWhiteList"
+                />
+            </div>
+            <a-table
+                size="middle"
+                :columns="columnsWhite"
+                :dataSource="dataWhiteList"
+                bordered
+                :loading="whiteLoading"
+                :pagination="ipaginationWhite"
+            >
+                <a slot="action" slot-scope="text, records" @click="addWhiteOk(records)">
+                    添加
+                </a>
+            </a-table>
+        </a-modal>
+    </div>
+</template>
+
+<script>
+import moment from 'moment'
+import { JeecgListMixin } from '@/mixins/ipagination'
+import { getAction, postAction, downFile, downFilePost, deleteAction } from '@/api/manage'
+import { mapGetters } from 'vuex'
+const columnsFixd = [
+    {
+        title: '项目名称',
+        dataIndex: 'projectName',
+        align: 'center',
+        key: 'projectName',
+        scopedSlots: { customRender: 'projectName' }
+    },
+    {
+        title: '操作人',
+        align: 'center',
+        dataIndex: 'userName'
+    },
+    {
+        title: '操作',
+        align: 'center',
+        dataIndex: 'action',
+        scopedSlots: { customRender: 'action' }
+    }
+]
+const columnsWhite = [
+    {
+        title: '项目名称',
+        dataIndex: 'projectName',
+        align: 'center',
+        key: 'projectName',
+        scopedSlots: { customRender: 'projectName' }
+    },
+    {
+        title: '运营负责人',
+        align: 'center',
+        dataIndex: 'responsibleId_dictText'
+    },
+    {
+        title: '设计负责人',
+        align: 'center',
+        dataIndex: 'designResponsibleId_dictText'
+    },
+    {
+        title: '操作',
+        align: 'center',
+        dataIndex: 'action',
+        scopedSlots: { customRender: 'action' }
+    }
+]
+
+export default {
+    data() {
+        return {
+            columns: [...columnsFixd], //table的表头
+            columnsWhite: columnsWhite,
+            whiteVisible: false,
+            loading: false,
+            whiteLoading: false,
+            addColumns: [],
+            data: [],
+            dataWhiteList: [],
+            ipagination: {
+                current: 1,
+                pageSize: 10,
+
+                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
+                    this.handleGetTableList()
+                }
+            },
+            ipaginationWhite: {
+                current: 1,
+                pageSize: 10,
+
+                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.ipaginationWhite.current = current
+                    this.ipaginationWhite.pageSize = pageSize
+                    this.getWhiteList()
+                }
+            },
+            projectName: '',
+            whiteListRul: '/monitor/projectMonitorWhiteList/list'
+        }
+    },
+    watch: {},
+    methods: {
+        ...mapGetters(['userInfo']),
+        handleGetTableList() {
+            this.loading = true
+            getAction(this.whiteListRul).then(res => {
+                this.loading = false
+                if (res.success) {
+                    // let result = res.result
+                    // this.data.push({ ...result, key: 1 })
+                    // result.map((item, index) => {
+                    //   item.key = index
+                    // })
+                    this.data = res.result.records.map((item, index) => {
+                        return {
+                            ...item,
+                            key: index
+                        }
+                    })
+                    this.ipagination.total = res.result.total
+                } else {
+                    this.$message.error(res.message)
+                    this.loading = false
+                }
+            })
+        },
+        addWhiteOk(item) {
+            postAction('/monitor/projectMonitorWhiteList/add', { projectId: item.id, userId: this.userInfo().id }).then(
+                res => {
+                    if (res.success) {
+                        this.whiteVisible = false
+                        this.projectName = ''
+                        this.handleGetTableList()
+                    } else {
+                        this.$message.error(res.message)
+                    }
+                }
+            )
+        },
+        addWhite() {
+            this.whiteVisible = true
+            this.getWhiteList()
+        },
+        getWhiteList() {
+            const params = {
+                pageNo: this.ipaginationWhite.current,
+                pageSize: this.ipaginationWhite.pageSize,
+                projectName: this.projectName
+            }
+            this.whiteLoading = true
+            getAction('/ctop/project/getProjectList', params).then(res => {
+                this.whiteLoading = false
+                if (res.success) {
+                    this.dataWhiteList = res.result.records.map((item, index) => {
+                        return {
+                            ...item,
+                            key: index
+                        }
+                    })
+                    this.ipaginationWhite.total = res.result.total
+                } else {
+                    this.$message.error(res.message)
+                }
+            })
+        },
+        whiteListOk() {},
+        deleteWhite(id) {
+            deleteAction('/monitor/projectMonitorWhiteList/delete', { id: id }).then(res => {
+                if (res.success) {
+                    this.handleGetTableList()
+                } else {
+                    this.$message.error(res.message)
+                }
+            })
+        },
+        filterOption(input, option) {
+            return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
+        }
+    },
+
+    mounted() {
+        this.handleGetTableList()
+    }
+}
+</script>

+ 1 - 1
src/views/modules/headline-view/headline-view-server.js

@@ -5,6 +5,6 @@
 
 export const urlAcount = 'http://118.24.244.213:8808'; // 线上
 // export const urlAcount = 'http://apipre.tjyourong.com.cn'; // 预生产
-// export const urlAcount = 'http://192.168.1.43:8080'; // 子安
+// export const urlAcount = 'http://192.168.1.43:8808'; // 子安
 // export const urlAcount = 'http://139.186.165.84:8808'; // 测试
 // export const urlAcount = 'http://192.168.1.8:8080'; // 学超

+ 4 - 0
src/views/modules/material/comment/selectTable.vue

@@ -281,6 +281,10 @@ export default {
     },
     handleClose() {
       this.topMiddle = false
+      if(!!!this.projectId){
+        this.keyValue = ''
+        this.getData()
+      }
     },
     // allData() {
     //   getAction('/ctop/product/getUserProductList', {

+ 1 - 1
src/views/modules/material/videoMaterial.vue

@@ -2154,7 +2154,7 @@ a {
 		@cancel="handleRejectReasonCancel"
     >
 		<div>
-			<p v-for="(item, index) in rejectReasonList" :key="index + 1">{{index + 1}}:{{ item }}</p>
+			<p v-for="(item, index) in rejectReasonList" :key="index + 1">{{ index + 1 }}:{{ item }}</p>
 		</div>
 	</a-modal>
   </a-card>

+ 2 - 2
vue.config.js

@@ -97,7 +97,7 @@ module.exports = {
       '/jeecg-boot': {
         // target: 'http://192.168.1.8:8080', //请求本地 需要jeecg-boot后台项目  蒙蒙
         // target: 'http://192.168.1.3:8080', //请求本地 需要jeecg-boot后台项目  蒙蒙
-        // target: 'http://192.168.1.3:7001', //请求本地 需要jeecg-boot后台项目  蒙蒙
+        target: 'http://192.168.1.3:7001', //请求本地 需要jeecg-boot后台项目  蒙蒙
         // target: 'http://192.168.0.59:8088', //请求本地 需要jeecg-boot后台项目  英豪
         // target: 'http://192.168.1.62:7001', //请求本地 需要jeecg-boot后台项目  英豪
         // target: 'http://192.168.6.162:9806', //请求本地 需要jeecg-boot后台项目  祚云
@@ -108,7 +108,7 @@ module.exports = {
         // target: 'http://192.168.1.219:7701', //请求本地 需要jeecg-boot后台项目  赵西安
         // target: 'http://192.168.1.193:8080', //请求本地 需要jeecg-boot后台项目  李煜一
         // target: 'http://192.168.1.193:31012', //请求本地 需要jeecg-boot后台项目  李煜一
-        target: 'http://api.tjyourong.com.cn', //请求本地 需要jeecg-boot后台项目
+        // target: 'http://api.tjyourong.com.cn', //请求本地 需要jeecg-boot后台项目
         // 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后台项目