Browse Source

巨量广告账户授权

houxiaohua 6 months ago
parent
commit
ff9cbb38fe
65 changed files with 895 additions and 51 deletions
  1. 1 1
      dist/assets/index.b57fbe5c.js
  2. 1 0
      dist/assets/index.79ed01e1.css
  3. 1 1
      dist/index.html
  4. 1 1
      dist/js/Home/index.3c966932.js
  5. 1 1
      dist/js/_dialog/_dialog.4182488b.js
  6. 1 1
      dist/js/_input/_input.b122b4de.js
  7. 1 1
      dist/js/_inputAppend/_inputAppend.4912cbea.js
  8. 1 1
      dist/js/_select/_select.98d8001b.js
  9. 1 1
      dist/js/acStatement/index.8441eb2f.js
  10. 1 1
      dist/js/adTask/index.7ed4fd79.js
  11. 1 1
      dist/js/adTask3/index.e6ec2f42.js
  12. 1 1
      dist/js/adqManage/index.09f61d05.js
  13. 1 1
      dist/js/adqManage3/index.777261bb.js
  14. 1 0
      dist/js/api/api.093710c7.js
  15. 1 1
      dist/js/api/api.fa03fe40.js
  16. 0 1
      dist/js/api/api.7120bcc0.js
  17. 1 1
      dist/js/api/api.a8d6676e.js
  18. 1 1
      dist/js/basisMoudle/error.124b4b28.js
  19. 1 0
      dist/js/basisMoudle/login.7f50ab7d.js
  20. 0 1
      dist/js/basisMoudle/login.de89a2f8.js
  21. 1 1
      dist/js/checkboxDefault/checkboxDefault.d6799fbc.js
  22. 1 1
      dist/js/collectClip/index.73c5dd79.js
  23. 1 1
      dist/js/commonList/commonList.7f46b1fc.js
  24. 1 1
      dist/js/configArea/index.56bc7814.js
  25. 1 1
      dist/js/configArea/index.f0ff73b6.js
  26. 1 1
      dist/js/define/define.3e8ac73f.js
  27. 1 1
      dist/js/gdtList/index.0e5d6f42.js
  28. 1 1
      dist/js/gdtList3/index.6f0169b4.js
  29. 1 1
      dist/js/index/index.61658e2f.js
  30. 1 1
      dist/js/index/index.9c7ab34a.js
  31. 1 1
      dist/js/index/index.62a4cb76.js
  32. 1 1
      dist/js/index/index.c5d8ece9.js
  33. 1 0
      dist/js/layout/index.80da5607.js
  34. 0 1
      dist/js/layout/index.e4c8f95b.js
  35. 1 1
      dist/js/layout/index_head.c6aed9e5.js
  36. 1 1
      dist/js/limitManage/index.b782beb4.js
  37. 1 1
      dist/js/materialBlock/materialBlock.c4534710.js
  38. 1 1
      dist/js/materialData/index.c8ba909b.js
  39. 1 1
      dist/js/materialLibrary/index.571ff55f.js
  40. 1 1
      dist/js/materialTs/materialTs.9212403d.js
  41. 1 1
      dist/js/memberManage/index.b4a5a835.js
  42. 1 1
      dist/js/menu/index.6fea089f.js
  43. 1 1
      dist/js/miniprogram/index.ffda084c.js
  44. 1 0
      dist/js/oeAdAccount/index.d2bff2a1.js
  45. 1 1
      dist/js/projectManage/index.bed875ea.js
  46. 1 1
      dist/js/radioGroup/radioGroup.451c50e3.js
  47. 1 1
      dist/js/tableInfo/tableInfo.d20d0843.js
  48. 1 1
      dist/js/tagBlock/tagBlock.53e52104.js
  49. 1 1
      dist/js/taskList/index.895fb0d1.js
  50. 1 1
      dist/js/teamManage/index.217a6adc.js
  51. 1 1
      dist/js/timeScreen/timeScreen.209cb6b4.js
  52. 1 1
      dist/js/warning/warning.31e5dd65.js
  53. 1 1
      dist/js/wechatPage/index.09dc6189.js
  54. 1 1
      dist/js/weekTime/weekTime.5bba9df7.js
  55. 1 1
      dist/js/weekTime/weekTime.552e63e3.js
  56. 3 0
      src/api/api.ts
  57. 157 0
      src/components/businessMoudle/oeAdAccount/agency/childList.vue
  58. 103 0
      src/components/businessMoudle/oeAdAccount/agency/editDialog.vue
  59. 167 0
      src/components/businessMoudle/oeAdAccount/agency/importDialog.vue
  60. 73 0
      src/components/businessMoudle/oeAdAccount/agency/manualInput.vue
  61. 31 0
      src/components/businessMoudle/oeAdAccount/hooks/agency.ts
  62. 58 0
      src/components/businessMoudle/oeAdAccount/hooks/api.ts
  63. 61 0
      src/components/businessMoudle/oeAdAccount/hooks/dialog.ts
  64. 180 0
      src/components/businessMoudle/oeAdAccount/index.vue
  65. 10 1
      src/router/index.ts

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


File diff suppressed because it is too large
+ 1 - 0
dist/assets/index.79ed01e1.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.b57fbe5c.js"></script>
15
+    <script type="module" crossorigin src="./assets/index.604e61a5.js"></script>
16 16
     <link rel="modulepreload" href="./js/@vue/@vue.5bfcce30.js">
17 17
     <link rel="modulepreload" href="./js/vue-router/vue-router.ccba075e.js">
18 18
     <link rel="modulepreload" href="./js/vue-demi/vue-demi.4f3c4c97.js">

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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


+ 3 - 0
src/api/api.ts

@@ -84,6 +84,9 @@ export enum Api{
84 84
     account_listToSelect = '/api/account/listToSelect',
85 85
     account_listNameToSelect = '/api/account/listNameToSelect',
86 86
 
87
+    // 巨量广告账户管理
88
+    oe_ad_account = '/api/oeAdAccount/lists',
89
+    oe_account_auth = '/oceanAuth/getUrl',
87 90
 
88 91
     //定向包
89 92
     directPacket_add = '/api/ad/targetingsAdd',

+ 157 - 0
src/components/businessMoudle/oeAdAccount/agency/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>

+ 103 - 0
src/components/businessMoudle/oeAdAccount/agency/editDialog.vue

@@ -0,0 +1,103 @@
1
+<template>
2
+  <el-dialog class="gdt-dialog" :close-on-click-modal="false" :destroy-on-close="true" v-model="visible" :title="`账户编辑(${account_id})`"
3
+    width="440px" :before-close="handleClose">
4
+    <div v-loading="loading" class="container">
5
+      <Select ref="ownerIdRef" title="所属人员"  class="block tMar20" selectWidth="260px" :haveTag="true"
6
+        :optObj="{ k: 'id', la: 'username', val: 'id' }" :options="userList.list" />
7
+      <Select ref="projectIdRef"  class="block tMar20" title="所属项目" selectWidth="260px" :optObj="{ k: 'id', la: 'name', val: 'id' }"
8
+        :options="projectList.list" />
9
+    </div>
10
+    <template #footer>
11
+      <div class="dialog-footer" style="text-align: right;padding:10px;padding-top: 0;">
12
+        <el-button size="default" @click="handleClose"> 取 消 </el-button>
13
+        <el-button size="default" type="primary" @click="submitEvent"> 确 认 </el-button>
14
+      </div>
15
+    </template>
16
+  </el-dialog>
17
+</template>
18
+<script setup lang="ts">
19
+import { nextTick, onBeforeMount, ref } from 'vue';
20
+import { agencyDialogExport } from '../hooks/dialog';
21
+import Select from '@/components/capsulationMoudle/_select.vue'
22
+import { accountSetParamAxios } from '../hooks/api';
23
+import { ElMessage } from 'element-plus';
24
+
25
+const emit = defineEmits<{
26
+  (event: "close", val?: any): void;
27
+}>();
28
+
29
+const loading = ref(false)
30
+const visible = ref(false)
31
+const account_id = ref('')
32
+const {
33
+  ownerIdRef,
34
+  projectIdRef,
35
+  userList,
36
+  projectList,
37
+  getUserList,
38
+  getProjectList,
39
+} = agencyDialogExport()
40
+
41
+const handleClose = ()=>{
42
+  visible.value = false
43
+}
44
+const submitEvent = () => {
45
+  if (account_id.value == '' || !account_id.value) {
46
+    ElMessage.warning('获取账户ID失败');
47
+    return
48
+  }
49
+  if (ownerIdRef.value?.value == '' || !ownerIdRef.value?.value) {
50
+    ElMessage.warning('请选择所属人员');
51
+    return
52
+  }
53
+  loading.value = true;
54
+  accountSetParamAxios({
55
+    account_id: account_id.value,
56
+    owner_id: ownerIdRef.value?.value,
57
+    project_id: projectIdRef.value?.value,
58
+  }).then((res)=>{
59
+    loading.value = false;
60
+    if(res){
61
+      ElMessage.warning('编辑成功')
62
+      visible.value = false
63
+      emit('close')
64
+    }
65
+  }).catch(()=>{
66
+    loading.value = false;
67
+  })
68
+}
69
+
70
+onBeforeMount(() => {
71
+  getUserList()
72
+  getProjectList()
73
+})
74
+
75
+/**初始化 */
76
+const initFun = async (flag, obj) => {
77
+  visible.value = flag
78
+  if (flag) {
79
+    account_id.value = obj.account_id
80
+    nextTick(()=>{
81
+      if(ownerIdRef.value && obj.owner_id){
82
+        ownerIdRef.value.value = obj.owner_id
83
+      }
84
+      if(projectIdRef.value && obj.project_id){
85
+        projectIdRef.value.value = obj.project_id
86
+      }
87
+    })
88
+  }
89
+}
90
+// 暴露自己的属性供父组件使用
91
+defineExpose({
92
+  initFun
93
+});
94
+</script>
95
+<style lang="scss" scoped>:deep(.spanTitle),
96
+.spanTitle {
97
+  font-size: 13px;
98
+  color: #666;
99
+  width: 70px !important;
100
+  text-align: right;
101
+  margin-right: 20px;
102
+}
103
+</style>

+ 167 - 0
src/components/businessMoudle/oeAdAccount/agency/importDialog.vue

@@ -0,0 +1,167 @@
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 " v-if="importType.type == 'part' && handType.type == 1">请确保输入的广告主账户已属于对应的代理商,否则会导致失败;单次授权账户上限{{ agencyCount }}个,如账户数量较多,请分批次输入</span>
19
+        <span class="flex_1 " v-if="importType.type == 'part' && handType.type == 2">该代理商账户下共{{acc_count}}个媒体账户,请选择想要导入的账户名称</span>
20
+        <span class="flex_1 " v-if="importType.type == 'all'">该代理商账户下共{{acc_count}}个媒体账户</span>
21
+      </div>
22
+
23
+      <!-- S 导入媒体账户 附加条件 -->
24
+      <div class="flex tMar15">
25
+        <Select ref="ownerIdRef" title="所属人员" selectWidth="160px" :haveTag="true"
26
+          :optObj="{ k: 'id', la: 'username', val: 'id' }" :options="userList.list" />
27
+        <Select ref="projectIdRef" title="所属项目" selectWidth="160px" :optObj="{ k: 'id', la: 'name', val: 'id' }"
28
+          :options="projectList.list" />
29
+      </div>
30
+      <!-- E 导入媒体账户 附加条件 -->
31
+
32
+      <!-- 手动输入 -->
33
+      <ManualInput v-show="importType.type == 'part' && handType.type == 1" :maxRow="agencyCount" @mInput="getMInput"></ManualInput>
34
+
35
+      <!-- 列表选择或者全部导入 -->
36
+      <ChildList ref="ChildListRef" v-show="importType.type == 'part' && handType.type == 2 || importType.type == 'all'" :agencyItem="agencyItem" :importType="importType.type" :handType="handType.type" @total="getCountAcc"></ChildList>
37
+    </div>
38
+    <template #footer>
39
+      <div class="dialog-footer" style="text-align: right;padding:10px;padding-top: 0;">
40
+        <el-button size="default" @click="handleClose"> 取 消 </el-button>
41
+        <el-button size="default" type="primary" @click="submitEvent"> 确 认 </el-button>
42
+      </div>
43
+    </template>
44
+  </el-dialog>
45
+</template>
46
+<script setup lang="ts">
47
+import { Search } from '@element-plus/icons-vue'
48
+import Select from '@/components/capsulationMoudle/_select.vue'
49
+import { getPromotedObjectType } from '@/components/businessMoudle/batchGdt/configArea/basicInfo/ts/basicApi'
50
+import { nextTick, onBeforeMount, reactive, ref, watch } from 'vue';
51
+import { ElMessage } from 'element-plus';
52
+import _ from 'lodash';
53
+import { agencyDialogExport } from '../hooks/dialog'
54
+import ChildList from './childList.vue'
55
+import ManualInput from './manualInput.vue'
56
+import { accountImAddAxios } from '../hooks/api'
57
+
58
+const emit = defineEmits<{
59
+  (event: "close", val?: any): void;
60
+}>();
61
+const loading = ref(false)
62
+const agencyCount = 300
63
+const agencyItem = ref<any>('')
64
+const inputValue = ref('')
65
+const visible = ref(false)
66
+const acc_count = ref(0)
67
+const ChildListRef = ref()
68
+
69
+const {
70
+  ownerIdRef,
71
+  projectIdRef,
72
+  importType,
73
+  handType,
74
+  userList,
75
+  projectList,
76
+  getUserList,
77
+  getProjectList,
78
+} = agencyDialogExport()
79
+
80
+onBeforeMount(() => {
81
+  getUserList()
82
+  getProjectList()
83
+})
84
+
85
+/**点击关闭弹框 */
86
+const handleClose = () => {
87
+  visible.value = false
88
+}
89
+const getCountAcc = (val) =>{
90
+  acc_count.value = val
91
+}
92
+const getMInput = (val)=>{
93
+  inputValue.value = val
94
+}
95
+
96
+/**点击确定 */
97
+const submitEvent = async () => {
98
+  if (ownerIdRef.value?.value == '' || !ownerIdRef.value?.value) {
99
+    ElMessage.warning('请选择所属人员');
100
+    return
101
+  }
102
+  let data_str = '';
103
+  if(importType.type == 'part' && handType.type == 1){
104
+    data_str = inputValue.value
105
+  }else{
106
+    if(ChildListRef.value){
107
+      await ChildListRef.value.getMultipleList().then((res)=>{
108
+        data_str = JSON.stringify(res)
109
+      })
110
+    }
111
+  }
112
+  if(data_str == ''){
113
+    ElMessage.warning('请输入账户ID或手动选择媒体账户!');
114
+    return
115
+  }
116
+  loading.value = true
117
+  accountImAddAxios({
118
+    agency_account_id: agencyItem.value.agency_account_id,
119
+    import_method: importType.type,
120
+    type: handType.type,
121
+    data_str,
122
+    owner_id: ownerIdRef.value?.value,
123
+    project_id: projectIdRef.value?.value,
124
+  }).then((res) => {
125
+    loading.value = false
126
+    if(res){
127
+      ElMessage.warning('导入成功')
128
+      visible.value = false
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
+    console.log(obj)
140
+    agencyItem.value = obj
141
+  }
142
+}
143
+// 暴露自己的属性供父组件使用
144
+defineExpose({
145
+  initFun
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
+}
167
+</style>

+ 73 - 0
src/components/businessMoudle/oeAdAccount/agency/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>

+ 31 - 0
src/components/businessMoudle/oeAdAccount/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?.agency_account_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
+}

+ 58 - 0
src/components/businessMoudle/oeAdAccount/hooks/api.ts

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

+ 61 - 0
src/components/businessMoudle/oeAdAccount/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
+}

+ 180 - 0
src/components/businessMoudle/oeAdAccount/index.vue

@@ -0,0 +1,180 @@
1
+<template>
2
+  <!--  类型切换 -->
3
+  <div class="typeBorlineBox flex_between">
4
+    <div class="flex" style="margin-left: 15px">
5
+      <div class="item" v-for="item in typeList.list" :key="item.id" :class="item.id == typeList.typeAc ? 'itemAc' : ''" @click="switchTypeItem(item)">
6
+      <div>{{item.name}}</div>
7
+      <div class="borLine"></div>
8
+    </div>
9
+    </div>
10
+    <el-button type="primary" size="default" class="rMar15" @click="authEvent()">账号授权</el-button>
11
+  </div>
12
+
13
+  <div class="screenBox flex" style="padding: 15px;s" v-loading="authLoading">
14
+    <Input ref="InputRef_text" title="关键词" placeholderTxt="关键词" @changeEvent="init()" @clearEvent="init()" />
15
+    <!-- <Select ref="ideaManRef" :clearFlag="true" title="所属人员" selectWidth="160px" :optObj="{ k: 'id', la: 'username', val: 'id' }"
16
+      @changeEvent="init()" @clearEvent="init()" :options="pageInfo.createrList" /> -->
17
+    <!-- <Select ref="ctypeRef" :clearFlag="true" title="类型" selectWidth="160px" @changeEvent="init()" @clearEvent="init()"
18
+      :options="pageInfo.getTypeList" /> -->
19
+  </div>
20
+
21
+  <!--  列表-->
22
+  <TableList ref="tableListRef" :tableData="tableInfo.tableList" immobilizationHeight="calc(100vh - 260px)" :descol="tableInfo.descolList" :total="total"
23
+    @init="init">
24
+    <template v-slot:operate="slotProps">
25
+      <div class="text-center">
26
+        <span class="c-theme pointer f13" @click="agencyEditEvent(slotProps.row)">编辑</span>
27
+        <Popconfirm @confirm="deleEvent(slotProps.row)" />
28
+      </div>
29
+    </template>
30
+  </TableList>
31
+  <!-- 代理商导入媒体账户 -->
32
+  <ImpoartDialog ref="ImpoartDialogRef" @close="init(1)"></ImpoartDialog>
33
+  <!-- 账户设置参数 -->
34
+  <EditDialog ref="EditDialogRef" @close="editClose"></EditDialog>
35
+</template>
36
+<script setup lang="ts">
37
+import Select from '@/components/capsulationMoudle/_select.vue'
38
+import { nextTick, onMounted, reactive, ref, getCurrentInstance } from 'vue'
39
+import Popconfirm from '@/components/capsulationMoudle/_popconfirm.vue'
40
+import TableList from '@/components/capsulationMoudle/tableList.vue'
41
+import Input from '@/components/capsulationMoudle/_input.vue'
42
+import { adqParam, reactiveTableAndAny } from "@/api/ApiModel";
43
+import { Api } from "@/api/api";
44
+import { ElMessage } from "element-plus";
45
+import { publicTableTs } from '@/components/businessMoudle/tableInfo'
46
+import ImpoartDialog from './agency/importDialog.vue'
47
+import EditDialog from './agency/editDialog.vue'
48
+import { agencyExport } from './hooks/agency'
49
+import { useRoute, useRouter } from 'vue-router'
50
+const route = useRoute();
51
+const router = useRouter();
52
+
53
+const { proxy } = getCurrentInstance() as any;
54
+
55
+const typeList = reactive({
56
+  list: [
57
+  {id:'ACCOUNT_ROLE_TYPE_ADVERTISER', name: '广告主' },
58
+  // {id:'ACCOUNT_ROLE_TYPE_AGENCY', name: '代理商' },
59
+],
60
+typeAc: 'ACCOUNT_ROLE_TYPE_ADVERTISER'
61
+})
62
+const switchTypeItem = (info)=>{
63
+  typeList.typeAc = info.id
64
+  init(1)
65
+}
66
+
67
+const {
68
+  EditDialogRef,
69
+  ImpoartDialogRef,
70
+  agencyEvent,
71
+  agencyEditEvent
72
+} = agencyExport()
73
+
74
+// 表格数据公共ts
75
+const descolParams = reactive([
76
+  { name: '账号名称', column: 'advertiser_name', minWidth: '120px'},
77
+  { name: '账号ID', column: 'advertiser_id', cancleForMat: true },
78
+  // { name: '授权状态', column: 'is_valid', },
79
+  // { name: '所属人员', column: 'owner_name', },
80
+  { name: '创建时间', column: 'created_at', minWidth: '100px'},
81
+  // { name: '操作', column: 'operate', slotFlag: true },
82
+])
83
+const { tableInfo, tableListRef, total } = publicTableTs(descolParams)
84
+
85
+
86
+const pageInfo = reactive<reactiveTableAndAny>({
87
+  getTypeList: [
88
+    { label: '微信MP', value: 1 },
89
+    { label: '广点通', value: 2 },
90
+  ],
91
+  createrList: [],
92
+})
93
+
94
+
95
+const authLoading = ref<boolean>(false)
96
+const authEvent = async () => {
97
+  authLoading.value = true
98
+  let res: any = await proxy.$http.get(Api.oe_account_auth)
99
+  authLoading.value = false
100
+  if (res && res.errNo == '0') {
101
+    window.open(res.rst, '_blank')
102
+  } else {
103
+    ElMessage.error(res.errMsg)
104
+  }
105
+}
106
+
107
+const InputRef_text = ref<{ value: string }>()
108
+const ideaManRef = ref<{ value: string | number }>()
109
+const ctypeRef = ref<{ value: string | number }>()
110
+//账号列表
111
+const init = async (page?: any, pageSize?: any) => {
112
+  tableListRef.value!.loading = true
113
+  const paramsModel = reactive<adqParam>({
114
+    keyword: InputRef_text.value!.value,
115
+    page: page ? page : 1,
116
+    page_size: pageSize ? pageSize : 20,
117
+  })
118
+  let res: any = await proxy.$http.get(Api.oe_ad_account, paramsModel)
119
+  tableListRef.value!.loading = false
120
+  if (res && res.errNo == '0') {
121
+    tableInfo.tableList = res.rst.data
122
+    total.value = res.rst.pageInfo.total
123
+  } else {
124
+    ElMessage.error(res.errMsg)
125
+  }
126
+}
127
+
128
+const deleEvent = async (item: any) => {
129
+  tableListRef.value!.loading = true
130
+  const paramsModel = reactive<adqParam>({
131
+    account_id: item.account_id
132
+  })
133
+  let res: any = await proxy.$http.post(Api.adq_dele, paramsModel)
134
+  tableListRef.value!.loading = false
135
+  ElMessage.info(res.errMsg)
136
+  if (res && res.errNo == '0') {
137
+    await init()
138
+  }
139
+}
140
+
141
+//创意师
142
+const init_createrList = async () => {
143
+  let res: any = await proxy.$http.get(Api.account_list)
144
+  if (res && res.errNo == '0') {
145
+    pageInfo.createrList = res.rst
146
+  } else {
147
+    ElMessage.error(res.errMsg)
148
+  }
149
+}
150
+
151
+const editClose = () => {
152
+  if(route.query?.account_id){
153
+    router.replace('/adqManage')
154
+  }
155
+  init(1)
156
+}
157
+
158
+onMounted(async () => {
159
+  if(route.query?.account_id){
160
+    agencyEditEvent({'account_id': route.query?.account_id})
161
+  }
162
+  await init()
163
+  await init_createrList()
164
+})
165
+</script>
166
+<style lang="scss" scoped>
167
+.dialogBox {
168
+  :deep(.el-input__wrapper) {
169
+    background: #F9F9F9;
170
+    border-radius: 5px;
171
+    border: 1px solid #F1F1F1;
172
+    height: 45px;
173
+    box-shadow: none;
174
+  }
175
+}
176
+
177
+.screenArea {
178
+  margin-bottom: 8px;
179
+}
180
+</style>

+ 10 - 1
src/router/index.ts

@@ -30,6 +30,7 @@ const adTask = () => import('@/components/businessMoudle/adTask/index.vue')
30 30
 const adTask3 = () => import('@/components/businessMoudle/adTask3/index.vue')
31 31
 const menuList = () => import('@/components/businessMoudle/menu/index.vue')
32 32
 const document = () => import('@/components/document/index.vue')
33
+const oeAdAccount = () => import('@/components/businessMoudle/oeAdAccount/index.vue')
33 34
 
34 35
 //数据报表
35 36
 const acStatement = () => import('@/components/businessMoudle/dataManagement/acStatement/index.vue')
@@ -250,7 +251,15 @@ const constantRoutes: Array<RouteRecordRaw> = [
250 251
         meta: {
251 252
           title: '素材报表'
252 253
         }
253
-      }
254
+      },
255
+      {
256
+        path: '/oeAdAccount',
257
+        component: oeAdAccount,
258
+        name: 'oeAdAccount',
259
+        meta: {
260
+          title: '广告账户管理'
261
+        }
262
+      },
254 263
     ],
255 264
   },
256 265
 ]