refuseDataCreatNew.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  1. <style></style>
  2. <template>
  3. <div class="data-refuse-statistics">
  4. <a-row class="image-list-heading vm-panel">
  5. <a-row type="flex" align="middle" justify="space-between" class="panel-body">
  6. <div class="search-bar" style="width:100%;display:flex">
  7. <span style="line-height:35px;margin-left:15px">账户选择:</span>
  8. <treeselect :appId.sync="appId" :multiple="false" />
  9. <a-button type="primary" style="margin-left:10px" @click="(ipagination.current=1);addUser()">搜索</a-button>
  10. </div>
  11. </a-row>
  12. </a-row>
  13. <a-row :gutter="10" style="margin-top:10px">
  14. <a-col :span="24">
  15. <a-card style="width:100%;">
  16. <div style="display:flex;margin:0 0 20px 0;position:relative">
  17. <a-input placeholder="请输出要查找的创意名称" style="width:300px;" v-model="keyWord" />
  18. <a-button type="primary" style="margin-left:10px" @click="addUserKey">搜索</a-button>
  19. <a-button type="primary" style="margin-left:10px" @click="reset()">刷新列表</a-button>
  20. <a-button type="primary" style="margin-left:10px" @click="clickAgain" v-if="selectedRowKeys.length>0"
  21. :loading="loadingList">一键重提
  22. </a-button>
  23. <a-button type="primary" style="position:absolute;right:0" @click="syncCreative"
  24. :loading="loadingSyncCreative">
  25. 同步创意
  26. </a-button>
  27. </div>
  28. <!-- /MaterialRefuse/syncCreative -->
  29. <a-table :columns="columns" :dataSource="dataList" bordered :loading="loading" size="middle"
  30. :pagination="ipagination" :rowSelection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange }">
  31. <!-- <div slot="videoUrl" slot-scope="videoUrl">
  32. <video class="video" :src="videoUrl" controls="controls" style="height:200px;width:112.5px">
  33. 您的浏览器不支持 video 标签。
  34. </video>
  35. </div> -->
  36. <div slot="coverUrl" slot-scope="coverUrl">
  37. <img :src="coverUrl" controls="controls" style="height:200px;width:112.5px" />
  38. </div>
  39. <template slot="creativeName" slot-scope="text, record">
  40. <div>
  41. {{ text }}
  42. <a-icon type="edit" style="cursor: pointer;" @click="onCellChange(record, 'creativeName')" />
  43. </div>
  44. </template>
  45. <template slot="description" slot-scope="text, record">
  46. <div>
  47. {{ text }}
  48. <a-icon type="edit" style="cursor: pointer;" @click="onCellChange(record, 'description')" />
  49. </div>
  50. </template>
  51. </a-table>
  52. </a-card>
  53. </a-col>
  54. </a-row>
  55. <a-modal :title="editTitle" :visible="visible" @ok="handleOk" :confirmLoading="confirmLoading"
  56. @cancel="handleCancel">
  57. <a-textarea v-model="editWord" autosize />
  58. </a-modal>
  59. <a-modal title="一键重提" @cancel="handleClose" :visible="visibleAgain" @ok="handleOkAgain"
  60. :confirmLoading="againLoading" :width="650" >
  61. <a-form :form="form">
  62. <a-form-item label="是否修改" :labelCol="{ lg: { span: 4 }, sm: { span: 6 } }"
  63. :wrapperCol="{ lg: { span: 18 }, sm: { span: 18 } }">
  64. <a-radio-group buttonStyle="solid" v-decorator="[
  65. 'type',
  66. { initialValue: 0} ]">
  67. <a-radio-button :value="0">否</a-radio-button>
  68. <a-radio-button :value="1">是</a-radio-button>
  69. </a-radio-group>
  70. </a-form-item>
  71. <a-form-item label="广告语" :labelCol="{ lg: { span: 4 }, sm: { span: 6 } }"
  72. :wrapperCol="{ lg: { span: 18 }, sm: { span: 18 } }" v-if="getData('type')==1">
  73. <a-input v-model="updateDescription" :max="10" :min="1" style="width:100%" @change="DescriptionChange">
  74. </a-input>
  75. <a @click="showTitle()">推荐标题</a><a style="margin-left:10px" @click="showCunTitle()">标题收藏</a>
  76. </a-form-item>
  77. <!-- <a-form-item label="行动号召" :labelCol="{ lg: { span: 6 }, sm: { span: 6 } }"
  78. :wrapperCol="{ lg: { span: 18 }, sm: { span: 18 } }" v-if="getData('type')==1">
  79. <a-select v-decorator="['updateActionBarText']" showSearch allowClear placeholder="选择行动号召按钮文案"
  80. optionFilterProp="children" :filterOption="filterOption">
  81. <a-select-option v-for="appModel in appList" :key="appModel.id" :value="appModel.actionBarText">
  82. {{ appModel.actionBarText }}
  83. </a-select-option>
  84. </a-select>
  85. </a-form-item> -->
  86. </a-form>
  87. </a-modal>
  88. <a-modal v-model="visibleFail" title="重提信息" :footer="null">
  89. <div v-if="fail">
  90. 修改成功条数:{{ fail.successCount }} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;失败条数:{{
  91. fail.failCount
  92. }}
  93. <div style="margin-top:20px">
  94. <p v-for="(item, index) of fail.failInfo" :key="index">
  95. <span>名称:{{ item.campaignName?item.campaignName:item.unitName }}</span><br />
  96. <span>错误信息:{{ item.message }}</span>
  97. </p>
  98. </div>
  99. </div>
  100. </a-modal>
  101. <a-modal title="推荐标题" v-model="titleVisible" :width="1000" :footer="null">
  102. <a-row :gutter="10">
  103. <a-col :sm="10" style="margin-bottom: 20px;z-index: 10">
  104. <a-card class="search-box" style="min-height:500px">
  105. <div style="margin-bottom:30px">
  106. <span style="display:inline-block;width:80px">行业</span>
  107. <a-cascader style="margin-top: 1rem;width:300px" v-model="dataOne" :options="options"
  108. :showSearch="{ filter }" expandTrigger="hover" @change="onChangeTitle" placeholder="请选择行业">
  109. <a-icon type="smile" slot="suffixIcon" class="test" />
  110. </a-cascader>
  111. </div>
  112. <div style="margin-bottom:30px">
  113. <span style="display:inline-block;width:80px">关键词</span>
  114. <a-input placeholder="请输入关键词" v-model="value" style="width: 300px" />
  115. </div>
  116. <span style="display:inline-block;width:80px;float:left"></span>
  117. <a-button type="primary" @click="searchQuery" :disabled="value == ''">生成</a-button>
  118. </a-card>
  119. </a-col>
  120. <a-col :sm="14" style="margin-bottom: 20px;z-index: 10">
  121. <a-card class="search-box" style="over-flow:auto">
  122. <a-list size="large" bordered :dataSource="title">
  123. <a-list-item slot="renderItem" slot-scope="item">
  124. <a slot="actions" @click="okTitle(item)">选择</a>
  125. {{ item }}
  126. </a-list-item>
  127. </a-list>
  128. </a-card>
  129. </a-col>
  130. </a-row>
  131. </a-modal>
  132. <a-modal title="收藏标题" v-model="cunTitleVisible" :width="1000" :footer="null">
  133. <a-row :gutter="10">
  134. <a-col :sm="24" style="margin-bottom: 20px;z-index: 10">
  135. <a-card class="search-box" style="over-flow:auto">
  136. <a-list size="large" bordered :dataSource="cunTitleList">
  137. <a-list-item slot="renderItem" slot-scope="item">
  138. <div slot="actions">
  139. <a @click="okTitleCun(item)">选择</a>
  140. <!-- <a-divider type="vertical" />
  141. <a @click="removeTitleCun(item)">删除</a> -->
  142. </div>
  143. {{ item.title }}
  144. </a-list-item>
  145. </a-list>
  146. </a-card>
  147. </a-col>
  148. </a-row>
  149. </a-modal>
  150. </div>
  151. </template>
  152. <script>
  153. import moment from 'moment'
  154. import {
  155. getRefuseCreative,
  156. updateCreative,
  157. selectByCreateName
  158. } from '@api/statistics'
  159. import axios from 'axios'
  160. import EditableCell from './components/EditableCell'
  161. import {
  162. mapGetters
  163. } from 'vuex'
  164. import {
  165. deleteAction,
  166. getAction,
  167. postAction
  168. } from '@/api/manage'
  169. import Treeselect from './components/Treeselect.vue'
  170. import {
  171. stopOtherVideo,
  172. closeAllVideoFun
  173. } from '@/utils/videoControl' // 停止除当前外的其他视频播放,及停止所有视频播放的方法
  174. const columns = [{
  175. title: '账号Id',
  176. dataIndex: 'accountId',
  177. key: 'accountId',
  178. align: 'center'
  179. },
  180. {
  181. title: '计划Id',
  182. dataIndex: 'campaignId',
  183. key: 'campaignId',
  184. align: 'center'
  185. },
  186. {
  187. title: '广告组id',
  188. dataIndex: 'unitId',
  189. key: 'unitId',
  190. align: 'center'
  191. },
  192. {
  193. title: '创意id',
  194. dataIndex: 'creativeId',
  195. key: 'photoClick',
  196. align: 'center'
  197. },
  198. {
  199. title: '创意名称',
  200. dataIndex: 'creativeName',
  201. key: 'creativeName',
  202. align: 'left',
  203. scopedSlots: {
  204. customRender: 'creativeName'
  205. }
  206. },
  207. // {
  208. // title: '视频',
  209. // dataIndex: 'videoUrl',
  210. // key: 'videoUrl',
  211. // align: 'center',
  212. // scopedSlots: {
  213. // customRender: 'videoUrl'
  214. // }
  215. // },
  216. {
  217. title: '封面',
  218. dataIndex: 'coverUrl',
  219. key: 'coverUrl',
  220. align: 'center',
  221. scopedSlots: {
  222. customRender: 'coverUrl'
  223. }
  224. },
  225. {
  226. title: '拒绝原因',
  227. dataIndex: 'reviewDetail',
  228. key: 'reviewDetail',
  229. align: 'left'
  230. },
  231. {
  232. title: '广告语',
  233. dataIndex: 'description',
  234. key: 'description',
  235. align: 'left',
  236. scopedSlots: {
  237. customRender: 'description'
  238. }
  239. }
  240. ]
  241. export default {
  242. name: 'refuse-data',
  243. components: {
  244. EditableCell,
  245. Treeselect
  246. },
  247. data: function () {
  248. return {
  249. title: '被拒创意列表',
  250. visibleFail: false,
  251. visibleAgain: false,
  252. againLoading: false,
  253. fail: null,
  254. appId: null,
  255. loading: false,
  256. columns,
  257. dataList: [],
  258. titleVisible: false,
  259. cunTitleVisible: false,
  260. keyWord: '',
  261. editTitle: '',
  262. confirmLoading: false,
  263. visible: false,
  264. editWord: '',
  265. nowData: null,
  266. selectedRowKeys: [],
  267. selectedRowKeysValue: [],
  268. loadingList: false,
  269. loadingSyncCreative: false,
  270. ipagination: {
  271. current: 1,
  272. pageSize: 50,
  273. showTotal: (total, range) => {
  274. return range[0] + '-' + range[1] + ' 共' + total + '条'
  275. },
  276. showQuickJumper: true,
  277. // showSizeChanger: true,
  278. total: 0,
  279. onChange: current => {
  280. // 切换分页时的回调,
  281. // 当在页面定义change事件时,切记要把此处的事件清除,因为这两个事件重叠了,可能到时候会导致一些莫名的bug
  282. this.ipagination.current = current
  283. this.selectedRowKeys = []
  284. this.selectedRowKeysValue = []
  285. this.addUser()
  286. }
  287. },
  288. form: this.$form.createForm(this),
  289. appList: [],
  290. options: [],
  291. cunTitleList: [],
  292. title: [],
  293. dataOne: [],
  294. value: '',
  295. updateDescription:'',//广告语的字符
  296. }
  297. },
  298. filters: {
  299. typeStatus(type) {
  300. // 2 - 提升应用安装;
  301. // 3 - 获取电商下单;
  302. // 4 - 推广品牌活动;
  303. // 5 - 收集销售线索;
  304. var data = ['', '', '提升应用安装', '获取电商下单', '推广品牌活动', '收集销售线索']
  305. return data[type]
  306. },
  307. status(sta) {
  308. var data = {
  309. '-1': '不限',
  310. 1: '已暂停',
  311. 3: '计划超预算',
  312. 4: '有效',
  313. 6: '余额不足'
  314. }
  315. return data[sta]
  316. },
  317. putStatus(sta) {
  318. var data = {
  319. 1: '投放中',
  320. 2: '暂停'
  321. }
  322. return data[sta]
  323. },
  324. createChannel(sta) {
  325. var data = {
  326. 0: '投放后台',
  327. 1: '汇创助手'
  328. }
  329. return data[sta]
  330. }
  331. },
  332. watch: {
  333. appId(n, o) {
  334. console.log(n, o)
  335. if (n != o) {
  336. this.ipagination.current = 1
  337. }
  338. },
  339. visibleFail(n, o) {
  340. if (!n) {
  341. this.visibleAgain = false
  342. this.selectedRowKeys = []
  343. this.selectedRowKeysValue = []
  344. this.addUser()
  345. }
  346. }
  347. },
  348. methods: {
  349. // 广告语改变
  350. DescriptionChange(e){
  351. console.log(e.target.value);
  352. if(e.target.value.length>30){
  353. // this.updateDescription=e.target.value.substr(0,30);
  354. // console.log(this.updateDescription)
  355. this.$message.error('广告语最多30字!')
  356. }
  357. },
  358. filter(inputValue, path) {
  359. return path.some(option => option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1)
  360. },
  361. onChangeTitle(value, selectedOptions) {
  362. console.log(value, selectedOptions)
  363. this.dataOne = value
  364. this.value = ''
  365. this.title = []
  366. },
  367. okTitleCun(item) {
  368. console.log(item)
  369. // this.form.setFieldsValue({
  370. // updateDescription: item.title
  371. // })
  372. this.updateDescription=item.title;
  373. this.cunTitleVisible = false;
  374. this.cunTitleList = []
  375. },
  376. okTitle(item) {
  377. // this.form.setFieldsValue({
  378. // updateDescription: item
  379. // })
  380. this.updateDescription=item;
  381. this.titleVisible = false;
  382. this.dataOne = []
  383. this.value = ""
  384. this.title = []
  385. },
  386. searchQuery() {
  387. // /ctop/creativeTitle/titleSuggestion
  388. console.log(this.value)
  389. getAction('/ctop/creativeTitle/titleSearch', {
  390. firstCategory: this.dataOne[0],
  391. secondCategory: this.dataOne[1],
  392. keywords: this.value
  393. }).then(res => {
  394. console.log(res)
  395. this.title = res.result ? res.result : []
  396. })
  397. // firstCategory,secondCategory,keywords
  398. },
  399. filterOption(input, option) {
  400. return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
  401. },
  402. getData(className) {
  403. return this.form.getFieldValue(className)
  404. },
  405. syncCreative() {
  406. this.loadingSyncCreative = true
  407. var params = {}
  408. // localStorage.setItem('accountIdCreat', record.campaignId)
  409. // localStorage.setItem('accountIdCreatNow', this.appId)
  410. params.accountId = this.appId
  411. getAction('/MaterialRefuse/syncCreative', params).then(res => {
  412. if (res.success) {
  413. this.loadingSyncCreative = false
  414. this.$message.success("同步成功")
  415. this.reset()
  416. } else {
  417. this.loadingSyncCreative = false
  418. this.$message.error(res.message)
  419. }
  420. })
  421. },
  422. clickAgain() {
  423. // this.loadingList = true
  424. this.visibleAgain = true
  425. // getAction('/MaterialRefuse/getAllActionBarText').then(res => {
  426. // if (res.success) {
  427. // this.appList = res.result
  428. // }
  429. // })
  430. // var params = {}
  431. // params.accountId = this.appId + ''
  432. // params.creativeArr = this.selectedRowKeysValue
  433. // postAction('/MaterialRefuse/batchUpdateCreative', params).then(res => {
  434. // if (res.success) {
  435. // this.loadingList = false
  436. // this.selectedRowKeysValue = []
  437. // this.selectedRowKeys = []
  438. // this.visibleFail = true
  439. // this.fail = res.result
  440. // this.addUser()
  441. // } else {
  442. // this.loadingList = false
  443. // this.visibleFail = true
  444. // this.fail = res.result
  445. // this.$message.error(res.message)
  446. // }
  447. // })
  448. },
  449. showTitle() {
  450. this.titleVisible = true;
  451. this.getHangye()
  452. },
  453. showCunTitle() {
  454. this.cunTitleVisible = true
  455. this.getCunTitle()
  456. },
  457. getCunTitle() {
  458. var params = {}
  459. params.accountId = this.appId
  460. params.userId = this.userInfo().id
  461. params.pageNo = 1
  462. params.pageSize = 500
  463. getAction('/kuaishou/kuaiShouTitleCollection/list', params).then(res => {
  464. if (res.success) {
  465. console.log(res.result)
  466. this.cunTitleList = res.result.records
  467. }
  468. })
  469. },
  470. getHangye() {
  471. getAction('/ctop/creativeTitle/getTitleLabel', '').then(res => {
  472. console.log(res)
  473. if (res.success) {
  474. this.options = res.result.map(item => {
  475. return {
  476. label: item.label,
  477. value: item.value,
  478. children: item.children.length > 0 ? [{
  479. label: '不限',
  480. value: 0
  481. }].concat(item.children) : [{
  482. label: '不限',
  483. value: 0
  484. }]
  485. }
  486. })
  487. this.options = [{
  488. label: '不限',
  489. value: 0
  490. }].concat(this.options)
  491. if (this.dataOne.length > 0) {
  492. return
  493. } else {
  494. this.dataOne = [0]
  495. }
  496. }
  497. })
  498. },
  499. onSelectChange(selectedRowKeys, selectionRows) {
  500. this.selectedRowKeys = selectedRowKeys
  501. this.selectedRowKeysValue = selectionRows.map(item => {
  502. return {
  503. description: item.description,
  504. creativeId: item.creativeId
  505. }
  506. })
  507. // this.selectedRowKeysValue.length > 0 ? this.selectedRowKeysValue :
  508. },
  509. handleOkAgain(e) {
  510. if(this.updateDescription.length>30&&this.getData('type')==1){
  511. this.$message.error('广告语最多30个字,请修正后再次提交!')
  512. }else{
  513. this.againLoading = true
  514. this.form.validateFields((err, values) => {
  515. if (!err) {
  516. values.updateDescription=this.updateDescription;
  517. var params = {
  518. ...values,
  519. accountId: this.appId,
  520. creativeArr: this.selectedRowKeysValue
  521. }
  522. postAction('/MaterialRefuse/batchUpdateCreative', params).then(res => {
  523. if (res.success) {
  524. // this.visibleFail = true
  525. this.visibleAgain = false
  526. this.selectedRowKeys = []
  527. this.selectedRowKeysValue = []
  528. this.addUser()
  529. this.againLoading = false
  530. this.$message.success(res.message)
  531. } else {
  532. this.againLoading = false
  533. this.$message.error(res.message)
  534. }
  535. })
  536. }
  537. })
  538. }
  539. },
  540. handleOk(e) {
  541. this.confirmLoading = true
  542. var params = {}
  543. params.accountId = this.nowData.accountId
  544. params.campaignId = this.nowData.campaignId
  545. params.unitId = this.nowData.unitId
  546. params.creativeId = this.nowData.creativeId
  547. params.creativeName = this.editTitle == '创意名称修改' ? this.editWord : this.nowData.creativeName
  548. params.description = this.editTitle == '广告语修改' ? this.editWord : this.nowData.description
  549. updateCreative(params).then(res => {
  550. if (res.code == 0) {
  551. this.addUser()
  552. this.visible = false
  553. this.confirmLoading = false
  554. } else {
  555. this.$message.error(res.message)
  556. this.visible = false
  557. this.confirmLoading = false
  558. }
  559. })
  560. },
  561. handleCancel(e) {
  562. this.visible = false
  563. },
  564. handleClose(e) {
  565. this.visibleAgain = false
  566. this.form.resetFields()
  567. },
  568. onCellChange(item, dataIndex) {
  569. this.editWord = item[dataIndex]
  570. this.editTitle = dataIndex == 'creativeName' ? '创意名称修改' : '广告语修改'
  571. this.nowData = item
  572. this.visible = true
  573. },
  574. moment,
  575. ...mapGetters(['nickname', 'avatar', 'userInfo']),
  576. addUser() {
  577. this.loading = true
  578. var params = {}
  579. // localStorage.setItem('accountIdCreat', record.campaignId)
  580. // localStorage.setItem('accountIdCreatNow', this.appId)
  581. params.accountId = this.appId
  582. // params.campaignId = localStorage.getItem('accountIdCreat')
  583. params.pageSize = this.ipagination.pageSize
  584. params.pageNo = this.ipagination.current
  585. getAction('/MaterialRefuse/getRefuseCreative', params).then(res => {
  586. if (res.code == 0) {
  587. this.dataList = res.result.records.map((v, index) => {
  588. return {
  589. ...v,
  590. key: index
  591. }
  592. })
  593. this.list = this.dataList
  594. this.loading = false
  595. this.ipagination.total = res.result.total
  596. }
  597. })
  598. },
  599. addUserKey() {
  600. this.dataList = this.list.filter(item => {
  601. return item.creativeName.toLowerCase().indexOf(this.keyWord.toLowerCase()) > -1
  602. })
  603. },
  604. reset() {
  605. this.addUser()
  606. }
  607. },
  608. distoryed() {},
  609. updated() {
  610. stopOtherVideo()
  611. },
  612. mounted: function () {
  613. this.$nextTick(() => {})
  614. }
  615. }
  616. </script>