copy-library.vue 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139
  1. <template>
  2. <div class="copy-library-content">
  3. <div class="control-con-header">
  4. <a-form
  5. class="grid-form"
  6. layout="inline"
  7. :form="form"
  8. hide-required-mark
  9. >
  10. <a-row class="grid-form-options">
  11. <a-form-item
  12. v-if="controlTypeModel === '1'"
  13. class="grid-form-item"
  14. label="账户:"
  15. :colon="false"
  16. >
  17. <acount-search class="acount-search-class" :appId.sync="configForm.acountId" :multiple="false" request="1,3"></acount-search>
  18. </a-form-item>
  19. <a-form-model-item v-if="controlTypeModel === '2'" label="项目:">
  20. <a-select
  21. class="common-input-long"
  22. show-search
  23. v-model="configForm.adConvertId"
  24. placeholder="请选择"
  25. :filter-option="filterOption"
  26. allowClear
  27. >
  28. <a-select-option
  29. v-for="(item, index) in optimizationOption"
  30. :key="index"
  31. :value="item.projectId"
  32. >
  33. {{ item.projectName }}
  34. </a-select-option>
  35. </a-select>
  36. </a-form-model-item>
  37. <a-form-item
  38. class="grid-form-item"
  39. label="关键词:"
  40. :colon="false"
  41. >
  42. <a-input v-model="configForm.num" placeholder="请输入关键词"/>
  43. </a-form-item>
  44. <a-form-item
  45. class="grid-form-item"
  46. label="选择时间:"
  47. :colon="false"
  48. >
  49. <a-range-picker
  50. v-model="configForm.launchDateRange"
  51. format="YYYY-MM-DD"
  52. @change="handleLaunchData"
  53. />
  54. </a-form-item>
  55. <a-form-item class="form-handle-btn">
  56. <a-button type="default" class="reset-class" @click="handleResetList">重置</a-button>
  57. <a-button type="primary" @click="handleQueryList">查询</a-button>
  58. </a-form-item>
  59. </a-row>
  60. </a-form>
  61. <a-button type="primary" class="upload-person" @click="handleAddAccountConfig">新增文案</a-button>
  62. </div>
  63. <div class="control-con-table">
  64. <a-tabs v-model="controlTypeModel" @change="handleTabsChange">
  65. <a-tab-pane key="1" tab="通用">
  66. <a-table
  67. ref="table"
  68. size="middle"
  69. bordered
  70. :columns="currencyColumns"
  71. :dataSource="currencyData"
  72. :pagination="false"
  73. :scroll="{x: 1500}"
  74. >
  75. </a-table>
  76. <a-pagination
  77. class="pagin-table-class"
  78. v-model="currencyPag.page"
  79. :page-size="currencyPag.size"
  80. :total="currencyTotalAll"
  81. :show-total="total => `共 ${currencyTotalAll} 条`"
  82. size="small"
  83. show-size-changer
  84. show-quick-jumper
  85. @change="handleCurrentPage"
  86. @showSizeChange="handleCurrentPage"
  87. />
  88. </a-tab-pane>
  89. <a-tab-pane key="2" tab="指定">
  90. <a-table
  91. ref="table"
  92. size="middle"
  93. bordered
  94. :columns="appointColumns"
  95. :dataSource="appointData"
  96. :pagination="false"
  97. :scroll="{x: 1500}"
  98. >
  99. </a-table>
  100. <a-pagination
  101. class="pagin-table-class"
  102. v-model="appointPag.page"
  103. :page-size="appointPag.size"
  104. :total="appointTotalAll"
  105. :show-total="total => `共 ${appointTotalAll} 条`"
  106. size="small"
  107. show-size-changer
  108. show-quick-jumper
  109. @change="handleAppointPage"
  110. @showSizeChange="handleAppointPage"
  111. />
  112. </a-tab-pane>
  113. </a-tabs>
  114. </div>
  115. <a-modal
  116. v-if="causeVisible"
  117. title="新建文案"
  118. dialog-class="copywrit-modal"
  119. :visible="causeVisible"
  120. @ok="handleCauseSure"
  121. @cancel="handleCauseCancel"
  122. >
  123. <div>
  124. <div class="acount-title">
  125. <div class="acount-title-left">文案类型</div>
  126. <div class="acount-title-right">
  127. <div class="only-title-mater">
  128. <a-radio-group v-model="copywrittypeName" button-style="solid" @change="handleFormLayoutChange">
  129. <a-radio-button value="horizontal">
  130. 通用
  131. </a-radio-button>
  132. <a-radio-button value="vertical">
  133. 指定素材
  134. </a-radio-button>
  135. </a-radio-group>
  136. </div>
  137. </div>
  138. </div>
  139. <div v-if="copywrittypeName === 'horizontal'" class="acount-title">
  140. <div class="acount-title-left">广告账户</div>
  141. <div class="acount-title-right">
  142. <div class="only-title-mater">
  143. <acount-search :appId.sync="advertisingAccount" request="1,3"></acount-search>
  144. </div>
  145. </div>
  146. </div>
  147. <div v-if="copywrittypeName === 'horizontal'" class="acount-title">
  148. <div class="acount-title-left">文件上传</div>
  149. <div class="acount-title-right">
  150. <div class="only-title-mater">
  151. <a-upload
  152. name="file"
  153. action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
  154. :file-list="fileList"
  155. @change="handleChange"
  156. >
  157. <a-button><a-icon type="upload"/>文件上传</a-button>
  158. </a-upload>
  159. </div>
  160. </div>
  161. </div>
  162. <div v-if="copywrittypeName === 'vertical'" class="acount-title">
  163. <div class="acount-title-left">选择素材</div>
  164. <div class="acount-title-right">
  165. <div class="only-title-mater">
  166. <div><a @click="handleSelectMaterial">选择素材</a></div>
  167. <div class="title-mater-list">
  168. <p
  169. class="mater-list-name"
  170. v-for="item in modalSelectMaterial"
  171. :key="item.id"
  172. >
  173. <span class="mater-list-show">{{ item.materialName }}</span>
  174. <span class="mater-list-icon" @click="handleDelAlone(item)"><a-icon type="close"/></span>
  175. </p>
  176. </div>
  177. </div>
  178. </div>
  179. </div>
  180. <div v-if="copywrittypeName === 'vertical'" class="acount-title push-plate">
  181. <div class="acount-title-left">创意标题</div>
  182. <div class="acount-title-right">
  183. <a-button type="primary" @click="handleAddOrigin"><a-icon type="plus" />创意标题</a-button>
  184. <span style="margin-left: 20px;">已填:{{ titleFiledResult.length || 0 }}</span>
  185. </div>
  186. </div>
  187. <div v-if="copywrittypeName === 'vertical'" class="acount-title">
  188. <div class="acount-title-left"></div>
  189. <div class="acount-title-right">
  190. <a-form :form="examinForm">
  191. <a-form-item
  192. v-for="item in defaultFormList"
  193. :key="item.id"
  194. class="examin-form-model"
  195. :label-col="labelCol"
  196. :wrapper-col="wrapperCol"
  197. label=""
  198. >
  199. <a-input
  200. v-decorator="[
  201. item.name,
  202. {rules: [
  203. {validator: validatePass, trigger: 'blur'}
  204. ]}
  205. ]"
  206. class="examin-form-input"
  207. :id="item.name"
  208. placeholder="请输入"
  209. @change="handleFormInputChang($event, item.name, item.id)"
  210. />
  211. <span class="examin-form-num">{{ item.lenSize }}/30</span>
  212. <a-icon class="examin-form-icon" type="delete" @click="handleDelOrigin(item)"/>
  213. <div class="ad-name-tags-class">
  214. <div v-if="item.tabStatus === 'alone'" class="name-tags-left">
  215. <a-tag
  216. v-for="val in item.updateTagsList"
  217. :key="val.id"
  218. color="#1890ff"
  219. @click="handleGetChangeAll(val.name, item.name, item.id)"
  220. >
  221. + {{ val.name }}
  222. </a-tag>
  223. </div>
  224. <div v-if="item.tabStatus === 'all'" class="name-tags-left">
  225. <a-tag
  226. v-for="val in item.defaultTagsList"
  227. :key="val.id"
  228. color="#1890ff"
  229. @click="handleGetChangeAll(val.name, item.name, item.id)"
  230. >
  231. + {{ val.name }}
  232. </a-tag>
  233. </div>
  234. <div v-if="item.tabStatus === 'alone'"><a @click="handleMoreTagsShow(item.id, 'more')">更多</a></div>
  235. <div v-if="item.tabStatus === 'all'"><a @click="handleMoreTagsShow(item.id, 'little')">收起</a></div>
  236. </div>
  237. </a-form-item>
  238. </a-form>
  239. </div>
  240. </div>
  241. </div>
  242. </a-modal>
  243. <a-modal
  244. v-if="visibleMatemal"
  245. title="选择素材"
  246. :visible="visibleMatemal"
  247. dialog-class="select-matermal-modal"
  248. @ok="handleOkShow"
  249. @cancel="handleCancelAll"
  250. >
  251. <div class="mater-viedo-content">
  252. <div class="viedo-header-class">
  253. <div></div>
  254. <div>
  255. 当前选择数量 {{ viedoCheckValue.length }}/{{ materTotalAll }}
  256. <a-button type="primary" class="refush-btn-mat" @click="handleRefreshMaster">刷新素材</a-button>
  257. </div>
  258. </div>
  259. <a-row class="viedo-serach-class" :gutter="24">
  260. <a-col :span="9">
  261. <a-form-item label="项目" :labelCol="labelCol" :wrapperCol="wrapperCol">
  262. <a-select
  263. class="common-input-long"
  264. show-search
  265. v-model="projectModelValue"
  266. placeholder="请选择"
  267. :filter-option="filterOption"
  268. allowClear
  269. >
  270. <a-select-option
  271. v-for="(item, index) in optimizationOption"
  272. :key="index"
  273. :value="item.projectId"
  274. >
  275. {{ item.projectName }}
  276. </a-select-option>
  277. </a-select>
  278. </a-form-item>
  279. </a-col>
  280. <a-col :span="9">
  281. <a-form-item label="日期选择" :labelCol="modalCol" :wrapperCol="modalWrapper">
  282. <a-range-picker
  283. v-model="masterTimes"
  284. format="YYYY-MM-DD"
  285. @change="handleSelectTimeChange"
  286. />
  287. </a-form-item>
  288. </a-col>
  289. <a-col :span="4">
  290. <a-button style="position: relative;top: 4px;" @click="handleAllChecked">全选</a-button>
  291. <a-button type="primary" style="position: relative;top: 4px;margin-left:5px" @click="handleSearchMaster">搜索</a-button>
  292. </a-col>
  293. </a-row>
  294. <div class="viedo-content-class">
  295. <a-checkbox-group class="viedo-content-group" v-model="viedoCheckValue">
  296. <li class="content-modal-li" v-for="(item, index) in viedoDefaultList" :key="index">
  297. <a-checkbox
  298. class="viedo-content-checkbox"
  299. :value="item.id"
  300. >
  301. </a-checkbox>
  302. <img :src="item.coverUrl"/>
  303. <div class="checkbox-select-time">时间:{{ item.createTime }}</div>
  304. <!-- <div class="checkbox-select-show"><a>查看视频</a></div> -->
  305. </li>
  306. </a-checkbox-group>
  307. <a-pagination
  308. class="pagin-table-class"
  309. v-model="masterPag.page"
  310. :page-size="masterPag.size"
  311. :total="materTotalAll"
  312. :show-total="total => `共 ${materTotalAll} 条`"
  313. size="small"
  314. show-size-changer
  315. show-quick-jumper
  316. @change="handleMasterPageChange"
  317. @showSizeChange="handleMasterPageChange"
  318. />
  319. </div>
  320. </div>
  321. </a-modal>
  322. </div>
  323. </template>
  324. <script>
  325. import AcountSearch from '@/views/modules/Statistics/components/Treeselect.vue';
  326. import {getAction, postFileAction, postAction} from '@/api/manage';
  327. import {fileCheck, fileEdit, fileEditAll, fileInsertV2, fileEditUpdate, fileEditUpdateBatch} from '@/api/actor';
  328. import {mapGetters} from 'vuex';
  329. import {urlAcount} from './copy-library-server.js';
  330. let COS = require('cos-js-sdk-v5');
  331. let cos = new COS({
  332. SecretId: 'AKIDE6IpMi8fJQRCg1iuWzFajjRs43kbbets',
  333. SecretKey: 'tXzuwMfplTTK3c9GFUyETilasvQfePu9'
  334. });
  335. export default {
  336. name: 'copy-library',
  337. components: {
  338. AcountSearch
  339. },
  340. data() {
  341. return {
  342. projectModelValue: '',
  343. optimizationOption: [], // 账户option
  344. controlTypeModel: '1',
  345. fileList: [],
  346. modalSelectMaterial: [],
  347. materTotalAll: 0,
  348. viedoCheckValue: [],
  349. viedoDefaultList: [
  350. {
  351. name: '北京市',
  352. id: 1,
  353. statDate: '2019-08-08'
  354. },
  355. {
  356. name: '上海市',
  357. id: 2,
  358. statDate: '2019-08-08'
  359. },
  360. {
  361. name: '天津市',
  362. id: 3,
  363. statDate: '2019-08-08'
  364. },
  365. {
  366. name: '武汉市',
  367. id: 4,
  368. statDate: '2019-08-08'
  369. },
  370. {
  371. name: '贵州市',
  372. id: 5,
  373. statDate: '2019-08-08'
  374. },
  375. {
  376. name: '太原市',
  377. id: 6,
  378. statDate: '2019-08-08'
  379. },
  380. {
  381. name: '大同市',
  382. id: 7,
  383. statDate: '2019-08-08'
  384. }
  385. ],
  386. visibleMatemal: false,
  387. advertisingAccount: [],
  388. copywrittypeName: 'horizontal',
  389. adNameTags: [],
  390. causeVisible: false,
  391. labelCol: {span: 4},
  392. wrapperCol: {span: 14},
  393. modalCol: {
  394. lg: {span: 6},
  395. sm: {span: 6},
  396. xs: {span: 6},
  397. md: {span: 6}
  398. },
  399. modalWrapper: {
  400. lg: {span: 18},
  401. sm: {span: 18},
  402. xs: {span: 14},
  403. md: {span: 14}
  404. },
  405. configForm: {
  406. acountId: '',
  407. num: '',
  408. adConvertId: '',
  409. launchDateRange: []
  410. },
  411. currencyPag: {
  412. page: 1,
  413. size: 10
  414. },
  415. currencyData: [],
  416. currencyTotalAll: 0,
  417. currencyColumns: [
  418. {
  419. title: '文案',
  420. align: 'center',
  421. width: 200,
  422. dataIndex: 'textCopywriter'
  423. },
  424. {
  425. title: '相关创意',
  426. align: 'center',
  427. width: 150,
  428. dataIndex: 'count'
  429. },
  430. {
  431. title: '花费(元)',
  432. align: 'center',
  433. width: 150,
  434. dataIndex: 'cost',
  435. sorter: (a, b) => a.cost - b.cost
  436. },
  437. {
  438. title: '展示数',
  439. dataIndex: 'showNum',
  440. width: 150,
  441. align: 'center',
  442. sorter: (a, b) => a.showNum - b.showNum
  443. },
  444. {
  445. title: '平均千次展现费用',
  446. dataIndex: 'costPerThousandShow',
  447. align: 'center',
  448. width: 200,
  449. sorter: (a, b) => a.costPerThousandShow - b.costPerThousandShow
  450. },
  451. {
  452. title: '点击数',
  453. dataIndex: 'click',
  454. width: 150,
  455. align: 'center',
  456. sorter: (a, b) => a.click - b.click
  457. },
  458. {
  459. title: '平均点击单价',
  460. dataIndex: 'costPerClick',
  461. width: 150,
  462. align: 'center',
  463. sorter: (a, b) => a.costPerClick - b.costPerClick
  464. },
  465. {
  466. title: '点击率',
  467. dataIndex: 'clickRate',
  468. align: 'center',
  469. width: 150,
  470. sorter: (a, b) => a.clickRate - b.clickRate
  471. },
  472. {
  473. title: '转化数',
  474. dataIndex: 'convertNum',
  475. align: 'center',
  476. width: 150,
  477. sorter: (a, b) => a.convertNum - b.convertNum
  478. },
  479. {
  480. title: '转化率',
  481. dataIndex: 'convertRate',
  482. align: 'center',
  483. width: 150,
  484. sorter: (a, b) => a.convertRate - b.convertRate
  485. },
  486. {
  487. title: '转化成本',
  488. dataIndex: 'costConvert',
  489. align: 'center',
  490. width: 150,
  491. sorter: (a, b) => a.costConvert - b.costConvert
  492. }
  493. ],
  494. appointColumns: [
  495. {
  496. title: '文案',
  497. align: 'center',
  498. width: 200,
  499. dataIndex: 'slogan'
  500. },
  501. {
  502. title: '相关创意',
  503. align: 'center',
  504. width: 150,
  505. dataIndex: 'count'
  506. },
  507. {
  508. title: '花费(元)',
  509. align: 'center',
  510. width: 150,
  511. dataIndex: 'cost',
  512. sorter: (a, b) => a.cost - b.cost
  513. },
  514. {
  515. title: '展示数',
  516. dataIndex: 'showNum',
  517. width: 150,
  518. align: 'center',
  519. sorter: (a, b) => a.showNum - b.showNum
  520. },
  521. {
  522. title: '平均千次展现费用',
  523. dataIndex: 'costPerThousandShow',
  524. align: 'center',
  525. width: 200,
  526. sorter: (a, b) => a.costPerThousandShow - b.costPerThousandShow
  527. },
  528. {
  529. title: '点击数',
  530. dataIndex: 'click',
  531. width: 150,
  532. align: 'center',
  533. sorter: (a, b) => a.click - b.click
  534. },
  535. {
  536. title: '平均点击单价',
  537. dataIndex: 'costPerClick',
  538. width: 150,
  539. align: 'center',
  540. sorter: (a, b) => a.costPerClick - b.costPerClick
  541. },
  542. {
  543. title: '点击率',
  544. dataIndex: 'clickRate',
  545. align: 'center',
  546. width: 150,
  547. sorter: (a, b) => a.clickRate - b.clickRate
  548. },
  549. {
  550. title: '转化数',
  551. dataIndex: 'convertNum',
  552. align: 'center',
  553. width: 150,
  554. sorter: (a, b) => a.convertNum - b.convertNum
  555. },
  556. {
  557. title: '转化率',
  558. dataIndex: 'convertRate',
  559. align: 'center',
  560. width: 150,
  561. sorter: (a, b) => a.convertRate - b.convertRate
  562. },
  563. {
  564. title: '转化成本',
  565. dataIndex: 'costConvert',
  566. align: 'center',
  567. width: 150,
  568. sorter: (a, b) => a.costConvert - b.costConvert
  569. }
  570. ],
  571. appointData: [],
  572. appointTotalAll: 0,
  573. appointPag: {
  574. page: 1,
  575. size: 10
  576. },
  577. masterPag: {
  578. page: 1,
  579. size: 10
  580. },
  581. defaultFormList: [],
  582. titleFiledResult: 0,
  583. examinForm: this.$form.createForm(this),
  584. masterTimes: [] // 选择素材的时间选择
  585. };
  586. },
  587. watch: {
  588. defaultFormList: {
  589. deep: true,
  590. handler(n, o) {
  591. const result = [];
  592. this.defaultFormList = n;
  593. this.$nextTick(() => {
  594. this.defaultFormList.forEach(item => {
  595. if (item.value) {
  596. result.push(item.value);
  597. }
  598. this.examinForm.setFieldsValue({[item.name]: item.value});
  599. });
  600. this.titleFiledResult = result;
  601. });
  602. }
  603. }
  604. },
  605. created() {
  606. this.form = this.$form.createForm(this);
  607. },
  608. mounted() {
  609. this.handleGetCurrencyList();
  610. this.handleGetProjectList();
  611. this.handleGetCreativeWord();
  612. },
  613. methods: {
  614. ...mapGetters(['nickname', 'avatar', 'userInfo']),
  615. handleRefreshMaster() {
  616. this.projectModelValue = '';
  617. this.masterTimes = [];
  618. this.viedoCheckValue = [];
  619. this.hendleMaterialInfo();
  620. },
  621. handleAllChecked() {
  622. this.viedoCheckValue = this.viedoDefaultList.map(item => item.id);
  623. },
  624. filterOption(input, option) {
  625. return (
  626. option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
  627. );
  628. },
  629. handleGetProjectList() {
  630. getAction('/ctop/projectMember/bytedanceProjectParticipateInList').then(result => {
  631. if (result.code === 0) {
  632. this.optimizationOption = result.result;
  633. }
  634. else {
  635. this.$message.error(result.message);
  636. }
  637. }).catch(error => {
  638. console.log(error, 'eeee');
  639. });
  640. },
  641. hendleMaterialInfo() {
  642. const paramsData = {
  643. projectId: this.projectModelValue,
  644. startDate: this.masterTimes[0],
  645. endDate: this.masterTimes[1],
  646. pageNo: this.masterPag.page,
  647. pageSize: this.masterPag.size
  648. };
  649. getAction('/ctop/materialInfo/listV2', paramsData).then(result => {
  650. if (result.code === 0) {
  651. this.viedoDefaultList = result.data.list;
  652. this.materTotalAll = result.data.total;
  653. }
  654. else {
  655. this.$message.error(result.message);
  656. }
  657. }).catch(error => {
  658. console.log(error, 'eeee');
  659. });
  660. },
  661. handleTabsChange(e) {
  662. const page = {
  663. page: 1,
  664. size: 10
  665. };
  666. this.currencyPag = page;
  667. this.appointPag = page;
  668. this.configForm = {
  669. acountId: '',
  670. num: '',
  671. adConvertId: '',
  672. launchDateRange: []
  673. };
  674. if (e === '1') {
  675. this.handleGetCurrencyList();
  676. }
  677. else if (e === '2') {
  678. this.handleGetAppointList();
  679. }
  680. },
  681. handleGetCurrencyList() {
  682. let paramsData = {
  683. accountId: this.configForm.acountId,
  684. keyWord: this.configForm.num,
  685. userId: this.userInfo().id,
  686. startTime: this.configForm.launchDateRange[0],
  687. endTime: this.configForm.launchDateRange[0],
  688. pageNo: this.currencyPag.page,
  689. pageSize: this.currencyPag.size
  690. };
  691. getAction(urlAcount + '/bytedance-api/advertiser/bytedanceGeneralCopywriter/queryPageListByText', paramsData).then(result => {
  692. if (result.code === 0) {
  693. this.currencyData = result.result.list;
  694. this.currencyTotalAll = result.result.total;
  695. }
  696. else {
  697. this.currencyData = [];
  698. this.currencyTotalAll = 0;
  699. this.$message.error(result.message);
  700. }
  701. }).catch(error => {
  702. console.log(error, 'eeee');
  703. });
  704. },
  705. handleGetAppointList() {
  706. let paramsData = {
  707. projectId: this.configForm.adConvertId,
  708. userId: this.userInfo().id,
  709. keyWord: this.configForm.num,
  710. startTime: this.configForm.launchDateRange[0],
  711. endTime: this.configForm.launchDateRange[0],
  712. pageNo: this.appointPag.page,
  713. pageSize: this.appointPag.size
  714. };
  715. getAction(urlAcount + '/bytedance-api/ctop/bytedanceVideoSlogenInfo/queryPageListByText', paramsData).then(result => {
  716. if (result.code === 0) {
  717. this.appointData = result.result.list;
  718. this.appointTotalAll = result.result.total;
  719. }
  720. else {
  721. this.appointData = [];
  722. this.appointTotalAll = [];
  723. this.$message.error(result.message);
  724. }
  725. }).catch(error => {
  726. console.log(error, 'eeee');
  727. });
  728. },
  729. handleChange(info) {
  730. const isZip = info.file.name.indexOf('xlsx') !== -1 || info.file.name.indexOf('xls') !== -1;
  731. if (!isZip) {
  732. this.$message.error('上传模板只能是 xls、xlsx格式!');
  733. return;
  734. }
  735. this.fileList = info.fileList;
  736. },
  737. handleSearchMaster() {
  738. this.hendleMaterialInfo();
  739. },
  740. handleSelectTimeChange(date, dateString) {
  741. this.masterTimes = dateString;
  742. },
  743. handleDelAlone(data) {
  744. this.modalSelectMaterial = this.modalSelectMaterial.filter(item => item.id !== data.id);
  745. },
  746. handleMasterPageChange(current, pageSize) {
  747. this.masterPag = {
  748. page: current = pageSize !== this.masterPag.size ? 1 : current,
  749. size: pageSize
  750. };
  751. this.hendleMaterialInfo();
  752. },
  753. handleSelectMaterial() {
  754. this.hendleMaterialInfo();
  755. this.visibleMatemal = true;
  756. },
  757. // 选择素材的取消按钮
  758. handleCancelAll() {
  759. this.projectModelValue = '';
  760. this.masterTimes = [];
  761. this.viedoCheckValue = [];
  762. this.visibleMatemal = false;
  763. },
  764. // 选择素材的确认按钮
  765. handleOkShow() {
  766. const defaultList = this.viedoDefaultList;
  767. const defaultCheckValue = this.viedoCheckValue;
  768. let finallyIds = new Set();
  769. let changeSelectMaterData = defaultList.filter(item => {
  770. if (defaultCheckValue.includes(item.id)) {
  771. return item;
  772. }
  773. });
  774. finallyIds = this.modalSelectMaterial.concat(changeSelectMaterData).map(item => item.id);
  775. this.modalSelectMaterial = defaultList.filter(item => {
  776. if (finallyIds.includes(item.id)) {
  777. return item;
  778. }
  779. });
  780. this.handleCancelAll();
  781. },
  782. handleFormLayoutChange(e) {
  783. const defaultValue = e.target.value;
  784. this.copywrittypeName = defaultValue;
  785. if (defaultValue === 'horizontal') {
  786. this.modalSelectMaterial = [];
  787. this.defaultFormList = [];
  788. }
  789. else if (defaultValue === 'vertical') {
  790. this.advertisingAccount = [];
  791. this.fileList = [];
  792. const defaultList = this.adNameTags;
  793. for (let i = 0; i < 3; i++) {
  794. const randomNum = new Date().getTime() + Math.ceil(Math.random() * 1000);
  795. this.defaultFormList.push({
  796. id: randomNum,
  797. name: 'username' + randomNum,
  798. value: '',
  799. lenSize: 0,
  800. tabStatus: 'alone',
  801. defaultTagsList: defaultList,
  802. updateTagsList: defaultList.slice(0, 4)
  803. });
  804. }
  805. }
  806. },
  807. handleFormInputChang(e, field, formId) {
  808. const changeFiled = [];
  809. this.defaultFormList.forEach(item => {
  810. if (item.id === formId) {
  811. item.value = e.target.value;
  812. }
  813. });
  814. this.defaultFormList.forEach(item => {
  815. if (item.value) {
  816. changeFiled.push(item.value);
  817. }
  818. });
  819. this.$nextTick(() => {
  820. const dynamicWordPackIds = [];
  821. let finallyLenList = this.handleJudgeExec(this.examinForm.getFieldsValue()[field]);
  822. let updateFinallyResult = this.adNameTags.filter(item => finallyLenList.includes(item.name)).map(val => val.name);
  823. const inputDefaultLen = this.defaultFormList.filter(item => item.id === formId)[0].value.length;
  824. let tagsLen = updateFinallyResult.length * 2;
  825. let tagsSureLen = 0;
  826. let resultSelectSize = 0;
  827. this.adNameTags.forEach(item => {
  828. updateFinallyResult.forEach(val => {
  829. if (item.name === val) {
  830. tagsSureLen += item.maxWordLen;
  831. dynamicWordPackIds.push(item.creativeWordId);
  832. }
  833. });
  834. });
  835. updateFinallyResult.forEach(item => {
  836. tagsLen += item.length;
  837. });
  838. resultSelectSize = inputDefaultLen - tagsLen + tagsSureLen;
  839. this.defaultFormList.forEach(item => {
  840. if (item.id === formId) {
  841. item.lenSize = resultSelectSize;
  842. item.wordPackId = dynamicWordPackIds;
  843. }
  844. });
  845. this.titleFiledResult = changeFiled;
  846. });
  847. },
  848. handleJudgeExec(item) {
  849. let re = /\{(.+?)\}/g;
  850. let array = [];
  851. let temp;
  852. while ((temp = re.exec(item))) {
  853. array.push(temp[1]);
  854. };
  855. return array;
  856. },
  857. // 点击获取光标位置进行字段插入
  858. handleGetChangeAll(item, field, formId) {
  859. let node = document.getElementById(field);
  860. let startPos = node.selectionStart; // input 第0个字符到选中的字符
  861. let endPos = node.selectionEnd; // 选中的字符到最后的字符
  862. let txt = node.value;
  863. this.$nextTick(() => {
  864. let finallyLenList = this.handleJudgeExec(txt);
  865. let updateFinallyResult = this.adNameTags.filter(item => finallyLenList.includes(item.name)).map(val => val.name);
  866. if (updateFinallyResult.length >= 2) {
  867. this.$message.error('最多选择两个词包');
  868. return;
  869. }
  870. if (startPos === 0 || endPos === 0) {
  871. txt += '{' + item + '}';
  872. this.examinForm.setFieldsValue({[field]: txt});
  873. }
  874. else {
  875. this.examinForm.setFieldsValue({[field]: txt.substring(0, startPos) + '{' + item + '}' + txt.substring(endPos)});
  876. node.selectionStart = startPos + item.length + 6;
  877. node.selectionEnd = startPos + item.length + 6;
  878. }
  879. node.focus();
  880. node.blur();
  881. });
  882. this.$nextTick(() => {
  883. const dynamicWordPackIds = [];
  884. let changeData = this.handleJudgeExec(this.examinForm.getFieldsValue()[field]);
  885. let updateChangeData = this.adNameTags.filter(item => changeData.includes(item.name)).map(val => val.name);
  886. const inputDefaultLen = this.examinForm.getFieldsValue()[field].length;
  887. let tagsLen = updateChangeData.length * 2;
  888. let tagsSureLen = 0;
  889. let resultSelectSize = 0;
  890. this.adNameTags.forEach(item => {
  891. updateChangeData.forEach(val => {
  892. if (item.name === val) {
  893. tagsSureLen += item.maxWordLen;
  894. dynamicWordPackIds.push(item.creativeWordId);
  895. }
  896. });
  897. });
  898. updateChangeData.forEach(item => {
  899. tagsLen += item.length;
  900. });
  901. resultSelectSize = inputDefaultLen - tagsLen + tagsSureLen;
  902. this.defaultFormList.forEach(item => {
  903. if (item.id === formId) {
  904. item.lenSize = resultSelectSize;
  905. item.value = this.examinForm.getFieldsValue()[field];
  906. item.wordPackId = dynamicWordPackIds;
  907. }
  908. });
  909. });
  910. },
  911. validatePass(rule, value, callback) {
  912. this.$nextTick(() => {
  913. let finallyLenList = this.handleJudgeExec(value);
  914. let updateFinallyResult = this.adNameTags.filter(item => finallyLenList.includes(item.name)).map(val => val.name);
  915. let resultSelectSize = 0;
  916. if (updateFinallyResult.length) {
  917. const inputDefaultLen = value.length;
  918. let tagsLen = updateFinallyResult.length * 2;
  919. let tagsSureLen = 0;
  920. this.adNameTags.forEach(item => {
  921. updateFinallyResult.forEach(val => {
  922. if (item.name === val) {
  923. tagsSureLen += item.maxWordLen;
  924. }
  925. });
  926. });
  927. updateFinallyResult.forEach(item => {
  928. tagsLen += item.length;
  929. });
  930. resultSelectSize = inputDefaultLen - tagsLen + tagsSureLen;
  931. }
  932. else {
  933. resultSelectSize = value.length;
  934. }
  935. // {地点}{日3期}{运8营商}{考3{区县}试}{节11555日}
  936. if (resultSelectSize === 0) {
  937. callback(new Error('请输入'));
  938. }
  939. else if (resultSelectSize > 30 || resultSelectSize < 5) {
  940. callback(new Error('创意标题5-30个字'));
  941. }
  942. else if (updateFinallyResult.length > 2) {
  943. callback(new Error('最多选择两个词包'));
  944. }
  945. else {
  946. callback();
  947. }
  948. });
  949. },
  950. handleMoreTagsShow(val, type) {
  951. if (type === 'more') {
  952. this.defaultFormList.forEach(item => {
  953. if (item.id === val) {
  954. item.tabStatus = 'all';
  955. }
  956. });
  957. }
  958. else if (type === 'little') {
  959. this.defaultFormList.forEach(item => {
  960. if (item.id === val) {
  961. item.tabStatus = 'alone';
  962. }
  963. });
  964. }
  965. },
  966. handleUploadWxecl() {
  967. if (!this.advertisingAccount.length) {
  968. this.$message.error('请选择账户');
  969. return;
  970. }
  971. if (!this.fileList.length) {
  972. this.$message.error('请上传文件');
  973. return;
  974. }
  975. let paramsData = new FormData()
  976. paramsData.append('accountId', this.advertisingAccount);
  977. paramsData.append('excelFile', this.fileList[0].originFileObj);
  978. postFileAction(urlAcount + '/bytedance-api/advertiser/bytedanceGeneralCopywriter/loadExcel', paramsData, {
  979. headers: {
  980. 'Content-Type': 'multipart/form-data'
  981. }
  982. }).then(result => {
  983. if (result.code === 0) {
  984. this.$message.success(result.message);
  985. this.controlTypeModel = '1';
  986. this.handleCauseCancel();
  987. this.handleGetCurrencyList();
  988. }
  989. else {
  990. this.$message.error(result.message);
  991. }
  992. }).catch(error => {
  993. console.log(error, 'eeee');
  994. });
  995. },
  996. handleVerticalAdd() {
  997. if (!this.modalSelectMaterial.length) {
  998. this.$message.error('请选择素材');
  999. return;
  1000. }
  1001. if (this.defaultFormList && this.defaultFormList.length < 3) {
  1002. this.$message.error('请至少输入3条标题');
  1003. return;
  1004. }
  1005. let changeSlogan = this.defaultFormList;
  1006. changeSlogan.forEach(item => {
  1007. item.title = item.value;
  1008. item.creative_word_ids = item.wordPackId;
  1009. });
  1010. let paramsData = {
  1011. materialIds: this.modalSelectMaterial.map(item => item.id),
  1012. userId: this.userInfo().id,
  1013. slogans: changeSlogan
  1014. };
  1015. this.examinForm.validateFields(err => {
  1016. if (!err) {
  1017. postAction(urlAcount + '/bytedance-api/ctop/bytedanceVideoSlogenInfo/addList', paramsData).then(result => {
  1018. if (result.code === 0) {
  1019. this.$message.success(result.message);
  1020. this.controlTypeModel = '1';
  1021. this.handleCauseCancel();
  1022. this.handleGetCurrencyList();
  1023. }
  1024. else {
  1025. this.$message.error(result.message);
  1026. }
  1027. }).catch(error => {
  1028. console.log(error, 'eeee');
  1029. });
  1030. }
  1031. });
  1032. },
  1033. handleCauseSure() {
  1034. if (this.copywrittypeName === 'horizontal') {
  1035. this.handleUploadWxecl();
  1036. }
  1037. else if (this.copywrittypeName === 'vertical') {
  1038. this.handleVerticalAdd();
  1039. }
  1040. },
  1041. handleCauseCancel() {
  1042. this.copywrittypeName = 'horizontal';
  1043. this.advertisingAccount = [];
  1044. this.fileList = [];
  1045. this.causeVisible = false;
  1046. this.defaultFormList = [];
  1047. this.modalSelectMaterial = [];
  1048. },
  1049. handleGetCreativeWord() {
  1050. getAction('/ctop/ByteDanceCreativeWordPackage/list').then(result => {
  1051. if (result.code === 0) {
  1052. this.adNameTags = result.result.records;
  1053. }
  1054. else {
  1055. this.$message.error(result.message);
  1056. }
  1057. }).catch(error => {
  1058. console.log(error, 'eeee');
  1059. });
  1060. },
  1061. handleAddOrigin() {
  1062. const randomNum = new Date().getTime() + Math.ceil(Math.random() * 1000);
  1063. this.defaultFormList.push({
  1064. id: randomNum,
  1065. name: 'username' + randomNum,
  1066. value: '',
  1067. lenSize: 0,
  1068. tabStatus: 'alone',
  1069. defaultTagsList: this.adNameTags,
  1070. updateTagsList: this.adNameTags.slice(0, 4)
  1071. });
  1072. },
  1073. handleDelOrigin(list) {
  1074. let formData = this.defaultFormList;
  1075. this.defaultFormList = formData.filter(item => list.id !== item.id);
  1076. },
  1077. handleAddAccountConfig() {
  1078. this.causeVisible = true;
  1079. },
  1080. handleLaunchData(date, dateString) {
  1081. this.configForm.launchDateRange = dateString;
  1082. },
  1083. handleQueryList() {
  1084. const page = {
  1085. page: 1,
  1086. size: 10
  1087. };
  1088. this.currencyPag = page;
  1089. this.appointPag = page;
  1090. if (this.controlTypeModel === '1') {
  1091. this.handleGetCurrencyList();
  1092. }
  1093. else if (this.controlTypeModel === '2') {
  1094. this.handleGetAppointList();
  1095. }
  1096. },
  1097. handleResetList() {
  1098. this.configForm = {
  1099. acountId: '',
  1100. num: '',
  1101. adConvertId: '',
  1102. launchDateRange: []
  1103. };
  1104. const page = {
  1105. page: 1,
  1106. size: 10
  1107. };
  1108. this.currencyPag = page;
  1109. this.appointPag = page;
  1110. if (this.controlTypeModel === '1') {
  1111. this.handleGetCurrencyList();
  1112. }
  1113. else if (this.controlTypeModel === '2') {
  1114. this.handleGetAppointList();
  1115. }
  1116. },
  1117. handleCurrentPage(current, pageSize) {
  1118. this.currencyPag = {
  1119. page: current = pageSize !== this.currencyPag.size ? 1 : current,
  1120. size: pageSize
  1121. };
  1122. this.handleGetCurrencyList();
  1123. },
  1124. handleAppointPage(current, pageSize) {
  1125. this.appointPag = {
  1126. page: current = pageSize !== this.appointPag.size ? 1 : current,
  1127. size: pageSize
  1128. };
  1129. this.handleGetAppointList();
  1130. }
  1131. }
  1132. };
  1133. </script>
  1134. <style lang="less" scoped>
  1135. @import "copy-library";
  1136. </style>