import { Button, Card, Drawer, Empty, Modal, Popconfirm, Space, Spin, Table, Tabs, Typography, message } from "antd" import React, { useEffect, useState } from "react" import '../index.less' import style from './index.less' import Dynamic from "./Dynamic"; import Material from "./Material"; import MaterialText from "./MaterialText"; import PageList from "./PageList"; import { DispatchAddelivery } from "."; import { CheckOutlined, SearchOutlined } from "@ant-design/icons"; import WechatAccount from "../../components/WechatAccount"; import { cartesianProduct, distributeArray, processData, splitArrayIntoRandomChunks } from "@/utils/utils"; import { columnsAddDynamic } from "./tableConfig"; import { useAjax } from "@/Hook/useAjax"; import { createDynamicTaskApi } from "@/services/adqV3"; import TacticsS from "./TacticsS"; import VideoChannel from "../../components/VideoChannel"; import { getCreativeDetailsApi } from "@/services/adqV3/global"; const { Text, Title } = Typography; /** * 新增创意 * @returns */ const AddDynamic: React.FC = ({ visible, onChange, onClose, adData: selectData, tactics, putInType }) => { /****************************************/ const [addelivery, setAddelivery] = useState({ adgroups: {}, targeting: [], dynamic: {}, dynamicMaterialDTos: {}, dynamicCreativesTextDTOS: {}, mediaType: 0 }) const { adgroups, dynamic } = addelivery const { marketingAssetOuterSpec, marketingCarrierType, marketingGoal, marketingSubGoal, siteSet, automaticSiteEnabled, sceneSpec } = addelivery.adgroups const { deliveryMode, creativeTemplateId, dynamicCreativeSwitch } = addelivery.dynamic const [wechatVisible, setWechatVisible] = useState(false) // 选择微信公众号弹窗控制 const [channelsProfileVisible, setChannelsProfileVisible] = useState(false) // 选择微信公众号弹窗控制 const [materialData, setMaterialData] = useState({}) // 素材数据 const [textData, setTextData] = useState({}) const [accountCreateLogs, setAccountCreateLogs] = useState([]) // 账户 const [tableData, setTableData] = useState({}) const [activeKey, setActiveKey] = useState() const [dynamicCount, setDynamicCount] = useState(0) const [adData, setAdData] = useState(selectData) const [adLength, setAdLength] = useState(0) const [adDataGroup, setAdDataGroup] = useState<{ [x: number]: any[] }>({}) const [creativeTemplateAppellation, setCreativeTemplateAppellation] = useState() const [creativeTemplateStyle, setCreativeTemplateStyle] = useState() const getCreativeDetails = useAjax((params) => getCreativeDetailsApi(params)) const createDynamicTask = useAjax((params) => createDynamicTaskApi(params)) /****************************************/ // 获取广告总数 useEffect(() => { if (adData && adData?.length > 0) { setAdLength(adData.length) } }, [adData]) useEffect(() => { if (creativeTemplateId) { let params: any = { marketingGoal, marketingTargetType: marketingAssetOuterSpec.marketingTargetType, marketingCarrierType, deliveryMode, creativeTemplateId, wechatSceneSpecPosition: sceneSpec?.wechatPosition, dynamicCreativeType: (deliveryMode === 'DELIVERY_MODE_COMPONENT' && !dynamicCreativeSwitch) ? 'DYNAMIC_CREATIVE_TYPE_PROGRAM' : 'DYNAMIC_CREATIVE_TYPE_COMMON' } if (automaticSiteEnabled) { params.automaticSiteEnabled = automaticSiteEnabled } else { params.siteSet = siteSet } params.taskType = putInType if (putInType === 'GAME') { params.marketingSubGoal = marketingSubGoal } getCreativeDetails.run(params).then(res => { if (res?.adcreativeTemplateStructAdpermits?.length > 0) { let adcreativeTemplateStructAdpermits = res?.adcreativeTemplateStructAdpermits[0] setCreativeTemplateAppellation(adcreativeTemplateStructAdpermits.creativeTemplateAppellation) setCreativeTemplateStyle(adcreativeTemplateStructAdpermits.creativeTemplateStyle) let creativeComponents = adcreativeTemplateStructAdpermits?.creativeComponents || [] let result = processData(creativeComponents); let newMaterialData: any = {}; let newTextData: any = {}; Object.keys(result).forEach(key => { let data = result[key] if ((key === 'image_list' || key === 'short_video' || key === 'video' || key === 'image' || key === 'element_story') && data.required) { newMaterialData[key] = data } else if (key === 'title' || (data.required && key === 'description')) { newTextData[key] = data } }) setMaterialData(newMaterialData) setTextData(newTextData) } }) } }, [creativeTemplateId, deliveryMode, dynamicCreativeSwitch, marketingGoal, marketingAssetOuterSpec, marketingCarrierType, siteSet, sceneSpec?.wechatPosition, automaticSiteEnabled, putInType]) useEffect(() => { if (adData && adData.length) { let adDataGroup: { [x: number]: any[] } = {} adData.forEach(item => { let accountId = item.accountId if (adDataGroup?.[accountId]?.length) { adDataGroup[accountId].push(item) } else { adDataGroup[accountId] = [item] } }) setAdDataGroup(adDataGroup) } }, [adData]) useEffect(() => { if (tactics) { const { adData, addelivery, accountCreateLogs, materialData, textData } = JSON.parse(tactics.strategyValue) setAccountCreateLogs(accountCreateLogs) setAddelivery(addelivery) setAdData(adData) setMaterialData(materialData) setTextData(textData) } else if (selectData?.length > 0) { const { siteSet, marketingCarrierType, marketingGoal, marketingTargetType, sceneSpec, automaticSiteEnabled, marketingSubGoal } = selectData[0] setAddelivery({ ...addelivery, adgroups: { marketingGoal, marketingSubGoal, marketingCarrierType, siteSet, automaticSiteEnabled, sceneSpec, marketingAssetOuterSpec: { marketingTargetType } } }) let AccountSet = new Set(selectData.map(item => item.accountId)) setAccountCreateLogs([...AccountSet].map(accountId => ({ accountId }))) } }, [selectData, tactics]) const clearData = () => { setTableData([]) } // 预览 const preview = () => { if (accountCreateLogs?.length === 0) { message.error('请先选择媒体账户') return } const { adgroups, dynamic, dynamicMaterialDTos, dynamicCreativesTextDTOS, mediaType } = addelivery if (!(adgroups && Object.keys(adgroups).length)) { message.error('请先配置广告信息') return } if (!(dynamic && Object.keys(dynamic).length)) { message.error('请先配置创意') return } if ((materialData && Object.keys(materialData).length) && !(dynamicMaterialDTos && Object.keys(dynamicMaterialDTos).length)) { message.error('请先配置创意素材') return } if ((textData && Object.keys(textData).length) && !(dynamicCreativesTextDTOS && Object.keys(dynamicCreativesTextDTOS).length)) { message.error('请先配置创意文案') return } if (!accountCreateLogs?.some(item => item?.pageList?.length) && !['PAGE_TYPE_WECHAT_MINI_GAME'].includes(dynamic?.creativeComponents?.mainJumpInfo?.[0]?.value?.pageType)) { message.error('请先选择落地页') return } if ((['MARKETING_TARGET_TYPE_WECHAT_OFFICIAL_ACCOUNT'].includes(adgroups?.marketingAssetOuterSpec?.marketingTargetType) || adgroups?.marketingCarrierType === 'MARKETING_CARRIER_TYPE_WECHAT_OFFICIAL_ACCOUNT') && !accountCreateLogs?.some(item => item?.wechatChannelList?.length)) { message.error('请先选择公众号') return } if (dynamic?.creativeComponents?.brand?.[0]?.value?.jumpInfo?.pageType === 'PAGE_TYPE_WECHAT_CHANNELS_PROFILE' && !accountCreateLogs?.some(item => item?.videoChannelList?.length)) { message.error('请先选择视频号') return } let newTableData: any = {}, newDynamicCount = 0 const textType = dynamicCreativesTextDTOS.type const textDto = dynamicCreativesTextDTOS?.dynamicCreativesTextDetailDTOList || [] const textDtoLenth = textDto.length const dynamicGroupLength = dynamicMaterialDTos?.dynamicGroup?.length || 0 let newDynamicGroup: any = [] if (![910].includes(dynamic.creativeTemplateId)) { newDynamicGroup = dynamicMaterialDTos?.dynamicGroup || [] if (newDynamicGroup.length > 0 && [0, 1, 2, 3, 4].includes(textType)) { if (textType === 0) { newDynamicGroup = newDynamicGroup.map((item: any) => ({ ...item, textDto: textDto?.[0] })) } else if (textType === 1) { newDynamicGroup = newDynamicGroup.map((item: any, index: number) => ({ ...item, textDto: textDto?.[index] })) } else if (textType === 2) { newDynamicGroup = newDynamicGroup.map((item: any, index: number) => ({ ...item, textDto: textDto?.[index % textDtoLenth] })) } else if ((textType === 3 && mediaType === 0) || (textType === 4 && mediaType === 1) || (textType === 4 && mediaType === 3)) { newDynamicGroup = cartesianProduct(newDynamicGroup, textDto || [{}]).map((item) => { let [dynamicGroup, textDtoData] = item return { ...dynamicGroup as any, textDto: textDtoData } }) } } } // 创意组平均分配到广告逻辑 let averageAdDynamicList: any[] = [] if ((mediaType === 1 || mediaType === 2 || mediaType === 3) && newDynamicGroup.length) { let adLength = adData.length if (mediaType === 1) { if (textType === 4) { if (adLength > newDynamicGroup.length) { message.error(`创意组分配规则选择“平均分配到广告”时,创意组总数必须大于等于广告总数。当前创意组数量:${dynamicGroupLength},广告数量:${adLength}`) return } averageAdDynamicList = splitArrayIntoRandomChunks(newDynamicGroup, adLength) } else { if (adLength > dynamicGroupLength) { message.error(`创意组分配规则选择“平均分配到广告”时,创意组总数必须大于等于广告总数。当前创意组数量:${dynamicGroupLength},广告数量:${adLength}`) return } averageAdDynamicList = distributeArray(newDynamicGroup, adLength) } } else if (mediaType === 2) { if (adLength < dynamicGroupLength) { message.error(`创意组分配规则选择“顺序分配到广告”时,创意组总数必须小于等于广告总数。当前创意组数量:${dynamicGroupLength},广告数量:${adLength}`) return } } else if (mediaType === 3) { const dynamicDataLength = textType === 4 ? newDynamicGroup.length : dynamicGroupLength if (Object.keys(adDataGroup).some(key => { const adLength = adDataGroup[key as any].length if (adLength > dynamicDataLength) { message.error(`创意组分配规则选择“账号下平均分配到广告”时,创意组总数必须大于等于每个账号广告总数。当前创意组数量:${dynamicDataLength},当前账号(${key})下广告数量:${adLength}`) return true } return false })) { return } } } // 落地页平均分配判断数量 if ([910].includes(dynamic.creativeTemplateId) && dynamic?.landingPageType === 1) { if (accountCreateLogs.some(item => { let total = adDataGroup[item.accountId].length let pageLength = item.pageList.length if (total > pageLength) { message.error(`当前${item.accountId}下的广告总数(${total})大于落地页总数(${pageLength}),平均分配需要落地页总数大于广告总数`) return true } return false })) { return } } else if (textType === 5) { if (dynamicGroupLength * accountCreateLogs.length !== textDtoLenth) { message.error(`创意文案配置错误,内容数量和所有创意数量对不上,所有创意数量:${dynamicGroupLength * accountCreateLogs.length},文案数量:${textDtoLenth}`) return } } if (textType === 1) { if (dynamicGroupLength !== textDtoLenth) { message.error(`当前创意文案是“创意组一一对应”模式,创意组总数(${dynamicGroupLength})要等于创意文案总数(${textDtoLenth})`) return } if (!dynamicCreativesTextDTOS.dynamicCreativesTextDetailDTOList.every((item: {}) => item && Object.keys(item).length)) { message.error('创意文案配置错误,内容空') return } } let accountIndex1 = 0, accountIndex2 = 0 if (dynamic?.landingPageType === 1 && [910].includes(dynamic.creativeTemplateId)) { accountCreateLogs.forEach(item => { let adData = adDataGroup[item.accountId] let averageAdPageList: any[] = distributeArray(item.pageList, adData.length) let newData: any[] = [] adData.forEach((ad, index) => { let data = [{ id: ad.adgroupId + '_' + index, adgroupsDto: ad, dynamicDto: dynamic, // 创意信息 }] newData = cartesianProduct(data, averageAdPageList[index]).map((item, index) => { let [d1, pageList, num] = item return { ...d1, id: d1.id + '_' + index, pageListDto: [pageList], dynamicDto: { ...d1.dynamicDto, dynamicCreativeName: d1.dynamicDto.dynamicCreativeName + num }, rowSpan: index === 0 ? averageAdPageList[index].length : 0, isRowSpan: true } }) newTableData[ad.adgroupId] = newData }) newDynamicCount += item.pageList.length }) } else { const handleDynamic = (adData: any[], averageAdDynamicList: any[]) => { adData.forEach((ad, index) => { let item = accountCreateLogs.find(a => a.accountId === ad.accountId) as PULLIN.AccountCreateLogsProps let averageAdDynamic = averageAdDynamicList?.[index] let data = [{ id: ad.adgroupId + '_' + index, pageListDto: item.pageList, // 落地页 adgroupsDto: ad, dynamicDto: dynamic, // 创意信息 averageAdDynamic, rowSpan: ((mediaType === 1 || mediaType === 3) && textType !== 4) ? averageAdDynamic.length : ([910].includes(dynamic.creativeTemplateId) ? item.pageList?.length : (textType === 3 ? textDtoLenth * dynamicGroupLength : dynamicGroupLength)) || 1 }] let newData: any[] = [] if ([910].includes(dynamic.creativeTemplateId)) { newData = cartesianProduct(data, item.pageList).map((item, index) => { let [d1, pageList, num] = item return { ...d1, id: d1.id + '_' + index, pageListDto: [pageList], dynamicDto: { ...d1.dynamicDto, dynamicCreativeName: d1.dynamicDto.dynamicCreativeName + num } } }) } else { if (mediaType === 1 || mediaType === 3) { data.forEach(item => { const { averageAdDynamic, ...ad } = item if (textType === 3) { let rowSpan = textDtoLenth * averageAdDynamic.length cartesianProduct(textDto, averageAdDynamic).forEach((taad: any, index) => { let [textValue, aad] = taad newData.push({ ...ad, id: ad.id + '_' + index, dynamicGroup: aad, textDto: textValue, rowSpan }) }) } else if (textType === 4) { averageAdDynamic.forEach((aad: any, index: number) => { newData.push({ ...ad, id: ad.id + '_' + index, dynamicGroup: aad, textDto: aad?.textDto, rowSpan: index === 0 ? averageAdDynamic.length : 0, isRowSpan: true }) }) } else { averageAdDynamic.forEach((aad: any, index: number) => { newData.push({ ...ad, id: ad.id + '_' + index, dynamicGroup: aad, textDto: textType === 2 ? textDto?.[index % textDtoLenth] : textType === 5 ? textDto?.[accountIndex2] : aad?.textDto }) accountIndex2 += 1 }) } }) } else if (mediaType === 2) { data.forEach((item) => { const { averageAdDynamic, ...ad } = item if (textType === 3) { cartesianProduct(textDto, [newDynamicGroup[accountIndex1 % newDynamicGroup.length]]).forEach((taad: any) => { let [textValue, aad, index] = taad newData.push({ ...ad, id: ad.id + '_' + index, dynamicGroup: aad, textDto: textValue, rowSpan: textDto.length }) }) } else { let { textDto: nowTextDto, ...dynamicGroup } = newDynamicGroup[accountIndex1 % newDynamicGroup.length] newData.push({ ...ad, dynamicGroup, textDto: textType === 2 ? textDto?.[0] : nowTextDto, rowSpan: 1 }) } accountIndex1 += 1 }) } else { newData = cartesianProduct(data, newDynamicGroup.length > 0 ? newDynamicGroup : [{}]).map((item, index) => { let [d1, group] = item return { ...d1, id: d1.id + '_' + index, dynamicGroup: group, textDto: (group as any)?.textDto } }) } } newDynamicCount += newData.length newTableData[ad.adgroupId] = newData }) } if (mediaType === 3) { Object.keys(adDataGroup).forEach(key => { const newAdData = adDataGroup[key as any] const adLength = newAdData.length if (textType === 4) { averageAdDynamicList = splitArrayIntoRandomChunks(newDynamicGroup, adLength) } else { averageAdDynamicList = distributeArray(newDynamicGroup, adLength) } handleDynamic(newAdData, averageAdDynamicList) }) } else { handleDynamic(adData, averageAdDynamicList) } } setDynamicCount(newDynamicCount) setActiveKey(adData?.[0].adgroupId?.toString()) console.log('newTableData-->', newTableData) setTableData(newTableData) } // 提交 const onSubmit = () => { const { dynamic, dynamicMaterialDTos, dynamicCreativesTextDTOS, mediaType } = addelivery let dynamicMaterialDTOS = [] if (dynamic.deliveryMode === 'DELIVERY_MODE_CUSTOMIZE' || dynamic?.dynamicCreativeSwitch) { if ((materialData && Object.keys(materialData).length && dynamicMaterialDTos && Object.keys(dynamicMaterialDTos).length)) { let mType = Object.keys(materialData)[0]; dynamicMaterialDTOS = dynamicMaterialDTos.dynamicGroup?.map((item: any) => { if (mType === 'image') { return [{ type: mType, valueJson: JSON.stringify({ value: { imageUrl: item?.image_id?.url, imageId: item?.image_id?.id, materialType: item?.image_id?.materialType, accountId: item?.image_id?.accountId } }) }] } else if (mType === 'image_list' || mType === 'element_story') { let key = 'image_list' if (mType === 'element_story') { key = 'element_story' } let list = item?.[key]?.map((l: any) => { return { imageUrl: l?.url, imageId: l?.id, materialType: l?.materialType, accountId: l?.accountId } }) return [{ type: mType, valueJson: JSON.stringify({ value: { list } }) }] } else if (['short_video', 'video'].includes(mType)) { let value: any = { materialType: item?.video_id?.materialType || item?.short_video1?.materialType || 0, videoUrl: item?.video_id?.url || item?.short_video1?.url, videoId: item?.video_id?.id || item?.short_video1?.id, keyFrameImageUrl: item?.video_id?.keyFrameImageUrl || item?.short_video1?.keyFrameImageUrl, accountId: item?.video_id?.accountId || item?.short_video1?.accountId, } if (item?.cover_id?.url) { value.imageUrl = item?.cover_id?.url value.imageId = item?.cover_id?.id value.materialCoverType = item?.cover_id?.materialType value.accountId = item?.cover_id?.accountId } return [{ type: mType, valueJson: JSON.stringify({ value }) }] } return [{ type: mType, valueJson: '' }] }) } } else { if (dynamicMaterialDTos && Object.keys(dynamicMaterialDTos).length) { dynamicMaterialDTOS = dynamicMaterialDTos.dynamicGroup?.map((item: { list: any[] }) => { return item.list.map(l => { if (Array.isArray(l)) { return { type: 'image_list', valueJson: JSON.stringify({ value: { list: l?.map((i: any) => { return { imageUrl: i?.url, imageId: i?.id, materialType: i?.materialType, accountId: i?.accountId } }) } }) } } else if (l?.url?.includes('mp4') || l?.keyFrameImageUrl) { return { type: 'video', valueJson: JSON.stringify({ value: { materialType: l?.materialType, videoUrl: l?.url, videoId: l?.id, keyFrameImageUrl: l?.keyFrameImageUrl, accountId: l?.accountId } }) } } else { return { type: 'image', valueJson: JSON.stringify({ value: { imageUrl: l?.url, imageId: l?.id, materialType: l?.materialType, accountId: l?.accountId } }) } } }) }) } } let accountIdParamDTOMap: any = {} accountCreateLogs.forEach(item => { let { pageList, userActionSetsList, accountId, wechatChannelList, videoChannelList } = item let userActionSetsListDto = userActionSetsList?.map((item: any) => ({ id: item?.userActionSetId, type: item?.type })) // dataSourceId let map: any = { userActionSetsList: userActionSetsListDto, pageList: pageList?.map((item: { pageId: any }) => item.pageId) } if (wechatChannelList && (['MARKETING_TARGET_TYPE_WECHAT_OFFICIAL_ACCOUNT'].includes(adgroups?.marketingAssetOuterSpec?.marketingTargetType) || adgroups?.marketingCarrierType === 'MARKETING_CARRIER_TYPE_WECHAT_OFFICIAL_ACCOUNT' || dynamic?.creativeComponents?.brand?.[0]?.value?.jumpInfo?.pageType === 'PAGE_TYPE_WECHAT_OFFICIAL_ACCOUNT_DETAIL')) { map.wechatChannelId = wechatChannelList?.[0]?.wechatOfficialAccountId } if (videoChannelList && dynamic?.creativeComponents?.brand?.[0]?.value?.jumpInfo?.pageType === 'PAGE_TYPE_WECHAT_CHANNELS_PROFILE') { map.videoChannelId = videoChannelList?.[0]?.wechatChannelsAccountId } accountIdParamDTOMap[accountId] = map }) dynamic.dynamicCreativeType = 'DYNAMIC_CREATIVE_TYPE_COMMON' if (dynamic.deliveryMode === 'DELIVERY_MODE_COMPONENT') { dynamic.dynamicCreativeType = dynamic?.dynamicCreativeSwitch ? 'DYNAMIC_CREATIVE_TYPE_COMMON' : 'DYNAMIC_CREATIVE_TYPE_PROGRAM' } let dynamicCreativesDTO = { ...dynamic, mediaType } if (dynamic.deliveryMode === 'DELIVERY_MODE_COMPONENT' && !dynamic?.dynamicCreativeSwitch) { dynamicCreativesDTO.creativeTemplateId = 711 } let params = { accountAdgroupMaps: adData.map(item => `${item.accountId},${item.adgroupId}`), dynamicCreativesDTO, dynamicCreativesTextDTOS, dynamicMaterialDTOS, accountIdParamDTOMap } createDynamicTask.run(params).then(res => { if (res) { Modal.success({ content: '创建任务提交成功', bodyStyle: { fontWeight: 700 }, okText: '返回上一页', closable: true, onOk: () => { onChange?.() }, onCancel: () => { } }) } }) } return 添加创意} open={visible} width={1500} onClose={onClose} bodyStyle={{ backgroundColor: '#f1f4fc', padding: '0 10px 10px' }} > 配置区} className={style.createAd} > {(adgroups?.marketingAssetOuterSpec?.marketingTargetType === 'MARKETING_TARGET_TYPE_WECHAT_OFFICIAL_ACCOUNT' || adgroups?.marketingCarrierType === 'MARKETING_CARRIER_TYPE_WECHAT_OFFICIAL_ACCOUNT' || addelivery?.dynamic?.creativeComponents?.brand?.[0]?.value?.jumpInfo?.pageType === 'PAGE_TYPE_WECHAT_OFFICIAL_ACCOUNT_DETAIL') && } {dynamic?.creativeComponents?.brand?.[0]?.value?.jumpInfo?.pageType === 'PAGE_TYPE_WECHAT_CHANNELS_PROFILE' && }
广告信息
已选广告 {Object.keys(adDataGroup).map((key: any) => { return
{key} {adDataGroup[key]?.map((item: any) => { return
{item.adgroupName}
})}
})}
{/* 创意 */} {/* 创意素材 */}
{/* 创意文案 */} {/* 落地页 */}
{ const { accountId, adgroupName, adgroupId, siteSet, marketingCarrierType, marketingGoal, marketingTargetType, sceneSpec, automaticSiteEnabled, marketingSubGoal } = item return { siteSet, marketingCarrierType, marketingGoal, marketingSubGoal, marketingTargetType, sceneSpec, automaticSiteEnabled, accountId, adgroupId, adgroupName } }), addelivery, accountCreateLogs, materialData, textData }} putInType={putInType} /> {/* 选择公众号 */} {wechatVisible && setWechatVisible(false)} onChange={(e) => { setAccountCreateLogs(e); setWechatVisible(false); clearData() }} />} {/* 选择视频号 */} {channelsProfileVisible && setChannelsProfileVisible(false)} onChange={(e) => { setAccountCreateLogs(e); setChannelsProfileVisible(false); clearData() }} />}
{activeKey && tableData && Object.keys(tableData)?.length > 0 ?
{ setActiveKey(e) }} type="card" activeKey={activeKey} tabBarExtraContent={ 创意总数:{dynamicCount} } > {adData.map(item => )} {addelivery?.dynamicCreativesTextDTOS?.type === 4 && 因为选择的是“创意组和文案叉乘打乱后分配”模式,会随机打乱,当前预览广告下创意内容会与实际建出来的创意有偏差,请以建出来的为准}
:
} } export default React.memo(AddDynamic)