accelerateExplorationList.vue 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759
  1. <template>
  2. <div class="toutiaoBatch">
  3. <div class="toolbox-automate-rules-create-content_title">
  4. <h3>加速探索列表</h3>
  5. <!-- <a-button type='primary' @click="goNewConfigInfo" class="goNewConfigInfo">新建配置信息</a-button> -->
  6. </div>
  7. <div class="topOptions">
  8. <div >
  9. <Treeselect :appId.sync="accountId" :multiple="false" request="2,4" ref="treeSelect" style="margin-bottom:8px;width:600px " />
  10. </div>
  11. <span class="optionBtn">
  12. <a-button type='primary' @click="search" class="searchBtn">查询</a-button>
  13. </span>
  14. </div>
  15. <div class="tableArea">
  16. <!-- <div class="tableOption" v-if="selectedRowKeys.length">
  17. :row-selection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange }"
  18. </div> -->
  19. <div class="table">
  20. <a-table
  21. :columns="columns"
  22. :data-source="data"
  23. bordered
  24. :pagination="ipagination"
  25. :loading="loading"
  26. @change="sort"
  27. :scroll="{'x':scrollX}"
  28. >
  29. <span slot="status" slot-scope="text,record">
  30. <a-spin :spinning="record.spin" size="small" >
  31. <div class="spin-content">
  32. <a-switch size="default" :checked='text==1' @change="switchChange(text,record)"/>
  33. </div>
  34. </a-spin>
  35. </span>
  36. <span slot="openProgramCreate" slot-scope="text,record">
  37. <a-spin :spinning="record.openProgramCreateSpin" size="small" >
  38. <div class="spin-content">
  39. <a-switch size="default" :checked='text==1' @change="openProgramCreateSwitchChange(text,record)"/>
  40. </div>
  41. </a-spin>
  42. </span>
  43. <span slot="cpaBid" slot-scope="text">
  44. {{text/1000}}
  45. </span>
  46. <span slot="authName" slot-scope="text">
  47. <!-- <a href="javascript:;" >{{text}}</a> -->
  48. {{text || '-'}}
  49. </span>
  50. <span slot="time" slot-scope="text,record">
  51. {{record.startTime}}至{{record.endTime}}
  52. </span>
  53. <span slot="operator" slot-scope="text,record">
  54. <a href="javascript:;" @click="goPlanList(record)">编辑</a>
  55. <a-divider type="vertical" />
  56. <a href="javascript:;" @click="deleteRecord(record)">删除</a>
  57. <a-divider type="vertical" />
  58. <a-popover v-model="record.show" trigger="click" placement="topRight" @visibleChange='visibleChange'>
  59. <div slot="content">
  60. <span style='font-weight:700;margin-right:15px;font-size:15px'>修改后重提</span>
  61. <a-radio-group v-model="examineAgainType" >
  62. <a-radio :value="1">修改广告语</a-radio>
  63. <a-radio :value="0">修改封面</a-radio>
  64. </a-radio-group>
  65. <a-button type='default' @click="examineAgainCancel(record)" size='small' style='margin-right:10px'>取消</a-button>
  66. <a-button type='primary' @click="examineAgainOk(record)" size='small' class="ok">重提</a-button>
  67. </div>
  68. <a href="javascript:;" type='primary' @click="()=>{record.show=true}">一键重提</a>
  69. </a-popover>
  70. <a-divider type="vertical" />
  71. <a-popover v-model="record.visible" trigger="click" placement="topLeft" @visibleChange='visibleChange'>
  72. <span slot="title">出价</span>
  73. <template slot="content" style="width:300px;">
  74. <div style="margin:5px 0 0">
  75. <span ><a-input-number :min="0" v-model="newBid" :step="0.1" placeholder="请输入出价" size="small" style='margin-right:20px;width:120px' /></span>
  76. <p style="color:red;font-size:12px;height:16px;padding:5px 0">{{bidErrorMessage}}</p>
  77. </div>
  78. <div>
  79. <a-button type='default' @click="bidChangeCancel(record)" size='small' style='margin-right:10px'>取消</a-button>
  80. <a-button type='primary' @click="bidChangeOk(record)" size='small' class="ok">修改</a-button>
  81. </div>
  82. </template>
  83. <a href="javascript:;" type='primary' @click="()=>{record.visible=true}">修改出价</a>
  84. </a-popover>
  85. </span>
  86. </a-table>
  87. </div>
  88. </div>
  89. <!-- </a-spin> -->
  90. </div>
  91. </template>
  92. <script>
  93. import moment from 'moment';
  94. import { getAction, postAction, downFile, downFilePost,deleteAction } from '@/api/manage';
  95. // import { JeecgListMixin } from '@/mixins/ipagination'
  96. // import editableCell from './editableCell'
  97. import Treeselect from '@/views/modules/Statistics/components/Treeselect.vue'
  98. import qs from 'qs'
  99. let typeValue='预算'
  100. const strategyColumns = [
  101. {
  102. title: '广告组名称',
  103. dataIndex: 'name',
  104. key: 'name',
  105. align: 'center',
  106. scopedSlots: { customRender: 'name' },
  107. width:200,
  108. fixed: 'left'
  109. },
  110. {
  111. title: '广告组ID',
  112. dataIndex: 'authName',
  113. key: 'authName',
  114. align: 'center',
  115. scopedSlots: { customRender: 'authName' },
  116. width:150,
  117. fixed: 'left'
  118. },
  119. {
  120. title: '所属广告账户',
  121. dataIndex: 'accountId',
  122. key: 'accountId',
  123. align: 'center',
  124. scopedSlots: { customRender: 'accountId' },
  125. width:200,
  126. fixed: 'left'
  127. },
  128. {
  129. title: '所属项目',
  130. dataIndex: 'createTime',
  131. key: 'createTime',
  132. align: 'center',
  133. scopedSlots: { customRender: 'createTime' },
  134. width:150,
  135. fixed: 'left'
  136. },
  137. {
  138. title: '探索状态',
  139. dataIndex: 'createTsime',
  140. key: 'createTime',
  141. align: 'center',
  142. scopedSlots: { customRender: 'createTime' },
  143. },
  144. {
  145. title: '探索预算',
  146. dataIndex: 'createTimes',
  147. key: 'createTime',
  148. align: 'center',
  149. scopedSlots: { customRender: 'createTime' },
  150. },
  151. {
  152. title: '优化目标',
  153. dataIndex: 'cpaBid',
  154. align: 'center',
  155. scopedSlots: { customRender: 'cpaBid' },
  156. // sorter:() => {}
  157. },
  158. {
  159. title: '消耗(元)',
  160. dataIndex: 'cost',
  161. width:150,
  162. tip: '广告在投放期间的花费总额',
  163. align: 'center',
  164. scopedSlots: { customRender: 'cost' },
  165. // sorter: () => {}
  166. },
  167. {
  168. title: '封面曝光数',
  169. dataIndex: 'photoShow',
  170. tip: '广告在瀑布流被观看次数',
  171. align: 'center',
  172. scopedSlots: { customRender: 'photoShow' },
  173. // sorter:() => {}
  174. },
  175. {
  176. title: '封面点击数',
  177. dataIndex: 'photoClick',
  178. tip: '用户点击封面进入视频播放页的次数(数据会进行反作弊去重)',
  179. align: 'center',
  180. scopedSlots: { customRender: 'photoClick' },
  181. // sorter: () => {}
  182. },
  183. {
  184. title: '封面点击率',
  185. dataIndex: 'clickRate',
  186. tip: '封面点击数占封面展示数百分比',
  187. align: 'center',
  188. scopedSlots: { customRender: 'clickRate' },
  189. // sorter:() => {}
  190. },
  191. {
  192. title: '封面点击单价',
  193. dataIndex: 'clickCost',
  194. tip: '封面点击数占封面展示数百分比',
  195. align: 'center',
  196. scopedSlots: { customRender: 'clickCost' },
  197. // sorter:() => {}
  198. },
  199. {
  200. title: '转化数',
  201. dataIndex: 'aclick',
  202. tip: '用户进入视频播放页观看的次数(数据会进行反作弊去重)',
  203. align: 'center',
  204. scopedSlots: { customRender: 'aClick' },
  205. // sorter:() => {}
  206. },
  207. {
  208. title: '转化成本',
  209. dataIndex: 'bclick',
  210. tip: '用户在视频播放页单击转化按钮的次数/展示数*100%',
  211. align: 'center',
  212. scopedSlots: { customRender: 'bClick' },
  213. // sorter:() => {}
  214. },
  215. {
  216. title: '转化率',
  217. dataIndex: 'bClickRate',
  218. tip: '行为数占素材曝光数百分比',
  219. align: 'center',
  220. scopedSlots: { customRender: 'bClickRate' },
  221. // sorter:() => {}
  222. },
  223. {
  224. title: '操作',
  225. dataIndex: 'status',
  226. key: 'status',
  227. align: 'center',
  228. scopedSlots: { customRender: 'status' },
  229. width:150,
  230. fixed:'right'
  231. },
  232. ];
  233. const publicColumns = [
  234. ]
  235. export default {
  236. name:'strategy-list',
  237. components: {
  238. // editableCell,
  239. Treeselect,
  240. },
  241. // mixins: [JeecgListMixin],
  242. data() {
  243. return {
  244. selectedRecord:{},
  245. bidErrorMessage:'',
  246. examineAgainType:1,
  247. newBid:undefined,
  248. examineAgain:false,
  249. accountId:[],
  250. accountList:[],
  251. strategyState:undefined,
  252. strategyName:'',
  253. strategyId:undefined,
  254. accountId:[],
  255. scrollX:2500,
  256. ipagination: {
  257. current: 1,
  258. pageSize: 10,
  259. // pageSizeOptions: ['10', '20', '30'],
  260. showTotal: (total, range) => {
  261. return range[0] + "-" + range[1] + " 共" + total + "条"
  262. },
  263. showQuickJumper: true,
  264. showSizeChanger:true,
  265. pageSizeOptions: ['10', '30', '50'],
  266. total: 0,
  267. onChange: (current, pageSize) => {
  268. // 切换分页时的回调,
  269. // 当在页面定义change事件时,切记要把此处的事件清除,因为这两个事件重叠了,可能到时候会导致一些莫名的bug
  270. this.ipagination.current = current;
  271. this.ipagination.pageSize= pageSize;
  272. }
  273. },
  274. spinning:false,
  275. moment,
  276. optionId:'',//input输入的id或关键词
  277. selectDisable:true,
  278. optValue:undefined,//操作设置的值 删除 暂停 开启
  279. visible: false,//出价里的弹出框
  280. //主页的表格
  281. data:[],
  282. columns:[...strategyColumns,...publicColumns],
  283. selectedRowKeys:[],
  284. loading:false,
  285. editID:0,
  286. url: {
  287. list:'/ctop/aiKuaishouAdvertiserStrategy/list',
  288. delete:'/ctop/aiKuaishouAdvertiserStrategy/delete',
  289. },
  290. xiugaiData:[],//存分别修改时候的数组
  291. }
  292. },
  293. computed: {
  294. hasSelected() {
  295. return this.selectedRowKeys.length > 0;
  296. },
  297. },
  298. methods: {
  299. // 加速探索OK事件
  300. targethandleOk(e){
  301. this.targetVisible=true
  302. },
  303. //状态改变
  304. switchChange(text,record){
  305. // this.spinning=true;
  306. console.log(text,record)
  307. record.spin=true;
  308. let status=text==1?0:1;
  309. getAction(`/ctop/aiKuaishouAdvertiserStrategy/oprateStatus`,{
  310. id:record.id,
  311. status
  312. }).then((res)=>{
  313. record.spin=false;
  314. if(res.success){
  315. this.getStrategyList()
  316. this.$message.success(res.message)
  317. }else{
  318. this.$message.error(res.message)
  319. }
  320. })
  321. },
  322. //是否开启程序化创意状态改变
  323. openProgramCreateSwitchChange(text,record){
  324. // this.spinning=true;
  325. console.log(text,record)
  326. record.openProgramCreateSpin=true;
  327. let status=text==1?0:1;
  328. getAction(`/ctop/aiKuaishouAdvertiserStrategy/oprateCreativeStatus`,{
  329. id:record.id,
  330. status
  331. }).then((res)=>{
  332. record.openProgramCreateSpin=false;
  333. if(res.success){
  334. this.getStrategyList()
  335. this.$message.success(res.message)
  336. }else{
  337. this.$message.error(res.message)
  338. }
  339. })
  340. },
  341. examineAgainMethod(record){
  342. console.log(record)
  343. this.examineAgain=true;
  344. this.selectedRecord=record
  345. },
  346. visibleChange(){
  347. this.bidErrorMessage='';
  348. this.examineAgainType=1;
  349. this.newBid=undefined;
  350. },
  351. bidChangeCancel(record){
  352. record.visible=false;
  353. this.newBid=undefined;
  354. this.bidErrorMessage=''
  355. },
  356. bidChangeOk(record){
  357. if(this.newBid){
  358. record.visible=false;
  359. postAction('/ai/batchUpdate/updateGroupBid',{
  360. accountId:record.accountId,
  361. bid:this.newBid*1000
  362. }).then(res=>{
  363. console.log(res)
  364. if(res.code==0){
  365. this.$message.success(res.message)
  366. this.newBid=undefined;
  367. this.getStrategyList()
  368. }
  369. })
  370. }else{
  371. this.bidErrorMessage='请正确填写出价'
  372. // this.$message.error('请正确填写出价')
  373. }
  374. },
  375. examineAgainCancel(record){
  376. record.show=false;
  377. this.examineAgainType=1
  378. },
  379. examineAgainOk(record){
  380. record.show=false;
  381. postAction('/kuaishou/creative/again',{
  382. accountId:record.accountId,
  383. updateType:this.examineAgainType
  384. }).then(res=>{
  385. console.log(res);
  386. if(res.code==0){
  387. this.$message.success('正在重提中,您可稍后查看结果')
  388. }else{
  389. this.$message.success(res.message)
  390. }
  391. this.examineAgainType=1
  392. })
  393. },
  394. onSelectChange(selectedRowKeys) {
  395. console.log('selectedRowKeys changed: ', selectedRowKeys);
  396. this.selectedRowKeys = selectedRowKeys;
  397. },
  398. goNewConfigInfo(){
  399. this.$router.push('/autoLaunch/configLaunchInfo')
  400. },
  401. goPlanList(record){
  402. console.log(record)
  403. this.$parent.currentStrategyId=record.id;
  404. this.$router.push(`/autoLaunch/configLaunchInfo?id=${record.id}`)
  405. },
  406. deleteRecord(record){
  407. this.loading=true
  408. deleteAction(this.url.delete,{
  409. id:record.id
  410. }).then(res=>{
  411. this.loading=false
  412. if(res.success){
  413. this.$message.success(res.message);
  414. this.getStrategyList()
  415. }else{
  416. this.$message.success(res.message);
  417. }
  418. })
  419. },
  420. filterOption(input, option) {
  421. return (
  422. option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
  423. );
  424. },
  425. //查询按钮事件
  426. search(){
  427. this.ipagination.current=1;
  428. this.getStrategyList()
  429. },
  430. //点击分页
  431. sort(pagination, filters, sorter, { currentDataSource }){
  432. console.log(pagination)
  433. this.ipagination.current=pagination.current;
  434. this.ipagination.pageSize=pagination.pageSize;
  435. this.getStrategyList()
  436. },
  437. getStrategyList(){
  438. this.loading = true
  439. console.log(this.accountId)
  440. getAction(this.url.list,{
  441. strategyId:this.strategyId==undefined?null:this.strategyId,
  442. accountId:this.accountId,
  443. pageNo:this.ipagination.current,
  444. pageSize:this.ipagination.pageSize
  445. }).then((res)=>{
  446. this.data=[]
  447. console.log(res)
  448. this.loading = false
  449. if(res.success){
  450. this.ipagination.total = res.result.total
  451. res.result.records.forEach((item)=>{
  452. item.key=item.id;
  453. item.show=false;
  454. item.visible=false;
  455. item.spin=false;
  456. item.openProgramCreateSpin=false;
  457. })
  458. this.data = res.result.records;
  459. this.selectedRowKeys=[];
  460. }
  461. })
  462. },
  463. },
  464. mounted() {
  465. this.getStrategyList()
  466. },
  467. activated() {
  468. this.getStrategyList()
  469. },
  470. beforeDestroy() {
  471. },
  472. filters: {
  473. toPercentage(val) {
  474. if(val){
  475. if(typeof val != 'string'){
  476. return (val * 100).toFixed(2) + '%'
  477. }else{
  478. return val
  479. }
  480. }else if(typeof val =='string'){
  481. return val
  482. }
  483. else{
  484. return 0
  485. }
  486. },
  487. //保留两位小数并且变成货币格式
  488. decimalsHandle(val){
  489. if(val && typeof val !='string'){
  490. if(val>=0){
  491. val=parseFloat(val).toFixed(2);
  492. let numberStr = val.toString()
  493. let str = numberStr.split('.')
  494. let str0=str[0].split('').reverse();
  495. for (let i = 0; i < str0.length; i++) {
  496. if ((i + 1) % 4 === 0) {
  497. str0.splice(i, 0, ',')
  498. }
  499. }
  500. str0.reverse()
  501. let handleResult = ''
  502. for (let j = 0; j < str0.length; j++) {
  503. handleResult += str0[j]
  504. }
  505. return handleResult+'.'+str[1]
  506. }else{
  507. val=parseFloat(val).toFixed(2);
  508. let numberStr = val.toString()
  509. let str = numberStr.split('.')
  510. let str0=str[0].substr(1).split('').reverse();
  511. for (let i = 0; i < str0.length; i++) {
  512. if ((i + 1) % 4 === 0) {
  513. str0.splice(i, 0, ',')
  514. }
  515. }
  516. str0.reverse()
  517. let handleResult = ''
  518. for (let j = 0; j < str0.length; j++) {
  519. handleResult += str0[j]
  520. }
  521. return '-'+handleResult+'.'+str[1]
  522. }
  523. }else if(typeof val =='string'){
  524. return val
  525. }
  526. else{
  527. return 0
  528. }
  529. },
  530. //变成货币格式
  531. formatCurrency(val){
  532. if((val||val==0)&& typeof val !='string'){
  533. let numberStr = val.toString()
  534. let str = numberStr.split('').reverse()
  535. for (let i = 0; i < str.length; i++) {
  536. if ((i + 1) % 4 === 0) {
  537. str.splice(i, 0, ',')
  538. }
  539. }
  540. str.reverse()
  541. let handleResult = ''
  542. for (let j = 0; j < str.length; j++) {
  543. handleResult += str[j]
  544. }
  545. return handleResult
  546. }else if(typeof val =='string'){
  547. return val
  548. }
  549. else{
  550. return '-'
  551. }
  552. },
  553. }
  554. }
  555. </script>
  556. <style lang="scss">
  557. #closeIcon{
  558. color: #0E74D2;
  559. }
  560. .toutiaoBatch{
  561. .ant-tag .anticon-close {
  562. color: #1890ff;
  563. }
  564. .ant-tag .anticon-close:hover{
  565. color: rgba(0, 0, 0, 0.85);
  566. }
  567. }
  568. .ant-tooltip-inner,.ant-tooltip-arrow::before{
  569. background-color: #fff;
  570. color: #333;
  571. }
  572. #batchModal{
  573. .rules,.totalPrice{
  574. font-weight: 600;
  575. }
  576. .selectePlan{
  577. font-size: 14px;
  578. font-weight: 700;
  579. color: #333;
  580. padding: 20px 0;
  581. }
  582. .totalPrice{
  583. margin-left: 20px;
  584. }
  585. .modifyTable{
  586. margin-top: 20px;
  587. width: 100%;
  588. height: 400px;
  589. overflow: auto;
  590. font-weight: 600;
  591. }
  592. }
  593. #copyModal{
  594. .ant-modal-header{
  595. text-align: center;
  596. }
  597. .copyTip{
  598. font-size: 12px;
  599. color: #999;
  600. }
  601. .copyName{
  602. width: 118px;
  603. display: inline-block;
  604. text-align: right;
  605. .copyKeyStart{
  606. color: red;
  607. }
  608. }
  609. // font-weight: 600;
  610. }
  611. </style>
  612. <style lang="scss" scoped>
  613. .toutiaoBatch{
  614. .breadcrumb{
  615. height: 22px;
  616. font-size: 12px;
  617. font-family: PingFangSC-Regular, PingFang SC;
  618. font-weight: 400;
  619. color: #000000;
  620. line-height: 22px;
  621. }
  622. background-color: #fff;
  623. padding: 10px 20px;
  624. position: relative;
  625. width: 100%;
  626. .OptinItem{
  627. display: inline-block;
  628. margin-right: 15px;
  629. margin-top: 15px;
  630. .ok{
  631. margin-right: 15px;
  632. }
  633. }
  634. .OptinItem:first-child{
  635. margin-right: 10px;
  636. }
  637. .topOptions{
  638. padding: 15px 0;
  639. display: flex;
  640. justify-content: space-between;
  641. .topOpt{
  642. width: 100%;
  643. margin-bottom: 10px;
  644. }
  645. }
  646. .optionBtn{
  647. // display: inline-block;
  648. float: right;
  649. // .searchBtn{
  650. // margin-right: 10px;
  651. // }
  652. }
  653. .tableArea{
  654. .tableOption{
  655. padding: 20px 0;
  656. }
  657. }
  658. .toolbox-automate-rules-create-content_title {
  659. background-color: #fff;
  660. display: flex;
  661. flex-flow: row nowrap;
  662. justify-content: flex-start;
  663. align-items: center;
  664. margin-bottom: 28px;
  665. position: relative;
  666. h3 {
  667. font-size: 22px;
  668. margin: 0;
  669. font-weight: 400;
  670. height: 30px;
  671. line-height: 30px;
  672. }
  673. .goNewConfigInfo{
  674. position: absolute;
  675. right: 0;
  676. top: 4px;
  677. }
  678. }
  679. }
  680. </style>