copy-library.vue 47 KB

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