createCampaign.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  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">
  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]
  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. items.campaignName = node.value
  280. node.focus()
  281. // this.campaignName = node.value
  282. }
  283. },
  284. getChange(name, index) {
  285. console.log(index, document.getElementsByClassName('rending'))
  286. var node = document.getElementsByClassName('rending')[index]
  287. var v = '{{' + name + '}}-'
  288. if (document.selection) {
  289. //IE
  290. node.focus()
  291. var sel = document.selection.createRange()
  292. sel.text = v
  293. sel.select()
  294. this.campaignName = v
  295. } else if (node.selectionStart || node.selectionStart == '0') {
  296. //MOZILLA/GOOGLE
  297. var startPos = node.selectionStart
  298. var endPos = node.selectionEnd
  299. var restoreTop = node.scrollTop
  300. node.value = node.value.substring(0, startPos) + v + node.value.substring(endPos, node.value.length)
  301. if (restoreTop > 0) {
  302. node.scrollTop = restoreTop
  303. }
  304. this.campaignName = node.value
  305. node.focus()
  306. node.selectionStart = startPos + v.length
  307. node.selectionEnd = startPos + v.length
  308. // this.campaignName = node.value
  309. } else {
  310. //OTHER
  311. node.value += v
  312. this.campaignName = node.value
  313. node.focus()
  314. // this.campaignName = node.value
  315. }
  316. },
  317. handleConfirmValue(rule, value, callback) {
  318. if (value == '' || value < 500 || value >= 100000000) {
  319. callback('请输入正确预算金额')
  320. }
  321. callback()
  322. },
  323. handleConfirmAppId(rule, value, callback) {
  324. if (this.type == 2 && (this.appId == '0' || this.appId == '')) {
  325. callback('请选择目标应用')
  326. }
  327. callback()
  328. },
  329. handleSubmit(e) {
  330. e.preventDefault()
  331. this.form.validateFields((err, values) => {
  332. if (!err) {
  333. this.loading = true
  334. let params = {}
  335. params.type = values.type
  336. // params.campaignBudget = this.campaignBudget
  337. if (this.campaignBudget == 'UNLIMITED') {
  338. params.dayBudget = 0
  339. } else if (this.campaignBudget == 'AS_BUDGET') {
  340. params.dayBudget = values.dayBudget * 1000
  341. } else {
  342. params.dayBudgetSchedule = this.dayBudgetSchedule.map((item) => {
  343. if (item.one == '') {
  344. return 0
  345. } else {
  346. return item.one * 1000
  347. }
  348. })
  349. }
  350. if (this.getData('nameType') == 0) {
  351. var dataArr = this.campaignName.split('-')
  352. if (dataArr[dataArr.length - 1] == '') {
  353. dataArr.pop()
  354. }
  355. params.campaignName = dataArr.join('-')
  356. } else {
  357. params.nameArr = this.tabs.map((item) => {
  358. return {
  359. accountId: item.accountId,
  360. campaignNames: item.campaignNames.map((i) => {
  361. return i.campaignName
  362. }),
  363. }
  364. })
  365. }
  366. params.accountArr = this.accountIds
  367. params.nameType = values.nameType
  368. params.createTotal = values.createTotal
  369. console.log(params)
  370. postAction('/kuaishou/crossAccount/batchCampaignCreate', params).then((res) => {
  371. console.log(res)
  372. if (res.success) {
  373. this.$message.success('创建成功')
  374. localStorage.setItem('campaignId', res.result)
  375. this.loading = false
  376. this.nextStep(res.result)
  377. } else {
  378. this.$message.error(res.message)
  379. this.loading = false
  380. }
  381. })
  382. }
  383. })
  384. },
  385. onChange(value) {
  386. console.log(value)
  387. },
  388. showBudgetStatusChange() {
  389. if (this.campaignBudget == 'UNLIMITED') {
  390. this.showBudgetDaily = false
  391. this.dayBudget = 0
  392. } else {
  393. this.showBudgetDaily = true
  394. this.dayBudget = ''
  395. }
  396. },
  397. typeChange() {
  398. if (this.type == 2) {
  399. this.promotionName = '提升应用安装'
  400. this.showApp = true
  401. this.showRedirect = false
  402. this.showUrlType = false
  403. this.showChannelType = false
  404. }
  405. if (this.type == 3) {
  406. this.promotionName = '获取电商下单'
  407. this.showApp = false
  408. this.showRedirect = true
  409. this.showUrlType = true
  410. this.showChannelType = false
  411. }
  412. if (this.type == 4) {
  413. this.promotionName = '推广品牌活动'
  414. this.showApp = false
  415. this.showRedirect = true
  416. this.showUrlType = false
  417. this.showChannelType = false
  418. }
  419. if (this.type == 5) {
  420. this.promotionName = '收集销售线索'
  421. this.showApp = false
  422. this.showRedirect = true
  423. this.showUrlType = false
  424. this.showChannelType = true
  425. }
  426. this.campaignName = this.promotionName + '_' + moment(new Date())
  427. },
  428. handleChange(value) {
  429. console.log(`selected ${value}`)
  430. },
  431. handleBlur() {
  432. console.log('blur')
  433. },
  434. handleFocus() {
  435. console.log('focus')
  436. },
  437. filterOption(input, option) {
  438. return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
  439. },
  440. nextStep() {
  441. this.$emit('nextStep')
  442. },
  443. getData(className) {
  444. return this.form.getFieldValue(className)
  445. },
  446. },
  447. mounted: function () {
  448. this.$nextTick(() => {
  449. this.changeCreateTotal()
  450. })
  451. },
  452. }
  453. </script>