index.tsx 83 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329
  1. import Tables from "@/components/Tables"
  2. import { useAjax } from "@/Hook/useAjax"
  3. import { createAdBatchApi, CreateAdProps } from "@/services/launchAdq/createAd"
  4. import { getSysAdcreativeInfo } from "@/services/launchAdq/creative"
  5. import { PromotedObjectType } from "@/services/launchAdq/enum"
  6. import { getTagsList, get_adcreative_template } from "@/services/launchAdq/global"
  7. import { getSysAdgroupsInfo } from "@/services/launchAdq/localAd"
  8. import { getsysTargetingInfo } from "@/services/launchAdq/targeting"
  9. import { CheckOutlined, CloseOutlined, SearchOutlined } from "@ant-design/icons"
  10. import { Button, Card, Col, Empty, Row, Select, Space, Spin, Tooltip, Image, message, Tabs, Popconfirm, notification, Divider, Checkbox, Modal } from "antd"
  11. import React, { useCallback, useEffect, useState } from "react"
  12. import { useModel } from "umi"
  13. import Ad from "./ad"
  14. import DataSourceModal from "../../components/dataSourceModal"
  15. import GoodsModal from "../../components/goodsModal"
  16. import IdModal from "../../components/idModal"
  17. import LookLanding from "../../components/lookLanding"
  18. import PageModal from "../../components/pageModal"
  19. import SelectCloud from "../../components/selectCloud"
  20. import style from './index.less'
  21. import Selector from "./selector"
  22. import SubmitModal from "./submitModal"
  23. import columns from "./tableConfig"
  24. import TargetIng from './targeting'
  25. import Creative from './creative'
  26. import AddGroup from '../../components/addGroup'
  27. import CustomerServiceModal from "../../components/customerServiceModal"
  28. import { getTaskDetailsApi } from "@/services/launchAdq/taskList"
  29. import CreativeCL from "./creativeCL"
  30. import { groupBy } from "@/utils/utils"
  31. import moment from "moment"
  32. import { getAccountListApi, getGroupListApi } from "@/services/launchAdq/subgroup"
  33. const CreateAd: React.FC = () => {
  34. /*************************/
  35. const { getAllUserAccount } = useModel('useLaunchAdq.useAdAuthorize')
  36. const [queryForm, setQueryForm] = useState<Partial<CreateAdProps>>({
  37. campaignName: '', // 计划名称
  38. campaignType: 'CAMPAIGN_TYPE_NORMAL', // 计划类型 CAMPAIGN_TYPE_NORMAL CAMPAIGN_TYPE_SEARCH
  39. promotedObjectType: 'PROMOTED_OBJECT_TYPE_WECHAT_OFFICIAL_ACCOUNT', // 推广目标类型
  40. speedMode: 'SPEED_MODE_STANDARD', // 投放速度模式
  41. sysAdgroupId: undefined, // 广告组ID
  42. sysAdgroup: undefined,//广告组内容
  43. sysTargetingId: undefined, // 定向包 id
  44. sysTargeting: undefined, // 定向包 内容
  45. adgroupName: undefined, // 广告名称
  46. configuredStatus: 'AD_STATUS_SUSPEND', // 广告状态
  47. sysAdcreativeId: undefined, // 创意ID
  48. taskMediaMaps: [], // 创意内容
  49. pageList: [],//本地落地页详情入口
  50. adqPageList: [],//云落地页
  51. expandEnabled: false,
  52. expandTargeting: [],
  53. model: 'cross'
  54. })
  55. const [launchMode, setLaunchMode] = useState<number>(Number(localStorage.getItem('LAUNCHMODE')) || 1) // 投放模式 1 现在投放模式 2 创量模式
  56. const [accountCreateLogs, setAccountCreateLogs] = useState<{ adAccountId: number, id: number, userActionSetsList?: any[], productList?: any, conversionList?: any, customAudienceList?: any, excludedCustomAudienceList?: any, pageList?: any, coldStartAudienceList?: any[] }[]>([]) // 账户
  57. const { currentUser: { userId } }: any = useModel('@@initialState', model => ({ currentUser: model.initialState?.currentUser }))
  58. const [goodsVisible, setGoodsVisible] = useState<boolean>(false) // 选择商品弹窗控制
  59. const [sourceVisible, setSourceVisible] = useState<boolean>(false) // 选择数据源弹窗控制
  60. const [idVisible, setIdVisible] = useState<boolean>(false) // 选择转化ID弹窗控制
  61. const [selectImgVisible, setSelectImgVisible] = useState<boolean>(false) // 选择转化ID弹窗控制
  62. const [lookVisible, setLookVisible] = useState<boolean>(false) // 选择转化ID弹窗控制
  63. const [subVisible, setSubVisible] = useState<boolean>(false) // 选择设置名称弹窗控制
  64. const [pageVisible, setPageVisible] = useState<boolean>(false) // 选择云端落地页控制
  65. const [tableData, setTableData] = useState<any[]>([]) // 预览表格
  66. const [tableSelect, setTableSelect] = useState<any[]>([])
  67. const [geoLocationList, setGeoLocationList] = useState<any>({}) // 所有地域列表
  68. const [modelList, setModelList] = useState<any>({}) // 所有品牌手机
  69. const [targetKey, set_targetKey] = useState('0')//创意key
  70. const [page_checked, set_page_checked] = useState(false)//创意key
  71. const [usesArr, setUsersArr] = useState<any>(localStorage.getItem('ADQUSERS' + userId) ? JSON.parse(localStorage.getItem('ADQUSERS' + userId) as any) : [])
  72. const { init, get } = useModel('useLaunchAdq.useBdMediaPup')
  73. const [cloudParams, setCloudParams] = useState<{ adcreativeTemplateId?: number }>({})
  74. const [accSearch, setAccSearch] = useState<string>()
  75. const tagsList_REGION = useAjax((params) => getTagsList(params))
  76. const tagsList_MODEL = useAjax((params) => getTagsList(params))
  77. const getSysAdgroups = useAjax((params) => getSysAdgroupsInfo(params))
  78. const getsysTargeting = useAjax((params) => getsysTargetingInfo(params))
  79. const getSysAdcreative = useAjax((params) => getSysAdcreativeInfo(params))
  80. const createAdBatch = useAjax((params) => createAdBatchApi(params))
  81. const getTaskDetails = useAjax((params) => getTaskDetailsApi(params))
  82. const getAdcreativeTemplate = useAjax((params) => get_adcreative_template(params))
  83. const getGroupList = useAjax(() => getGroupListApi())
  84. /*************************/
  85. useEffect(() => {
  86. getGroupList.run()
  87. }, [])
  88. /** 判断出价方式,优化目标 “二方包”人群包仅能在出价方式为CPC(包含oCPM点击优化目标)、CPM场景下使用 */
  89. // useEffect(() => {
  90. // if (queryForm?.sysAdgroup && Object.keys(queryForm?.sysAdgroup).length > 0 && (!['BID_MODE_CPC', 'BID_MODE_CPM'].includes(queryForm?.sysAdgroup?.bidMode) || !(queryForm?.sysAdgroup?.bidMode === 'BID_MODE_OCPM' && queryForm?.sysAdgroup?.optimizationGoal === 'OPTIMIZATIONGOAL_CLICK'))) {
  91. // setAccountCreateLogs(() => accountCreateLogs.map(item => {
  92. // delete item?.customAudienceList
  93. // delete item?.excludedCustomAudienceList
  94. // return item
  95. // }))
  96. // }
  97. // }, [queryForm?.sysAdgroup])
  98. /**数据回填 */
  99. useEffect(() => {
  100. let taskId = sessionStorage.getItem('TASKID')
  101. if (taskId) {
  102. getTaskDetails.run(taskId).then(async res => {
  103. const { adCreateLogs, campaignType, promotedObjectType, speedMode, sysAdgroup, sysAdgroupId, sysTargeting, sysTargetingId } = res
  104. let adcreativeTemplateId = adCreateLogs[0]?.sysAdcreative?.adcreativeTemplateId
  105. let sysPageId = adCreateLogs[0]?.sysPageId
  106. let pageId = adCreateLogs[0]?.pageId
  107. // 账号信息相关
  108. let adCreateLogsData = adCreateLogs?.map((item: any) => {
  109. return {
  110. adAccountId: item?.accountId,
  111. id: item?.accountId,
  112. // 数据源
  113. userActionSetsList: item?.userActionSetList?.map((item: any) => ({ ...item, id: item?.userActionSetId })),
  114. // 商品
  115. productList: item?.product ? [{ ...item?.product, productCatalog: item?.productCatalog, id: Number(item?.product?.productOuterId?.replace(/\D/ig, '')) }] : undefined,
  116. coldStartAudienceList: item?.coldStartAudienceList?.map((item: any) => ({ ...item, id: item.audienceId })),
  117. // pageList: [item.page]
  118. // 定向用户群
  119. customAudienceList: item?.customAudienceList?.map((item: any) => ({ ...item, id: item.audienceId })),
  120. // 排除用户群
  121. excludedCustomAudienceList: item?.excludedCustomAudienceList?.map((item: any) => ({ ...item, id: item.audienceId }))
  122. }
  123. }).filter((item: any, index: number, self: any) => self.findIndex((i: any) => i.id == item.id) === index)
  124. setAccountCreateLogs(adCreateLogsData)
  125. let type: 1 | 2 = 1
  126. if (sysPageId && pageId) {
  127. type = 1
  128. } else if (sysPageId) {
  129. if (adCreateLogs?.every((item: { sysAdcreative: { adcreativeTemplateId: number }, sysPageId: number }) => item.sysAdcreative.adcreativeTemplateId === adcreativeTemplateId && (item.sysPageId === sysPageId))) {
  130. type = 2
  131. } else {
  132. type = 1
  133. }
  134. } else {
  135. if (adCreateLogs?.every((item: { sysAdcreative: { adcreativeTemplateId: number }, pageId: number }) => item.sysAdcreative.adcreativeTemplateId === adcreativeTemplateId)) {
  136. type = 2
  137. } else {
  138. type = 1
  139. }
  140. }
  141. setLaunchMode(type)
  142. /** 本地落地页处理 */
  143. let pageList: any = []
  144. /** 云端落地页 */
  145. let adqPageList: any[] = []
  146. let taskMediaMaps: any[] = []
  147. let type2Data = {}
  148. if (type === 1) {
  149. const sorted = groupBy(adCreateLogs, (item) => [item.sysAdcreativeId])
  150. pageList = sorted?.map((item: any[]) => {
  151. if (item.some((item1: { sysPageId: number }) => item1.sysPageId)) {
  152. return item[0].sysPage
  153. } else {
  154. return null
  155. }
  156. })
  157. adqPageList = sorted?.map((item: any[]) => {
  158. if (item.some((item1: { pageId: number }) => item1.pageId)) {
  159. return item.map((item1: any) => ({
  160. pageList: [{ ...item1.page, id: item1.page.pageId }],
  161. adAccountId: item1?.accountId,
  162. id: item1?.accountId,
  163. }))
  164. } else {
  165. return null
  166. }
  167. })
  168. taskMediaMaps = groupBy(adCreateLogs, (item) => [item.accountId])?.[0]?.map((item: any, index: number) => {
  169. let pageElementsSpecList = item?.sysPage?.pageSpecsList[0]?.pageElementsSpecList // 内容区
  170. let globalSpec = item?.sysPage?.globalSpec // 悬浮组件
  171. /** 处理客服 */
  172. let cropUserGroupMap: any[] = []
  173. if ((pageElementsSpecList as any[])?.some((item: { elementType: string }) => item?.elementType === 'ENTERPRISE_WX') || (globalSpec?.globalElementsSpecList?.length > 0 && globalSpec?.globalElementsSpecList?.some((item: { floatButtonSpec: { elementType: string } }) => item?.floatButtonSpec?.elementType === 'ENTERPRISE_WX'))) {
  174. let groupList: { type: number, name: string, cropList: any[], cropId?: number, groupId?: number }[] = [];
  175. (pageElementsSpecList as any[])?.forEach((item: { elementType: string, enterpriseWxSpec: { btnTitle: string } }) => {
  176. if (item?.elementType === 'ENTERPRISE_WX') {
  177. groupList.push({ type: 1, name: '联系商家', cropList: [] }) // item.enterpriseWxSpec.btnTitle
  178. }
  179. })
  180. if ((globalSpec?.globalElementsSpecList?.length > 0 && globalSpec?.globalElementsSpecList)) {
  181. groupList.push({ type: 2, name: '悬浮组件', cropList: [] })
  182. }
  183. cropUserGroupMap = sorted[0]?.map((item: any) => {
  184. let corpUserGroup1s = item?.corpUserGroup1s
  185. let corpUserGroup2s = item?.corpUserGroup2s
  186. return {
  187. adAccountId: item.accountId, id: item.accountId, data: groupList.map((crop: any, index: number) => {
  188. return { ...crop, cropList: crop.type === 1 ? corpUserGroup1s[index] ? [{ ...corpUserGroup1s[index], id: corpUserGroup1s[index].groupId }] : [] : corpUserGroup2s[0] ? [{ ...corpUserGroup2s[0], id: corpUserGroup2s[0].groupId }] : [] }
  189. })
  190. }
  191. })
  192. }
  193. // 落地页信息
  194. let accountPageIdMap: any = {}
  195. adCreateLogs?.forEach((item: any) => {
  196. if (item?.pageId) {
  197. accountPageIdMap[item.accountId] = item?.pageId
  198. }
  199. })
  200. return { sysAdcreative: item?.sysAdcreative, sysPageId: item?.sysPageId, cropUserGroupMap, accountPageIdMap }
  201. })
  202. } else {
  203. const sorted = groupBy(adCreateLogs, (item) => [item.accountId])
  204. let adCreateLog = adCreateLogs[0]
  205. if (adCreateLog?.sysPageId) {
  206. pageList = [adCreateLog?.sysPage]
  207. } else {
  208. pageList = [null]
  209. }
  210. if (adCreateLog?.pageId) {
  211. adqPageList = groupBy(adCreateLogs, (item) => [item.sysAdcreativeId])?.map((item: any[]) => {
  212. if (item.some((item1: { pageId: number }) => item1.pageId)) {
  213. return item.map((item1: any) => ({
  214. pageList: [{ ...item1.page, id: item1.page.pageId }],
  215. adAccountId: item1?.accountId,
  216. id: item1?.accountId,
  217. }))
  218. } else {
  219. return null
  220. }
  221. })
  222. } else {
  223. adqPageList = [null]
  224. }
  225. let template = await getAdcreativeTemplate.run({ promotedObjectType, adcreativeTemplateId, siteSet: sysAdgroup.siteSet })
  226. let states = { kp_show: false, xd_show: true, sj_show: false, bq_show: false, sp_show: false }
  227. if (template[0]) {
  228. let pageList = template[0]?.landingPageConfig?.supportPageTypeList?.filter((i: { description: string | string[] }) => i.description.includes('微信原生推广页'))//当前版本只获取微信原生页,后期改进
  229. let pageType = pageList?.length ? pageList[0]?.pageType : null
  230. //数据展示组件
  231. if (template[0].adcreativeAttributes.some((item: { name: string }) => item.name === 'conversion_data_type' || item.name === 'conversion_target_type')) {
  232. states = { ...states, sj_show: true }
  233. }
  234. //行动按钮组件存在
  235. if (states.xd_show) {
  236. let supportLinkNameTypeData = (pageList?.filter((item: { pageType: any; }) => item.pageType === pageType)[0] as any)?.supportLinkNameType
  237. let linkNameList = supportLinkNameTypeData?.list
  238. if (linkNameList) { // && !linkPageType
  239. } else {
  240. states = { ...states, xd_show: false }
  241. }
  242. if (supportLinkNameTypeData?.required) {
  243. states = { ...states, xd_show: true }
  244. }
  245. }
  246. // 视频结束页 end_page
  247. if (template[0].adcreativeElements.some((item: { name: string }) => item.name === 'end_page')) {
  248. states = { ...states, sp_show: true }
  249. }
  250. }
  251. if (adcreativeTemplateId === 2106) {
  252. template[0].adcreativeElements = template[0]?.adcreativeElements?.map((item: any) => {
  253. if (item.name === "description") {
  254. return { ...item, name: 'title', title: item['description'] }
  255. }
  256. return item
  257. })
  258. }
  259. type2Data['textData'] = template[0]?.adcreativeElements?.filter((item: any) => item.name === 'title' || (item.required && item.name === 'description')).map((item: any) => ({ ...item, pupState: states }))
  260. type2Data['materialData'] = template[0]?.adcreativeElements?.filter((item: any) => item.required && item.name === 'image_list' || item.name === 'short_video1' || item.name === 'video' || item.name === 'image' || item.name === 'element_story').map((item: any) => {
  261. return {
  262. label: item.description === '图片' && res[0]?.adcreativeElements?.some((item: any) => item.name === 'video') ? '视频封面图' : item.description,
  263. name: item.name,
  264. restriction: item.restriction,
  265. arrayProperty: item?.arrayProperty
  266. }
  267. })
  268. taskMediaMaps = [sorted[0][0]].map((item: any) => {
  269. let pageElementsSpecList = item?.sysPage?.pageSpecsList[0]?.pageElementsSpecList // 内容区
  270. let globalSpec = item?.sysPage?.globalSpec // 悬浮组件
  271. /** 处理客服 */
  272. let cropUserGroupMap: any[] = []
  273. if ((pageElementsSpecList as any[])?.some((item: { elementType: string }) => item?.elementType === 'ENTERPRISE_WX') || (globalSpec?.globalElementsSpecList?.length > 0 && globalSpec?.globalElementsSpecList?.some((item: { floatButtonSpec: { elementType: string } }) => item?.floatButtonSpec?.elementType === 'ENTERPRISE_WX'))) {
  274. let groupList: { type: number, name: string, cropList: any[], cropId?: number, groupId?: number }[] = [];
  275. (pageElementsSpecList as any[])?.forEach((item: { elementType: string, enterpriseWxSpec: { btnTitle: string } }) => {
  276. if (item?.elementType === 'ENTERPRISE_WX') {
  277. groupList.push({ type: 1, name: '联系商家', cropList: [] }) // item.enterpriseWxSpec.btnTitle
  278. }
  279. })
  280. if ((globalSpec?.globalElementsSpecList?.length > 0 && globalSpec?.globalElementsSpecList)) {
  281. groupList.push({ type: 2, name: '悬浮组件', cropList: [] })
  282. }
  283. cropUserGroupMap = groupBy(adCreateLogs, (item) => [item.sysAdcreativeId])[0]?.map((item: any) => {
  284. let corpUserGroup1s = item?.corpUserGroup1s
  285. let corpUserGroup2s = item?.corpUserGroup2s
  286. return {
  287. adAccountId: item.accountId, id: item.accountId, data: groupList.map((crop: any, index: number) => {
  288. return { ...crop, cropList: crop.type === 1 ? corpUserGroup1s[index] ? [{ ...corpUserGroup1s[index], id: corpUserGroup1s[index].groupId }] : [] : corpUserGroup2s[0] ? [{ ...corpUserGroup2s[0], id: corpUserGroup2s[0].groupId }] : [] }
  289. })
  290. }
  291. })
  292. }
  293. // 落地页信息
  294. let accountPageIdMap: any = {}
  295. adCreateLogs?.forEach((item: any) => {
  296. if (item?.pageId) {
  297. accountPageIdMap[item.accountId] = item?.pageId
  298. }
  299. })
  300. let { adcreativeElements, ...Adcreative } = JSON.parse(JSON.stringify(item?.sysAdcreative))
  301. delete adcreativeElements?.title
  302. delete adcreativeElements?.description
  303. delete adcreativeElements?.imageUrlList
  304. delete adcreativeElements?.elementStory
  305. delete adcreativeElements?.imageUrl
  306. delete adcreativeElements?.videoUrl
  307. delete adcreativeElements?.shortVideo1Url
  308. return { sysAdcreative: { ...Adcreative, adcreativeElements }, sysPageId: item?.sysPageId, cropUserGroupMap, accountPageIdMap }
  309. })
  310. // 处理 materials [] texts []
  311. let newMaterials: any[] = [], newTexts: any[] = []
  312. sorted[0].forEach((item: any) => {
  313. let { title, description, imageUrlList, elementStory, imageUrl, videoUrl, shortVideo1Url } = item?.sysAdcreative?.adcreativeElements
  314. let texts = {};
  315. let materials = {};
  316. if (title) texts['title'] = title;
  317. if (description) texts['description'] = description;
  318. if (imageUrlList) materials['imageUrlList'] = imageUrlList;
  319. if (elementStory) materials['elementStory'] = elementStory;
  320. if (imageUrl) materials['imageUrl'] = imageUrl;
  321. if (videoUrl) materials['videoUrl'] = videoUrl;
  322. if (shortVideo1Url) materials['shortVideo1Url'] = shortVideo1Url;
  323. newMaterials.push(materials)
  324. newTexts.push(texts)
  325. })
  326. let groupMaterials: any[] = []
  327. let groupTexts: any[] = []
  328. if (newMaterials.length > 0 && newMaterials?.every(item => Object.keys(item).length > 0)) {
  329. let firstField = Object.keys(newMaterials[0])[0]
  330. groupMaterials = groupBy(newMaterials, (item) => [item[firstField]])
  331. type2Data['materials'] = newMaterials
  332. }
  333. if (newTexts.length > 0 && newTexts?.every(item => Object.keys(item).length > 0)) {
  334. let firstField = Object.keys(newTexts[0])[0]
  335. groupTexts = groupBy(newTexts, (item) => [item[firstField]])
  336. type2Data['texts'] = newTexts
  337. }
  338. let mLength = groupMaterials.length || 1
  339. let tLength = groupTexts.length || 1
  340. if (mLength * tLength === sorted[0].length) { // 数量对上是 叉乘 否则 一对一
  341. if (groupMaterials.length > 0) type2Data['materials'] = groupMaterials.map((item: any[]) => item[0])
  342. if (groupTexts.length > 0) type2Data['texts'] = groupTexts.map((item: any[]) => item[0])
  343. type2Data['model'] = 'cross'
  344. } else {
  345. type2Data['model'] = 'corres'
  346. }
  347. }
  348. if (sysAdgroup?.beginDate && moment(sysAdgroup?.beginDate) < moment()) {
  349. sysAdgroup.beginDate = moment().format('YYYY-MM-DD')
  350. message.warning('请注意,检测投放开始日期小于今天,以自动改成今天,如需修改,请重新设置')
  351. }
  352. if (sysAdgroup?.endDate && moment(sysAdgroup?.endDate) < moment()) {
  353. sysAdgroup.endDate = moment().format('YYYY-MM-DD')
  354. message.warning('请注意,检测投放结束日期小于今天,以自动改成今天,如需修改,请重新设置')
  355. }
  356. setQueryForm({
  357. ...queryForm,
  358. ...type2Data,
  359. campaignType,
  360. promotedObjectType,
  361. speedMode,
  362. sysAdgroup,
  363. sysAdgroupId,
  364. sysTargeting,
  365. sysTargetingId,
  366. adgroupName: sysAdgroup?.adgroupName,
  367. configuredStatus: sysAdgroup?.configuredStatus,
  368. expandEnabled: sysAdgroup?.expandEnabled || false,
  369. expandTargeting: sysAdgroup?.expandTargeting || [],
  370. taskMediaMaps: taskMediaMaps || [],
  371. pageList,
  372. adqPageList
  373. })
  374. })
  375. sessionStorage.removeItem('TASKID')
  376. } else {
  377. let adqAdData = localStorage.getItem('ADQAD')
  378. if (adqAdData) {
  379. const { queryForm, accountCreateLogs } = JSON.parse(adqAdData)
  380. if (queryForm?.sysAdgroup) {
  381. if (queryForm?.sysAdgroup?.beginDate && moment(queryForm?.sysAdgroup?.beginDate) < moment()) {
  382. queryForm.sysAdgroup.beginDate = moment().format('YYYY-MM-DD')
  383. message.warning('请注意,检测投放开始日期小于今天,已自动改成今天,如需修改,请重新设置')
  384. }
  385. if (queryForm?.sysAdgroup?.endDate && moment(queryForm?.sysAdgroup?.endDate) < moment()) {
  386. queryForm.sysAdgroup.endDate = moment().format('YYYY-MM-DD')
  387. message.warning('请注意,检测投放结束日期小于今天,已自动改成今天,如需修改,请重新设置')
  388. }
  389. }
  390. setQueryForm({ ...queryForm })
  391. setAccountCreateLogs(accountCreateLogs)
  392. }
  393. }
  394. }, [])
  395. // 设置地域
  396. useEffect(() => {
  397. tagsList_REGION.run({ type: 'REGION' }).then(res => {
  398. if (res && Array.isArray(res)) {
  399. setGeoLocationList(() => (res as any[])?.reduce((prev: any, cur: { id: number }) => {
  400. prev[cur.id] = cur
  401. return prev
  402. }, {}))
  403. }
  404. })
  405. tagsList_MODEL.run({ type: 'DEVICE_BRAND_MODEL' }).then(res => {
  406. if (res && Array.isArray(res)) {
  407. setModelList(() => (res as any[])?.reduce((prev: any, cur: { id: number }) => {
  408. prev[cur.id] = cur
  409. return prev
  410. }, {}))
  411. }
  412. })
  413. }, [])
  414. // 获取账户列表
  415. useEffect(() => {
  416. getAllUserAccount.run()
  417. }, [])
  418. // 账号对比
  419. useEffect(() => {
  420. if (getAllUserAccount?.data?.data && accountCreateLogs) {
  421. if (accountCreateLogs.some(item => !getAllUserAccount?.data?.data?.find((item1: { accountId: number }) => item.adAccountId == item1.accountId))) {
  422. let errorData: any[] = []
  423. let newAccountCreateLogs = accountCreateLogs.filter(item => {
  424. let data = getAllUserAccount?.data?.data?.find((item1: { accountId: number }) => item.adAccountId == item1.accountId)
  425. if (data) {
  426. return true
  427. } else {
  428. errorData.push(item.adAccountId)
  429. return false
  430. }
  431. })
  432. notification.error({
  433. duration: 60 * 5,
  434. message: '重要提示',
  435. description: `本地媒体账户与你所拥有账户对不上,当前创建账号不符合账号及部分相关配置已清空。请把保存在本地的媒体账户或者媒体账户组清空,重新选择保存。问题账户:(${errorData.toString()})`
  436. })
  437. setAccountCreateLogs(newAccountCreateLogs)
  438. setQueryForm({ ...queryForm, adqPageList: [], taskMediaMaps: queryForm?.taskMediaMaps?.map(item => ({ ...item, accountPageIdMap: {} })) })
  439. }
  440. }
  441. }, [getAllUserAccount?.data, accountCreateLogs, queryForm])
  442. /** 获取广告详情 */
  443. useEffect(() => {
  444. if (getSysAdgroups?.data?.bidMode !== 'BID_MODE_CPM' && accountCreateLogs?.length > 0) {
  445. let newAccountCreateLogs = accountCreateLogs?.map((item: any) => {
  446. if (item?.customAudienceList) {
  447. delete item?.customAudienceList
  448. }
  449. return { ...item }
  450. })
  451. setAccountCreateLogs([...newAccountCreateLogs])
  452. }
  453. }, [getSysAdgroups?.data?.bidMode])
  454. /** 删除商品内容 */
  455. const goodsDel = (index: number) => {
  456. let newArr = JSON.parse(JSON.stringify(accountCreateLogs))
  457. delete newArr[index].productList
  458. setAccountCreateLogs(newArr)
  459. }
  460. /** 删除数据源 */
  461. const sourceDel = (index: number, num: number) => {
  462. let newArr = JSON.parse(JSON.stringify(accountCreateLogs))
  463. newArr[index].userActionSetsList?.splice(num, 1)
  464. setAccountCreateLogs(newArr)
  465. }
  466. /** 删除人群包 */
  467. const cpDel = (index: number, num: number, key: string) => {
  468. let newArr = JSON.parse(JSON.stringify(accountCreateLogs))
  469. newArr[index][key]?.splice(num, 1)
  470. setAccountCreateLogs(newArr)
  471. }
  472. // 创意素材与文案叉乘处理
  473. const whatever = (...arrs: any[]) => {
  474. if (arrs[0]?.length && arrs[1]?.length) {
  475. if (queryForm.model === 'corres') { // 一一对应
  476. return arrs[0].map((item: any, index: number) => ({ ...item, ...arrs[1][index] }))
  477. }
  478. return arrs.reduce((total, curr) => total.flatMap((e: any) => curr.map((e2: any) => ({ ...e2, ...e }))))
  479. } else if (arrs[0]?.length) {
  480. return arrs[0]
  481. } else if (arrs[1]?.length) {
  482. return arrs[1]
  483. } else {
  484. return ['']
  485. }
  486. }
  487. /** 预览 */
  488. const preview = () => {
  489. let newQueryForm: Partial<CreateAdProps> = JSON.parse(JSON.stringify(queryForm))
  490. if (accountCreateLogs?.length === 0) {
  491. message.error('请选择媒体账户')
  492. return
  493. }
  494. if (!newQueryForm.promotedObjectType) {
  495. message.error('请选择推广目标')
  496. return
  497. }
  498. if (!newQueryForm.sysAdgroup) {
  499. message.error('请先设置广告基本信息')
  500. return
  501. }
  502. if (!newQueryForm.sysTargeting) {
  503. message.error('请选择定向')
  504. return
  505. }
  506. if (!newQueryForm.taskMediaMaps?.every(item => item.sysAdcreative)) {
  507. message.error('请设置创意的基本信息')
  508. return
  509. }
  510. if (!newQueryForm.taskMediaMaps?.every(item => item.sysPageId || item.accountPageIdMap)) {
  511. message.error('请选择落地页')
  512. return
  513. }
  514. if (launchMode === 2) {
  515. if ((queryForm?.materialData && queryForm?.materialData?.length > 0) && !(newQueryForm?.materials && newQueryForm?.materials?.length > 0)) {
  516. message.error('请选择创意素材')
  517. return
  518. }
  519. if ((queryForm?.textData && queryForm.textData?.length > 0) && !(newQueryForm?.texts && newQueryForm?.texts?.length > 0)) {
  520. message.error('请选择创意文案')
  521. return
  522. }
  523. if (queryForm.model === 'corres' && (queryForm?.materialData && queryForm?.materialData?.length > 0) && (queryForm?.textData && queryForm.textData?.length > 0) && queryForm.texts?.length !== queryForm?.materials?.length) {
  524. message.error('素材文案一一对应模式下,素材数量与文案数量要相等,请修改')
  525. return
  526. }
  527. }
  528. if (newQueryForm?.taskMediaMaps && newQueryForm?.taskMediaMaps?.some((item: { cropUserGroupMap: any[] }) => item?.cropUserGroupMap?.length > 0)) {
  529. let cropData = newQueryForm?.taskMediaMaps?.filter((item: { cropUserGroupMap: any[] }) => item?.cropUserGroupMap?.length > 0)
  530. if (cropData?.some((item: { cropUserGroupMap: { data: { cropList: any[] }[] }[] }) => {
  531. return item?.cropUserGroupMap?.some((item1: { data: { cropList: any[] }[] }) => item1?.data?.some((item2: { cropList: any[] }) => item2?.cropList?.length === 0))
  532. })) {
  533. message.error('请完善落地页企微客服组')
  534. return
  535. }
  536. }
  537. let data: any[] = []
  538. if (launchMode === 2) {
  539. if (Array.isArray(newQueryForm.materials) && Array.isArray(newQueryForm?.texts)) {
  540. let taskMediaMap = JSON.parse(JSON.stringify(newQueryForm.taskMediaMaps[0]))
  541. let adcreativeElements = taskMediaMap.sysAdcreative?.adcreativeElements || {}
  542. let newTaskMediaMaps = whatever(newQueryForm.materials, newQueryForm.texts).map((item: any) => {
  543. taskMediaMap.sysAdcreative.adcreativeElements = { ...adcreativeElements, ...item }
  544. return JSON.parse(JSON.stringify(taskMediaMap))
  545. })
  546. newQueryForm.taskMediaMaps = newTaskMediaMaps
  547. }
  548. }
  549. accountCreateLogs.forEach((item: any) => {
  550. newQueryForm.taskMediaMaps?.forEach((task, index) => {
  551. let obj = {
  552. ...item,
  553. ...newQueryForm,
  554. sysAdGroupData: newQueryForm.sysAdgroup,
  555. targetingData: newQueryForm.sysTargeting,
  556. sysAdcreativeData: task.sysAdcreative,
  557. pageData: launchMode === 2 ? (newQueryForm.pageList as any)[0] || (newQueryForm.adqPageList as any)[0]?.find((adq: { adAccountId: any }) => adq.adAccountId === item.adAccountId)?.pageList[0] : (newQueryForm.pageList as any)[index] || (newQueryForm.adqPageList as any)[index]?.find((adq: { adAccountId: any }) => adq.adAccountId === item.adAccountId)?.pageList[0],
  558. myId: Number(item.id + '' + index)
  559. }
  560. data.push(obj)
  561. })
  562. })
  563. setTableData(data)
  564. }
  565. const submit = (props: { campaignName: string, count?: number }) => {
  566. let newQueryForm = JSON.parse(JSON.stringify(queryForm))
  567. if (launchMode === 2) {
  568. if (Array.isArray(newQueryForm.materials) && Array.isArray(newQueryForm?.texts)) {
  569. let taskMediaMap = JSON.parse(JSON.stringify(newQueryForm.taskMediaMaps[0]))
  570. let adcreativeElements = taskMediaMap.sysAdcreative?.adcreativeElements || {}
  571. let newTaskMediaMaps = whatever(newQueryForm.materials, newQueryForm.texts).map((item: any) => {
  572. if (item) {
  573. taskMediaMap.sysAdcreative.adcreativeElements = { ...adcreativeElements, ...item }
  574. } else {
  575. taskMediaMap.sysAdcreative.adcreativeElements = { ...adcreativeElements }
  576. }
  577. return JSON.parse(JSON.stringify(taskMediaMap))
  578. })
  579. newQueryForm.taskMediaMaps = newTaskMediaMaps
  580. }
  581. }
  582. let newtaskMediaMaps = newQueryForm.taskMediaMaps.map((item1: { cropUserGroupMap?: any[] }) => {
  583. let { cropUserGroupMap, ...data } = item1
  584. if (cropUserGroupMap && cropUserGroupMap?.length > 0) {
  585. let corpUserGroup1Map: any = {}
  586. let corpUserGroup2Map: any = {}
  587. cropUserGroupMap.forEach((cropData: { id: number, data: any[] }) => {
  588. let cropData1: { corpId: string, groupId: number }[] = []
  589. let cropData2: { corpId: string, groupId: number }[] = []
  590. cropData?.data.forEach((crop: { type: 1 | 2, cropList: { corpId: string, groupId: number }[] }) => {
  591. let cropList = crop.cropList
  592. if (crop.type === 1) {
  593. cropData1.push({ corpId: cropList[0].corpId, groupId: cropList[0].groupId })
  594. } else {
  595. cropData2.push({ corpId: cropList[0].corpId, groupId: cropList[0].groupId })
  596. }
  597. })
  598. if (cropData1.length > 0) {
  599. corpUserGroup1Map[cropData.id.toString()] = cropData1
  600. }
  601. if (cropData2.length > 0) {
  602. corpUserGroup2Map[cropData.id.toString()] = cropData2
  603. }
  604. })
  605. return { ...data, corpUserGroup1Map: Object.keys(corpUserGroup1Map)?.length > 0 ? corpUserGroup1Map : null, corpUserGroup2Map: Object.keys(corpUserGroup2Map)?.length > 0 ? corpUserGroup2Map : null }
  606. }
  607. return data
  608. })
  609. newQueryForm.taskMediaMaps = newtaskMediaMaps
  610. let params = { ...newQueryForm, ...props }
  611. let accountLogs = accountCreateLogs.map((item: any, index) => {
  612. // userActionSetsList 数据源 productList 商品
  613. let data: any = { adAccountId: item.adAccountId, count: props.count || 1 }
  614. if (item?.userActionSetsList?.length > 0) { // 数据源
  615. data.userActionSets = item?.userActionSetsList?.map((item: any) => ({ id: item?.id, type: item?.type }))
  616. }
  617. if (item?.productList?.length > 0) { // 商品
  618. data.productId = item?.productList[0].productOuterId
  619. data.productCatalogId = item?.productList[0].productCatalogId
  620. }
  621. if (item?.customAudienceList?.length > 0) {
  622. data.customAudience = item?.customAudienceList?.map((item: any) => item.id)
  623. }
  624. if (item?.excludedCustomAudienceList?.length > 0) {
  625. data.excludedCustomAudience = item?.excludedCustomAudienceList?.map((item: any) => item.id)
  626. }
  627. if (item?.pageList) {
  628. data.pageId = item?.pageData?.id
  629. }
  630. if (item?.coldStartAudienceList?.length > 0) {
  631. data.coldStartAudience = item?.coldStartAudienceList?.map((item: any) => item.id)
  632. }
  633. return data
  634. })
  635. if (params?.expandEnabled) {
  636. params.sysAdgroup.expandEnabled = params?.expandEnabled
  637. params.sysAdgroup.expandTargeting = []
  638. }
  639. if (params?.expandTargeting?.length > 0) {
  640. params.sysAdgroup.expandTargeting = params?.expandTargeting
  641. }
  642. params.accountCreateLogs = accountLogs
  643. delete params.sysAdgroupId
  644. delete params.sysAdcreativeId
  645. delete params.sysTargetingId
  646. delete params.pageList
  647. delete params.adqPageList
  648. delete params.count
  649. delete params?.expandEnabled
  650. delete params?.expandTargeting
  651. delete params?.texts
  652. delete params?.textData
  653. delete params?.materialData
  654. delete params?.materials
  655. delete params?.model
  656. console.log('paramsSubmit====>', params)
  657. createAdBatch.run(params).then(res => {
  658. if (res) {
  659. Modal.success({
  660. content: '任务提交成功',
  661. bodyStyle: { fontWeight: 700 },
  662. okText: '跳转任务列表',
  663. closable: true,
  664. onOk: () => {
  665. sessionStorage.setItem('CAMP', props?.campaignName)
  666. window.location.href = '/#/launchSystemNew/launchManage/taskList'
  667. },
  668. onCancel: () => {
  669. setSubVisible(false)
  670. }
  671. })
  672. }
  673. })
  674. }
  675. /** 清除数据 */
  676. const clearData = () => {
  677. setTableData([])
  678. setTableSelect([])
  679. }
  680. /** 存为预设 */
  681. const severBd = () => {
  682. // queryForm accountCreateLogs
  683. localStorage.setItem('ADQAD', JSON.stringify({
  684. queryForm,
  685. accountCreateLogs
  686. }))
  687. message.success('存储成功')
  688. }
  689. /** 清除 */
  690. const delBdPlan = () => {
  691. localStorage.removeItem('ADQAD')
  692. setAccountCreateLogs([])
  693. setQueryForm({
  694. campaignName: '', // 计划名称
  695. campaignType: 'CAMPAIGN_TYPE_NORMAL', // 计划类型 CAMPAIGN_TYPE_NORMAL CAMPAIGN_TYPE_SEARCH
  696. promotedObjectType: 'PROMOTED_OBJECT_TYPE_WECHAT_OFFICIAL_ACCOUNT', // 推广目标类型
  697. speedMode: 'SPEED_MODE_STANDARD', // 投放速度模式
  698. sysAdgroupId: undefined, // 广告组内容
  699. sysTargetingId: undefined, // 定向包 id
  700. adgroupName: undefined, // 广告名称
  701. configuredStatus: 'AD_STATUS_SUSPEND', // 广告状态
  702. sysAdcreativeId: undefined, // 创意ID
  703. expandEnabled: false,
  704. expandTargeting: [],
  705. model: 'cross'
  706. })
  707. }
  708. /** 设置落地页 */
  709. const setPage = (e: any) => {
  710. let arr: any = queryForm.taskMediaMaps || []
  711. function setUrl(item: { sysAdcreative: { overrideCanvasHeadOption: string, adcreativeElements: any } }) {
  712. if (item?.sysAdcreative?.overrideCanvasHeadOption && item?.sysAdcreative?.overrideCanvasHeadOption === "OPTION_CANVAS_OVERRIDE_CREATIVE") {
  713. let adcreativeElementsNew = { ...item.sysAdcreative.adcreativeElements }
  714. let obj = e[0].pageSpecsList[0].pageElementsSpecList[0]
  715. let { topImageSpec, topVideoSpec, topSliderSpec } = obj
  716. Object.keys(adcreativeElementsNew).forEach(key => {
  717. switch (key) {
  718. case 'imageUrl'://图素材
  719. adcreativeElementsNew[key] = topImageSpec?.imageUrl
  720. break;
  721. case 'videoUrl'://视频素材
  722. adcreativeElementsNew[key] = topVideoSpec?.videoUrl
  723. break;
  724. case 'imageUrlList'://图素材
  725. adcreativeElementsNew[key] = topSliderSpec?.imageUrlList || [topImageSpec?.imageUrl]
  726. break;
  727. case 'shortVideoStruct'://视频素材
  728. adcreativeElementsNew[key] = { shortVideo1Url: topVideoSpec?.videoUrl }
  729. break;
  730. }
  731. })
  732. return { ...item, sysPageId: e[0]?.id, accountPageIdMap: null, sysAdcreative: { ...item.sysAdcreative, adcreativeElements: adcreativeElementsNew } }
  733. }
  734. return { ...item, sysPageId: e[0]?.id, accountPageIdMap: null, }
  735. }
  736. if (page_checked) {
  737. arr = queryForm.taskMediaMaps?.map(item => {
  738. return setUrl(item)
  739. })
  740. } else {
  741. arr[targetKey as string] = setUrl(arr[targetKey as string])
  742. }
  743. getPageInfo(arr)
  744. setSelectImgVisible(false)
  745. }
  746. /** 获取落地页详情 */
  747. const getPageInfo = useCallback((arrList) => {
  748. console.log('arrList====>', arrList)
  749. if (arrList && arrList[targetKey]?.sysPageId) {
  750. get.run({ mediaType: 'PAGE', sysMediaId: arrList[targetKey]?.sysPageId }).then(res => {
  751. if (!Object.keys(res)?.includes('fail')) {
  752. let data = res
  753. let pageElementsSpecList = data?.pageSpecsList[0]?.pageElementsSpecList // 内容区
  754. let globalSpec = data?.globalSpec // 悬浮组件
  755. let arr: any = queryForm.pageList || []
  756. let adqPageArr: any = queryForm.adqPageList || []
  757. adqPageArr[targetKey] = null
  758. arr[targetKey] = data
  759. /** 处理客服 */
  760. let cropUserGroupMap: any[] = []
  761. if ((pageElementsSpecList as any[])?.some((item: { elementType: string }) => item?.elementType === 'ENTERPRISE_WX') || (globalSpec?.globalElementsSpecList?.length > 0 && globalSpec?.globalElementsSpecList?.some((item: { floatButtonSpec: { elementType: string } }) => item?.floatButtonSpec?.elementType === 'ENTERPRISE_WX'))) {
  762. let groupList: { type: number, name: string, cropList: any[], cropId?: number, groupId?: number }[] = [];
  763. (pageElementsSpecList as any[])?.forEach((item: { elementType: string, enterpriseWxSpec: { btnTitle: string } }) => {
  764. if (item?.elementType === 'ENTERPRISE_WX') {
  765. groupList.push({ type: 1, name: '联系商家', cropList: [] }) // item.enterpriseWxSpec.btnTitle
  766. }
  767. })
  768. if ((globalSpec?.globalElementsSpecList?.length > 0 && globalSpec?.globalElementsSpecList)) {
  769. groupList.push({ type: 2, name: '悬浮组件', cropList: [] })
  770. }
  771. cropUserGroupMap = accountCreateLogs?.map((item: any) => ({ adAccountId: item.adAccountId, id: item.id, data: groupList }))
  772. }
  773. arrList[targetKey].cropUserGroupMap = cropUserGroupMap
  774. setQueryForm({ ...queryForm, pageList: arr, taskMediaMaps: arrList, adqPageList: adqPageArr })//设置落地页详情数组
  775. } else {
  776. //清空对应创意中的落地页ID
  777. let arr = queryForm.taskMediaMaps || []
  778. arr[targetKey].sysPageId = ''
  779. setQueryForm({ ...queryForm, taskMediaMaps: arr })
  780. }
  781. })
  782. }
  783. }, [queryForm, targetKey, accountCreateLogs])
  784. // 设置云端落地页
  785. const setAdqPage = useCallback((data) => {
  786. if (Array.isArray(data) && data.length > 0) {
  787. let objMap = {}
  788. data?.forEach(item => {
  789. objMap[item.adAccountId] = item.pageList[0].pageId
  790. })
  791. let arr: any = queryForm.taskMediaMaps || []
  792. let adqPageArr: any = queryForm.adqPageList || []
  793. let pageArr: any = queryForm.pageList || []
  794. adqPageArr[targetKey as string] = data
  795. pageArr[targetKey as string] = null
  796. delete arr[targetKey as string]?.cropUserGroupMap
  797. arr[targetKey as string] = { ...arr[targetKey as string], sysPageId: '', accountPageIdMap: objMap }
  798. // 重新设置云端数据并清空本地数据
  799. setQueryForm({ ...queryForm, taskMediaMaps: arr, adqPageList: adqPageArr, pageList: pageArr })
  800. }
  801. }, [queryForm, targetKey])
  802. // tabs新增和删除
  803. const onEdit = useCallback((targetKey: string | React.MouseEvent<Element, MouseEvent> | React.KeyboardEvent<Element>, action: 'add' | 'remove') => {
  804. if (queryForm.taskMediaMaps) {
  805. if (action === 'remove') {
  806. let arr = queryForm.taskMediaMaps
  807. let adqPageArr: any = queryForm.adqPageList || []
  808. let pageArr: any = queryForm.pageList || []
  809. adqPageArr[targetKey as string] = null
  810. pageArr[targetKey as string] = null
  811. arr[targetKey as string] = { ...arr[targetKey as string], sysPageId: '', accountPageIdMap: null }
  812. setQueryForm({ ...queryForm, taskMediaMaps: arr, pageList: pageArr, adqPageList: adqPageArr })
  813. }
  814. }
  815. }, [queryForm, targetKey])
  816. // 媒体组更新通知
  817. const usersChange = useCallback(() => {
  818. let data = JSON.parse(localStorage.getItem('ADQUSERS' + userId) as any)
  819. setUsersArr(data)
  820. }, [])
  821. // 切换投放模式
  822. const switchLaunchMode = () => {
  823. if (launchMode === 1) {
  824. setLaunchMode(2)
  825. localStorage.setItem('LAUNCHMODE', '2')
  826. } else {
  827. setLaunchMode(1)
  828. localStorage.setItem('LAUNCHMODE', '1')
  829. }
  830. delBdPlan()
  831. set_targetKey('0')
  832. }
  833. /** 获取分组里账号 */
  834. const getGroupAccountList = (ids: number[]) => {
  835. if (ids.length > 0) {
  836. let data = ids.map(id => getAccountListApi(id))
  837. Promise.all(data).then(res => {
  838. if (res?.length > 0 && res.every((item: { code: number }) => item.code === 200)) {
  839. let userArr: any[] = []
  840. res.forEach((item: { data: { adAccountList: { accountId: number, id: number }[] } }) => {
  841. item.data.adAccountList.forEach(acc => {
  842. let obj = userArr.find((item: { accountId: number }) => item.accountId === acc.accountId)
  843. if (!obj) {
  844. userArr.push(acc)
  845. }
  846. })
  847. })
  848. setAccountCreateLogs(userArr?.map((item) => ({ adAccountId: item?.accountId, id: item.accountId })))
  849. clearData()
  850. setQueryForm({ ...queryForm, adqPageList: [], pageList: [], taskMediaMaps: queryForm?.taskMediaMaps?.map((item: { sysPageId: number }) => ({ ...item, sysPageId: '', accountPageIdMap: {}, cropUserGroupMap: [] })) })
  851. } else {
  852. message.error('操作异常')
  853. }
  854. })
  855. } else {
  856. setAccountCreateLogs([])
  857. }
  858. }
  859. return <Space direction="vertical" style={{ width: '100%' }}>
  860. <Card
  861. title={<Space>
  862. <div className={style.cardTitle}>配置区</div>
  863. <Popconfirm
  864. title="数据部分不会保存,是否切换?"
  865. onConfirm={switchLaunchMode}
  866. okText="是"
  867. cancelText="否"
  868. >
  869. <Button type="link" style={{ padding: 0 }}>切换投放模式</Button>
  870. </Popconfirm>
  871. </Space>}
  872. className={style.createAd}
  873. hoverable
  874. // extra={<AddGroup onChange={usersChange} pitcherData={getAdAccount?.data?.data} />}
  875. >
  876. <Space wrap>
  877. <Selector label="媒体账户组">
  878. <Select
  879. mode="multiple"
  880. style={{ minWidth: 200 }}
  881. placeholder="快捷选择媒体账户组"
  882. maxTagCount={1}
  883. allowClear
  884. bordered={false}
  885. filterOption={(input: any, option: any) => {
  886. return option!.children?.toString().toLowerCase().includes(input.toLowerCase())
  887. }}
  888. onChange={(e, option) => { getGroupAccountList(e) }}
  889. >
  890. {getGroupList?.data?.map((item: any) => <Select.Option value={item.groupId} key={item.groupId}>{item.groupName}</Select.Option>)}
  891. </Select>
  892. </Selector>
  893. <Selector label="媒体账户">
  894. <Select
  895. mode="multiple"
  896. style={{ minWidth: 200, maxWidth: 500 }}
  897. placeholder="媒体账户(多个,,空格换行)"
  898. maxTagCount={1}
  899. allowClear
  900. bordered={false}
  901. maxTagPlaceholder={<Tooltip color="#FFF" title={<span style={{ color: '#000' }}>{accountCreateLogs?.filter((item, index) => index !== 0)?.map(item => item.adAccountId).toString()}</span>}>
  902. <span>+{accountCreateLogs?.length > 1 ? accountCreateLogs.length - 1 : 0}</span>
  903. </Tooltip>}
  904. dropdownMatchSelectWidth={false}
  905. autoClearSearchValue={false}
  906. filterOption={(input: any, option: any) => {
  907. let newInput: string[] = input ? input?.split(/[,,\n\s]+/ig).filter((item: any) => item) : []
  908. return newInput?.some(val => option!.children?.toString().toLowerCase()?.includes(val))
  909. }}
  910. value={accountCreateLogs?.map((item: { id: number }) => item?.id)}
  911. onChange={(e, option) => {
  912. setQueryForm({ ...queryForm, adqPageList: [], pageList: [], taskMediaMaps: queryForm?.taskMediaMaps?.map((item: { sysPageId: number }) => ({ ...item, sysPageId: '', accountPageIdMap: {}, cropUserGroupMap: [] })) })
  913. setAccountCreateLogs(option?.map((item: any) => ({ adAccountId: item?.children?.toString()?.split('_')[0], id: item?.value })))
  914. clearData()
  915. }}
  916. searchValue={accSearch}
  917. onSearch={(val) => {
  918. setAccSearch(val)
  919. }}
  920. dropdownRender={menu => (
  921. <>
  922. {menu}
  923. <Divider style={{ margin: '8px 0' }} />
  924. <Space style={{ padding: '0 8px 4px' }}>
  925. <Checkbox onChange={(e) => {
  926. let data = []
  927. if (e.target.checked) {
  928. data = JSON.parse(JSON.stringify(getAllUserAccount?.data?.data))
  929. if (accSearch) {
  930. let newAccSearch = accSearch?.split(/[,,\n\s]+/ig).filter((item: any) => item)
  931. data = data?.filter((item: any) => newAccSearch?.some(val => item!.accountId?.toString().toLowerCase()?.includes(val)))
  932. }
  933. }
  934. setQueryForm({ ...queryForm, adqPageList: [], pageList: [], taskMediaMaps: queryForm?.taskMediaMaps?.map((item: { sysPageId: number }) => ({ ...item, sysPageId: '', accountPageIdMap: {}, cropUserGroupMap: [] })) })
  935. setAccountCreateLogs(data?.map((item: any) => ({ adAccountId: item?.accountId, id: item?.adAccountId })))
  936. clearData()
  937. }}>全选</Checkbox>
  938. </Space>
  939. </>
  940. )}
  941. >
  942. {getAllUserAccount?.data?.data?.map((item: any) => <Select.Option value={item.accountId} key={item.id}>{item.remark ? item.accountId + '_' + item.remark : item.accountId}</Select.Option>)}
  943. </Select>
  944. </Selector>
  945. <Selector label="推广目标">
  946. <Select style={{ width: 200 }} value={queryForm?.promotedObjectType} placeholder="请选择推广目标" bordered={false} showSearch filterOption={(input: any, option: any) =>
  947. (option!.children as unknown as string).toLowerCase().includes(input.toLowerCase())
  948. } onChange={(e) => { setQueryForm({ ...queryForm, promotedObjectType: e, sysAdgroup: null, sysAdgroupId: undefined, taskMediaMaps: [], sysAdcreativeId: undefined, materials: [], textData: [], texts: [] }); clearData() }}>
  949. {Object.keys(PromotedObjectType).map(key => {
  950. return <Select.Option value={key} key={key}>{PromotedObjectType[key]}</Select.Option>
  951. })}
  952. </Select>
  953. </Selector>
  954. {launchMode === 2 && accountCreateLogs?.length > 0 && <>
  955. <Button onClick={() => { setGoodsVisible(true) }}>商品广告(选填){accountCreateLogs?.some(item => item?.productList?.length) && <CheckOutlined style={{ color: '#1890ff' }} />}</Button>
  956. <Button onClick={() => { setSourceVisible(true) }}>精准匹配归因(选填){accountCreateLogs?.some(item => item?.userActionSetsList?.length) && <CheckOutlined style={{ color: '#1890ff' }} />}</Button>
  957. </>}
  958. </Space>
  959. <div className={style.cardBody}>
  960. <Row className={style.content}>
  961. <Col span={launchMode === 1 ? 12 : 8} xl={launchMode === 1 ? 12 : 8} lg={24} md={24} sm={24} xs={24} className={style.conLeft}>
  962. <Row className={`${style.conTitle} ${style.conRightBorder}`}><Col span={24}>广告</Col></Row>
  963. <Row className={style.items}>
  964. {/* =============广告基本信息=========== */}
  965. <Ad queryForm={queryForm} setQueryForm={setQueryForm} getSysAdgroups={getSysAdgroups} clearData={clearData} />
  966. {/* =============定向包=========== */}
  967. <TargetIng
  968. queryForm={queryForm}
  969. setQueryForm={setQueryForm}
  970. getSysAdgroups={getSysAdgroups}
  971. clearData={clearData}
  972. setAccountCreateLogs={setAccountCreateLogs}
  973. getsysTargeting={getsysTargeting}
  974. geoLocationList={geoLocationList}
  975. modelList={modelList}
  976. cpDel={cpDel}
  977. accountCreateLogs={accountCreateLogs}
  978. />
  979. {launchMode === 1 && <>
  980. {/* =============商品=========== */}
  981. <Col className={style.conRightBorder} span={5}>
  982. <div className={style.top}>
  983. 商品
  984. </div>
  985. <div className={style.center}>
  986. <div className={style.centerContent}>
  987. {accountCreateLogs?.map((item: any, index: number) => {
  988. if (item?.productList) {
  989. return <div className={style.acc} key={index}>
  990. <div className={style.accName} style={{ fontWeight: 800 }}>{item.adAccountId}</div>
  991. {
  992. item?.productList?.map((pack: { productName: string, author: string, id: number }, index: number) => {
  993. return <div className={style.accCon} key={pack.id}>{pack.productName}<CloseOutlined className={style.close} onClick={() => {
  994. goodsDel(index)
  995. }} /></div>
  996. })
  997. }
  998. </div>
  999. } else {
  1000. return null
  1001. }
  1002. })}
  1003. </div>
  1004. </div>
  1005. <div className={style.bottom}>
  1006. {accountCreateLogs?.length > 0 ? <span onClick={() => { setGoodsVisible(true) }}>编辑</span> : <Tooltip title="请先选择媒体账户">
  1007. <span>编辑</span>
  1008. </Tooltip>}
  1009. </div>
  1010. </Col>
  1011. {/* 数据源 */}
  1012. <Col className={style.conRightBorder} span={5}>
  1013. <div className={style.top}>
  1014. 数据源
  1015. </div>
  1016. <div className={style.center}>
  1017. <div className={style.centerContent}>
  1018. {accountCreateLogs?.map((item: any, index: number) => {
  1019. if (item?.userActionSetsList && item?.userActionSetsList?.length > 0) {
  1020. return <div className={style.acc} key={index}>
  1021. <div className={style.accName} style={{ fontWeight: 800 }}>{item.adAccountId}</div>
  1022. {
  1023. item?.userActionSetsList?.map((pack: { name: string, type: string, id: number }, index1: number) => {
  1024. return <div className={style.accCon} key={pack.id}> <span className={style.title}>{pack.name}{' > '}{pack.type?.replace('USER_ACTION_SET_TYPE_', '')}</span> <CloseOutlined className={style.close} onClick={() => {
  1025. sourceDel(index, index1)
  1026. }} /></div>
  1027. })
  1028. }
  1029. </div>
  1030. } else {
  1031. return null
  1032. }
  1033. })}
  1034. </div>
  1035. </div>
  1036. <div className={style.bottom}>
  1037. {accountCreateLogs?.length > 0 ? <span onClick={() => { setSourceVisible(true) }}>编辑</span> : <Tooltip title="请先选择媒体账户">
  1038. <span>编辑</span>
  1039. </Tooltip>}
  1040. </div>
  1041. </Col>
  1042. </>}
  1043. </Row>
  1044. </Col>
  1045. {/* =============广告创意=========== */}
  1046. {launchMode === 1 ? <Col span={12} xl={12} lg={24} md={24} sm={24} xs={24} className={style.conRight}>
  1047. <Row className={style.conTitle}><Col span={24}>广告创意</Col></Row>
  1048. <Row className={style.items}>
  1049. {/* 创意 */}
  1050. <Creative queryForm={queryForm} setQueryForm={setQueryForm} getSysAdgroups={getSysAdgroups} clearData={clearData} getSysAdcreative={getSysAdcreative} set_targetKey={set_targetKey} targetKey={targetKey} page_checked={page_checked} />
  1051. {/* 落地页 */}
  1052. <Col span={12} >
  1053. <div className={style.top}>
  1054. 落地页
  1055. {(queryForm?.taskMediaMaps && queryForm?.taskMediaMaps[targetKey]?.cropUserGroupMap?.length > 0) && <CustomerServiceModal data={queryForm?.taskMediaMaps[targetKey]?.cropUserGroupMap} onChange={(data) => {
  1056. let newQueryForm = JSON.parse(JSON.stringify(queryForm))
  1057. newQueryForm.taskMediaMaps[targetKey].cropUserGroupMap = data
  1058. setQueryForm(newQueryForm)
  1059. }} />}
  1060. </div>
  1061. <div className={style.center}>
  1062. <Tabs size={'small'} onEdit={onEdit} type="editable-card" activeKey={targetKey} onChange={(key) => { set_targetKey(key) }} hideAdd >
  1063. {
  1064. queryForm?.taskMediaMaps?.map((item, index) => {
  1065. return <Tabs.TabPane tab={'创意' + (index + 1)} key={index} >
  1066. <Spin spinning={get.loading}>
  1067. <div className={style.centerContent}>
  1068. {
  1069. item?.sysPageId || item?.accountPageIdMap ? <>
  1070. {
  1071. (item?.sysPageId && queryForm?.pageList) && <>
  1072. <div>落地页名称:{queryForm?.pageList[targetKey]?.pageName || ''}</div>
  1073. <div>分享名称:{queryForm?.pageList[targetKey]?.shareContentSpec?.shareTitle || ''}</div>
  1074. <div>分享描述:{queryForm?.pageList[targetKey]?.shareContentSpec?.shareDescription || ''}</div>
  1075. <div style={{ marginBottom: 10 }}>原生推广页顶部素材预览:
  1076. <div>{queryForm?.pageList[targetKey]?.pageSpecsList && queryForm?.pageList[targetKey]?.pageSpecsList[0]?.pageElementsSpecList?.filter((item: any, index: number) => index === 0)?.map((item: { elementType: 'TOP_IMAGE' | 'TOP_VIDEO' | 'TOP_SLIDER', topImageSpec: any, topSliderSpec: any, topVideoSpec: any }, index: number) => {
  1077. switch (item?.elementType) {
  1078. case 'TOP_IMAGE':
  1079. return <Image width={80} src={item?.topImageSpec?.imageUrl} style={{ borderRadius: 8, overflow: 'hidden' }} key={index} />
  1080. case 'TOP_SLIDER':
  1081. return <Space wrap key={index}>
  1082. {item?.topSliderSpec?.imageUrlList?.map((url: string, index: number) => <Image width={70} src={url} style={{ borderRadius: 8 }} key={'TOP_SLIDER' + index} />)}
  1083. </Space>
  1084. case 'TOP_VIDEO':
  1085. return <video src={item?.topVideoSpec?.videoUrl} width={150} controls key={index}></video>
  1086. }
  1087. })}</div>
  1088. </div>
  1089. </>
  1090. }
  1091. {
  1092. queryForm?.adqPageList && queryForm?.adqPageList[targetKey]?.map((adq: any) => {
  1093. return <div className={style.acc} key={adq.adAccountId}>
  1094. <div className={style.accName} style={{ fontWeight: 800 }}>{adq.adAccountId}</div>
  1095. <div className={style.accCon}>
  1096. <span className={style.title}>{adq.pageList[0].pageName}</span>
  1097. </div>
  1098. </div>
  1099. })
  1100. }
  1101. </> : <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />}
  1102. </div>
  1103. </Spin>
  1104. </Tabs.TabPane>
  1105. })
  1106. }
  1107. </Tabs>
  1108. </div>
  1109. <div className={style.bottom}>{
  1110. (queryForm?.taskMediaMaps && queryForm?.taskMediaMaps[targetKey]?.sysAdcreative) ? <>
  1111. {queryForm?.taskMediaMaps && queryForm?.taskMediaMaps[targetKey]?.sysPageId && <Button type="link" onClick={() => { setLookVisible(true) }}>查看</Button>}
  1112. <Button type="link" onClick={() => {
  1113. setSelectImgVisible(true)
  1114. // 判定是否用原生页顶部替换外部素材
  1115. if (queryForm?.taskMediaMaps && queryForm?.taskMediaMaps[targetKey]?.sysAdcreative?.overrideCanvasHeadOption === 'OPTION_CANVAS_OVERRIDE_CREATIVE') {
  1116. init({ mediaType: 'PAGE', cloudSize: undefined, adcreativeTemplateId: queryForm?.taskMediaMaps[targetKey]?.sysAdcreative?.adcreativeTemplateId })
  1117. } else {
  1118. init({ mediaType: 'PAGE', cloudSize: undefined })
  1119. }
  1120. }}>{queryForm?.taskMediaMaps && queryForm?.taskMediaMaps[targetKey]?.sysPageId ? '修改' : '选择落地页'}</Button>
  1121. {accountCreateLogs?.length > 0 ? <Button type="link" onClick={() => {
  1122. setPageVisible(true)
  1123. if (queryForm?.taskMediaMaps && queryForm?.taskMediaMaps[targetKey]?.sysAdcreative?.overrideCanvasHeadOption === 'OPTION_CANVAS_OVERRIDE_CREATIVE') {
  1124. setCloudParams({ adcreativeTemplateId: queryForm?.taskMediaMaps[targetKey]?.sysAdcreative?.adcreativeTemplateId })
  1125. } else {
  1126. setCloudParams({})
  1127. }
  1128. }}>云端落地页</Button> : <Tooltip title="请先选择媒体账户">
  1129. <Button type="link">云端落地页</Button>
  1130. </Tooltip>}
  1131. </> : <Tooltip title="请先设置创意">
  1132. <Button type="link"><span>选择落地页</span></Button>
  1133. </Tooltip>}
  1134. </div>
  1135. </Col>
  1136. </Row>
  1137. </Col> : <Col span={16} xl={16} lg={24} md={24} sm={24} xs={24} className={style.conRight}>
  1138. <Row className={style.conTitle}><Col span={24}>广告创意</Col></Row>
  1139. <Row className={style.items}>
  1140. {/* 创意 */}
  1141. <CreativeCL queryForm={queryForm} setQueryForm={setQueryForm} clearData={clearData} getSysAdcreative={getSysAdcreative} targetKey={targetKey} />
  1142. {/* 落地页 */}
  1143. <Col className={style.conRightBorder} style={{ maxWidth: '25%', border: 'none' }}>
  1144. <div className={style.top}>
  1145. 落地页
  1146. {(queryForm?.taskMediaMaps && queryForm?.taskMediaMaps[targetKey]?.cropUserGroupMap?.length > 0) && <CustomerServiceModal data={queryForm?.taskMediaMaps[targetKey]?.cropUserGroupMap} onChange={(data) => {
  1147. let newQueryForm = JSON.parse(JSON.stringify(queryForm))
  1148. newQueryForm.taskMediaMaps[targetKey].cropUserGroupMap = data
  1149. setQueryForm(newQueryForm)
  1150. }} />}
  1151. </div>
  1152. <div className={style.center}>
  1153. {queryForm?.taskMediaMaps?.filter((item, index) => index === 0)?.map((item, index) => {
  1154. return <Spin spinning={get.loading} key={index}>
  1155. <div className={style.centerContent}>
  1156. {item?.sysPageId || item?.accountPageIdMap ? <>
  1157. {(item?.sysPageId && queryForm?.pageList) && <>
  1158. <div>落地页名称:{queryForm?.pageList[targetKey]?.pageName || ''}</div>
  1159. <div>分享名称:{queryForm?.pageList[targetKey]?.shareContentSpec?.shareTitle || ''}</div>
  1160. <div>分享描述:{queryForm?.pageList[targetKey]?.shareContentSpec?.shareDescription || ''}</div>
  1161. <div style={{ marginBottom: 10 }}>原生推广页顶部素材预览:
  1162. <div>{queryForm?.pageList[targetKey]?.pageSpecsList && queryForm?.pageList[targetKey]?.pageSpecsList[0]?.pageElementsSpecList?.filter((item: any, index: number) => index === 0)?.map((item: { elementType: 'TOP_IMAGE' | 'TOP_VIDEO' | 'TOP_SLIDER', topImageSpec: any, topSliderSpec: any, topVideoSpec: any }, index: number) => {
  1163. switch (item?.elementType) {
  1164. case 'TOP_IMAGE':
  1165. return <Image width={80} src={item?.topImageSpec?.imageUrl} style={{ borderRadius: 8, overflow: 'hidden' }} key={index} />
  1166. case 'TOP_SLIDER':
  1167. return <Space wrap key={index}>
  1168. {item?.topSliderSpec?.imageUrlList?.map((url: string, index: number) => <Image width={70} src={url} style={{ borderRadius: 8 }} key={'TOP_SLIDER' + index} />)}
  1169. </Space>
  1170. case 'TOP_VIDEO':
  1171. return <video src={item?.topVideoSpec?.videoUrl} width={150} controls key={index}></video>
  1172. }
  1173. })}</div>
  1174. </div>
  1175. </>}
  1176. {queryForm?.adqPageList && queryForm?.adqPageList[targetKey]?.map((adq: any) => {
  1177. return <div className={style.acc} key={adq.adAccountId}>
  1178. <div className={style.accName} style={{ fontWeight: 800 }}>{adq.adAccountId}</div>
  1179. <div className={style.accCon}>
  1180. <span className={style.title}>{adq.pageList[0].pageName}</span>
  1181. </div>
  1182. </div>
  1183. })}
  1184. </> : <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />}
  1185. </div>
  1186. </Spin>
  1187. })}
  1188. </div>
  1189. <div className={style.bottom}>{
  1190. (queryForm?.taskMediaMaps && queryForm?.taskMediaMaps[targetKey]?.sysAdcreative) ? <>
  1191. {queryForm?.taskMediaMaps && queryForm?.taskMediaMaps[targetKey]?.sysPageId && <Button type="link" onClick={() => { setLookVisible(true) }}>查看</Button>}
  1192. <Button type="link" onClick={() => {
  1193. setSelectImgVisible(true)
  1194. // 判定是否用原生页顶部替换外部素材
  1195. if (queryForm?.taskMediaMaps && queryForm?.taskMediaMaps[targetKey]?.sysAdcreative?.overrideCanvasHeadOption === 'OPTION_CANVAS_OVERRIDE_CREATIVE') {
  1196. init({ mediaType: 'PAGE', cloudSize: undefined, adcreativeTemplateId: queryForm?.taskMediaMaps[targetKey]?.sysAdcreative?.adcreativeTemplateId })
  1197. } else {
  1198. init({ mediaType: 'PAGE', cloudSize: undefined })
  1199. }
  1200. }}>{queryForm?.taskMediaMaps && queryForm?.taskMediaMaps[targetKey]?.sysPageId ? '修改' : '选择落地页'}</Button>
  1201. {accountCreateLogs?.length > 0 ? <Button type="link" onClick={() => {
  1202. setPageVisible(true)
  1203. if (queryForm?.taskMediaMaps && queryForm?.taskMediaMaps[targetKey]?.sysAdcreative?.overrideCanvasHeadOption === 'OPTION_CANVAS_OVERRIDE_CREATIVE') {
  1204. setCloudParams({ adcreativeTemplateId: queryForm?.taskMediaMaps[targetKey]?.sysAdcreative?.adcreativeTemplateId })
  1205. } else {
  1206. setCloudParams({})
  1207. }
  1208. }}>云端落地页</Button> : <Tooltip title="请先选择媒体账户">
  1209. <Button type="link">云端落地页</Button>
  1210. </Tooltip>}
  1211. </> : <Tooltip title="请先设置创意">
  1212. <Button type="link"><span>选择落地页</span></Button>
  1213. </Tooltip>}
  1214. </div>
  1215. </Col>
  1216. </Row>
  1217. </Col>}
  1218. </Row>
  1219. {/* =============广告底部按钮=========== */}
  1220. <Space className={style.bts}>
  1221. <Button type='primary' onClick={severBd}>存为预设</Button>
  1222. <Button type='primary' onClick={preview}><SearchOutlined /> 批量预览广告</Button>
  1223. <Button onClick={delBdPlan}>清空配置/预设</Button>
  1224. </Space>
  1225. </div>
  1226. </Card>
  1227. <Card
  1228. className={style.createAd}
  1229. hoverable
  1230. extra={tableData?.length > 0 ? <Space>
  1231. <span>推广计划总数:{tableData?.length}</span>
  1232. <span>广告总数:{tableData?.length}</span>
  1233. {/* {tableSelect?.length > 0 && <span> 已选:<span style={{ color: '#1890FF' }}>{tableSelect?.length}</span> 条</span>} */}
  1234. {
  1235. <Button type='primary' onClick={() => {
  1236. // if (tableSelect.length === 0) {
  1237. // message.error('请选择要提交的计划!')
  1238. // return
  1239. // };
  1240. setSubVisible(true)
  1241. }}>批量提交审核</Button>
  1242. }
  1243. </Space> : false
  1244. }
  1245. >
  1246. {tableData?.length > 0 ? <div className={style.cardBody}>
  1247. <div className={style.content} style={{ marginTop: 20 }}>
  1248. <Tables
  1249. columns={columns()}
  1250. dataSource={tableData}
  1251. total={0}
  1252. size="small"
  1253. bordered
  1254. scroll={{ x: 2000 }}
  1255. myKey={'myId'}
  1256. // rowSelection={{
  1257. // selectedRowKeys: tableSelect?.map((item: any) => item?.myId.toString()),
  1258. // onChange: (selectedRowKeys: React.Key[], selectedRows: any) => {
  1259. // setTableSelect(selectedRows)
  1260. // }
  1261. // }}
  1262. />
  1263. </div>
  1264. </div> : <div style={{ minHeight: 400, display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
  1265. <Empty description="请先完成模块配置后,再预览广告计划" />
  1266. </div>}
  1267. </Card>
  1268. {/* 选择商品 */}
  1269. {goodsVisible && <GoodsModal visible={goodsVisible} data={accountCreateLogs} onClose={() => setGoodsVisible(false)} onChange={(e) => { setAccountCreateLogs(e); setGoodsVisible(false); clearData() }} />}
  1270. {/* 选择数据源 */}
  1271. {sourceVisible && <DataSourceModal visible={sourceVisible} promotedObjectType={queryForm.promotedObjectType} data={accountCreateLogs} onClose={() => setSourceVisible(false)} onChange={(e) => { setAccountCreateLogs(e); setSourceVisible(false); clearData() }} />}
  1272. {/* 选择转化ID */}
  1273. {idVisible && <IdModal visible={idVisible} data={accountCreateLogs} onClose={() => setIdVisible(false)} onChange={(e) => { setAccountCreateLogs(e); setSourceVisible(false); clearData() }} />}
  1274. {/* 选择ADQ落地页 */}
  1275. {pageVisible && <PageModal cloudParams={cloudParams} visible={pageVisible} data={queryForm?.adqPageList?.[targetKey] || accountCreateLogs} onClose={() => setPageVisible(false)} onChange={(e) => { setAdqPage(e); setPageVisible(false); clearData() }} />}
  1276. {/* 选择素材 */}
  1277. {selectImgVisible && <SelectCloud visible={selectImgVisible} onClose={() => setSelectImgVisible(false)} onChange={setPage} isBack={false} />}
  1278. {/* 查看落地页 */}
  1279. {lookVisible && <LookLanding visible={lookVisible} onClose={() => setLookVisible(false)} id={queryForm?.taskMediaMaps && queryForm?.taskMediaMaps[targetKey].sysPageId} />}
  1280. {/* 设置名称 */}
  1281. {subVisible && <SubmitModal data={getSysAdgroups?.data} visible={subVisible} onClose={() => setSubVisible(false)} onChange={submit} ajax={createAdBatch} />}
  1282. </Space>
  1283. }
  1284. export default CreateAd