猎羽广告

index.vue 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  1. <template>
  2. <div class="flex titleBox">
  3. <span>程序化批量/广点通</span>
  4. </div>
  5. <div class="areaBox" style="margin-top:10px;">
  6. <div class="areaTitle">
  7. 配置区
  8. <el-button class="lMar20" type="primary" @click="openStrategyGroups">选择策略组</el-button>
  9. <span class="smallTitle lMarauto">预览广告数 : <span class="c-theme">{{NumberHandle(pageInfo.num_total.adNum)||0}}</span></span>
  10. </div>
  11. <div class="areaCon">
  12. <div class="screenArea">
  13. <Select ref="accRef"
  14. :clearFlag="true"
  15. :isMultiple="true"
  16. title="媒体账户"
  17. selectWidth="160px"
  18. @clearEvent="accClearEvent"
  19. @changeEvent="accEvent"
  20. @visibleEvent="accVisibleEvent"
  21. :optObj="{k:'account_id',la:'account_id',val:'account_id'}"
  22. :options="pageInfo.accountList"/>
  23. <Select ref="targetRef"
  24. :clearFlag="false"
  25. title="推广目标"
  26. selectWidth="160px"
  27. :optObj="{k:'name',la:'desc',val:'name'}"
  28. @changeEvent="targetChange"
  29. :options="pageInfo.targetList"/>
  30. <el-button type="primary" class="lMarauto" @click="openRuleConfig">规则配置</el-button>
  31. </div>
  32. <div class="configArea">
  33. <div v-for="item in pageInfo.adTitleList" :key="item.id"
  34. :style=" {width:item.name == '广告' ? 'calc((100vw - 40px - 32px) / 6 * 2)' : 'calc((100vw - 40px - 32px) / 6 * 4)'}">
  35. <div class="bigTitle" :class="item.name == '广告创意' ? 'no_left_boder' : ''">{{item.name}}</div>
  36. <div class="flex">
  37. <div class="blockBox" v-for="sub in item.subList" :key="sub.id" :class="sub.name == '广告基本信息' ? '' : 'no_left_boder'">
  38. <div class="smallTitle">
  39. {{sub.name}}
  40. <span class="chooseCss" v-if="sub.haveChooseNum">已选: {{NumberHandle(sub.chooseNum) || 0}}</span>
  41. </div>
  42. <div class="showInfoArea">
  43. <template v-if="sub.name == '创意文案'">
  44. <Copywriter ref="CopywriterRef" :num_total="pageInfo.num_total" :basicInfoData="basicInfoData.fillBack" :adTemplateItem="originalityBasicInfoData?.apiResult?.adTemplateItem || {}" @writerCallBack="writerCallBack"></Copywriter>
  45. </template>
  46. <template v-if="sub.name == '落地页'">
  47. <LandPage ref="LandPageRef" :accIdsList="pageInfo.accIdsList" :page_type="originalityBasicInfoData?.receiveForm?.landingPageExample?.page_type" @landPage="landPageEvent"></LandPage>
  48. </template>
  49. <div class="noData" v-if="!sub.haveContent">暂无数据 </div>
  50. <!-- 定向包展示 -->
  51. <template v-if="sub.name == '定向包'">
  52. <DirectPacketExhibition :showFlag="sub.haveContent" ref="DirectPacketExhibitionRef" @updateHaveContent="updateHaveContent"></DirectPacketExhibition>
  53. </template>
  54. <div v-if="sub.name == '广告基本信息'">
  55. <template v-for="(item) in basicInfoData.copywriting">
  56. <div class="bMar8 lH16 c-515a6e" v-if="item?.indexOf('投放日期:') != -1">{{ item }}{{Number(pageInfo.RuleConfigObj?.start_day) > 0 ? `- 规则配置已设置自动延后 ${pageInfo.RuleConfigObj?.start_day} 天,实际开始日期为:${AddDays(basicInfoData?.fillBack?.begin_date, Number(pageInfo?.RuleConfigObj?.start_day))}` : ''}}</div>
  57. <div class="bMar8 lH16 c-515a6e" v-else>{{ item }}</div>
  58. </template>
  59. </div>
  60. <div v-if="sub.name == '创意基本信息'">
  61. <template v-for="(main_item, main_index) in originalityBasicInfoData.receiveForm">
  62. <template v-if="String(main_index) == 'profiles' || String(main_index) == 'brand'">
  63. <div class="bMar8 lH16 c-515a6e">{{ `${String(main_index) == 'brand' ? '品牌名称' : '昵称'}:` }}{{ main_item.api_value.name }}</div>
  64. <div class="bMar8 lH16 c-515a6e">{{ `${String(main_index) == 'brand' ? '品牌标识图' : '头像'}:` }}
  65. <img :src="main_item.api_value.oss_url" class="oss_url_img" alt="">
  66. </div>
  67. </template>
  68. <template v-if="main_item.copywriting && main_item.copywriting.length > 0">
  69. <template v-for="item in main_item.copywriting">
  70. <div class="bMar8 lH16 c-515a6e">{{ item }}</div>
  71. </template>
  72. </template>
  73. </template>
  74. </div>
  75. <div v-if="sub.name == '创意素材'">
  76. <template v-for="cItem in cMaterial.list" :key="cItem.id">
  77. <div class="flex bMar8">
  78. <template v-for="cSub in cItem.list" :key="cItem.id+cSub.subId">
  79. <div class="flex" style="width: 100%;justify-content: center"
  80. v-if="cMaterial.haveCoverOrVideo == 2 || cMaterial.haveCoverOrVideo == 1">
  81. <video :src="cSub.videoUrl" height="50"></video>
  82. </div>
  83. <div style="width: 100%;justify-content: center" class="lMar10 flex" v-if="cMaterial.haveCoverOrVideo == 3 || cMaterial.haveCoverOrVideo == 1">
  84. <img :src="cSub.picUrl" height="50"/>
  85. </div>
  86. </template>
  87. </div>
  88. </template>
  89. </div>
  90. </div>
  91. <div class="btn" @click="openDialogEvent(sub)">{{sub.haveContent ? '编辑' : '添加'}}</div>
  92. </div>
  93. </div>
  94. </div>
  95. </div>
  96. <div class="btnArea">
  97. <span class="" v-if="pageInfo.accIdsList && pageInfo.accIdsList.length>0">
  98. <template v-for="(item,index) in basicInfoData.outerConfig">
  99. <el-button plain class="rMar10 outerButton" v-if="item.enabled" @click="basicOuterClick(index)">
  100. <el-icon :class="['outerIcon', !item.isComplete || 'outerIconActive']"><CircleCheck v-if="!item.isComplete" /><SuccessFilled v-else/></el-icon>
  101. {{item.name}}
  102. </el-button>
  103. </template>
  104. </span>
  105. <span class="lMarauto">
  106. <el-button type="primary" @click="openPreAreaEvent" v-loading.fullscreen.lock="openPreAreaLoading">批量预览广告</el-button>
  107. <el-button type="primary" @click="openSaveStrategyGroups" v-loading.fullscreen.lock="openPreAreaLoading">保存策略组</el-button>
  108. </span>
  109. </div>
  110. </div>
  111. </div>
  112. <!-- 预览区-->
  113. <PreviewArea ref="PreviewAreaRef" @continueCreate="continueCreate"></PreviewArea>
  114. <!--规则配置-->
  115. <RuleConfig ref="RuleConfigRef" @ExposeEvent="val=>pageInfo.RuleConfigObj = val"></RuleConfig>
  116. <!-- 创意素材-->
  117. <!-- :max_creative_num="pageInfo.RuleConfigObj?.adcreative_max || 0" -->
  118. <CreativeMaterial ref="CreativeMaterialRef"
  119. :haveCoverOrVideo="cMaterial.haveCoverOrVideo"
  120. :haveShowVideoObj = "cMaterial.haveShowVideoObj"
  121. :video_tips="cMaterial.video_tips"
  122. :image_tips="cMaterial.image_tips"
  123. @closeLoading="close_reuse_loading"
  124. :maxNum_imageList="cMaterial.array_property?.max_number || 1"
  125. @assignEvent="assignEvent_CreativeMaterial"></CreativeMaterial>
  126. <!-- 创意基本信息 -->
  127. <OriginalityBasic ref="originalityBasicRef" :visible="originalityBasicInfoData.visible" :key="originalityBasicInfoData.positionKey"
  128. :adBasicInfo="basicInfoData.fillBack" :accIdsList="pageInfo.accIdsList"
  129. :promoted_object_type="pageInfo.targetValue" @close="originalityBasicClose"
  130. @submitIsOver="switch_complate_flag_creaBasicInfo"
  131. ></OriginalityBasic>
  132. <!-- 广告基本信息 -->
  133. <BasicInfo :visible="basicInfoData.visible"
  134. :dataFillBack="basicInfoData.fillBack"
  135. :promoted_object_type="pageInfo.targetValue"
  136. :ruleConfigObj="pageInfo.RuleConfigObj"
  137. @close="basicInfoClose"></BasicInfo>
  138. <!-- 扩量种子人群 -->
  139. <ExpandPopulation :visible="basicInfoData.outerConfig.expandPopulation.visible" :accIdsList="pageInfo.accIdsList" :fillback="basicInfoData.outerConfig['expandPopulation'].value" @close="(obj)=>{basicOuterClose({val: obj?.val || null, type: obj?.type || null, key:'expandPopulation'})}" title="扩量种子人群"></ExpandPopulation>
  140. <!-- 一方数据助攻 - 智能定向 -->
  141. <ExpandPopulation :visible="basicInfoData.outerConfig.targetingPartyData.visible" :accIdsList="pageInfo.accIdsList" :fillback="basicInfoData.outerConfig['targetingPartyData'].value" @close="(obj)=>{basicOuterClose({val: obj?.val || null, type: obj?.type || null, key:'targetingPartyData'})}" title="一方数据助攻"></ExpandPopulation>
  142. <!-- 精准匹配归因 -->
  143. <AttributionOuter :visible="basicInfoData.outerConfig.attributionOuter.visible" :accIdsList="pageInfo.accIdsList" :fillback="basicInfoData.outerConfig['attributionOuter'].value" @close="(obj)=>{basicOuterClose({val: obj?.val || null, type: obj?.type || null , key:'attributionOuter'})}"></AttributionOuter>
  144. <!-- 配置视频号 -->
  145. <WeChatVideoAccount :visible="basicInfoData.outerConfig.weChatVideoAccount.visible" :accIdsList="pageInfo.accIdsList" :fillback="basicInfoData.outerConfig['weChatVideoAccount']" :acc_plan_ad_count="pageInfo.acc_plan_ad_count" @close="(obj: IOuterConfigRule)=>{basicOuterClose({ ...obj, key:'weChatVideoAccount'})}"></WeChatVideoAccount>
  146. <!-- 优量汇流量包 -->
  147. <UnionPosition :visible="basicInfoData.outerConfig.unionPosition.visible" :accIdsList="pageInfo.accIdsList" :infoSelect="basicInfoData.outerConfig.unionPosition.infoSelect" :fillback="basicInfoData.outerConfig['unionPosition'].value" @close="(obj)=>{basicOuterClose({val: obj?.val || null, type: obj?.type || null , key:'unionPosition'})}"></UnionPosition>
  148. <!-- 复用配置 -->
  149. <ResuseConfig ref="ResuseConfigRef" @aNewConfig="aNewConfigEvent" @reuse="reuseEvent"></ResuseConfig>
  150. <!-- 策略组列表 -->
  151. <StrategyGroupsList ref="StrategyGroupsListRef"></StrategyGroupsList>
  152. <!-- 保存策略组弹框 -->
  153. <StrategyGroupsDialog ref="StrategyGroupsDialogRef"></StrategyGroupsDialog>
  154. </template>
  155. <script setup lang="ts">
  156. import {getCurrentInstance, nextTick, onMounted, reactive, ref, provide, computed,toRef,watch} from "vue";
  157. import {adqParam, reactiveTableAndAny} from "@/api/ApiModel";
  158. import Select from '@/components/capsulationMoudle/_select.vue'
  159. import DirectPacketExhibition from '@/components/businessMoudle/batchGdt/configArea/directPacket/echoIndex.vue'
  160. import RuleConfig from '@/components/businessMoudle/batchGdt/configArea/ruleConfig/index.vue'
  161. import CreativeMaterial from '@/components/businessMoudle/batchGdt/configArea/creativeMaterial/index.vue'
  162. import ResuseConfig from '@/components/businessMoudle/batchGdt/configArea/resuseConfig/index.vue'
  163. import PreviewArea from '@/components/businessMoudle/batchGdt/previewArea/index.vue'
  164. import {Api} from "@/api/api";
  165. import {ElMessage} from "element-plus";
  166. import BasicInfo from "./basicInfo/index.vue";
  167. import ExpandPopulation from './basicInfo/expandPopulation.vue'
  168. import AttributionOuter from './basicInfo/attributionOuter.vue'
  169. import WeChatVideoAccount from './basicInfo/weChatVideoAccount.vue'
  170. import UnionPosition from './basicInfo/unionPosition.vue'
  171. import OriginalityBasic from './originalityBasic/index.vue'
  172. import Copywriter from './copywriter/index.vue'
  173. import LandPage from "./landPage/index.vue";
  174. import { getPromotedObjectType } from './basicInfo/ts/basicApi'
  175. import _ from "lodash";
  176. import { previewCompute } from './ts/preview'
  177. import { submitPreview } from './ts/submitPreview'
  178. import { materialDeclare, handleMultiple } from './ts/material'
  179. import { IOuterConfigRule, basicInfoDeclare, handleAdBasic} from './ts/adBasic'
  180. import { resuseConfigEvent} from './ts/resuseConfigTs'
  181. import handleJudge from './ts/judgeEvent'
  182. import { mockEvent } from './ts/mock'
  183. import { AddDays } from "@/common/common";
  184. import StrategyGroupsList from './strategyGroups/list.vue'
  185. import StrategyGroupsDialog from './strategyGroups/saveDialog.vue'
  186. import { strategyGroupsEvent } from './ts/strategyGroups'
  187. const { proxy } = getCurrentInstance() as any;
  188. // 全局方法定义
  189. const NumberHandle = proxy.$NumberHandle
  190. // S 参数声明
  191. const {
  192. basicInfoData
  193. } = basicInfoDeclare()
  194. const {
  195. CreativeMaterialRef,
  196. cMaterial
  197. } = materialDeclare()
  198. // E 参数声明
  199. const targetRef = ref<{value:any}>()
  200. const originalityBasicRef = ref()
  201. const pageInfo = reactive<reactiveTableAndAny>({
  202. last_ad_show_list:[],//最终需要的数组
  203. num_total: {
  204. accNum:0,//账号数
  205. planNum:0,//计划数
  206. adNum:0,//预览广告数
  207. },
  208. targetValue: '',
  209. targetList:[],
  210. adTitleList:[
  211. {id:1,name:'广告',subList:[
  212. { id:2,name:'广告基本信息',haveContent:false },
  213. { id:3,name:'定向包',chooseNum:0,haveChooseNum:true,haveContent:false },
  214. ]},
  215. {id:4,name:'广告创意',subList:[
  216. { id:5,name:'创意基本信息',haveContent:false },
  217. { id:6,name:'创意素材',chooseNum:0,haveChooseNum:true,haveContent:false },
  218. { id:7,name:'创意文案',chooseNum:0,haveChooseNum:true,haveContent:false },
  219. { id:8,name:'落地页',chooseNum:0,haveChooseNum:true,haveContent:false },
  220. ]},
  221. ],
  222. accountList:[],
  223. accIdsList:[],//选中的格式化后的账户列表
  224. accIdsList_copy_last:[],//选中的格式化后的账户列表
  225. directObj:{},//定向包展示的数据
  226. RuleConfigObj:{},//规则配置的值
  227. copywriterInfoData: {//创意文案
  228. data: [],
  229. allocation_type: '',//分配形式 1自动分配 2程序化相乘分配
  230. },
  231. copyLandPageInfoData: {//落地页
  232. data: [],
  233. allocation_type: '',//分配形式 1自动分配 2程序化相乘分配
  234. loadPageRule: 0, //0 全部相同 //1 按账户分配 //2 分配到计划 // 3分配到广告
  235. },
  236. acc_plan_ad_count: {}, //各账户对应的计划数、广告数;用于微信视频号的配置
  237. })
  238. //创意基本信息
  239. const originalityBasicInfoData = reactive<any>({
  240. positionKey: 0,//广告基本信息版位变化+1
  241. receiveForm: {},//自己操作的form
  242. apiResult: {},//接口返回的数据
  243. params: [],//接口需要的数据
  244. })
  245. //创意文案
  246. const CopywriterRef = ref()
  247. const LandPageRef = ref()
  248. //获取账号列表
  249. const get_account_list = async () => {
  250. const paramsModel = reactive<adqParam>({
  251. page:1,
  252. page_size:10000,
  253. })
  254. let res:any = await proxy.$http.get(Api.adq_list,paramsModel)
  255. if(res&&res.errNo=='0'){
  256. pageInfo.accountList = res.rst.data
  257. }else{
  258. ElMessage.error(res.errMsg)
  259. }
  260. }
  261. //创意基本信息是否上传完成
  262. const resuse_complate_flag_creaBasicInfo=ref<boolean>(false)
  263. const switch_complate_flag_creaBasicInfo = (val:any)=>{
  264. resuse_complate_flag_creaBasicInfo.value = val
  265. }
  266. watch(()=>resuse_complate_flag_creaBasicInfo.value,async (val)=>{
  267. if(val){
  268. // 创意素材 - 修改或者新增
  269. await CreativeMaterialRef.value?.deleAcEvent(pageInfo.accIdsList,false)
  270. CreativeMaterialRef.value?.creatice_reuseEvent()
  271. }
  272. })
  273. //创意素材清空
  274. const CreativeMaterial_clear = () => {
  275. nextTick(()=> {
  276. CreativeMaterialRef.value?.clearAllEvent()
  277. updateHaveContent(6, 0, false, true)
  278. })
  279. }
  280. //推广目标
  281. const targetChange = () => {
  282. pageInfo.targetValue = targetRef.value?.value
  283. }
  284. //打开规则配置
  285. const RuleConfigRef = ref<{switchShow:(val:boolean)=>void}>()
  286. const openRuleConfig = () => {
  287. nextTick(()=>{
  288. RuleConfigRef.value?.switchShow(true)
  289. })
  290. }
  291. // 得到规则配置的值
  292. const get_ruleConfig_info = async () => {
  293. let res:any = await proxy.$http.get(Api.ruleConfig_get)
  294. if(res&&res.errNo=='0'){
  295. let resNew:any = res.rst
  296. pageInfo.RuleConfigObj = resNew
  297. }else{
  298. ElMessage.error(res.errMsg)
  299. }
  300. }
  301. //监听创意素材点击了确定
  302. watch(()=>cMaterial.key,()=>{
  303. cMaterial.list = _.cloneDeep(cMaterial.list_copy)
  304. let num = cMaterial.list&&cMaterial.list.length
  305. updateHaveContent(6,num)
  306. })
  307. // 定向包
  308. const DirectPacketExhibitionRef = ref<{get_echoAcId:()=>void,
  309. showDirectPacket:()=>void,
  310. clearDirectContent:()=>void,
  311. AcChangeEvent:(arr:any)=>void
  312. // addAcEvent:(arr:any)=>void,deleAcEvent:(arr:any)=>void
  313. }>()
  314. // 打开添加 / 编辑
  315. const openDialogEvent = async (sub:any) => {
  316. if( !judgeEvent( sub.id ) ) return; // 判断是否完成前一模块
  317. if(sub.name == '定向包'){
  318. nextTick(()=>{
  319. if(DirectPacketExhibitionRef.value) { DirectPacketExhibitionRef.value[0]?.showDirectPacket() }
  320. if(sub.haveContent){
  321. if(DirectPacketExhibitionRef.value) { DirectPacketExhibitionRef.value[0]?.get_echoAcId() }
  322. }
  323. })
  324. }
  325. if(sub.name == '广告基本信息'){
  326. basicInfoData.visible = true;
  327. }
  328. if(sub.name == '创意基本信息'){
  329. if (basicInfoData.fillBack?.automatic_site && basicInfoData.fillBack?.automatic_site != ''){
  330. originalityBasicRef.value?.switchShow(true, {
  331. 'fillback': originalityBasicInfoData.receiveForm,
  332. 'apiResult': originalityBasicInfoData.apiResult,
  333. })
  334. } else {
  335. ElMessage.error('请完善广告基本信息!')
  336. }
  337. }
  338. if(sub.name == '创意素材'){
  339. await get_cover_info()
  340. console.log('cMaterial', cMaterial)
  341. console.log('打开之前CreativeMaterialRef',cMaterial.list);
  342. CreativeMaterialRef.value?.switchShow(true,sub.haveContent,cMaterial.list,cMaterial.testNew_text)
  343. console.log(cMaterial.array_property);
  344. }
  345. if(sub.name == '创意文案' && CopywriterRef.value){
  346. CopywriterRef.value[0]?.initFun(true)
  347. }
  348. if(sub.name == '落地页' && LandPageRef.value){
  349. LandPageRef.value[0]?.initFun(true, pageInfo.num_total, pageInfo.last_ad_show_list)
  350. }
  351. }
  352. //更新数值,判断是否有内容
  353. const updateHaveContent = (id:number,chooseNum?:number,minusFlag?:boolean,clearFlag?:boolean) => {
  354. nextTick(()=>{
  355. // id : adTitleList的id chooseNum: 选中的个数 minusFlag:是否需要减少
  356. if(clearFlag){ //清空
  357. pageInfo.adTitleList.forEach(i=>{
  358. i.subList.forEach(s=>{
  359. if(s.id == id){
  360. s.haveContent = false
  361. s.chooseNum = 0
  362. }
  363. })
  364. })
  365. }else{
  366. if(id == 3){
  367. if(DirectPacketExhibitionRef.value){
  368. pageInfo.directObj = DirectPacketExhibitionRef.value[0]?.getObjValue()
  369. }
  370. //清空落地页
  371. if(LandPageRef.value){
  372. LandPageRef.value[0]?.clearEvent()
  373. }
  374. updateHaveContent(8,0,false,true)
  375. computeCount()
  376. }
  377. pageInfo.adTitleList.forEach(i=>{
  378. i.subList.forEach(s=>{
  379. if(s.id == id){
  380. s.haveContent = true
  381. if(Number(chooseNum)>0){
  382. s.chooseNum = chooseNum
  383. }
  384. if(minusFlag){//减法开关
  385. s.chooseNum -= 1
  386. }
  387. if(s.chooseNum==0){
  388. s.haveContent = false
  389. if(id == 3 && DirectPacketExhibitionRef.value) {
  390. DirectPacketExhibitionRef.value[0]?.clearDirectContent()
  391. }
  392. }
  393. }
  394. })
  395. })
  396. }
  397. })
  398. }
  399. /**计算广告数、计划数、账号数 并获取计划列表信息 */
  400. const computeCount = (cb?) => {
  401. if(isMock.value){
  402. let { pageInfo_mock, cMaterial_mock, basicInfoData_mock } = mockEvent()
  403. for(let key in pageInfo_mock) {
  404. pageInfo[key] = pageInfo_mock[key]
  405. }
  406. for(let key in cMaterial_mock) {
  407. cMaterial[key] = cMaterial_mock[key]
  408. }
  409. for(let key in basicInfoData_mock) {
  410. basicInfoData[key] = basicInfoData_mock[key]
  411. }
  412. }else{
  413. if( !judgeEvent(7, true) ) return; // 创意文案之前未填写,则不进行下面逻辑
  414. }
  415. previewCompute(pageInfo, cMaterial, basicInfoData).then((res:any)=>{
  416. pageInfo.num_total.accNum = res.num_total.accNum;
  417. pageInfo.num_total.planNum = res.num_total.planNum;
  418. pageInfo.num_total.adNum = res.num_total.adNum;
  419. pageInfo.last_ad_show_list = res.last_ad_show_list;
  420. pageInfo.acc_plan_ad_count = res.acc_plan_ad_count;
  421. cb ? cb() : ''
  422. })
  423. }
  424. /**创意文案回调 */
  425. const writerCallBack = (obj) => {
  426. pageInfo.copywriterInfoData.data = obj.writer;
  427. pageInfo.copywriterInfoData.allocation_type = obj.allocation_type;
  428. if(obj.writer && Array.isArray(obj.writer)){
  429. updateHaveContent(7,pageInfo.copywriterInfoData.data?.length)
  430. }else{
  431. updateHaveContent(7,0)
  432. }
  433. computeCount()
  434. }
  435. /**落地页回调 */
  436. const landPageEvent = (obj) => {
  437. let length = 0;
  438. for(let i in obj.landPage){
  439. length += obj.landPage[i].length
  440. }
  441. pageInfo.copyLandPageInfoData.data = obj.landPage;
  442. pageInfo.copyLandPageInfoData.allocation_type = obj.allocation_type;
  443. pageInfo.copyLandPageInfoData.loadPageRule = obj.loadPageRule;
  444. if(obj.landPage && JSON.stringify(obj.landPage) != '{}') {
  445. updateHaveContent(8,length)
  446. }else{
  447. updateHaveContent(8,0)
  448. }
  449. computeCount()
  450. }
  451. /**创意基本信息回调 */
  452. const originalityBasicClose = (obj) => {
  453. originalityBasicRef.value?.switchShow(false)
  454. if(obj){
  455. if(originalityBasicInfoData.apiResult?.templateCurr?.adcreative_template_id != obj.apiResult?.templateCurr?.adcreative_template_id){
  456. //清空创意素材、文案、落地页
  457. CreativeMaterial_clear()
  458. if(LandPageRef.value){
  459. LandPageRef.value[0]?.clearEvent()
  460. }
  461. updateHaveContent(7,0,false,true)
  462. if(CopywriterRef.value) {
  463. CopywriterRef.value[0]?.clearEvent()
  464. }
  465. updateHaveContent(8,0,false,true)
  466. }
  467. originalityBasicInfoData.params = _.cloneDeep(obj.apiFormList)
  468. originalityBasicInfoData.receiveForm = _.cloneDeep(obj.form)
  469. originalityBasicInfoData.apiResult = _.cloneDeep(obj.apiResult)
  470. updateHaveContent(5,1)
  471. }
  472. }
  473. /**清空创意基本信息 */
  474. const clearOriginalityInfo = () => {
  475. originalityBasicInfoData.positionKey += 1;
  476. originalityBasicInfoData.receiveForm = {}
  477. originalityBasicInfoData.params = []
  478. originalityBasicInfoData.apiResult = {}
  479. }
  480. onMounted(()=>{
  481. nextTick(async ()=>{
  482. await get_ruleConfig_info() //规则配置获取
  483. //获取推广目标类型
  484. await getPromotedObjectType().then((res)=>{
  485. pageInfo.targetList = res
  486. if(targetRef.value){
  487. targetRef.value.value = pageInfo.targetList[0].name
  488. }
  489. pageInfo.targetValue = targetRef.value?.value
  490. })
  491. get_account_list()
  492. getAdPresetsInfo(); // 广告预存信息获取
  493. })
  494. })
  495. // S 每个模块判断是否可添加编辑
  496. const {
  497. judgeEvent
  498. } = handleJudge({
  499. pageInfo,
  500. basicInfoData,
  501. originalityBasicInfoData,
  502. cMaterial,
  503. })
  504. // E 每个模块判断是否可添加编辑
  505. // S 广告基本信息 及 外部配置
  506. const {
  507. basicInfoClose,
  508. getAdPresetsInfo,
  509. basicOuterClick,
  510. basicOuterClose,
  511. getCommonValue,
  512. isCompleteEvent
  513. } = handleAdBasic({
  514. CreativeMaterialRef,
  515. CopywriterRef,
  516. LandPageRef,
  517. targetRef,
  518. pageInfo,
  519. basicInfoData,
  520. clearOriginalityInfo,
  521. updateHaveContent,
  522. judgeEvent,
  523. CreativeMaterial_clear
  524. })
  525. // E 广告基本信息 及 外部配置
  526. /**S 复用 */
  527. const {
  528. accRef,
  529. ResuseConfigRef,
  530. accVisibleEvent,
  531. accEvent,
  532. aNewConfigEvent,
  533. reuseEvent,
  534. close_reuse_loading,
  535. accClearEvent,
  536. } = resuseConfigEvent({
  537. originalityBasicRef,
  538. CopywriterRef,
  539. LandPageRef,
  540. CreativeMaterialRef,
  541. DirectPacketExhibitionRef,
  542. pageInfo,
  543. basicInfoData,
  544. originalityBasicInfoData,
  545. updateHaveContent,
  546. isCompleteEvent,
  547. getCommonValue,
  548. clearOriginalityInfo,
  549. CreativeMaterial_clear
  550. })
  551. /**E 复用 */
  552. // S 创意素材
  553. const {
  554. assignEvent_CreativeMaterial,
  555. get_cover_info,
  556. } = handleMultiple({
  557. originalityBasicInfoData,
  558. ResuseConfigRef,
  559. computeCount,
  560. cMaterial,
  561. close_reuse_loading,
  562. // updateHaveContent
  563. })
  564. // E 创意素材
  565. /**S 提交预览 */
  566. const {
  567. isMock,
  568. openPreAreaLoading,
  569. PreviewAreaRef,
  570. openPreAreaEvent,
  571. continueCreate,
  572. } = submitPreview({
  573. pageInfo,
  574. basicInfoData,
  575. judgeEvent,
  576. computeCount,
  577. aNewConfigEvent
  578. })
  579. /**E 提交预览 */
  580. /**S 策略组 */
  581. const {
  582. StrategyGroupsDialogRef,
  583. StrategyGroupsListRef,
  584. openStrategyGroups,
  585. openSaveStrategyGroups
  586. } = strategyGroupsEvent({
  587. cMaterial,
  588. basicInfoData,
  589. pageInfo,
  590. isMock,
  591. judgeEvent
  592. })
  593. /**E 策略组 */
  594. //传值
  595. provide('accountIds',toRef(pageInfo,'accIdsList'))
  596. </script>
  597. <style lang="scss" scoped>
  598. @import "src/assets/style/batchGdt.scss";
  599. .titleBox{
  600. font-size: 14px;
  601. font-weight: 700;
  602. line-height: 48px;
  603. color: #515a6e;
  604. background-color: #fff;
  605. box-shadow: 0 2px 4px 0 rgba(0,0,0,.08);
  606. padding: 0 30px 0 32px;
  607. }
  608. .areaCon{
  609. .screenArea{
  610. display: flex;
  611. align-items: center;
  612. }
  613. .configArea{
  614. margin-top: 20px;
  615. display: flex;
  616. .bigTitle{
  617. font-size: 14px;
  618. border: 1px solid #F2F2F2;
  619. padding: 20px 12px;
  620. font-weight: 600;
  621. }
  622. .blockBox{
  623. width: calc((100vw - 40px - 32px) / 6);
  624. border: 1px solid #F2F2F2;
  625. border-top: none;
  626. border-bottom: none;
  627. }
  628. .no_left_boder{
  629. border-left: none!important;
  630. }
  631. .smallTitle{
  632. font-size: 13px;
  633. padding: 17px 12px;
  634. font-weight: 600;
  635. display: flex;
  636. align-items: center;
  637. .chooseCss{
  638. font-size: 12px;
  639. margin-left: auto;
  640. color: #999999;
  641. font-weight: 400;
  642. }
  643. }
  644. .showInfoArea{
  645. height: 250px;
  646. font-size: 12px;
  647. overflow-y: auto;
  648. padding: 8px 12px;
  649. scrollbar-color: transparent transparent;
  650. &::-webkit-scrollbar{
  651. width: 2px;
  652. }
  653. &:hover{
  654. box-shadow: 0 2px 4px 0 rgba(0,0,0,.08);
  655. }
  656. .noData{
  657. margin: 20px auto;
  658. font-size: 13px;
  659. color: #999999;
  660. text-align: center;
  661. }
  662. }
  663. .btn{
  664. border: 1px solid #F2F2F2;
  665. height: 44px;
  666. display: flex;
  667. align-items: center;
  668. justify-content: center;
  669. cursor: pointer;
  670. border-left: none;
  671. border-right: none;
  672. &:hover{
  673. box-shadow: 0 2px 4px 0 rgba(0,0,0,.08);
  674. }
  675. }
  676. }
  677. .btnArea{
  678. margin-top: 20px;
  679. display: flex;
  680. align-items: center;
  681. }
  682. }
  683. .lH16{
  684. line-height: 16px;
  685. }
  686. .c-515a6e{
  687. color: #515a6e;
  688. }
  689. .outerButton{
  690. &:hover{
  691. .outerIcon{
  692. color: #3173FF
  693. }
  694. .outerIconActive{
  695. color: #00b697;
  696. }
  697. }
  698. }
  699. .outerIcon{
  700. color: #888;
  701. margin: 0 10px;
  702. font-size: 16px;
  703. }
  704. .outerIconActive{
  705. color: #00b697;
  706. }
  707. .oss_url_img{
  708. width:60px;
  709. height: 60px;
  710. border-radius: 6px;
  711. }
  712. </style>