newDynamic.tsx 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611
  1. import { Button, Card, Form, Modal, Radio, Space, Spin, message } from "antd"
  2. import React, { useContext, useEffect, useState } from "react"
  3. import '../../index.less'
  4. import { getCreativeDetailsApi, getCreativeTemplateListApi } from "@/services/adqV3/global";
  5. import { useAjax } from "@/Hook/useAjax";
  6. import { DELIVERY_MODE_ENUM, pageSpecFieldConVert, pageSpecFieldConVertUn } from "../../const";
  7. import New2Radio from "@/pages/launchSystemV3/components/New2Radio";
  8. import New1Radio from "@/pages/launchSystemV3/components/New1Radio";
  9. import { outAdcreativeTemplateIdFun } from "@/pages/launchSystemNew/launchManage/localAd/adenum";
  10. import { DispatchAddelivery } from "..";
  11. import { processData, randomString } from "@/utils/utils";
  12. import CreativeTemplateContent from "./creativeTemplateContent";
  13. import CreativeConversionAssistant from "./creativeConversionAssistant";
  14. import CreativeTemplateSetup from "./creativeTemplateSetup";
  15. export const DispatchDynamic = React.createContext<PULLIN.DynamicReactContent | null>(null);
  16. interface Props {
  17. value?: any,
  18. visible?: boolean
  19. creativeTemplateStyle?: string,
  20. onClose?: () => void
  21. onChange?: (value: any) => void
  22. }
  23. /**
  24. * 创意新建
  25. * @param param0
  26. * @returns
  27. */
  28. const NewDynamic: React.FC<Props> = ({ value: newValue, visible, onClose, onChange, creativeTemplateStyle: oldCreativeTemplateStyle }) => {
  29. /**********************************/
  30. const { addelivery, setMaterialData, setTextData } = useContext(DispatchAddelivery)!;
  31. const { adgroups } = addelivery
  32. const [form] = Form.useForm();
  33. const creativeTemplateStyle = Form.useWatch('creativeTemplateStyle', form);
  34. const deliveryMode = Form.useWatch('deliveryMode', form);
  35. const [marketingGoalTypeList, setMarketingGoalTypeList] = useState<PULLIN.DataType[]>([])
  36. const [adcreativeTemplateList, setAdcreativeTemplateList] = useState<PULLIN.AdcreativeTemplateList[]>([])
  37. const [creativeComponents, setCreativeComponents] = useState<any>({})
  38. const [isUpdate, setIsUpdate] = useState<boolean>(false)
  39. const { marketingGoal, marketingAssetOuterSpec, marketingCarrierType, siteSet, sceneSpec, automaticSiteEnabled } = adgroups
  40. const [newMaterialData, setNewMaterialData] = useState<any>({}) // 素材数据
  41. const [newTextData, setNewTextData] = useState<any>({})
  42. const [value, setValue] = useState<any>(newValue)
  43. const getCreativeTemplateList = useAjax((params) => getCreativeTemplateListApi(params))
  44. const getCreativeDetails = useAjax((params) => getCreativeDetailsApi(params))
  45. /**********************************/
  46. useEffect(() => {
  47. if (deliveryMode === 'DELIVERY_MODE_CUSTOMIZE') { // 自定义创意
  48. getCreativeTemplateList.run({
  49. marketingGoal,
  50. marketingTargetType: marketingAssetOuterSpec.marketingTargetType,
  51. marketingCarrierType,
  52. siteSet,
  53. wechatSceneSpecPosition: sceneSpec?.wechatPosition || []
  54. }).then((res: any) => {
  55. let newArr: any = []
  56. let newData: any[] = []
  57. // 过滤掉相同的和即将下线的
  58. if (!res) {
  59. return
  60. }
  61. if (automaticSiteEnabled) {
  62. delete res?.SITE_SET_WECHAT
  63. }
  64. let creativeTemplateStyle = ''
  65. Object.values(res)?.forEach(arr => {
  66. newData.push(arr)
  67. if (Array.isArray(arr)) {
  68. arr?.forEach((item: any) => {
  69. let adcreativeTemplateListStructAdpermit = item?.adcreativeTemplateListStructAdpermit
  70. if (adcreativeTemplateListStructAdpermit) {
  71. creativeTemplateStyle += adcreativeTemplateListStructAdpermit?.creativeTemplateStyle
  72. let creativeTemplateId = adcreativeTemplateListStructAdpermit.creativeTemplateId
  73. if (newArr.length > 0) {//假如已存在ID,需要过滤相同
  74. if (outAdcreativeTemplateIdFun(creativeTemplateId) && newArr.every((i: { creativeTemplateId: any }) => i.creativeTemplateId !== creativeTemplateId)) {//不重复的添加
  75. newArr.push(adcreativeTemplateListStructAdpermit)
  76. }
  77. } else {//不存在ID直接过滤掉即将下线的
  78. if (outAdcreativeTemplateIdFun(creativeTemplateId)) {
  79. newArr.push(adcreativeTemplateListStructAdpermit)
  80. }
  81. }
  82. }
  83. })
  84. }
  85. })
  86. /*****暂时排除激励和banner有问题******/
  87. if (!siteSet || siteSet.some((i: string) => i === 'SITE_SET_MOMENTS')) {
  88. newArr = newArr.filter((item: { creativeTemplateId: number }) => ![2107, 2109].includes(item.creativeTemplateId))
  89. }
  90. /*****暂时排除出框形态 视频合约广告******/
  91. if (!siteSet || siteSet.some((i: string) => i === 'SITE_SET_WECHAT')) {
  92. newArr = newArr.filter((item: { creativeTemplateId: number }) => item.creativeTemplateId !== 1945)
  93. }
  94. newArr = newArr.filter((item: { creativeTemplateId: number }) => ![713, 727, 951, 965].includes(item.creativeTemplateId))
  95. let newArr1: any[] = []
  96. let newArr2: any[] = []
  97. newArr?.forEach((arr: { creativeTemplateId: any, creativeTemplateAppellation: string, creativeSampleImage: string, isGeneral?: boolean }) => {
  98. let arr2 = { label: arr.creativeTemplateAppellation, value: arr.creativeTemplateId, img: arr.creativeSampleImage, ...arr }
  99. if (newData.every((item: any[]) => item.find(i => i?.adcreativeTemplateListStructAdpermit?.creativeTemplateId === arr.creativeTemplateId))) {
  100. newArr1.push({ ...arr2, isGeneral: true })
  101. } else {
  102. newArr2.push(arr2)
  103. }
  104. })
  105. setAdcreativeTemplateList([...newArr1, ...newArr2])
  106. let goalTypeData: PULLIN.DataType[] = []
  107. if (creativeTemplateStyle.includes('视频')) {
  108. goalTypeData.push({ label: '视频', value: 'video' })
  109. form.setFieldsValue({ creativeTemplateStyle: 'video' })
  110. } else if (creativeTemplateStyle.includes('图片')) {
  111. form.setFieldsValue({ creativeTemplateStyle: 'image' })
  112. }
  113. if (creativeTemplateStyle.includes('图片')) {
  114. goalTypeData.push({ label: '图片', value: 'image' })
  115. }
  116. setMarketingGoalTypeList(goalTypeData)
  117. })
  118. } else if (deliveryMode === 'DELIVERY_MODE_COMPONENT') { // 组件化创意
  119. getTemplate()
  120. }
  121. }, [deliveryMode, marketingGoal, marketingAssetOuterSpec, marketingCarrierType, siteSet, sceneSpec?.wechatPosition, value, automaticSiteEnabled])
  122. useEffect(() => {
  123. if (!(value && Object.keys(value).length > 0) && adcreativeTemplateList?.length > 0 && marketingGoalTypeList?.length > 0) {
  124. typeChange(marketingGoalTypeList.some(item => item.value === 'video') ? '视频' : '图片')
  125. }
  126. }, [value, adcreativeTemplateList, marketingGoalTypeList])
  127. const typeChange = (creativeTemplateStyle: string, isAntTemplateId?: boolean) => {
  128. if (creativeTemplateStyle && adcreativeTemplateList?.length > 0) {
  129. let adcreativeTemplateIdArr = adcreativeTemplateList?.filter(item => item.creativeTemplateStyle === creativeTemplateStyle)
  130. if (adcreativeTemplateIdArr?.length > 0) {
  131. let creativeTemplateId = adcreativeTemplateIdArr[0].creativeTemplateId
  132. getTemplate(creativeTemplateId, isAntTemplateId)
  133. form.setFieldsValue({ creativeTemplateId })
  134. }
  135. }
  136. }
  137. // 获取创意形式详情
  138. const getTemplate = (id?: any, isAntTemplateId?: boolean) => {
  139. // CAMPAIGN_TYPE_NORMAL
  140. if (marketingAssetOuterSpec?.marketingTargetType && deliveryMode) {
  141. let params: any = {
  142. marketingGoal,
  143. marketingTargetType: marketingAssetOuterSpec.marketingTargetType,
  144. marketingCarrierType,
  145. deliveryMode,
  146. creativeTemplateId: id,
  147. wechatSceneSpecPosition: sceneSpec?.wechatPosition,
  148. dynamicCreativeType: deliveryMode === 'DELIVERY_MODE_COMPONENT' ? 'DYNAMIC_CREATIVE_TYPE_PROGRAM' : 'DYNAMIC_CREATIVE_TYPE_COMMON'
  149. }
  150. if (automaticSiteEnabled) {
  151. params.automaticSiteEnabled = automaticSiteEnabled
  152. } else {
  153. params.siteSet = siteSet
  154. }
  155. getCreativeDetails.run(params).then(res => {
  156. if (res?.adcreativeTemplateStructAdpermits?.length > 0) {
  157. let adcreativeTemplateStructAdpermits = res?.adcreativeTemplateStructAdpermits[0]
  158. templateChange(adcreativeTemplateStructAdpermits, isAntTemplateId)
  159. } else {
  160. message.error({
  161. content: '当前所选营销目的,广告版位下不支持该创意形式。或者无此创意形式权限,请联系相关人员开通白名单',
  162. duration: 10
  163. })
  164. setCreativeComponents({})
  165. }
  166. })
  167. }
  168. }
  169. //每次选中创意设置该展示的界面
  170. const templateChange = (adcreativeTemplateStructAdpermits: any, isAntTemplateId?: boolean) => {
  171. let creativeComponents = adcreativeTemplateStructAdpermits?.creativeComponents || []
  172. let creativeTemplateId = adcreativeTemplateStructAdpermits?.creativeTemplateId
  173. let creativeTemplateAppellation = adcreativeTemplateStructAdpermits?.creativeTemplateAppellation
  174. let result = processData(creativeComponents);
  175. console.log('result-->', result);
  176. setCreativeComponents(result)
  177. let newMaterialData: { [x: string]: any } = {};
  178. let newTextData: { [x: string]: any } = {};
  179. Object.keys(result).forEach(key => {
  180. let data = result[key]
  181. if ((key === 'image_list' || key === 'short_video' || key === 'video' || key === 'image' || key === 'element_story') && data.required) {
  182. newMaterialData[key] = data
  183. } else if (key === 'title' || (data.required && key === 'description')) {
  184. newTextData[key] = data
  185. }
  186. })
  187. setNewMaterialData(newMaterialData)
  188. setNewTextData(newTextData)
  189. if (!(value && Object.keys(value).length > 0) || isAntTemplateId) {
  190. let values: any = {
  191. dynamicCreativeName: creativeTemplateAppellation ? '自定义创意' + '_' + creativeTemplateAppellation + '_' + localStorage.getItem('userId') + '_' + randomString(true, 3, 5) : '动态创意' + '_' + localStorage.getItem('userId') + '_' + randomString(true, 3, 5),
  192. pageSpec: [{
  193. pageType: 'PAGE_TYPE_WECHAT_CANVAS',
  194. overrideCanvasHeadOption: 'OPTION_CREATIVE_OVERRIDE_CANVAS'
  195. }],
  196. brand: undefined
  197. }
  198. Object.keys(result).forEach(key => {
  199. switch (key) {
  200. case 'brand':
  201. let brand = result[key]
  202. let page_type = brand.children.page_type
  203. let typeList = ["PAGE_TYPE_WECHAT_OFFICIAL_ACCOUNT_DETAIL", "PAGE_TYPE_H5_PROFILE", "PAGE_TYPE_NOT_USED", "PAGE_TYPE_WECHAT_CHANNELS_PROFILE"]
  204. let enumeration = (page_type.enumProperty.enumeration as { value: string, description: string }[]).filter((item: { value: string; }) => typeList.includes(item.value))
  205. values.jumpInfo = {
  206. pageType: enumeration[0]?.value
  207. }
  208. break
  209. case 'text_link':// 朋友圈文字链
  210. let textLink = result[key]
  211. let linkNameType = textLink?.children?.link_name_type
  212. let linkNameEnumeration = (linkNameType?.enumProperty?.enumeration as { value: string, description: string }[]).map(item => ({ label: item.description, value: item.value }))
  213. values.textLink = {
  214. value: {
  215. linkNameType: linkNameEnumeration?.[0]?.value,
  216. jumpInfo: {
  217. pageType: 'PAGE_TYPE_WECHAT_CANVAS'
  218. }
  219. }
  220. }
  221. values.textLinkShow = true
  222. break
  223. case 'action_button':
  224. let actionButton = result[key]
  225. let buttonText = actionButton.children.button_text
  226. let butttonTextEnumeration = (buttonText.enumProperty.enumeration as { value: string }[]).map(item => ({ label: item.value, value: item.value }))
  227. values.actionButton = {
  228. value: {
  229. buttonText: butttonTextEnumeration?.[0]?.value,
  230. jumpInfo: {
  231. pageType: 'PAGE_TYPE_WECHAT_CANVAS'
  232. }
  233. }
  234. }
  235. values.actionButtonShow = true
  236. break
  237. case 'floating_zone':
  238. let floatingZone = result[key]
  239. let floatingZoneData: any = {
  240. value: {
  241. floatingZoneSwitch: false,
  242. floatingZoneType: 'FLOATING_ZONE_TYPE_IMAGE_TEXT',
  243. floatingZoneButtonText: '了解更多'
  244. }
  245. }
  246. if (floatingZone?.children?.floating_zone_image_id && floatingZone?.children?.floating_zone_button_text) {
  247. floatingZoneData.value.floatingZoneButtonText = floatingZone.children.floating_zone_button_text?.enumProperty?.enumeration[0]?.value
  248. }
  249. if (floatingZone?.required) {
  250. floatingZoneData.value.floatingZoneSwitch = true
  251. }
  252. values.floatingZone = floatingZoneData
  253. break
  254. }
  255. })
  256. if ([1707, 1708].includes(creativeTemplateId)) {
  257. delete values?.actionButtonShow
  258. values.cardType = ['not']
  259. }
  260. form.setFieldsValue(values)
  261. setTimeout(() => { setIsUpdate(true) }, 50)
  262. }
  263. }
  264. const handleOk = (values: any) => {
  265. const {
  266. creativeTemplateStyle,
  267. brand,
  268. jumpInfo,
  269. pageSpec,
  270. textLinkShow,
  271. textLink,
  272. actionButtonShow,
  273. cardType,
  274. actionButton,
  275. showDataShow,
  276. showData,
  277. floatingZone,
  278. ...surplusValues
  279. } = values
  280. let dynamicValues: any = {
  281. ...surplusValues,
  282. }
  283. let creativeComponents: any = {}
  284. let actionButtonJumpInfo = {
  285. pageType: undefined
  286. }
  287. if (pageSpec?.length > 0) {
  288. let { pageType } = pageSpec?.[0]
  289. actionButtonJumpInfo.pageType = pageType
  290. creativeComponents.mainJumpInfo = pageSpec.map((item: { pageType: string, overrideCanvasHeadOption: string, }) => {
  291. return {
  292. value: {
  293. pageType: item.pageType,
  294. pageSpec: {
  295. [pageSpecFieldConVert[item.pageType as keyof typeof pageSpecFieldConVert]]: {
  296. pageId: null,
  297. overrideCanvasHeadOption: item.overrideCanvasHeadOption
  298. }
  299. }
  300. }
  301. }
  302. })
  303. }
  304. // 品牌形象
  305. if (jumpInfo) {
  306. let pageType = jumpInfo.pageType
  307. let value: { [x: string]: any } = {
  308. jumpInfo
  309. }
  310. if (['PAGE_TYPE_H5_PROFILE'].includes(pageType)) {
  311. value['profileId'] = brand
  312. } else if (["PAGE_TYPE_NOT_USED"].includes(pageType)) {
  313. let [brandName, brandImageId] = brand.split('_')
  314. value['brandName'] = brandName
  315. value['brandImageId'] = brandImageId
  316. } else {
  317. value['brandName'] = null
  318. value['brandImageId'] = null
  319. }
  320. let pageSpecData: any = {}
  321. if (pageType === 'PAGE_TYPE_H5_PROFILE') {
  322. pageSpecData[pageSpecFieldConVert[pageType as keyof typeof pageSpecFieldConVert]] = {
  323. pageId: null
  324. }
  325. } else if (pageType === 'PAGE_TYPE_H5') {
  326. pageSpecData[pageSpecFieldConVert[pageType as keyof typeof pageSpecFieldConVert]] = {
  327. pageUrl: null,
  328. mpaH5WildcardUrl: null
  329. }
  330. } else if (pageType === 'PAGE_TYPE_WECHAT_OFFICIAL_ACCOUNT_DETAIL') {
  331. pageSpecData[pageSpecFieldConVert[pageType as keyof typeof pageSpecFieldConVert]] = {
  332. appId: null
  333. }
  334. }
  335. value.jumpInfo = {
  336. ...value.jumpInfo,
  337. pageSpec: pageSpecData
  338. }
  339. let length = pageSpec.length
  340. creativeComponents.brand = Array(length).fill('').map(() => ({ value }))
  341. }
  342. // 朋友圈文字链
  343. if (textLinkShow) {
  344. creativeComponents.textLink = [textLink]
  345. }
  346. // 行动按钮
  347. if (actionButton && Object.keys(actionButton).length > 0) {
  348. let newActionButton = [actionButton]
  349. if (!actionButton.value?.jumpInfo) {
  350. newActionButton = [{
  351. ...actionButton,
  352. value: {
  353. ...actionButton.value,
  354. jumpInfo: actionButtonJumpInfo
  355. }
  356. }]
  357. }
  358. creativeComponents.actionButton = newActionButton
  359. }
  360. // 数据外显
  361. if (showDataShow) {
  362. creativeComponents.showData = [showData]
  363. }
  364. if (floatingZone?.value) {
  365. let value = floatingZone.value
  366. let { image, ...val } = value
  367. if (val.floatingZoneType === "FLOATING_ZONE_TYPE_SINGLE_IMAGE") {
  368. delete image?.floatingZoneImageId
  369. delete image?.floatingZoneImageUrl
  370. delete image?.floatingZoneImageMaterialType
  371. } else {
  372. delete image?.floatingZoneSingleImageId
  373. delete image?.floatingZoneSingleImageUrl
  374. delete image?.floatingZoneSingleImageMaterialType
  375. }
  376. creativeComponents.floatingZoneComponent = {
  377. ...val,
  378. ...image
  379. }
  380. }
  381. dynamicValues.creativeComponents = creativeComponents
  382. setMaterialData(newMaterialData)
  383. setTextData(newTextData)
  384. onChange?.(dynamicValues)
  385. }
  386. useEffect(() => {
  387. if (value && Object.keys(value).length > 0 && adcreativeTemplateList?.length > 0 && ((value.deliveryMode === 'DELIVERY_MODE_CUSTOMIZE' && oldCreativeTemplateStyle) || value.deliveryMode === 'DELIVERY_MODE_COMPONENT')) {
  388. const {
  389. creativeComponents: {
  390. brand,
  391. textLink,
  392. actionButton,
  393. showData,
  394. mainJumpInfo,
  395. floatingZoneComponent
  396. },
  397. ...surplusValues
  398. } = JSON.parse(JSON.stringify(value))
  399. let dynamicValues: any = {
  400. ...surplusValues
  401. }
  402. if (value.deliveryMode === 'DELIVERY_MODE_CUSTOMIZE') {
  403. getTemplate(value.creativeTemplateId)
  404. dynamicValues.creativeTemplateStyle = oldCreativeTemplateStyle === '视频' ? 'video' : 'image'
  405. }
  406. // else getTemplate()
  407. // 卡片广告
  408. let isCardDynamic = dynamicValues?.creativeTemplateId && [1707, 1708].includes(dynamicValues.creativeTemplateId)
  409. let cardType: string[] = []
  410. // 529 闪屏视频 没有品牌 要单独处理
  411. if (brand && brand?.length > 0) {
  412. let { jumpInfo, brandName, brandImageId, profileId } = brand[0].value
  413. if (jumpInfo) {
  414. let { pageType } = jumpInfo
  415. dynamicValues.jumpInfo = { pageType }
  416. }
  417. if (brandName && brandImageId) {
  418. dynamicValues.brand = brandName + '_' + brandImageId
  419. } else if (profileId) {
  420. dynamicValues.brand = profileId
  421. }
  422. }
  423. if (mainJumpInfo && mainJumpInfo?.length > 0) {
  424. dynamicValues.pageSpec = mainJumpInfo.map((item: any) => {
  425. let { pageSpec, pageType } = item.value
  426. let key = Object.keys(pageSpec)[0]
  427. let pageSpecValue = pageSpec[key]
  428. return { ...pageSpecValue, pageType }
  429. })
  430. }
  431. // 文字链
  432. if (textLink && textLink?.length > 0) {
  433. dynamicValues = {
  434. ...dynamicValues,
  435. textLinkShow: true,
  436. textLink: textLink[0]
  437. }
  438. }
  439. // 行动按钮
  440. if (actionButton && actionButton?.length > 0) {
  441. dynamicValues = {
  442. ...dynamicValues,
  443. actionButtonShow: true,
  444. actionButton: actionButton[0]
  445. }
  446. if (isCardDynamic) {
  447. cardType.push('action_button')
  448. delete dynamicValues.actionButtonShow
  449. }
  450. }
  451. // 数据外显
  452. if (showData && showData?.length > 0) {
  453. dynamicValues = {
  454. ...dynamicValues,
  455. showDataShow: true,
  456. showData: showData[0]
  457. }
  458. }
  459. if (floatingZoneComponent && Object.keys(floatingZoneComponent).length) {
  460. const {
  461. floatingZoneImageId,
  462. floatingZoneImageUrl,
  463. floatingZoneImageMaterialType,
  464. floatingZoneSingleImageId,
  465. floatingZoneSingleImageUrl,
  466. floatingZoneSingleImageMaterialType,
  467. ...val
  468. } = floatingZoneComponent
  469. dynamicValues = {
  470. ...dynamicValues,
  471. floatingZone: {
  472. value: {
  473. image: {
  474. floatingZoneImageId,
  475. floatingZoneImageUrl,
  476. floatingZoneImageMaterialType,
  477. floatingZoneSingleImageId,
  478. floatingZoneSingleImageUrl,
  479. floatingZoneSingleImageMaterialType,
  480. },
  481. ...val
  482. }
  483. }
  484. }
  485. }
  486. if (cardType.length === 0 && isCardDynamic) {
  487. cardType = ['not']
  488. }
  489. dynamicValues.cardType = cardType
  490. form.setFieldsValue({ ...dynamicValues })
  491. }
  492. }, [value, oldCreativeTemplateStyle, adcreativeTemplateList])
  493. return <Modal
  494. title={<strong style={{ fontSize: 20 }}>创意基本信息</strong>}
  495. visible={visible}
  496. onCancel={onClose}
  497. footer={null}
  498. width={900}
  499. className={`modalResetCss`}
  500. bodyStyle={{ padding: '0 0 40px', position: 'relative', borderRadius: '0 0 8px 8px' }}
  501. maskClosable={false}
  502. >
  503. <Form
  504. form={form}
  505. name="newDynamic"
  506. labelAlign='left'
  507. layout="vertical"
  508. colon={false}
  509. style={{ backgroundColor: '#f1f4fc', maxHeight: 650, overflow: 'hidden', overflowY: 'auto', padding: '0 10px 10px', borderRadius: '0 0 8px 8px' }}
  510. scrollToFirstError={{
  511. behavior: 'smooth',
  512. block: 'center'
  513. }}
  514. onFinishFailed={({ errorFields }) => {
  515. message.error(errorFields?.[0]?.errors?.[0])
  516. }}
  517. onFinish={handleOk}
  518. initialValues={{
  519. deliveryMode: 'DELIVERY_MODE_CUSTOMIZE',
  520. configuredStatus: 'AD_STATUS_NORMAL'
  521. }}
  522. >
  523. <Spin spinning={getCreativeTemplateList.loading || getCreativeDetails.loading}>
  524. <DispatchDynamic.Provider value={{ form, adgroups, value, creativeComponents, setCreativeComponents, isUpdate, setIsUpdate }}>
  525. <Space direction="vertical" style={{ width: '100%' }}>
  526. {/* 创意形式 */}
  527. <Card
  528. title={<strong style={{ fontSize: 18 }}>创意形式</strong>}
  529. className="cardResetCss"
  530. >
  531. <Form.Item name="deliveryMode" label={<strong>投放模式</strong>} rules={[{ required: true, message: '请选择投放模式!' }]}>
  532. <Radio.Group onChange={() => {
  533. setTimeout(() => { setIsUpdate(true) }, 50)
  534. setValue(undefined)
  535. }}>
  536. {Object.keys(DELIVERY_MODE_ENUM).map(key => <Radio value={key} key={key}>{DELIVERY_MODE_ENUM[key as keyof typeof DELIVERY_MODE_ENUM]}</Radio>)}
  537. </Radio.Group>
  538. </Form.Item>
  539. {deliveryMode === 'DELIVERY_MODE_CUSTOMIZE' && <>
  540. <Form.Item name="creativeTemplateStyle" label={<strong>创意形式类型</strong>} rules={[{ required: true, message: '请选择营销目的!' }]}>
  541. <New1Radio data={marketingGoalTypeList} onChange={(e) => { typeChange(e === 'video' ? '视频' : '图片', true); }} />
  542. </Form.Item>
  543. <Form.Item name="creativeTemplateId" label={<strong>创意形式</strong>} rules={[{ required: true, message: '请选择营销目的!' }]}>
  544. <New2Radio
  545. data={adcreativeTemplateList.filter(item => creativeTemplateStyle === 'video' ? item.creativeTemplateStyle === '视频' : item.creativeTemplateStyle === '图片')}
  546. onChange={(id) => { getTemplate(id, true); }}
  547. />
  548. </Form.Item>
  549. </>}
  550. </Card>
  551. {Object.keys(creativeComponents).length > 0 && <>
  552. {/* 创意内容 */}
  553. <CreativeTemplateContent automaticSiteEnabled={automaticSiteEnabled} />
  554. {/* 营销组件 */}
  555. <CreativeConversionAssistant automaticSiteEnabled={automaticSiteEnabled} />
  556. {/* 创意设置 */}
  557. <CreativeTemplateSetup />
  558. </>}
  559. </Space>
  560. </DispatchDynamic.Provider>
  561. </Spin>
  562. <Form.Item className="submit_pull">
  563. <Space>
  564. <Button onClick={onClose}>取消</Button>
  565. <Button type="primary" htmlType="submit" className="modalResetCss">
  566. 确定
  567. </Button>
  568. </Space>
  569. </Form.Item>
  570. </Form>
  571. </Modal>
  572. }
  573. export default React.memo(NewDynamic)