朱鑫波 vor 4 Jahren
Ursprung
Commit
c7f25fe25a
51 geänderte Dateien mit 14504 neuen und 660 gelöschten Zeilen
  1. 7 0
      src/api/actor.js
  2. BIN
      src/assets/img/spLbLAbh.jpg
  3. 61 0
      src/filters.js
  4. 2 2
      src/views/modules/Statistics/components/Treeselect.vue
  5. 98 50
      src/views/modules/Statistics/components/selectPagination.vue
  6. 10 2
      src/views/modules/account-config/account-config-server.js
  7. 145 52
      src/views/modules/account-config/account-config.vue
  8. 119 0
      src/views/modules/account-config/components/check-more-plat/check-more-plat.less
  9. 331 0
      src/views/modules/account-config/components/check-more-plat/check-more-plat.vue
  10. 118 10
      src/views/modules/account-config/components/configuration-modal.less
  11. 989 206
      src/views/modules/account-config/components/configuration-modal.vue
  12. 81 39
      src/views/modules/account-config/components/directional-logic/directional-logic.vue
  13. 71 0
      src/views/modules/account-config/components/tree-select/tree-select.less
  14. 126 0
      src/views/modules/account-config/components/tree-select/tree-select.vue
  15. 222 0
      src/views/modules/autoLaunch/application/application-service.js
  16. 115 0
      src/views/modules/autoLaunch/application/application.less
  17. 1134 0
      src/views/modules/autoLaunch/application/application.vue
  18. 652 0
      src/views/modules/autoLaunch/application/components/creatApplication.vue
  19. 603 0
      src/views/modules/autoLaunch/application/components/editApplication.vue
  20. 71 0
      src/views/modules/autoLaunch/application/components/tree-select.less
  21. 303 0
      src/views/modules/autoLaunch/application/components/tree-select.vue
  22. 365 0
      src/views/modules/autoLaunch/application/components/uploadFile.vue
  23. 5 3
      src/views/modules/autoLaunch/configLaunchInfo.vue
  24. 429 0
      src/views/modules/autoLaunch/directional/components/selectRegion.vue
  25. 1414 0
      src/views/modules/autoLaunch/directional/components/targetedPopulation.vue
  26. 291 0
      src/views/modules/autoLaunch/directional/components/templateModal.vue
  27. 71 0
      src/views/modules/autoLaunch/directional/components/tree-select.less
  28. 303 0
      src/views/modules/autoLaunch/directional/components/tree-select.vue
  29. 213 0
      src/views/modules/autoLaunch/directional/directional-service.js
  30. 113 0
      src/views/modules/autoLaunch/directional/directional.less
  31. 1037 0
      src/views/modules/autoLaunch/directional/directional.vue
  32. 58 0
      src/views/modules/autoLaunch/material-pool/material.vue
  33. 65 0
      src/views/modules/autoLaunch/url/components/tree-select.less
  34. 273 0
      src/views/modules/autoLaunch/url/components/tree-select.vue
  35. 213 0
      src/views/modules/autoLaunch/url/url-service.js
  36. 113 0
      src/views/modules/autoLaunch/url/url.less
  37. 984 0
      src/views/modules/autoLaunch/url/url.vue
  38. 10 2
      src/views/modules/creative-copywrit/creative-copywrit.less
  39. 527 66
      src/views/modules/creative-copywrit/creative-copywrit.vue
  40. 1 0
      src/views/modules/crowd-control/components/tree-select/tree-select.vue
  41. 47 28
      src/views/modules/crowd-control/crowd-control-service.js
  42. 5 2
      src/views/modules/crowd-control/crowd-control.less
  43. 320 138
      src/views/modules/crowd-control/crowd-control.vue
  44. 10 0
      src/views/modules/headline-view/headline-view-server.js
  45. 0 0
      src/views/modules/headline-view/headline-view.less
  46. 1742 0
      src/views/modules/headline-view/headline-view.vue
  47. 51 7
      src/views/modules/material/accountCheck.vue
  48. 3 3
      src/views/modules/material/accountCheckBytedance.vue
  49. 423 0
      src/views/modules/material/comment/selectTable.vue
  50. 155 46
      src/views/modules/material/videoMaterial.vue
  51. 5 4
      vue.config.js

+ 7 - 0
src/api/actor.js

@@ -178,6 +178,13 @@ export function fileEditUpdate(parameter) {
     })
 }
 
+export function fileEditUpdateBatch(parameter) {
+    return axios({
+        url: "/ctop/materialInfo/bytedance/batchedit",
+        method: 'put',
+        data: parameter
+    })
+}
 
 export function fileEditAll(parameter) {
     return axios({

BIN
src/assets/img/spLbLAbh.jpg


+ 61 - 0
src/filters.js

@@ -360,6 +360,67 @@ const filters = {
             4: 'iOS网页游戏'
         }
         return data[str]
+    },
+    // 人群包定向
+    customCrowdHandler(val){
+        let str=''
+        switch (val) {
+            case 1:
+                str='上传人群'
+                break;
+            case 2:
+                str='广告人群'
+                break;
+            case 3:
+                str='主题专区'
+                break;
+            case 4:
+                str='逻辑规则'
+                break;
+            case 5:
+                str='人群扩展'
+                break;
+            case 6:
+                str='平台定制'
+                break;
+            case 7:
+                str='定制付费'
+                break;
+            case 8:
+                str='网红粉丝类别'
+                break;
+            case 9:
+                str='内容付费行为'
+                break;
+            case 10:
+                str='移动应用安装'
+                break;
+            case 11:
+                str='快手使用活跃度'
+                break;
+            case 12:
+                str='行业分类'
+                break;
+            case 13:
+                str='商业兴趣'
+                break;
+            case 14:
+                str='固化标签'
+                break;
+            case 15:
+                str='行业偏好'
+                break;
+            case 16:
+                str='第三方标签'
+                break;
+            case 17:
+                str='产品关键词'
+                break;
+        
+            default:
+                break;
+        }
+        return str
     }
 
 }

+ 2 - 2
src/views/modules/Statistics/components/Treeselect.vue

@@ -201,9 +201,9 @@ export default {
                       return {
                         id: i.accountId,
                         label:
-                          (i.userName && i.userName.length == 2
+                          (i.userName&&i.userName.length == 2
                             ? i.userName + '\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0'
-                            : i.userName && i.userName.length == 3
+                            : i.userName&&i.userName.length == 3
                             ? i.userName + '\xa0\xa0\xa0\xa0'
                             : i.userName) +
                           '\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0' +

+ 98 - 50
src/views/modules/Statistics/components/selectPagination.vue

@@ -20,37 +20,68 @@
   text-align: center;
 }
 </style>
+<style lang="scss" scoped>
+.require-check {
+  /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>
   <a-form-item
     label="项目名称"
     :label-col="labelCol"
     :wrapper-col="wrapperCol"
     v-clickoutside="handleClose"
-    style="width:100%"
+    style="width: 100%"
     class="select-table"
+    :class="{ 'require-check': requireCheck }"
   >
-    <a-input placeholder="请选择项目" @focus="topMiddle = true" v-model="keyValue" @change="getData" />
+    <a-input
+      placeholder="请选择项目名称"
+      @focus="topMiddle = true"
+      v-model="keyValue"
+      @change="getData(productId)"
+      :disabled="disabled"
+    />
     <div
       v-show="topMiddle"
       v-infinite-scroll="handleInfiniteOnLoad"
-      style="background:white;padding:10px;box-shadow: 0 2px 8px 0 rgba(0,0,0,.15);position:relative;z-index:1000"
+      style="
+        background: white;
+        padding: 10px;
+        box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.15);
+        position: absolute;
+        z-index: 1000;
+        width: 100%;
+      "
       class="demo-infinite-container"
       :infinite-scroll-disabled="busy"
       :infinite-scroll-distance="80"
     >
       <a-list :data-source="data">
         <a-list-item slot="renderItem" slot-scope="item" @click="showProject(item)">
-          <a-list-item-meta :description="'广告主名称:'+item.advertiserName">
+          <a-list-item-meta :description="'广告主名称:' + item.advertiserName">
             <a slot="title">项目名称:{{ item.projectName }}</a>
           </a-list-item-meta>
           <div>
-            {{item.mediaId == '1'
-            ? '头条'
-            : item.mediaId == '2'
-            ? '快手'
-            : item.mediaId == '3'
-            ? '头条内广'
-            : '快手内广'}}
+            {{
+              item.mediaId == '1'
+                ? '头条'
+                : item.mediaId == '2'
+                ? '快手'
+                : item.mediaId == '3'
+                ? '头条内广'
+                : '快手内广'
+            }}
           </div>
         </a-list-item>
         <div v-if="loading && !busy" class="demo-loading-container">
@@ -98,7 +129,7 @@ export default {
   directives: { clickoutside, infiniteScroll },
   props: {
     projectId: {
-      type: String,
+      type: [String, Number],
       default() {
         return ''
       },
@@ -108,37 +139,55 @@ export default {
       default() {
         return ''
       },
-    }
+    },
+    labelCol: {
+      type: Object,
+      default() {
+        return {
+          xs: { span: 24 },
+          sm: { span: 5 },
+        }
+      },
+    },
+    disabled: {
+      type: Boolean,
+      default() {
+        return false
+      },
+    },
+    requireCheck: {
+      type: Boolean,
+      default() {
+        return false
+      },
+    },
   },
 
   data() {
     return {
       taobaoSpecialOfferList: {
-        advertiserId: "fd41614705a047dd65ab0e34e9150cfe",
-        advertiserName: " 淘宝(中国)软件有限公司",
-        createTime: "2021-03-03 10:15:30",
-        designResponsibleName: "辛巴特",
+        advertiserId: 'fd41614705a047dd65ab0e34e9150cfe',
+        advertiserName: ' 淘宝(中国)软件有限公司',
+        createTime: '2021-03-03 10:15:30',
+        designResponsibleName: '辛巴特',
         id: 3660879,
         maxBid: 30000,
-        mediaId: "1",
+        mediaId: '1',
         productId: 1410280,
-        productName: "头条-淘宝特价版",
+        productName: '头条-淘宝特价版',
         projectId: 1530887,
-        projectName: "头条-淘宝特价版",
-        responsibleName: "董琪",
-        roleCode: "operator",
+        projectName: '头条-淘宝特价版',
+        responsibleName: '董琪',
+        roleCode: 'operator',
         saleId: null,
         saleName: null,
-        updateTime: "2021-03-03 21:23:04",
-        userId: "a0d58df3392c4583b55ce3b041792aa7",
-        userName: "王晓娟"
+        updateTime: '2021-03-03 21:23:04',
+        userId: 'a0d58df3392c4583b55ce3b041792aa7',
+        userName: '王晓娟',
       },
+      productId: '',
       loading: false,
       busy: false,
-      labelCol: {
-        xs: { span: 24 },
-        sm: { span: 5 },
-      },
       wrapperCol: {
         xs: { span: 24 },
         sm: { span: 12 },
@@ -197,15 +246,17 @@ export default {
         return { orientationId: item.orientationId, orientationName: item.orientationName }
       })
     },
-    getData() {
-      if(this.keyValue == ''){
-        this.$emit('update:projectId', "")
+    getData(productId) {
+      this.productId = productId
+      if (this.keyValue == '') {
+        this.$emit('update:projectId', '')
       }
       this.ipagination.current = 1
       getAction('/ctop/projectMember/participateListV2', {
         userId: this.userInfo().id,
-        pageNo:  this.ipagination.current,
+        pageNo: this.ipagination.current,
         projectName: this.keyValue,
+        productId: productId?productId:'',
       }).then((res) => {
         if (res.code == 0) {
           let defaultList = res.result.records.map((item, index) => {
@@ -213,13 +264,12 @@ export default {
               ...item,
               projectId: item.projectId + '',
               key: index,
-            };
+            }
           })
           if (this.type === 'taobao') {
-            this.data = defaultList.filter(item => item.productId === 1410280);
-          }
-          else {
-            this.data = defaultList;
+            this.data = defaultList.filter((item) => item.productId === 1410280)
+          } else {
+            this.data = defaultList
           }
           // this.dataElse = res.result.records.map((item, index) => {
           //   return {
@@ -271,23 +321,21 @@ export default {
         pageSize: this.ipagination.pageSize,
         pageNo: this.ipagination.current,
         projectName: this.keyValue,
+        productId: this.productId?this.productId:null,
       }).then((res) => {
         if (res.code == 0) {
           this.busy = true
           let defaultList = res.result.records.map((item, index) => {
-              return {
-                ...item,
-                projectId: item.projectId + '',
-              }
-            })
-          this.data = data.concat(
-            
-          )
+            return {
+              ...item,
+              projectId: item.projectId + '',
+            }
+          })
+          this.data = data.concat()
           if (this.type === 'taobao') {
-            this.data = defaultList.filter(item => item.productId === 1410280);
-          }
-          else {
-            this.data = data.concat(defaultList);
+            this.data = defaultList.filter((item) => item.productId === 1410280)
+          } else {
+            this.data = data.concat(defaultList)
           }
           // this.data = res.result.records.map((item, index) => {
           //   return {

+ 10 - 2
src/views/modules/account-config/account-config-server.js

@@ -1,2 +1,10 @@
-export const urlAcount = 'http://118.24.244.213:8080';
-// export const urlAcount = 'http://192.168.1.43:8080';
+/**
+ * @file 账户配置API
+ * @author jiayufei
+ */
+
+export const urlAcount = 'http://118.24.244.213:8080'; // 线上
+// export const urlAcount = 'http://apipre.tjyourong.com.cn'; // 预生产
+// export const urlAcount = 'http://192.168.1.43:8080'; // 子安
+// export const urlAcount = 'http://139.186.165.84:8080'; // 测试
+// export const urlAcount = 'http://192.168.1.8:8080'; // 学超

+ 145 - 52
src/views/modules/account-config/account-config.vue

@@ -39,12 +39,15 @@
                         <template slot="title">
                             <span>当日花费</span>
                         </template>
-                        <a-icon type="smile-o"/>
+                        <a-icon type="question-circle"/>
                     </a-tooltip>
                 </span>
                 <span slot="acountRelax" slot-scope="text, record">
                     <a-switch :checked="text === 0" @change="handleSwitchChang($event, record)"/>
                 </span>
+                <span solt="accountBudget" slot-scope="text, record">
+                    {{ record.accountBudgetMode === '1' ? '不限' : text }}
+                </span>
                 <span slot="action" slot-scope="text, record">
                     <a @click="handleEdit(record)">编辑</a>
                     <a-divider type="vertical"/>
@@ -52,23 +55,7 @@
                     <a-divider type="vertical"/>
                     <a @click="handleUpdateMod(record)">修改出价</a>
                     <a-divider type="vertical"/>
-                    <a-popover v-model="record.show" trigger="click">
-                        <template slot="content">
-                            <div><a-input v-model="budgetContent" placeholder="请输入" style="width: 140px;"/></div>
-                            <div style="margin-top: 10px;">
-                                <a-button
-                                    size="small"
-                                    type="primary"
-                                    style="margin-left: 15px;margin-right: 15px;"
-                                    @click="handlePopoverSure(record, 'budget')"
-                                >
-                                    确定
-                                </a-button>
-                                <a-button size="small" @click="handleBudgetPopover(record)">取消</a-button>
-                            </div>
-                        </template>
-                        <a>修改预算</a>
-                    </a-popover>
+                    <a @click="handleUpdateBudget(record)">修改预算</a>
                 </span>
             </a-table>
             <a-pagination
@@ -83,6 +70,45 @@
             />
         </div>
         <a-modal
+            title="修改预算"
+            v-if="budgetVisible"
+            :visible="budgetVisible"
+            dialog-class="mode-modal-class"
+            @ok="handleBudgetSure"
+            @cancel="handleBudgetCancel"
+        >
+            <div>
+                <a-form-model
+                    ref="budgetForm"
+                    :model="budgetForm"
+                    :rules="budgetRules"
+                    :label-col="labelCol"
+                    :wrapper-col="wrapperCol"
+                >
+                    <a-form-model-item label="预算方式">
+                        <a-radio-group
+                            v-model="budgetForm.budgetType"
+                            button-style="solid"
+                            @change="handleAccountMode"
+                        >
+                            <a-radio-button value="1">不限预算</a-radio-button>
+                            <a-radio-button value="2">指定预算</a-radio-button>
+                        </a-radio-group>
+                    </a-form-model-item>
+                    <a-form-model-item v-if="budgetForm.budgetType === '2'" label="账户日预算" prop="budget">
+                        <a-input-number
+                            v-model="budgetForm.budget"
+                            :min="1000"
+                            :max="9999999.99"
+                            :step="0.01"
+                            @blur="handleAccountBudget"
+                        /> 元
+                    </a-form-model-item>
+                    <!-- <div v-if="adBudgetShowTitle" style="width: 500px;color: #f00;margin-left: 140px;">单次修改预算幅度, 不能低于100.0元</div> -->
+                </a-form-model>
+            </div>
+        </a-modal>
+        <a-modal
             title="修改出价"
             v-if="modeVisible"
             :visible="modeVisible"
@@ -115,6 +141,7 @@
                                 v-model="configForm.adMinBid"
                                 :min="0.1"
                                 :max="10000"
+                                :step="0.01"
                                 placeholder="请输入最小值"
                             />
                         </a-form-model-item>
@@ -125,6 +152,7 @@
                                 v-model="configForm.adMaxBid"
                                 :min="0.1"
                                 :max="10000"
+                                :step="0.01"
                                 placeholder="请输入最大值"
                             />
                         </a-form-model-item>
@@ -136,6 +164,7 @@
                                 v-model="configForm.adMinBid"
                                 :min="0.1"
                                 :max="10000"
+                                :step="0.01"
                                 placeholder="请输入最小值"
                             />
                         </a-form-model-item>
@@ -146,12 +175,15 @@
                                 v-model="configForm.adMaxBid"
                                 :min="0.1"
                                 :max="10000"
+                                :step="0.01"
                                 placeholder="请输入最大值"
                             />
                         </a-form-model-item>
                         <a-form-model-item label="浮动间隔" prop="adStepBid">
                             <a-input-number
                                 class="common-input"
+                                :min="0"
+                                :step="0.01"
                                 v-model="configForm.adStepBid"
                                 placeholder="请输入浮动间隔"
                             />
@@ -177,32 +209,72 @@ export default {
     data() {
         let adMinBidValidator = (rule, value, callback) => {
             const finallyResult = Number(this.configForm.adMaxBid);
-            if (finallyResult !== '' && value && Number(value) < finallyResult) {
+            if (finallyResult !== '' && value && Number(value) <= finallyResult) {
                 callback();
             }
             else {
                 callback('最低出价不能高于最高出价');
             }
         };
+        let adCpaBidValidator = (rule, value, callback) => {
+            if (Number(this.updateModTxt.adBudget) < Number(value)) {
+                callback('出价不能大于预算');
+            }
+            else {
+                callback();
+            }
+        };
         let adMaxBidValidator = (rule, value, callback) => {
             const finallyResult = Number(this.configForm.adMinBid);
-            if (finallyResult !== undefined && value && Number(value) > finallyResult) {
+            if (finallyResult && value && Number(value) <= finallyResult) {
+                callback('最高出价不能低于最低出价');
+            }
+            else if (Number(this.updateModTxt.adBudget) < Number(value)) {
+                callback('出价不能大于预算');
+            }
+            else if (Number(this.configForm.adMaxBid) > Number(this.configForm.adMinBid) + Number(this.configForm.adStepBid)) {
+                this.$refs['ruleForm'].clearValidate(['adStepBid']);
                 callback();
             }
             else {
-                callback('最高出价不能低于最低出价');
+                this.$refs['ruleForm'].clearValidate(['adMinBid']);
+                callback();
             }
         };
         let floatingIntervalValidator = (rule, value, callback) => {
             const finallyResult = Number(this.configForm.adMinBid) + Number(value);
-            if (finallyResult !== undefined < Number(this.configForm.adMaxBid)) {
+            if (finallyResult < Number(this.configForm.adMaxBid)) {
                 callback();
             }
             else {
                 callback('最低出价+浮动间隔<最高出价');
             }
         };
+        let budgetValidator = (rule, value, callback) => {
+            const changeBudget = this.updateModTxt.accountBudget;
+            if (Number(value) > Number(changeBudget) && Number(value) < (Number(changeBudget) + 100)) {
+                callback('单次修改预算幅度, 不能低于100.0元');
+            }
+            else if (Number(value) < Number(changeBudget) && Number(value) > (Number(changeBudget) - 100)) {
+                callback('单次修改预算幅度, 不能低于100.0元');
+            }
+            else {
+                callback();
+            }
+        };
         return {
+            adBudgetShowTitle: false,
+            budgetVisible: false,
+            budgetForm: {
+                budgetType: '1',
+                budget: 0
+            },
+            budgetRules: {
+                budget: [
+                    {required: true, message: '请输入', trigger: 'blur'},
+                    {validator: budgetValidator, trigger: 'blur'}
+                ]
+            },
             labelCol: {span: 4},
             wrapperCol: {span: 14},
             configForm: {
@@ -213,7 +285,8 @@ export default {
             },
             rules: {
                 adCpaBid: [
-                    {required: true, message: '请输入', trigger: 'blur'}
+                    {required: true, message: '请输入', trigger: 'blur'},
+                    {validator: adCpaBidValidator, trigger: 'blur'}
                 ],
                 adStepBid: [
                     {required: true, message: '请输入', trigger: 'blur'},
@@ -267,8 +340,9 @@ export default {
                     align: 'center'
                 },
                 {
-                    title: '账户日预算量(元)',
-                    dataIndex: 'adBudget',
+                    title: '账户日预算(元)',
+                    dataIndex: 'accountBudget',
+                    width: 180,
                     align: 'center'
                 },
                 {
@@ -279,12 +353,14 @@ export default {
                 {
                     align: 'center',
                     dataIndex: 'cost',
+                    width: 150,
                     slots: {title: 'customTitle'}
                 },
                 {
                     title: '操作',
                     dataIndex: 'action',
                     align: 'center',
+                    width: '20%',
                     scopedSlots: {customRender: 'action'}
                 }
             ]
@@ -298,6 +374,14 @@ export default {
     },
     methods: {
         ...mapGetters(['nickname', 'avatar', 'userInfo']),
+        handleAccountMode(e) {
+            this.budgetForm.budget = 1000;
+            this.adBudgetShowTitle = false;
+        },
+        handleAccountBudget(e) {
+            const adBudgetInput = e.target.value;
+            this.budgetForm.budget = Number(Number(adBudgetInput).toFixed(2));
+        },
         handleModeSure() {
             let paramsData = new FormData();
             if (this.updateModTxt.adBidCreateType === 'FIX') {
@@ -337,39 +421,43 @@ export default {
         },
         handleUpdateMod(record) {
             this.updateModTxt = record;
+            this.configForm.adCpaBid = record.adCpaBid;
+            this.configForm.adMinBid = record.adMinBid;
+            this.configForm.adMaxBid = record.adMaxBid;
+            this.configForm.adStepBid = record.adStepBid;
             this.modeVisible = true;
         },
-        handlePopoverSure(record, type) {
-            const defaultList = {
-                accountId: record.accountId,
-                bid: this.modContent,
-                budget: this.budgetContent,
-                adId: record.adId ? record.adId : '',
-                id: record.id,
-                cost: record.cost
-            };
+        handleUpdateBudget(record) {
+            this.updateModTxt = record;
+            this.budgetForm.budgetType = record.accountBudgetMode;
+            this.budgetForm.budget = record.accountBudget;
+            this.budgetVisible = true;
+        },
+        handleBudgetSure() {
             let paramsData = new FormData();
-            if (type === 'mod') {
+            paramsData.append('accountId', this.updateModTxt.accountId);
+            paramsData.append('adId', this.updateModTxt.adId);
+            paramsData.append('type', 2);
+            paramsData.append('budget', this.budgetForm.budget);
+            paramsData.append('budgetType', this.budgetForm.budgetType);
+            paramsData.append('id', this.updateModTxt.id);
+            paramsData.append('cost', this.updateModTxt.cost);
+            if (this.adBudgetShowTitle) {
+                return;
             }
-            else if (type === 'budget') {
-                if (Number(defaultList.budget) >= record.adBudget && Number(defaultList.budget) < (record.adBudget + 100)) {
-                    this.$message.error('单次修改预算幅度, 不能低于100.0元');
-                    return;
+            this.$refs.budgetForm.validate(valid => {
+                if (valid) {
+                    this.handlePopoverChange(paramsData);
                 }
-                if (Number(defaultList.budget) <= record.adBudget && Number(defaultList.budget) > (record.adBudget - 100)) {
-                    this.$message.error('单次修改预算幅度, 不能低于100.0元');
-                    return;
+                else {
+                    console.log('error submit!!');
+                    return false;
                 }
-                record.show = false;
-                this.budgetContent = '';
-                paramsData.append('accountId', defaultList.accountId);
-                paramsData.append('adId', defaultList.adId);
-                paramsData.append('type', 2);
-                paramsData.append('budget', defaultList.budget);
-                paramsData.append('id', defaultList.id);
-                paramsData.append('cost', defaultList.cost);
-            }
-            this.handlePopoverChange(paramsData);
+            });
+        },
+        handleBudgetCancel() {
+            this.budgetVisible = false;
+            this.budgetForm.budgetType = '1';
         },
         handlePopoverChange(data) {
             putAction(urlAcount + '/bytedance-api/advertiser/aiBytedanceAdvertiserStrategy/updStaOrCpaOrBudgetById', data).then(result => {
@@ -380,6 +468,8 @@ export default {
                     this.adStepBid = undefined;
                     this.adCpaBid = undefined;
                     this.modeVisible = false;
+                    this.budgetVisible = false;
+                    this.budgetForm.budgetType = '1';
                     this.handleInitTable();
                 }
                 else {
@@ -405,6 +495,9 @@ export default {
                     result.result.records.forEach(item => {
                         item.show = false;
                         item.visible = false;
+                        if (item.accountBudgetMode === '1') {
+                            item.accountBudget = '不限';
+                        }
                     });
                     this.dataSource = result.result.records;
                     this.totalAll = result.result.total;

+ 119 - 0
src/views/modules/account-config/components/check-more-plat/check-more-plat.less

@@ -0,0 +1,119 @@
+.ul-radio-group {
+    border-radius: 5px;
+    height: 32px;
+    padding: 0;
+    margin: 0;
+    border: none;
+    background: transparent;
+    .btn {
+        background: transparent;
+        padding: 0;
+        margin: 0;
+        border: none;
+    }
+    .item {
+        min-width: 80px;
+        padding: 0px 15px;
+        text-align: center;
+        display: inline-block;
+        border: 1px solid #ccc;
+        border-left: 0;
+        height: 32px;
+        line-height: 32px;
+        cursor: pointer;
+        .checkbox-button-input {
+            width: 0;
+            height: 0;
+            opacity: 0;
+        }
+        .ant-checkbox {
+            display: none;
+        }
+    }
+    .bgcolor {
+        color: rgba(0, 0, 0, 0.25);
+        background-color: #f5f5f5;
+        border-color: #d9d9d9;
+        cursor: not-allowed;
+    }
+    .item::after {
+        content: '';
+        position: absolute;
+        right: 1px;
+        top: -2px;
+        width: 0;
+        height: 0;
+        border-top: 6px solid transparent;
+        border-bottom: 6px solid transparent;
+        border-left: 6px solid;
+        border-left-color: #e0e0e0;
+        -webkit-transform: rotate(-45deg);
+        -ms-transform: rotate(-45deg);
+        transform: rotate(-45deg);
+        border-radius: 2px;
+    }
+    .item:hover {
+        color: #1890ff;
+    }
+    .selection {
+        color: #fff;
+        background: #1890ff;
+    }
+    .item.selection:hover {
+        color: #fff;
+        background: #40a9ff;
+    }
+    .item.selection:after {
+        border-left: 6px solid #1890ff;
+    }
+    .item:hover::after {
+        border-left: 6px solid #40a9ff;
+    }
+    .bgcolor:hover {
+        color: rgba(0, 0, 0, 0.25);
+        background-color: #f5f5f5;
+        border-color: #d9d9d9;
+        cursor: not-allowed;
+    }
+    .bgcolor:hover::after {
+        border-left: 6px solid #e0e0e0;
+    }
+    .bgcolor.selection:after {
+        border-left: 6px solid #e0e0e0;
+    }
+    .bgcolor.selection {
+        color: rgba(0, 0, 0, 0.25);
+        background-color: #f5f5f5;
+        border-color: #d9d9d9;
+        cursor: not-allowed;
+    }
+    .bgcolor.selection:hover {
+        color: rgba(0, 0, 0, 0.25);
+        background-color: #f5f5f5;
+        border-color: #d9d9d9;
+        cursor: not-allowed;
+    }
+    .bgcolor.selection:after {
+        border-left: 6px solid #e0e0e0;
+    }
+    .ant-checkbox-wrapper + .ant-checkbox-wrapper {
+        margin-left: 0;
+    }
+}
+.ul-radio-group .item:first-child {
+    border-radius: 5px 0 0 5px;
+    border-left: 1px solid #ccc;
+}
+.ul-radio-group .item.selection:first-child {
+    border-radius: 5px 0 0 5px;
+    border-left: 1px solid #1890ff;
+}
+.ul-radio-group .item.selection:nth-child(2) {
+    border-left: 1px solid #1890ff;
+}
+.ul-radio-group .item:first-child:after {
+    border-left: 0;
+}
+.ul-radio-group .item:last-child {
+    border-radius: 0px 5px 5px 0px;
+}

+ 331 - 0
src/views/modules/account-config/components/check-more-plat/check-more-plat.vue

@@ -0,0 +1,331 @@
+<style lang="scss">
+.ul-radio-group {
+  border-radius: 5px;
+  height: 32px;
+  padding: 0;
+  margin: 0;
+  border: none;
+  background: transparent;
+
+  .btn {
+    background: transparent;
+    padding: 0;
+    margin: 0;
+    border: none;
+  }
+  .item {
+    min-width: 80px;
+    padding: 0px 15px;
+    text-align: center;
+    display: inline-block;
+    border: 1px solid #ccc;
+    border-left: 0;
+    height: 32px;
+    line-height: 32px;
+    cursor: pointer;
+    .checkbox-button-input {
+      width: 0;
+      height: 0;
+      opacity: 0;
+    }
+    .ant-checkbox {
+      display: none;
+    }
+  }
+  .bgcolor {
+    color: rgba(0, 0, 0, 0.25);
+    background-color: #f5f5f5;
+    border-color: #d9d9d9;
+    cursor: not-allowed;
+  }
+  .item::after {
+    content: '';
+    position: absolute;
+    right: 1px;
+    top: -2px;
+    width: 0;
+    height: 0;
+    border-top: 6px solid transparent;
+    border-bottom: 6px solid transparent;
+    border-left: 6px solid;
+    border-left-color: #e0e0e0;
+    -webkit-transform: rotate(-45deg);
+    -ms-transform: rotate(-45deg);
+    transform: rotate(-45deg);
+    border-radius: 2px;
+  }
+  .item:hover {
+    color: #1890ff;
+  }
+  .selection {
+    color: #fff;
+    background: #1890ff;
+    // border-color: #1890ff;
+  }
+  .item.selection:hover {
+    color: #fff;
+    background: #40a9ff;
+  }
+  .item.selection:after {
+    border-left: 6px solid #1890ff;
+  }
+  .item:hover::after {
+    // border-color: #40a9ff;
+    border-left: 6px solid #40a9ff;
+  }
+  .bgcolor:hover {
+    color: rgba(0, 0, 0, 0.25);
+    background-color: #f5f5f5;
+    border-color: #d9d9d9;
+    cursor: not-allowed;
+  }
+  .bgcolor:hover::after {
+    // border-color: #40a9ff;
+    border-left: 6px solid #e0e0e0;
+  }
+  .bgcolor.selection:after {
+    border-left: 6px solid #e0e0e0;
+  }
+  .bgcolor.selection {
+    color: rgba(0, 0, 0, 0.25);
+    background-color: #f5f5f5;
+    border-color: #d9d9d9;
+    cursor: not-allowed;
+  }
+  .bgcolor.selection:hover {
+    // color: #1890ff;
+    color: rgba(0, 0, 0, 0.25);
+    background-color: #f5f5f5;
+    border-color: #d9d9d9;
+    cursor: not-allowed;
+  }
+  .bgcolor.selection:after {
+    border-left: 6px solid #e0e0e0;
+  }
+  .ant-checkbox-wrapper + .ant-checkbox-wrapper {
+    margin-left: 0;
+  }
+}
+.ul-radio-group .item:first-child {
+  border-radius: 5px 0 0 5px;
+  border-left: 1px solid #ccc;
+}
+.ul-radio-group .item.selection:first-child {
+  border-radius: 5px 0 0 5px;
+  border-left: 1px solid #1890ff;
+}
+.ul-radio-group .item.selection:nth-child(2) {
+  border-left: 1px solid #1890ff;
+}
+.ul-radio-group .item:first-child:after {
+  border-left: 0;
+}
+.ul-radio-group .item:last-child {
+  border-radius: 0px 5px 5px 0px;
+}
+</style>
+<template>
+    <div class="ul-radio-group">
+        <a-checkbox-group v-model="selectedVal" :disabled="disabled" style="width: 100%">
+            <a-checkbox
+                v-for="item of selectOption"
+                :label="item.label"
+                :key="item.value"
+                :value="item.value"
+                :class="{
+                    item: true && userButton,
+                    selection: selectedVal && selectedVal.indexOf(item.value) > -1 && userButton,
+                    bgcolor: item.disabled
+                }"
+            >
+                {{ item.label }}
+            </a-checkbox>
+        </a-checkbox-group>
+    </div>
+</template>
+<script>
+import {isArray} from '@/utils/Tools';
+import {getAction } from '@/api/manage';
+export default {
+    name: 'check-more-plat',
+    props: {
+        userButton: {
+            type: Boolean,
+            default() {
+                return true
+            }
+        },
+        code: {
+            // 参数code
+            type: String,
+            default: ''
+        },
+        allValue: {
+            type: Boolean,
+            default() {
+                return false
+            }
+        },
+        options: {
+            // 外部传入的option 可替代请求项
+            type: Array,
+            default() {
+                return []
+            }
+        },
+        value: {
+            // v-model绑定值
+            type: [Number, Array, String],
+            default() {
+                return []
+            }
+        },
+        label: {
+            // label 绑定值
+            type: [Array, String],
+            default: ''
+        },
+        radioStyle: {
+            // 是否复选框模拟单选效果
+            type: Boolean,
+            default: false
+        },
+        disabled: {
+            // 是否禁用
+            type: Boolean,
+            default: false
+        }
+    },
+    data() {
+        return {
+            selectOption: []
+        }
+    },
+    watch: {
+        options(val) {
+            if (isArray(val)) {
+                this.selectOption.splice(0, this.selectOption.length);
+                this.selectOption.push(...val);
+            }
+        },
+        selectedVal(n, o) {
+            if (this.radioStyle && !this.allValue) {
+                if (n.length == 0) {
+                this.selectedVal = o;
+                }
+            }
+        }
+    },
+    computed: {
+        selectedVal: {
+            get: function () {
+                return this.value;
+            },
+            set: function (val) {
+                this.selectChange(val);
+            }
+        }
+    },
+    mounted() {
+        this.$nextTick(() => {
+            if (this.code && this.options.length == 0) {
+                // 如果code值不为空且options.lengt==0, 则去请求字典项
+                this.getOptions();
+            }
+            else {
+                // 否则直接获取外部传入的options
+                this.selectOption.splice(0, this.selectOption.length);
+                this.selectOption.push(...this.options);
+            }
+        });
+    },
+  methods: {
+    getOptions() {
+        // 获取字典项
+        getAction('/sys/dictItem/list', { dictId: this.code, pageSize: 1000, pageNo: 1 }).then((res) => {
+            if (res.success && isArray(res.result.records)) {
+                var data = res.result.records;
+                data = data.map((item) => {
+                    return {
+                        label: item.itemText,
+                        value: item.itemValue,
+                        ...item
+                    };
+                });
+                if (this.allValue) {
+                    data.unshift({ label: '不检查', value: 'unlimited' });
+                    if (this.value == '' || this.value == '' || this.value == null || this.value.length == 0) {
+                        this.selectedVal = ['unlimited'];
+                    };
+                }
+                else {
+                    if (this.value == '' || this.value == '' || this.value == null || this.value.length == 0) {
+                        this.selectedVal = [];
+                    }
+                }
+                this.selectOption.push(...data);
+            }
+        });
+    },
+    selectChange(val) {
+        // 选择事件
+        if (!this.radioStyle) {
+            // 多选
+            var retrunData = [];
+            let label = this.selectOption.filter((v) => val.findIndex((item) => item == v.value) > -1).map((v) => v.label);
+            if (this.allValue) {
+                if (val.findIndex((item) => item == 'unlimited') == 0) {
+                    retrunData = val.slice(-1);
+                }
+                else if (val.findIndex((item) => item == 'unlimited') == val.length - 1) {
+                    retrunData = ['unlimited'];
+                }
+                else {
+                    retrunData = val;
+                }
+            }
+            else {
+                retrunData = val;
+            }
+            this.$emit('input', retrunData);
+            this.$emit('update:label', label);
+            this.$emit('change', val);
+        }
+        else {
+            // 模拟单选radio效果
+            let selectVal = [];
+            if (this.allValue) {
+                if (val.length == 0) {
+                    selectVal = ['unlimited'];
+                }
+            }
+            else {
+                if (val.length == 0) {
+                    selectVal = [];
+                }
+            }
+            if (val.length > 0) {
+                selectVal = val.slice(-1);
+            }
+            let label = this.selectOption
+            .filter((v) => selectVal.findIndex((item) => item == v.value) > -1)
+            .map((v) => v.label);
+            this.$emit('input', selectVal);
+            this.$emit('update:label', label);
+            this.$emit('change', selectVal);
+        }
+    },
+    emitChange(...args) {
+        // emit change事件
+        this.$emit('change', ...args);
+    },
+    consoleFun(...args) {
+        // 打印信息
+        if (process.env.NODE_ENV == 'development') {
+            console.log(...args);
+        }
+    }
+  }
+}
+</script>
+

+ 118 - 10
src/views/modules/account-config/components/configuration-modal.less

@@ -15,6 +15,11 @@
                 margin-right: 20px;
             }
         }
+        .form-itrm-icon {
+            position: absolute;
+            top: 3px;
+            left: -175px;
+        }
         .separate-title-header {
             font-size: 22px;
             font-weight: bold;
@@ -32,6 +37,7 @@
             margin-bottom: 15px;
             .select-orientation-content {
                 margin-left: 198px;
+                margin-top: 20px;
                 width: 440px;
                 border: 1px solid #eee;
                 height: 300px;
@@ -53,12 +59,20 @@
                 }
                 .orientation-content-substance {
                     height: 310px;
-                    margin: 12px;
+                    overflow-y: auto;
+                    margin: 10px;
                     .content-substance-singal {
-                        height: 28px;
-                        line-height: 28px;
+                        display: flex;
+                        margin-top: 10px;
                         .singal-spn {
                             margin-right: 10px;
+                            display: inline-block;
+                            width: 80px;
+                            text-align: right;
+                        }
+                        .singal-content {
+                            display: inline-block;
+                            width: 80%;
                         }
                     }
                 }
@@ -67,6 +81,29 @@
                 margin-left: 40px !important;
             }
             .select-orientation-class {
+                // /deep/ .ant-select-selection--single .ant-select-selection__rendered {
+                //     display: flex;
+                //     justify-content: space-between;
+                // }
+                // /deep/ .ant-select-selection-selected-value {
+                //     clear: both;
+                //     width: 320px;
+                // }
+                .orient-list {
+                    display: flex;
+                    justify-content: space-between;
+                    width: 240px;
+                    .orient-option-left {
+                        float: left;
+                        // width: 150px;
+                        // white-space: nowrap;
+                        // overflow: hidden;
+                        // text-overflow: ellipsis;
+                    }
+                    .orient-option-right {
+                        float: right;
+                    }
+                }
                 .ant-form-item-label {
                     width: 200px;
                 }
@@ -107,7 +144,7 @@
                 display: inline-block;
                 .ant-form-item-label {
                     width: 160px;
-                    margin-left: 73px;
+                    margin-left: 53px;
                 }
                 .ant-form-item-control-wrapper {
                     width: 110px;
@@ -178,12 +215,6 @@
             .acount-search-class {
                 width: 350px;
             }
-            
-            .form-itrm-icon {
-                position: absolute;
-                top: 3px;
-                left: -175px;
-            }
             .advers-title-class {
                 margin-left: 10px;
                 margin-right: 15px;
@@ -203,11 +234,34 @@
             .adver-position-radio {
                 margin-left: 140px;
                 margin-bottom: 15px;
+                .create-web-url-class {
+                    width: 320px;
+                    height: 110px;
+                    background-color: #f9f8f8;
+                    display: flex;
+                    .web-url-img {
+                        width: 53px;
+                        img {
+                            width: 100%;
+                        }
+                    }
+                    .web-url-content {
+                        margin-top: 10px;
+                        margin-left: 10px;
+                        .url-content-id {
+                            margin-top: 10px;
+                        }
+                    }
+                }
                 .creative-label-content {
                     width: 400px;
                     height: 200px;
                     padding: 10px;
                     border: 1px solid #eee;
+                    .label-content-select-tag {
+                        height: 80%;
+                        overflow: auto;
+                    }
                     .tag-select-class {
                         margin-bottom: 15px;
                     }
@@ -234,4 +288,58 @@
             }
         }
     }
+}
+.web-url-modal {
+    width: 1000px !important;
+    .mater-viedo-content {
+        .viedo-header-class {
+            display: flex;
+            justify-content: space-between;
+            border-bottom: 1px solid #eee;
+            .refush-btn-mat {
+                margin-left: 20px;
+            }
+        }
+        .viedo-serach-class {
+            margin-top: 20px;
+        }
+        .viedo-content-class {
+            .viedo-content-group {
+                display: flex;
+                flex-wrap: wrap;
+            }
+            .no-data-group {
+                height: 200px;
+                line-height: 200px;
+                text-align: center;
+            }
+            .content-modal-li {
+                border: 1px solid #e4e4e4;
+                width: 180px;
+                height: 425px;
+                text-align: center;
+                position: relative;
+                margin: 0 10px 10px 0;
+                .checkbox-select-show,
+                .checkbox-select-time {
+                    text-align: left;
+                    margin-top: 14px;
+                    padding-left: 10px;
+                    white-space: nowrap;
+                    overflow: hidden;
+                    text-overflow: ellipsis;
+                }
+                img {
+                    width: 90%;
+                    margin-top: 20px;
+                }
+                .viedo-content-checkbox {
+                    position: absolute;
+                    z-index: 100;
+                    left: 0;
+                    top: 0;
+                }
+            }
+        }
+    }
 }

Datei-Diff unterdrückt, da er zu groß ist
+ 989 - 206
src/views/modules/account-config/components/configuration-modal.vue


+ 81 - 39
src/views/modules/account-config/components/directional-logic/directional-logic.vue

@@ -4,7 +4,7 @@
             <div class="select-class-left">
                 <a-tabs v-model="selectPackageTabs" @change="handleTabsChange">
                     <a-tab-pane key="1" tab="定向池">
-                        <a-input-search class="input-search" v-model="directInput" placeholder="请输入账户名或ID" @change="handleSearchPack($event, 'all', 'direct')" />
+                        <a-input-search class="input-search" v-model="directInput" placeholder="请输入人群包名称" @change="handleSearchPack($event, 'all', 'direct')" />
                         <a-table
                             :columns="columns"
                             :data-source="tableDataAllDirect"
@@ -18,7 +18,7 @@
                         </a-table>
                     </a-tab-pane>
                     <a-tab-pane key="2" tab="排除池">
-                        <a-input-search class="input-search" v-model="excludeInput" placeholder="请输入账户名或ID" @change="handleSearchPack($event, 'all', 'exclude')" />
+                        <a-input-search class="input-search" v-model="excludeInput" placeholder="请输入人群包名称" @change="handleSearchPack($event, 'all', 'exclude')" />
                         <a-table
                             :columns="columns"
                             :data-source="tableDataAllExclude"
@@ -38,7 +38,7 @@
                     已选<span class="clear-all-tab"><a @click="handleDelAloneAll('all')">清空</a></span>
                 </div>
                 <div class="class-left-content">
-                    <a-tabs v-model="selectAllRightTabs">
+                    <a-tabs v-model="selectAllRightTabs" @change="handleSelectAllTabs">
                         <a-tab-pane key="3">
                             <span slot="tab">
                                 定向({{ tableSelectDirectIds.length || 0 }})
@@ -82,7 +82,7 @@
             </div>
         </div>
         <div v-else>
-            <a-input-search class="input-search" v-model="aloneInput" placeholder="请输入账户名或ID" @change="handleSearchPack($event, 'alone')" />
+            <a-input-search class="input-search" v-model="aloneInput" placeholder="请输入人群包名称" @change="handleSearchPack($event, 'alone')" />
             <div class="tree-select-class">
                 <div class="select-class-left">
                     <a-table
@@ -133,6 +133,10 @@ export default {
             type: String,
             default: ''
         },
+        valueids: {
+            type: String,
+            default: ''
+        },
         defaultlist: {
             type: Array,
             default: () => {
@@ -255,6 +259,7 @@ export default {
                     console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
                     this.tableSelectDirectIds = selectedRows && selectedRows.map(item => item.key);
                     this.tableSelectDirectData = selectedRows;
+                    this.$emit('selection-direct-event', this.tableSelectDirectIds);
                 },
                 selectedRowKeys: this.tableSelectDirectIds,
                 getCheckboxProps: record => ({
@@ -272,6 +277,7 @@ export default {
                     console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
                     this.tableSelectExcludeIds = selectedRows && selectedRows.map(item => item.key);
                     this.tableSelectExcludeData = selectedRows;
+                    this.$emit('selection-exclude-event', this.tableSelectExcludeIds);
                 },
                 selectedRowKeys: this.tableSelectExcludeIds,
                 getCheckboxProps: record => ({
@@ -298,7 +304,6 @@ export default {
         // },
         defaultlist(newVal) {
             if (newVal) {
-                console.log(newVal, '----newVal--val');
                 this.tableDataAllDirect = newVal;
                 this.updateTableAllDirect = newVal;
                 this.tableDataAllExclude = newVal;
@@ -308,7 +313,6 @@ export default {
             }
         },
         packtype(newVal, oldVal) {
-            console.log(newVal, 'new--new');
             if (newVal === 'directional') {
                 this.tableSelectIds = [];
                 this.selectRightData = [];
@@ -338,29 +342,52 @@ export default {
         this.updateTableAllExclude = this.defaultlist;
         this.tableDataAlone = this.defaultlist;
         this.updateTreeDataAlone = this.defaultlist;
-        
-        console.log(this.updateTableAllDirect, 'this.updateTableAllDirect');
-        console.log(this.updatelistinclude, this.updatelistexclude, '--00--00--00--0--555555');
-        if (this.updatelistinclude.length && this.updatelistexclude.length) {
-            this.tableSelectDirectIds = [...this.updatelistinclude];
-            this.tableSelectExcludeIds = [...this.updatelistexclude];
-            this.updateTableAllDirect.forEach(item => {
-                this.updatelistinclude.forEach(val => {
-                    if (item.key === val) {
-                        this.tableSelectDirectData.push(item);
-                    }
+
+        if (this.valueids === '3') {
+            if (this.updatelistinclude.length && this.updatelistexclude.length) {
+                this.tableSelectDirectIds = [...this.updatelistinclude];
+                this.tableSelectExcludeIds = [...this.updatelistexclude];
+                this.updateTableAllDirect.forEach(item => {
+                    this.updatelistinclude.forEach(val => {
+                        if (item.key === val) {
+                            this.tableSelectDirectData.push(item);
+                        }
+                    });
                 });
-            });
-            this.updateTableAllExclude.forEach(item => {
-                this.updatelistexclude.forEach(val => {
-                    if (item.key === val) {
-                        this.tableSelectExcludeData.push(item);
-                    }
+                this.updateTableAllExclude.forEach(item => {
+                    this.updatelistexclude.forEach(val => {
+                        if (item.key === val) {
+                            this.tableSelectExcludeData.push(item);
+                        }
+                    });
                 });
-            });
+            }
+            else if (this.updatelistexclude.length && !this.updatelistinclude.length) {
+                this.tableSelectExcludeIds = [...this.updatelistexclude];
+                this.selectPackageTabs = '2';
+                this.selectAllRightTabs = '4';
+                this.updateTableAllExclude.forEach(item => {
+                    this.updatelistexclude.forEach(val => {
+                        if (item.key === val) {
+                            this.tableSelectExcludeData.push(item);
+                        }
+                    });
+                });
+            }
+            else if (!this.updatelistexclude.length && this.updatelistinclude.length) {
+                this.tableSelectDirectIds = [...this.updatelistinclude];
+                this.selectPackageTabs = '1';
+                this.selectAllRightTabs = '3';
+                this.updateTableAllDirect.forEach(item => {
+                    this.updatelistinclude.forEach(val => {
+                        if (item.key === val) {
+                            this.tableSelectDirectData.push(item);
+                        }
+                    });
+                });
+            }
         }
-        else if (this.updatelistinclude.length && !this.updatelistexclude.length) {
-            console.log(11111);
+        else if (this.valueids === '1') {
             this.tableSelectIds = [...this.updatelistinclude];
             this.updateTableAllDirect.forEach(item => {
                 this.updatelistinclude.forEach(val => {
@@ -370,8 +397,7 @@ export default {
                 });
             });
         }
-        else if (!this.updatelistinclude.length && this.updatelistexclude.length) {
-            console.log(222222);
+        else if (this.valueids === '2') {
             this.tableSelectIds = [...this.updatelistexclude];
             this.updateTableAllDirect.forEach(item => {
                 this.updatelistexclude.forEach(val => {
@@ -380,11 +406,24 @@ export default {
                     }
                 });
             });
-            console.log(this.selectRightData, 'this.selectRightData--this.selectRightData');
         }
     },
     methods: {
+        handleSelectAllTabs(e) {
+            if (e === '3') {
+                this.selectPackageTabs = '1';
+            }
+            else if (e === '4') {
+                this.selectPackageTabs = '2';
+            }
+        },
         handleTabsChange(e) {
+            if (e === '1') {
+                this.selectAllRightTabs = '3';
+            }
+            else if (e === '2') {
+                this.selectAllRightTabs = '4';
+            }
             this.tableDataAllDirect = [];
             this.tableDataAllExclude = [];
             this.directInput = '';
@@ -431,32 +470,25 @@ export default {
             this.selectRightData = selectedRows;
             this.$emit('selection-alone-event', selectedRowKeys);
         },
-        handleSelectionDirect(selectedRowKeys, selectedRows) {
-            this.tableSelectDirectIds = selectedRowKeys;
-            this.tableSelectDirectData = selectedRows;
-            this.$emit('selection-direct-event', selectedRowKeys);
-        },
-        handleSelectionExclude(selectedRowKeys, selectedRows) {
-            this.tableSelectExcludeIds = selectedRowKeys;
-            this.tableSelectExcludeData = selectedRows;
-            this.$emit('selection-exclude-event', selectedRowKeys);
-        },
         handleDelTree(list, type, style) {
             if (type === 'alone') {
                 let formData = this.selectRightData;
                 this.selectRightData = formData.filter(item => list.key !== item.key);
                 this.tableSelectIds = this.selectRightData.map(item => item.key);
+                this.$emit('clear-table-alone', this.tableSelectIds);
             }
             else if (type === 'all') {
                 if (style === 'direct') {
                     let directData = this.tableSelectDirectData;
                     this.tableSelectDirectData = directData.filter(item => list.key !== item.key);
                     this.tableSelectDirectIds = this.tableSelectDirectData.map(item => item.key);
+                    this.$emit('clear-table-direct', this.tableSelectDirectIds);
                 }
                 else if (style === 'exclude') {
                     let excludeData = this.tableSelectExcludeData;
                     this.tableSelectExcludeData = excludeData.filter(item => list.key !== item.key);
                     this.tableSelectExcludeIds = this.tableSelectExcludeData.map(item => item.key);
+                    this.$emit('clear-table-exclude', this.tableSelectExcludeIds);
                 }
             }
         },
@@ -464,12 +496,22 @@ export default {
             if (type === 'alone') {
                 this.selectRightData = [];
                 this.tableSelectIds = [];
+                this.$emit('clearlist');
             }
             else if (type === 'all') {
                 this.tableSelectDirectIds = [];
                 this.tableSelectDirectData = [];
                 this.tableSelectExcludeIds = [];
                 this.tableSelectExcludeData = [];
+                this.tableDataAllDirect = [];
+                this.tableDataAllExclude = [];
+                this.directInput = '';
+                this.excludeInput = '';
+                this.$nextTick(() => {
+                    this.tableDataAllDirect = this.updateTableAllDirect;
+                    this.tableDataAllExclude = this.updateTableAllExclude;
+                });
+                this.$emit('clearlist');
             }
         }
     }

+ 71 - 0
src/views/modules/account-config/components/tree-select/tree-select.less

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

+ 126 - 0
src/views/modules/account-config/components/tree-select/tree-select.vue

@@ -0,0 +1,126 @@
+<template>
+    <div class="tree-select-content">
+        <!-- <a-input-search class="input-search" placeholder="请输入账户名或ID" @change="onChange" /> -->
+        <div class="tree-select-class">
+            <div class="select-class-left">
+                <div class="class-left-header">可放开定向</div>
+                <div class="class-left-content">
+                    <template>
+                        <a-checkbox-group v-model="checkedValue" @change="handleCheckGroup">
+                            <a-row>
+                                <a-col :span="24" v-for="item in changeCheckData" :key="item.value">
+                                    <a-checkbox :value="item.value">{{ item.label }}</a-checkbox>
+                                </a-col>
+                            </a-row>
+                        </a-checkbox-group>
+                    </template>
+                    <div class="example">
+                        <span v-if="!changeCheckData.length">暂无数据</span>
+                    </div>
+                </div>
+            </div>
+            <div class="select-class-right">
+                <div class="class-left-header">
+                    已选 ({{ applyTypeOption.length ? applyTypeOption.length : 0}})
+                    <span class="clear-all-class"><a @click="handleClearAll">清空</a></span>
+                </div>
+                <div v-if="applyTypeOption.length" class="class-left-content">
+                    <div class="apply-right-tree" v-for="item in applyTypeOption" :key="item.value">
+                        <p class="left-content-p">
+                            <a-tooltip placement="left">
+                                <template slot="title">
+                                    <span>{{ item.label }}</span>
+                                </template>
+                                {{ item.label }}
+                            </a-tooltip>
+                        </p>
+                        <a-icon type="delete" class="delete-type-class" @click="handleDelTree(item)" />
+                    </div>
+                </div>
+                <div v-else class="no-data-class">暂无数据</div>
+            </div>
+        </div>
+    </div>
+</template>
+<script>
+import {mapGetters} from 'vuex';
+
+export default {
+    name: 'tree-select',
+    props: {
+        defaultlist: {
+            type: Array,
+            default: () => []
+        },
+        editdata: {
+            type: Array,
+            default: () => []
+        }
+    },
+    data() {
+        return {
+            checkedValue: [],
+            checkedKeys: [],
+            treeData: [],
+            updateTreeData: [],
+            applyTypeOption: [],
+            changeCheckData: []
+        };
+    },
+    mounted() {
+        this.changeCheckData = this.defaultlist;
+        this.updateTreeData = this.defaultlist;
+        if (this.editdata.length) {
+            this.checkedValue = [...this.editdata];
+            const rightSelectList = [];
+            this.updateTreeData.forEach(item => {
+                if (this.editdata.includes(item.value)) {
+                    rightSelectList.push(item);
+                }
+            });
+            this.applyTypeOption = rightSelectList;
+        }
+    },
+    methods: {
+        ...mapGetters(['userInfo']),
+        handleCheckGroup(checkedValues) {
+            const rightSelectList = [];
+            this.checkedValue = checkedValues;
+            this.updateTreeData.forEach(item => {
+                if (checkedValues.includes(item.value)) {
+                    rightSelectList.push(item);
+                }
+            });
+            this.applyTypeOption = rightSelectList;
+            this.$emit('select-finally-result', this.applyTypeOption);
+        },
+        handleClearAll() {
+            this.checkedValue = [];
+            this.applyTypeOption = [];
+            this.$emit('select-finally-result', this.applyTypeOption);
+        },
+        handleDelTree(list) {
+            const defaultData = this.applyTypeOption;
+            this.applyTypeOption = defaultData.filter(item => item.value !== list.value);
+            this.checkedValue = this.applyTypeOption.map(item => item.value);
+            this.$emit('select-finally-result', this.applyTypeOption);
+        },
+        onChange(e) {
+            const value = e.target.value;
+            this.changeCheckData = value !== '' ? this.getNewTreeData(this.updateTreeData, value) : [...this.updateTreeData];
+        },
+        getNewTreeData(data, value) {
+            const checkList = [];
+            data.forEach(item => {
+                if (item.label.indexOf(value) !== -1) {
+                    checkList.push(item);
+                }
+            });
+            return checkList;
+        },
+    }
+};
+</script>
+<style lang="less" scoped>
+    @import 'tree-select';
+</style>

+ 222 - 0
src/views/modules/autoLaunch/application/application-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();

+ 115 - 0
src/views/modules/autoLaunch/application/application.less

@@ -0,0 +1,115 @@
+.directional-content {
+    background: #fff;
+    // height: calc(100vh - 137px);
+    padding: 20px;
+    overflow-y: auto;
+    .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;
+    }
+}
+/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;
+    }
+}
+
+

Datei-Diff unterdrückt, da er zu groß ist
+ 1134 - 0
src/views/modules/autoLaunch/application/application.vue


+ 652 - 0
src/views/modules/autoLaunch/application/components/creatApplication.vue

@@ -0,0 +1,652 @@
+<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="handleOk"
+      :confirmLoading="confirmLoading"
+      @cancel="handleCancel"
+      width="800px"
+    >
+      <a-card :body-style="{ padding: '24px 32px' }" :bordered="false">
+        <a-form :form="form">
+          <selectTable :projectId.sync="projectId" ref="selectTable" :requireCheck="true"></selectTable>
+          <a-form-item
+            label="设备类型"
+            :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
+            :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
+          >
+            <a-radio-group v-model="appType" @change="changePlatform">
+              <a-radio-button value="android">安卓</a-radio-button>
+              <a-radio-button value="ios">IOS</a-radio-button>
+            </a-radio-group>
+          </a-form-item>
+          <!-- <a-form-item v-if="appType == 'android'"> -->
+          <a-form-item
+            label="推广类型"
+            :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
+            :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
+          >
+            <a-radio-group v-model="platform" @change="changeShowUploadType">
+              <a-radio value="1">应用下载</a-radio>
+              <a-radio value="2">网页游戏</a-radio>
+            </a-radio-group>
+          </a-form-item>
+
+          <a-form-item
+            label="上传应用"
+            :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
+            :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
+          >
+            <a-radio-group v-model="uploadType" @change="changeShowUpload">
+              <a-radio-button value="1">本地上传</a-radio-button>
+              <a-radio-button value="2">填写链接</a-radio-button>
+            </a-radio-group>
+          </a-form-item>
+
+          <a-form-item
+            v-if="uploadType == '2'"
+            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 }],
+                },
+              ]"
+            />
+          </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="应用名称"
+            v-if="uploadType == '2'"
+            :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="上传文件"
+            v-if="uploadType == '1'"
+            :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
+            :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
+            class="require-class fileUpload"
+            id="fileUpload"
+          >
+            <!-- <a-upload name="file" :file-list="fileList" :before-upload="beforeUpload" @change="handleChange">
+              <a-button><a-icon type="upload" />文件上传</a-button>
+            </a-upload> -->
+            <!-- :action="uploadAction" -->
+            <a-upload
+              name="file"
+              :multiple="false"
+              :headers="tokenHeader"
+              :file-list="fileList"
+              :showUploadList="false"
+              :beforeUpload="beforeUpload"
+              @change="handleChange"
+              style="margin-right: 20px"
+            >
+              <a-button :disabled="fileUrl == '' && !projectId">
+                <a-icon type="upload" />
+                {{ loadDisabled ? '上传中,请稍后' : '文件上传' }}
+              </a-button>
+            </a-upload>
+            <a @click="downLoadFile">文件格式下载</a>
+          </a-form-item>
+          <a-form-item
+            label="应用标记"
+            :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
+            :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
+            v-if="uploadType == '2'"
+          >
+            <a-input
+              v-decorator="[
+                'appVersion',
+                {
+                  rules: [{ required: true, message: ' ' }, { validator: checkAppVersion }],
+                },
+              ]"
+              placeholder="请填写应用标记,必填且不可重复,如快手-5.6.1.66"
+            />
+          </a-form-item>
+          <!-- <a-form-item>
+            <a-form-item :wrapperCol="{ span: 24 }" style="text-align: center">
+              <a-button htmlType="submit" type="primary">提交</a-button>
+              <a-button style="margin-left: 8px">保存</a-button>
+            </a-form-item>
+          </a-form-item> -->
+          <a-form-item
+            label=""
+            :labelCol="{ span: 5 }"
+            :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 }, offset: 5 }"
+            v-if="uploadType == '2' && appType == 'android'"
+          >
+            <!-- <a-radio-group
+              v-decorator="[
+                'useSdk',
+                {
+                  rules: [{ required: true }],
+                  initialValue: '0',
+                },
+              ]"
+            >
+              <a-radio value="0">未接入</a-radio>
+              <a-radio value="1">已接入</a-radio>
+            </a-radio-group> -->
+            <a-checkbox-group
+              v-decorator="[
+                'useSdk',
+                {
+                  rules: [{ message: '安卓应用已接入快手广告监测SDK必选' }],
+                },
+              ]"
+            >
+              <a-checkbox :value="0"> 该应用已接入快手广告监测SDK </a-checkbox>
+            </a-checkbox-group>
+          </a-form-item>
+          <a-form-item
+            label="隐私政策链接"
+            :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
+            :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
+            v-if="uploadType == '2' && appType == 'android'"
+          >
+            <a-input
+              v-decorator="[
+                'appPrivacyUrl',
+                {
+                  rules: [{ required: true, message: '请填写隐私政策链接' }, { validator: handleConfirmValue }],
+                },
+              ]"
+              placeholder="请填写隐私政策链接"
+            />
+          </a-form-item>
+
+          <a-form-item
+            label="监测链接"
+            :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
+            :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
+            v-if="uploadType == '2' && appType == 'android'"
+          >
+            <a-input v-decorator="['trackUrl']" 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: '1', //上传类型 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,
+    }
+  },
+  methods: {
+    checkAppVersion(rule, value, callback) {
+      if (value != '') {
+        if (this.projectId) {
+          let params = {}
+          params.projectId = this.projectId
+          params.appVersion = value
+          getAction('/kuaishouAppPackage/checkAppVersion', params).then((res) => {
+            if (res.success) {
+              callback()
+            } else {
+              callback(res.message)
+            }
+          })
+        }
+      } else {
+        callback('应用标记必填')
+      }
+    },
+    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) {
+      // let fileList = [...info.fileList]
+
+      // // 1. Limit the number of uploaded files
+      // //    Only to show two recent uploaded files, and old ones will be replaced by the new
+      // fileList = fileList.slice(-2)
+
+      // // 2. read from response and show file link
+      // fileList = fileList.map((file) => {
+      //   if (file.response) {
+      //     // Component will show file.url as link
+      //     file.url = file.response.url
+      //   }
+      //   return file
+      // })
+      // if (fileList.length > 0) {
+      //   this.fileList = [
+      //     {
+      //       ...fileList[fileList.length - 1],
+      //     },
+      //   ]
+      // } else {
+      //   this.fileList = []
+      // }
+      this.loadDisabled = false
+      this.$message.success('文件导入成功')
+      // if (info.file.status !== 'uploading') {
+      //   console.log(info.file, info.fileList)
+      // }
+      // if (info.file.status === 'done') {
+      //   this.loadDisabled = false
+      //   if (info.file.response.code == 200) {
+      //     // this.application = true
+      //     // this.$emit('getDataList')
+      //     this.okCreated = true
+      //     this.$message.success(info.file.response.message)
+      //   } else {
+      //     this.okCreated = false
+      //     this.$message.error(info.file.response.message)
+      //   }
+      // } else if (info.file.status === 'error') {
+      //   this.$message.error(`${info.file.name}上传失败`)
+      //   this.loadDisabled = false
+      // }
+
+      // console.log(this.form)
+    },
+    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 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()
+          //   } else if (result.code === 201) {
+          //     that.$message.error(result.message)
+          //     that.personForm.name = result.result.orientationName
+          //     that.personForm.resource = result.result.type
+          //     that.personNameDisabled = true
+          //     that.personResourceDisabled = true
+          //     reject()
+          //   }
+          // })
+          // .catch((error) => {
+          //   console.log(error, 'eeee')
+          //   reject()
+          // })
+        })
+      })
+    },
+    handleOk() {
+      this.handleSubmit()
+    },
+    handleCancel() {
+      this.dataFile = null
+      this.appType = 'android'
+      this.okCreated = false
+      this.form.resetFields()
+      this.fileUrl = ''
+      this.projectId = undefined
+      this.$refs.selectTable.keyValue = ''
+      this.$refs.selectTable.getData()
+      this.file = ''
+      this.platform = '1'
+      this.application = false
+      this.uploadType = '1'
+    },
+    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.projectId) {
+            this.confirmLoading = true
+            let params = {}
+            params.projectId = this.projectId
+            if (this.uploadType == '1') {
+              // var file = document.getElementById('fileId').files[0] //获取文件流
+              this.url.insertTemplateUrl = '/kuaishouAppPackage/importAppExcel'
+              params.platform = this.appType == 'ios' ? +this.platform + 2 : +this.platform
+              params.imageUrl = this.fileUrl
+              if (this.dataFile) {
+                let formData = new FormData()
+                formData.append('file', this.dataFile)
+                formData.append('projectId', this.projectId)
+                formData.append('platform', this.appType == 'ios' ? +this.platform + 2 : +this.platform)
+                formData.append('imageUrl', this.fileUrl)
+                // 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}`
+                // }
+
+                postAction('/kuaishouAppPackage/importAppExcel', formData).then((res) => {
+                  this.confirmLoading = false
+                  if (res.code === 200) {
+                    this.$message.success('创建成功')
+                    this.handleCancel()
+                    this.$emit('getDataList')
+                  } else {
+                    this.$message.error(res.message)
+                  }
+                })
+              } else {
+                this.$message.error('请上传文件')
+              }
+
+              return
+            } else {
+              this.url.insertTemplateUrl = '/kuaishouAppPackage/fillInLink'
+              params = { ...values }
+              params.useSdk = params.useSdk ? (params.useSdk.length > 0 ? 1 : 0) : null
+              params.projectId = this.projectId
+              params.appIconUrl = this.fileUrl
+              params.platform = this.appType == 'ios' ? +this.platform + 2 : +this.platform
+            }
+
+            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.$message.error('请填写必填项')
+          }
+        }
+      })
+    },
+
+    onChange(value) {},
+  },
+  created: function () {
+    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>

+ 603 - 0
src/views/modules/autoLaunch/application/components/editApplication.vue

@@ -0,0 +1,603 @@
+<template>
+  <div>
+    <a-modal
+      title="编辑应用"
+      :visible="application"
+      @ok="handleOk"
+      :confirmLoading="confirmLoading"
+      @cancel="handleCancel"
+      width="800px"
+    >
+      <a-card :body-style="{ padding: '24px 32px' }" :bordered="false">
+        <a-form :form="form">
+          <!-- <selectTable :projectId.sync="projectId" ref="selectTable" :requireCheck="true"></selectTable> -->
+          <a-form-item
+            label="项目名称"
+            :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
+            :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
+          >
+            <a-input
+              disabled
+              v-decorator="[
+                'projectName',
+                {
+                  rules: [{ required: true }],
+                },
+              ]"
+            />
+          </a-form-item>
+          <a-form-item
+            label="设备类型"
+            :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
+            :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
+          >
+            <a-radio-group v-model="appType" @change="changePlatform" disabled>
+              <a-radio-button value="android">安卓</a-radio-button>
+              <a-radio-button value="ios">IOS</a-radio-button>
+            </a-radio-group>
+          </a-form-item>
+          <!-- <a-form-item v-if="appType == 'android'"> -->
+          <a-form-item
+            label="推广类型"
+            :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
+            :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
+          >
+            <a-radio-group v-model="platform" disabled>
+              <a-radio value="1">应用下载</a-radio>
+              <a-radio value="2">网页游戏</a-radio>
+            </a-radio-group>
+          </a-form-item>
+
+          <a-form-item
+            label="上传应用"
+            :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
+            :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
+          >
+            <a-radio-group v-model="uploadType">
+              <a-radio-button value="1" disabled>本地上传</a-radio-button>
+              <a-radio-button value="2">填写链接</a-radio-button>
+            </a-radio-group>
+          </a-form-item>
+
+          <a-form-item
+            label="上传文件"
+            v-if="uploadType == '1'"
+            :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
+            :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
+          >
+            <!-- <a-upload name="file" :file-list="fileList" :before-upload="beforeUpload" @change="handleChange">
+              <a-button><a-icon type="upload" />文件上传</a-button>
+            </a-upload> -->
+            <a-upload
+              name="file"
+              :multiple="false"
+              :action="uploadAction"
+              :headers="tokenHeader"
+              :file-list="fileList"
+              :showUploadList="false"
+              :beforeUpload="beforeUpload"
+              @change="handleChange"
+              style="margin-right: 20px"
+            >
+              <a-button :disabled="(!projectId && !fileUrl) || loadDisabled">
+                <a-icon type="upload" />
+                {{ loadDisabled ? '上传中,请稍后' : '文件上传' }}
+              </a-button>
+            </a-upload>
+            <a @click="downLoadFile">文件格式下载</a>
+          </a-form-item>
+
+          <a-form-item
+            v-if="uploadType == '2'"
+            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 }],
+                },
+              ]"
+            />
+          </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="应用名称"
+            v-if="uploadType == '2'"
+            :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"
+          >
+            <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 } }"
+            v-if="uploadType == '2'"
+          >
+            <a-input
+              v-decorator="[
+                'appVersion',
+                {
+                  rules: [{ required: true, message: ' ' }, { validator: checkAppVersion }],
+                },
+              ]"
+              placeholder="请填写应用标记,必填且不可重复,如快手-5.6.1.66"
+            />
+          </a-form-item>
+          <!-- <a-form-item>
+            <a-form-item :wrapperCol="{ span: 24 }" style="text-align: center">
+              <a-button htmlType="submit" type="primary">提交</a-button>
+              <a-button style="margin-left: 8px">保存</a-button>
+            </a-form-item>
+          </a-form-item> -->
+          <a-form-item
+            label=""
+            :labelCol="{ span: 5 }"
+            :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 }, offset: 5 }"
+            v-if="uploadType == '2' && appType == 'android'"
+          >
+            <a-checkbox-group v-decorator="['useSdk']">
+              <a-checkbox :value="0"> 该应用已接入快手广告监测SDK </a-checkbox>
+            </a-checkbox-group>
+          </a-form-item>
+          <a-form-item
+            label="隐私政策链接"
+            :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
+            :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
+            v-if="uploadType == '2' && appType == 'android'"
+          >
+            <a-input
+              v-decorator="[
+                'appPrivacyUrl',
+                {
+                  rules: [{ required: true, message: '请填写隐私政策链接' }, { validator: handleConfirmValue }],
+                },
+              ]"
+              placeholder="请填写隐私政策链接"
+            />
+          </a-form-item>
+
+          <a-form-item
+            label="监测链接"
+            :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
+            :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
+            v-if="uploadType == '2' && appType == 'android'"
+          >
+            <a-input v-decorator="['trackUrl']" 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 pick from 'lodash.pick'
+const fileSuffix = ['xlsx', 'xls', 'zip']
+export default {
+  name: 'BaseForm',
+  components: {
+    uploadFile,
+    selectTable,
+  },
+  data() {
+    return {
+      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) },
+      appId: null,
+    }
+  },
+  methods: {
+    checkAppVersion(rule, value, callback) {
+      if (value != '') {
+        if (this.projectId) {
+          let params = {}
+          params.projectId = this.projectId
+          params.appVersion = value
+          params.id = this.appId
+          getAction('/kuaishouAppPackage/checkAppVersion', params).then((res) => {
+            if (res.success) {
+              callback()
+            } else {
+              callback(res.message)
+            }
+          })
+        }
+      } else {
+        callback('应用标记必填')
+      }
+    },
+    overUpload(file) {
+      console.log(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) {
+      console.log(info)
+      let fileList = [...info.fileList]
+
+      // 1. Limit the number of uploaded files
+      //    Only to show two recent uploaded files, and old ones will be replaced by the new
+      fileList = fileList.slice(-2)
+
+      // 2. read from response and show file link
+      fileList = fileList.map((file) => {
+        if (file.response) {
+          // Component will show file.url as link
+          file.url = file.response.url
+        }
+        return file
+      })
+      if (fileList.length > 0) {
+        this.fileList = [
+          {
+            ...fileList[fileList.length - 1],
+          },
+        ]
+      } else {
+        this.fileList = []
+      }
+      // this.loadDisabled = false
+      // this.$message.success('文件导入成功,异步创建中,请稍后查看...')
+      if (info.file.status !== 'uploading') {
+        console.log(info.file, info.fileList)
+      }
+      if (info.file.status === 'done') {
+        this.loadDisabled = false
+        if (info.file.response.code == 200) {
+          this.application = true
+          this.$emit('getDataList')
+          this.$message.success(info.file.response.message)
+        } else {
+          this.$message.error(info.file.response.message)
+        }
+      } else if (info.file.status === 'error') {
+        this.$message.error(`${info.file.name}上传失败`)
+        this.loadDisabled = false
+      }
+
+      // console.log(this.form)
+    },
+    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.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()
+          //   } else if (result.code === 201) {
+          //     that.$message.error(result.message)
+          //     that.personForm.name = result.result.orientationName
+          //     that.personForm.resource = result.result.type
+          //     that.personNameDisabled = true
+          //     that.personResourceDisabled = true
+          //     reject()
+          //   }
+          // })
+          // .catch((error) => {
+          //   console.log(error, 'eeee')
+          //   reject()
+          // })
+        })
+      })
+    },
+    handleOk() {
+      this.handleSubmit()
+    },
+    handleCancel() {
+      this.form.resetFields()
+      this.imageUrl = ''
+      this.fileUrl = ''
+      this.platform = '1'
+      this.application = false
+      this.uploadType = '2'
+    },
+    showApplication(val) {
+      this.application = true
+      this.appId = val.id
+      getAction('/kuaishouAppPackage/queryById', { id: val.id }).then((res) => {
+        //   'appIconUrl',
+        if (res.success) {
+          this.fileUrl = res.result.appIconUrl
+          this.appType = res.result.platform > 2 ? 'ios' : 'android'
+          this.platform = res.result.platform > 2 ? res.result.platform - 2 + '' : res.result.platform + ''
+          res.result.useSdk = res.result.useSdk ? (res.result.useSdk == 0 ? [] : [0]) : null
+          this.projectId = res.result.projectId
+          if (this.appType == 'android') {
+            this.$nextTick(() => {
+              this.form.setFieldsValue(
+                pick(res.result, 'url', 'packageName', 'appPrivacyUrl', 'useSdk', 'trackUrl', 'appName', 'projectName')
+              )
+              setTimeout(() => {
+                this.form.setFieldsValue(pick(res.result, 'appVersion'))
+              }, 150)
+            })
+          } else {
+            setTimeout(() => {
+              this.form.setFieldsValue(pick(res.result, 'url', 'appVersion', 'projectName'))
+            }, 100)
+            setTimeout(() => {
+              this.form.setFieldsValue(pick(res.result, 'appName'))
+            }, 150)
+          }
+        }
+      })
+    },
+    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'
+      // }
+    },
+
+    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.projectId) {
+            this.confirmLoading = true
+            let params = {}
+            params.projectId = this.projectId
+            if (this.uploadType == '1') {
+              this.url.insertTemplateUrl = '/kuaishouAppPackage/importAppExcel'
+              params.platform = this.appType == 'ios' ? +this.platform + 2 : +this.platform
+              params.imageUrl = this.fileUrl
+            } else {
+              this.url.insertTemplateUrl = '/kuaishouAppPackage/fillInLink'
+              params = { ...values }
+              params.useSdk = params.useSdk ? (params.useSdk.length > 0 ? 1 : 0) : null
+              params.id = this.appId
+              params.projectId = this.projectId
+              params.appIconUrl = this.fileUrl
+              params.platform = this.appType == 'ios' ? +this.platform + 2 : +this.platform
+            }
+            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.$message.error('请填写必填项')
+          }
+        }
+      })
+    },
+
+    onChange(value) {
+      console.log(value)
+    },
+  },
+  created: function () {
+    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>

+ 71 - 0
src/views/modules/autoLaunch/application/components/tree-select.less

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

+ 303 - 0
src/views/modules/autoLaunch/application/components/tree-select.vue

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

+ 365 - 0
src/views/modules/autoLaunch/application/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>

+ 5 - 3
src/views/modules/autoLaunch/configLaunchInfo.vue

@@ -2608,14 +2608,16 @@ export default {
                     })
                 }
             }
-            
-           if(val!=undefined && (val&&val.length>0) ){
+           if(val!=undefined &&val){
                 if(this.getFormData('campaignType')==2){
                     
                     if(this.getFormData('singleAppid')==1){
                         this.getIsActivate(val.key)
                     }else{
-                        this.getIsActivate(val[0].key)
+                        if(val!=undefined && (val&&val.length>0)){
+                            this.getIsActivate(val[0].key)
+                        }
+                        
                     }
                     
                 }

+ 429 - 0
src/views/modules/autoLaunch/directional/components/selectRegion.vue

@@ -0,0 +1,429 @@
+<style scoped>
+  .transfer {
+    display: flex;
+  }
+
+  .transfer .transfer-box {
+    width: 350px;
+    height: 250px;
+    border: 1px solid #dadfe3;
+    display: flex;
+    overflow-x: auto;
+    overflow-y: hidden;
+    box-sizing: border-box;
+    margin-right: 25px;
+  }
+
+  .content-box {
+    min-width: 174px;
+    width: 100%;
+    height: 100%;
+    border-right: 1px solid #dadfe3;
+  }
+
+  .content-box .content-title {
+    width: 100%;
+    background: #f8f9fa;
+    border-bottom: 1px solid #dadfe3;
+    padding: 5px 15px;
+    font-size: 16px;
+    font-weight: 700;
+    line-height: 30px;
+  }
+
+  .content-box .content {
+    width: 100%;
+    height: 85%;
+    overflow: auto;
+  }
+
+  .content-box .content p:hover {
+    background: #edf1f5;
+    cursor: pointer;
+  }
+
+  .content-box .content p:hover span {
+    display: inline-block;
+  }
+
+  .content-box .content p span {
+    display: none;
+  }
+
+  p {
+    padding: 5px;
+    margin-bottom: 0;
+    border-bottom: 1px solid #f2f2f2;
+  }
+
+  .backgroundOnly {
+    background: #edf1f5;
+  }
+</style>
+<style>
+  .transfer .ant-checkbox-group {
+    width: 100px;
+    overflow-x: hidden;
+  }
+
+  .transfer .ant-checkbox-group-item {
+    display: inline-block;
+    margin-right: 8px;
+    width: 100%;
+  }
+</style>
+
+<template>
+  <div class="transfer">
+    <div class="transfer-box">
+      <div class="content-box">
+        <p class="content-title">省份</p>
+        <div class="content" style="position:relative">
+          <!-- <div style="position:absolute;top:0;left:0;width:100%;height:100%;background: rgba(0, 0, 0, 0.5)"
+            v-if="loading"></div> -->
+          <p><input type="checkbox" class="select_all" @change="checkAllBox" v-model="checkAll" /> 全选</p>
+
+          <p v-for="(item, index) of province" :key="item.value" :class="{ backgroundOnly: provinceIndex == index }">
+            <input class="checkItem" type="checkbox" :value="item.value" :id="item.value" v-model="checkMatched"
+              @change="checkOne(item, index)" />
+            <span @click="showCity(item, index)" style="color:black;display:inline-block;margin-left:5px;width:80%">{{
+              item.label
+            }}</span>
+          </p>
+        </div>
+      </div>
+      <div class="content-box" :style="{ borderRight: !showClass ? '0px' : '1px solid #dadfe3' }" v-show="showCityData">
+        <p class="content-title">城市</p>
+        <div class="content">
+          <!-- <p>
+            <input
+              type="checkbox"
+              class="select_all"
+              @change="checkAllBoxCity"
+              v-model="checkAllCity"
+            /> 全选
+          </p>-->
+          <p v-for="(item, index) of city" :key="item.id" :class="{ backgroundOnly: cityIndex == index }">
+            <input class="checkItem" type="checkbox" :value="item.value" :id="item.value" v-model="checkMatchedCity"
+              @change="checkOneCity(item, index)" />
+            {{ item.label }}
+          </p>
+        </div>
+      </div>
+    </div>
+    <div class="transfer-box" style="width:176px">
+      <div class="content-box">
+        <p class="content-title">
+          已选
+          <span style="float:right;font-weight:normal;color:blue;cursor: pointer;font-size:14px"
+            @click="clear">清空</span>
+        </p>
+        <div class="content">
+          <p v-for="(item, index) of checkData" :key="index">
+            {{ item.label }}
+            <!-- <span
+              style="float:right;font-weight:normal;color:blue;cursor: pointer;font-size:14px"
+              @click="detele(item,index)"
+            >删除</span>-->
+          </p>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+  import {
+    JeecgListMixin
+  } from '@/mixins/JeecgListMixin'
+  import {
+    getProvince,
+    postAction
+  } from '@/api/manage'
+  import $ from 'jquery'
+  export default {
+    name: 'ByteDanceUserOrientationTemplateList',
+    components: {},
+    props: ['dataValue'],
+    data() {
+      return {
+        showClass: false,
+        showCityData: false,
+        checkData: [],
+        checkMatched: [],
+        province: [],
+        city: [],
+        area: [],
+        CityData: '/kuaishou/batch/getRegion',
+        provinceIndex: null,
+        cityIndex: null,
+        checkAll: false,
+        checkMatchedCity: [],
+        checkAllCity: false,
+        nowProvince: null,
+        loading: false
+      }
+    },
+    computed: {},
+    mounted() {
+      this.$nextTick(() => {
+        this.getData().then(() => {
+            console.log(this.dataValue)
+          if (this.dataValue.length>0&&this.dataValue[0].value) {
+            return
+          } else {
+            postAction('/kuaishou/batch/getRegionDetail', {
+              regionArr: this.dataValue
+            }).then(res => {
+              if (res.success) {
+                //   this.populationData.allForm.region = res.result
+                this.checkData = res.result
+                this.checkMatched = res.result.map(item => {
+                  return item.value
+                })
+                this.checkMatchedCity = res.result.map(item => {
+                  return item.value
+                })
+                this.$emit('update:checkData', this.checkData)
+              }
+            })
+          }
+
+          //   if (this.dataValue.length > 0) {
+
+          //   }
+        })
+
+      })
+    },
+    watch: {
+      dataValue: {
+        deep: true,
+        immediate: true, // immediate选项可以开启首次赋值监听
+        handler(n, o) {
+          if (n.length > 0 && n[0].value) {
+            // this.getData().then(() => {
+            console.log(1)
+            //   if (n.length > 0) {
+            this.$nextTick(() => {
+              this.checkData = n
+              this.checkMatched = n.map(item => {
+                return item.value
+              })
+              this.checkMatchedCity = n.map(item => {
+                return item.value
+              })
+              this.$emit('update:checkData', this.checkData)
+            })
+            //   }
+            // })
+
+          }
+
+        }
+      }
+    },
+    methods: {
+      getData() {
+        this.loading = true
+        var that = this
+        return new Promise(function (resolve, reject) {
+          getProvince(that.CityData, {
+            level: 1
+          }).then(res => {
+            if (res.code == '0') {
+              //   this.province.push(...res.result.records)
+              that.province = res.result.map(item => {
+                return {
+                  label: item.name,
+                  value: item.regionId
+                }
+              })
+              that.province = that.province.filter(item => {
+                return item.label != '台湾' && item.label != '香港' && item.label != '澳门'
+              })
+              that.loading = false
+              resolve()
+            }
+          })
+        })
+
+      },
+      showCity(item, index) {
+        this.city = []
+        this.showCityData = false
+        this.showClass = false
+        this.provinceIndex = index
+        this.cityIndex = null
+        this.nowProvince = item
+        this.checkMatchedCity = []
+        getProvince(this.CityData, {
+          parent: item.value
+        }).then(res => {
+          if (res.code == '0') {
+            this.city = res.result.map(item => {
+              return {
+                label: item.name,
+                value: item.regionId
+              }
+            })
+            if (this.checkMatched.indexOf(item.value) != -1) {
+              this.checkAllCity = true
+              this.checkMatchedCity = this.city.map(item => {
+                return item.value
+              })
+            } else {
+              this.checkMatchedCity = this.checkData.map(item => {
+                return item.value
+              })
+            }
+            //   this.city.push(...res.result.records)
+            this.showCityData = true
+          }
+        })
+      },
+      checkAllBox() {
+        this.checkMatched = []
+        this.checkData = []
+        if (this.checkAll) {
+          this.checkMatched = this.province.map(item => {
+            return item.value
+          })
+          this.checkData.push(...this.province)
+        } else {
+          this.checkMatched = []
+          this.checkData = []
+          this.checkMatchedCity = []
+        }
+        this.$emit('update:checkData', this.checkData)
+      },
+      checkOne(item, index) {
+        if (this.checkMatched.indexOf(item.value) == -1) {
+          var index1 = this.checkData.findIndex(v => v.value === item.value)
+          this.checkData.splice(index1, 1)
+          if (this.nowProvince) {
+            if (this.nowProvince.value == item.value) {
+              this.checkMatchedCity = []
+            }
+          }
+        } else {
+          this.checkData.push(item)
+          var data = []
+          getProvince(this.CityData, {
+            parent: item.value
+          }).then(res => {
+            if (res.code == '0') {
+              data = res.result.map(item => {
+                return {
+                  label: item.name,
+                  value: item.regionId
+                }
+              })
+              for (var i = 0; i < this.checkData.length; i++) {
+                for (let j = 0; j < data.length; j++) {
+                  if (this.checkData[i].value == data[j].value) {
+                    this.checkData.splice(i, 1)
+                  }
+                }
+              }
+            }
+          })
+
+          if (this.nowProvince) {
+            if (item.value == this.nowProvince.value) {
+              this.checkMatchedCity = this.city.map(item => {
+                return item.value
+              })
+            }
+          }
+        }
+        if (this.checkMatched.length == this.province.length) {
+          this.checkAll = true
+        } else {
+          this.checkAll = false
+        }
+        this.$emit('update:checkData', this.checkData)
+      },
+      checkAllBoxCity() {
+        this.checkMatchedCity = []
+        if (this.checkAllCity) {
+          this.checkMatchedCity = this.city.map(item => {
+            return item.value
+          })
+          this.checkMatched.push(this.nowProvince.value)
+          this.checkData.push(this.nowProvince)
+        } else {
+          this.checkMatchedCity = []
+          var index = this.checkData.findIndex(v => v.value === this.nowProvince.value)
+          var index1 = this.checkMatched.findIndex(v => v === this.nowProvince.value)
+          this.checkData.splice(index, 1)
+          this.checkMatched.splice(index1, 1)
+        }
+        this.$emit('update:checkData', this.checkData)
+      },
+      checkOneCity(item, index) {
+        var allCity = this.checkMatchedCity.filter(v => {
+          return v.toString().slice(0, 2) == this.nowProvince.value
+        })
+
+        if (allCity.length == this.city.length) {
+          this.checkMatched.push(this.nowProvince.value)
+          this.checkData.push(this.nowProvince)
+          for (var i = 0; i < allCity.length; i++) {
+            for (var j = 0; j < this.checkData.length; j++) {
+              if (allCity[i] == this.checkData[j].value) {
+                this.checkData.splice(j, 1)
+                j--
+              }
+            }
+          }
+        }
+        if (this.checkMatchedCity.indexOf(item.value) != -1) {
+          if (allCity.length != this.city.length) {
+            this.checkData.push(item)
+          }
+          if (this.checkMatched.length == this.province.length) {
+            this.checkAll = true
+          } else {
+            this.checkAll = false
+          }
+        } else {
+          if (this.checkMatched.indexOf(this.nowProvince.value) != -1) {
+            var index1 = this.checkData.findIndex(v => v.value === this.nowProvince.value)
+            var index2 = this.checkMatched.findIndex(v => v === this.nowProvince.value)
+            this.checkData.splice(index1, 1)
+            this.checkMatched.splice(index2, 1)
+            this.checkAll = false
+            var data = this.city.filter(v => {
+              return v.value != item.value
+            })
+            this.checkData.push(...data)
+          } else {
+            var index1 = this.checkData.findIndex(v => v.value === item.value)
+            this.checkData.splice(index1, 1)
+          }
+        }
+        this.$emit('update:checkData', this.checkData)
+      },
+      clear() {
+        this.checkData = []
+        this.checkMatched = []
+        this.checkMatchedCity = []
+        this.checkAll = false
+        this.$emit('update:checkData', this.checkData)
+      },
+      detele(item, index) {
+        //   if (this.checkMatched.indexOf(this.nowProvince.value) != -1) {
+        var index1 = this.checkMatched.findIndex(v => v === item.value)
+        var index2 = this.checkData.findIndex(v => v.value === item.value)
+        this.checkData.splice(index2, 1)
+        this.checkMatched.splice(index1, 1)
+        this.checkAll = false
+        //   } else {
+        //   }
+
+        this.$emit('update:checkData', this.checkData)
+      }
+    }
+  }
+</script>

Datei-Diff unterdrückt, da er zu groß ist
+ 1414 - 0
src/views/modules/autoLaunch/directional/components/targetedPopulation.vue


+ 291 - 0
src/views/modules/autoLaunch/directional/components/templateModal.vue

@@ -0,0 +1,291 @@
+<style>
+#table_time_selected1 tr {
+  border: 1px solid rgb(102, 162, 243);
+}
+
+.plug-timer-grid th {
+  line-height: 25px;
+}
+
+.group-creat .ant-form-item-required::before {
+  display: inline-block;
+  margin-right: 4px;
+  color: #f5222d;
+  font-size: 14px;
+  font-family: SimSun, sans-serif;
+  line-height: 1;
+  content: '';
+}
+
+.else-label .ant-form-item-label label::after {
+  content: '';
+  position: relative;
+  top: -0.5px;
+  margin: 0 8px 0 2px;
+}
+.ant-form-item-required::before {
+  display: inline-block;
+  margin-right: 4px;
+  color: #f5222d;
+  font-size: 14px;
+  font-family: SimSun, sans-serif;
+  line-height: 1;
+  content: '*';
+}
+</style>
+<style lang="scss" scoped>
+.require-check {
+  /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>
+  <a-modal v-model="visible" :title="type === 'add' ? '新建定向包' : '修改定向包'" :width="1100" v-if="visible">
+    <a-spin :spinning="spinning">
+      <a-form @submit="handleSubmit" :form="form">
+        <a-row :gutter="24">
+          <a-col :md="24" :sm="24" :xxl="24">
+            <selectTable
+              :projectId.sync="projectId"
+              :labelCol="labelCol"
+              :disabled="disabled"
+              :requireCheck="true"
+              v-if="!disabled"
+            ></selectTable>
+            <a-form-item
+              v-else
+              label="项目名称"
+              :labelCol="{ lg: { span: 7 }, sm: { span: 7 } }"
+              :wrapperCol="{ lg: { span: 12 }, sm: { span: 12 } }"
+              class="require-check"
+            >
+              <a-input v-model="projectName" :disabled="disabled"></a-input>
+            </a-form-item>
+          </a-col>
+        </a-row>
+        <a-form-item
+          label="定向包名称"
+          :labelCol="{ lg: { span: 7 }, sm: { span: 7 } }"
+          :wrapperCol="{ lg: { span: 12 }, sm: { span: 12 } }"
+        >
+          <a-input
+            v-decorator="['templateName', { rules: [{ required: true, message: '模板名称必填' }] }]"
+            :disabled="type == 'look'"
+          ></a-input>
+        </a-form-item>
+
+        <targeted-population ref="population" :populationData.sync="populationData" />
+      </a-form>
+    </a-spin>
+    <template slot="footer">
+      <!-- <a-button type="primary" @click="handleSubmit" :loading="loading"> 确定 </a-button> -->
+      <a-button
+        type="default"
+        @click="
+          () => {
+            this.visible = false
+          }
+        "
+      >
+        取消
+      </a-button>
+      <a-button type="primary" @click="handleSubmit" :loading="loading">
+        {{ type == 'add' ? '确定' : '修改' }}
+      </a-button>
+    </template>
+  </a-modal>
+</template>
+
+<script>
+import { getAction, postAction, deleteAction, putAction } from '@/api/manage'
+import moment from 'moment'
+import { mapGetters } from 'vuex'
+import jq from 'jquery'
+import selectTable from '@/views/modules/Statistics/components/selectPagination.vue'
+import targetedPopulation from './targetedPopulation.vue'
+import pick from 'lodash.pick'
+export default {
+  name: 'new-mould',
+  components: {
+    targetedPopulation,
+    selectTable,
+  },
+  data() {
+    return {
+      visible: false,
+      spinning: false,
+      projectName: '',
+      form: this.$form.createForm(this),
+      projectId: '',
+      populationData: {},
+      accountId: '',
+      templateId: undefined,
+      type: 'add',
+      loading: false,
+      labelCol: { lg: { span: 7 }, sm: { span: 7 } },
+      disabled: false,
+    }
+  },
+  computed: {},
+  methods: {
+    create(accountId, type) {
+      this.disabled = false
+      this.spinning = false
+      this.visible = true
+      this.type = type
+      this.populationData = {}
+      this.accountId = accountId
+    },
+    handleOk(item, type) {
+      this.spinning = true
+      this.visible = true
+      this.type = type
+      var params = {}
+      params.id = item.id
+      this.templateId = item.id
+      this.projectName = item.projectName
+      this.projectId = item.projectId
+      getAction('/kuaishouDirectionalPackage/queryById', params).then((res) => {
+        if (res.success) {
+          var dataJson = {
+            ...res.result,
+          }
+
+          this.populationData = dataJson
+
+          this.populationData.devicePrice = dataJson.devicePrice ? JSON.parse(dataJson.devicePrice) : null
+          this.populationData.appInterest = dataJson.appInterest ? JSON.parse(dataJson.appInterest) : null
+          this.populationData.businessInterest = dataJson.businessInterest
+            ? JSON.parse(dataJson.businessInterest)
+            : null
+          this.populationData.fansStar = dataJson.fansStar ? JSON.parse(dataJson.fansStar) : null
+          this.populationData.interestVideo = dataJson.interestVideo ? JSON.parse(dataJson.interestVideo) : null
+          this.populationData.deviceBrand = dataJson.deviceBrand ? JSON.parse(dataJson.deviceBrand) : null
+
+          this.populationData.age = dataJson.min ? [dataJson.min, dataJson.max] : []
+          this.populationData.agesRange = dataJson.agesRange ? JSON.parse(dataJson.agesRange) : []
+          this.populationData.devicePrice = dataJson.devicePrice ? dataJson.devicePrice : null
+
+          this.populationData.behavior = dataJson.label
+          this.populationData.interest = dataJson.interestLabel
+
+          this.populationData.sceneType = dataJson.sceneType ? JSON.parse(dataJson.sceneType) : []
+          this.populationData.allForm = {}
+          this.populationData.allForm.regionType =
+            dataJson.region && JSON.parse(dataJson.region).length > 0 ? 'limit' : 'noLimit'
+
+          this.populationData.allForm.region = dataJson.region
+          // postAction('/kuaishou/batch/getRegionDetail', {
+          //   regionArr: dataJson.region
+          // }).then(res => {
+          //   console.log(res, 11111)
+          //   if (res.success) {
+          //     this.populationData.allForm.region = res.result
+          //   }
+          // })
+
+          this.populationData.allForm.ageType =
+            dataJson.agesRange.length > 0 ? 'ageLimit' : dataJson.min>0 ? 'ageCustom' : 'noLimit'
+          this.populationData.allForm.device = dataJson.deviceBrand && eval(dataJson.deviceBrand).length > 0 ? '1' : '0'
+          this.populationData.allForm.price = dataJson.devicePrice && eval(dataJson.devicePrice).length > 0 ? '1' : '0'
+          this.populationData.allForm.appType =
+            dataJson.appInterest && eval(dataJson.appInterest).length > 0
+              ? '1'
+              : dataJson.appIds && eval(dataJson.appIds).length > 0
+              ? '2'
+              : '0'
+          this.populationData.allForm.fansStar =
+            dataJson.fansStar && eval(dataJson.fansStar).length > 0 ? '1' : '0'
+          this.populationData.allForm.interestVideo =
+            dataJson.interestVideo && eval(dataJson.interestVideo).length > 0 ? '1' : '0'
+          this.populationData.allForm.platform_os = dataJson.platformOs
+          this.populationData.allForm.businessInterestType = dataJson.businessInterestType
+          this.populationData.allForm.isOpen = dataJson.isOpen
+          this.populationData.allForm.noAgeBreak = dataJson.noAgeBreak + ''
+          this.populationData.allForm.noGenderBreak = dataJson.noGenderBreak + ''
+          this.populationData.allForm.noAreaBreak = dataJson.noAreaBreak + ''
+          this.populationData.allForm.behaviorInterest = dataJson.label ? '1' : '0'
+          this.populationData.allForm.checkArr =
+            this.populationData.allForm.appType == '2' ? JSON.parse(dataJson.appIds) : []
+          this.populationData.projectId = dataJson.projectId + ''
+
+          this.disabled = true
+
+          this.$nextTick(() => {
+            console.log(dataJson)
+            this.form.setFieldsValue(pick(dataJson, ['templateName']))
+            this.spinning = false
+          })
+        }
+      })
+    },
+    handleCancel(e) {
+      this.visible = false
+    },
+    handleSubmit(e) {
+      //   this.$refs.population.handleSubmit()
+
+      e.preventDefault()
+      this.$refs.population.handleSubmit()
+      this.$refs.population.formAll.validateFields((err, value) => {
+        if (this.populationData.allForm.appType == '2') {
+          if (this.populationData.appIds.length == 0) {
+            this.$message.error('APP名称未选择')
+          }
+        }
+        if (!err) {
+          this.form.validateFieldsAndScroll((err, values) => {
+            if (!err) {
+              // this.loading = true
+              if (this.projectId) {
+                var params = {
+                  ...this.populationData,
+                  templateName: values.templateName,
+                  projectId: this.projectId,
+                }
+                params.label = JSON.stringify(params.behavior)
+                params.interestLabel = JSON.stringify(params.interest)
+                if (this.type == 'add') {
+                  postAction('/kuaishouDirectionalPackage/createDirectionalPackage', params).then((res) => {
+                    if (res.success) {
+                      this.visible = false
+                      this.loading = false
+                      this.$emit('getData')
+                    } else {
+                      this.loading = false
+                      this.$message.error(res.message)
+                    }
+                  })
+                } else if (this.type == 'edit') {
+                  params.id = this.templateId
+                  postAction('/kuaishouDirectionalPackage/updateDirectionalPackage', params).then((res) => {
+                    this.visible = false
+                    if (res.success) {
+                      this.loading = false
+                      this.$emit('getData')
+                    } else {
+                      this.loading = false
+                      this.$message.error(res.message)
+                    }
+                  })
+                }
+              } else {
+                this.$message.error('请选择项目')
+              }
+            }
+          })
+        }
+      })
+    },
+  },
+}
+</script>

+ 71 - 0
src/views/modules/autoLaunch/directional/components/tree-select.less

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

+ 303 - 0
src/views/modules/autoLaunch/directional/components/tree-select.vue

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

+ 213 - 0
src/views/modules/autoLaunch/directional/directional-service.js

@@ -0,0 +1,213 @@
+/**
+ * @file 人群包管理基础服务
+ * @author jiayufei(jiayufei@c-top.com.cn)
+ */
+
+ class AppMarketService {
+    constructor() {}
+
+    // 相关账户的table列表
+    setAcountColumns() {
+        return [
+            {
+                title: '账户名称',
+                dataIndex: 'authName',
+                width: '50%',
+                align: 'center'
+            },
+            {
+                title: '编辑',
+                dataIndex: 'action',
+                scopedSlots: {customRender: 'action'},
+                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: 0,
+                value: '不限'
+            },
+            {
+                label: 1,
+                value: 'Android'
+            },
+            {
+                label: 2,
+                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();

+ 113 - 0
src/views/modules/autoLaunch/directional/directional.less

@@ -0,0 +1,113 @@
+.directional-content {
+    background: #fff;
+    // height: calc(100vh - 137px);
+    padding: 20px;
+    overflow-y: auto;
+    .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;
+    }
+}
+/deep/ .push-modal {
+    width: 600px !important;
+    .acount-title {
+        display: flex;
+        font-size: 14px;
+        height: 40px;
+        line-height: 40px;
+        .acount-title-left {
+            margin-right: 20px;
+            width: 100px;
+        }
+    }
+    .push-plate {
+        margin-bottom: 20px;
+    }
+}
+.person-modal {
+    width: 500px;
+    /deep/ .ant-form-item {
+        display: flex;
+    }
+    /deep/ .ant-form-item-label {
+        width: 20%;
+    }
+    /deep/ .ant-form-item-control-wrapper {
+        width: 80%;
+    }
+    .acount-search-class {
+        width: 100% !important;
+    }
+    .upload-txt-rules {
+        margin-top: 10px;
+        margin-bottom: 10px;
+        line-height: 1.5;
+    }
+    /deep/ .ant-radio-group {
+        line-height: 30px;
+    }
+}
+/deep/ .cause-modal {
+    width: 600px !important;
+    .cause-modal-table-class {
+        height: 500px;
+        overflow-y: auto;
+    }
+    .pagin-table-class {
+        display: flex;
+        justify-content: flex-end;
+        margin-top: 20px;
+    }
+}
+/deep/ .relax-modal {
+    width: 600px !important;
+    .acount-title {
+        display: flex;
+        font-size: 14px;
+        height: 40px;
+        line-height: 40px;
+        .acount-title-left {
+            margin-right: 20px;
+            width: 100px;
+        }
+    }
+    .push-plate {
+        margin-bottom: 20px;
+    }
+}
+
+.grid-form-item-account {
+    /deep/ .ant-form-item-control {
+        line-height: inherit;
+    }
+}
+
+

Datei-Diff unterdrückt, da er zu groß ist
+ 1037 - 0
src/views/modules/autoLaunch/directional/directional.vue


+ 58 - 0
src/views/modules/autoLaunch/material-pool/material.vue

@@ -0,0 +1,58 @@
+<template>
+    <a-card
+        style="width:100%"
+        :tab-list="tabListNoTitle"
+        :active-tab-key="currentTabComponent"
+        @tabChange="key => onTabChange(key)"
+    >
+        <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'),
+    },
+    data() {
+        return {
+            currentTabComponent:'directional',//当前加载的组件名称
+            tabListNoTitle: [
+                {
+                    key: 'directional',
+                    tab: '定向包管理',
+                },
+                {
+                    key: 'person',
+                    tab: '人群包管理',
+                },
+                {
+                    key: 'url',
+                    tab: '落地页管理',
+                },
+                {
+                    key: 'application',
+                    tab: '应用包管理',
+                },
+            ], 
+        }
+    },
+    methods: {
+        onTabChange(key, type) {
+            this.currentTabComponent = key;
+        },
+    },
+    created() {
+        this.currentTabComponent = 'directional';
+    }
+   
+}
+
+</script>

+ 65 - 0
src/views/modules/autoLaunch/url/components/tree-select.less

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

+ 273 - 0
src/views/modules/autoLaunch/url/components/tree-select.vue

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

+ 213 - 0
src/views/modules/autoLaunch/url/url-service.js

@@ -0,0 +1,213 @@
+/**
+ * @file 人群包管理基础服务
+ * @author jiayufei(jiayufei@c-top.com.cn)
+ */
+
+ class AppMarketService {
+    constructor() {}
+
+    // 相关账户的table列表
+    setAcountColumns() {
+        return [
+            {
+                title: '账户名称',
+                dataIndex: 'authName',
+                width: '50%',
+                align: 'center'
+            },
+            {
+                title: '落地页数量',
+                dataIndex: 'count',
+                scopedSlots: {customRender: 'count'},
+                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: 0,
+                value: '不限'
+            },
+            {
+                label: 1,
+                value: 'Android'
+            },
+            {
+                label: 2,
+                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();

+ 113 - 0
src/views/modules/autoLaunch/url/url.less

@@ -0,0 +1,113 @@
+.directional-content {
+    background: #fff;
+    // height: calc(100vh - 137px);
+    padding: 20px;
+    overflow-y: auto;
+    .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;
+    }
+}
+/deep/ .push-modal {
+    width: 600px !important;
+    .acount-title {
+        display: flex;
+        font-size: 14px;
+        height: 40px;
+        line-height: 40px;
+        .acount-title-left {
+            margin-right: 20px;
+            width: 100px;
+        }
+    }
+    .push-plate {
+        margin-bottom: 20px;
+    }
+}
+.person-modal {
+    width: 500px;
+    /deep/ .ant-form-item {
+        display: flex;
+    }
+    /deep/ .ant-form-item-label {
+        width: 20%;
+    }
+    /deep/ .ant-form-item-control-wrapper {
+        width: 80%;
+    }
+    .acount-search-class {
+        width: 100% !important;
+    }
+    .upload-txt-rules {
+        margin-top: 10px;
+        margin-bottom: 10px;
+        line-height: 1.5;
+    }
+    /deep/ .ant-radio-group {
+        line-height: 30px;
+    }
+}
+/deep/ .cause-modal {
+    width: 600px !important;
+    .cause-modal-table-class {
+        height: 500px;
+        overflow-y: auto;
+    }
+    .pagin-table-class {
+        display: flex;
+        justify-content: flex-end;
+        margin-top: 20px;
+    }
+}
+/deep/ .relax-modal {
+    width: 600px !important;
+    .acount-title {
+        display: flex;
+        font-size: 14px;
+        height: 40px;
+        line-height: 40px;
+        .acount-title-left {
+            margin-right: 20px;
+            width: 100px;
+        }
+    }
+    .push-plate {
+        margin-bottom: 20px;
+    }
+}
+
+.grid-form-item-account {
+    /deep/ .ant-form-item-control {
+        line-height: inherit;
+    }
+}
+
+

+ 984 - 0
src/views/modules/autoLaunch/url/url.vue

@@ -0,0 +1,984 @@
+<template>
+    <div class="directional-content">
+        <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">
+                        <!-- <a-form-item label="项目名称"> -->
+                        <selectTable :projectId.sync="projectId" ref="selectTable" :requireCheck="false"></selectTable>
+                    </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>
+                        </span>
+                        
+                    </a-col>
+                </a-row>
+            </a-form>
+        </div>
+        <div class="control-con-table">
+            <a-table
+                ref="table"
+                size="middle"
+                bordered
+                :columns="columns"
+                :dataSource="dataSource"
+                :pagination="ipagination"
+                :loading="dataLoading"
+            >
+                <span slot="action" slot-scope="text, record">
+                    <a @click="handlePush(record)">推送</a>
+                    <a-divider type="vertical" />
+                    <a @click="handleEdit(record)">编辑</a>
+                    <a-divider type="vertical" />
+                    <a @click="handleDelete(record)">删除</a>
+                </span>
+
+                <span slot="accountCount" slot-scope="text, record">
+                    <a @click="handleAcountRelax('account', record)">{{ text }}</a>
+                </span>
+                <span slot="unitCount" slot-scope="text, record">
+                    <a @click="handleAcountRelax('unit', record)">{{ text }}</a>
+                </span>
+                
+                <span slot="actionMore" slot-scope="text, record">
+                    <a @click="handleCause(record)">推送历史</a>
+                </span>
+            </a-table>
+        </div>
+        <a-modal
+            title="推送账户"
+            v-if="pushVisible"
+            :visible="pushVisible"
+            :confirm-loading="pushConfirmLoading"
+            dialog-class="push-modal"
+            @ok="handlePushSure"
+            @cancel="handlePushCancel"
+            okText="下一步"
+        >
+            <div>
+                <div class="acount-title">
+                    <div class="acount-title-left">已选定向包</div>
+                    <div class="acount-title-right">{{ tableSelectList.templateName }}</div>
+                </div>
+                <div class="acount-title push-plate">
+                    <div class="acount-title-left">推送平台</div>
+                    <div class="acount-title-right">{{ tableSelectList.platformOs }}</div>
+                </div>
+                <tree-select @applyType="handleApplyType" :projectId="tableSelectList.projectId" :templateId="tableSelectList.id"></tree-select>
+            </div>
+        </a-modal>
+        <a-modal
+            title="为定向包设置自定义人群"
+            v-if="setPersonVisible"
+            :visible="setPersonVisible"
+            :confirm-loading="setPersonLoading"
+            dialog-class="push-modal"
+            @ok="handleSetPerson"
+            @cancel="handlePersonCancel"
+        >
+             <!-- @change="handleChange" -->
+            <el-collapse v-model="activeKey" accordion>
+                <el-collapse-item :name="item.key" :key="index" v-for="(item ,index) in finallyRightTree">
+                    <template slot="title">
+                        <h2>{{item.title}}</h2>
+                    </template>
+                    <a-form  
+                        :wrapperCol="{ lg: { span: 17 }, sm: { span: 17 } }"
+                    >
+                        <div class="acount-title">
+                            <div class="acount-title-left">自定义人群</div>
+                            <div class="acount-title-right"> 
+                                <a-radio-group v-model="item.people" buttonStyle="solid" @change="checkPerson(item)">
+                                    <a-radio-button value="0">不限</a-radio-button>
+                                    <a-radio-button value="1">定向</a-radio-button>                           
+                                    <a-radio-button value="2">排除</a-radio-button>                           
+                                    <a-radio-button value="3">同时定向排除</a-radio-button>                           
+                                </a-radio-group>
+                            </div>
+                        </div>
+                        <div class="dingxiang_paichu" v-if="item.people!='0'" style="width:100%">
+                            <a-tabs v-model="item.tabKey" @change="retargetAccountId(item.key)"  >
+                                <a-tab-pane key="1" tab="定向池" v-if="item.people!='2'">
+                                    <a-table
+                                        :columns="retargetColumns"
+                                        :row-key="record => record.key"
+                                        :data-source="retargetDataAll"                                        
+                                        :loading="loading"
+                                        style="width:100%;margin:15px 0"
+                                        :pagination='false'
+                                        @change="retargetTableChange"
+                                        :scroll="{ y: 250 }"
+                                        :row-selection="rowSelectionMin"
+                                        bordered
+                                    >
+                                        <template slot="name" slot-scope="name"> {{ name }} </template>
+                                        <template slot="populationType" slot-scope="populationType"> {{ populationType | customCrowdHandler}} </template>
+                                    </a-table>
+                                </a-tab-pane>
+                                <a-tab-pane key="2" tab="排除池" v-if="item.people!='1'">
+                                    <a-table
+                                        :columns="retargetColumns"
+                                        :row-key="record => record.key"
+                                        :data-source="retargetDataAll"                                        
+                                        :loading="loading"
+                                        style="width:100%;margin:15px 0"
+                                        :pagination='false'
+                                        @change="retargetTableChange"
+                                        :scroll="{ y: 250 }"
+                                        :row-selection="rowSelectionMax"
+                                        bordered
+                                    >
+                                        <template slot="name" slot-scope="name"> {{ name }} </template>
+                                        <template slot="populationType" slot-scope="populationType"> {{ populationType | customCrowdHandler}} </template>
+                                    </a-table>
+                                </a-tab-pane>
+                            </a-tabs>
+                                
+                        </div>  
+                    </a-form>
+                </el-collapse-item>
+            </el-collapse>
+        </a-modal>
+        <a-modal
+            title="推送历史"
+            v-if="causeVisible"
+            :visible="causeVisible"
+            :confirm-loading="causeConfirmLoading"
+            :footer="null"
+            dialog-class="cause-modal"
+            @cancel="handleCauseCancel"
+        >
+            <div>
+                <div class="cause-modal-table-class">
+                    <a-select
+                        style="width:200px;margin-bottom:10px"
+                        v-model="resultHistory"
+                        placeholder="请选择"
+                        allow-clear
+                    >
+                        <a-select-option :value="1">推送成功</a-select-option>
+                        <a-select-option :value="0">推送失败</a-select-option>
+                    </a-select>
+                    <a-table :columns="causeColumns" :data-source="causeData" bordered :pagination="false">
+                        <span slot="action" slot-scope="text, record">
+                            <a-popconfirm
+                                title="是否重新推送?"
+                                ok-text="是"
+                                cancel-text="否"
+                                @confirm="handleAgian(record)"
+                            >
+                                <a :disabled="record.result==='推送成功'">重新推送</a>
+                            </a-popconfirm>
+                            
+                        </span>
+                    </a-table>
+                </div>
+                <a-pagination
+                    class="pagin-table-class"
+                    :total="totalAllCause"
+                    size="small"
+                    @change="handleCauseSizeChange"
+                />
+            </div>
+        </a-modal>   
+        <a-modal
+            :title="relaxStatus === 'unit' ? '相关组' : '相关账户'"
+            v-if="relaxVisible"
+            :visible="relaxVisible"
+            :confirm-loading="relaxConfirmLoading"
+            :footer="null"
+            dialog-class="relax-modal"
+            @cancel="handleRelaxCancel"
+            rowKey="index"
+        >
+            <div v-if="relaxStatus === 'account'">
+                <a-table :columns="acountColumns" :data-source="acountData" bordered :pagination="accountIpagination">
+                </a-table>
+            </div>
+            <div v-else>
+                <AcountSearch :appId.sync="unitAccountId" :multiple="false"  request="2,4"   ref="treeSelect" style="margin-bottom:8px;width:300px " />   
+                <a-table :columns="depColumns" :data-source="acountData" bordered :pagination="accountIpagination">
+                </a-table>
+            </div>
+        </a-modal>
+        <a-modal
+            :title="'编辑自定义人群(' + personName + ')'"
+            :visible="personNameVisible"
+            @ok="handleAddPopulation"
+            dialog-class="relax-modal"
+            @cancel="handleCancelPerson"
+            :loading="personLoading"
+            rowKey="index">
+            <a-form  
+                :labelCol="{ lg: { span: 7 }, sm: { span: 7 } }"
+                :wrapperCol="{ lg: { span: 17 }, sm: { span: 17 } }"
+            >
+                <a-form-item label="定向包名称">
+                    <a-input
+                        disabled
+                        :default-value="(personDetail ? personDetail.templateName : '-') "
+                        placeholder="请输入"
+                    />
+                </a-form-item>
+                <a-form-item label="账户名称">
+                    <a-input
+                        disabled
+                        :default-value="(personDetail ? personDetail.authName : '-') "
+                        placeholder="请输入"
+                    />
+                </a-form-item>
+                <a-form-item label="自定义人群">
+                    <a-radio-group v-model="people" buttonStyle="solid" @change="customCrowdChange">
+                        <a-radio-button value="0">不限</a-radio-button>
+                        <a-radio-button value="1">定向</a-radio-button>                           
+                        <a-radio-button value="2">排除</a-radio-button>                           
+                        <a-radio-button value="3">同时定向排除</a-radio-button>                           
+                    </a-radio-group>
+                </a-form-item>
+                <div class="dingxiang_paichu" v-if="people!='0'" style="width:100%">
+                    <a-tabs v-model="tabKey" @change="retargetTabChange"  >
+                        <a-tab-pane key="1" tab="定向池" v-if="people!='2'">
+                            <a-table
+                                :columns="retargetColumns"
+                                :row-key="record => record.key"
+                                :data-source="retargetDataAll"                                        
+                                :loading="loading"
+                                style="width:100%;margin:15px 0"
+                                :pagination='false'
+                                @change="retargetTableChange"
+                                :scroll="{ y: 250 }"
+                                :row-selection="rowSelection"
+                                bordered
+                            >
+                                <template slot="name" slot-scope="name"> {{ name }} </template>
+                                <template slot="populationType" slot-scope="populationType"> {{ populationType | customCrowdHandler}} </template>
+                            </a-table>
+                        </a-tab-pane>
+                        <a-tab-pane key="2" tab="排除池" v-if="people!='1'">
+                            <a-table
+                                :columns="retargetColumns"
+                                :row-key="record => record.key"
+                                :data-source="retargetDataAll"                                        
+                                :loading="loading"
+                                style="width:100%;margin:15px 0"
+                                :pagination='false'
+                                @change="retargetTableChange"
+                                :scroll="{ y: 250 }"
+                                :row-selection="rowSelection2"
+                                bordered
+                            >
+                                <template slot="name" slot-scope="name"> {{ name }} </template>
+                                <template slot="populationType" slot-scope="populationType"> {{ populationType | customCrowdHandler}} </template>
+                            </a-table>
+                        </a-tab-pane>
+                    </a-tabs>
+                        
+                </div>  
+            </a-form>
+        </a-modal>
+    </div>
+</template>
+<script>
+import TreeSelect from './components/tree-select';
+import {getAction, postAction} from '@/api/manage';
+import AcountSearch from '@/views/modules/Statistics/components/Treeselect.vue';
+import AppMarketService from './url-service';
+import selectTable from '@/views/modules/Statistics/components/selectPagination.vue';
+import BMF from 'browser-md5-file';
+let retargetColumns=[
+    {
+        title: '人群包',
+        dataIndex: 'name',
+        sorter: true,
+        width: '40%',
+        scopedSlots: { customRender: 'name' },
+    },
+    {
+    title: '属性',
+      dataIndex: 'populationType',
+      scopedSlots: {
+        customRender: 'populationType'
+      },
+      width: 200
+    },
+    {
+        title: '所属账号',
+        dataIndex: 'accountId',
+        sorter: true,
+        width: '40%',
+        scopedSlots: { customRender: 'accountId' },
+    },
+    
+]
+let COS = require('cos-js-sdk-v5');
+let cos = new COS({
+    SecretId: 'AKIDE6IpMi8fJQRCg1iuWzFajjRs43kbbets',
+    SecretKey: 'tXzuwMfplTTK3c9GFUyETilasvQfePu9'
+});
+export default {
+    name: 'directional',
+    components: {
+        TreeSelect,
+        AcountSearch,
+        selectTable,
+    },
+    data() {
+        let that = this;
+        return {
+            //自定义人群参数
+            personLoading: false,
+            retargetColumns,
+            retargetData: [],
+            retargetDataAll: [],
+            loading: false,
+            customCrowd: 'NONE',//自定义人群 选择的值
+            selectedRowKeys: [],
+            incluedSelectedRowKeys: [],
+            incluedSelectedKeys: [],
+            excludeSelectedKeys: [],
+            excludeSelectedRowKeys: [],
+            //自定义人群参数结束
+            resultHistory: null,
+            unitAccountId: "",
+            activeKey: "",
+            setPersonVisible: false,
+            setPersonLoading: false,
+            tabKey:'1',
+            people: '0',
+            peopleList: [],
+            dataElse: [],
+            personName: "",
+            personNameVisible: false,
+            personDetail: null,
+            dataLoading: false,
+            personResourceDisabled: false,
+            personNameDisabled: false,
+            totalAllCause: 0,
+            projectId: undefined, // 搜索的账户ID
+            uploadAcountIds: '',
+            totalAll: 10,
+            finallyRightTree: [],
+            fileList: [],
+            relaxVisible: false,
+            relaxConfirmLoading: false,
+            pushVisible: false,
+            pushConfirmLoading: false,
+            causeVisible: false,
+            causeConfirmLoading: false,
+            labelCol: {span: 4},
+            wrapperCol: {span: 14},
+            confirmLoading: false,
+            mateTypeTasks: AppMarketService.setMateTypeTasks(), // 匹配类型
+            populationTypeTasks: AppMarketService.setPopulationTypeTasks(), // 人群包类型
+            platform: AppMarketService.setPlatform(), // 状态枚举
+            relaxStatus: '',
+            relaxData: null,
+            causeData: [], // 原因的table列表数据,
+            depData: [], // 相关项目的table列表数据,
+            acountData: [], // 相关账户的table列表数据,
+            acountColumns: AppMarketService.setAcountColumns(), // 相关账户的table列表
+            depColumns: AppMarketService.setDepColumns(), // 相关项目的table列表
+            causeColumns: AppMarketService.setCauseColumns(), // 原因的table列表
+            dataSource: [],
+            ipagination: {
+                current: 1,
+                pageSize: 10,
+                //   pageSizeOptions: ['10', '20', '30'],
+                showTotal: (total, range) => {
+                    return range[0] + "-" + range[1] + " 共" + total + "条"
+                },
+                showQuickJumper: true,
+                showSizeChanger:false,
+                pageSizeOptions: ['10', '30', '50'],
+                total: 0,
+                onChange: (current, pageSize) => {
+                    // 切换分页时的回调,
+                    // 当在页面定义change事件时,切记要把此处的事件清除,因为这两个事件重叠了,可能到时候会导致一些莫名的bug
+                    this.ipagination.current = current;
+                    this.ipagination.pageSize= pageSize;
+                    this.handleGetTableList()
+                }
+            },
+            accountIpagination: {
+                current: 1,
+                pageSize: 10,
+                //   pageSizeOptions: ['10', '20', '30'],
+                showTotal: (total, range) => {
+                    return range[0] + "-" + range[1] + " 共" + total + "条"
+                },
+                showQuickJumper: true,
+                showSizeChanger:false,
+                pageSizeOptions: ['10', '30', '50'],
+                total: 0,
+                onChange: (current, pageSize) => {
+                    // 切换分页时的回调,
+                    // 当在页面定义change事件时,切记要把此处的事件清除,因为这两个事件重叠了,可能到时候会导致一些莫名的bug
+                    this.accountIpagination.current = current;
+                    this.accountIpagination.pageSize= pageSize;
+                    this.handleAcountRelax(this.relaxStatus  ,this.relaxData)
+                }
+            },
+            columns: [
+                {
+                    title: '落地页名称',
+                    align: 'center',
+                    width: 200,
+                    ellipsis: true,
+                    dataIndex: 'landpageName'
+                },
+                {
+                    title: '所属项目',
+                    align: 'center',
+                    dataIndex: 'projectName',
+                    customRender(t) {
+                        if(t) {
+                            return t
+                        }
+                        else {
+                            return '-'
+                        }
+                    }
+                },
+                {
+                    title: '所属账户',
+                    align: 'center',
+                    dataIndex: 'authName',
+                    customRender(t) {
+                        if(t) {
+                            return t
+                        }
+                        else {
+                            return '-'
+                        }
+                    }
+                },
+                {
+                    title: '修改时间',
+                    dataIndex: 'landpageUpdateTime',
+                    align: 'center'
+                },
+                {
+                    title: '相关账户',
+                    dataIndex: 'accountCount',
+                    scopedSlots: {customRender: 'accountCount'},
+                    align: 'center'
+                },
+                {
+                    title: '相关组',
+                    dataIndex: 'unitCount',
+                     scopedSlots: {customRender: 'unitCount'},
+                    align: 'center'
+                }
+            ],
+            personRules: AppMarketService.setPersonRules(), // 上传人群包表单校验规则
+            tablePag: {
+                page: 1,
+                size: 10
+            },
+            // table 原因的分页
+            causePag: {
+                page: 1,
+                size: 10
+            },
+            tableSelectList: {},
+            acountRelaxDetail: {},
+            causeDetailData: {},
+            editPerson: null,
+        };
+    },
+    watch: {
+        unitAccountId: function(n,o) {
+            if(this.relaxVisible){
+                this.handleAcountRelax(this.relaxStatus  ,this.relaxData)
+            }
+        },
+        resultHistory: function(n,o) {
+            this.handleCauseTableData(this.tableSelectList.id);
+        },
+    },
+    computed: {
+        hasSelected() {
+            return this.selectedRowKeys.length > 0;
+        },
+        rowSelection() {
+            return {
+                onChange: (selectedRowKeys, selectedRows) => {
+                    this.incluedSelectedRowKeys = selectedRowKeys;
+                    this.incluedSelectedKeys = selectedRows
+                },
+                getCheckboxProps: record => ({
+                    props: {
+                        disabled: this.excludeSelectedRowKeys.indexOf(record.key)>-1,  
+                        name: record.name,
+                        defaultChecked:this.incluedSelectedRowKeys.indexOf(record.key)>-1
+                    },
+                }),
+            };
+        },
+        rowSelection2() {
+            return {
+                onChange: (selectedRowKeys, selectedRows) => {
+                    this.excludeSelectedRowKeys = selectedRowKeys;
+                    this.excludeSelectedKeys = selectedRows;
+                },
+                getCheckboxProps: record => ({
+                    props: {
+                        disabled: this.incluedSelectedRowKeys.indexOf(record.key)>-1, 
+                        name: record.name,
+                        defaultChecked:this.excludeSelectedRowKeys.indexOf(record.key)>-1
+                    },
+                }),
+            };
+        },
+        rowSelectionMin() {
+            return {
+                onChange: (selectedRowKeys, selectedRows) => {
+                    let index = this.finallyRightTree.findIndex(item => item.key === this.activeKey);
+                    this.finallyRightTree[index].incluedSelectedRowKeys = selectedRowKeys;
+                    this.finallyRightTree[index].incluedSelectedKeys = selectedRows;
+                },
+                getCheckboxProps: record => ({
+                    props: {
+                        disabled: this.finallyRightTree[this.finallyRightTree.findIndex(item => item.key === this.activeKey)].excludeSelectedRowKeys.indexOf(record.key)>-1,  
+                        name: record.name,
+                        defaultChecked:this.finallyRightTree[this.finallyRightTree.findIndex(item => item.key === this.activeKey)].incluedSelectedRowKeys.indexOf(record.key)>-1
+                    },
+                }),
+            };
+        },
+        rowSelectionMax() {
+            return {
+                onChange: (selectedRowKeys, selectedRows) => {
+                    let index = this.finallyRightTree.findIndex(item => item.key === this.activeKey);
+                    this.finallyRightTree[index].excludeSelectedRowKeys = selectedRowKeys;
+                    this.finallyRightTree[index].excludeSelectedKeys = selectedRows;
+                },
+                getCheckboxProps: record => ({
+                    props: {
+                        disabled: this.finallyRightTree[this.finallyRightTree.findIndex(item => item.key === this.activeKey)].incluedSelectedRowKeys.indexOf(record.key)>-1, 
+                        name: record.name,
+                        defaultChecked:this.finallyRightTree[this.finallyRightTree.findIndex(item => item.key === this.activeKey)].excludeSelectedRowKeys.indexOf(record.key)>-1
+                    },
+                }),
+            };
+        },
+    },
+    created() {
+        this.form = this.$form.createForm(this);
+    },
+    mounted() {
+        this.handleGetTableList({});
+    },
+    methods: {
+        onSelectExcludePerson(selectedRowKeys, selectedRows) {
+            
+            let index = this.finallyRightTree.findIndex(item => item.key === this.activeKey);
+            this.finallyRightTree[index].incluedSelectedRowKeys = selectedRowKeys;
+            this.finallyRightTree[index].incluedSelectedKeys = selectedRows;
+        },
+        onSelectPerson(selectedRowKeys, selectedRows) {
+            let index = this.finallyRightTree.findIndex(item => item.key === this.activeKey);
+            this.finallyRightTree[index].excludeSelectedRowKeys = selectedRowKeys;
+            this.finallyRightTree[index].excludeSelectedKeys = selectedRows;
+        },
+        // 自定义人群的改变
+        retargetTableChange(pagination, filters, sorter){
+            // //console.log(pagination);
+        },
+        checkPerson(item) {
+            if(item.people === '1' || item.people === '2'){
+                this.retargetAccountId(item.key);
+                item.tabKey = item.people
+            }
+            else if(item.people === '3'){
+                this.retargetAccountId(item.key);
+                item.tabKey='1'
+            }
+            this.$nextTick(() => {
+                item.incluedSelectedRowKeys = [];
+                item.incluedSelectedKeys = [];
+                item.excludeSelectedKeys = [];
+                item.excludeSelectedRowKeys = [];
+            })
+        },
+        // 自定义人群的--同时定向排除tab切换事件
+        retargetAccountId(accountId){
+            //console.log()
+            this.retargetDataAll=[];
+            this.loading=true;
+            
+            getAction('/kuaishou/batch/getPopulationList',{
+                accountId:accountId
+            }).then((res)=>{
+                // //console.log(res)
+                this.loading=false;
+                if(res.success){
+                    res.result.forEach((ele)=>{
+                        ele.key=ele.orientationId;
+                        ele.id= ele.orientationId;
+                        ele.name=ele.orientationName+"("+ele.orientationId+")";
+                        // ele.accountName=this.accountInfo.title
+                        ele.accountId=accountId;      
+                    })
+                    // this.retargetData=res.data;
+                    this.retargetDataAll=[...this.retargetDataAll,...res.result];
+                    
+                }
+            })
+        },
+        customCrowdChange(e){
+            //console.log(e);
+            
+           
+            if(e.target.value=='1' || e.target.value=='2'){
+                this.retargetTabChange();
+                this.tabKey=e.target.value
+            }else if(e.target.value=='3'){
+                this.retargetTabChange();
+                this.tabKey='1'
+            }
+            this.$nextTick(() => {
+                this.incluedSelectedRowKeys = [];
+                this.incluedSelectedKeys = [];
+                this.excludeSelectedKeys = [];
+                this.excludeSelectedRowKeys = [];
+            })
+        },
+        // 自定义人群的--同时定向排除tab切换事件
+        retargetTabChange(){
+            //console.log()
+            this.retargetDataAll=[];
+            this.loading=true;
+            
+            getAction('/kuaishou/batch/getPopulationList',{
+                accountId:this.personDetail.accountId
+            }).then((res)=>{
+                // //console.log(res)
+                this.loading=false;
+                if(res.success){
+                    res.result.forEach((ele)=>{
+                        ele.key=ele.orientationId   
+                        ele.id= ele.orientationId 
+                        ele.name=ele.orientationName+"("+ele.orientationId+")"
+                        // ele.accountName=this.accountInfo.title
+                        ele.accountId=this.personDetail.accountId           
+                    })
+                    // this.retargetData=res.data;
+                    this.retargetDataAll=[...this.retargetDataAll,...res.result];
+                    
+                }
+            })
+        },
+        getPeople() {
+            var data = ''
+            return new Promise((resolve, reject) => {
+                getAction('/kuaishou/batch/getPopulationList', { accountId: this.personDetail.accountId }).then((res) => {
+                if (res.success) {
+                    if (res.result) {
+                        this.peopleList = res.result.map((item, index) => {
+                            return {
+                                ...item,
+                                key: index,
+                            }
+                        })
+                        this.dataElse = this.peopleList
+                        resolve(res.result)
+                    }
+                }
+                })
+            })
+        },
+        handleCancelPerson() {
+            this.personNameVisible = false;
+        },
+        handleEditPerson(val) {
+            this.personNameVisible = true;
+            this.relaxVisible = false;
+            this.personDetail = val;
+            this.personName = val.authName;
+            let params = {};
+            params.accountId = val.accountId;
+            params.templateId = val.templateId;
+            getAction('/kuaishouDirectionalPackage/queryPopulationById' ,params).then(res => {
+                if(res.success) {
+                    this.retargetAccountId(val.accountId);
+                    this.editPerson = res.result;
+                    if(res.result.population&&res.result.excludePopulation){
+                        this.people = '3';
+                    }
+                    else if(res.result.population && !res.result.excludePopulation){
+                        this.people = '1';
+                    }
+                    else if(!res.result.population&&!res.result.excludePopulation){
+                        this.people = '0';
+                    }
+                    else{
+                        this.people = '2';
+                    }
+                    this.incluedSelectedRowKeys = res.result.population ? res.result.population : [];
+                    this.excludeSelectedRowKeys = res.result.excludePopulation ? res.result.excludePopulation : [];
+                }
+            })
+        },
+        handleAddPopulation() {
+            this.personLoading = true;
+            let params = {};
+            params.accountId = this.personDetail.accountId;
+            if(this.people == '0') {
+
+            }
+            else if(this.people == '1') {
+                params.population = this.incluedSelectedRowKeys;
+            }
+            else if(this.people == '2') {
+                params.excludePopulation = this.excludeSelectedRowKeys;
+            }
+            else {
+                params.population = this.incluedSelectedRowKeys;
+                params.excludePopulation = this.excludeSelectedRowKeys;
+            }
+            postAction('/kuaishouDirectionalPackage/editPopulation', params).then(res => {
+                if(res.success) {
+                    this.personLoading = false;
+                    this.$message.success('人群包修改成功');
+                    this.handleCancelPerson()
+                }
+                else {
+                    this.personLoading = false;
+                    this.$message.error(res.message);
+                }
+            }).catch(error => {
+
+            })
+
+
+        },
+        getTemplateList() {
+            this.form.resetFields();
+            this.projectId = undefined;
+            this.handleGetTableList({});
+        },
+        addNewTemplate(accountId) {
+            this.$refs.templateModal.create(null, 'add')
+        },
+        handleCauseSizeChange(current, pageSize) {
+            this.causePag = {
+                page: current,
+                size: pageSize
+            };
+            this.handleCauseTableData();
+        },
+        handleGetTableList(data) {
+            const paramsData = {
+                projectId: this.projectId,
+                pageNo:  this.ipagination.current,
+                pageSize: this.ipagination.pageSize
+            };
+            this.dataSource = []
+            this.dataLoading = true;
+            getAction('/kuaishouLandpagePackage/list', paramsData).then(result => {
+                this.dataLoading = false;
+                if (result.code === 200) {
+                    this.dataSource = result.result.list || [];
+                    this.ipagination.total = result.result.total || 0;
+                }
+                else {
+                    this.$message.error(result.message);
+                }
+            }).catch(error => {
+                this.dataLoading = false;
+                console.log(error, 'eeee');
+            });
+        },
+        handleDelete(data) {
+            let that = this
+            this.$confirm({
+                title: '删除提示',
+                content: '是否删除该定向包?',
+                onOk() {
+                    getAction('/kuaishouDirectionalPackage/delete', {id: data.id}).then(result => {
+                        if (result.code === 200) {
+                            that.handleGetTableList({});
+                            that.$message.success('删除成功');
+                        }
+                        else {
+                            that.$message.error(result.message);
+                        }
+                    }).catch(error => {
+                        console.log(error, 'eeee');
+                    });
+                }
+            });
+        },
+        handleAcountRelax(txt, recd) {
+            this.relaxStatus = txt;
+            this.relaxData = recd;
+            this.relaxVisible = true;
+            let params = {};
+            let url = "";
+            params.siteId = recd.siteId;
+           
+            params.pageNo = this.accountIpagination.current;
+            params.pageSize = this.accountIpagination.pageSize;
+            if(txt === 'unit') {
+                params.accountId = this.unitAccountId;
+                url = "/kuaishouLandpagePackage/getRelatedGroups";
+            }
+            else {
+                url = "/kuaishouLandpagePackage/getRelatedAccounts";
+            }
+            
+            // acountData
+            getAction(url, params).then( res => {
+                if(res.success) {
+                    this.acountData = res.result.list;
+                    this.accountIpagination.total = res.result.total;
+                }
+            })
+        },
+        handleRelaxCancel() {
+            this.unitAccountId = ''
+            this.relaxVisible = false;
+        },
+        handleCause(list) {
+            this.causeVisible = true;
+            this.handleCauseTableData(list.id);
+            this.tableSelectList = list;
+        },
+        handleCauseTableData(id) {
+            const paramsData = {
+                id: id,
+                pageNo: this.causePag.page,
+                pageSize: this.causePag.size,
+                status: this.resultHistory
+            };
+            postAction('/kuaishouDirectionalPackage/queryPushResults', paramsData).then(result => {
+                if (result.code === 200) {
+                    this.causeData = result.result.list || [];
+                    this.totalAllCause = result.result.total || 0;
+                }
+                else {
+                    this.$message.error(result.message);
+                }
+            }).catch(error => {
+                console.log(error, 'eeee');
+            });
+        },
+        handleApplyType(list) {
+            if(list.length > 0) {
+                this.finallyRightTree = list.map(item => {
+                    return {
+                        ...item,
+                        incluedSelectedRowKeys: [],
+                        incluedSelectedKeys: [],
+                        excludeSelectedKeys: [],
+                        excludeSelectedRowKeys: [],
+                        people: '0',
+                        tabKey: '1'
+                    }
+                });
+            }
+            else {
+                this.finallyRightTree = []
+            }
+            
+        },
+        handleEdit(val) {
+            this.$refs.templateModal.handleOk(val, 'edit')
+        },
+        handlePush(val) {
+            this.finallyRightTree = [];
+            this.tableSelectList = val;
+            this.pushVisible = true;
+        },
+        handleCauseCancel() {
+            this.causeVisible = false;
+        },
+        handleAgian(val) {
+            this.finallyRightTree = [];
+            this.finallyRightTree.push({
+                key: val.accountId,
+                title: val.authName,
+                incluedSelectedRowKeys: [],
+                incluedSelectedKeys: [],
+                excludeSelectedKeys: [],
+                excludeSelectedRowKeys: [],
+                people: '0',
+                tabKey: '1'
+            });
+            this.causeVisible = false;
+            this.handlePushSure();
+        },
+        handleSetPerson() {
+            this.setPersonLoading = true;
+            // this.finallyRightTree
+            let params = {};
+            params.id = this.tableSelectList.id;
+            params.datas = this.finallyRightTree.map(item => {
+                return {
+                    accountId: item.key,
+                    population: item.people === '0' ? []: item.people === '1' || item.people === '3' ? item.incluedSelectedRowKeys : [],
+                    excludePopulation: item.people === '0' ? []: item.people === '2' || item.people === '3' ? item.excludeSelectedRowKeys : [],
+                }
+            })
+            postAction('/kuaishouDirectionalPackage/pushDirectionalPackage' ,params).then(res => {
+                this.setPersonLoading = false;
+                if(res.success) {
+                    this.$message.success('推送中,请稍候')
+                    this.handlePersonCancel()
+                }
+                else {
+                    this.$message.error(res.result)
+                }
+            }).catch(error => {
+
+            })
+            
+        },
+        handlePersonCancel() {
+            this.setPersonVisible = false;
+        },
+        handlePushSure() {
+            if(this.finallyRightTree.length > 0) {
+                this.pushVisible = false;
+                this.setPersonVisible = true;
+                this.activeKey = this.finallyRightTree[0].key
+            }
+            else {
+                this.$message.error("请选择要分享的账户")
+            }
+            
+        },
+        handlePushCancel() {
+            this.pushVisible = false;
+        },
+        beforeUpload(file) {
+            this.cosUpload(file);
+        },
+        handleChange(info) {
+            this.fileList = info.fileList;
+        },
+        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.projectId = undefined;
+            this.handleGetTableList({});
+            this.$refs.selectTable.keyValue = "";
+            this.$refs.selectTable.getData()
+        },
+    }
+};
+</script>
+<style lang="less" scoped>
+    @import "url";
+</style>

+ 10 - 2
src/views/modules/creative-copywrit/creative-copywrit.less

@@ -6,15 +6,23 @@
         height: 500px !important;
         overflow-y: auto;
     }
+    .ad-name-tags-class {
+        width: 500px;
+        display: flex;
+        .name-tags-left {
+            width: 350px;
+        }
+    }
     .acount-title {
         display: flex;
         font-size: 14px;
-        height: 40px;
-        line-height: 40px;
         .acount-title-left {
             margin-right: 20px;
             width: 100px;
         }
+        .only-title-mater {
+            height: 35px;
+        }
         .examin-form-model {
             width: 500px;
             position: relative;

+ 527 - 66
src/views/modules/creative-copywrit/creative-copywrit.vue

@@ -313,7 +313,7 @@
             <a-form layout="inline" :selfUpdate="true">
                 <a-row :gutter="24">
                     <a-col :md="8" :sm="8">
-                        <selectTable :projectId.sync="queryParam.projectId"></selectTable>
+                        <selectTable :projectId.sync="queryParam.productId" ref="selectTable"></selectTable>
                     </a-col>
                     <a-col :md="8" :sm="8">
                         <a-form-item label="素材名称">
@@ -346,7 +346,7 @@
                     </a-col>
                     <a-col :md="8" :sm="8">
                         <span style="float: left; overflow: hidden" class="table-page-search-submitButtons">
-                            <a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
+                            <a-button type="primary" @click="handleSubmit" icon="search">查询</a-button>
                             <a-button type="primary" @click="searchRe" icon="reload" style="margin-left: 8px">重置</a-button>
                         </span>
                     </a-col>
@@ -368,7 +368,7 @@
             <a-button
                 @click="onCheckAllChange"
                 v-if="
-                queryParam.projectId &&
+                queryParam.productId &&
                 active == '1' &&
                 (role.roleCode == 'operator' ||
                     role.roleCode == 'kuaishouOperationManager' ||
@@ -381,7 +381,7 @@
             </a-button>
             <a-button
                 v-if="
-                queryParam.projectId &&
+                queryParam.productId &&
                 active == '1' &&
                 (role.roleCode == 'operator' ||
                     role.roleCode == 'kuaishouOperationManager' ||
@@ -390,16 +390,34 @@
                     role.roleCode == 'touTiaoOperationManager')
                 "
                 :disabled="checkArr.length == 0"
-                @click="tongbu"
+                @click="tongbu('1')"
             >
-                一键同步
+                一键同步头条
             </a-button>
+            <a-button
+                v-if="
+                queryParam.productId &&
+                active == '1' &&
+                (role.roleCode == 'operator' ||
+                    role.roleCode == 'kuaishouOperationManager' ||
+                    role.roleCode == 'admin' ||
+                    role.roleCode == 'operationAssistant' ||
+                    role.roleCode == 'touTiaoOperationManager')
+                "
+                :disabled="checkArr.length == 0"
+                @click="tongbu('3')"
+            >
+                一键同步头条内广
+            </a-button>
+            <!-- &&  -->
+            <a-button v-if="checkArr.length && active !== '0'" type="primary" @click="handleFodderWind">素材下线</a-button>
+            <a-button v-if="checkArr.length && active === '0'" type="primary" @click="handleApprovedClick">通过审核</a-button>
         </div>
         <a-tabs @change="callbackTwo" v-model="active" type="card" id="material-card">
             <a-tab-pane :tab="item.tab" v-for="item of examinelList" :key="item.value">
                 <a-spin :spinning="spinning">
                     <div v-if="dataSource.length > 0">
-                        <a-checkbox-group @change="onChangeCheck" v-model="checkArr" class="home-card">
+                        <a-checkbox-group @change="onChangeCheck($event, item)" v-model="checkArr" class="home-card">
                         <div class="home-item" v-for="(items, index) in dataSource" :key="index" @click="showDetail(items)">
                             <span v-if="items.excellent == 0"></span>
                             <span
@@ -600,7 +618,7 @@
                                         </a-menu-item>
                                     </a-menu>
                                 </a-dropdown>
-                                <a-checkbox :value="items.id" style="float: right" v-show="active == '1'"></a-checkbox>
+                                <a-checkbox :value="items.id" style="float: right" v-show="active == '0' || active == '1'"></a-checkbox>
                                 <br />
                                 {{ items.createTime | getDate }}
                             </span>
@@ -1465,14 +1483,100 @@
             <div>
                 <div class="acount-title">
                     <div class="acount-title-left">素材名称</div>
-                    <div class="acount-title-right">{{ currentPageOnlyList.materialName }}</div>
+                    <div class="acount-title-right">
+                        <div class="only-title-mater">{{ currentPageOnlyList.materialName }}</div>
+                    </div>
                 </div>
                 <div class="acount-title push-plate">
                     <div class="acount-title-left">创意标题</div>
                     <div class="acount-title-right">
                         <a-button type="primary" @click="handleAddOrigin"><a-icon type="plus" />创意标题</a-button>
-                        <a-button class="examin-select-title" @click="handleSelectTitle">选标题</a-button>
-                        <span>已填:{{ titleFiledResult.length || 0 }}</span>
+                        <!-- TODO 暂时功能隐藏 -->
+                        <!-- <a-button class="examin-select-title" @click="handleSelectTitle">选标题</a-button> -->
+                        <span style="margin-left: 20px;">已填:{{ titleFiledResult.length || 0 }}</span>
+                    </div>
+                </div>
+                <div class="acount-title">
+                    <div class="acount-title-left"></div>
+                    <div class="acount-title-right">
+                        <a-form :form="examinForm">
+                            <a-form-item
+                                v-for="item in defaultFormList"
+                                :key="item.id"
+                                class="examin-form-model"
+                                :label-col="labelCol"
+                                :wrapper-col="wrapperCol"
+                                label=""
+                            >
+                                <a-input
+                                    v-decorator="[
+                                        item.name,
+                                        {rules: [
+                                            {validator: validatePass, trigger: 'blur'}
+                                        ]}
+                                    ]"
+                                    class="examin-form-input"
+                                    :id="item.name"
+                                    placeholder="请输入"
+                                    @change="handleFormInputChang($event, item.name, item.id)"
+                                />
+                                <span class="examin-form-num">{{ item.lenSize }}/30</span>
+                                <a-icon class="examin-form-icon" type="delete" @click="handleDelOrigin(item)"/>
+                                <div class="ad-name-tags-class">
+                                    <div v-if="item.tabStatus === 'alone'" class="name-tags-left">
+                                        <a-tag
+                                            v-for="val in item.updateTagsList"
+                                            :key="val.id"
+                                            color="#1890ff"
+                                            @click="handleGetChangeAll(val.name, item.name, item.id)"
+                                        >
+                                            + {{ val.name }}
+                                        </a-tag>
+                                    </div>
+                                    <div v-if="item.tabStatus === 'all'" class="name-tags-left">
+                                        <a-tag
+                                            v-for="val in item.defaultTagsList"
+                                            :key="val.id"
+                                            color="#1890ff"
+                                            @click="handleGetChangeAll(val.name, item.name, item.id)"
+                                        >
+                                            + {{ val.name }}
+                                        </a-tag>
+                                    </div>
+                                    <div v-if="item.tabStatus === 'alone'"><a @click="handleMoreTagsShow(item.id, 'more')">更多</a></div>
+                                    <div v-if="item.tabStatus === 'all'"><a @click="handleMoreTagsShow(item.id, 'little')">收起</a></div>
+                                </div>
+                            </a-form-item>
+                        </a-form>
+                    </div>
+                </div>
+            </div>
+        </a-modal>
+        <a-modal
+            v-if="batchVisible"
+            title="审核通过"
+            dialog-class="examin-modal"
+            :visible="batchVisible"
+            @ok="handleBatchSure"
+            @cancel="handleBatchCancel"
+        >
+            <div>
+                <div class="acount-title">
+                    <div class="acount-title-left">素材名称</div>
+                    <div class="acount-title-right" :style="accountMaster">
+                        <div class="only-title-mater" v-for="item in modalShowBatchList" :key="item.id">
+                            {{ item.materialName }}
+                        </div>
+                    </div>
+                    <a-icon :type="materTitltStatus ? 'up' : 'down'" style="margin-top: 5px;margin-left: 15px;" @click="handleMaterTitleClick"/>
+                </div>
+                <div class="acount-title push-plate">
+                    <div class="acount-title-left">创意标题</div>
+                    <div class="acount-title-right">
+                        <a-button type="primary" @click="handleAddOrigin"><a-icon type="plus" />创意标题</a-button>
+                        <!-- TODO 暂时功能隐藏 -->
+                        <!-- <a-button class="examin-select-title" @click="handleSelectTitle">选标题</a-button> -->
+                        <span style="margin-left: 20px;">已填:{{ titleFiledResult.length || 0 }}</span>
                     </div>
                 </div>
                 <div class="acount-title">
@@ -1491,22 +1595,45 @@
                                     v-decorator="[
                                         item.name,
                                         { rules: [
-                                            {required: true, message: '请输入创意标题'},
-                                            {min: 5, max: 30, message: '创意标题5-30个字'}
+                                            {validator: validatePass, trigger: 'blur'}
                                         ]}
                                     ]"
                                     class="examin-form-input"
                                     placeholder="请输入"
-                                    @change="handleFormInputChang($event, item)"
+                                    @change="handleFormInputChang($event, item.name, item.id)"
                                 />
-                                <span class="examin-form-num">{{ handleFilterName(item.name) }}/30</span>
+                                <span class="examin-form-num">{{ item.lenSize }}/30</span>
                                 <a-icon class="examin-form-icon" type="delete" @click="handleDelOrigin(item)"/>
+                                <div class="ad-name-tags-class">
+                                    <div v-if="item.tabStatus === 'alone'" class="name-tags-left">
+                                        <a-tag
+                                            v-for="val in item.updateTagsList"
+                                            :key="val.id"
+                                            color="#1890ff"
+                                            @click="handleGetChangeAll(val.name, item.name, item.id)"
+                                        >
+                                            + {{ val.name }}
+                                        </a-tag>
+                                    </div>
+                                    <div v-if="item.tabStatus === 'all'" class="name-tags-left">
+                                        <a-tag
+                                            v-for="val in item.defaultTagsList"
+                                            :key="val.id"
+                                            color="#1890ff"
+                                            @click="handleGetChangeAll(val.name, item.name, item.id)"
+                                        >
+                                            + {{ val.name }}
+                                        </a-tag>
+                                    </div>
+                                    <div v-if="item.tabStatus === 'alone'"><a @click="handleMoreTagsShow(item.id, 'more')">更多</a></div>
+                                    <div v-if="item.tabStatus === 'all'"><a @click="handleMoreTagsShow(item.id, 'little')">收起</a></div>
+                                </div>
                             </a-form-item>
                         </a-form>
                     </div>
                 </div>
             </div>
-        </a-modal>  
+        </a-modal>
     </a-card>
 </template>
 <script>
@@ -1514,13 +1641,14 @@ import PermissionModal from '@/views/modules/material/modules/DepartModal';
 import {JeecgListMixin} from '@/mixins/JeecgListMixin';
 import JEllipsis from '@/components/jeecg/JEllipsis';
 import UploadToAli from '@femessage/upload-to-ali';
-import selectTable from '@/views/modules/Statistics/components/selectPagination.vue';
-import {fileCheck, fileEdit, fileEditAll, fileInsertV2, fileEditUpdate} from '@/api/actor';
+import selectTable from '@/views/modules/material/comment/selectTable.vue';
+import {fileCheck, fileEdit, fileEditAll, fileInsertV2, fileEditUpdate, fileEditUpdateBatch} from '@/api/actor';
 import {deleteAction, getAction, postAction, putAction} from '@/api/manage';
 import uploadFile from '@/components/uploadFile.vue';
 import {closeAllVideoFun, stopOtherVideo} from '@/utils/videoControl';
 import accountCheck from '@/views/modules/material/accountCheck';
 import accountCheckBytedance from '@/views/modules/material/accountCheckBytedance';
+import {urlAcount} from '../account-config/account-config-server.js';
 
 import qs from 'qs';
 import {mapGetters} from 'vuex';
@@ -1540,6 +1668,14 @@ export default {
     },
     data() {
         return {
+            adNameTags: [],
+            materTitltStatus: false,
+            accountMaster: {
+                height: '35px',
+                overflow: 'hidden'
+            },
+            batchVisible: false,
+            showTabsTitle: '',
             taobaoSpecialOfferTitle: 'taobao',
             defaultSolganStatus: 'input',
             defaultSolganTitle: 'test',
@@ -1722,7 +1858,8 @@ export default {
             bohuiShow: false,
             waterLoading: false,
             videoTag: [],
-            videoVisibleChange: ''
+            videoVisibleChange: '',
+            modalShowBatchList: []
         };
     },
     filters: {
@@ -1809,6 +1946,7 @@ export default {
             }
         });
         this.getHangye();
+        this.handleGetCreativeWord();
     },
     watch: {
         $route(n, o) {
@@ -1819,7 +1957,7 @@ export default {
                 this.loadData();
             }
         },
-        'queryParam.projectId'(n, o) {
+        'queryParam.productId'(n, o) {
             if (n !== '') {
                 this.getList(n);
             }
@@ -1861,6 +1999,246 @@ export default {
     },
     methods: {
         ...mapGetters(['nickname', 'avatar', 'userInfo']),
+        handleSubmit() {
+            this.searchQuery();
+            this.checkArr = [];
+        },
+        handleMoreTagsShow(val, type) {
+            if (type === 'more') {
+                this.defaultFormList.forEach(item => {
+                    if (item.id === val) {
+                        item.tabStatus = 'all';
+                    }
+                });
+            }
+            else if (type === 'little') {
+                this.defaultFormList.forEach(item => {
+                    if (item.id === val) {
+                        item.tabStatus = 'alone';
+                    }
+                });
+            }
+        },
+        handleGetCreativeWord() {
+            getAction('/ctop/ByteDanceCreativeWordPackage/list').then(result => {
+                if (result.code === 0) {
+                    this.adNameTags = result.result.records;
+                }
+                else {
+                    this.$message.error(result.message);
+                }
+            }).catch(error => {
+                console.log(error, 'eeee');
+            });
+        },
+        validatePass(rule, value, callback) {
+            this.$nextTick(() => {
+                let finallyLenList = this.handleJudgeExec(value);
+                console.log(finallyLenList, 'finallyLenList---finallyLenList--finallyLenList');
+                let updateFinallyResult = this.adNameTags.filter(item => finallyLenList.includes(item.name)).map(val => val.name);
+                console.log(updateFinallyResult, '000000000000');
+                let resultSelectSize = 0;
+                if (finallyLenList.length) {
+                    const inputDefaultLen = value.length;
+                    let tagsLen = finallyLenList.length * 4;
+                    let tagsSureLen = 0;
+                    this.adNameTags.forEach(item => {
+                        finallyLenList.forEach(val => {
+                            if (item.name === val) {
+                                tagsSureLen += item.maxWordLen;
+                            }
+                        });
+                    });
+                    finallyLenList.forEach(item => {
+                        tagsLen += item.length;
+                    });
+                    resultSelectSize = inputDefaultLen - tagsLen + tagsSureLen;
+                }
+                else {
+                    resultSelectSize = value.length;
+                }
+                if (resultSelectSize === 0) {
+                    callback(new Error('请输入'));
+                }
+                else if (resultSelectSize > 30 || resultSelectSize < 5) {
+                    callback(new Error('创意标题5-30个字'));
+                }
+                else if (updateFinallyResult.length > 2) {
+                    callback(new Error('最多选择两个词包'));
+                }
+                else {
+                    callback();
+                }
+            });
+        },
+        handleJudgeExec(item) {
+            let re = /\{\{(.+?)\}\}/g;
+            let array = [];
+            let temp;
+            while ((temp = re.exec(item))) {
+                array.push(temp[1]);
+            };
+            return array;
+        },
+        // 点击获取光标位置进行字段插入
+        handleGetChangeAll(item, field, formId) {
+            let node = document.getElementById(field);
+            let startPos = node.selectionStart; // input 第0个字符到选中的字符
+            let endPos = node.selectionEnd; // 选中的字符到最后的字符
+            let txt = node.value;
+            this.$nextTick(() => {
+                let finallyLenList = this.handleJudgeExec(txt);
+                let updateFinallyResult = this.adNameTags.filter(item => finallyLenList.includes(item.name)).map(val => val.name);
+                if (updateFinallyResult.length >= 2) {
+                    this.$message.error('最多选择两个词包');
+                    return;
+                }
+                if (startPos === 0 || endPos === 0) {
+                    txt += '{{' + item + '}}';
+                    this.examinForm.setFieldsValue({[field]: txt});
+                }
+                else {
+                    this.examinForm.setFieldsValue({[field]: txt.substring(0, startPos) + '{{' + item + '}}' + txt.substring(endPos)});
+                    node.selectionStart = startPos + item.length + 6;
+                    node.selectionEnd = startPos + item.length + 6;
+                }
+                node.focus();
+                node.blur();
+            });
+            this.$nextTick(() => {
+                const dynamicWordPackIds = [];
+                let changeData = this.handleJudgeExec(this.examinForm.getFieldsValue()[field]);
+                let updateChangeData = this.adNameTags.filter(item => changeData.includes(item.name)).map(val => val.name);
+                const inputDefaultLen = this.examinForm.getFieldsValue()[field].length;
+                let tagsLen = updateChangeData.length * 4;
+                let tagsSureLen = 0;
+                let resultSelectSize = 0;
+                this.adNameTags.forEach(item => {
+                    updateChangeData.forEach(val => {
+                        if (item.name === val) {
+                            tagsSureLen += item.maxWordLen;
+                            dynamicWordPackIds.push(item.creativeWordId);
+                        }
+                    });
+                });
+                updateChangeData.forEach(item => {
+                    tagsLen += item.length;
+                });
+                resultSelectSize = inputDefaultLen - tagsLen + tagsSureLen;
+                this.defaultFormList.forEach(item => {
+                    if (item.id === formId) {
+                        item.lenSize = resultSelectSize;
+                        item.value = this.examinForm.getFieldsValue()[field];
+                        item.wordPackId = dynamicWordPackIds;
+                    }
+                });
+            });
+        },
+        handleMaterTitleClick() {
+            this.materTitltStatus = !this.materTitltStatus;
+            if (this.materTitltStatus) {
+                this.accountMaster = {
+                    height: 'auto'
+                };
+            }
+            else {
+                this.accountMaster = {
+                    height: '35px',
+                    overflow: 'hidden'
+                };
+            }
+        },
+        handleApprovedClick() {
+            const batchList = [];
+            this.defaultFormList = [];
+            this.dataSource.forEach(item => {
+                if (this.checkArr.includes(item.id)) {
+                    batchList.push(item);
+                }
+            });
+            this.modalShowBatchList = batchList;
+            this.batchVisible = true;
+            this.materTitltStatus = false;
+            this.accountMaster = {
+                height: '35px',
+                overflow: 'hidden'
+            };
+            for (let i = 0; i < 3; i++) {
+                const randomNum = new Date().getTime() + Math.ceil(Math.random() * 1000);
+                this.defaultFormList.push({
+                    id: randomNum,
+                    name: 'username' + randomNum,
+                    value: '',
+                    lenSize: 0,
+                    tabStatus: 'alone',
+                    defaultTagsList: this.adNameTags,
+                    updateTagsList: this.adNameTags.slice(0, 4)
+                });
+            }
+        },
+        handleBatchSure() {
+            if (this.defaultFormList && this.defaultFormList.length < 3) {
+                this.$message.error('请至少输入3条标题');
+                return;
+            }
+            let changeSlogan = this.defaultFormList;
+            changeSlogan.forEach(item => {
+                item.title = item.value;
+                item.creative_word_ids = item.wordPackId;
+            });
+            let params = {
+                ids: this.modalShowBatchList.map(item => item.id) || [],
+                auditorId: this.userInfo().id,
+                status: 1,
+                slogans: changeSlogan
+            };
+            this.examinForm.validateFields(err => {
+                if (!err) {
+                    fileEditUpdateBatch(params).then(res => {
+                        if (res.code === 200) {
+                            this.refuseReason = '';
+                            this.batchVisible = false;
+                            this.defaultFormList = [];
+                            this.$message.success('审核成功');
+                            this.loadData();
+                        }
+                        
+                    });
+                }
+            });
+        },
+        handleBatchCancel() {
+            this.batchVisible = false;
+        },
+        handleFodderWind() {
+            if (this.checkArr.length > 8) {
+                this.$message.error('最多可以支持同时选择8个视频');
+                return;
+            }
+            const paramsData = {
+                offlineFlag: 1,
+                id: this.checkArr.join(',')
+            };
+            let that = this;
+            this.$confirm({
+                title: '下线提示',
+                content: '是否下线选中视频',
+                onOk() {
+                    getAction(urlAcount + '/bytedance-api/advertiser/materialInfoController/updMaterialOfflineById', paramsData).then(result => {
+                        if (result.code === 0) {
+                            that.searchQuery();
+                            that.checkArr = [];
+                            that.$message.success(result.message);
+                        }
+                        else {
+                            that.$message.error(result.message);
+                        }
+                    }).catch(error => {
+                        console.log(error, 'eeee');
+                    });
+                }
+            });
+        },
         compareToFirstPassword(rule, value, callback) {
             if (value && value.length > 30 || value.length < 5) {
                 callback('创意标题5-30个字');
@@ -1877,7 +2255,6 @@ export default {
                     this.showUrlWater = res.result.watermarkUrl;
                     this.name = res.result.watermarkCode;
                     this.materialName = res.result.materialName;
-                    // 0317淘特除螨仪.mp4     0317幸福里 没钱 高清版.mp4    0316幸福里来北京五年 高清  大妈和美女2高清.mp4  WIFIAQZS2004JYL.mp4
                     res.result.slogans.forEach(item => {
                         item.name = 'username' + item.id;
                     });
@@ -1937,10 +2314,10 @@ export default {
                 this.solganForm.setFieldsValue({[data.name]: data.slogan});
             });
         },
-        handleFormInputChang(e, data) {
+        handleFormInputChang(e, field, formId) {
             const changeFiled = [];
             this.defaultFormList.forEach(item => {
-                if (item.id === data.id) {
+                if (item.id === formId) {
                     item.value = e.target.value;
                 }
             });
@@ -1949,7 +2326,34 @@ export default {
                     changeFiled.push(item.value);
                 }
             });
-            this.titleFiledResult = changeFiled;
+            this.$nextTick(() => {
+                const dynamicWordPackIds = [];
+                let finallyLenList = this.handleJudgeExec(this.examinForm.getFieldsValue()[field]);
+                let updateFinallyResult = this.adNameTags.filter(item => finallyLenList.includes(item.name)).map(val => val.name);
+                const inputDefaultLen = this.defaultFormList.filter(item => item.id === formId)[0].value.length;
+                let tagsLen = updateFinallyResult.length * 4;
+                let tagsSureLen = 0;
+                let resultSelectSize = 0;
+                this.adNameTags.forEach(item => {
+                    updateFinallyResult.forEach(val => {
+                        if (item.name === val) {
+                            tagsSureLen += item.maxWordLen;
+                            dynamicWordPackIds.push(item.creativeWordId);
+                        }
+                    });
+                });
+                updateFinallyResult.forEach(item => {
+                    tagsLen += item.length;
+                });
+                resultSelectSize = inputDefaultLen - tagsLen + tagsSureLen;
+                this.defaultFormList.forEach(item => {
+                    if (item.id === formId) {
+                        item.lenSize = resultSelectSize;
+                        item.wordPackId = dynamicWordPackIds;
+                    }
+                });
+                this.titleFiledResult = changeFiled;
+            });
         },
         handleCheckBoxChang(data) {
             this.applyTypeOption = data;
@@ -2007,7 +2411,10 @@ export default {
                 this.defaultFormList.push({
                     id: dateTime,
                     name: name,
-                    value: item
+                    value: item,
+                    tabStatus: 'alone',
+                    defaultTagsList: this.adNameTags,
+                    updateTagsList: this.adNameTags.slice(0, 4)
                 });
             });
             this.titleResult = [];
@@ -2030,7 +2437,11 @@ export default {
             this.defaultFormList.push({
                 id: randomNum,
                 name: 'username' + randomNum,
-                value: ''
+                value: '',
+                lenSize: 0,
+                tabStatus: 'alone',
+                defaultTagsList: this.adNameTags,
+                updateTagsList: this.adNameTags.slice(0, 4)
             });
         },
         handleDelOrigin(list) {
@@ -2038,21 +2449,47 @@ export default {
             this.defaultFormList = formData.filter(item => list.id !== item.id);
         },
         handleExamin(data) {
+            this.defaultFormList = [];
             getAction('/ctop/materialInfo/queryById', {
                 id: data.id
             }).then(res => {
                 if (res.success) {
                     if (res.result.slogans.length) {
                         res.result.slogans.forEach(item => {
+                            let finallyLenList = this.handleJudgeExec(item.slogan);
+                            let resultSelectSize = 0;
+                            if (finallyLenList.length) {
+                                const inputDefaultLen = item.slogan.length;
+                                let tagsLen = finallyLenList.length * 4;
+                                let tagsSureLen = 0;
+                                this.adNameTags.forEach(item => {
+                                    finallyLenList.forEach(val => {
+                                        if (item.name === val) {
+                                            tagsSureLen += item.maxWordLen;
+                                        }
+                                    });
+                                });
+                                finallyLenList.forEach(item => {
+                                    tagsLen += item.length;
+                                });
+                                resultSelectSize = inputDefaultLen - tagsLen + tagsSureLen;
+                            }
+                            else {
+                                resultSelectSize = item.slogan.length;
+                            }
                             item.name = 'username' + item.id;
                             item.value = item.slogan;
+                            item.lenSize = resultSelectSize;
+                            item.tabStatus = 'alone';
+                            item.defaultTagsList = this.adNameTags;
+                            item.updateTagsList = this.adNameTags.slice(0, 4);
                         });
                         this.defaultFormList = res.result.slogans;
-                        this.$nextTick(() => {
-                            this.defaultFormList.forEach(item => {
-                                this.defaultFormList.setFieldsValue({[item.name]: item.slogan});
-                            });
-                        });
+                        // this.$nextTick(() => {
+                        //     this.defaultFormList.forEach(item => {
+                        //         this.defaultFormList.setFieldsValue({[item.name]: item.slogan});
+                        //     });
+                        // });
                     }
                     else {
                         for (let i = 0; i < 3; i++) {
@@ -2060,7 +2497,11 @@ export default {
                             this.defaultFormList.push({
                                 id: randomNum,
                                 name: 'username' + randomNum,
-                                value: ''
+                                value: '',
+                                lenSize: 0,
+                                tabStatus: 'alone',
+                                defaultTagsList: this.adNameTags,
+                                updateTagsList: this.adNameTags.slice(0, 4)
                             });
                         }
                     }
@@ -2074,6 +2515,7 @@ export default {
             this.causeVisible = true;
             this.recommendVisible = false;
             this.titleResult = [];
+            this.checkArr = [];
         },
         handleCauseCancel() {
             this.causeVisible = false;
@@ -2084,11 +2526,16 @@ export default {
                 this.$message.error('请至少输入3条标题');
                 return;
             }
+            let changeSlogan = this.defaultFormList;
+            changeSlogan.forEach(item => {
+                item.title = item.value;
+                item.creative_word_ids = item.wordPackId;
+            });
             let params = {
                 id: this.currentPageOnlyList.id,
                 auditorId: this.userInfo().id,
                 status: 1,
-                slogans: this.defaultFormList.map(item => item.value) || []
+                slogans: changeSlogan
             };
             this.examinForm.validateFields(err => {
                 if (!err) {
@@ -2320,23 +2767,29 @@ export default {
             return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0;
         },
         moment,
-        tongbu() {
-            getAction('/ctop/project/queryById', {id: this.queryParam.projectId}).then(res => {
-                if (res.success) {
-                    if (res.result.mediaId === '1' || res.result.mediaId === '3') {
-                        this.$refs.check.getData('/ctop/userAllocation/getAccountListByProjectId', {
-                            userId: this.userInfo().id,
-                            projectId: this.queryParam.projectId
-                        });
-                    }
-                    else if (res.result.mediaId === '2' || res.result.mediaId === '4') {
-                        this.$refs.accountCheckBytedance.getParticipateList(this.queryParam.projectId);
-                    }
-                }
-                else {
-                    this.$message.error('网络波动,请稍后再试');
-                }
-            });
+        tongbu(value) {
+            // getAction('/ctop/project/queryById', {id: this.queryParam.projectId}).then(res => {
+            //     if (res.success) {
+            //         if (res.result.mediaId === '1' || res.result.mediaId === '3') {
+            //             this.$refs.check.getData('/ctop/userAllocation/getAccountListByProjectId', {
+            //                 userId: this.userInfo().id,
+            //                 projectId: this.queryParam.projectId
+            //             });
+            //         }
+            //         else if (res.result.mediaId === '2' || res.result.mediaId === '4') {
+            //             this.$refs.accountCheckBytedance.getParticipateList(this.queryParam.projectId);
+            //         }
+            //     }
+            //     else {
+            //         this.$message.error('网络波动,请稍后再试');
+            //     }
+            // });
+            this.mediaId = value
+            this.$refs.check.getData('/ctop/userAllocation/getAccountListByUserIdAndProductId', {
+                userId: this.userInfo().id,
+                productId: this.queryParam.productId,
+                mediaId: value,
+            })
         },
         implement(data) {
             let params = {};
@@ -2419,22 +2872,26 @@ export default {
             this.queryParam = {
                 type: 'VIDEO',
                 userId: this.userInfo().id,
-                status: this.active
-            };
+                status: this.active,
+                productId: ''
+            }
+            this.$refs.selectTable.keyValue = "";
+            this.$refs.selectTable.getData()
             this.labelValue = [];
             this.loadData(1);
+            this.checkArr = [];
         },
         getList(value) {
-            if (value) {
-                getAction('/ctop/projectMember/participateListV2', {
-                    userId: this.userInfo().id,
-                    projectId: value
-                }).then(res => {
-                    if (res.code === 0) {
-                        this.mediaId = res.result.records[0].mediaId;
-                    };
-                });
-            }
+            // if (value) {
+            //     getAction('/ctop/projectMember/participateListV2', {
+            //         userId: this.userInfo().id,
+            //         projectId: value
+            //     }).then(res => {
+            //         if (res.code === 0) {
+            //             this.mediaId = res.result.records[0].mediaId;
+            //         };
+            //     });
+            // }
             this.loadData();
         },
         onChangeCheckImage(checkedList) {
@@ -2442,7 +2899,10 @@ export default {
                 this.checkAllImage = false;
             }
         },
-        onChangeCheck(checkedList) {
+        onChangeCheck(checkedList, data) {
+            if (data.value === '0') {
+                this.showTabsTitle = '0';
+            }
             if (checkedList.length === 0) {
                 this.checkAll = false;
             }
@@ -2650,7 +3110,8 @@ export default {
                         this.visibleDetail = false;
                         closeAllVideoFun();
                     });
-                } else {
+                }
+                else {
                     fileEdit({
                         id: this.id,
                         status: editStatus,
@@ -2926,7 +3387,7 @@ export default {
                     type: 'VIDEO',
                     userId: this.userInfo().id,
                     status: key,
-                    projectId: this.queryParam.projectId
+                    productId: this.queryParam.productId
                 }
                 if (this.labelValue.length >= 1) {
                     this.queryParam.tagCode = this.labelValue[this.labelValue.length - 1];
@@ -2934,7 +3395,7 @@ export default {
                 else {
                     this.queryParam.tagCode = '';
                 }
-                if (this.form.getFieldValue('projectId')) {
+                if (this.form.getFieldValue('productId')) {
                     this.form.setFieldsValue({
                         projectId: ''
                     });

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

@@ -143,6 +143,7 @@ export default {
             }
             defaultCheckKey.splice(value, 1);
             this.checkedKeys = defaultCheckKey;
+            this.$emit('applyType', this.applyTypeOption);
         },
         onChange(e) {
             const value = e.target.value;

+ 47 - 28
src/views/modules/crowd-control/crowd-control-service.js

@@ -11,23 +11,27 @@ class AppMarketService {
         return [
             {
                 title: '账户名称',
-                dataIndex: 'accountName',
-                width: '30%'
+                dataIndex: 'authName',
+                width: '30%',
+                align: 'center'
             },
             {
-                title: '所属项目',
-                dataIndex: 'projectName',
-                width: '30%'
+                title: '覆盖数量',
+                dataIndex: 'coverNum',
+                width: '30%',
+                align: 'center'
             },
             {
                 title: '人群包数量',
-                dataIndex: 'count',
-                width: '20%'
+                dataIndex: 'populationCount',
+                width: '20%',
+                align: 'center'
             },
             {
                 title: '状态',
                 dataIndex: 'statusStr',
-                width: '20%'
+                width: '20%',
+                align: 'center'
             }
         ]
     }
@@ -36,40 +40,55 @@ class AppMarketService {
     setCauseColumns() {
         return [
             {
-                title: '项目名称',
-                dataIndex: 'projectName',
-                width: '30%'
+                title: '账户名称',
+                dataIndex: 'authName',
+                width: '25%',
+                align: 'center'
             },
             {
-                title: '账户名称',
-                dataIndex: 'accountName',
-                width: '30%'
+                title: '推送结果',
+                dataIndex: 'result',
+                width: '25%',
+                align: 'center'
             },
             {
-                title: '原因',
+                title: '失败原因',
                 dataIndex: 'message',
-                width: '40%'
+                width: '25%',
+                align: 'center',
+                customRender(t) {
+                    if(t === 'OK') {
+                        return '-';
+                    }
+                    else {
+                        return t;
+                    }
+                }
+            },
+            {
+                title: '操作',
+                dataIndex: 'action',
+                scopedSlots: {customRender: 'action'},
+                width: '25%',
+                align: 'center'
             }
         ]
     }
 
-    // 相关项目的table列表
+    // 相关的table列表
     setDepColumns() {
         return [
             {
-                title: '项目名称',
-                dataIndex: 'projectName',
-                width: '40%'
+                title: '广告组名称',
+                dataIndex: 'unitName',
+                width: '50%',
+                align: 'center'
             },
             {
-                title: '账户数量',
-                dataIndex: 'accountCount',
-                width: '20%'
-            },
-            {
-                title: '人群包数量',
-                dataIndex: 'count',
-                width: '20%'
+                title: '所属账户',
+                dataIndex: 'authName',
+                width: '50%',
+                align: 'center'
             }
         ]
     }

+ 5 - 2
src/views/modules/crowd-control/crowd-control.less

@@ -1,13 +1,16 @@
 .crowd-control-content {
     background: #fff;
-    height: calc(100vh - 137px);
+    // height: calc(100vh - 137px);
     padding: 20px;
     overflow-y: auto;
+    .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;
+            width: 100% !important;
         }
         .reset-class {
             margin-right: 10px !important;

+ 320 - 138
src/views/modules/crowd-control/crowd-control.vue

@@ -1,52 +1,43 @@
 <template>
     <div class="crowd-control-content">
-        <div class="control-con-header">
+        <div class="table-page-search-wrapper">
             <a-form
-                class="grid-form" layout="inline"
+                layout="inline"
                 :form="form"
                 hide-required-mark
                 @submit="handleQueryList"
             >
-                <a-row class="grid-form-options">
-                    <a-form-item
-                        class="grid-form-item"
-                        label="名称"
-                        :colon="false"
-                    >
-                        <a-input
-                            v-decorator="['name']" type="text"
-                            placeholder="请输入"
-                        />
-                    </a-form-item>
-                    <a-form-item
-                        class="grid-form-item grid-form-item-account" label="账户"
-                        :colon="false"
-                    >
-                        <acount-search class="acount-search-class" :appId.sync="acountId" :multiple="false"></acount-search>
-                    </a-form-item>
-                    <a-form-item
-                        class="grid-form-item grid-form-type" label="状态"
-                        :colon="false"
-                    >
-                        <a-select
-                            v-decorator="['status']"
-                            placeholder="请选择"
-                            allow-clear
+                <a-row :gutter="24">
+                    <a-col :md="8" :sm="8" :xxl="6">
+                        <selectTable :projectId.sync="projectId" ref="selectTable" :requireCheck="false"></selectTable>
+                    </a-col>
+                    <a-col :md="8" :sm="8" :xxl="6">
+                        <a-form-item
+                            label="名称"
                         >
-                            <a-select-option v-for="item in statusTasks" :key="item.label">
-                                {{ item.value }}
-                            </a-select-option>
-                        </a-select>
-                    </a-form-item>
-                    <a-form-item class="form-handle-btn">
-                        <a-button type="default" class="reset-class" @click="handleResetForm">重置</a-button>
-                        <a-button type="primary" html-type="submit">查询</a-button>
-                    </a-form-item>
+                            <a-input
+                                v-decorator="['name']" type="text"
+                                placeholder="请输入"
+                            />
+                        </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="handleUploadPerson" class="middle-button">
+                                上传人群包
+                            </a-button>
+                             <a-button type="primary" @click="handleUpdatePerson" v-if="realShow" :loading="realLoading">
+                                更新人群
+                            </a-button>
+                           
+                        </span>
+                        
+                    </a-col>
                 </a-row>
             </a-form>
-            <a-button type="primary" class="upload-person" @click="handleUploadPerson">
-                上传人群包
-            </a-button>
+            
         </div>
         <div class="control-con-table">
             <a-table
@@ -58,15 +49,19 @@
                 :pagination="false"
             >
                 <span slot="action" slot-scope="text, record">
-                    <a @click="handleEdit(record)" :disabled="record.status !== 4">推送</a>
+                    <a @click="handleEdit(record)">推送</a>
                     <a-divider type="vertical" />
                     <a @click="handleDelete(record)">删除</a>
                 </span>
+                                
+                <span slot="actionMore" slot-scope="text, record">
+                    <a @click="handleHistory(record)">推送历史</a>
+                </span>
                 <span slot="cause" slot-scope="text, record">
                     <a class="cause-text-class" @click="handleCause(record)">失败原因</a>
                 </span>
                 <span slot="depRelax" slot-scope="text, record">
-                    <a @click="handleAcountRelax('dep', record)">{{ text }}</a>
+                    <a @click="handleAcountRelax('unit', record)">{{ text }}</a>
                 </span>
                 <span slot="acountRelax" slot-scope="text, record">
                     <a @click="handleAcountRelax('acount', record)">{{ text }}</a>
@@ -77,7 +72,6 @@
                 :total="totalAll"
                 :show-total="total => `共 ${totalAll} 条`"
                 size="small"
-                show-size-changer
                 show-quick-jumper
                 @change="onShowSizeChange"
                 @showSizeChange="onShowSizeChange"
@@ -100,21 +94,30 @@
                     :label-col="labelCol"
                     :wrapper-col="wrapperCol"
                 >
-                    <a-form-model-item label="匹配类型" prop="resource">
-                        <a-radio-group v-model="personForm.resource" :disabled="personResourceDisabled">
-                            <a-radio v-for="item in mateTypeTasks" :key="item.label" :value="item.label">{{ item.value }}</a-radio>
-                        </a-radio-group>
-                    </a-form-model-item>
-                    <a-form-model-item ref="name" label="人群包名称" prop="name">
+                    <selectTable
+                        :projectId.sync="uploadProjectId"
+                        :labelCol="labelCol"
+                        :disabled="disabled"
+                        :requireCheck="true"
+                        v-if="!disabled"
+                    ></selectTable>
+                     <a-form-model-item ref="name" label="人群包名称" prop="name">
                         <a-input
                             v-model="personForm.name"
                             placeholder="请输入人群包名称"
                             :disabled="personNameDisabled"
                         />
                     </a-form-model-item>
-                    <a-form-model-item label="选择账户" class="grid-form-item-account">
-                        <acount-search class="acount-search-class" :appId.sync="uploadAcountIds" :multiple="false"></acount-search>
+                    <a-form-model-item label="匹配类型" prop="resource">
+                        <a-radio-group v-model="personForm.resource" :disabled="personResourceDisabled">
+                            <a-radio v-for="item in mateTypeTasks" :key="item.label" :value="item.label">{{ item.value }}</a-radio>
+                        </a-radio-group>
                     </a-form-model-item>
+                   
+                    <!-- <a-form-model-item label="选择账户" class="grid-form-item-account">
+                        <acount-search class="acount-search-class" :appId.sync="uploadAcountIds" :multiple="false"></acount-search>
+                    </a-form-model-item> -->
+
                     <a-form-model-item label="上传人群包">
                         <a-upload
                             name="file"
@@ -156,7 +159,7 @@
                         </a-radio-group>
                     </div>
                 </div>
-                <tree-select @applyType="handleApplyType"></tree-select>
+                <tree-select :httpSrc="src" @applyType="handleApplyType" :projectId="tableSelectList.projectId" :templateId="tableSelectList.id"></tree-select>
             </div>
         </a-modal>
         <a-modal
@@ -181,7 +184,7 @@
             </div>
         </a-modal>   
         <a-modal
-            :title="relaxStatus === 'dep' ? '相关项目' : '相关账户'"
+            :title="relaxStatus === 'unit' ? '相关组' : '相关账户'"
             v-if="relaxVisible"
             :visible="relaxVisible"
             :confirm-loading="relaxConfirmLoading"
@@ -190,32 +193,60 @@
             @cancel="handleRelaxCancel"
         >
             <div>
-                <div class="acount-title">
-                    <div class="acount-title-left">人群包名称</div>
-                    <div class="acount-title-right">{{ acountRelaxDetail.orientationName }}</div>
-                </div>
-                <div class="acount-title push-plate">
-                    <div class="acount-title-left">目标账户</div>
-                    <div class="acount-title-right">{{ acountRelaxDetail.accountName }}</div>
-                </div>
-                <template v-if="relaxStatus === 'dep'">
-                    <a-table :columns="depColumns" :data-source="depData" bordered>
+                <template v-if="relaxStatus === 'unit'">
+                    <AcountSearch :appId.sync="unitAccountId" :multiple="false"  request="2,4"   ref="treeSelect" style="margin-bottom:8px;width:300px " />   
+                    <a-table :columns="depColumns" :data-source="depData" bordered :pagination="accountIpagination">
                     </a-table>
                 </template>
                 <template v-if="relaxStatus === 'acount'">
-                    <a-table :columns="acountColumns" :data-source="acountData" bordered></a-table>
+                    <a-table :columns="acountColumns" :data-source="acountData" bordered :pagination="accountIpagination"></a-table>
                 </template>
             </div>
         </a-modal>
+
+        <a-modal
+            title="推送历史"
+            v-if="historyVisible"
+            :visible="historyVisible"
+            :confirm-loading="causeConfirmLoading"
+            :footer="null"
+            dialog-class="cause-modal"
+            @cancel="historyVisible = false"
+        >
+            <div>
+                <div class="cause-modal-table-class">
+                    <a-table :columns="causeColumns" :data-source="historyData" bordered :pagination="false">
+                        <span slot="action" slot-scope="text, record">
+                            <a-popconfirm
+                                title="是否重新推送?"
+                                ok-text="是"
+                                cancel-text="否"
+                                @confirm="handleAgian(record)"
+                            >
+                                <a :disabled="record.result==='推送成功'">重新推送</a>
+                            </a-popconfirm>
+                            
+                        </span>
+                    </a-table>
+                </div>
+                <a-pagination
+                    class="pagin-table-class"
+                    :total="totalAllHistory"
+                    size="small"
+                    @change="handleHistorySizeChange"
+                />
+            </div>
+        </a-modal>   
     </div>
 </template>
 <script>
-import TreeSelect from './components/tree-select/tree-select';
+import TreeSelect from '@/views/modules/autoLaunch/directional/components/tree-select.vue';
 import {getAction, postAction} from '@/api/manage';
 import AcountSearch from '@/views/modules/Statistics/components/Treeselect.vue';
+import selectTable from '@/views/modules/Statistics/components/selectPagination.vue';
 import AppMarketService from './crowd-control-service';
 import BMF from 'browser-md5-file';
-
+import { mapGetters } from 'vuex';
 let COS = require('cos-js-sdk-v5');
 let cos = new COS({
     SecretId: 'AKIDE6IpMi8fJQRCg1iuWzFajjRs43kbbets',
@@ -225,16 +256,21 @@ export default {
     name: 'crowd-control',
     components: {
         TreeSelect,
-        AcountSearch
+        AcountSearch,
+        selectTable
     },
     data() {
         let that = this;
         return {
+            src: '/kuaishouPopulationPackage/getAccountByProjectId',
+            unitAccountId: '',
             personResourceDisabled: false,
             personNameDisabled: false,
             totalAllCause: 0,
             acountId: undefined, // 搜索的账户ID
+            projectId: null,
             uploadAcountIds: '',
+            uploadProjectId: '',
             totalAll: 10,
             finallyRightTree: [],
             fileList: [],
@@ -268,63 +304,54 @@ export default {
                     dataIndex: 'orientationName'
                 },
                 {
-                    title: '人群包类型',
-                    align: 'center',
-                    dataIndex: 'populationType',
-                    customRender(t) {
-                        return t ? that.populationTypeTasks.find(item => item.label === Number(t)).value : '-';
-                    }
-                },
-                {
                     title: '匹配类型',
                     align: 'center',
                     dataIndex: 'typeStr'
                 },
                 {
-                    title: '上传时间',
+                    title: '创建时间',
                     dataIndex: 'statDate',
                     align: 'center'
                 },
                 {
-                    title: '覆盖数量',
-                    dataIndex: 'coverNum',
-                    align: 'center'
-                },
-                {
-                    title: '状态',
-                    dataIndex: 'statusStr',
-                    align: 'center'
-                },
-                {
-                    title: '原因',
-                    dataIndex: '',
+                    title: '关联项目',
+                    dataIndex: 'projectName',
                     align: 'center',
-                    scopedSlots: {customRender: 'cause'}
+                    ellipsis: true,
+                    customRender(t) {
+                        if(t) {
+                            return t
+                        }
+                        else {
+                            return '-'
+                        }
+                    }
                 },
                 {
-                    title: '目标账户',
-                    dataIndex: 'accountName',
+                    title: '相关账户',
+                    dataIndex: 'accountCount',
                     align: 'center',
-                    ellipsis: true
+                    scopedSlots: {customRender: 'acountRelax'}
                 },
                 {
-                    title: '相关项目',
-                    dataIndex: 'projectCount',
+                    title: '相关',
+                    dataIndex: 'unitCount',
                     align: 'center',
                     scopedSlots: {customRender: 'depRelax'}
                 },
                 {
-                    title: '相关账户',
-                    dataIndex: 'accountCount',
-                    align: 'center',
-                    scopedSlots: {customRender: 'acountRelax'}
-                },
-                {
                     title: '操作',
                     dataIndex: 'action',
                     align: 'center',
                     scopedSlots: {customRender: 'action'}
-                }
+                },
+                {
+                    title: '更多',
+                    dataIndex: 'actionMore',
+                    align: 'center',
+                    scopedSlots: {customRender: 'actionMore'},
+                    ellipsis: true
+                },
             ],
             personForm: {
                 name: '',
@@ -340,18 +367,125 @@ export default {
                 page: 1,
                 size: 10
             },
+            historyPag: {
+                page: 1,
+                size: 10
+            },
             tableSelectList: {},
             acountRelaxDetail: {},
-            causeDetailData: {}
+            causeDetailData: {},
+            historyData: [],
+            totalAllHistory: 0,
+            historySelectList: null,
+            historyVisible: false,
+            accountIpagination: {
+                current: 1,
+                pageSize: 10,
+                //   pageSizeOptions: ['10', '20', '30'],
+                showTotal: (total, range) => {
+                    return range[0] + "-" + range[1] + " 共" + total + "条"
+                },
+                showQuickJumper: true,
+                showSizeChanger:false,
+                pageSizeOptions: ['10', '30', '50'],
+                total: 0,
+                onChange: (current, pageSize) => {
+                    // 切换分页时的回调,
+                    // 当在页面定义change事件时,切记要把此处的事件清除,因为这两个事件重叠了,可能到时候会导致一些莫名的bug
+                    this.accountIpagination.current = current;
+                    this.accountIpagination.pageSize= pageSize;
+                    this.handleAcountRelax(this.relaxStatus  ,this.acountRelaxDetail)
+                }
+            },
+            realShow: false,
+            realLoading: false
         };
     },
+    watch: {
+        unitAccountId: function(n,o) {
+            if(this.relaxVisible){
+                this.handleAcountRelax(this.relaxStatus  ,this.acountRelaxDetail)
+            }
+        },
+    },
     created() {
         this.form = this.$form.createForm(this);
     },
     mounted() {
+        this.realShow = this.userInfo().realname === '管理员' ? true : false
+        if(!this.realShow) {
+            getAction('/kuaishou/batch/syncUserPopulationList',{ userId:this.userInfo().id, type:1}).then(res => {
+                if(res.success) {
+
+                }
+            })
+        }
         this.handleGetTableList({});
     },
     methods: {
+        ...mapGetters(['nickname', 'avatar', 'userInfo']),
+        handleAgian(val) {
+            let params = {};
+            params.id = val.id;
+            params.accountIds = [val.accountId];
+            postAction('/kuaishouPopulationPackage/push' ,params).then(res => {
+                if(res.success) {
+                   
+                    if(!this.realShow) {
+                        getAction('/kuaishou/batch/syncUserPopulationList',{ userId:this.userInfo().id, type:1}).then(res => {
+                            if(res.success) {
+                                this.$message.success(res.message);
+                                this.historyVisible = false;
+                                this.handleGetTableList({});
+                            }
+                            else {
+                                this.$message.error(res.message);
+                            }
+                        })
+                    }
+                    else {
+                        this.$message.success(res.message);
+                        this.historyVisible = false;
+                        this.handleGetTableList({});
+                    }
+                }
+                else {
+                    this.$message.error(res.message);
+                }
+            })
+
+        },
+        handleHistorySizeChange(current, pageSize) {
+            this.historyPag = {
+                page: current,
+                size: pageSize
+            };
+            this.handleHistoryTableData(this.historySelectList.id);
+        },
+        handleHistory(list) {
+            this.historyVisible = true;
+            this.handleHistoryTableData(list.id);
+            this.historySelectList = list;
+        },
+        handleHistoryTableData(id) {
+            const paramsData = {
+                id: id,
+                pageNo: this.historyPag.page,
+                pageSize: this.historyPag.size,
+                status: this.resultHistory
+            };
+            getAction('/kuaishouPopulationPackage/queryPushHistory', paramsData).then(result => {
+                if (result.code === 200) {
+                    this.historyData = result.result.list || [];
+                    this.totalAllHistory = result.result.total || 0;
+                }
+                else {
+                    this.$message.error(result.message);
+                }
+            }).catch(error => {
+                console.log(error, 'eeee');
+            });
+        },
         onShowSizeChange(current, pageSize) {
             const paramsData = this.form.getFieldsValue();
             this.tablePag = {
@@ -370,13 +504,13 @@ export default {
         handleGetTableList(data) {
             const paramsData = {
                 orientationName: data.name,
-                accountId: this.acountId,
+                projectId: this.projectId,
                 status: data.status,
                 pageNo: this.tablePag.page,
                 pageSize: this.tablePag.size
             };
             this.dataSource = []
-            getAction('/kuaishouCrowdPack/queryPageList', paramsData).then(result => {
+            getAction('/kuaishouPopulationPackage/list', paramsData).then(result => {
                 if (result.code === 200) {
                     this.dataSource = result.result.list || [];
                     this.totalAll = result.result.total || 0;
@@ -392,9 +526,9 @@ export default {
             let that = this;
             this.$confirm({
                 title: '删除提示',
-                content: '确定要删除这一条吗?',
+                content: '是否删除该人群包?',
                 onOk() {
-                    getAction('/kuaishouCrowdPack/delete', {id: data.id}).then(result => {
+                    getAction('/kuaishouPopulationPackage/delete', {id: data.id}).then(result => {
                         if (result.code === 200) {
                             that.handleGetTableList({});
                             that.$message.success('删除成功');
@@ -409,19 +543,24 @@ export default {
             });
         },
         handleAcountRelaxTable() {
-            const paramsData = {
-                signature: this.acountRelaxDetail.signature,
-                accountId: this.acountRelaxDetail.accountId,
-                type: this.relaxStatus === 'dep' ? 1 : 2
-            };
-            getAction('/kuaishouCrowdPack/queryRel', paramsData).then(result => {
+            let url = this.relaxStatus === 'unit' ? '/kuaishouPopulationPackage/getRelatedGroups' : '/kuaishouPopulationPackage/getRelatedAccounts'
+            let paramsData = {};
+            paramsData.id = this.acountRelaxDetail.id;
+            paramsData.pageNo = this.accountIpagination.current;
+            paramsData.pageSize = this.accountIpagination.pageSize;
+            if(this.relaxStatus === 'unit') {
+                paramsData.accountId = this.unitAccountId;
+            }
+                
+            getAction(url, paramsData).then(result => {
                 if (result.code === 200) {
-                    if (this.relaxStatus === 'dep') {
+                    if (this.relaxStatus === 'unit') {
                         this.depData = result.result.list;
                     }
                     else if (this.relaxStatus === 'acount') {
                         this.acountData = result.result.list;
                     }
+                     this.accountIpagination.current = result.result.total;
                 }
                 else {
                     this.$message.error(result.message);
@@ -431,8 +570,8 @@ export default {
             });
         },
         handleAcountRelax(txt, recd) {
-            if (txt === 'dep') {
-                this.relaxStatus = 'dep';
+            if (txt === 'unit') {
+                this.relaxStatus = 'unit';
             }
             else if (txt === 'acount') {
                 this.relaxStatus = 'acount';
@@ -442,6 +581,7 @@ export default {
             this.relaxVisible = true;
         },
         handleRelaxCancel() {
+            this.unitAccountId = '';
             this.relaxVisible = false;
         },
         handleCause(list) {
@@ -478,22 +618,46 @@ export default {
             this.causeVisible = false;
         },
         handlePushSure() {
-            const paramsData = {
-                accountIds: this.finallyRightTree.map(item => item.key),
-                signature: this.tableSelectList.signature,
-                accountId: this.tableSelectList.accountId
-            };
-            postAction('/kuaishouCrowdPack/accountPush', paramsData).then(result => {
-                if (result.code === 200) {
-                    this.pushVisible = false;
-                    this.handleGetTableList({});
-                }
-                else {
-                    this.$message.error(result.message);
-                }
-            }).catch(error => {
-                console.log(error, 'eeeeeee');
-            });
+            if(this.finallyRightTree.length > 0) {
+                this.pushConfirmLoading = true;
+                const paramsData = {
+                    accountIds: this.finallyRightTree.map(item => item.key),
+                    id: this.tableSelectList.id
+                };
+                postAction('/kuaishouPopulationPackage/push', paramsData).then(result => {
+                    
+                    if (result.code === 200) {
+                        
+                        if(!this.realShow) {
+                            getAction('/kuaishou/batch/syncUserPopulationList',{ userId:this.userInfo().id, type:1}).then(res => {
+                                if(res.success) {
+                                    this.pushConfirmLoading = false;
+                                    this.pushVisible = false;
+                                    this.handleGetTableList({});
+                                    this.$message.success('推送成功')
+                                }
+                            })
+                        }
+                        else {
+                            this.pushConfirmLoading = false;
+                            this.pushVisible = false;
+                            this.handleGetTableList({});
+                            this.$message.success('推送成功')
+                        }
+                    }
+                    else {
+                        this.pushConfirmLoading = false;
+                        this.$message.error(result.message);
+                    }
+                }).catch(error => {
+                    this.pushConfirmLoading = false;
+                    console.log(error, 'eeeeeee');
+                });
+            }
+            else {
+                this.$message.error("请选择要推送的账户")
+            }
+           
         },
         handlePushCancel() {
             this.pushVisible = false;
@@ -506,7 +670,7 @@ export default {
             let that = this;
             return new Promise(function (resolve, reject) {
                 bmf.md5(file, (err, md5) => {
-                    getAction('/kuaishouCrowdPack/checkCrowdPackage', {signature: md5}).then(result => {
+                    getAction('kuaishouPopulationPackage/checkPopulationPackage', {signature: md5}).then(result => {
                         if (result.code === 200) {
                             that.personNameDisabled = false;
                             that.personResourceDisabled = false;
@@ -598,17 +762,35 @@ export default {
         },
         handleResetForm() {
             this.form.resetFields();
-            this.acountId = undefined;
+            this.projectId = undefined;
             this.handleGetTableList({});
+            this.$refs.selectTable.keyValue = "";
+            this.$refs.selectTable.getData()
         },
         handleUploadPerson() {
             this.personVisible = true;
         },
+        handleUpdatePerson() {
+            if(this.realShow) {
+                this.realLoading = true;
+                getAction('/kuaishou/batch/syncUserPopulationList',{ userId:this.userInfo().id, type:0}).then(res => {
+                    if(res.success) {
+                        this.realLoading = false;
+                        this.$message.success('更新成功');
+                        this.handleResetForm();
+                    }
+                    else {
+                        this.realLoading = false;
+                        this.$message.error('更新失败');
+                    }
+                })
+            }
+        },
         handleOk() {
             this.$refs.ruleForm.validate(valid => {
                 if (valid) {
-                    if (!this.uploadAcountIds) {
-                        this.$message.error('请选择账户');
+                    if (!this.uploadProjectId) {
+                        this.$message.error('请选择项目');
                         return;
                     }
                     if (!this.fileList.length) {
@@ -627,10 +809,10 @@ export default {
             const paramsData = {
                 type: this.personForm.resource,
                 orientationName: this.personForm.name,
-                accountId: this.uploadAcountIds,
+                projectId: this.uploadProjectId,
                 url: this.fileList[0].url
             };
-            postAction('/kuaishouCrowdPack/uploadCrowdPack', paramsData).then(result => {
+            postAction('/kuaishouPopulationPackage/add', paramsData).then(result => {
                 this.confirmLoading = false
                 if (result.code === 200) {
                     this.personVisible = false;
@@ -641,7 +823,7 @@ export default {
                     this.fileList = [];
                     this.personForm.name = '';
                     this.personForm.resource = '';
-                    this.uploadAcountIds = undefined;
+                    this.uploadProjectId = undefined;
                 }
                 else {
                     this.$message.error(result.message);
@@ -656,7 +838,7 @@ export default {
             this.personResourceDisabled = false;
             this.personNameDisabled = false;
             this.$refs.ruleForm.resetFields();
-            this.uploadAcountIds = '';
+            this.uploadProjectId = '';
             this.personForm.name = '';
             this.personForm.resource = '';
             this.fileList = [];

+ 10 - 0
src/views/modules/headline-view/headline-view-server.js

@@ -0,0 +1,10 @@
+/**
+ * @file 数据查看API
+ * @author jiayufei
+ */
+
+// export const urlAcount = 'http://118.24.244.213:8080'; // 线上
+// export const urlAcount = 'http://apipre.tjyourong.com.cn'; // 预生产
+export const urlAcount = 'http://192.168.1.43:8080'; // 子安
+// export const urlAcount = 'http://139.186.165.84:8080'; // 测试
+// export const urlAcount = 'http://192.168.1.8:8080'; // 学超

+ 0 - 0
src/views/modules/headline-view/headline-view.less


Datei-Diff unterdrückt, da er zu groß ist
+ 1742 - 0
src/views/modules/headline-view/headline-view.vue


+ 51 - 7
src/views/modules/material/accountCheck.vue

@@ -13,9 +13,19 @@
 <template>
   <div>
     <a-modal title="账户选择" v-model="showEdit" @ok="handleOk" @cancel="close" width="80%">
-      <a-checkbox :indeterminate="indeterminate" @change="onCheckAllChange" :checked="checkAll">全选</a-checkbox>
+      <!-- <a-checkbox :indeterminate="indeterminate" @change="onCheckAllChange" :checked="checkAll">全选</a-checkbox>
       <br />
-      <a-checkbox-group :options="showList" v-model="dataValue" class="checked-account" @change="onChange"/>
+      <a-checkbox-group :options="showList" v-model="dataValue" class="checked-account" @change="onChange" /> -->
+      <a-tree
+        v-model="checkedKeys"
+        checkable
+        :expanded-keys="expandedKeys"
+        :auto-expand-parent="autoExpandParent"
+        :selected-keys="selectedKeys"
+        :tree-data="treeData"
+        @expand="onExpand"
+        @select="onSelect"
+      />
     </a-modal>
   </div>
 </template>
@@ -30,19 +40,44 @@ export default {
 
   data: function () {
     return {
+      checkedKeys: [],
       showEdit: false,
       dataList: [],
       showList: null,
       dataValue: [],
       indeterminate: false,
       checkAll: false,
+      expandedKeys: [],
+      autoExpandParent: true,
+      selectedKeys: [],
+      treeData:[],
     }
   },
+  watch: {
+    checkedKeys(val) {
+      console.log('onCheck', val)
+    },
+  },
   methods: {
+    onExpand(expandedKeys) {
+      console.log('onExpand', expandedKeys)
+      // if not set autoExpandParent to false, if children expanded, parent can not collapse.
+      // or, you can remove all expanded children keys.
+      this.expandedKeys = expandedKeys
+      this.autoExpandParent = false
+    },
+    onCheck(checkedKeys) {
+      console.log('onCheck', checkedKeys)
+      this.checkedKeys = checkedKeys
+    },
+    onSelect(selectedKeys, info) {
+      console.log('onSelect', info)
+      this.selectedKeys = selectedKeys
+    },
     handleOk(e) {
       console.log(e)
       this.showEdit = false
-      this.$emit('synchro', this.dataValue)
+      this.$emit('synchro', this.checkedKeys)
     },
     close() {
       this.showEdit = false
@@ -72,17 +107,26 @@ export default {
       this.dataList = []
       this.showList = null
       this.dataValue = []
+      this.checkedKeys = []
       this.indeterminate = false
       this.checkAll = false
       console.log(url, item)
       getAction(url, item).then((res) => {
-        if (res.code == 0) {
-          this.showList = res.result.map((item) => {
+        if (res.success) {
+          let arrList = []
+          this.treeData = res.result.map(item=>{
             return {
-              label: item.authName,
-              value: item.accountId,
+              title: item.projectName,
+              key: item.projectId,
+              children:item.userAllocationList.map(i=>{
+                  return {
+                    title: i.authName+'\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0'+(i.userName?i.userName:'管理员'), 
+                    key: i.accountId
+                  }
+              })
             }
           })
+         
         }
         console.log(res)
       })

+ 3 - 3
src/views/modules/material/accountCheckBytedance.vue

@@ -289,12 +289,12 @@ export default {
         resolve(data)
       }
     },
-    getParticipateList(projectId) {
+    getParticipateList(productId) {
       //我参与的
       //   toutiaoParticipateList
       this.showEdit = true
-      getAction('/ctop/userAllocation/getUserIdListByProjectId', {
-        projectId: projectId,
+      getAction('/ctop/userAllocation/getUserIdListByProductId', {
+        productId: productId,
       }).then((res) => {
         if (res.code == 0) {
           console.log(res)

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

@@ -0,0 +1,423 @@
+<style>
+.select-table .ant-table-thead > tr > th,
+.select-table .ant-table-tbody > tr > td {
+  padding: 0 !important;
+}
+.select-table .ant-table {
+  font-size: 12px;
+}
+.demo-infinite-container {
+  border: 1px solid #e8e8e8;
+  border-radius: 4px;
+  overflow: auto;
+  padding: 8px 24px;
+  height: 300px;
+}
+.demo-loading-container {
+  position: absolute;
+  bottom: 40px;
+  width: 100%;
+  text-align: center;
+}
+</style>
+<style lang="scss" scoped>
+.require-check {
+  /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>
+  <a-form-item
+    label="产品名称"
+    :label-col="labelCol"
+    :wrapper-col="wrapperCol"
+    v-clickoutside="handleClose"
+    style="width: 100%"
+    class="select-table"
+    :class="{'require-check':requireCheck} "
+  >
+    <a-input
+      placeholder="请选择产品名称"
+      @focus="topMiddle = true"
+      v-model="keyValue"
+      @change="getData"
+      :disabled="disabled"
+    />
+    <div
+      v-show="topMiddle"
+      v-infinite-scroll="handleInfiniteOnLoad"
+      style="
+        background: white;
+        padding: 10px;
+        box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.15);
+        position: absolute;
+        z-index: 1000;
+        width: 100%;
+      "
+      class="demo-infinite-container"
+      :infinite-scroll-disabled="busy"
+      :infinite-scroll-distance="80"
+    >
+      <a-list :data-source="data">
+        <a-list-item slot="renderItem" slot-scope="item" @click="showProject(item)">
+          <a-list-item-meta :description="'广告主名称:' + item.advertiserName">
+            <a slot="title">产品名称:{{ item.productName }}</a>
+          </a-list-item-meta>
+          <!-- <div>
+            {{
+              item.mediaId == '1'
+                ? '头条'
+                : item.mediaId == '2'
+                ? '快手'
+                : item.mediaId == '3'
+                ? '头条内广'
+                : '快手内广'
+            }}
+          </div> -->
+        </a-list-item>
+        <div v-if="loading && !busy" class="demo-loading-container">
+          <a-spin />
+        </div>
+      </a-list>
+    </div>
+  </a-form-item>
+</template>
+
+<script>
+import { getAction, postAction } from '@/api/manage'
+import moment from 'moment'
+import { mapGetters } from 'vuex'
+import jq from 'jquery'
+import infiniteScroll from 'vue-infinite-scroll'
+const clickoutside = {
+  // 初始化指令
+  bind(el, binding, vnode) {
+    function documentHandler(e) {
+      // 这里判断点击的元素是否是本身,是本身,则返回
+      if (el.contains(e.target)) {
+        return false
+      }
+      // 判断指令中是否绑定了函数
+      if (binding.expression) {
+        // 如果绑定了函数 则调用那个函数,此处binding.value就是handleClose方法
+        binding.value(e)
+      }
+    }
+    // 给当前元素绑定个私有变量,方便在unbind中可以解除事件监听
+    el.__vueClickOutside__ = documentHandler
+    document.addEventListener('click', documentHandler)
+  },
+  update() {},
+  unbind(el, binding) {
+    // 解除事件监听
+    document.removeEventListener('click', el.__vueClickOutside__)
+    delete el.__vueClickOutside__
+  },
+}
+export default {
+  name: 'select-pagination',
+  components: {},
+  directives: { clickoutside, infiniteScroll },
+  props: {
+    projectId: {
+      type: [String, Number],
+      default() {
+        return ''
+      },
+    },
+    type: {
+      type: String,
+      default() {
+        return ''
+      },
+    },
+    labelCol: {
+      type: Object,
+      default() {
+        return {
+          xs: { span: 24 },
+          sm: { span: 5 },
+        }
+      },
+    },
+    disabled: {
+      type: Boolean,
+      default() {
+        return false
+      },
+    },
+    requireCheck: {
+      type: Boolean,
+      default() {
+        return false
+      },
+    }
+  },
+
+  data() {
+    return {
+      taobaoSpecialOfferList: {
+        advertiserId: "fd41614705a047dd65ab0e34e9150cfe",
+        advertiserName: " 淘宝(中国)软件有限公司",
+        createTime: "2021-03-03 10:15:30",
+        designResponsibleName: "辛巴特",
+        id: 3660879,
+        maxBid: 30000,
+        mediaId: "1",
+        productId: 1410280,
+        productName: "头条-淘宝特价版",
+        projectId: 1530887,
+        projectName: "头条-淘宝特价版",
+        responsibleName: "董琪",
+        roleCode: "operator",
+        saleId: null,
+        saleName: null,
+        updateTime: "2021-03-03 21:23:04",
+        userId: "a0d58df3392c4583b55ce3b041792aa7",
+        userName: "王晓娟"
+      },
+      loading: false,
+      busy: false,
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 12 },
+      },
+      selectedRowKeys: [],
+      selectedRowKeysValue: [],
+      topMiddle: false,
+      keyValue: '',
+      data: [],
+      dataElse: [],
+      ipagination: {
+        current: 0,
+        pageSize: 20,
+      },
+      rowClick: (record, index) => ({
+        // 事件
+        on: {
+          click: () => {
+            // var str =
+            //   record.mediaId == '1'
+            //     ? '头条'
+            //     : record.mediaId == '2'
+            //     ? '快手'
+            //     : record.mediaId == '3'
+            //     ? '头条内广'
+            //     : '快手内广'
+            this.keyValue = record.productName
+            this.topMiddle = false
+            this.data = this.dataElse
+            this.$emit('update:projectId', record.id)
+          },
+        },
+      }),
+    }
+  },
+  computed: {},
+  filters: {},
+  methods: {
+    showProject(record) {
+      var str =
+        record.mediaId == '1'
+          ? '头条'
+          : record.mediaId == '2'
+          ? '快手'
+          : record.mediaId == '3'
+          ? '头条内广'
+          : '快手内广'
+      this.keyValue = record.productName
+      this.topMiddle = false
+      this.$emit('update:projectId', record.id)
+    },
+    ...mapGetters(['nickname', 'avatar', 'userInfo']),
+    onSelectChange(selectedRowKeys, selectionRows) {
+      this.selectedRowKeys = selectedRowKeys
+      this.selectedRowKeysValue = selectionRows.map((item) => {
+        return { orientationId: item.orientationId, orientationName: item.orientationName }
+      })
+    },
+    getData() {
+      if (this.keyValue == '') {
+        this.$emit('update:projectId', '')
+      }
+      this.ipagination.current = 1
+      getAction('/ctop/product/getUserProductList', {
+        userId: this.userInfo().id,
+        pageNo: this.ipagination.current,
+        productName: this.keyValue,
+      }).then((res) => {
+        if (res.code == 0) {
+          let defaultList = res.result.records.map((item, index) => {
+            return {
+              ...item,
+              productId: item.id + '',
+              key: index,
+            };
+          })
+          if (this.type === 'taobao') {
+            this.data = defaultList.filter(item => item.productId === 1410280);
+          }
+          else {
+            this.data = defaultList;
+          }
+          // this.dataElse = res.result.records.map((item, index) => {
+          //   return {
+          //     ...item,
+          //     projectId: item.projectId + '',
+          //     key: index,
+          //   }
+          // })
+        }
+      })
+    },
+    handleClose() {
+      this.topMiddle = false
+    },
+    // allData() {
+    //   getAction('/ctop/product/getUserProductList', {
+    //     userId: this.userInfo().id,
+    //     pageSize: this.ipagination.pageSize,
+    //     pageNo: this.ipagination.current,
+    //   }).then((res) => {
+    //     if (res.code == 0) {
+    //       this.data = res.result.records.map((item, index) => {
+    //         return {
+    //           ...item,
+    //           projectId: item.projectId + '',
+    //           key: index,
+    //         }
+    //       })
+    //       this.dataElse = res.result.records.map((item, index) => {
+    //         return {
+    //           ...item,
+    //           projectId: item.projectId + '',
+    //           key: index,
+    //         }
+    //       })
+    //     }
+    //   })
+    // },
+    handleInfiniteOnLoad() {
+      const data = this.data
+      this.loading = true
+      this.ipagination.current++
+      // this.fetchData((res) => {
+      //   this.data = data.concat(res.results)
+      //   this.loading = false
+      // })
+      getAction('/ctop/product/getUserProductList', {
+        userId: this.userInfo().id,
+        pageSize: this.ipagination.pageSize,
+        pageNo: this.ipagination.current,
+        productName: this.keyValue,
+      }).then((res) => {
+        if (res.code == 0) {
+          this.busy = true
+          let defaultList = res.result.records.map((item, index) => {
+              return {
+                ...item,
+                projectId: item.projectId + '',
+              }
+            })
+          this.data = data.concat(
+            
+          )
+          if (this.type === 'taobao') {
+            this.data = defaultList.filter(item => item.productId === 1410280);
+          }
+          else {
+            this.data = data.concat(defaultList);
+          }
+          // this.data = res.result.records.map((item, index) => {
+          //   return {
+          //     ...item,
+          //     projectId: item.projectId + '',
+          //     key: index,
+          //   }
+          // })
+          // this.dataElse = res.result.records.map((item, index) => {
+          //   return {
+          //     ...item,
+          //     projectId: item.projectId + '',
+          //     key: index,
+          //   }
+          // })
+        }
+      })
+    },
+  },
+  watch: {
+    projectId(n, o) {
+      if (n == '') {
+        this.keyValue = ''
+      } else {
+      }
+    },
+  },
+  mounted: function () {
+    // this.handleInfiniteOnLoad()
+  },
+}
+</script>
+
+<style type="text/css">
+.plug-timer-grid {
+  width: 100%;
+}
+
+.plug-timer-grid td,
+.plug-timer-grid th {
+  border: 1px solid #97b4d1;
+  text-align: center; /*cursor:pointer;*/
+  font-size: 10px;
+  line-height: 10px;
+}
+
+.Selected {
+  background-color: rgb(102, 162, 243);
+  opacity: 0.5;
+}
+
+.plug-timer-grid {
+  border-collapse: collapse;
+  z-index: 4;
+}
+
+.plug-timer-grid thead tr {
+  display: table-row;
+  vertical-align: inherit;
+  border-color: inherit;
+}
+
+.group-creat table td {
+  height: 20px;
+  max-width: 5px;
+  font-size: 12px;
+  text-align: center;
+  vertical-align: middle;
+  overflow: hidden;
+  transition: background 0.5s;
+  -webkit-transition: background 0.5s;
+}
+
+.plug-timer-grid tbody th {
+  width: 4%;
+}
+
+.plug-timer-grid tbody tr td {
+  width: 2%;
+}
+
+/*.clear{*/
+/*  margin:20px 0px 20px 0px;*/
+/*}*/
+</style>

+ 155 - 46
src/views/modules/material/videoMaterial.vue

@@ -356,10 +356,13 @@ a {
         <a-row :gutter="24">
           <a-col :md="8" :sm="8">
             <!-- <a-form-item label="项目名称"> -->
-            <selectTable :projectId.sync="queryParam.projectId"></selectTable>
+            <selectTable :projectId.sync="queryParam.productId" ref="selectTable"></selectTable>
           </a-col>
 
           <a-col :md="8" :sm="8">
+            <selectTableProject :projectId.sync="queryParam.projectId" :productId="queryParam.productId" ref="selectTableProject"></selectTableProject>
+          </a-col>
+          <a-col :md="8" :sm="8">
             <a-form-item label="素材名称">
               <a-input placeholder="请输入素材名称" v-model="queryParam.materialName"></a-input>
             </a-form-item>
@@ -390,6 +393,34 @@ a {
             </a-form-item>
           </a-col>
           <a-col :md="8" :sm="8">
+            <a-form-item label="剪辑">
+              <a-select v-model="queryParam.clipId" allowClear show-search :filter-option="filterOption">
+                <a-select-option v-for="item in designList" :key="item.userId" :value="item.userId">
+                  {{ item.companyName + '_' + item.userName }}
+                </a-select-option>
+              </a-select>
+            </a-form-item>
+          </a-col>
+          <a-col :md="8" :sm="8">
+            <a-form-item label="拍摄">
+              <a-select v-model="queryParam.shotId" allowClear show-search :filter-option="filterOption">
+                <a-select-option v-for="item in designList" :key="item.userId" :value="item.userId">
+                  {{ item.companyName + '_' + item.userName }}
+                </a-select-option>
+              </a-select>
+            </a-form-item>
+          </a-col>
+          <a-col :md="8" :sm="8">
+            <a-form-item label="编导">
+              <a-select v-model="queryParam.planId" allowClear show-search :filter-option="filterOption">
+                <a-select-option v-for="item in designList" :key="item.userId" :value="item.userId">
+                  {{ item.companyName + '_' + item.userName }}
+                </a-select-option>
+              </a-select>
+            </a-form-item>
+          </a-col>
+
+          <a-col :md="8" :sm="8">
             <span style="float: left; overflow: hidden" class="table-page-search-submitButtons">
               <a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
               <a-button type="primary" @click="searchRe" icon="reload" style="margin-left: 8px">重置</a-button>
@@ -418,7 +449,7 @@ a {
       <a-button
         @click="onCheckAllChange"
         v-if="
-          queryParam.projectId &&
+          queryParam.productId &&
           active == '1' &&
           (role.roleCode == 'operator' ||
             role.roleCode == 'kuaishouOperationManager' ||
@@ -430,7 +461,49 @@ a {
       >
       <a-button
         v-if="
-          queryParam.projectId &&
+          queryParam.productId &&
+          active == '1' &&
+          (role.roleCode == 'operator' ||
+            role.roleCode == 'kuaishouOperationManager' ||
+            role.roleCode == 'admin' ||
+            role.roleCode == 'operationAssistant' ||
+            role.roleCode == 'touTiaoOperationManager')
+        "
+        :disabled="checkArr.length == 0"
+        @click="tongbu('1')"
+        >一键同步头条</a-button
+      >
+      <a-button
+        v-if="
+          queryParam.productId &&
+          active == '1' &&
+          (role.roleCode == 'operator' ||
+            role.roleCode == 'kuaishouOperationManager' ||
+            role.roleCode == 'admin' ||
+            role.roleCode == 'operationAssistant' ||
+            role.roleCode == 'touTiaoOperationManager')
+        "
+        :disabled="checkArr.length == 0"
+        @click="tongbu('3')"
+        >一键同步头条内广</a-button
+      >
+      <a-button
+        v-if="
+          queryParam.productId &&
+          active == '1' &&
+          (role.roleCode == 'operator' ||
+            role.roleCode == 'kuaishouOperationManager' ||
+            role.roleCode == 'admin' ||
+            role.roleCode == 'operationAssistant' ||
+            role.roleCode == 'touTiaoOperationManager')
+        "
+        :disabled="checkArr.length == 0"
+        @click="tongbu('2')"
+        >一键同步快手</a-button
+      >
+      <a-button
+        v-if="
+          queryParam.productId &&
           active == '1' &&
           (role.roleCode == 'operator' ||
             role.roleCode == 'kuaishouOperationManager' ||
@@ -439,8 +512,8 @@ a {
             role.roleCode == 'touTiaoOperationManager')
         "
         :disabled="checkArr.length == 0"
-        @click="tongbu"
-        >一键同步</a-button
+        @click="tongbu('4')"
+        >一键同步快手内广</a-button
       >
     </div>
 
@@ -721,7 +794,7 @@ a {
                     <a-checkbox :value="items.id" style="float: right" v-show="active == '1'"></a-checkbox>
 
                     <br />
-                    {{ items.createTime | getDate }}
+                    {{ items.createTime }}
                   </span>
                 </div>
               </div>
@@ -1260,7 +1333,15 @@ a {
           </a-carousel>
         </a-modal>
         <div style="flex: 3; padding: 10px; box-sizing: border-box">
-          <a-form v-if="detail" class="detail ant-advanced-search-form" layout="inline">
+          <a-form v-if="detail&&allDetailData" class="detail ant-advanced-search-form" layout="inline">
+            <div>
+              <a-form-item label="视频名称">{{allDetailData.materialName}}</a-form-item>
+            </div>
+            <div>
+              <a-form-item label="唯一编码">{{allDetailData.code}}</a-form-item>
+            </div>
+            
+            <a-form-item label="视频链接"><a-input v-model="allDetailData.url" type="text" read-only /></a-form-item>
             <div v-if="detail.parameter" style="display: flex">
               <a-form-item label="视频时长" v-if="detail.parameter.second" style="flex: 1"
                 >{{ detail.parameter.second }}秒</a-form-item
@@ -1667,8 +1748,8 @@ import qs from 'qs'
 import { mapGetters } from 'vuex'
 import moment from 'moment'
 
-import selectTable from '@/views/modules/Statistics/components/selectPagination.vue'
-
+import selectTable from './comment/selectTable.vue'
+import selectTableProject from '@/views/modules/Statistics/components/selectPagination.vue'
 import BMF from 'browser-md5-file'
 import uploadFile from '@/components/uploadFile.vue'
 import { closeAllVideoFun, stopOtherVideo } from '@/utils/videoControl'
@@ -1685,10 +1766,12 @@ export default {
     uploadFile,
     PermissionModal,
     accountCheckBytedance,
+    selectTableProject,
   },
 
   data() {
     return {
+      designList: [],
       // 标签的数据
       labelValue: [],
       options: [],
@@ -1862,6 +1945,7 @@ export default {
       waterLoading: false,
       videoTag: [],
       videoVisibleChange: '',
+      allDetailData: null,
     }
   },
   filters: {
@@ -1929,7 +2013,7 @@ export default {
         }
       })
     }, 1000)
-
+    this.getDesignList()
     getAction('/ctop/tagInfo/treeList', {
       pageSize: 10000,
     }).then((res) => {
@@ -1950,9 +2034,12 @@ export default {
         this.loadData()
       }
     },
-    'queryParam.projectId': function (n, o) {
+    'queryParam.productId': function (n, o) {
       if (n != '') {
         this.getList(n)
+        this.checkArr = []
+        this.$refs.selectTableProject.keyValue = ''
+        this.$refs.selectTableProject.getData(n)
       }
     },
     visibleDetail: function (n, o) {
@@ -1976,6 +2063,14 @@ export default {
     },
   },
   methods: {
+    // 获取设计人员
+    getDesignList() {
+      postAction('/ctop/kuaishou/videoReport/getDesignList').then((res) => {
+        if (res.success) {
+          this.designList = res.result
+        }
+      })
+    },
     changeTag(visible) {
       if (this.videoVisibleChange != visible) {
         this.videoVisibleChange = visible
@@ -2189,33 +2284,40 @@ export default {
       return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
     },
     moment,
-    tongbu() {
-      getAction('/ctop/project/queryById', { id: this.queryParam.projectId }).then((res) => {
-        console.log(res)
-        if (res.success) {
-          if (res.result.mediaId == '1' || res.result.mediaId == '3') {
-            this.$refs.check.getData('/ctop/userAllocation/getAccountListByProjectId', {
-              userId: this.userInfo().id,
-              projectId: this.queryParam.projectId,
-            })
-          } else if (res.result.mediaId == '2' || res.result.mediaId == '4') {
-            this.$refs.accountCheckBytedance.getParticipateList(this.queryParam.projectId)
-          }
-        } else {
-          this.$message.error('网络波动,请稍后再试')
-        }
-      })
+    tongbu(value) {
+      this.mediaId = value
+      // getAction('/ctop/project/queryById', { id: this.queryParam.projectId }).then((res) => {
+      //   console.log(res)
+      //   if (res.success) {
+      if (value == '1' || value == '3') {
+        this.$refs.check.getData('/ctop/userAllocation/getAccountListByUserIdAndProductId', {
+          userId: this.userInfo().id,
+          productId: this.queryParam.productId,
+          mediaId: value,
+        })
+      } else if (value == '2' || value == '4') {
+        this.$refs.accountCheckBytedance.getParticipateList(this.queryParam.productId)
+        // this.$refs.check.getData('/ctop/userAllocation/getAccountListByUserIdAndProductId', {
+        //   userId: this.userInfo().id,
+        //   productId: this.queryParam.productId,
+        //   mediaId: value,
+        // })
+      }
+      //   } else {
+      //     this.$message.error('网络波动,请稍后再试')
+      //   }
+      // })
     },
     implement(data) {
       // {treeData:data,shieldBackwardSwitch:this.shieldBackwardSwitch}
       var params = {}
       params.mediaId = this.mediaId
       params.materialArray = JSON.stringify(this.checkArr)
-      params.accountArray = data.treeData?JSON.stringify(data.treeData):JSON.stringify(data)
-      if(this.mediaId == '2'){
+      params.accountArray = data.treeData ? JSON.stringify(data.treeData) : JSON.stringify(data)
+      if (this.mediaId == '2') {
         params.shieldBackwardSwitch = data.shieldBackwardSwitch
       }
-      
+
       postAction('/ctop/materialUpload/uploadAccount', params).then((res) => {
         if (res.code == 0) {
           this.checkArr = []
@@ -2294,27 +2396,33 @@ export default {
         type: 'VIDEO',
         userId: this.userInfo().id,
         status: this.active,
+        productId: '',
       }
+      this.$refs.selectTable.keyValue = ''
+      this.$refs.selectTable.getData()
+      this.$refs.selectTableProject.keyValue = ''
+      this.$refs.selectTableProject.getData()
+      
       this.labelValue = []
 
       this.loadData(1)
     },
     getList(value) {
-      if (value) {
-        // this.mediaId = this.dataElse.filter(item => {
-        //   if (value == item.projectId) {
-        //     return item
-        //   }
-        // })[0].mediaId
-        getAction('/ctop/projectMember/participateListV2', {
-          userId: this.userInfo().id,
-          projectId: value,
-        }).then((res) => {
-          if (res.code == 0) {
-            this.mediaId = res.result.records[0].mediaId
-          }
-        })
-      }
+      // if (value) {
+      //   // this.mediaId = this.dataElse.filter(item => {
+      //   //   if (value == item.projectId) {
+      //   //     return item
+      //   //   }
+      //   // })[0].mediaId
+      //   getAction('/ctop/product/getUserProductList', {
+      //     userId: this.userInfo().id,
+      //     productId: value,
+      //   }).then((res) => {
+      //     if (res.code == 0) {
+      //       this.mediaId = res.result.records[0].mediaId
+      //     }
+      //   })
+      // }
       this.loadData()
     },
     onChangeCheckImage(checkedList) {
@@ -2382,6 +2490,7 @@ export default {
       this.id = item.id
       this.code = item.code
       this.excellent = item.excellent
+      this.allDetailData = item
       if (this.active == '2') {
         this.refuseReason = item.refuseReason
         this.refuseFile = item.refuseFile ? JSON.parse(item.refuseFile) : null
@@ -2811,7 +2920,7 @@ export default {
           type: 'VIDEO',
           userId: this.userInfo().id,
           status: key,
-          projectId: this.queryParam.projectId,
+          productId: this.queryParam.productId,
         }
         if (this.labelValue.length >= 1) {
           this.queryParam.tagCode = this.labelValue[this.labelValue.length - 1]

+ 5 - 4
vue.config.js

@@ -72,12 +72,12 @@ module.exports = {
          target: 'http://jiaoyangapi.shyouteng.com.cn', //请求本地 需要jeecg-boot后台项目  蒙蒙
         // target: 'http://192.168.0.59:8088', //请求本地 需要jeecg-boot后台项目  英豪
         // target: 'http://192.168.1.62:8088', //请求本地 需要jeecg-boot后台项目  英豪
-        // target: 'http://192.168.6.162:8806', //请求本地 需要jeecg-boot后台项目  祚云
+        // target: 'http://192.168.6.162:9806', //请求本地 需要jeecg-boot后台项目  祚云
         // target: 'http://192.168.1.43:8098', //请求本地 需要jeecg-boot后台项目  毕洁泉
         // target: 'http://192.168.1.43:8088', //请求本地 需要jeecg-boot后台项目  毕洁泉
         // target: 'http://192.168.1.43:8806', //请求本地 需要jeecg-boot后台项目  毕洁泉
         // target: 'http://192.168.0.252:8098', //请求本地 需要jeecg-boot后台项目  毕洁泉
-        // target: 'http://192.168.1.219:8080', //请求本地 需要jeecg-boot后台项目  赵西安
+        // target: 'http://192.168.1.219:8081', //请求本地 需要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后台项目
@@ -86,9 +86,10 @@ module.exports = {
         //  target: 'http://adsp.tjyourong.com.cn/', //请求本地 需要jeecg-boot后台项目
         // target: 'http://192.168.1.251/', //请求本地 需要jeecg-boot后台项目 
         // target:'http://118.24.244.213:8804',
+        // target: 'http://192.168.1.43:8080', // 子安
+        // target: 'http://192.168.1.8:8806', // 学超
       //  target:'http://139.186.165.84:8806', //测试
-
-
+        // target:'http://apipre.tjyourong.com.cn', //预生产
 
         ws: false,