猎羽广告

account.vue 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. <template>
  2. <div>
  3. <div class="screenBox_mini">
  4. <Input ref="InputRef_text" title="关键词" placeholderTxt="关键词" @changeEvent="()=>init()" @clearEvent="()=>init()"/>
  5. <Select ref="acRef"
  6. title="账号"
  7. selectWidth="160px"
  8. @changeEvent="()=>init()" @clearEvent="()=>init()"
  9. :isMultiple="true"
  10. :optObj="{k:'account_id',la:'account_id',val:'account_id'}"
  11. :options="pageInfo.acList"/>
  12. <Select ref="statusRef"
  13. title="状态"
  14. selectWidth="160px"
  15. @changeEvent="()=>init()" @clearEvent="()=>init()"
  16. :options="pageInfo.statusList"/>
  17. <TimeScreen title="时间" selectWidth="260px" :haveQuick="false" :clearFlag="true" :valueIsKong="true"
  18. ref="timeRef"
  19. @init="()=>init()"></TimeScreen>
  20. <span class="pointer c-theme lMar10" @click="clearEvent">清空</span>
  21. <el-button class="lMarauto" type="primary" @click="goNewPlanEvent">新建计划</el-button>
  22. </div>
  23. <div>
  24. <div class="bMar10 flex">
  25. <Dropdown title="批量操作" :list="tableInfo.moreList" @close="dropdownEvent" class="rMar10"
  26. :disabledFlag="tableInfo.multipleSelection&&tableInfo.multipleSelection.length == 0"></Dropdown>
  27. <div>已选 : <span>{{tableInfo.multipleSelection&&tableInfo.multipleSelection.length}}</span></div>
  28. <!-- <el-button class="lMarauto" type="primary" @click="customIndEvent">自定义指标</el-button>-->
  29. <div class="lMarauto">
  30. <Indicators type="media_base" @refresh="IndicatorsRefreshList"></Indicators>
  31. </div>
  32. </div>
  33. 我是账户列表
  34. <el-table v-loading="loading" ref="tableRef" :data="tableInfo.tableList"
  35. :header-cell-style="tableHeaderStyle"
  36. :key="tableInfo.updateKey" style="width: 100%"
  37. border empty-text="暂无数据"
  38. row-key="campaign_id"
  39. max-height="calc(100vh - 294px)">
  40. <el-table-column fixed width="80" >
  41. <template #header>
  42. <div class="flex">
  43. <el-checkbox v-model="tableInfo.chooseAll" @change="allChooseCheckboxEvent"></el-checkbox>
  44. <el-dropdown class="lMar10" @command="handleCommandChoosePage">
  45. <el-icon color="#3173FF"><i-ep-ArrowDownBold /></el-icon>
  46. <template #dropdown>
  47. <el-dropdown-menu>
  48. <el-dropdown-item command="1">当前页</el-dropdown-item>
  49. <el-dropdown-item command="2">全部</el-dropdown-item>
  50. </el-dropdown-menu>
  51. </template>
  52. </el-dropdown>
  53. </div>
  54. </template>
  55. <template #default="scope">
  56. <div class="checkBoxSelf flex"
  57. @click="singleChooseCheckboxEvent(tableInfo.multipleSelection.findIndex(n=>n.campaign_id == scope.row.campaign_id),scope.row)"
  58. :class="tableInfo.multipleSelection.findIndex(n=>n.campaign_id == scope.row.campaign_id)>=0 ? 'active' : ''">
  59. <el-icon color="#fff" v-if="tableInfo.multipleSelection.findIndex(n=>n.campaign_id == scope.row.campaign_id)>=0"><i-ep-Check /></el-icon>
  60. </div>
  61. </template>
  62. </el-table-column>
  63. <template v-for="item in tableInfo.descol">
  64. <el-table-column :fixed="item.isfixed" :min-width="item.minWidth ? item.minWidth : '80px'">
  65. <template #header>
  66. <div class="flex"
  67. :style="{ justifyContent: item.alignSelf ? item.alignSelf : 'center' }"
  68. :class="[tableInfo.sortKey == item.column ? 'active_css' : '',item.isSort ? 'pointer' : '']"
  69. @click="item.isSort&&sortEvent(item.column)">
  70. {{ item.name }}
  71. <el-tooltip v-if="item.notes" effect="dark" :content="item.notes"><i-ep-QuestionFilled class="lMar5 c-999 f14 pointer" /></el-tooltip>
  72. <div v-if="item.isSort">
  73. <div class="sortItem"><el-icon :color="tableInfo.sortKey == item.column ? '#3173FF' : ''"><i-ep-CaretBottom /></el-icon></div>
  74. </div>
  75. </div>
  76. </template>
  77. <template #default="scope">
  78. <div class="flex" :style="{ justifyContent: item.alignSelf ? item.alignSelf : 'center' }">
  79. <div v-if="item.column == 'campaign_name'">
  80. <span class="c-theme flex campaignName">
  81. <span class="pointer" @click="goAdvertEvent(scope.row.campaign_id)">{{scope.row[item.column]}}</span>
  82. <el-icon color="#3173FF" class="pointer lMarauto f16 icon" @click="edit_campaign_name_event(scope.row)"><i-ep-Edit /></el-icon>
  83. </span>
  84. </div>
  85. <div v-else-if="item.column == 'configured_status'">
  86. <span class="c-green" v-if="scope.row[item.column] == 'AD_STATUS_NORMAL'">正常</span>
  87. <span class="c-red" v-else-if="scope.row[item.column] == 'AD_STATUS_SUSPEND'">暂停</span>
  88. <span v-else>-</span>
  89. </div>
  90. <div v-else-if="item.column == 'speed_mode'">
  91. <span v-if="scope.row[item.column] == 'SPEED_MODE_STANDARD'">标准投</span>
  92. <span v-else-if="scope.row[item.column] == 'SPEED_MODE_FAST'">加速投放</span>
  93. <span v-else>-</span>
  94. </div>
  95. <div v-else-if="item.column == 'operate'">
  96. <div class="flex">
  97. <span class="c-theme pointer" @click="editPlanEvent(scope.row)">修改</span>
  98. <span class="lMar10"
  99. :class="scope.row.configured_status == 'AD_STATUS_NORMAL' ? 'pointer-drop c-green-opa' : 'pointer c-green'"
  100. @click="scope.row.configured_status == 'AD_STATUS_SUSPEND'&&batchPlanEvent(scope.row,1)">启用</span>
  101. </div>
  102. <div>
  103. <span :class="scope.row.configured_status == 'AD_STATUS_SUSPEND' ? 'pointer-drop c-red-opa' : 'pointer c-red'"
  104. @click="scope.row.configured_status == 'AD_STATUS_NORMAL'&&batchPlanEvent(scope.row,2)">暂停</span>
  105. <Popconfirm key="dele" @confirm="batchPlanEvent(scope.row,3)" :slotFlag="true">
  106. <template #con>
  107. <span class="pointer lMar10">删除</span>
  108. </template>
  109. </Popconfirm>
  110. </div>
  111. </div>
  112. <div class="flex c-theme pointer" v-else-if="item.column == 'daily_budget'" @click="editPlanEvent(scope.row)">
  113. {{scope.row[item.column] ? NumberHandle(scope.row[item.column]) : '不限'}}
  114. </div>
  115. <div class="cellDiv" :class="tableInfo.sortKey == item.column ? 'active_css' : ''" v-else>
  116. <el-tooltip :disabled="!(scope.row[item.column] && scope.row[item.column].length >30)" effect="dark" :content="scope.row[item.column]+''">
  117. <div class="clampTwo line21" style="flex: 1">
  118. {{ scope.row[item.column] || scope.row[item.column]==0 ?
  119. (item.cancleForMat ? (scope.row[item.column] ? scope.row[item.column] : '-') : NumberHandle(scope.row[item.column])) : '-'}}
  120. <span v-if="item.hasPercent&&(scope.row[item.column] || scope.row[item.column] ==0)">%</span>
  121. </div>
  122. </el-tooltip>
  123. </div>
  124. </div>
  125. </template>
  126. </el-table-column>
  127. </template>
  128. </el-table>
  129. <div class="paginationBox flex" style="justify-content: center" v-if="Number(tableInfo.total) > 0">
  130. <el-pagination
  131. v-model:currentPage="tableInfo.currentPage"
  132. v-model:page-size="tableInfo.pageSize"
  133. background
  134. :total="tableInfo.total"
  135. @current-change="handleCurrentChange" />
  136. </div>
  137. </div>
  138. <EditIpt ref="planEditIptRef" title="推广计划" @confirm="planEditConfirm"></EditIpt>
  139. <TargetEdit ref="TargetEditRef" title="计划设置" @confirm="init"></TargetEdit>
  140. </div>
  141. </template>
  142. <script setup lang="ts">
  143. import {getCurrentInstance, nextTick, onMounted, reactive, ref} from "vue";
  144. import Select from '@/components/capsulationMoudle/_select.vue'
  145. import TimeScreen from '@/components/capsulationMoudle/timeScreen.vue'
  146. import Input from '@/components/capsulationMoudle/_input.vue'
  147. import EditIpt from '@/components/businessMoudle/gdtList/dialog/editIpt.vue'
  148. import TargetEdit from '@/components/businessMoudle/gdtList/dialog/target.vue'
  149. import Dropdown from '@/components/capsulationMoudle/_dropdown.vue'
  150. import Popconfirm from '@/components/capsulationMoudle/_popconfirm.vue'
  151. import noData from '@/components/capsulationMoudle/noData.vue'
  152. import {listTs} from "@/components/businessMoudle/gdtList/ts/list";
  153. import {Api} from "@/api/api";
  154. import {ElMessage} from "element-plus";
  155. import {batchGdt_edit, batchGdt_list, reactiveTableAndAny} from "@/api/ApiModel";
  156. import Indicators from './indicators/index.vue'
  157. const { proxy } = getCurrentInstance() as any;
  158. // 全局方法定义
  159. const NumberHandle = proxy.$NumberHandle
  160. const emit = defineEmits<{
  161. (event: "goNewPlan"): void;
  162. (event: "goAdvert",campaign_id:any): void;
  163. }>();
  164. const goNewPlanEvent = () => {
  165. emit('goNewPlan')
  166. }
  167. const goAdvertEvent = (campaign_id:any) => {
  168. emit('goAdvert',campaign_id)
  169. }
  170. const loading = ref<boolean>(false)
  171. const tableInfo = reactive<reactiveTableAndAny>({
  172. tableList:[],
  173. tableList_all:[],
  174. descol:[
  175. { name:'计划名称',column:'campaign_name',slotFlag: true,isfixed:true,alignSelf:'left'},
  176. { name:'操作',column:'operate',slotFlag: true,isfixed:true},
  177. { name:'账号ID',column:'account_id',cancleForMat:true},
  178. { name:'计划ID',column:'campaign_id',cancleForMat:true},
  179. { name:'计划类型',column:'campaign_type'},
  180. { name:'推广目标类型',column:'promoted_object_type'},
  181. { name:'日预算(元)',column:'daily_budget',slotFlag: true},
  182. // { name:'总预算',column:'total_budget'},
  183. { name:'投放日期',column:'created_time'},
  184. { name:'客户状态',column:'configured_status',slotFlag: true},
  185. { name:'投放速度',column:'speed_mode',slotFlag: true},
  186. ],
  187. multipleSelection:[],
  188. updateKey:1,
  189. chooseAll:false,
  190. sortKey:'',
  191. moreList:[
  192. {value:'1',label:'启用'},
  193. {value:'2',label:'暂停'},
  194. {value:'3',label:'删除'},
  195. ],
  196. currentPage:1,
  197. pageSize:20,
  198. total:0,
  199. totalPages:0,//共多少页
  200. })
  201. //批量操作
  202. const batchEvent = () => {
  203. }
  204. // 启用 暂停 删除
  205. const batchPlanApi = async (arr?:any,val?:any) => {
  206. const paramsModel = reactive<batchGdt_edit>({
  207. campaign_infos:JSON.stringify(arr),
  208. flag:val?val:0
  209. })
  210. let res:any = await proxy.$http.post(Api.batchGdt_plan_batch_edit,paramsModel)
  211. ElMessage.info(res.errMsg)
  212. if(res&&res.errNo=='0'){
  213. init()
  214. tableInfo.multipleSelection = []
  215. }else{
  216. loading.value = false
  217. }
  218. }
  219. const batchPlanEvent = async (row?:any,val?:any) => {
  220. loading.value = true
  221. let arr:any = []
  222. arr.push({
  223. account_id:row.account_id,
  224. campaign_id:row.campaign_id
  225. })
  226. batchPlanApi(arr,val)
  227. }
  228. const dropdownEvent = (val: string | number | object) => {
  229. loading.value = true
  230. let arr:any = []
  231. tableInfo.multipleSelection.forEach(item=>{
  232. arr.push({
  233. account_id:item.account_id,
  234. campaign_id:item.campaign_id
  235. })
  236. })
  237. batchPlanApi(arr,val)
  238. }
  239. //修改计划
  240. const editPlanEvent = (row:any) => {
  241. nextTick(()=>{
  242. TargetEditRef.value!.switchShow(true,row)
  243. })
  244. }
  245. //修改计划名称
  246. const edit_campaign_name_event = (row:any) => {
  247. nextTick(()=>{
  248. planEditIptRef.value!.switchShow(true,row.campaign_name)
  249. })
  250. }
  251. //推广计划 - 确定
  252. const planEditConfirm = () => {
  253. }
  254. //排序
  255. const sortEvent = (row:any) => {
  256. }
  257. //列表
  258. const init = async (page?:any,totalPages?:any) => {
  259. loading.value = true
  260. const paramsModel = reactive<batchGdt_list>({
  261. account_ids:acRef.value!.value,
  262. keyword:InputRef_text.value!.value,
  263. status:statusRef.value!.value,
  264. start:timeRef.value!.dateVal&&timeRef.value!.dateVal[0],
  265. end:timeRef.value!.dateVal&&timeRef.value!.dateVal[1],
  266. page:page?page:1,
  267. pageSize:totalPages ? totalPages : tableInfo.pageSize
  268. })
  269. let res:any = await proxy.$http.get(Api.batchGdt_plan_list,paramsModel)
  270. loading.value = false
  271. if(res&&res.errNo=='0'){
  272. if(totalPages){
  273. tableInfo.tableList_all = res.rst.data
  274. }else{
  275. tableInfo.tableList = res.rst.data
  276. tableInfo.total = res.rst.pageInfo.total
  277. tableInfo.totalPages = res.rst.pageInfo.total
  278. }
  279. }else{
  280. ElMessage.error(res.errMsg)
  281. }
  282. }
  283. //分页
  284. const handleCurrentChange = (val) => {
  285. tableInfo.currentPage = val
  286. init(val)
  287. }
  288. //清空值
  289. const clearChooseVal = ()=>{
  290. tableInfo.chooseAll = false
  291. tableInfo.multipleSelection = []
  292. }
  293. //添加值
  294. const multipleSelection_add = (item?:any) => {
  295. let idx:number = tableInfo.multipleSelection.findIndex(n=>n.campaign_id == item.campaign_id)
  296. if(idx<0){
  297. tableInfo.multipleSelection.push(item)
  298. }
  299. }
  300. //删除值
  301. const multipleSelection_splice = (item?:any) => {
  302. let idx:number = tableInfo.multipleSelection.findIndex(n=>n.campaign_id == item.campaign_id)
  303. if(idx>=0){
  304. tableInfo.multipleSelection.splice(idx,1)
  305. }
  306. }
  307. const handleCommandChoosePage = async (command: string | number | object)=>{
  308. let arr:any = tableInfo.tableList
  309. clearChooseVal()
  310. tableInfo.chooseAll = true
  311. if(command == 2){ // 全部
  312. await init(1,tableInfo.totalPages)
  313. arr = tableInfo.tableList_all
  314. }
  315. arr.forEach(item=>{
  316. multipleSelection_add(item)
  317. })
  318. }
  319. //全选
  320. const allChooseCheckboxEvent = (val:string | number | boolean)=>{
  321. tableInfo.tableList.forEach(item=>{
  322. if(val){
  323. multipleSelection_add(item)
  324. }else{
  325. tableInfo.multipleSelection = []
  326. }
  327. })
  328. }
  329. //单选
  330. const singleChooseCheckboxEvent = (idx:number,row:any)=>{
  331. if(idx==-1){
  332. tableInfo.multipleSelection.push(row)
  333. }else{
  334. tableInfo.multipleSelection.splice(idx,1)
  335. tableInfo.chooseAll = false
  336. }
  337. }
  338. const IndicatorsRefreshList = () => {
  339. //这里刷新列表
  340. }
  341. const {
  342. init_acList,
  343. pageInfo,
  344. timeRef,
  345. acRef,
  346. statusRef,
  347. InputRef_text,
  348. clearEvent,
  349. tableHeaderStyle,
  350. planEditIptRef,
  351. TargetEditRef,
  352. customIndEvent
  353. } = listTs()
  354. onMounted(()=>{
  355. nextTick(async ()=>{
  356. await init_acList()
  357. await init()
  358. })
  359. })
  360. </script>
  361. <style lang="scss" scoped>
  362. .campaignName{
  363. .icon{
  364. color: #3173FF;
  365. opacity: 0;
  366. }
  367. &:hover{
  368. .icon{
  369. opacity: 1;
  370. }
  371. }
  372. }
  373. .checkBoxSelf{
  374. width: 13px;
  375. height: 13px;
  376. border: 1px solid #d9d9d9;
  377. border-radius: 2px;
  378. &:hover{
  379. cursor: pointer;
  380. border: 1px solid #3173FF;
  381. }
  382. &.active{
  383. border: 1px solid #3173FF;
  384. background-color: #3173FF;
  385. }
  386. }
  387. </style>