copy-library.vue 53 KB

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