setProjectDirectional.vue 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068
  1. <template>
  2. <div class="setProjectDirectional">
  3. <div class="moduler">
  4. <div v-if="projectInfo.length>0">
  5. <span style="margin-right:8px"> 项目:<strong>{{projectInfo[0].name||''}}</strong></span>
  6. <span style="margin-right:8px"> 推广目的:<strong>{{projectInfo[0].landingType=='APP'?'应用推广':'销售线索收集'||''}}</strong></span>
  7. <span style="margin-right:8px"> 投放媒体:<strong>{{projectInfo[0].deliveryRange=="DEFAULT"?'默认':'穿山甲'||''}}</strong></span>
  8. <span style="margin-right:8px"> 投放方式:
  9. <strong v-if="projectInfo[0].adTarget=='CPA'">优先成本</strong>
  10. <strong v-if="projectInfo[0].adTarget=='COST'">优先跑量</strong>
  11. <strong v-if="projectInfo[0].adTarget=='PUSH'">激进抢量</strong>
  12. </span>
  13. </div>
  14. </div>
  15. <a-form :form="form">
  16. <div class="moduler">
  17. <div class="moduler-title">广告位置</div>
  18. <div class="ad-range">
  19. <div class="row-item">
  20. <div class="hint-item"></div>
  21. <div class="label-item">
  22. <div class="text-item">广告位置</div>
  23. <div class="required-item"></div>
  24. </div>
  25. <div class="input-item">
  26. <a-form-item>
  27. <a-radio-group v-model="adposition" @change="adpositionChange">
  28. <a-radio-button value="smartInventorys" v-if="projectInfo.length>0&&projectInfo[0].deliveryRange=='DEFAULT'">优选广告位</a-radio-button>
  29. <a-radio-button value="inventoryTypes" v-if="projectInfo.length>0&&projectInfo[0].deliveryRange=='DEFAULT'">按媒体指定位置</a-radio-button>
  30. <a-radio-button :value="900000000" v-if="projectInfo.length>0&&projectInfo[0].deliveryRange=='UNION'">穿山甲</a-radio-button>
  31. <!-- <a-radio-button value="sceneInventorys">按场景指定位置</a-radio-button> -->
  32. </a-radio-group>
  33. </a-form-item>
  34. <div style="width: 400px; margin-top: 24px;" class="inventoryTypes" v-show="adposition=='inventoryTypes'">
  35. <div class="inventory-tags-lists-header">
  36. <a-checkbox :indeterminate="indeterminate" :checked="checkAll" @change="onCheckAllChange">
  37. </a-checkbox>
  38. <div class="inventory-tags-lists-name"><strong>APP名称</strong></div>
  39. </div>
  40. <div class="inventory-tags-lists-container">
  41. <a-checkbox-group v-model="checkedList" :options="plainOptions" @change="onChange" />
  42. </div>
  43. </div>
  44. <div style="width: 400px; margin-top: 24px;" v-show="adposition=='sceneInventorys'">
  45. <div class="inventory-tags-lists-header">
  46. <div class="inventory-tags-lists-name" style="padding-left:15px"><strong>位置选择</strong></div>
  47. </div>
  48. <div class="inventory-tags-lists-container">
  49. <a-radio-group v-model=sceneInventory>
  50. <a-radio :style="radioStyle" value="VIDEO_SCENE">沉浸式竖版视频场景广告位</a-radio>
  51. <a-radio :style="radioStyle" value="FEED_SCENE">信息流场景广告位</a-radio>
  52. <a-radio :style="radioStyle" value="TAIL_SCENE">视频后贴和尾帧场景广告位</a-radio>
  53. </a-radio-group>
  54. </div>
  55. </div>
  56. </div>
  57. </div>
  58. <div class="row-item" v-if="projectInfo.length>0&&projectInfo[0].deliveryRange=='UNION'">
  59. <div class="hint-item"></div>
  60. <div class="label-item">
  61. <div class="text-item">投放形式</div>
  62. <div class="required-item"></div>
  63. </div>
  64. <div class="input-item">
  65. <a-form-item>
  66. <a-radio-group v-model="unionVideoType">
  67. <a-radio-button value="REWARDED_VIDEO">
  68. 激励视频
  69. <a-tooltip>
  70. <template slot="title">特定场景下用户通过观看视频广告以换取游戏/应用内虚拟奖励的广告</template>
  71. <a-icon type="question-circle" />
  72. </a-tooltip>
  73. </a-radio-button>
  74. <a-radio-button value="ORIGINAL_VIDEO">原生</a-radio-button>
  75. </a-radio-group>
  76. </a-form-item>
  77. </div>
  78. </div>
  79. </div>
  80. </div>
  81. <div class="moduler">
  82. <div class="moduler-title">用户定向</div>
  83. <div class="ad-range">
  84. <div class="row-item">
  85. <div class="hint-item"></div>
  86. <div class="label-item">
  87. <div class="text-item">地域</div>
  88. <div class="required-item"></div>
  89. </div>
  90. <div class="input-item">
  91. <a-form-item>
  92. <a-radio-group v-model="district" @change="cityChange">
  93. <a-radio-button value="NONE">不限</a-radio-button>
  94. <a-radio-button value="CITY">按省市</a-radio-button>
  95. <a-radio-button value="COUNTY">按区县</a-radio-button>
  96. </a-radio-group>
  97. </a-form-item>
  98. <div class="region" v-show="district!='NONE'">
  99. <!-- 省市 -->
  100. <div class="provincyCity" v-if="district=='CITY'">
  101. <linkMultiSelect title='省份' :listArr='[]' :maxLayers='2' :listUrl='regionCityListUrl' @getSelectedArr='getSelectedCityArr'/>
  102. </div>
  103. <!-- 区县 -->
  104. <div class="district" v-else-if="district=='COUNTY'">
  105. <linkMultiSelect title='省份' :listArr='[]' :maxLayers='3' :listUrl='regionCityListUrl' @getSelectedArr='getSelectedCountyArr'/>
  106. </div>
  107. </div>
  108. </div>
  109. </div>
  110. <div class="row-item">
  111. <div class="hint-item"></div>
  112. <div class="label-item">
  113. <div class="text-item">性别</div>
  114. <div class="required-item"></div>
  115. </div>
  116. <div class="input-item">
  117. <a-form-item>
  118. <a-radio-group v-decorator="['gender', {initialValue:'NONE' }]" >
  119. <a-radio-button value="NONE">不限</a-radio-button>
  120. <a-radio-button value="GENDER_MALE">男</a-radio-button>
  121. <a-radio-button value="GENDER_FEMALE">女</a-radio-button>
  122. </a-radio-group>
  123. </a-form-item>
  124. </div>
  125. </div>
  126. <div class="row-item">
  127. <div class="hint-item"></div>
  128. <div class="label-item">
  129. <div class="text-item">年龄</div>
  130. <div class="required-item"></div>
  131. </div>
  132. <div class="input-item">
  133. <a-form-item>
  134. <radioCheck :checkArr='ageArr' @getSonValue='getAgeSelect' />
  135. </a-form-item>
  136. </div>
  137. </div>
  138. <div class="row-item">
  139. <div class="hint-item"></div>
  140. <div class="label-item">
  141. <div class="text-item">自定义人群</div>
  142. <div class="required-item"></div>
  143. </div>
  144. <div class="input-item">
  145. <a-form-item>
  146. <a-radio-group v-model="customCrowd" >
  147. <a-radio-button value="NONE">不限</a-radio-button>
  148. <a-radio-button value="CUSTOMt_CROWED">自定义人群</a-radio-button>
  149. </a-radio-group>
  150. </a-form-item>
  151. <div class="dingxiang_paichu" v-if="customCrowd=='CUSTOMt_CROWED'" style="width:60%">
  152. <a-tabs default-active-key="1" @change="retargetTabChange" >
  153. <a-tab-pane key="1" tab="定向池" >
  154. <a-table
  155. :columns="retargetColumns"
  156. :row-key="record => record.key"
  157. :data-source="retargetDataAll"
  158. :loading="loading"
  159. style="width:100%;margin:15px 0"
  160. :pagination='false'
  161. @change="retargetTableChange"
  162. :scroll="{ y: 250 }"
  163. :row-selection="rowSelection"
  164. bordered
  165. >
  166. <template slot="name" slot-scope="name"> {{ name }} </template>
  167. </a-table>
  168. </a-tab-pane>
  169. <a-tab-pane key="2" tab="排除池" >
  170. <a-table
  171. :columns="retargetColumns"
  172. :row-key="record => record.key"
  173. :data-source="retargetDataAll"
  174. :loading="loading"
  175. style="width:100%;margin:15px 0"
  176. :pagination='false'
  177. @change="retargetTableChange"
  178. :scroll="{ y: 250 }"
  179. :row-selection="rowSelection2"
  180. bordered
  181. >
  182. <template slot="name" slot-scope="name"> {{ name }} </template>
  183. </a-table>
  184. </a-tab-pane>
  185. </a-tabs>
  186. </div>
  187. </div>
  188. </div>
  189. <div class="row-item">
  190. <div class="hint-item"></div>
  191. <div class="label-item">
  192. <div class="text-item">智能放量</div>
  193. <div class="required-item"></div>
  194. </div>
  195. <div class="input-item">
  196. <a-form-item>
  197. <a-radio-group v-model="autoExtendEnabled" >
  198. <a-radio-button :value="0">不启用</a-radio-button>
  199. <a-radio-button :value="1">启用</a-radio-button>
  200. </a-radio-group>
  201. </a-form-item>
  202. <!-- <span class="tishi"><a-icon type="exclamation-circle" class="tubiao" />智能放量不支持受众预估</span> -->
  203. <div v-if="autoExtendEnabled==1" class="deviceBrand">
  204. <singleLayersSelecte title='可放开定向' :listArr='autoExtendOptions' :checked='autoExtendTargetsChecked' @getCheckedList='getAutoExtendEnabled'/>
  205. </div>
  206. </div>
  207. </div>
  208. <div class="row-item" v-if="projectInfo.length>0&&projectInfo[0].deliveryRange=='UNION'">
  209. <div class="hint-item"></div>
  210. <div class="label-item">
  211. <div class="text-item">精选流量</div>
  212. <div class="required-item"></div>
  213. </div>
  214. <div class="input-item">
  215. <a-form-item>
  216. <a-radio-group v-decorator="['superiorPopularityType', { initialValue:'NONE'}]">
  217. <a-radio-button value="NONE">不限</a-radio-button>
  218. <!-- <a-radio-button value="APP " :disabled='getFormData("deliveryRange")!="UNION"'>应用软件精选</a-radio-button> -->
  219. <a-radio-button value="GAME" >游戏精选</a-radio-button>
  220. </a-radio-group>
  221. </a-form-item>
  222. </div>
  223. </div>
  224. </div>
  225. </div>
  226. </a-form>
  227. <!-- 当前账户 -->
  228. <div class="moduler">
  229. <div class="adName">
  230. <span>当前账户:</span>
  231. <div class="nameList">
  232. <strong v-for="item in LHKaccountInfo" :key="item.value" class="item">{{item.title+'('+item.value+')'}}</strong>
  233. </div>
  234. </div>
  235. </div>
  236. <!-- 操作 -->
  237. <div class="moduler">
  238. <!-- <div class="moduler-title">计划名称</div> -->
  239. <div class="opt">
  240. <a-button type="default" style="margin-right:15px" @click="goBack">取消</a-button>
  241. <a-button type="primary" @click="goNext" :loading="goNextloading">下一步</a-button>
  242. </div>
  243. </div>
  244. <!-- 投放链接 -->
  245. <div class="infoModal">
  246. <a-modal v-model="visible" title="提示" @ok="handleOk" :keyboard='false' :maskClosable='false'>
  247. <ul>
  248. <li v-for="(item,index) in errorInfo" :key="index">
  249. <span>账户{{LHKaccountInfo[index].title}}:</span>{{item.message || '定向设置成功'}}
  250. </li>
  251. </ul>
  252. <template slot="footer">
  253. <a-button key="back" @click="handleCancel">
  254. 返回本页
  255. </a-button>
  256. <a-button key="submit" type="primary" @click="handleOk">
  257. 下一步
  258. </a-button>
  259. </template>
  260. </a-modal>
  261. </div>
  262. </div>
  263. </template>
  264. <script>
  265. import moment from 'moment'
  266. import { getAction, postAction, downFile, downFilePost } from '@/api/manage'
  267. import radioCheck from './radioCheck';
  268. import linkMultiSelect from '../BatchCreate/linkMultiSelect'
  269. import singleLayersSelecte from '../BatchCreate/singleLayerSelecte'
  270. import qs from 'qs'
  271. var str = ""
  272. for (let i = 0; i < 7*48; i++) {
  273. str+='0'
  274. }
  275. let ageArr=[
  276. {
  277. value:'',
  278. title:'不限',
  279. checked:false,
  280. },
  281. {
  282. value:'AGE_BETWEEN_18_23',
  283. title:' 18-23岁',
  284. checked:false,
  285. },
  286. {
  287. value:'AGE_BETWEEN_24_30',
  288. title:'24-30岁',
  289. checked:false,
  290. },
  291. {
  292. value:'AGE_BETWEEN_31_40',
  293. title:'31-40岁',
  294. checked:false,
  295. },
  296. {
  297. value:'AGE_BETWEEN_41_49',
  298. title:'41-49岁',
  299. checked:false,
  300. },
  301. {
  302. value:'AGE_ABOVE_50',
  303. title:'大于等于50岁',
  304. checked:false,
  305. },
  306. ]
  307. let autoExtendOptions=[
  308. {
  309. label:'地域',
  310. value:'REGION',
  311. },
  312. {
  313. label:'性别',
  314. value:'GENDER',
  315. },
  316. {
  317. label:'年龄',
  318. value:'AGE',
  319. },
  320. {
  321. label:'行为兴趣',
  322. value:'INTEREST_ACTION',
  323. },
  324. {
  325. label:'自定义人群',
  326. value:'CUSTOM_AUDIENCE',
  327. },
  328. ]
  329. let retargetColumns=[
  330. {
  331. title: '人群包',
  332. dataIndex: 'name',
  333. sorter: true,
  334. width: '40%',
  335. scopedSlots: { customRender: 'name' },
  336. },
  337. {
  338. title: '属性',
  339. dataIndex: 'tag',
  340. // filters: [
  341. // { text: '自定义', value: 'male' },
  342. // { text: '系统推荐', value: 'female' },
  343. // { text: '第三方', value: 'femal' },
  344. // ],
  345. width: '20%',
  346. },
  347. {
  348. title: '所属账号',
  349. dataIndex: 'accountName',
  350. sorter: true,
  351. width: '40%',
  352. scopedSlots: { customRender: 'accountName' },
  353. },
  354. ]
  355. const plainOptions = [{
  356. value: 1,
  357. label: '今日头条'
  358. },
  359. {
  360. value: 10001,
  361. label: '西瓜视频'
  362. },
  363. {
  364. value: 40001,
  365. label: '抖音'
  366. },
  367. {
  368. value: 30001,
  369. label: '抖音火山版'
  370. },
  371. {
  372. value: 900000000,
  373. label: '穿山甲'
  374. },
  375. ];
  376. export default {
  377. components: {
  378. radioCheck,
  379. linkMultiSelect,
  380. singleLayersSelecte
  381. },
  382. data() {
  383. return {
  384. projectInfo:[],
  385. LHKaccountInfo:[],
  386. form: this.$form.createForm(this),
  387. adposition:'smartInventorys',
  388. unionVideoType:'REWARDED_VIDEO',
  389. district:'NONE',
  390. sceneInventory:'',
  391. checkedList: [],
  392. indeterminate: false,
  393. checkAll: false,
  394. plainOptions,
  395. // 定向的参数
  396. regionValue:'NONE',
  397. ageArr,//受众年龄
  398. city:[],
  399. age:[],
  400. regionCityListUrl:'ctop/bytedanceAreaInfo/list',
  401. regionCountyListUrl:'ctop/bytedanceAreaInfo/list',
  402. // 自定义人群
  403. // 自定义人群参数
  404. retargetColumns,
  405. retargetData:[],
  406. retargetDataAll:[],
  407. loading:false,
  408. customCrowd:'NONE',//自定义人群 选择的值
  409. selectedRowKeys:[],
  410. incluedSelectedRowKeys:[],
  411. incluedSelectedKeys:[],
  412. excludeSelectedKeys:[],
  413. excludeSelectedRowKeys:[],
  414. autoExtendEnabled:0,//智能放量是否开启
  415. autoExtendOptions,//智能投放可选定向数组
  416. autoExtendTargets:[],//智能放量开启后的选择数据----------需传递的参数
  417. autoExtendTargetsChecked:[],
  418. radioStyle: {
  419. display: 'block',
  420. height: '30px',
  421. lineHeight: '30px',
  422. padding: '0 15px'
  423. },
  424. goNextloading:false,
  425. goPlanShowloading:false,
  426. dateRange: [moment(), moment()],
  427. visible:false,
  428. errorInfo:[],
  429. validationRules: {
  430. url: [
  431. {
  432. required: true,
  433. validator: this.validateURL,
  434. },
  435. ],
  436. name:[{
  437. required: true,
  438. validator: this.validateName,
  439. }],
  440. bid:[{
  441. required: true,
  442. message:'出价信息必须填写',
  443. // validator: this.validateBid,
  444. }],
  445. roi:[{
  446. required: true,
  447. message:'ROI系数必须填写',
  448. // validator: this.validateBid,
  449. }],
  450. },
  451. currentConvertTypes:[],
  452. convertIds:[],
  453. }
  454. },
  455. watch: {
  456. },
  457. computed: {
  458. hasSelected() {
  459. return this.selectedRowKeys.length > 0;
  460. },
  461. rowSelection() {
  462. return {
  463. // selectedRowKeys: this.incluedSelectedRowKeys,
  464. onChange: (selectedRowKeys, selectedRows) => {
  465. console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
  466. this.incluedSelectedRowKeys = selectedRowKeys;
  467. this.incluedSelectedKeys=selectedRows
  468. },
  469. getCheckboxProps: record => ({
  470. props: {
  471. disabled: this.excludeSelectedRowKeys.indexOf(record.key)>-1, // Column configuration not to be checked
  472. name: record.name,
  473. },
  474. }),
  475. };
  476. },
  477. rowSelection2() {
  478. return {
  479. // selectedRowKeys: this.excludeSelectedRowKeys,
  480. onChange: (selectedRowKeys, selectedRows) => {
  481. // console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
  482. // this.selectedRowKeys = selectedRowKeys;
  483. this.excludeSelectedRowKeys = selectedRowKeys;
  484. this.excludeSelectedKeys=selectedRows
  485. },
  486. getCheckboxProps: record => ({
  487. props: {
  488. disabled: this.incluedSelectedRowKeys.indexOf(record.key)>-1, // Column configuration not to be checked
  489. name: record.name,
  490. },
  491. }),
  492. };
  493. },
  494. },
  495. methods: {
  496. adpositionChange(){
  497. if(this.adposition!='inventoryTypes'){
  498. this.checkedList=[];
  499. this.indeterminate=false;
  500. this.checkAll=false;
  501. }
  502. },
  503. cityChange(){
  504. this.city=[];
  505. },
  506. onChange(checkedList) {
  507. this.indeterminate = !!checkedList.length && checkedList.length < plainOptions.length;
  508. this.checkAll = checkedList.length === plainOptions.length;
  509. },
  510. onCheckAllChange(e) {
  511. let valueOption = [];
  512. this.plainOptions.forEach((item) => {
  513. valueOption.push(item.value)
  514. })
  515. Object.assign(this, {
  516. checkedList: e.target.checked ? valueOption : [],
  517. indeterminate: false,
  518. checkAll: e.target.checked,
  519. });
  520. },
  521. // 自定义人群的--同时定向排除tab切换事件
  522. retargetTabChange(tabkey){
  523. console.log(tabkey)
  524. this.retargetDataAll=[];
  525. this.loading=true;
  526. this.LHKaccountInfo.forEach(item=>{
  527. getAction('/ctop/audience/list',{
  528. accountId:item.value
  529. }).then((res)=>{
  530. // console.log(res)
  531. this.loading=false;
  532. if(res.success){
  533. res.data.forEach((ele)=>{
  534. ele.key=item.value+'_'+ele.custom_audience_id
  535. ele.id= ele.custom_audience_id
  536. ele.accountName=item.title
  537. ele.accountId=item.value
  538. })
  539. // this.retargetData=res.data;
  540. this.retargetDataAll=[...this.retargetDataAll,...res.data];
  541. }
  542. })
  543. })
  544. },
  545. onSelectChange(selectedRowKeys) {
  546. // console.log('selectedRowKeys changed: ', selectedRowKeys);
  547. this.selectedRowKeys = selectedRowKeys;
  548. },
  549. // 自定义人群的改变
  550. retargetTableChange(pagination, filters, sorter){
  551. // console.log(pagination);
  552. },
  553. //获取选中的城市
  554. getSelectedCityArr(val){
  555. // console.log(val);
  556. this.city=[];
  557. this.city=val;
  558. },
  559. // 获取选中的区县
  560. getSelectedCountyArr(val){
  561. // console.log(val)
  562. this.city=[];
  563. this.city=val;
  564. },
  565. //获取选中的年龄段
  566. getAgeSelect(val){
  567. // console.log(val)
  568. if(val.length==1&&val[0]==""){
  569. this.age=[]
  570. }else{
  571. this.age=val;
  572. }
  573. },
  574. //获取智能放量定向的值
  575. getAutoExtendEnabled(val){
  576. // console.log(val)
  577. this.autoExtendTargets=[];
  578. this.autoExtendTargets.push(...val)
  579. },
  580. callback(val) {
  581. console.log(val);
  582. },
  583. handleOk(e) {
  584. this.visible=false;
  585. this.$router.push({path:'/LaunchHousekeeper/setProjectCreate'})
  586. },
  587. handleCancel(e) {
  588. this.visible = false;
  589. },
  590. // 直达链接是否启用
  591. useOpenUrlChange(){
  592. this.form.setFieldsValue({
  593. openUrl:''
  594. })
  595. },
  596. //获取表单的某一个属性值
  597. getFormData(className) {
  598. return this.form.getFieldValue(className)
  599. },
  600. dateChange(date, dateString) {
  601. // console.log(date,dateString)
  602. this.form.getFieldDecorator('startTime')
  603. this.form.getFieldDecorator('endTime')
  604. this.form.setFieldsValue({
  605. startTime: date[0].format('YYYY-MM-DD HH:mm'),
  606. endTime: date[1].format('YYYY-MM-DD HH:mm'),
  607. })
  608. },
  609. // 验证网址
  610. IsURL(res) {
  611. // var strRegex = /^([hH][tT]{2}[pP]:\/\/|[hH][tT]{2}[pP][sS]:\/\/|www\.)(([A-Za-z0-9-~]+)\.)+([A-Za-z0-9-~\/])+$/
  612. var strRegex = /^([hH][tT]{2}[pP]:\/\/|[hH][tT]{2}[pP][sS]:\/\/)(([A-Za-z0-9-~]+)\.)+([A-Za-z0-9-~\/])+(.+[A-Za-z0-9-~\/])+$/
  613. var re = new RegExp(strRegex)
  614. // console.log(re.test(res))
  615. if (re.test(res)) {
  616. return true
  617. } else {
  618. return false
  619. }
  620. },
  621. validateURL(rule, value, callback) {
  622. // console.log(rule, value, callback);
  623. if (this.IsURL(value)) {
  624. callback()
  625. } else if (value && !this.IsURL(value)) {
  626. callback('链接地址无法访问,请正确输入')
  627. } else {
  628. callback('链接必须填写')
  629. }
  630. },
  631. validateName(rule, value, callback){
  632. // console.log(rule, value, callback);
  633. if (value) {
  634. callback()
  635. } else {
  636. callback('应用包名称必须填写')
  637. }
  638. },
  639. validateBid(rule, value, callback){
  640. // console.log(rule, value, callback);
  641. if (value) {
  642. callback()
  643. } else {
  644. callback('出价必须填写')
  645. }
  646. },
  647. goBack() {
  648. this.$router.replace('/modules/LaunchHousekeeper/LaunchHousekeeperList')
  649. this.$bus.$emit('remove', '/LaunchHousekeeper/setProjectDirectional')
  650. },
  651. // 保存并新建创意
  652. goNext() {
  653. this.$nextTick(()=>{
  654. this.form.validateFields((err, values) => {
  655. if (!err) {
  656. console.log('Received values of form: ', values)
  657. if(this.district!='NONE'){
  658. values.district=this.district
  659. }
  660. console.log(this.excludeSelectedKeys,this.incluedSelectedKeys)
  661. this.goNextloading=true;
  662. if(this.adposition!='inventoryTypes'){
  663. this.checkedList=[];
  664. }
  665. if(this.projectInfo.length>0&&this.projectInfo[0].deliveryRange=='UNION'){
  666. this.checkedList=[];
  667. this.checkedList.push(900000000)
  668. }
  669. let params=[];
  670. params=this.projectInfo.map((item,index)=>{
  671. item.retargetingTagsExclude=[];
  672. item.retargetingTagsInclude=[];
  673. this.excludeSelectedKeys.forEach(ele=>{
  674. if(ele.accountId==item.accountId){
  675. item.retargetingTagsExclude.push(ele.id)
  676. }
  677. })
  678. this.incluedSelectedKeys.forEach(ele=>{
  679. if(ele.accountId==item.accountId){
  680. item.retargetingTagsInclude.push(ele.id)
  681. }
  682. })
  683. let city=this.city.map(item=>{
  684. return item*1
  685. })
  686. return {
  687. ...item,
  688. unionVideoType:this.unionVideoType,
  689. inventoryType:this.checkedList,
  690. audience:{
  691. age:this.age,
  692. city,
  693. ...values,
  694. retargetingTagsExclude:item.retargetingTagsExclude,
  695. retargetingTagsInclude:item.retargetingTagsInclude,
  696. autoExtendEnabled:this.autoExtendEnabled,
  697. autoExtendTargets:this.autoExtendTargets,
  698. inventoryType:this.checkedList,
  699. district:this.district=='NONE'?'':this.district,
  700. }
  701. }
  702. })
  703. console.log(params)
  704. postAction('/adlab/Project/setAudience', params).then((res) => {
  705. console.log(res)
  706. if (res.success) {
  707. this.goNextloading=false;
  708. if(res.result){
  709. this.errorInfo=res.result;
  710. this.visible=true;
  711. let projectInfo=[]
  712. res.result.forEach(item=>{
  713. if(item.code==0){
  714. projectInfo.push(item)
  715. }
  716. })
  717. sessionStorage.setItem('projectInfo',JSON.stringify(projectInfo))
  718. }
  719. } else {
  720. this.goNextloading=false;
  721. this.$message.error('网络开小差了,等会再试试')
  722. }
  723. })
  724. }else{
  725. this.$message.error('请正确填写必填项目')
  726. }
  727. })
  728. })
  729. },
  730. },
  731. mounted() {
  732. this.$bus.$emit('remove', '/LaunchHousekeeper/setProjectConvert')
  733. let projectInfo=sessionStorage.getItem('projectInfo');
  734. if(projectInfo){
  735. this.projectInfo=JSON.parse(projectInfo)
  736. }
  737. let LHKaccountInfo=sessionStorage.getItem('LHKaccountInfo');
  738. if(LHKaccountInfo){
  739. this.LHKaccountInfo=JSON.parse(LHKaccountInfo)
  740. }
  741. this.LHKaccountInfo.forEach(item=>{
  742. getAction('/ctop/audience/list',{
  743. accountId:item.value
  744. }).then((res)=>{
  745. // console.log(res)
  746. this.loading=false;
  747. if(res.success){
  748. res.data.forEach((ele)=>{
  749. ele.key=item.value+'_'+ele.custom_audience_id
  750. ele.id= ele.custom_audience_id
  751. ele.accountName=item.title
  752. ele.accountId=item.value
  753. })
  754. // this.retargetData=res.data;
  755. this.retargetDataAll=[...this.retargetDataAll,...res.data];
  756. }
  757. })
  758. })
  759. if(this.projectInfo.length>0&&this.projectInfo[0].deliveryRange=='UNION'){
  760. this.checkedList=[];
  761. this.checkedList.push(900000000)
  762. this.adposition=900000000
  763. }
  764. },
  765. }
  766. </script>
  767. <style lang="scss">
  768. .setProjectDirectional{
  769. .ant-btn-danger {
  770. background-color: #ff4d4f !important;
  771. }
  772. }
  773. .ant-tooltip-inner,
  774. .ant-tooltip,
  775. .ant-tooltip-arrow::before {
  776. background-color: #fff;
  777. color: #333;
  778. }
  779. .ant-tooltip-inner {
  780. span {
  781. display: block;
  782. }
  783. }
  784. .ant-tooltip {
  785. max-width: 450px;
  786. }
  787. .setProjectDirectional {
  788. .ant-radio-button-wrapper {
  789. min-width: 80px;
  790. text-align: center;
  791. }
  792. .ant-form-item {
  793. -webkit-box-sizing: border-box;
  794. box-sizing: border-box;
  795. margin: 0;
  796. padding: 0;
  797. color: rgba(0, 0, 0, 0.65);
  798. font-size: 14px;
  799. font-variant: tabular-nums;
  800. line-height: 1.5;
  801. list-style: none;
  802. -webkit-font-feature-settings: 'tnum';
  803. font-feature-settings: 'tnum';
  804. vertical-align: top;
  805. }
  806. .directedBody {
  807. .ant-form-item {
  808. margin-bottom: 20px;
  809. }
  810. }
  811. .ant-checkbox-group-item {
  812. display: block;
  813. padding: 5px 15px;
  814. }
  815. .inventoryTypes{
  816. .ant-checkbox-wrapper,
  817. .ant-checkbox-group-item {
  818. display: block;
  819. padding: 5px 15px;
  820. }
  821. .ant-checkbox-wrapper:first-child {
  822. padding: 0 15px 5px;
  823. }
  824. }
  825. .singleLayersSelecte .selectBox .selectBox1 .selectLists{
  826. padding: 5px 15px;
  827. }
  828. .singleLayersSelecte .selectBox .title{
  829. background-color: #F8F9FA;
  830. height: 36px;
  831. line-height: 33px;
  832. border-radius: 4px 4px 0 0;
  833. font-weight: bold;
  834. display: -webkit-box;
  835. }
  836. .singleLayersSelecte .selectBox .title .clearAllBtn[data-v-ce06bf4a] {
  837. position: absolute;
  838. top: 1px;
  839. right: 0;
  840. }
  841. .singleLayersSelecte .selectBox .selectRight[data-v-ce06bf4a] {
  842. width: 35%;
  843. border: 1px solid #ddd;
  844. border-radius: 5px;
  845. }
  846. .singleLayersSelecte .selectBox .selectLeft[data-v-ce06bf4a] {
  847. width: 65%;
  848. margin-right: 2%;
  849. border: 1px solid #ddd;
  850. border-radius: 5px;
  851. }
  852. .linkMultiSel[data-v-dc40dba0] {
  853. width: 100%;
  854. height: 310px;
  855. display: -webkit-box;
  856. display: -ms-flexbox;
  857. display: flex;
  858. margin-top: 15px;
  859. }
  860. }
  861. </style>
  862. <style lang="scss" scoped>
  863. .setProjectDirectional {
  864. font-family: PingFangSC-Regular, tahoma, arial, 'Hiragino Sans GB', 'Microsoft yahei', sans-serif;
  865. color: #333;
  866. ul,
  867. li {
  868. margin: 0;
  869. padding: 0;
  870. }
  871. .moduler {
  872. background: #fff;
  873. margin-bottom: 16px;
  874. position: relative;
  875. padding: 32px 24px 48px 32px;
  876. border-radius: 4px;
  877. box-shadow: 0px 1px 6px 0px rgba(0, 0, 0, 0.05);
  878. .moduler-title {
  879. display: flex;
  880. align-items: center;
  881. font-size: 22px;
  882. margin-bottom: 20px;
  883. }
  884. .row-item {
  885. display: flex;
  886. justify-content: flex-start;
  887. align-items: center;
  888. margin-bottom: 32px;
  889. }
  890. .row-item:last-of-type {
  891. margin-bottom: 0;
  892. }
  893. .row-item .hint-item {
  894. width: 24px;
  895. min-width: 24px;
  896. align-self: flex-start;
  897. line-height: 20px;
  898. height: 20px;
  899. margin-top: 9px;
  900. }
  901. .row-item .label-item {
  902. position: relative;
  903. align-items: flex-start;
  904. align-self: flex-start;
  905. line-height: 20px;
  906. height: 20px;
  907. margin-top: 10px;
  908. width: 80px;
  909. min-width: 80px;
  910. .text-item {
  911. font-size: 14px;
  912. width: 60px;
  913. }
  914. }
  915. .row-item .required-item {
  916. width: 4px;
  917. height: 4px;
  918. border-radius: 2px;
  919. background: #f45858;
  920. position: absolute;
  921. right: 10px;
  922. top: 50%;
  923. transform: translateY(-50%);
  924. }
  925. .row-item .input-item {
  926. min-width: 670px;
  927. position: relative;
  928. // height: 35px;
  929. .tip {
  930. font-size: 12px;
  931. color: tomato;
  932. }
  933. .inventory-tags-lists-header {
  934. background-color: #F8F9FA;
  935. border: 1px solid #E4E9ED;
  936. height: 36px;
  937. line-height: 33px;
  938. border-radius: 4px 4px 0 0;
  939. font-weight: bold;
  940. display: flex;
  941. }
  942. .inventory-tags-lists-container {
  943. border: 1px solid #E4E9ED;
  944. margin-top: -1px;
  945. height: 100%;
  946. padding: 4px 0px;
  947. border-radius: 0 0 4px 4px;
  948. }
  949. .inventory-tags-lists-item {
  950. width: 100%;
  951. height: 37px;
  952. line-height: 37px;
  953. padding-left: 12px;
  954. padding-right: 12px;
  955. display: flex;
  956. font-size: 14px;
  957. color: #333;
  958. }
  959. }
  960. .adName{
  961. display: flex;
  962. .nameList{
  963. width: 90%;
  964. }
  965. .item{
  966. display: inline-block;
  967. width: 30%;
  968. margin-left: 15px;
  969. margin-bottom: 10px;
  970. }
  971. }
  972. }
  973. .opt {
  974. text-align: right;
  975. }
  976. }
  977. </style>