editGroup.vue 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029
  1. <style>
  2. #table_time_selected1 tr {
  3. border: 1px solid rgb(102, 162, 243);
  4. }
  5. .plug-timer-grid th {
  6. line-height: 25px;
  7. }
  8. .group-creat .ant-form-item-required::before {
  9. display: inline-block;
  10. margin-right: 4px;
  11. color: #f5222d;
  12. font-size: 14px;
  13. font-family: SimSun, sans-serif;
  14. line-height: 1;
  15. content: '';
  16. }
  17. .else-label .ant-form-item-label label::after {
  18. content: '';
  19. position: relative;
  20. top: -0.5px;
  21. margin: 0 8px 0 2px;
  22. }
  23. </style>
  24. <template>
  25. <a-modal v-model="visible" title="修改广告组信息" :width="900" v-if="visible">
  26. <a-form @submit="handleSubmit" :form="form">
  27. <a-form-item label="目标应用" :labelCol="{ lg: { span: 7 }, sm: { span: 7 } }"
  28. :wrapperCol="{ lg: { span: 10 }, sm: { span: 17 } }" v-if="campaignType == '2'">
  29. <a-select :disabled="typeCopy=='edit'"
  30. v-decorator="['appId', { rules: [{ required: true, message: '请选择目标应用' }] }]" showSearch allowClear
  31. placeholder="选择应用目标" optionFilterProp="children" style="width: 500px" @focus="handleFocus" @blur="handleBlur"
  32. @change="handleChange" :filterOption="filterOption">
  33. <a-select-option value="0">请选择目标应用</a-select-option>
  34. <a-select-option v-for="appModel in appList" :key="appModel.appId" :value="appModel.appId">
  35. {{ appModel.appName }}&#12288;&nbsp;&#12288; {{ appModel.appVersion }}&#12288;&#12288;&#12288;{{
  36. appModel.platform | platform
  37. }}
  38. </a-select-option>
  39. </a-select>
  40. <br v-if="typeCopy!='edit'">
  41. <span v-if="typeCopy!='edit'" style="color:red">如修改目标应用,请重新选择落地页</span>
  42. <!-- <a @click="addApplication" style="margin-left:10px">添加应用</a> -->
  43. <creat-application ref="application" />
  44. </a-form-item>
  45. <a-form-item label=" " class="else-label" :labelCol="{ lg: { span: 7 }, sm: { span: 7 } }"
  46. :wrapperCol="{ lg: { span: 10 }, sm: { span: 17 } }"
  47. v-if="campaignType == '2'&&showSite&&(getPlatForm(getData('appId'))=='1'||getPlatForm(getData('appId'))=='2')">
  48. <a-select v-model="siteId" showSearch allowClear placeholder="选择应用下载详情页" optionFilterProp="children"
  49. :filterOption="filterOption">
  50. <a-select-option v-for="appModel in siteList" :key="appModel.siteId" :value="appModel.siteId">
  51. {{ appModel.name }}
  52. </a-select-option>
  53. </a-select>
  54. </a-form-item>
  55. <a-form-item label="转化类型" :labelCol="{ lg: { span: 7 }, sm: { span: 7 } }"
  56. :wrapperCol="{ lg: { span: 10 }, sm: { span: 17 } }" v-if="campaignType == '3'">
  57. <a-radio-group buttonStyle="solid"
  58. v-decorator="['urlType', { rules: [{ required: true, message: '请选择目标应用' }], initialValue:1 }]">
  59. <a-radio-button :value="1">淘宝商品</a-radio-button>
  60. <a-radio-button :value="2">淘客商品</a-radio-button>
  61. </a-radio-group>
  62. </a-form-item>
  63. <a-form-item :label="campaignType == '3' ? ' ' : '链接'" :labelCol="{ lg: { span: 7 }, sm: { span: 7 } }"
  64. :wrapperCol="{ lg: { span: 10 }, sm: { span: 17 } }" v-if="campaignType != '2'"
  65. :class="{ 'else-label': campaignType == '3' }">
  66. <!-- 请填写以http://或者https://开头的落地页地址,长度不超过1000个字符 -->
  67. <a-input placeholder="请填写链接"
  68. v-decorator="['url', { rules: [{ required: true, message: ' ' }, { validator: handleConfirmValue }] }]" />
  69. </a-form-item>
  70. <a-form-item label=" " :labelCol="{ lg: { span: 7 }, sm: { span: 7 } }"
  71. :wrapperCol="{ lg: { span: 10 }, sm: { span: 17 } }" class="else-label"
  72. v-if="campaignType == '2'&&(getPlatForm(getData('appId'))=='1'||getPlatForm(getData('appId'))=='2')">
  73. <a-checkbox @change="onChange" :checked="allForm.useAppMarket">
  74. 优先从系统应用商店下载
  75. </a-checkbox>
  76. </a-form-item>
  77. <a-form-item label=" " :labelCol="{ lg: { span: 7}, sm: { span: 7 } }"
  78. :wrapperCol="{ lg: { span: 10 }, sm: { span: 16 } }" class="else-label" v-if="allForm.useAppMarket">
  79. 请勾选投放应用已上架的应用商店(默认全选)
  80. <a-checkbox-group v-model="allForm.appStore">
  81. <a-checkbox value="huawei">华为</a-checkbox>
  82. <a-checkbox value="oppo">OPPO</a-checkbox>
  83. <a-checkbox value="vivo">VIVO</a-checkbox>
  84. <a-checkbox value="xiaomi">小米</a-checkbox>
  85. <a-checkbox value="meizu">魅族</a-checkbox>
  86. <a-checkbox value="smartisan">锤子</a-checkbox>
  87. </a-checkbox-group>
  88. </a-form-item>
  89. <a-form-item label="投放范围" :labelCol="{ lg: { span: 7 }, sm: { span: 7 } }"
  90. :wrapperCol="{ lg: { span: 10 }, sm: { span: 17 } }"
  91. v-if="allianceAccount">
  92. <a-radio-group buttonStyle="solid" v-model="allForm.allianceAccount" :disabled="typeCopy=='edit'">
  93. <a-radio-button value="1">默认</a-radio-button>
  94. <a-radio-button value="2">联盟广告</a-radio-button>
  95. </a-radio-group>
  96. </a-form-item>
  97. <div style="text-align:center;font-size:16px;margin-bottom:10px">
  98. 目标人群
  99. </div>
  100. <a-form-item label="选择模板" :labelCol="{ lg: { span: 7 }, sm: { span: 7 } }"
  101. :wrapperCol="{ lg: { span: 10 }, sm: { span: 17 } }">
  102. <a-select showSearch allowClear placeholder="选择模板" optionFilterProp="children" style="width: 500px"
  103. @change="handleChangeMould" :filterOption="filterOption">
  104. <a-select-option v-for="(appModel, index) in dataList" :key="index" :value="appModel.id">
  105. {{ appModel.templateName }}
  106. </a-select-option>
  107. </a-select>
  108. </a-form-item>
  109. <targeted-population ref="population" :populationData.sync="populationData"
  110. :platform="getPlatForm(getData('appId'))" :lol="allForm.allianceAccount"/>
  111. <a-form-item label=" " :labelCol="{ lg: { span: 7 }, sm: { span: 7 } }"
  112. :wrapperCol="{ lg: { span: 10 }, sm: { span: 17 } }" class="else-label">
  113. <div style="display:flex;">
  114. <a-checkbox :checked="checkedTrue" @change="getCheck">
  115. 是否设置为模板
  116. </a-checkbox>
  117. <a-input v-model="nameValue" v-if="checkedTrue" placeholder="请输入模板名称" style="width:70%" />
  118. </div>
  119. </a-form-item>
  120. <div style="text-align:center;font-size:16px">
  121. 预算和排期
  122. </div>
  123. <a-form-item label="单日预算" :labelCol="{ lg: { span: 7 }, sm: { span: 7 } }"
  124. :wrapperCol="{ lg: { span: 10 }, sm: { span: 17 } }">
  125. <a-radio-group buttonStyle="solid" v-model="allForm.dayBudget">
  126. <a-radio-button value="0">不限</a-radio-button>
  127. <a-radio-button value="1">统一预算</a-radio-button>
  128. </a-radio-group>
  129. </a-form-item>
  130. <a-form-item label=" " :labelCol="{ lg: { span: 7 }, sm: { span: 7 } }"
  131. :wrapperCol="{ lg: { span: 10 }, sm: { span: 17 } }" class="else-label" v-show="allForm.dayBudget == '1'">
  132. <a-input placeholder="不小于100,不超过100000000,仅支持输入自然数" v-decorator="[
  133. 'dayBudget',
  134. ]" />
  135. </a-form-item>
  136. <a-form-item label="投放方式" :labelCol="{ lg: { span: 7 }, sm: { span: 7 } }"
  137. :wrapperCol="{ lg: { span: 10 }, sm: { span: 17 } }">
  138. <a-radio-group buttonStyle="solid" v-decorator="['speed']">
  139. <a-radio-button :value="1">正常投放</a-radio-button>
  140. <a-radio-button :value="2">平滑投放</a-radio-button>
  141. </a-radio-group>
  142. <br />
  143. <span>
  144. {{ getData('speed') == 2 ? '平滑匀速投放' : '尽快展示广告消耗预算' }}
  145. </span>
  146. </a-form-item>
  147. <a-form-item label="排期" :labelCol="{ lg: { span: 7 }, sm: { span: 7 } }"
  148. :wrapperCol="{ lg: { span: 10 }, sm: { span: 17 } }">
  149. <!-- v-decorator="['speed', { initialValue: '1' }]" -->
  150. <a-radio-group buttonStyle="solid" v-model="allForm.time" @change="setTime">
  151. <a-radio-button value="1">从今天开始长期投放</a-radio-button>
  152. <a-radio-button value="2">设置开始和结束日期</a-radio-button>
  153. </a-radio-group>
  154. <br />
  155. <a-range-picker v-if="allForm.time == '2'" v-model="timeRange" format="YYYY-MM-DD" :allowClear="false" />
  156. </a-form-item>
  157. <a-form-item label="投放时段" :labelCol="{ lg: { span: 7 }, sm: { span: 7 } }"
  158. :wrapperCol="{ lg: { span: 17 }, sm: { span: 17 } }">
  159. <!-- v-decorator="['speed', { initialValue: '1' }]" -->
  160. <a-radio-group buttonStyle="solid" v-model="allForm.scheduleTime" @change="setTimeAll">
  161. <a-radio-button value="1">全天</a-radio-button>
  162. <a-radio-button value="2">特定时间</a-radio-button>
  163. </a-radio-group>
  164. <br />
  165. <selectCheckAll style="width:100%" v-show="allForm.scheduleTime == '2'"
  166. :scheduleTime.sync="allForm.scheduleTimeData" ref="selectCheck" />
  167. </a-form-item>
  168. <a-form-item label="创意展现方式" :labelCol="{ lg: { span: 7 }, sm: { span: 7 } }"
  169. :wrapperCol="{ lg: { span: 10 }, sm: { span: 17 } }">
  170. <!-- v-decorator="['speed', { initialValue: '1' }]" -->
  171. <a-radio-group buttonStyle="solid" v-decorator="['showMode', { initialValue: 2 }]">
  172. <a-radio-button :value="2">智能优选</a-radio-button>
  173. <a-radio-button :value="1">随机轮播</a-radio-button>
  174. </a-radio-group>
  175. <br />
  176. <span>
  177. {{
  178. getData('showMode') == 1
  179. ? '广告组包含的广告创意将随机展现'
  180. : '每一次展现的时候,系统会进行CTR预估,预估CTR高的会得到展现机会'
  181. }}
  182. </span>
  183. </a-form-item>
  184. <a-form-item label="场景广告位" :labelCol="{ lg: { span: 7 }, sm: { span: 7 } }"
  185. :wrapperCol="{ lg: { span: 17 }, sm: { span: 17 } }" v-if="allForm.allianceAccount=='1'">
  186. <!-- v-decorator="['speed', { initialValue: '1' }]" -->
  187. <a-radio-group buttonStyle="solid" :disabled="typeCopy=='edit'" v-model="allForm.sceneIdAll">
  188. <a-radio-button :value="1">优选广告位</a-radio-button>
  189. <a-radio-button :value="2">按场景选择广告位</a-radio-button>
  190. </a-radio-group>
  191. <!-- getData('speed') == '2' -->
  192. <br>
  193. </a-form-item>
  194. <a-form-item label=" " :labelCol="{ lg: { span: 7 }, sm: { span: 7 } }"
  195. :wrapperCol="{ lg: { span: 10 }, sm: { span: 17 } }" class="else-label" v-if="allForm.sceneIdAll == 2">
  196. <a-checkbox-group :disabled="typeCopy=='edit'" :defaultValue="[7]" v-model="allForm.sceneId">
  197. <a-checkbox :value="7">信息流广告</a-checkbox>
  198. <a-checkbox :value="6">上下滑大屏广告</a-checkbox>
  199. <a-checkbox :value="3">视频播放页广告</a-checkbox>
  200. </a-checkbox-group>
  201. </a-form-item>
  202. <div style="text-align:center;font-size:16px">优化目标和计费</div>
  203. <a-form-item label=" " :labelCol="{ lg: { span: 6 }, sm: { span: 6 } }"
  204. :wrapperCol="{ lg: { span: 18 }, sm: { span: 18 } }" class="else-label">
  205. <div style="width:100%">
  206. <a-layout>
  207. <a-layout-content style="padding:10px;">
  208. <!-- <div :style="{ marginBottom: '16px' }">
  209. <a-button @click="addGroup" :disabled="allForm.group.length > 10">添加广告组</a-button>
  210. </div> -->
  211. <a-row>
  212. <a-col :sm="24" :md="24" :xl="24" :xxl="24" v-for="(item, index) of allForm.group" :key="index">
  213. <a-card title :ref="item" style="height:435px">
  214. <div style="clear:both"></div>
  215. <a-form-item label="优化目标" :labelCol="{ lg: { span: 6 }, sm: { span: 7 } }"
  216. :wrapperCol="{ lg: { span: 18 }, sm: { span: 17 } }">
  217. <a-radio-group buttonStyle="solid" v-model="item.bidType" @change="resData(index)">
  218. <a-radio-button :value="1">点击数</a-radio-button>
  219. <a-radio-button :value="10">转化数</a-radio-button>
  220. </a-radio-group>
  221. </a-form-item>
  222. <a-form-item label="转化目标" :labelCol="{ lg: { span: 6 }, sm: { span: 7 } }"
  223. :wrapperCol="{ lg: { span: 18 }, sm: { span: 17 } }" v-if="item.bidType==10">
  224. <a-select v-model="item.ocpxActionType">
  225. <a-select-option :value="2">行为数</a-select-option>
  226. <a-select-option :value="180"
  227. v-if="campaignType == '2' && allForm.groupTypeData.isActivate == '1'">激活</a-select-option>
  228. <a-select-option :value="53" v-if="
  229. (campaignType == '4' || campaignType == '5') && allForm.groupTypeData.isFormSubmit == '1'
  230. ">表单提交</a-select-option>
  231. <a-select-option :value="394" v-if="
  232. allForm.groupTypeData.isOrderSubmit == '1'
  233. ">订单提交</a-select-option>
  234. <a-select-option :value="348" v-if="
  235. allForm.groupTypeData.isValidClue == '1'
  236. ">使用有效线索</a-select-option>
  237. <a-select-option :value="383" v-if="
  238. allForm.groupTypeData.isCreditGrant == '1'
  239. ">授信出价</a-select-option>
  240. <a-select-option :value="384" v-if="
  241. allForm.groupTypeData.isWanJian == '1'
  242. ">完件出价</a-select-option>
  243. <a-select-option :value="190" v-if="
  244. allForm.groupTypeData.isPurchase == '1'
  245. ">付费出价</a-select-option>
  246. <a-select-option :value="191" v-if="
  247. allForm.groupTypeData.isFirstdayRoi == '1'
  248. ">首日ROI</a-select-option>
  249. <a-select-option :value="396" v-if="
  250. allForm.groupTypeData.isRegister == '1'
  251. ">注册优化目标</a-select-option>
  252. </a-select>
  253. </a-form-item>
  254. <a-form-item label="深度转化目标" :labelCol="{ lg: { span: 6 }, sm: { span: 7 } }"
  255. :wrapperCol="{ lg: { span: 18 }, sm: { span: 17 } }" v-if="
  256. (item.ocpxActionType == 180 || item.ocpxActionType == 53) &&
  257. allForm.groupTypeData.deepConversionTypes.length > 0
  258. ">
  259. <a-select v-model="item.deepConversionType" allowClear>
  260. <a-select-option :value="items.deepConversionType"
  261. v-for="(items, index) of allForm.groupTypeData.deepConversionTypes" :key="index">
  262. {{ items.desc }}</a-select-option>
  263. </a-select>
  264. </a-form-item>
  265. <a-form-item label="计费方式" :labelCol="{ lg: { span: 6 }, sm: { span: 7 } }"
  266. :wrapperCol="{ lg: { span: 18 }, sm: { span: 17 } }">
  267. <a-radio-group :defaultValue="1">
  268. <a-radio :value="1">{{item.bidType == 1?"点击计费":"展示计费(oCPM)"}}</a-radio>
  269. </a-radio-group>
  270. </a-form-item>
  271. <a-form-item label="出价" :labelCol="{ lg: { span: 6 }, sm: { span: 7 } }"
  272. :wrapperCol="{ lg: { span: 18 }, sm: { span: 17 } }" v-if="item.bidType ==1">
  273. <a-input-number v-model="item.bid" @change="showTip(index)"
  274. :style="{ borderColor: item.showTipCheck ? 'red' : '#d9d9d9' }" style="width:100%">
  275. </a-input-number>
  276. <span style="color:red" v-if="item.showTipCheck">不得低于0.2元,不得高于项目最高出价{{ maxBid }}元</span>
  277. </a-form-item>
  278. <a-form-item label="目标成本" :labelCol="{ lg: { span: 6 }, sm: { span: 7 } }"
  279. :wrapperCol="{ lg: { span: 18 }, sm: { span: 17 } }" v-else>
  280. <a-input-number v-model="item.cpaBid" @change="showTip(index)"
  281. :style="{ borderColor: item.showTipCheck ? 'red' : '#d9d9d9' }" style="width:100%">
  282. </a-input-number>
  283. <span style="color:red" v-if="item.showTipCheck">{{
  284. item.bidType == 1
  285. ? '不得低于1元,不得高于项目最高出价' + maxBid + '元'
  286. : '不得低于1元,不得高于项目最高出价' + maxBid + '元'
  287. }}</span>
  288. <span style="color:red;font-weight:700" v-else-if="item.ocpxActionType==2&&item.cpaBid&&item.cpaBid>1">
  289. 行为出价大于1元,请注意!!!
  290. </span>
  291. </a-form-item>
  292. <a-form-item label="深度转化出价" :labelCol="{ lg: { span: 6 }, sm: { span: 7 } }"
  293. :wrapperCol="{ lg: { span: 18 }, sm: { span: 17 } }" v-if="
  294. (item.ocpxActionType == 180 || item.ocpxActionType == 53) &&
  295. allForm.groupTypeData.deepConversionTypes.length > 0 &&
  296. item.deepConversionType != ''
  297. ">
  298. <a-input-number v-model="item.deepConversionBid" @change="deep_conversion_bidTip(index)"
  299. :style="{ borderColor: item.deepConversionBidCheck ? 'red' : '#d9d9d9' }" style="width:100%"
  300. :disabled="item.cpaBid == ''"></a-input-number>
  301. <span style="color:red" v-if="item.deepConversionBidCheck">深度转化目标成本必须高于优化目标成本,且不得高于3000元</span>
  302. </a-form-item>
  303. <a-form-item label="广告组名称" :labelCol="{ lg: { span: 6 }, sm: { span: 7 } }"
  304. :wrapperCol="{ lg: { span: 18 }, sm: { span: 17 } }">
  305. <a-input v-model="item.unitName" @change="checkGroup($event, index)"></a-input>
  306. <span style="color:red" v-if="item.unitNameCheck">广告组名称重复</span>
  307. </a-form-item>
  308. </a-card>
  309. </a-col>
  310. </a-row>
  311. </a-layout-content>
  312. </a-layout>
  313. </div>
  314. </a-form-item>
  315. </a-form>
  316. <template slot="footer">
  317. <a-button type="primary" @click="handleSubmit" :loading="loading">
  318. 确定
  319. </a-button>
  320. </template>
  321. <a-modal v-model="visibleFail" title="错误信息" :footer="null">
  322. <div v-if="visibleData">
  323. 失败条数:{{ visibleData.failCount }}
  324. <div style="margin-top:20px">
  325. <p v-for="(item, index) of visibleData.failInfo" :key="index">
  326. <span>名称:{{ item.campaignName?item.campaignName:item.unitName }}</span><br />
  327. <span>错误信息:{{ item.failMessage }}</span>
  328. </p>
  329. </div>
  330. </div>
  331. </a-modal>
  332. </a-modal>
  333. </template>
  334. <script>
  335. import {
  336. getAction,
  337. postAction,
  338. deleteAction,
  339. putAction
  340. } from '@/api/manage'
  341. import moment from 'moment'
  342. import {
  343. mapGetters
  344. } from 'vuex'
  345. import jq from 'jquery'
  346. import Treeselect from '@/views/modules/Statistics/components/Treeselect.vue'
  347. import targetedPopulation from '@/views/modules/kuaishouapp/account/stepForm/stepModule/targetedPopulation.vue'
  348. import creatApplication from '@/views/modules/kuaishouapp/account/stepForm/stepModule/creatApplication.vue'
  349. import selectCheckAll from '@/views/modules/kuaishouapp/account/stepForm/stepModule/test'
  350. import pick from 'lodash.pick'
  351. export default {
  352. name: 'new-mould',
  353. components: {
  354. targetedPopulation,
  355. Treeselect,
  356. creatApplication,
  357. selectCheckAll
  358. },
  359. data() {
  360. return {
  361. allianceAccount:false,
  362. visibleFail: false,
  363. visibleData: null,
  364. checkedTrue: false,
  365. nameValue: '',
  366. visible: false,
  367. timeRange: [],
  368. form: this.$form.createForm(this),
  369. step: 0,
  370. people: '2',
  371. targeted: '2',
  372. topMiddle: false,
  373. topMiddleNo: false,
  374. keyValue: '',
  375. keyValueNo: '',
  376. selectedRowKeys: [],
  377. selectedRowKeysValue: [],
  378. selectedRowKeysNo: [],
  379. selectedRowKeysValueNo: [],
  380. data: [],
  381. populationData: {},
  382. url: {
  383. insertTemplateUrl: '/kuaishou/create/createGroups',
  384. userAllocationList: '/ctop/userAllocation/list',
  385. campaignList: '/kuaishou/kuaiShouCampaignTemplate/list',
  386. getDeepConversionUrl: '/kuaishou/kuaiShouConversionTypes/getIsActivate',
  387. getCampaignTemplate: '/kuaishou/kuaiShouCampaignTemplate/getKuaiShouCampaignTemplate',
  388. appListUrl: '/kuaishou/kuaiShouCreateAppTemplate/list'
  389. },
  390. appList: [],
  391. appId: '',
  392. loading: false,
  393. campaignTemplateId: '',
  394. campaignType: '2',
  395. maxBid: 0,
  396. allForm: {
  397. sceneIdAll: 1,
  398. dayBudget: '0',
  399. time: '1',
  400. scheduleTime: '1',
  401. scheduleTimeData: '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
  402. group: [],
  403. groupTypeData: null,
  404. fail: [],
  405. success: [],
  406. sceneId: [7],
  407. useAppMarket: false,
  408. appStore: ['huawei', 'oppo', 'vivo', 'xiaomi',
  409. 'meizu', 'smartisan'
  410. ],
  411. allianceAccount:'1'
  412. },
  413. typeCopy: "edit",
  414. dataList: [],
  415. unitId: '',
  416. oneCampaignId: '',
  417. copyCampaignId: '',
  418. showSite: false,
  419. siteId: "",
  420. siteList: [],
  421. isUpdateTrackUrl: false,
  422. clickTrackUrl: ""
  423. }
  424. },
  425. computed: {},
  426. filters: {
  427. platform(str) {
  428. var data = {
  429. 1: 'Android应用下载',
  430. 2: 'Android网页游戏',
  431. 3: 'iOS应用下载',
  432. 4: 'iOS网页游戏'
  433. }
  434. return data[str]
  435. }
  436. },
  437. methods: {
  438. getCheck(e) {
  439. this.checkedTrue = e.target.checked
  440. },
  441. resData(index) {
  442. this.allForm.group[index].bid = ''
  443. this.allForm.group[index].cpaBid = ''
  444. this.allForm.group[index].showTipCheck = false
  445. this.allForm.group[index].deepConversionBidCheck = false
  446. this.allForm.group[index].deepConversionType = ''
  447. this.allForm.group[index].deepConversionBid = ''
  448. },
  449. removeGroup(index) {
  450. this.allForm.group.splice(index, 1)
  451. },
  452. deep_conversion_bidTip(index) {
  453. if (
  454. this.allForm.group[index].deepConversionBid < this.allForm.group[index].cpaBid ||
  455. this.allForm.group[index].deepConversionBid > 3000
  456. ) {
  457. this.allForm.group[index].deepConversionBidCheck = true
  458. } else {
  459. this.allForm.group[index].deepConversionBidCheck = false
  460. }
  461. },
  462. checkGroup(e, index) {
  463. if (e.target.value != '') {
  464. getAction('/kuaishou/batch/checkUnitName', {
  465. campaignId: localStorage.getItem('advertisingGroupKey'),
  466. unitName: e.target.value
  467. }).then(res => {
  468. this.allForm.group[index].unitNameCheck = !res.result
  469. })
  470. }
  471. },
  472. showTip(index) {
  473. if (this.allForm.group[index].bidType == 1) {
  474. if (this.allForm.group[index].bid < 0.2 || this.allForm.group[index].bid > this.maxBid) {
  475. this.allForm.group[index].showTipCheck = true
  476. } else {
  477. this.allForm.group[index].showTipCheck = false
  478. }
  479. } else {
  480. if (this.allForm.group[index].cpaBid < 1 || this.allForm.group[index].cpaBid > this.maxBid) {
  481. this.allForm.group[index].showTipCheck = true
  482. } else {
  483. this.allForm.group[index].showTipCheck = false
  484. }
  485. }
  486. },
  487. getScheduleTime(item) {
  488. this.allForm.scheduleTimeData = item
  489. },
  490. setTime(e) {
  491. // console.log(moment('2019-12-27'))
  492. if (e.target.value == '2') {
  493. this.timeRange[0] = moment().startOf('day')
  494. this.timeRange[1] = moment().add(1, 'months')
  495. }
  496. },
  497. setTimeAll(e) {
  498. // console.log(moment('2019-12-27'))
  499. // if (e.target.value == '2') {
  500. // this.$refs.selectCheck.init()
  501. // } else {
  502. // }
  503. },
  504. getData(className) {
  505. return this.form.getFieldValue(className)
  506. },
  507. handleConfirmValue(rule, value, callback) {
  508. if (this.campaignType == '3') {
  509. if (value == '') {
  510. callback('请填写链接')
  511. }
  512. } else if (this.campaignType == '4') {
  513. if (/(http|https):\/\/([\w.]+\/?)\S*/.test(value) && value != '' && value.length < 10000) {
  514. callback()
  515. } else {
  516. callback('链接不能为空且开头为http://或https://,并且长度小于10000')
  517. }
  518. } else if (this.campaignType == '5') {
  519. if (/(http|https):\/\/([\w.]+\/?)\S*/.test(value) && value != '' && value.length < 10000) {
  520. callback()
  521. } else {
  522. callback('链接不能为空且开头为http://或https://,并且长度小于10000')
  523. }
  524. }
  525. },
  526. budgetValue(rule, value, callback) {
  527. if (value < 100 || value > 100000000) {
  528. callback('不小于100,不超过100000000,仅支持输入自然数')
  529. }
  530. callback()
  531. },
  532. handleConfirmBid(rule, value, callback) {
  533. if (this.bid == 0 || this.bid <= 0.2 || this.bid >= 100) {
  534. callback('不得低于0.2元,不得高于100元')
  535. }
  536. callback()
  537. },
  538. handleConfirmCpaBid(rule, value, callback) {
  539. if (this.ocpxActionType == '2' && (this.cpaBid == 0 || this.cpaBid <= 1 || this.cpaBid >= 3000)) {
  540. callback('金额不得低于1元,不得高于3000元')
  541. }
  542. if (this.ocpxActionType == '180' && (this.cpaBid == 0 || this.cpaBid <= 5 || this.cpaBid >= 3000)) {
  543. callback('金额不得低于5元,不得高于3000元')
  544. }
  545. callback()
  546. },
  547. onSelectChange(selectedRowKeys, selectionRows) {
  548. this.selectedRowKeys = selectedRowKeys
  549. this.selectedRowKeysValue = selectionRows.map(item => {
  550. return {
  551. orientationId: item.orientationId,
  552. orientationName: item.orientationName
  553. }
  554. })
  555. },
  556. getCheckboxProps(record) {
  557. return {
  558. props: {
  559. disabled: this.selectedRowKeysValueNo.some(item => item.orientationId === record.orientationId)
  560. }
  561. }
  562. },
  563. onSelectChangeNo(selectedRowKeys, selectionRows) {
  564. this.selectedRowKeysNo = selectedRowKeys
  565. this.selectedRowKeysValueNo = selectionRows.map(item => {
  566. return {
  567. orientationId: item.orientationId,
  568. orientationName: item.orientationName
  569. }
  570. })
  571. },
  572. getCheckboxPropsNo(record) {
  573. return {
  574. props: {
  575. disabled: this.selectedRowKeysValue.some(item => item.orientationId === record.orientationId)
  576. }
  577. }
  578. },
  579. okSelect() {
  580. this.keyValue = ''
  581. this.topMiddle = false
  582. for (let i = 0; i < this.selectedRowKeysValue.length; i++) {
  583. this.keyValue += this.selectedRowKeysValue[i].orientationName + ' '
  584. }
  585. },
  586. okSelectNo() {
  587. this.keyValueNo = ''
  588. this.topMiddleNo = false
  589. for (let i = 0; i < this.selectedRowKeysValueNo.length; i++) {
  590. this.keyValueNo += this.selectedRowKeysValueNo[i].orientationName + ' '
  591. }
  592. },
  593. radioChange() {
  594. this.selectedRowKeys = []
  595. this.selectedRowKeysValue = []
  596. this.selectedRowKeysNo = []
  597. this.selectedRowKeysValueNo = []
  598. this.keyValue = ''
  599. this.keyValueNo = ''
  600. },
  601. addApplication() {
  602. this.$refs.application.showApplication()
  603. },
  604. handleOk(item, type, campaignId, unitNameCopy, isUpdateTrackUrl, clickTrackUrl) {
  605. this.visible = true
  606. this.showSite = false
  607. this.isUpdateTrackUrl = isUpdateTrackUrl
  608. this.clickTrackUrl = clickTrackUrl
  609. // /kuaishou/batch/getUnitDetail
  610. this.typeCopy = type
  611. if (campaignId) {
  612. this.oneCampaignId = item.campaignId
  613. this.copyCampaignId = campaignId
  614. }
  615. console.log(item.campaignId, campaignId)
  616. this.unitId = item.unitId
  617. var params = {}
  618. params.accountId = item.accountId
  619. params.unitId = item.unitId
  620. getAction('/kuaishou/batch/getUnitDetail', params).then(res => {
  621. if (res.success) {
  622. var dataJson = {
  623. ...res.result.baseInfo,
  624. ...res.result.appInfo,
  625. ...res.result.target
  626. }
  627. // dataJson.useAppMarket = dataJson.useAppMarket==0?false:true
  628. this.allForm.sceneIdAll = JSON.parse(dataJson.sceneId).filter(item => item == 1).length > 0 ? 1 : JSON.parse(dataJson.sceneId)[0] ==5 ? 5 : 2
  629. this.allForm.allianceAccount = this.allForm.sceneIdAll==5?'2':'1'
  630. this.allForm.useAppMarket = dataJson.useAppMarket ? (dataJson.useAppMarket == 0 ? false : true) : false
  631. this.allForm.appStore = this.allForm.useAppMarket ? JSON.parse(dataJson.appStore) : ['huawei', 'oppo',
  632. 'vivo', 'xiaomi',
  633. 'meizu', 'smartisan'
  634. ]
  635. this.allForm.sceneId = this.allForm.sceneIdAll == 1 ? [7] : JSON.parse(res.result.baseInfo
  636. .sceneId)
  637. console.log(this.allForm.sceneId, 1111111)
  638. this.allForm.dayBudget = dataJson.dayBudget == 0 ? '0' : '1'
  639. dataJson.dayBudget = dataJson.dayBudget / 1000
  640. this.allForm.time = dataJson.endTime ? '2' : '1'
  641. this.timeRange = [moment(dataJson.beginTime), moment(dataJson.endTime)]
  642. this.allForm.scheduleTime = dataJson.scheduleTime.indexOf('1') != -1 ? '2' : '1'
  643. this.allForm.scheduleTimeData = dataJson.scheduleTime
  644. this.allForm.group = [{
  645. bidType: dataJson.bidType,
  646. bid: dataJson.bid,
  647. cpaBid: dataJson.cpaBid / 1000,
  648. showTipCheck: false,
  649. deepConversionBidCheck: false,
  650. unitName: unitNameCopy ? unitNameCopy : dataJson.unitName,
  651. unitNameCheck: false,
  652. deepConversionType: dataJson.deepConversionType,
  653. deepConversionBid: dataJson.deepConversionBid / 1000,
  654. ocpxActionType:dataJson.ocpxActionType
  655. }]
  656. this.populationData = dataJson
  657. this.populationData.population = dataJson.population ? JSON.parse(dataJson.population) : null
  658. this.populationData.excludePopulation = dataJson.excludePopulation ? JSON.parse(dataJson
  659. .excludePopulation) :
  660. null
  661. this.populationData.devicePrice = dataJson.devicePrice ? JSON.parse(dataJson.devicePrice) : null
  662. this.populationData.appInterest = dataJson.appInterest ? JSON.parse(dataJson.appInterest) : null
  663. this.populationData.businessInterest = dataJson.businessInterest ?
  664. JSON.parse(dataJson.businessInterest) :
  665. null
  666. this.populationData.fansStar = dataJson.fansStar ? JSON.parse(dataJson.fansStar) : null
  667. this.populationData.interestVideo = dataJson.interestVideo ? JSON.parse(dataJson.interestVideo) : null
  668. this.populationData.deviceBrand = dataJson.deviceBrand ? JSON.parse(dataJson.deviceBrand) : null
  669. this.populationData.age = dataJson.ageMin ? [dataJson.ageMin, dataJson.ageMax] : []
  670. this.populationData.agesRange = dataJson.agesRange ? JSON.parse(dataJson.agesRange) : []
  671. this.populationData.devicePrice = dataJson.devicePrice ? dataJson.devicePrice : null
  672. this.populationData.allForm = {}
  673. this.populationData.allForm.regionType =
  674. dataJson.region && JSON.parse(dataJson.region).length > 0 ? 'limit' : 'noLimit'
  675. this.populationData.allForm.region = dataJson.region
  676. // postAction('/kuaishou/batch/getRegionDetail', {
  677. // regionArr: dataJson.region
  678. // }).then(res => {
  679. // console.log(res, 11111)
  680. // if (res.success) {
  681. // this.populationData.allForm.region = res.result
  682. // }
  683. // })
  684. this.populationData.allForm.ageType =
  685. dataJson.agesRange.length > 0 ? 'ageLimit' : dataJson.ageMin ? 'ageCustom' : 'noLimit'
  686. this.populationData.allForm.device = dataJson.deviceBrand ? '1' : '0'
  687. this.populationData.allForm.price = dataJson.devicePrice ? '1' : '0'
  688. this.populationData.allForm.appType = dataJson.appInterest ? '1' : dataJson.appIds ? '2' : '0'
  689. this.populationData.allForm.fansStar = dataJson.fansStar ? '1' : '0'
  690. this.populationData.allForm.interestVideo = dataJson.interestVideo ? '1' : '0'
  691. this.populationData.allForm.platform_os = dataJson.platformOs
  692. this.populationData.allForm.businessInterestType = dataJson.businessInterest ? 2 : 0
  693. this.populationData.allForm.isOpen = dataJson.isOpen
  694. this.populationData.allForm.noAgeBreak = dataJson.noAgeBreak + ''
  695. this.populationData.allForm.noGenderBreak = dataJson.noGenderBreak + ''
  696. this.populationData.allForm.noAreaBreak = dataJson.noAreaBreak + ''
  697. this.populationData.allForm.checkArr = this.populationData.allForm.appType == '2' ? JSON.parse(dataJson
  698. .appIds) : []
  699. this.$nextTick(() => {
  700. console.log(dataJson)
  701. this.form.setFieldsValue(pick(dataJson, ['appId', 'urlType', 'url', 'dayBudget', 'speed',
  702. 'showMode'
  703. ]))
  704. // this.form.setFieldsValue({
  705. // appId: dataJson.appId
  706. // })
  707. // this.form.setFieldsValue({
  708. // dayBudget: dataJson.dayBudget
  709. // })
  710. // this.form.setFieldsValue({
  711. // speed: dataJson.speed
  712. // })
  713. // this.form.setFieldsValue({
  714. // showMode: dataJson.showMode
  715. // })
  716. // console.log(dataJson.sceneId)
  717. // this.form.setFieldsValue({
  718. // sceneId: dataJson.sceneId
  719. // })
  720. })
  721. }
  722. })
  723. },
  724. handleCancel(e) {
  725. this.visible = false
  726. },
  727. handleSubmit(e) {
  728. // this.$refs.population.handleSubmit()
  729. e.preventDefault()
  730. this.$refs.population.handleSubmit()
  731. this.form.validateFieldsAndScroll((err, values) => {
  732. if (!err) {
  733. this.loading = true
  734. var groupArr = this.allForm.group.map(item => {
  735. return {
  736. ...item,
  737. cpaBid: item.cpaBid != '' ? item.cpaBid * 1000 : '',
  738. bid: item.bid != '' ? item.bid * 1000 : '',
  739. deepConversionBid: item.deepConversionBid != '' ? item.deepConversionBid * 1000 : '',
  740. ocpxActionType: item.ocpxActionType,
  741. bidType: item.bidType == 1 ? 2 : 10
  742. }
  743. })[0]
  744. var json = {
  745. ...values,
  746. // sceneId: this.allForm.sceneIdAll == 1 ? [this.allForm.sceneIdAll] : this.allForm.sceneId,
  747. sceneId: this.allForm.allianceAccount=='1'?this.allForm.sceneIdAll == 1 ? [this.allForm.sceneIdAll] : this.allForm.sceneId:[5],
  748. dayBudget: values.dayBudget * 1000
  749. }
  750. var params = {
  751. ...this.populationData,
  752. ...json,
  753. accountId: localStorage.getItem('accountId'),
  754. unitId: this.unitId,
  755. unitType: 4,
  756. beginTime: this.allForm.time == '2' ? moment(this.timeRange[0]).format('YYYY-MM-DD') : moment()
  757. .startOf('day').format('YYYY-MM-DD'),
  758. endTime: this.allForm.time == '2' ? moment(this.timeRange[1]).format('YYYY-MM-DD') : '',
  759. scheduleTime: this.allForm.scheduleTimeData
  760. }
  761. if (this.allForm.useAppMarket == true || this.allForm.useAppMarket == false) {
  762. params.useAppMarket = this.allForm.useAppMarket ? 1 : 0
  763. if (this.allForm.useAppMarket == true) {
  764. params.appStore = this.allForm.appStore
  765. }
  766. }
  767. if (this.isUpdateTrackUrl) {
  768. if (this.showSite && (this.getPlatForm(this.getData('appId')) == '1' || this.getPlatForm(this.getData(
  769. 'appId')) == '2')) {
  770. params.otherJson = {
  771. isUpdate: true,
  772. siteId: this.siteId,
  773. isUpdateTrackUrl: true,
  774. clickTrackUrl: this.clickTrackUrl
  775. }
  776. } else {
  777. params.otherJson = {
  778. isUpdateTrackUrl: true,
  779. clickTrackUrl: this.clickTrackUrl,
  780. isUpdate: false
  781. }
  782. }
  783. } else {
  784. if (this.showSite && (this.getPlatForm(this.getData('appId')) == '1' || this.getPlatForm(this.getData(
  785. 'appId')) == '2')) {
  786. params.otherJson = {
  787. isUpdate: true,
  788. siteId: this.siteId,
  789. isUpdateTrackUrl: false,
  790. }
  791. } else {
  792. params.otherJson = {
  793. isUpdate: false,
  794. isUpdateTrackUrl: false,
  795. }
  796. }
  797. }
  798. if (this.checkedTrue) {
  799. var data = this.populationData
  800. postAction('/kuaishou/batch/addDirectionalTemplate', {
  801. accountId: localStorage.getItem('accountId'),
  802. templateName: this.nameValue,
  803. templateContent: JSON.stringify(this.populationData)
  804. }).then(res => {})
  805. }
  806. if(this.allForm.allianceAccount=='1'){
  807. var {...paramsEnd} = params
  808. }else{
  809. var {fansStar,appType,businessInterestType,interestVideo,isOpen,noAgeBreak,noGenderBreak,noAreaBreak,...paramsElse} = params.allForm
  810. params.allForm = paramsElse
  811. var {businessInterestType,isOpen,noAgeBreak,noGenderBreak,noAreaBreak,...paramsEnd} = params
  812. }
  813. if (this.typeCopy == 'edit') {
  814. var param = {
  815. ...paramsEnd,
  816. ...groupArr
  817. }
  818. postAction('/kuaishou/batch/updateUnit', param).then(res => {
  819. if (res.result.code == 0) {
  820. this.visible = false
  821. this.$emit('getList', localStorage.getItem('advertisingGroupKey'))
  822. this.loading = false
  823. } else {
  824. this.loading = false
  825. this.$message.error(res.result.message)
  826. }
  827. })
  828. } else if (this.typeCopy == 'copy') {
  829. paramsEnd.type = 'copy'
  830. paramsEnd.copyUnitId = this.unitId
  831. paramsEnd.copyToCampaignId = this.copyCampaignId
  832. paramsEnd.campaignId = this.oneCampaignId
  833. paramsEnd.createCount = 1
  834. paramsEnd.groupArr = [groupArr]
  835. postAction('/kuaishou/batch/copyUnit', paramsEnd).then(res => {
  836. if (res.success) {
  837. if (res.result.failCount > 0) {
  838. this.visibleFail = true
  839. this.visibleData = res.result
  840. this.loading = false
  841. } else {
  842. var that = this
  843. setTimeout(() => {
  844. that.visible = false
  845. that.loading = false
  846. that.$emit('getList', localStorage.getItem('advertisingGroupKey'))
  847. }, 1000)
  848. }
  849. } else {
  850. this.$message.error(res.message)
  851. }
  852. })
  853. }
  854. }
  855. })
  856. },
  857. onChange(e) {
  858. this.allForm.useAppMarket = e.target.checked
  859. // console.log(value)
  860. },
  861. getPageList(appId) {
  862. getAction('/kuaishou/batch/getPageList', {
  863. accountId: localStorage.getItem('accountId'),
  864. appId: appId,
  865. viewComp: 7
  866. }).then(res => {
  867. if (res.success) {
  868. console.log(res)
  869. this.siteList = res.result
  870. }
  871. })
  872. },
  873. handleChange(value) {
  874. // this.$refs.population.getAppList(value)
  875. if (value == this.getData('appId')) {
  876. this.showSite = false
  877. } else {
  878. this.showSite = true
  879. this.siteId = ''
  880. this.getPageList(value)
  881. }
  882. },
  883. handleChangeMould(value) {
  884. if (value) {
  885. this.populationData = JSON.parse(
  886. this.dataList.filter(item => {
  887. return item.id == value
  888. })[0].templateContent
  889. )
  890. } else {
  891. this.populationData = {}
  892. }
  893. },
  894. getPlatForm(appId) {
  895. if (appId) {
  896. var data = this.appList.filter(item => {
  897. return item.appId == appId
  898. })
  899. return data[0].platform
  900. }
  901. },
  902. handleBlur() {
  903. console.log('blur')
  904. },
  905. handleFocus() {
  906. console.log('focus')
  907. },
  908. filterOption(input, option) {
  909. return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
  910. },
  911. prevStep() {
  912. this.$emit('prevStep', this.campaignId ? this.campaignId : localStorage.getItem('advertisingGroupKey'))
  913. },
  914. getMould() {
  915. let params = {}
  916. params.accountId = localStorage.getItem('accountId')
  917. getAction('/kuaishou/batch/getDirectionalTemplate', params).then(res => {
  918. console.log(res)
  919. if (res.success) {
  920. this.dataList = res.result.map((item, index) => {
  921. return {
  922. ...item,
  923. key: index
  924. }
  925. })
  926. }
  927. })
  928. },
  929. getAppList() {
  930. let params = {}
  931. params.accountId = localStorage.getItem('accountId')
  932. getAction('/kuaishou/batch/getAppList', params).then(res => {
  933. if (res.success) {
  934. this.appList = res.result.map((item, index) => {
  935. return {
  936. ...item,
  937. key: index
  938. }
  939. })
  940. }
  941. })
  942. },
  943. getCampaignList() {
  944. var params = {}
  945. params.accountId = localStorage.getItem('accountId')
  946. params.campaignId = this.campaignId ? this.campaignId : localStorage.getItem('advertisingGroupKey')
  947. getAction('/kuaishou/batch/getCampaignList', params).then(res => {
  948. if (res.success) {
  949. this.campaignType = res.result.records[0].campaignType
  950. }
  951. })
  952. },
  953. },
  954. activated: function () {
  955. this.getAppList()
  956. this.getCampaignList()
  957. this.getMould()
  958. getAction('/kuaishou/batch/getIsActivate', {
  959. accountId: localStorage.getItem('accountId')
  960. }).then(res => {
  961. if (res.success) {
  962. this.allForm.groupTypeData = res.result
  963. }
  964. })
  965. getAction('/kuaishou/batch/getWhiteList',{
  966. accountId:localStorage.getItem('accountId')
  967. }).then(res=>{
  968. if(res.success){
  969. console.log(res)
  970. if(res.result){
  971. if(res.result.alliance_account == 1){
  972. this.allianceAccount = true
  973. }else{
  974. this.allianceAccount = false
  975. }
  976. }else{
  977. this.allianceAccount = false
  978. }
  979. }
  980. })
  981. getAction('/kuaishou/batch/getProjectMaxBid', {
  982. accountId: localStorage.getItem('accountId')
  983. }).then(res => {
  984. if (res.success) {
  985. this.maxBid = res.result / 1000
  986. }
  987. })
  988. }
  989. }
  990. </script>