Browse Source

优量汇流量包

xiuli.gao 1 year ago
parent
commit
937e43ecbe

+ 3 - 1
src/assets/style/self.scss

@@ -376,7 +376,9 @@
376 376
 .flexShrink0{
377 377
   flex-shrink: 0;
378 378
 }
379
-
379
+.flex_1{
380
+  flex: 1;
381
+}
380 382
 .borRightNone{
381 383
   border-right: none;
382 384
 }

+ 18 - 8
src/components/businessMoudle/batchGdt/configArea/basicInfo/attributionOuter.vue

@@ -54,17 +54,19 @@
54 54
         </div>
55 55
       </div>
56 56
     </div>
57
+    <p class="warn-content" style="margin-left: 180px;" v-if="params[accId] && !params[accId].activate_status">所选择的数据源(数据源名称)未接入数据,请谨慎选择以免影响广告归因结果</p>
57 58
     <template #footer>
58
-      <span class="dialog-footer">
59
-        <el-button @click="handleClose"> 取 消 </el-button>
60
-        <el-button type="primary" @click="submitEvent"> 确 定 </el-button>
61
-      </span>
59
+        <span class="dialog-footer">
60
+          <el-button @click="handleClose"> 取 消 </el-button>
61
+          <el-button type="primary" @click="submitEvent"> 确 定 </el-button>
62
+        </span>
62 63
     </template>
63 64
   </el-dialog>
64 65
 </template>
65 66
 <script setup lang="ts">
66 67
 import { reactive, ref, watch } from 'vue';
67 68
 import { userActionSetsGet } from './ts/basicApi'
69
+import { ElMessage } from "element-plus";
68 70
 const props = defineProps({
69 71
   visible: {
70 72
     type: Boolean,
@@ -108,7 +110,7 @@ const accItemEvent = (item, type?) => {
108 110
     loading.value = true;
109 111
     accId.value && userActionSetsGet({ 'account_id': accId.value }).then((data) => {
110 112
       let res = data.map((v) => {
111
-        return Object.assign(v, { 'checkboxValue': params[accId.value] && params[accId.value] != '' && params[accId.value] == v.user_action_set_id ? true : false })
113
+        return Object.assign(v, { 'checkboxValue': params[accId.value] && params[accId.value] != '' && params[accId.value].user_action_set_id == v.user_action_set_id ? true : false })
112 114
       })
113 115
       tableData.value = res;
114 116
       tableDataAll[item.id] = res;
@@ -124,6 +126,14 @@ const accItemEvent = (item, type?) => {
124 126
 }
125 127
 /**确定提交 */
126 128
 const submitEvent = () => {
129
+  for(let i = 0; i < props.accIdsList.length; i++){
130
+    let key = props.accIdsList[i].id;
131
+    if(!params[key] || params[key] == ''){
132
+      ElMessage.warning(`账户${key}选择的数据源数量为:0,应选数量为:1`)
133
+      return
134
+    }
135
+  }
136
+  console.log('0000')
127 137
   let obj = {};
128 138
   for (let i in params) {
129 139
     if (params[i] && params[i] != '') {
@@ -145,7 +155,7 @@ const rowClick = (row) => {
145 155
   row.checkboxValue = !row.checkboxValue
146 156
   if (row.checkboxValue) {
147 157
     allCheckboxValue.value = true
148
-    params[accId.value] = row.user_action_set_id
158
+    params[accId.value] = row
149 159
   } else {
150 160
     allCheckboxValue.value = false
151 161
     params[accId.value] = ''
@@ -162,7 +172,7 @@ const allCheckboxclick = () => {
162 172
     allCheckboxValue.value = false
163 173
   } else if (tableData.value?.length > 0) {
164 174
     tableData.value[0].checkboxValue = true;
165
-    params[accId.value] = tableData.value[0].user_action_set_id
175
+    params[accId.value] = tableData.value[0]
166 176
     allCheckboxValue.value = true
167 177
   }
168 178
 }
@@ -196,7 +206,7 @@ const clearClick = (type) => {
196 206
 }
197 207
 /**全选是否可用判断 */
198 208
 const determineAllSelect = () => {
199
-  if ((tableData.value.length > 0 && (!params[accId.value] || params[accId.value] == '')) || (params[accId.value] && tableData.value.filter((v)=>{return v.user_action_set_id == params[accId.value] && v.checkboxValue == true}).join() != '')) {
209
+  if ((tableData.value.length > 0 && (!params[accId.value] || params[accId.value] == '')) || (params[accId.value] && tableData.value.filter((v)=>{return v.user_action_set_id == params[accId.value].user_action_set_id && v.checkboxValue == true}).join() != '')) {
200 210
     disabled.value = false
201 211
   } else {
202 212
     disabled.value = true

+ 2 - 1
src/components/businessMoudle/batchGdt/configArea/basicInfo/expandPopulation.vue

@@ -16,9 +16,10 @@
16 16
       <div class="tabelCon">
17 17
         <div class="title">{{ title }} <span class="refresh" @click="accItemEvent({ 'id': accId }, 'upload')">刷新</span></div>
18 18
         <div class="conInfo">
19
-          <el-select v-model="selectModel" multiple filterable placeholder="请选择人群包" style="width: 500px" size="large" @change="selectChange">
19
+          <el-select v-model="selectModel" multiple filterable :multiple-limit="10" placeholder="请选择人群包" style="width: 500px" size="large" @change="selectChange">
20 20
             <el-option v-for="item in options" :key="item.audience_id" :label="item.name" :value="item.audience_id" />
21 21
           </el-select>
22
+          <p class="warn-content">最多可选择10个扩量种子人群</p>
22 23
         </div>
23 24
       </div>
24 25
     </div>

+ 76 - 25
src/components/businessMoudle/batchGdt/configArea/basicInfo/index.vue

@@ -1,5 +1,5 @@
1 1
 <template>
2
-  <el-dialog class="gdt-dialog" v-model="dialogVisible" title="广告基本信息" width="1080px" top="40px"
2
+  <el-dialog class="gdt-dialog" :close-on-click-modal="false" v-model="dialogVisible" title="广告基本信息" width="1080px" top="40px"
3 3
     :before-close="handleClose">
4 4
     <div class="container">
5 5
       <template v-for="(item, main_index) in basicInfoJsonInfo" :key="main_index + 'basicInfoJsonInfo'">
@@ -764,18 +764,13 @@ watch([
764 764
 watch(
765 765
   () => props.visible,
766 766
   (newValue, oldValue) => {
767
-    dialogVisible.value = newValue
768
-  }, { immediate: true})
769
-/**监听数据回显 */
770
-watch(
771
-  () => props.dataFillBack,
772
-  (newValue, oldValue) => {
773
-    if (!newValue.id) return;
774
-     form.daily_budget_radio = newValue?.daily_budget ? '2' : '1';
775
-     for(let i in newValue){
776
-      form[i] = newValue[i]
767
+    dialogVisible.value = newValue;
768
+    if (!props.dataFillBack.id) return;
769
+     form.daily_budget_radio = props.dataFillBack?.daily_budget ? '2' : '1';
770
+     for(let i in props.dataFillBack){
771
+      form[i] = props.dataFillBack[i]
777 772
      }
778
-    form.bid_scene_radio = newValue?.bid_scene == 'BID_SCENE_NORMAL_AVERAGE' || newValue?.bid_scene == 'BID_SCENE_NORMAL_TARGET' ? '' : newValue?.bid_scene;
773
+    form.bid_scene_radio = props.dataFillBack?.bid_scene == 'BID_SCENE_NORMAL_AVERAGE' || props.dataFillBack?.bid_scene == 'BID_SCENE_NORMAL_TARGET' ? '' : props.dataFillBack?.bid_scene;
779 774
     if(form.bid_way == '2'){
780 775
       let arr = form.bid_range?.split('-') || [];
781 776
       form.bid_range_1 = {
@@ -786,42 +781,98 @@ watch(
786 781
     }
787 782
     watchSiteIds()
788 783
     if (form.bid_site == '1') { // 分版位出价
789
-      if (newValue.bid_site_details){
790
-        let bid_site_details = JSON.parse(newValue.bid_site_details)
784
+      if (props.dataFillBack.bid_site_details){
785
+        let bid_site_details = JSON.parse(props.dataFillBack.bid_site_details)
791 786
         site_ids_arr_1.value.forEach((item) => {
792 787
           item.coefficient = bid_site_details[item.value] || 1;
793 788
           item.offer = getOffer(bid_site_details[item.value], 'site')
794 789
         });
795 790
       }
796 791
     }
797
-    if (newValue.deep_conversion_behavior_spec || newValue.deep_conversion_worth_spec) {
798
-      let deep_spec = JSON.parse(newValue.deep_conversion_behavior_spec)
799
-      if(newValue.deep_conversion_type == 'DEEP_CONVERSION_WORTH') { // 优化ROI
800
-        deep_spec = JSON.parse(newValue.deep_conversion_worth_spec)
792
+    if (props.dataFillBack.deep_conversion_behavior_spec || props.dataFillBack.deep_conversion_worth_spec) {
793
+      let deep_spec = JSON.parse(props.dataFillBack.deep_conversion_behavior_spec)
794
+      if(props.dataFillBack.deep_conversion_type == 'DEEP_CONVERSION_WORTH') { // 优化ROI
795
+        deep_spec = JSON.parse(props.dataFillBack.deep_conversion_worth_spec)
801 796
       }
802 797
       deep_conversion_behavior_spec.target = deep_spec.target;
803 798
       deep_conversion_behavior_spec.rate = deep_spec.rate || '';
804
-      deep_conversion_behavior_spec.price = newValue.deep_conversion_type == 'DEEP_CONVERSION_WORTH' ? deep_spec.roi : deep_spec.price;
799
+      deep_conversion_behavior_spec.price = props.dataFillBack.deep_conversion_type == 'DEEP_CONVERSION_WORTH' ? deep_spec.roi : deep_spec.price;
805 800
       deep_conversion_behavior_spec.min = deep_spec.min;
806 801
       deep_conversion_behavior_spec.max = deep_spec.max;
807 802
       deep_conversion_behavior_spec_fillBack.min = deep_spec.min;
808 803
       deep_conversion_behavior_spec_fillBack.max = deep_spec.max;
809
-      deep_conversion_behavior_spec_fillBack2.value = newValue.deep_conversion_type == 'DEEP_CONVERSION_WORTH' ? deep_spec.roi : deep_spec.price;
804
+      deep_conversion_behavior_spec_fillBack2.value = props.dataFillBack.deep_conversion_type == 'DEEP_CONVERSION_WORTH' ? deep_spec.roi : deep_spec.price;
810 805
     }
811 806
     if (form.deep_bid_site == '1') { // 分版位深度出价
812
-      if (newValue.deep_bid_site_details){
813
-        let deep_bid_site_details = JSON.parse(newValue.deep_bid_site_details)
807
+      if (props.dataFillBack.deep_bid_site_details){
808
+        let deep_bid_site_details = JSON.parse(props.dataFillBack.deep_bid_site_details)
814 809
         site_ids_arr_2.value.forEach((item) => {
815 810
           item.coefficient = deep_bid_site_details[item.value] || 1;
816 811
           item.offer = getOffer(deep_bid_site_details[item.value], 'deep_bit_site')
817 812
         });
818 813
       }
819 814
     }
820
-    first_day_begin_time.flag = newValue.first_day_begin_time && newValue.first_day_begin_time != '' ? true : false;
821
-    first_day_begin_time.value = newValue.first_day_begin_time.slice(0,5)
822
-    checkedWechat.value = newValue.bid_site_wechat_enabled == '1' ? true : false; // 支持微信朋友圈&微信公众号与小程序版位
815
+    first_day_begin_time.flag = props.dataFillBack.first_day_begin_time && props.dataFillBack.first_day_begin_time != '' ? true : false;
816
+    first_day_begin_time.value = props.dataFillBack.first_day_begin_time.slice(0,5)
817
+    checkedWechat.value = props.dataFillBack.bid_site_wechat_enabled == '1' ? true : false; // 支持微信朋友圈&微信公众号与小程序版位
823 818
     watch_deep_conversion()
824 819
   }, { immediate: true})
820
+/**监听数据回显 */
821
+// watch(
822
+//   () => props.dataFillBack,
823
+//   (newValue, oldValue) => {
824
+//     if (!newValue.id) return;
825
+//      form.daily_budget_radio = newValue?.daily_budget ? '2' : '1';
826
+//      for(let i in newValue){
827
+//       form[i] = newValue[i]
828
+//      }
829
+//     form.bid_scene_radio = newValue?.bid_scene == 'BID_SCENE_NORMAL_AVERAGE' || newValue?.bid_scene == 'BID_SCENE_NORMAL_TARGET' ? '' : newValue?.bid_scene;
830
+//     if(form.bid_way == '2'){
831
+//       let arr = form.bid_range?.split('-') || [];
832
+//       form.bid_range_1 = {
833
+//         con: form.bid_range,
834
+//         min: arr.length > 0 ? arr[0] : '',
835
+//         max: arr.length > 1 ? arr[1] : '',
836
+//       }
837
+//     }
838
+//     watchSiteIds()
839
+//     if (form.bid_site == '1') { // 分版位出价
840
+//       if (newValue.bid_site_details){
841
+//         let bid_site_details = JSON.parse(newValue.bid_site_details)
842
+//         site_ids_arr_1.value.forEach((item) => {
843
+//           item.coefficient = bid_site_details[item.value] || 1;
844
+//           item.offer = getOffer(bid_site_details[item.value], 'site')
845
+//         });
846
+//       }
847
+//     }
848
+//     if (newValue.deep_conversion_behavior_spec || newValue.deep_conversion_worth_spec) {
849
+//       let deep_spec = JSON.parse(newValue.deep_conversion_behavior_spec)
850
+//       if(newValue.deep_conversion_type == 'DEEP_CONVERSION_WORTH') { // 优化ROI
851
+//         deep_spec = JSON.parse(newValue.deep_conversion_worth_spec)
852
+//       }
853
+//       deep_conversion_behavior_spec.target = deep_spec.target;
854
+//       deep_conversion_behavior_spec.rate = deep_spec.rate || '';
855
+//       deep_conversion_behavior_spec.price = newValue.deep_conversion_type == 'DEEP_CONVERSION_WORTH' ? deep_spec.roi : deep_spec.price;
856
+//       deep_conversion_behavior_spec.min = deep_spec.min;
857
+//       deep_conversion_behavior_spec.max = deep_spec.max;
858
+//       deep_conversion_behavior_spec_fillBack.min = deep_spec.min;
859
+//       deep_conversion_behavior_spec_fillBack.max = deep_spec.max;
860
+//       deep_conversion_behavior_spec_fillBack2.value = newValue.deep_conversion_type == 'DEEP_CONVERSION_WORTH' ? deep_spec.roi : deep_spec.price;
861
+//     }
862
+//     if (form.deep_bid_site == '1') { // 分版位深度出价
863
+//       if (newValue.deep_bid_site_details){
864
+//         let deep_bid_site_details = JSON.parse(newValue.deep_bid_site_details)
865
+//         site_ids_arr_2.value.forEach((item) => {
866
+//           item.coefficient = deep_bid_site_details[item.value] || 1;
867
+//           item.offer = getOffer(deep_bid_site_details[item.value], 'deep_bit_site')
868
+//         });
869
+//       }
870
+//     }
871
+//     first_day_begin_time.flag = newValue.first_day_begin_time && newValue.first_day_begin_time != '' ? true : false;
872
+//     first_day_begin_time.value = newValue.first_day_begin_time.slice(0,5)
873
+//     checkedWechat.value = newValue.bid_site_wechat_enabled == '1' ? true : false; // 支持微信朋友圈&微信公众号与小程序版位
874
+//     watch_deep_conversion()
875
+//   }, { immediate: true})
825 876
 </script>
826 877
 <style lang="scss" scoped>@import "@/assets/style/batchDialogGdt.scss";
827 878
 

+ 6 - 3
src/components/businessMoudle/batchGdt/configArea/basicInfo/outer.scss

@@ -54,10 +54,13 @@
54 54
 
55 55
     }
56 56
   }
57
-  .dialog-footer{
58
-    text-align: right;
59
-  }
60 57
   .conInfo {
61 58
     padding: 20px;
62 59
   }
60
+}
61
+.warn-content{
62
+  color: #f1902b;
63
+  font-size: 12px;
64
+  line-height: 20px;
65
+  margin-top: 6px;
63 66
 }

+ 10 - 0
src/components/businessMoudle/batchGdt/configArea/basicInfo/ts/basicApi.ts

@@ -87,4 +87,14 @@ export async function userActionSetsGet(params: {account_id: string}) {
87 87
   } else {
88 88
     return []
89 89
   }
90
+}
91
+
92
+/**优量汇流量包获取 */
93
+export async function unionPositionPackagesGet(params: {account_id: string, type: 1 | 2}) {
94
+  const res: any = await http.get('/api/ad/unionPositionPackagesGet',params)
95
+  if (res.errNo == 0) {
96
+    return res.rst;
97
+  } else {
98
+    return []
99
+  }
90 100
 }

+ 8 - 5
src/components/businessMoudle/batchGdt/configArea/basicInfo/ts/fillBack.ts

@@ -143,7 +143,7 @@ export const FillBackData = ({ data, type, updateScene = {}, cb }: IFillBackData
143 143
       'first_day_begin_time': data.first_day_begin_time,
144 144
       'time_series_type': data.time_series_type,
145 145
       'time_series': data.time_series_type == '2' ? data.time_series : '',
146
-      'daily_budget': data.daily_budget_radio == '1' ? 0 : data.daily_budget,
146
+      'daily_budget': data.daily_budget_radio == '1' ? 0 : Number(data.daily_budget),
147 147
       'bid_mode': data.bid_mode,
148 148
       'bid_way': data.smart_bid_type == 'SMART_BID_TYPE_CUSTOM' ? data.bid_way : '',
149 149
       'smart_bid_type': data.bid_scene == 'BID_SCENE_UNKNOWN' ? data.smart_bid_type : '',
@@ -245,12 +245,15 @@ export const FillBackData = ({ data, type, updateScene = {}, cb }: IFillBackData
245 245
   } else {
246 246
     params = data
247 247
   }
248
-  for(let i in params){
249
-    let typesOf = typeof params[i]
250
-    if (typesOf == 'number') {
251
-      params[i] = String(params[i])
248
+  if(type == 'api'){ // 从后端获取数据回显时,把number变为string
249
+    for(let i in params){
250
+      let typesOf = typeof params[i]
251
+      if (typesOf == 'number') {
252
+        params[i] = String(params[i])
253
+      }
252 254
     }
253 255
   }
256
+ 
254 257
   //对应展示文案
255 258
   copywriting.push(`广告形式:${basicInfoJson['广告形式']['ad_form'].data.list.filter((v) => { return v.value == data.ad_form })[0]?.label}`)
256 259
   copywriting.push(`转化归因:${basicInfoJson['目标详情']['attribution_type'].data.list.filter((v) => { return v.value == data.attribution_type })[0]?.label}`)

+ 310 - 0
src/components/businessMoudle/batchGdt/configArea/basicInfo/unionPosition.vue

@@ -0,0 +1,310 @@
1
+<template>
2
+  <el-dialog class="gdt-dialog" v-model="dialogVisible" title="优量汇流量包" width="1000px" top="40px"
3
+    :before-close="handleClose">
4
+    <div class="container tabelListBox" v-loading="loading">
5
+      <div class="ids">
6
+        <div class="accItem" v-for="(item, idx) in accIdsList" :key="item.id" :class="item.id == accId ? 'active' : ''"
7
+          @click="accItemEvent(item)">
8
+          {{ item.name || '-' }}
9
+          <el-icon :size="14" :color="item.id == accId ? '#197afb' : '#606266'" class="lMarauto">
10
+            <CircleCheck v-if="checkTrue(item.id)" />
11
+            <i-ep-ArrowRight v-else />
12
+          </el-icon>
13
+        </div>
14
+      </div>
15
+      <div class="tabelCon">
16
+        <div class="title flex_between">
17
+          <el-radio-group v-model="typeSelect" size="default" @change="accItemEvent({ 'id': accId })">
18
+            <el-radio-button v-for="item in infoSelect" :label="item.id">{{ item.name }}</el-radio-button>
19
+          </el-radio-group>
20
+          <div>
21
+            <el-input style="width:320px;margin-right: 6px;" v-model="searchKeyWrod" clearable
22
+            :placeholder="`请输入流量包${searchSelect == '1' ? '名称' : 'ID'}查询`" class="input-with-select"
23
+            @clear="clearClick('input')">
24
+            <template #prepend>
25
+              <el-select v-model="searchSelect" placeholder="Select" style="width: 100px">
26
+                <el-option label="流量包名称" value="1" />
27
+                <el-option label="流量包ID" value="2" />
28
+              </el-select>
29
+            </template>
30
+          </el-input>
31
+          <el-button type="primary" @click="searchClick">查询</el-button>
32
+          <span class="refresh" @click="clearClick('clear')">清空</span>
33
+          <span class="refresh" @click="accItemEvent({ 'id': accId }, 'upload')">刷新</span>
34
+          </div>
35
+        </div>
36
+        <div class="conInfo">
37
+          <el-table border height="56vh" :data="tableData" style="width: 100%"
38
+            @row-click="rowClick">
39
+            <template v-slot:empty>
40
+              <span v-if="searchKeyWrod && searchKeyWrod != ''">未搜索到相关内容,请更换关键字或ID重试</span>
41
+              <span v-else>暂无流量包信息</span>
42
+            </template>
43
+            <el-table-column width="40" align="center">
44
+              <template #header="scope">
45
+                <div :class="['self_checkbox', allCheckboxValue ? 'self_checkbox_active' : false,  disabled ? 'self_checkbox_disabled': '']"
46
+                  @click="allCheckboxclick"></div>
47
+              </template>
48
+              <template #default="scope">
49
+                <div :class="['self_checkbox', scope.row.checkboxValue ? 'self_checkbox_active' : false]"></div>
50
+              </template>
51
+            </el-table-column>
52
+            <el-table-column property="union_package_name" label="流量包名称" show-overflow-tooltip />
53
+            <el-table-column property="union_package_id" label="流量包ID" />
54
+            <el-table-column property="last_modified_time" label="最后更新时间" show-overflow-tooltip />
55
+          </el-table>
56
+        </div>
57
+      </div>
58
+    </div>
59
+    <template #footer>
60
+        <span class="dialog-footer">
61
+          <el-button @click="handleClose"> 取 消 </el-button>
62
+          <el-button type="primary" @click="submitEvent"> 确 定 </el-button>
63
+        </span>
64
+    </template>
65
+  </el-dialog>
66
+</template>
67
+<script setup lang="ts">
68
+import { reactive, ref, watch } from 'vue';
69
+import { unionPositionPackagesGet } from './ts/basicApi'
70
+import { ElMessage } from "element-plus";
71
+const props = defineProps({
72
+  visible: {
73
+    type: Boolean,
74
+    default: false
75
+  },
76
+  dataFillBack: {
77
+    type: Object,
78
+    default: () => { }
79
+  },
80
+  accIdsList: {
81
+    type: Array<{ id: string, name: string }>,
82
+    default: () => []
83
+  },
84
+  infoSelect: {
85
+    type: Array<{ id: 1 | 2, name: string }>,
86
+    default: () => []
87
+  }
88
+})
89
+const emit = defineEmits<{
90
+  (event: "close", val?: any): void;
91
+}>();
92
+const accId = ref('')
93
+const loading = ref(false)
94
+const tableDataAll = reactive({})
95
+const tableData = ref<any[]>([]);
96
+const dialogVisible = ref(props.visible)
97
+const params = reactive({})
98
+const searchKeyWrod = ref('')
99
+const allCheckboxValue = ref(false)
100
+const searchSelect = ref('1')
101
+const disabled = ref(false)
102
+const typeSelect = ref()
103
+/**关闭弹框 */
104
+const handleClose = () => {
105
+  emit('close')
106
+}
107
+/**点击媒体账户 */
108
+const accItemEvent = (item, type?) => {
109
+  accId.value = item?.id;
110
+  if (params[accId.value][typeSelect.value] && params[accId.value][typeSelect.value].length != 0) {
111
+    allCheckboxValue.value = true
112
+  } else {
113
+    allCheckboxValue.value = false
114
+  }
115
+  if (!tableDataAll[item.id][typeSelect.value] || type == 'upload') {
116
+    loading.value = true;
117
+    accId.value && unionPositionPackagesGet({ 'account_id': accId.value, 'type': typeSelect!.value }).then((data) => {
118
+      let res = data.map((v) => {
119
+        let flag = false;
120
+        params[accId.value] && params[accId.value][typeSelect.value] && Array.isArray(params[accId.value][typeSelect.value]) && params[accId.value][typeSelect.value]?.forEach((item) => {
121
+          if(item.union_package_id == v.union_package_id){flag=true}
122
+        });
123
+        return Object.assign(v, { 'checkboxValue': flag })
124
+      })
125
+      tableData.value = res;
126
+      tableDataAll[item.id][typeSelect.value] = res;
127
+      searchClick()
128
+      loading.value = false;
129
+    }).catch(() => {
130
+      loading.value = false;
131
+    })
132
+  } else {
133
+    tableData.value = tableDataAll[item.id][typeSelect.value];
134
+    searchClick()
135
+  }
136
+}
137
+/**确定提交 */
138
+const submitEvent = () => {
139
+  let obj = {};
140
+  for (let i in params) {
141
+    for(let j in params[i]){
142
+      if(params[i][j].length == 0){
143
+        ElMessage.warning(`${i} 未选择${j=='1'?'定投':'屏蔽'}流量包`)
144
+        return
145
+      }
146
+    }
147
+    if (params[i] && params[i] != '') {
148
+      obj[i] = params[i]
149
+    }
150
+  }
151
+  emit('close', {
152
+    type: 'submit',
153
+    val: Object.keys(obj).length == 0 ? null : obj
154
+  })
155
+}
156
+/**点击单行 */
157
+const rowClick = (row) => {
158
+  row.checkboxValue = !row.checkboxValue
159
+  if (row.checkboxValue) {
160
+    allCheckboxValue.value = true
161
+    if(params[accId.value][typeSelect.value].length >= 20) {
162
+      ElMessage.warning('最多可选择20个流量包,已达上限!')
163
+    }else {
164
+      params[accId.value][typeSelect.value].push(row)
165
+    }
166
+  } else {
167
+    allCheckboxValue.value = false
168
+    params[accId.value][typeSelect.value] = params[accId.value][typeSelect.value].filter((v)=>{
169
+      return v.union_package_id != row.union_package_id
170
+    })
171
+  }
172
+}
173
+/**点击全选 */
174
+const allCheckboxclick = () => {
175
+  if(disabled.value) return;
176
+  if (allCheckboxValue.value) {
177
+    tableDataAll[accId.value][typeSelect.value].forEach((v) => {
178
+      v.checkboxValue = false
179
+    })
180
+    params[accId.value][typeSelect.value] = []
181
+    allCheckboxValue.value = false
182
+  } else if (tableData.value?.length > 0) {
183
+    tableData.value.forEach((v,index)=>{
184
+      index < 20 ? v.checkboxValue = true : ''
185
+    })
186
+    if(tableData.value.length > 20) {
187
+      ElMessage.warning('最多可选择20个流量包,已为您选择前20个流量包!')
188
+    }
189
+    params[accId.value][typeSelect.value] = tableData.value.slice(0,20)
190
+    allCheckboxValue.value = true
191
+  }
192
+}
193
+/**模糊查询 */
194
+const searchClick = () => {
195
+  if (searchKeyWrod.value == '') {
196
+    tableData.value = tableDataAll[accId.value][typeSelect.value]
197
+  }else if (searchSelect.value == '1') { //根据流量包名称搜索
198
+    tableData.value = tableDataAll[accId.value][typeSelect.value].filter((v) => {
199
+      return v.union_package_name.indexOf(searchKeyWrod.value) != -1
200
+    })
201
+  }else if (searchSelect.value == '2') { //根据流量包ID搜索
202
+    tableData.value = tableDataAll[accId.value][typeSelect.value].filter((v) => {
203
+      return String(v.union_package_id).indexOf(searchKeyWrod.value) != -1
204
+    })
205
+  }
206
+  determineAllSelect()
207
+}
208
+/**清空 */
209
+const clearClick = (type) => {
210
+  tableData.value = tableDataAll[accId.value][typeSelect.value]
211
+  searchKeyWrod.value = ''
212
+  if (type == 'clear') {
213
+    tableDataAll[accId.value][typeSelect.value].forEach((v) => {
214
+      v.checkboxValue = false
215
+    })
216
+    params[accId.value][typeSelect.value] = []
217
+    allCheckboxValue.value = false
218
+  }
219
+  determineAllSelect()
220
+}
221
+/**全选是否可用判断 */
222
+const determineAllSelect = () => {
223
+  if ( tableData.value.length > 0) {
224
+    disabled.value = false
225
+  } else {
226
+    disabled.value = true
227
+  }
228
+}
229
+/**判断媒体账户是否选择完毕 */
230
+const checkTrue = (id) => {
231
+  let flag = true
232
+  props.infoSelect.forEach((item,index)=>{
233
+    if(!params[id][item.id] || params[id][item.id].length == 0){
234
+      flag = false
235
+    }
236
+  })
237
+  return flag
238
+}
239
+/**弹框显隐监听 */
240
+watch(
241
+  () => props.visible,
242
+  (newValue, oldValue) => {
243
+    dialogVisible.value = newValue
244
+    if (newValue) {
245
+      if(!props.infoSelect[0]) return;
246
+      typeSelect.value = props.infoSelect[0].id;
247
+      props.accIdsList.forEach((item)=>{
248
+        tableDataAll[item.id] = {
249
+          [props.infoSelect[0].id]: null
250
+        }
251
+        params[item.id] = {
252
+          [props.infoSelect[0].id]: [],
253
+        }
254
+        if(props.infoSelect[1]){
255
+          tableDataAll[item.id][props.infoSelect[1].id] = null;
256
+          params[item.id][props.infoSelect[1].id] = []
257
+        }
258
+      })
259
+
260
+      accItemEvent(props.accIdsList[0])
261
+    }
262
+  }, { immediate: true })
263
+</script>
264
+<style lang="scss" scoped>
265
+@import './outer.scss';
266
+
267
+.tabelListBox {
268
+  .title {
269
+    height: 50px;
270
+    background-color: #fafafa;
271
+  }
272
+}
273
+
274
+.self_checkbox {
275
+  width: 14px;
276
+  height: 14px;
277
+  border: 1px solid #d9d9d9;
278
+  border-radius: 2px;
279
+  position: relative;
280
+  cursor: pointer;
281
+}
282
+.self_checkbox_active {
283
+  background-color: #3173FF;
284
+  border-color: #3173FF;
285
+
286
+  &::after {
287
+    box-sizing: content-box;
288
+    content: "";
289
+    border: 1px solid #ffffff;
290
+    border-left: 0;
291
+    border-top: 0;
292
+    height: 7px;
293
+    left: 4px;
294
+    position: absolute;
295
+    top: 1px;
296
+    transform: rotate(45deg) scaleY(1);
297
+    width: 3px;
298
+    transition: transform .15s ease-in 50ms;
299
+    transform-origin: center;
300
+  }
301
+}
302
+.self_checkbox_disabled{
303
+  background-color: #edf2fc;
304
+  border-color: #dcdfe6;
305
+  cursor: not-allowed;
306
+  &::after{
307
+    border: none;
308
+  }
309
+}
310
+</style>

+ 18 - 1
src/components/businessMoudle/batchGdt/configArea/index.vue

@@ -82,6 +82,8 @@
82 82
   <ExpandPopulation :visible="basicInfoData.outerConfig.targetingPartyData.visible" :accIdsList="pageInfo.accIdsList" @close="(obj)=>{basicOuterClose({val: obj?.val || null, type: obj?.type || null, key:'targetingPartyData'})}" title="一方数据助攻"></ExpandPopulation>
83 83
   <!-- 精准匹配归因 -->
84 84
   <AttributionOuter :visible="basicInfoData.outerConfig.attributionOuter.visible" :accIdsList="pageInfo.accIdsList" @close="(obj)=>{basicOuterClose({val: obj?.val || null, type: obj?.type || null , key:'attributionOuter'})}"></AttributionOuter>
85
+  <!-- 优量汇流量包 -->
86
+  <UnionPosition :visible="basicInfoData.outerConfig.unionPosition.visible" :accIdsList="pageInfo.accIdsList" :infoSelect="basicInfoData.outerConfig.unionPosition.infoSelect" @close="(obj)=>{basicOuterClose({val: obj?.val || null, type: obj?.type || null , key:'unionPosition'})}"></UnionPosition>
85 87
 </template>
86 88
 <script setup lang="ts">
87 89
 import {getCurrentInstance, nextTick, onMounted, reactive, ref, provide, computed,toRef} from "vue";
@@ -95,6 +97,7 @@ import {deepCopy} from "@/common/common";
95 97
 import BasicInfo from "./basicInfo/index.vue";
96 98
 import ExpandPopulation from './basicInfo/expandPopulation.vue'
97 99
 import AttributionOuter from './basicInfo/attributionOuter.vue'
100
+import UnionPosition from './basicInfo/unionPosition.vue'
98 101
 import { getAdPresets } from './basicInfo/ts/basicApi'
99 102
 import { FillBackData } from './basicInfo/ts/fillBack'
100 103
 
@@ -150,7 +153,7 @@ const accEvent = () => {
150 153
 }
151 154
 
152 155
 //广告基本信息
153
-const basicInfoData = reactive({
156
+const basicInfoData = reactive<any>({
154 157
   visible:false,
155 158
   copywriting:[],
156 159
   fillBack: {},
@@ -162,6 +165,14 @@ const basicInfoData = reactive({
162 165
       name: '精准匹配归因',
163 166
       value: '',
164 167
     },
168
+    unionPosition: {
169
+      enabled: false,
170
+      visible:false,
171
+      optional: false, 
172
+      infoSelect: [],//流量包type
173
+      name: '优量汇流量包',
174
+      value: '',
175
+    },
165 176
     expandPopulation: {
166 177
       enabled: false, //是否需要配置
167 178
       visible:false, //对应弹框显隐
@@ -278,6 +289,11 @@ const getButtonBasicOuter = (res) => {
278 289
   if(res?.attribution_type == 2) { // 精准匹配归因
279 290
     basicInfoData.outerConfig.attributionOuter.enabled = true;
280 291
   }
292
+  if(res?.union_position_enabled == 1 || res?.exclude_union_position_enabled == 1) { //优量汇流量包
293
+    basicInfoData.outerConfig.unionPosition.enabled = true;
294
+    res?.union_position_enabled == 1 && basicInfoData.outerConfig.unionPosition.infoSelect.push({name:'定投流量包',id: 1})
295
+    res?.exclude_union_position_enabled == 1 && basicInfoData.outerConfig.unionPosition.infoSelect.push({name:'屏蔽流量包',id:2})
296
+  }
281 297
 }
282 298
 /**点击基础信息外层配置 */
283 299
 const basicOuterClick = (key) => {
@@ -291,6 +307,7 @@ interface IBasicOuterClose {
291 307
   'val'?: string
292 308
 }
293 309
 const basicOuterClose = ({key,val,type}:IBasicOuterClose) => {
310
+  console.log('外部配置',key,val)
294 311
   basicInfoData.outerConfig[key].visible = false;
295 312
   if(type == 'submit') {
296 313
     basicInfoData.outerConfig[key].value = val;