createCampaign.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. <style>
  2. .create-campaign .ant-form-item-control {
  3. line-height: inherit;
  4. }
  5. </style>
  6. <template>
  7. <a-card :body-style="{ padding: '24px 32px' }" :bordered="false" class="create-campaign">
  8. <a-form @submit="handleSubmit" :form="form">
  9. <a-form-item
  10. label="选择账户"
  11. :labelCol="{ lg: { span: 7 }, sm: { span: 7 } }"
  12. :wrapperCol="{ lg: { span: 10 }, sm: { span: 17 } }"
  13. >
  14. <Treeselect :appId.sync="accountIds" request="2,4" ref="treeSelect" style="width: 100%" />
  15. </a-form-item>
  16. <a-form-item
  17. label="推广目的"
  18. :labelCol="{ lg: { span: 7 }, sm: { span: 7 } }"
  19. :wrapperCol="{ lg: { span: 10 }, sm: { span: 17 } }"
  20. >
  21. <a-radio-group v-decorator="['type', { initialValue: 2 }]" buttonStyle="solid">
  22. <!-- <a-radio-button
  23. v-for="purpose in typeList"
  24. :key="purpose.itemText"
  25. :value="purpose.itemValue"
  26. >{{purpose.itemText}}</a-radio-button> -->
  27. <a-radio-button :value="2">提升应用安装</a-radio-button>
  28. <a-radio-button :value="3">获取电商下单</a-radio-button>
  29. <a-radio-button :value="4">推广品牌活动</a-radio-button>
  30. <a-radio-button :value="5">收集销售线索</a-radio-button>
  31. </a-radio-group>
  32. </a-form-item>
  33. <a-form-item
  34. label="创建数量"
  35. :labelCol="{ lg: { span: 7 }, sm: { span: 7 } }"
  36. :wrapperCol="{ lg: { span: 10 }, sm: { span: 17 } }"
  37. >
  38. <!-- {{ createTotal }} -->
  39. <a-input-number
  40. v-decorator="['createTotal', { initialValue: 1 }]"
  41. :min="1"
  42. :max="10"
  43. @change="changeCreateTotal"
  44. />
  45. </a-form-item>
  46. <a-form-item
  47. label="命名方式"
  48. :labelCol="{ lg: { span: 7 }, sm: { span: 7 } }"
  49. :wrapperCol="{ lg: { span: 10 }, sm: { span: 17 } }"
  50. >
  51. <a-radio-group v-decorator="['nameType', { initialValue: 0 }]" buttonStyle="solid" @change="nameTypeChange">
  52. <a-radio-button :value="0">统一命名</a-radio-button>
  53. <a-radio-button :value="1">分别命名</a-radio-button>
  54. </a-radio-group>
  55. </a-form-item>
  56. <a-form-item
  57. label="计划名称"
  58. :labelCol="{ lg: { span: 7 }, sm: { span: 7 } }"
  59. :wrapperCol="{ lg: { span: 10 }, sm: { span: 17 } }"
  60. v-if="getData('nameType') == 0"
  61. >
  62. <!-- campaignName -->
  63. <a-input
  64. class="rending"
  65. placeholder="请输入计划名称"
  66. v-model="campaignName"
  67. style="margin-bottom: 20px"
  68. ></a-input>
  69. <br />
  70. <a-tag color="#2db7f5" @click="getChange('项目名称', 0)">项目名称</a-tag>
  71. <a-tag color="#2db7f5" @click="getChange('计划类型', 0)">计划类型</a-tag>
  72. <a-tag color="#2db7f5" @click="getChange('日期', 0)">日期</a-tag>
  73. <a-tag color="#2db7f5" @click="getChange('数值', 0)">数值</a-tag>
  74. </a-form-item>
  75. <a-form-item
  76. label="计划名称"
  77. :labelCol="{ lg: { span: 7 }, sm: { span: 7 } }"
  78. :wrapperCol="{ lg: { span: 10 }, sm: { span: 17 } }"
  79. v-if="getData('nameType') == 1"
  80. >
  81. <!-- campaignName -->
  82. <!-- @change="callback" -->
  83. <!-- {{ tabs }} -->
  84. <a-tabs v-model="active" type="card">
  85. <a-tab-pane :key="item.accountId" :tab="item.authName" v-for="(item, index) of tabs">
  86. <div v-for="(items, indexBest) of item.campaignNames" :key="indexBest" style="margin-bottom: 10px">
  87. <a-input
  88. class="rending"
  89. placeholder="请输入计划名称"
  90. v-model="items.campaignName"
  91. style="margin-bottom: 10px"
  92. ></a-input>
  93. <br />
  94. <a-tag color="#2db7f5" @click="getChangeAll('项目名称', indexBest, index, items)">项目名称</a-tag>
  95. <a-tag color="#2db7f5" @click="getChangeAll('计划类型', indexBest, index, items)">计划类型</a-tag>
  96. <a-tag color="#2db7f5" @click="getChangeAll('日期', indexBest, index, items)">日期</a-tag>
  97. <a-tag color="#2db7f5" @click="getChangeAll('数值', indexBest, index, items)">数值</a-tag>
  98. </div>
  99. </a-tab-pane>
  100. </a-tabs>
  101. <!-- <a-input
  102. class="rending"
  103. placeholder="请输入计划名称"
  104. v-model="campaignName"
  105. style="margin-bottom: 20px"
  106. ></a-input>
  107. <br />
  108. <a-tag color="#2db7f5" @click="getChange('项目名称')">项目名称</a-tag>
  109. <a-tag color="#2db7f5" @click="getChange('计划类型')">计划类型</a-tag>
  110. <a-tag color="#2db7f5" @click="getChange('日期')">日期</a-tag>
  111. <a-tag color="#2db7f5" @click="getChange('数值')">数值</a-tag> -->
  112. </a-form-item>
  113. <a-form-item
  114. label="单日预算"
  115. :labelCol="{ lg: { span: 7 }, sm: { span: 7 } }"
  116. :wrapperCol="{ lg: { span: 10 }, sm: { span: 17 } }"
  117. >
  118. <a-radio-group @change="showBudgetStatusChange" v-model="campaignBudget" buttonStyle="solid">
  119. <a-radio-button value="UNLIMITED">不限</a-radio-button>
  120. <a-radio-button value="AS_BUDGET">统一预算</a-radio-button>
  121. <a-radio-button value="DAY_BUDGET">分日预算</a-radio-button>
  122. </a-radio-group>
  123. </a-form-item>
  124. <a-form-item
  125. label="预算金额"
  126. v-if="campaignBudget == 'AS_BUDGET'"
  127. :labelCol="{ lg: { span: 7 }, sm: { span: 7 } }"
  128. :wrapperCol="{ lg: { span: 10 }, sm: { span: 17 } }"
  129. >
  130. <a-input
  131. v-decorator="[
  132. 'dayBudget',
  133. { rules: [{ required: true, message: 'error:' }, { validator: handleConfirmValue }] },
  134. ]"
  135. placeholder="不小于500,不超过100000000,仅支持输入自然数"
  136. type="number"
  137. style="width: 70%"
  138. ></a-input
  139. >元
  140. </a-form-item>
  141. <a-form-item
  142. label="分日预算"
  143. v-if="campaignBudget == 'DAY_BUDGET'"
  144. :labelCol="{ lg: { span: 7 }, sm: { span: 7 } }"
  145. :wrapperCol="{ lg: { span: 17 }, sm: { span: 17 } }"
  146. >
  147. <!-- <a-input
  148. v-decorator="[
  149. 'dayBudget',
  150. { rules: [{ required: true, message: 'error:' }, { validator: handleConfirmValue }] },
  151. ]"
  152. placeholder="不小于500,不超过100000000,仅支持输入自然数"
  153. type="number"
  154. style="width: 70%"
  155. ></a-input
  156. >元 -->
  157. <a-row>
  158. <a-col :span="3" v-for="(item, index) of dayBudgetSchedule" :key="index">
  159. <a-card :title="'周' + numberReturn(index)">
  160. <a-input-number :min="500" :max="100000000" v-model="item.one" :precision="1" />
  161. </a-card>
  162. </a-col>
  163. </a-row>
  164. </a-form-item>
  165. <a-form-item :wrapperCol="{ span: 24 }" style="text-align: center">
  166. <a-button htmlType="submit" type="primary" :loading="loading">下一步</a-button>
  167. <!-- <a-button style="margin-left: 8px">保存</a-button> -->
  168. </a-form-item>
  169. </a-form>
  170. </a-card>
  171. </template>
  172. <script>
  173. import { deleteAction, postAction, getAction } from '@/api/manage'
  174. import moment from 'moment'
  175. import { mapActions, mapGetters } from 'vuex'
  176. import Treeselect from '@/views/modules/Statistics/components/Treeselect.vue'
  177. export default {
  178. name: 'create-campaign',
  179. components: {
  180. Treeselect,
  181. },
  182. data() {
  183. return {
  184. accountIds: [],
  185. active: null,
  186. promotionName: '',
  187. tabs: [],
  188. dayBudgetSchedule: [{ one: '' }, { one: '' }, { one: '' }, { one: '' }, { one: '' }, { one: '' }, { one: '' }],
  189. type: '2',
  190. typeList: {},
  191. appList: {},
  192. showBudgetDaily: false,
  193. campaignName: '',
  194. campaignBudget: 'UNLIMITED',
  195. dayBudget: 0,
  196. appId: '0', //应用目标
  197. showApp: true,
  198. redirectUrl: '', // 链接地址
  199. showRedirect: false,
  200. urlType: '1',
  201. showUrlType: false,
  202. channelType: '1',
  203. showChannelType: false,
  204. loading: false,
  205. form: this.$form.createForm(this),
  206. url: {
  207. dictListUrl: 'toutiao/dictitem/list',
  208. appListUrl: '/kuaishou/kuaiShouCreateAppTemplate/list',
  209. insertTemplateUrl: '/kuaishou/batch/campaignCreate',
  210. },
  211. createTotal: [],
  212. }
  213. },
  214. methods: {
  215. ...mapGetters(['nickname', 'avatar', 'userInfo']),
  216. numberReturn(num) {
  217. var arr = ['一', '二', '三', '四', '五', '六', '天']
  218. return arr[num]
  219. },
  220. getCampaignId(campaignId) {
  221. alert(1)
  222. },
  223. changeCreateTotal() {
  224. this.$nextTick(() => {
  225. this.createTotal = []
  226. for (let i = 0; i < this.getData('createTotal'); i++) {
  227. this.createTotal.push({ campaignName: '' })
  228. }
  229. })
  230. },
  231. nameTypeChange(e) {
  232. console.log(e.target.value)
  233. if (e.target.value == 1) {
  234. if (this.accountIds.length > 0) {
  235. postAction('/kuaishou/crossAccount/getAuthName', { accountArr: this.accountIds }).then((res) => {
  236. if (res.success) {
  237. this.tabs = res.result.map((item) => {
  238. return {
  239. ...item,
  240. campaignNames: JSON.parse(JSON.stringify(this.createTotal)),
  241. }
  242. })
  243. this.active = res.result[0].accountId
  244. } else {
  245. this.tabs = []
  246. }
  247. })
  248. }
  249. } else {
  250. }
  251. },
  252. getChangeAll(name, indexBest, index, items) {
  253. var node = document.getElementsByClassName('rending')[indexBest + this.getData('createTotal') * index]
  254. var v = '{{' + name + '}}-'
  255. if (document.selection) {
  256. //IE
  257. node.focus()
  258. var sel = document.selection.createRange()
  259. sel.text = v
  260. sel.select()
  261. items.campaignName = v
  262. } else if (node.selectionStart || node.selectionStart == '0') {
  263. //MOZILLA/GOOGLE
  264. var startPos = node.selectionStart
  265. var endPos = node.selectionEnd
  266. var restoreTop = node.scrollTop
  267. node.value = node.value.substring(0, startPos) + v + node.value.substring(endPos, node.value.length)
  268. if (restoreTop > 0) {
  269. node.scrollTop = restoreTop
  270. }
  271. items.campaignName = node.value
  272. node.focus()
  273. node.selectionStart = startPos + v.length
  274. node.selectionEnd = startPos + v.length
  275. // this.campaignName = node.value
  276. } else {
  277. //OTHER
  278. node.value += v
  279. console.log(node.value)
  280. items.campaignName = node.value
  281. node.focus()
  282. // this.campaignName = node.value
  283. }
  284. },
  285. getChange(name, index) {
  286. console.log(index, document.getElementsByClassName('rending'))
  287. var node = document.getElementsByClassName('rending')[index]
  288. var v = '{{' + name + '}}-'
  289. if (document.selection) {
  290. //IE
  291. node.focus()
  292. var sel = document.selection.createRange()
  293. sel.text = v
  294. sel.select()
  295. this.campaignName = v
  296. } else if (node.selectionStart || node.selectionStart == '0') {
  297. //MOZILLA/GOOGLE
  298. var startPos = node.selectionStart
  299. var endPos = node.selectionEnd
  300. var restoreTop = node.scrollTop
  301. node.value = node.value.substring(0, startPos) + v + node.value.substring(endPos, node.value.length)
  302. if (restoreTop > 0) {
  303. node.scrollTop = restoreTop
  304. }
  305. this.campaignName = node.value
  306. node.focus()
  307. node.selectionStart = startPos + v.length
  308. node.selectionEnd = startPos + v.length
  309. // this.campaignName = node.value
  310. } else {
  311. //OTHER
  312. node.value += v
  313. this.campaignName = node.value
  314. node.focus()
  315. // this.campaignName = node.value
  316. }
  317. },
  318. handleConfirmValue(rule, value, callback) {
  319. if (value == '' || value < 500 || value >= 100000000) {
  320. callback('请输入正确预算金额')
  321. }
  322. callback()
  323. },
  324. handleConfirmAppId(rule, value, callback) {
  325. if (this.type == 2 && (this.appId == '0' || this.appId == '')) {
  326. callback('请选择目标应用')
  327. }
  328. callback()
  329. },
  330. handleSubmit(e) {
  331. e.preventDefault()
  332. this.form.validateFields((err, values) => {
  333. if (!err) {
  334. this.loading = true
  335. let params = {}
  336. params.type = values.type
  337. // params.campaignBudget = this.campaignBudget
  338. if (this.campaignBudget == 'UNLIMITED') {
  339. params.dayBudget = 0
  340. } else if (this.campaignBudget == 'AS_BUDGET') {
  341. params.dayBudget = values.dayBudget * 1000
  342. } else {
  343. params.dayBudgetSchedule = this.dayBudgetSchedule.map((item) => {
  344. if (item.one == '') {
  345. return 0
  346. } else {
  347. return item.one * 1000
  348. }
  349. })
  350. }
  351. if (this.getData('nameType') == 0) {
  352. var dataArr = this.campaignName.split('-')
  353. if (dataArr[dataArr.length - 1] == '') {
  354. dataArr.pop()
  355. }
  356. params.campaignName = dataArr.join('-')
  357. } else {
  358. params.nameArr = this.tabs.map((item) => {
  359. return {
  360. accountId: item.accountId,
  361. campaignNames: item.campaignNames.map((i) => {
  362. return i.campaignName
  363. }),
  364. }
  365. })
  366. }
  367. params.accountArr = this.accountIds
  368. params.nameType = values.nameType
  369. params.createTotal = values.createTotal
  370. console.log(params)
  371. postAction('/kuaishou/crossAccount/batchCampaignCreate', params).then((res) => {
  372. console.log(res)
  373. if (res.success) {
  374. this.$message.success('创建成功')
  375. localStorage.setItem('campaignId', res.result)
  376. this.loading = false
  377. this.nextStep(res.result)
  378. } else {
  379. this.$message.error(res.message)
  380. this.loading = false
  381. }
  382. })
  383. }
  384. })
  385. },
  386. onChange(value) {
  387. console.log(value)
  388. },
  389. showBudgetStatusChange() {
  390. if (this.campaignBudget == 'UNLIMITED') {
  391. this.showBudgetDaily = false
  392. this.dayBudget = 0
  393. } else {
  394. this.showBudgetDaily = true
  395. this.dayBudget = ''
  396. }
  397. },
  398. typeChange() {
  399. if (this.type == 2) {
  400. this.promotionName = '提升应用安装'
  401. this.showApp = true
  402. this.showRedirect = false
  403. this.showUrlType = false
  404. this.showChannelType = false
  405. }
  406. if (this.type == 3) {
  407. this.promotionName = '获取电商下单'
  408. this.showApp = false
  409. this.showRedirect = true
  410. this.showUrlType = true
  411. this.showChannelType = false
  412. }
  413. if (this.type == 4) {
  414. this.promotionName = '推广品牌活动'
  415. this.showApp = false
  416. this.showRedirect = true
  417. this.showUrlType = false
  418. this.showChannelType = false
  419. }
  420. if (this.type == 5) {
  421. this.promotionName = '收集销售线索'
  422. this.showApp = false
  423. this.showRedirect = true
  424. this.showUrlType = false
  425. this.showChannelType = true
  426. }
  427. this.campaignName = this.promotionName + '_' + moment(new Date())
  428. },
  429. handleChange(value) {
  430. console.log(`selected ${value}`)
  431. },
  432. handleBlur() {
  433. console.log('blur')
  434. },
  435. handleFocus() {
  436. console.log('focus')
  437. },
  438. filterOption(input, option) {
  439. return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
  440. },
  441. nextStep() {
  442. this.$emit('nextStep')
  443. },
  444. getData(className) {
  445. return this.form.getFieldValue(className)
  446. },
  447. },
  448. mounted: function () {
  449. this.$nextTick(() => {
  450. this.changeCreateTotal()
  451. })
  452. },
  453. }
  454. </script>