refuseDataCreatNew.vue 20 KB

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