Browse Source

账号分配

houxiaohua 6 months ago
parent
commit
14660d66a4
72 changed files with 918 additions and 61 deletions
  1. 0 2
      dist/assets/index-B-M_fJAo.js
  2. 1 1
      dist/assets/index-BsLd0kJB.css
  3. 2 0
      dist/assets/index-CoGxHAod.js
  4. 1 0
      dist/assets/index-DSQ7fKBy.css
  5. 0 1
      dist/assets/index-M64Vbvjr.css
  6. 1 1
      dist/index.html
  7. 1 0
      dist/js/Echarts/Echarts.D2RVNpV7.js
  8. 0 1
      dist/js/Echarts/echarts.B1e27IPe.js
  9. 1 1
      dist/js/Home/index.yhz9P9Nf.js
  10. 1 1
      dist/js/_dialog/_dialog.D2HnYN3y.js
  11. 1 1
      dist/js/_input/_input.D3r6RnaO.js
  12. 1 1
      dist/js/_inputAppend/_inputAppend.BtaYes0h.js
  13. 1 1
      dist/js/_select/_select.BNOT3h5I.js
  14. 1 1
      dist/js/acStatement/index.C790mken.js
  15. 1 0
      dist/js/adAccountGroup/index.CER_0KEY.js
  16. 0 1
      dist/js/adAccountGroup/index.D8v_LpqC.js
  17. 1 1
      dist/js/adTask/index.chWQLxhU.js
  18. 1 1
      dist/js/adTask3/index.Bf_LX02P.js
  19. 1 1
      dist/js/adqManage/index.MJS59hPy.js
  20. 1 1
      dist/js/adqManage3/index.BRbemY-N.js
  21. 0 1
      dist/js/api/api.CiL1JNfb.js
  22. 1 1
      dist/js/api/api.CBddB12r.js
  23. 1 0
      dist/js/api/api.Cy7QJEb6.js
  24. 1 1
      dist/js/api/api.5tpjNCX9.js
  25. 1 1
      dist/js/basisMoudle/error.RSQ3dC6C.js
  26. 1 1
      dist/js/basisMoudle/login.Bs1sKBvb.js
  27. 1 1
      dist/js/checkboxDefault/checkboxDefault.BgULPinQ.js
  28. 1 1
      dist/js/collectClip/index.DEPJ9_CC.js
  29. 1 1
      dist/js/commonList/commonList.Bo-Rt009.js
  30. 1 1
      dist/js/configArea/index.CLw7EhJK.js
  31. 1 1
      dist/js/configArea/index.Bxp15YrB.js
  32. 1 1
      dist/js/define/define.BJ6hJcAt.js
  33. 0 1
      dist/js/echarts/echarts.B1e27IPe.js
  34. 1 1
      dist/js/gdtList/index.Bp2omFjB.js
  35. 1 1
      dist/js/gdtList3/index.DdBoj864.js
  36. 1 1
      dist/js/index/index.Bjkcevv2.js
  37. 1 1
      dist/js/index/index.B7uxSgUj.js
  38. 1 1
      dist/js/index/index.CnROzGUW.js
  39. 1 1
      dist/js/index/index.tGYguRqT.js
  40. 1 1
      dist/js/layout/index.Czteb2TZ.js
  41. 1 1
      dist/js/layout/index_head.CuNFpMWx.js
  42. 1 1
      dist/js/limitManage/index.D3mMrb8i.js
  43. 1 1
      dist/js/materialBlock/materialBlock.CPXRJvDt.js
  44. 1 1
      dist/js/materialData/index.PrAUPRn5.js
  45. 1 1
      dist/js/materialLibrary/index.wlAQf9dm.js
  46. 1 1
      dist/js/materialTs/materialTs.B1Knf1kw.js
  47. 1 1
      dist/js/memberManage/index.kbJHuOF3.js
  48. 1 1
      dist/js/menu/index.jVWadtsP.js
  49. 1 1
      dist/js/miniprogram/index.BL81i49q.js
  50. 1 1
      dist/js/oeAdAccount/index.CILTx2qz.js
  51. 1 1
      dist/js/projectManage/index.D70my85k.js
  52. 1 1
      dist/js/radioGroup/radioGroup.Co2VfwKI.js
  53. 1 1
      dist/js/tableInfo/tableInfo.DFiuymlx.js
  54. 1 1
      dist/js/tagBlock/tagBlock.Dqj1h2Nm.js
  55. 1 1
      dist/js/taskList/index.D-Z36nfv.js
  56. 1 1
      dist/js/teamManage/index.CRi4VhBK.js
  57. 1 1
      dist/js/timeScreen/timeScreen.b4x4ubBm.js
  58. 1 1
      dist/js/warning/warning.BEXz9tLN.js
  59. 1 1
      dist/js/wechatPage/index.DtbL4Ti3.js
  60. 1 1
      dist/js/weekTime/weekTime.D__sF9QU.js
  61. 1 1
      dist/js/weekTime/weekTime.B4DMv7w7.js
  62. 1 0
      src/api/api.ts
  63. 71 0
      src/components/businessMoudle/adAccountGroup/dialog/addResult.vue
  64. 157 0
      src/components/businessMoudle/adAccountGroup/dialog/childList.vue
  65. 166 0
      src/components/businessMoudle/adAccountGroup/dialog/importDialog.vue
  66. 73 0
      src/components/businessMoudle/adAccountGroup/dialog/manualInput.vue
  67. 231 0
      src/components/businessMoudle/adAccountGroup/dialog/type.vue
  68. 31 0
      src/components/businessMoudle/adAccountGroup/hooks/agency.ts
  69. 57 0
      src/components/businessMoudle/adAccountGroup/hooks/api.ts
  70. 61 0
      src/components/businessMoudle/adAccountGroup/hooks/dialog.ts
  71. 12 2
      src/components/businessMoudle/adAccountGroup/index.vue
  72. 2 2
      src/components/businessMoudle/oeAdAccount/index.vue

File diff suppressed because it is too large
+ 0 - 2
dist/assets/index-B-M_fJAo.js


File diff suppressed because it is too large
+ 1 - 1
dist/assets/index-BsLd0kJB.css


File diff suppressed because it is too large
+ 2 - 0
dist/assets/index-CoGxHAod.js


File diff suppressed because it is too large
+ 1 - 0
dist/assets/index-DSQ7fKBy.css


File diff suppressed because it is too large
+ 0 - 1
dist/assets/index-M64Vbvjr.css


+ 1 - 1
dist/index.html

@@ -12,7 +12,7 @@
12 12
 			document.write('<script src="' + src + '"><\/script>');
13 13
 			})();
14 14
     </script>
15
-    <script type="module" crossorigin src="./assets/index-B-M_fJAo.js"></script>
15
+    <script type="module" crossorigin src="./assets/index-CoGxHAod.js"></script>
16 16
     <link rel="modulepreload" crossorigin href="./js/@vue/@vue.lccsL1Mu.js">
17 17
     <link rel="modulepreload" crossorigin href="./js/vue-router/vue-router.D86bYXwF.js">
18 18
     <link rel="modulepreload" crossorigin href="./js/vue-demi/vue-demi.Dq6ymT-8.js">

File diff suppressed because it is too large
+ 1 - 0
dist/js/Echarts/Echarts.D2RVNpV7.js


File diff suppressed because it is too large
+ 0 - 1
dist/js/Echarts/echarts.B1e27IPe.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/Home/index.yhz9P9Nf.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/_dialog/_dialog.D2HnYN3y.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/_input/_input.D3r6RnaO.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/_inputAppend/_inputAppend.BtaYes0h.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/_select/_select.BNOT3h5I.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/acStatement/index.C790mken.js


File diff suppressed because it is too large
+ 1 - 0
dist/js/adAccountGroup/index.CER_0KEY.js


File diff suppressed because it is too large
+ 0 - 1
dist/js/adAccountGroup/index.D8v_LpqC.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/adTask/index.chWQLxhU.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/adTask3/index.Bf_LX02P.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/adqManage/index.MJS59hPy.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/adqManage3/index.BRbemY-N.js


File diff suppressed because it is too large
+ 0 - 1
dist/js/api/api.CiL1JNfb.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/api/api.CBddB12r.js


File diff suppressed because it is too large
+ 1 - 0
dist/js/api/api.Cy7QJEb6.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/api/api.5tpjNCX9.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/basisMoudle/error.RSQ3dC6C.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/basisMoudle/login.Bs1sKBvb.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/checkboxDefault/checkboxDefault.BgULPinQ.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/collectClip/index.DEPJ9_CC.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/commonList/commonList.Bo-Rt009.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/configArea/index.CLw7EhJK.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/configArea/index.Bxp15YrB.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/define/define.BJ6hJcAt.js


File diff suppressed because it is too large
+ 0 - 1
dist/js/echarts/echarts.B1e27IPe.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/gdtList/index.Bp2omFjB.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/gdtList3/index.DdBoj864.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/index/index.Bjkcevv2.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/index/index.B7uxSgUj.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/index/index.CnROzGUW.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/index/index.tGYguRqT.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/layout/index.Czteb2TZ.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/layout/index_head.CuNFpMWx.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/limitManage/index.D3mMrb8i.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/materialBlock/materialBlock.CPXRJvDt.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/materialData/index.PrAUPRn5.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/materialLibrary/index.wlAQf9dm.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/materialTs/materialTs.B1Knf1kw.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/memberManage/index.kbJHuOF3.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/menu/index.jVWadtsP.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/miniprogram/index.BL81i49q.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/oeAdAccount/index.CILTx2qz.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/projectManage/index.D70my85k.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/radioGroup/radioGroup.Co2VfwKI.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/tableInfo/tableInfo.DFiuymlx.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/tagBlock/tagBlock.Dqj1h2Nm.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/taskList/index.D-Z36nfv.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/teamManage/index.CRi4VhBK.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/timeScreen/timeScreen.b4x4ubBm.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/warning/warning.BEXz9tLN.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/wechatPage/index.DtbL4Ti3.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/weekTime/weekTime.D__sF9QU.js


File diff suppressed because it is too large
+ 1 - 1
dist/js/weekTime/weekTime.B4DMv7w7.js


+ 1 - 0
src/api/api.ts

@@ -93,6 +93,7 @@ export enum Api{
93 93
     ad_account_group_edit = '/api/adAccountGroup/edit',
94 94
     ad_account_group_convert = '/api/adAccountGroup/convert',
95 95
     ad_account_group_detail = '/api/adAccountGroup/detail',
96
+    oe_account_add_to_group = '/api/adAccountGroup/addAccount',
96 97
 
97 98
     //定向包
98 99
     directPacket_add = '/api/ad/targetingsAdd',

+ 71 - 0
src/components/businessMoudle/adAccountGroup/dialog/addResult.vue

@@ -0,0 +1,71 @@
1
+<template>
2
+  <Dialog ref="DialogRef"
3
+          :dialogVisible="dialogShow"
4
+          @close="closeEvent"
5
+          width="800px"
6
+          height="420px"
7
+          minheight="400px"
8
+          :dialog-title="title"
9
+          class="addEditText">
10
+    <template v-slot:content>
11
+      <div class="dialogBox" v-loading="loading">
12
+        <div class="tMar20">
13
+          <TableList
14
+              tableHeight="100vh"
15
+              :tableData="data"
16
+              :descol="descolParams"
17
+          >
18
+          </TableList>
19
+        </div>
20
+      </div>
21
+    </template>
22
+  </Dialog>
23
+
24
+</template>
25
+<script setup lang="ts">
26
+import Dialog from '@/components/capsulationMoudle/_dialog.vue'
27
+import {reactive, ref} from "vue";
28
+
29
+const emit = defineEmits<{
30
+  (event: "initType"): void;
31
+}>();
32
+
33
+const descolParams = reactive([
34
+  { name:'广告账户id',column:'advertiser_id'},
35
+  { name:'广告账户名',column:'advertiser_name'},
36
+  { name:'状态',column:'note'},
37
+])
38
+
39
+const props = withDefaults(defineProps<{
40
+  title?: string,
41
+  data?: any
42
+}>(), {
43
+  title: '添加文案',
44
+  data: null
45
+})
46
+
47
+const dialogShow = ref<boolean>(false)
48
+
49
+//添加文案-确定
50
+const loading = ref<boolean>(false)
51
+
52
+//关闭
53
+const closeEvent = () => {
54
+  dialogShow.value = false
55
+  emit('initType')
56
+}
57
+
58
+// 切换显隐
59
+const switchShow = (val:boolean)=>{
60
+  dialogShow.value = val
61
+}
62
+// 父组件共享值
63
+defineExpose({
64
+  switchShow,
65
+});
66
+</script>
67
+
68
+<style lang="scss" scoped>
69
+
70
+
71
+</style>

+ 157 - 0
src/components/businessMoudle/adAccountGroup/dialog/childList.vue

@@ -0,0 +1,157 @@
1
+<template>
2
+  <div v-loading="loading" class="tMar15">
3
+    <div class="flex">
4
+      <el-input v-model="keyword" style="width: 300px;" placeholder="请输入搜索关键词" :prefix-icon="Search" size="default"
5
+        clearable @input="search()" @clear="search()" />
6
+      <div v-if="selectionFlag" class="flex_1 flex">
7
+        <p class="f12 c-555">(已选 {{ multipleSelection.length }} 个媒体账户)</p>
8
+        <span class="f13 pointer c-theme" @click="clearMultiple">清空选择</span>
9
+      </div>
10
+    </div>
11
+
12
+
13
+    <el-table ref="multipleTableRef" :data="tableData" style="width: 100%" row-key="account_id" class="tMar15" height="36vh"
14
+      :header-cell-style="tableHeaderStyle" @selection-change="handleSelectionChange" border>
15
+      <el-table-column v-if="selectionFlag" reserve-selection type="selection" width="55" align="center" />
16
+      <el-table-column v-else label="序号" width="80" align="center">
17
+        <template #default="scope">
18
+          {{ (scope.$index + 1) + (pagination.page - 1) * pagination.pageSize }}
19
+        </template>
20
+      </el-table-column>
21
+      <el-table-column prop="corporation_name" label="账户名称" />
22
+      <el-table-column prop="account_id" label="账户ID" />
23
+    </el-table>
24
+    <!-- 分页 -->
25
+    <div class="flex_center tMar10 bMar10">
26
+      <el-pagination v-model:current-page="pagination.page" v-model:page-size="pagination.pageSize"
27
+        :page-sizes="[10, 20, 50, 100]" :small="true" layout="total, sizes, prev, pager, next, jumper"
28
+        :total="pagination.total" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
29
+    </div>
30
+
31
+  </div>
32
+</template>
33
+<script setup lang="ts">
34
+import { nextTick, onBeforeMount, reactive, ref, watch } from 'vue';
35
+import { accountChildListAxios } from '../hooks/api'
36
+import { Search } from '@element-plus/icons-vue'
37
+import { tableHeaderStyle } from '@/api/eventModel'
38
+import _, { reject } from 'lodash';
39
+const props = defineProps({
40
+  agencyItem: {
41
+    type: Object,
42
+    default: () => { }
43
+  },
44
+  importType: {
45
+    type: String,
46
+    default: ''
47
+  },
48
+  handType: {
49
+    type: Number,
50
+    default: 0
51
+  }
52
+})
53
+const emit = defineEmits<{
54
+  (event: "total", value: any): void;
55
+}>();
56
+const loading = ref(false)
57
+const keyword = ref('')
58
+const oldTableDataMain = ref([]);//原始账户列表数据
59
+const oldTableData = ref([]);//搜索时进行操作的账户列表
60
+const tableData = ref([]);//table列表数据
61
+const multipleSelection = ref<any[]>([])
62
+const selectionFlag = ref(false)
63
+const multipleTableRef = ref()
64
+const total = ref(0)
65
+const pagination = reactive({
66
+  page: 1,
67
+  pageSize: 20,
68
+  total: 0
69
+})
70
+/**多选 */
71
+const handleSelectionChange = (val: any[], row) => {
72
+  multipleSelection.value = val
73
+}
74
+/**清空选择 */
75
+const clearMultiple = () => {
76
+  multipleSelection.value = []
77
+  multipleTableRef.value?.clearSelection()
78
+}
79
+/**模糊搜索 */
80
+const search = () => {
81
+  let oldList = _.cloneDeep(oldTableDataMain.value)
82
+  if (!isNaN(Number(keyword.value))) { //根据账户ID进行搜索
83
+    oldTableData.value = oldList.filter((v: any) => {
84
+      return v.account_id?.indexOf(keyword.value) != -1
85
+    })
86
+  } else {//根据账户名称就行搜索
87
+    oldTableData.value = oldList.filter((v: any) => {
88
+      return v.corporation_name?.indexOf(keyword.value) != -1
89
+    })
90
+  }
91
+  pagination.total = oldTableData.value.length;
92
+  pagination.page = 1;
93
+  getPagination()
94
+}
95
+/**分页 */
96
+const getPagination = () => {
97
+  const dataList = _.cloneDeep(oldTableData.value)
98
+  tableData.value = dataList.slice((pagination.page - 1) * pagination.pageSize, pagination.page * pagination.pageSize)
99
+}
100
+const handleSizeChange = (val) => {
101
+  pagination.page = 1;
102
+  pagination.pageSize = val;
103
+  getPagination()
104
+}
105
+const handleCurrentChange = (val) => {
106
+  pagination.page = val;
107
+  getPagination()
108
+}
109
+const getList = () => {
110
+  if (!props.agencyItem?.agency_account_id) return;
111
+  loading.value = true;
112
+  accountChildListAxios({
113
+    agency_account_id: props.agencyItem?.agency_account_id,
114
+    keyword: keyword.value
115
+  }).then((res: any) => {
116
+    loading.value = false;
117
+    oldTableDataMain.value = res.list;
118
+    oldTableData.value = _.cloneDeep(oldTableDataMain.value)
119
+    pagination.total = res.total;
120
+    total.value = res.total
121
+    emit('total', total.value)
122
+    getPagination()
123
+  }).catch(() => {
124
+    loading.value = false;
125
+  })
126
+}
127
+onBeforeMount(() => {
128
+  getList();
129
+})
130
+
131
+/** 暴露自己的属性供父组件使用 */
132
+/** 获取选中的媒体账户 */
133
+const getMultipleList = () => {
134
+  return new Promise((resolve,reject)=>{
135
+    if(selectionFlag.value) {
136
+      resolve(multipleSelection.value)
137
+    }else{
138
+      resolve(oldTableDataMain.value)
139
+    }
140
+  })
141
+}
142
+defineExpose({
143
+  getMultipleList
144
+});
145
+
146
+watch([
147
+  () => props.importType,
148
+  () => props.handType
149
+], (newValue, oldValue) => {
150
+  if (newValue[0] == 'part' && newValue[1] == 2) {
151
+    selectionFlag.value = true
152
+    multipleSelection.value = []
153
+  } else {
154
+    selectionFlag.value = false
155
+  }
156
+}, { immediate: true })
157
+</script>

+ 166 - 0
src/components/businessMoudle/adAccountGroup/dialog/importDialog.vue

@@ -0,0 +1,166 @@
1
+<template>
2
+  <el-dialog class="gdt-dialog" :close-on-click-modal="false" :destroy-on-close="true" v-model="visible" title="导入广告账户"
3
+    width="800px" top="40px" :before-close="handleClose">
4
+    <div v-loading="loading" class="container">
5
+      <!-- S 导入type操作 -->
6
+      <el-radio-group v-model="importType.type" size="default" class="block tMar20">
7
+        <el-radio-button v-for="item in importType.list" :label="item.id">{{ item.name }}</el-radio-button>
8
+      </el-radio-group>
9
+      <el-radio-group v-model="handType.type" size="default" class="block tMar10" v-if="importType.type == 'part'">
10
+        <el-radio v-for="item in handType.list" :label="item.id">{{ item.name }}</el-radio>
11
+      </el-radio-group>
12
+      <!-- E 导入type操作 -->
13
+
14
+      <div class="flex_start c-aaa line18 tMar10">
15
+        <el-icon class="rMar7 tMar2" color="#ff9b48">
16
+          <WarningFilled />
17
+        </el-icon>
18
+        <span class="flex_1 "
19
+          v-if="importType.type == 'part' && handType.type == 1">请确保输入的广告主账户已属于对应的代理商,否则会导致失败;单次授权账户上限{{ agencyCount
20
+          }}个,如账户数量较多,请分批次输入</span>
21
+        <span class="flex_1 "
22
+          v-if="importType.type == 'part' && handType.type == 2">该代理商账户下共{{ acc_count }}个媒体账户,请选择想要导入的账户名称</span>
23
+        <span class="flex_1 " v-if="importType.type == 'all'">该代理商账户下共{{ acc_count }}个媒体账户</span>
24
+      </div>
25
+
26
+      <!-- 手动输入 -->
27
+      <ManualInput v-show="importType.type == 'part' && handType.type == 1" :maxRow="agencyCount" @mInput="getMInput">
28
+      </ManualInput>
29
+
30
+      <!-- 列表选择或者全部导入 -->
31
+      <ChildList ref="ChildListRef" v-show="importType.type == 'part' && handType.type == 2 || importType.type == 'all'"
32
+        :groupItem="groupItem" :importType="importType.type" :handType="handType.type" @total="getCountAcc"></ChildList>
33
+    </div>
34
+    <template #footer>
35
+      <div class="dialog-footer" style="text-align: right;padding:10px;padding-top: 0;">
36
+        <el-button size="default" @click="handleClose"> 取 消 </el-button>
37
+        <el-button size="default" type="primary" @click="submitEvent"> 确 认 </el-button>
38
+      </div>
39
+    </template>
40
+    <!-- 账号导入结果 -->
41
+    <ResultDialog :title="textTitle" :data="data" ref="TextDialogRef"></ResultDialog>
42
+  </el-dialog>
43
+</template>
44
+<script setup lang="ts">
45
+import { Search } from '@element-plus/icons-vue'
46
+import Select from '@/components/capsulationMoudle/_select.vue'
47
+import { getPromotedObjectType } from '@/components/businessMoudle/batchGdt/configArea/basicInfo/ts/basicApi'
48
+import { nextTick, onBeforeMount, reactive, ref, watch, provide } from 'vue';
49
+import { ElMessage } from 'element-plus';
50
+import _ from 'lodash';
51
+import { agencyDialogExport } from '../hooks/dialog'
52
+import ChildList from './childList.vue'
53
+import ManualInput from './manualInput.vue'
54
+import { accountImAddAxios } from '../hooks/api'
55
+import ResultDialog from './addResult.vue'
56
+
57
+const emit = defineEmits<{
58
+  (event: "close", val?: any): void;
59
+}>();
60
+const loading = ref(false)
61
+const agencyCount = 300
62
+const groupItem = ref<any>('')
63
+const inputValue = ref('')
64
+const visible = ref(false)
65
+const acc_count = ref(0)
66
+const ChildListRef = ref()
67
+const data = ref({})
68
+const textTitle=ref<string>('') 
69
+
70
+const TextDialogRef=ref<{switchShow:(val:boolean)=>void,
71
+  text_textarea:string,
72
+  textVal:string|number,
73
+}>()
74
+
75
+const addTextEvent = ()=>{
76
+  textTitle.value = '广告账户导入结果'
77
+  nextTick(()=>{
78
+    TextDialogRef.value!.switchShow(true)
79
+  })
80
+}
81
+
82
+const {
83
+  importType,
84
+  handType,
85
+  getUserList,
86
+  getProjectList,
87
+} = agencyDialogExport()
88
+
89
+onBeforeMount(() => {
90
+  getUserList()
91
+  getProjectList()
92
+})
93
+
94
+/**点击关闭弹框 **/
95
+const handleClose = () => {
96
+  visible.value = false
97
+}
98
+const getCountAcc = (val) => {
99
+  acc_count.value = val
100
+}
101
+const getMInput = (val) => {
102
+  inputValue.value = val
103
+}
104
+
105
+/**点击确定 */
106
+const submitEvent = async () => {
107
+  let data_str = '';
108
+  if (importType.type == 'part' && handType.type == 1) {
109
+    data_str = inputValue.value
110
+  }
111
+  if (data_str == '') {
112
+    ElMessage.warning('请输入账户ID或手动选择广告账户!');
113
+    return
114
+  }
115
+  loading.value = true
116
+  accountImAddAxios({
117
+    group_id: groupItem.value.id,
118
+    import_method: importType.type,
119
+    type: handType.type,
120
+    data_str,
121
+  }).then((res) => {
122
+    loading.value = false
123
+    if (res) {
124
+      console.log(res)
125
+      ElMessage.warning('导入完成')
126
+      data.value = res
127
+      // visible.value = false
128
+      addTextEvent()
129
+      // emit('close')
130
+    }
131
+  }).catch(() => { loading.value = false })
132
+}
133
+
134
+
135
+/**初始化 */
136
+const initFun = async (flag, obj) => {
137
+  visible.value = flag
138
+  if (flag) {
139
+    groupItem.value = obj
140
+  }
141
+}
142
+// 暴露自己的属性供父组件使用
143
+defineExpose({
144
+  initFun,
145
+});
146
+
147
+</script>
148
+<style lang="scss" scoped>
149
+@import "@/assets/style/batchDialogGdt.scss";
150
+
151
+:deep(.spanTitle),
152
+.spanTitle {
153
+  font-size: 13px;
154
+  color: #666;
155
+}
156
+
157
+.container {
158
+  max-height: 73vh;
159
+  overflow-y: auto;
160
+  height: auto !important;
161
+  border-bottom: 1px solid #f2f2f2;
162
+}
163
+
164
+.block {
165
+  display: block;
166
+}</style>

+ 73 - 0
src/components/businessMoudle/adAccountGroup/dialog/manualInput.vue

@@ -0,0 +1,73 @@
1
+<template>
2
+  <div class="tMar20 textBox">
3
+    <div class="flex_between titleBox">
4
+      <div>请输入广告主账户ID({{ getRows() }} / {{ maxRow }} )</div>
5
+      <div class="c-theme pointer" @click="text_textarea = ''">清空</div>
6
+    </div>
7
+    <div class="tips">请输入广告主账户ID,多账户请换行(即每个账户ID一行)</div>
8
+    <el-input id="emojiInput" v-model="text_textarea" resize="none" :rows="12" type="textarea" style="width: 100%;" @input="emit('mInput', text_textarea)"/>
9
+  </div>
10
+</template>
11
+<script setup lang="ts">
12
+import { ref, watch } from 'vue';
13
+
14
+const props = defineProps({
15
+  maxRow:{
16
+    type: Number,
17
+    default: 300
18
+  }
19
+})
20
+const emit = defineEmits<{
21
+  (event: "mInput", value: string): void;
22
+}>();
23
+const text_textarea = ref<any>('')
24
+//获取行数
25
+const getRows = ()=>{
26
+  let count:number = 0
27
+  text_textarea.value?.split('\n').forEach(item=>{
28
+    if(item!==''){
29
+      count++
30
+    }
31
+  })
32
+  return count
33
+}
34
+
35
+watch(()=>text_textarea.value, (newValue, oldValue) => {
36
+  if(getRows() > props.maxRow) {
37
+    text_textarea.value = oldValue;
38
+  }
39
+}, { immediate: true })
40
+</script>
41
+<style scoped lang="scss">
42
+.textBox{
43
+  color: #161E46;
44
+  border: 1px solid #d9d9d9;
45
+  height: 340px;
46
+  overflow-y: auto;
47
+  scrollbar-color: transparent transparent;
48
+  &::-webkit-scrollbar{
49
+    width: 2px;
50
+  }
51
+  &:deep(.el-textarea){
52
+    --el-input-border:none;
53
+    --el-input-border-color:none;
54
+    padding: 0 10px;
55
+  }
56
+  &:deep(.el-textarea__inner:hover){
57
+    box-shadow: none;
58
+  }
59
+  &:deep(.el-textarea__inner:focus){
60
+    box-shadow: none;
61
+  }
62
+  .titleBox{
63
+    background-color: #f5f5f5;
64
+    padding: 15px 20px;
65
+  }
66
+  .tips{
67
+    color: #999;
68
+    background-color: rgba(49, 115, 255, .1);
69
+    padding: 15px 20px;
70
+    font-size: 12px;
71
+  }
72
+}
73
+</style>

+ 231 - 0
src/components/businessMoudle/adAccountGroup/dialog/type.vue

@@ -0,0 +1,231 @@
1
+<template>
2
+  <div class="flex">
3
+    <!-- <div class="f14 rMar10 c-theme_text">分类:</div> -->
4
+    <el-select class="addTextSelect" v-model="textVal"
5
+               placeholder="请选择分类" clearable filterable
6
+               :allow-create="allowCreateFlag"
7
+               @change="changeEvent"
8
+               :style="{width:inputWidth}">
9
+      <el-option v-for="item in pageInfo.textTypeList" :key="item.id" :label="item.name" :value="item.id" >
10
+        <div class="flex">
11
+          <span>{{ item.name }}</span>
12
+          <span class="lMarauto" v-if="allowCreateFlag">
13
+            <span><el-icon color="#3173FF" class="pointer f12" @click="editTypeEvent(item)"><i-ep-Edit /></el-icon></span>
14
+            <span @click="deleType(item)"><el-icon color="#3173FF" class="pointer f12 lMar5"><i-ep-Delete /></el-icon></span>
15
+          </span>
16
+        </div>
17
+      </el-option>
18
+    </el-select>
19
+  </div>
20
+
21
+  <!--  修改类型-->
22
+  <Dialog ref="DialogRef_editType"
23
+          :dialogVisible="dialogShow_editType"
24
+          @confirm="confirmEvent_editType"
25
+          @close="dialogShow_editType = false"
26
+          width="600px"
27
+          dialog-title="修改类型">
28
+    <template v-slot:content>
29
+      <div class="dialogBox" v-loading="typeLoading">
30
+        <Input ref="InputRef_typeName" title="" />
31
+      </div>
32
+    </template>
33
+  </Dialog>
34
+
35
+  <!--  删除类型-->
36
+  <Dialog ref="DialogRef_deleType"
37
+          :dialogVisible="dialogShow_deleType"
38
+          @confirm="confirmEvent_deleType"
39
+          @close="dialogShow_deleType = false"
40
+          width="400px"
41
+          minheight="50px"
42
+          dialog-title="提示">
43
+    <template v-slot:content>
44
+      <div class="dialogBox flex" v-loading="deleLoading">
45
+        <el-icon color="#e6a23c" size="20" class="rMar15"><i-ep-WarningFilled /></el-icon>
46
+        <span class="line21">删除该分类后,标题库列表和筛选项将不再展示该分类,确认删除吗?</span>
47
+      </div>
48
+    </template>
49
+  </Dialog>
50
+
51
+</template>
52
+<script setup lang="ts">
53
+import Dialog from '@/components/capsulationMoudle/_dialog.vue'
54
+import Input from '@/components/capsulationMoudle/_input.vue'
55
+import {getCurrentInstance, nextTick, onMounted, reactive, ref} from "vue";
56
+import {reactiveTableAndAny, textParam} from "@/api/ApiModel";
57
+import {Api} from "@/api/api";
58
+import {ElMessage} from "element-plus";
59
+
60
+const emit = defineEmits<{
61
+  (event: "init"): void;
62
+  (event: "change",val:any): void;
63
+}>();
64
+
65
+
66
+const { proxy } = getCurrentInstance() as any;
67
+// 全局方法定义
68
+const NumberHandle = proxy.$NumberHandle
69
+
70
+const props = withDefaults(defineProps<{
71
+  allowCreateFlag?: boolean,
72
+  inputWidth?: string,
73
+}>(), {
74
+  allowCreateFlag: false,
75
+  inputWidth:'300px'
76
+})
77
+
78
+
79
+const dialogShow = ref<boolean>(false)
80
+
81
+// 选中的事件
82
+const changeEvent = (val:any) => {
83
+  emit('change',val)
84
+}
85
+
86
+//列表
87
+const pageInfo = reactive<reactiveTableAndAny>({
88
+  textTypeList:[],
89
+})
90
+const init = async () => {
91
+  let res:any = await proxy.$http.get(Api.text_type_list)
92
+  if(res&&res.errNo=='0'){
93
+    let resNew:any = res.rst
94
+    //列表赋值
95
+    pageInfo.textTypeList = resNew
96
+  }else{
97
+    ElMessage.error(res.errMsg)
98
+  }
99
+}
100
+
101
+
102
+//添加文案-确定
103
+const loading = ref<boolean>(false)
104
+const textVal = ref<string|number>()
105
+
106
+//修改类型
107
+const InputRef_typeName=ref<{value:string}>()
108
+const dialogShow_editType = ref<boolean>(false)
109
+const typeLoading = ref<boolean>(false)
110
+const edit_id = ref<number>(0)
111
+const confirmEvent_editType = async ()=>{
112
+  if(InputRef_typeName.value!.value == ''){
113
+    ElMessage.error('请输入名称')
114
+    return
115
+  }
116
+  typeLoading.value = true
117
+  const paramsModel = reactive<textParam>({
118
+    classify_id:Number(edit_id.value),
119
+    classify_name:InputRef_typeName.value!.value
120
+  })
121
+  let res:any = await proxy.$http.post(Api.text_type_edit,paramsModel)
122
+  typeLoading.value  = false
123
+  if(res&&res.errNo=='0'){
124
+    let resNew:any = res.rst
125
+    dialogShow_editType.value = false
126
+    edit_id.value = 0
127
+    await init()
128
+  }else{
129
+    ElMessage.error(res.errMsg)
130
+  }
131
+}
132
+
133
+// 新建类型
134
+const add_type = async ()=>{
135
+  const paramsModel = reactive<textParam>({
136
+    classify_name:textVal.value
137
+  })
138
+  let res:any = await proxy.$http.post(Api.text_type_add,paramsModel)
139
+  if(res&&res.errNo=='0'){
140
+    let resNew:any = res.rst
141
+    textVal.value = resNew.classify_id
142
+  }else{
143
+    ElMessage.error(res.errMsg)
144
+  }
145
+}
146
+
147
+//编辑分类
148
+const editTypeEvent = (item:any)=>{
149
+  dialogShow_editType.value = true
150
+  edit_id.value = item.id
151
+  nextTick(()=> {
152
+    InputRef_typeName.value!.value = item.name
153
+  })
154
+}
155
+//删除
156
+const dialogShow_deleType = ref<boolean>(false)
157
+const deleLoading = ref<boolean>(false)
158
+const deleType = (item:any)=>{
159
+  dialogShow_deleType.value = true
160
+  edit_id.value = item.id
161
+}
162
+const confirmEvent_deleType = async () => {
163
+  deleLoading.value = true
164
+  const paramsModel = reactive<textParam>({
165
+    classify_id:edit_id.value
166
+  })
167
+  let res:any = await proxy.$http.post(Api.text_type_dele,paramsModel)
168
+  deleLoading.value = false
169
+  if(res&&res.errNo=='0'){
170
+    let resNew:any = res.rst
171
+    dialogShow_deleType.value = false
172
+    textVal.value = ''
173
+    await init()
174
+  }else{
175
+    ElMessage.error(res.errMsg)
176
+  }
177
+}
178
+
179
+
180
+// 父组件共享值
181
+defineExpose({
182
+  init,
183
+  add_type,
184
+  textVal,
185
+});
186
+
187
+
188
+onMounted(()=>{
189
+  nextTick(async ()=>{
190
+
191
+  })
192
+})
193
+</script>
194
+<style lang="scss" scoped>
195
+.addTextSelect{
196
+  :deep(.el-select-dropdown__item){
197
+    padding: 0 10px;
198
+  }
199
+}
200
+.textBox{
201
+  color: #161E46;
202
+  border: 1px solid #d9d9d9;
203
+  height: 350px;
204
+  overflow-y: auto;
205
+  scrollbar-color: transparent transparent;
206
+  &::-webkit-scrollbar{
207
+    width: 2px;
208
+  }
209
+  &:deep(.el-textarea){
210
+    --el-input-border:none;
211
+    --el-input-border-color:none;
212
+    padding: 0 10px;
213
+  }
214
+  &:deep(.el-textarea__inner:hover){
215
+    box-shadow: none;
216
+  }
217
+  &:deep(.el-textarea__inner:focus){
218
+    box-shadow: none;
219
+  }
220
+  .titleBox{
221
+    background-color: #f5f5f5;
222
+    padding: 15px 20px;
223
+  }
224
+  .tips{
225
+    color: #999;
226
+    background-color: rgba(49, 115, 255, .1);
227
+    padding: 15px 20px;
228
+    font-size: 12px;
229
+  }
230
+}
231
+</style>

+ 31 - 0
src/components/businessMoudle/adAccountGroup/hooks/agency.ts

@@ -0,0 +1,31 @@
1
+import { ref } from "vue"
2
+import { ElMessage } from "element-plus";
3
+
4
+export const agencyExport = () => {
5
+  const EditDialogRef = ref()
6
+  const ImpoartDialogRef = ref()
7
+  const agencyEvent = (info) => {
8
+    if (!info?.id) {
9
+      ElMessage.error('账户组获取失败,无法导入账户!')
10
+      return
11
+    }
12
+    if (ImpoartDialogRef.value) {
13
+      ImpoartDialogRef.value.initFun(true, info)
14
+    }
15
+  }
16
+  const agencyEditEvent = (info) => {
17
+    if (!info?.account_id) {
18
+      ElMessage.error('账户获取失败,无法进行编辑!')
19
+      return
20
+    }
21
+    if (EditDialogRef.value) {
22
+      EditDialogRef.value.initFun(true, info)
23
+    }
24
+  }
25
+  return {
26
+    EditDialogRef,
27
+    ImpoartDialogRef,
28
+    agencyEvent,
29
+    agencyEditEvent
30
+  }
31
+}

+ 57 - 0
src/components/businessMoudle/adAccountGroup/hooks/api.ts

@@ -0,0 +1,57 @@
1
+import http from '@/http/http'
2
+import { ElMessage, ElMessageBox } from "element-plus";
3
+import {Api} from "@/api/api";
4
+
5
+/**巨量广告账户导入账户组 */
6
+interface IAccountImAdd {
7
+  group_id: number,
8
+  import_method: string,
9
+  type: string,
10
+  data_str: string,
11
+}
12
+export function accountImAddAxios(params: IAccountImAdd) {
13
+  return new Promise(async (resolve,reject)=>{
14
+    const res: any = await http.post(Api.oe_account_add_to_group, params)
15
+    if (res.errNo == 0) {
16
+      resolve(res.rst)
17
+    } else {
18
+      ElMessage.error(res.errMsg)
19
+      reject()
20
+    }
21
+  })
22
+}
23
+
24
+/**代理商子账户列表 */
25
+interface IAccountChildList {
26
+  agency_account_id: string,
27
+  keyword?: string
28
+}
29
+export function accountChildListAxios(params: IAccountChildList) {
30
+  return new Promise(async (resolve,reject)=>{
31
+    const res: any = await http.get('/api/account/agentChildList', params)
32
+    if (res.errNo == 0) {
33
+      resolve(res.rst)
34
+    } else {
35
+      ElMessage.error(res.errMsg)
36
+      reject()
37
+    }
38
+  })
39
+}
40
+
41
+/**账户设置参数 */
42
+interface IAccountSetParam {
43
+  account_id: string,
44
+  owner_id: string,
45
+  project_id?: string
46
+}
47
+export function accountSetParamAxios(params: IAccountSetParam) {
48
+  return new Promise(async (resolve,reject)=>{
49
+    const res: any = await http.post('/api/account/setParam', params)
50
+    if (res.errNo == 0) {
51
+      resolve(res.rst)
52
+    } else {
53
+      ElMessage.error(res.errMsg)
54
+      reject()
55
+    }
56
+  })
57
+}

+ 61 - 0
src/components/businessMoudle/adAccountGroup/hooks/dialog.ts

@@ -0,0 +1,61 @@
1
+import { reactive, ref } from "vue"
2
+import $http from '@/http/http'
3
+import to from 'await-to-js'
4
+import { Api as $api } from '@/api/api'
5
+import { ElMessage } from "element-plus"
6
+
7
+export const agencyDialogExport = () => {
8
+  const ownerIdRef = ref()
9
+  const projectIdRef = ref()
10
+  const importType = reactive<any>({
11
+    list: [
12
+      { id: 'part', name: '部分导入' },
13
+      // { id: 'all', name: '全部导入' }
14
+    ],
15
+    type: 'part'
16
+  })
17
+  const handType = reactive<any>({
18
+    list: [
19
+      { id: 1, name: '手动输入' },
20
+      // { id: 2, name: '手动选择' },
21
+    ],
22
+    type: 1
23
+  })
24
+  const userList = reactive<any>({
25
+    list:[],
26
+    active: ''
27
+  })
28
+  const projectList = reactive<any>({
29
+    list:[],
30
+    active: ''
31
+  })
32
+
33
+  /**获取人员列表 */
34
+  const getUserList = async () => {
35
+    const url = $api.user_list
36
+    const params = {}
37
+    const [err, res]: any = await to($http.get(url, params))
38
+    if (err || res?.errNo !== '0') return ElMessage.error(err?.message || res?.errMsg || "操作失败")
39
+    userList.list = [...res?.rst]
40
+  }
41
+
42
+  /**项目列表 */
43
+  const getProjectList = async () => {
44
+    const url = $api.project_list
45
+    const params = {}
46
+    const [err, res]: any = await to($http.get(url, params))
47
+    if (err || res?.errNo !== '0') return ElMessage.error(err?.message || res?.errMsg || "操作失败")
48
+    projectList.list = [...res?.rst]
49
+  }
50
+
51
+  return {
52
+    projectIdRef,
53
+    ownerIdRef,
54
+    importType,
55
+    handType,
56
+    userList,
57
+    projectList,
58
+    getProjectList,
59
+    getUserList
60
+  }
61
+}

+ 12 - 2
src/components/businessMoudle/adAccountGroup/index.vue

@@ -16,12 +16,14 @@
16 16
   >
17 17
     <template v-slot:operate="slotProps">
18 18
       <div class="text-center">
19
+        <span class="c-theme pointer f13 rMar7" @click="agencyEvent(slotProps.row)">导入账户</span>
19 20
         <span class="operate_text lMar8 pointer" @click="addEvent(slotProps.row)">编辑</span>
20 21
         <Popconfirm @confirm="deleEvent(slotProps.row)"/>
21 22
       </div>
22 23
     </template>
23 24
   </TableList>
24
-
25
+  <!-- 账号组导入广告账户 -->
26
+  <ImpoartDialog ref="ImpoartDialogRef" @close="init()"></ImpoartDialog>
25 27
   <!--  添加分组-->
26 28
   <AddGroup ref="AddGroupRef" @init="init"></AddGroup>
27 29
 </template>
@@ -36,6 +38,8 @@ import {Api} from "@/api/api";
36 38
 import {ElMessage} from "element-plus";
37 39
 import { publicTableTs } from '@/components/businessMoudle/tableInfo'
38 40
 import AddGroup from '@/components/businessMoudle/adAccountGroup/dialog/addGroup.vue'
41
+import { agencyExport } from './hooks/agency'
42
+import ImpoartDialog from './dialog/importDialog.vue'
39 43
 
40 44
 const { proxy } = getCurrentInstance() as any;
41 45
 
@@ -52,12 +56,18 @@ const descolParams = reactive([
52 56
 const { tableInfo,tableListRef,total } = publicTableTs(descolParams)
53 57
 
54 58
 const addEvent = (item?:any) => {
55
-  console.log(item)
56 59
   nextTick(()=>{
57 60
     AddGroupRef.value!.switchShow(true,item||'')
58 61
   })
59 62
 }
60 63
 
64
+const {
65
+  EditDialogRef,
66
+  ImpoartDialogRef,
67
+  agencyEvent,
68
+  agencyEditEvent
69
+} = agencyExport()
70
+
61 71
 const AddGroupRef = ref<{switchShow:(val:boolean,info?:any)=>void}>()
62 72
 
63 73
 const InputRef_text = ref<{value:string}>()

+ 2 - 2
src/components/businessMoudle/oeAdAccount/index.vue

@@ -54,9 +54,9 @@ const { proxy } = getCurrentInstance() as any;
54 54
 
55 55
 const typeList = reactive({
56 56
   list: [
57
-  {id:'ADVERTISER', name: '广告' },
57
+  {id:'ADVERTISER', name: '广告账号' },
58 58
   {id:'CUSTOMER_ADMIN', name: '纵横组织' },
59
-  {id:'UNCLAIMED', name: '仓库' },
59
+  {id:'UNCLAIMED', name: '待认领账号' },
60 60
 ],
61 61
   typeAc: 'CUSTOMER_ADMIN'
62 62
 })