wjx 6 mesi fa
parent
commit
e84d5ba90c

+ 9 - 7
src/pages/launchSystemV3/material/cloudNew/const.ts

@@ -27,11 +27,13 @@ export const updateTreeData = (list: DataNode[], key: React.Key, children: DataN
 
 /** 选择素材 展示字段 */
 export const showFieldList = [
-    { label: '创建时间', value: 'material.create_time' },
-    { label: '消耗', value: 'material_data_day.cost' },
-    { label: '点击率', value: 'material_data_day.ctr' },
-    { label: '目标转化率', value: 'material_data_day.conversions_rate' },
-    { label: '创意关联数', value: 'material_data_day.adgroup_count' },
-    { label: '创意关联数', value: 'material_data_day.dynamic_creative_count' },
-    { label: '备注', value: 'description' }
+    { label: '创建时间', value: 'material.create_time', field: 'create_time' },
+    { label: '下单次数', value: 'material_data_day.order_pv', field: 'order_pv' },
+    { label: '下单成本', value: 'material_data_day.order_cost', field: 'order_cost' },
+    { label: '消耗', value: 'material_data_day.cost', field: 'cost' },
+    { label: '点击率', value: 'material_data_day.ctr', field: 'ctr' },
+    { label: '目标转化率', value: 'material_data_day.conversions_rate', field: 'conversions_rate' },
+    { label: '创意关联数', value: 'material_data_day.adgroup_count', field: 'adgroup_count' },
+    { label: '创意关联数', value: 'material_data_day.dynamic_creative_count', field: 'dynamic_creative_count' },
+    { label: '备注', value: 'description', field: 'description' }
 ]

+ 11 - 5
src/pages/launchSystemV3/material/cloudNew/selectCloudNew.tsx

@@ -40,7 +40,7 @@ const SelectCloudNew: React.FC<CLOUDNEW.SelectCloudNewProps> = ({ visible, defau
     const [searchParams, setSearchParams] = useState<Partial<CLOUDNEW.GetMaterialDataListProps>>({})
     const [uploadVisible, setUploadVisible] = useState<boolean>(false)
     const [showField, setShowField] = useLocalStorageState<string[]>('show-field', ['material.create_time', 'material_data_day.cost', 'material_data_day.ctr', 'material_data_day.conversions_rate', 'material_data_day.dynamic_creative_count']);
-    const [sortData, setSortData] = useLocalStorageState<{ sortField: string, sortType: boolean }>('sort-data', { sortField: 'material.create_time', sortType: false });
+    const [sortData, setSortData] = useLocalStorageState<{ sortField: string | undefined, sortType: boolean }>('sort-data', { sortField: undefined, sortType: false });
 
     const getMaterialDataList = useAjax((params) => getMaterialDataListApi(params))
     /************************************/
@@ -52,8 +52,12 @@ const SelectCloudNew: React.FC<CLOUDNEW.SelectCloudNewProps> = ({ visible, defau
     }, [sliderImgContent])
 
     useEffect(() => {
-        getMaterialDataList.run({ ...sortData, ...searchParams, ...defaultParams, ...queryParams })
-    }, [queryParams, defaultParams, searchParams, sortData])
+        let params = { ...searchParams, ...defaultParams, ...queryParams }
+        if (sortData?.sortField) {
+            params = { ...params, ...sortData }
+        }
+        getMaterialDataList.run(params)
+    }, [queryParams, defaultParams, searchParams, sortData, showField])
 
     // 根据内容宽度计算列数
     useEffect(() => {
@@ -189,7 +193,7 @@ const SelectCloudNew: React.FC<CLOUDNEW.SelectCloudNewProps> = ({ visible, defau
                                 >全选</Checkbox>
                                 <span>已选 <span style={{ color: '#1890FF' }}>{checkedFolderList?.length || 0}</span>/{num} 个素材</span>
                                 {checkedFolderList.length > 0 && <a style={{ color: 'red' }} onClick={() => setCheckedFolderList([])}>清除所有</a>}
-                                <Text>「排序-{showFieldList.find(item => item.value === sortData.sortField)?.label}-{sortData.sortType ? '正序' : '倒序'}」</Text>
+                                {sortData?.sortField && <Text>「排序-{showFieldList.find(item => item.value === sortData.sortField)?.label}-{sortData.sortType ? '正序' : '倒序'}」</Text>}
                             </div>
                             <div className={style.left_bts}>
                                 <Popover
@@ -218,6 +222,7 @@ const SelectCloudNew: React.FC<CLOUDNEW.SelectCloudNewProps> = ({ visible, defau
                                                             message.warn('最少选择1个指标')
                                                             return
                                                         }
+                                                        setSortData({ ...sortData, sortField: undefined })
                                                         setShowField(value as any)
                                                     }}
                                                 />
@@ -231,8 +236,9 @@ const SelectCloudNew: React.FC<CLOUDNEW.SelectCloudNewProps> = ({ visible, defau
                                                         filterOption={(input, option) =>
                                                             (option?.label as any)?.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                                         }
-                                                        options={showFieldList.filter(item => item.value !== 'description')}
+                                                        options={showFieldList.filter(item => showField.includes(item.value) && item.value !== 'description')}
                                                         value={sortData.sortField}
+                                                        allowClear
                                                         onChange={(value) => {
                                                             setSortData({ ...sortData, sortField: value as any })
                                                         }}

+ 9 - 3
src/pages/launchSystemV3/material/cloudNew/selectSearch.tsx

@@ -33,6 +33,9 @@ const SelectSearch: React.FC<Props> = ({ onSearch }) => {
             } else if ('uploadTime' === key && value?.length === 2) {
                 params.uploadTimeMin = moment(value?.[0]).format('YYYY-MM-DD')
                 params.uploadTimeMax = moment(value?.[1]).format('YYYY-MM-DD')
+            } else if ('dataTime' === key && value?.length === 2) {
+                params.dataTimeMin = moment(value?.[0]).format('YYYY-MM-DD')
+                params.dataTimeMax = moment(value?.[1]).format('YYYY-MM-DD')
             } else {
                 params[key] = value
             }
@@ -85,6 +88,9 @@ const SelectSearch: React.FC<Props> = ({ onSearch }) => {
                         options={getUserAll?.data?.map((item: { nickname: any; userId: any }) => ({ label: item.nickname, value: item.userId }))}
                     />
                 </Form.Item></Col>
+                <Col><Form.Item name={'minCost'}>
+                    <InputNumber style={{ width: 80 }} placeholder="最小消耗" />
+                </Form.Item></Col>
                 <Col><Form.Item name={'accountIds'}>
                     <Input.TextArea rows={1} style={{ width: 190 }} allowClear placeholder="广告账号(多个逗号、换行等隔开)" />
                 </Form.Item></Col>
@@ -97,9 +103,6 @@ const SelectSearch: React.FC<Props> = ({ onSearch }) => {
                 <Col><Form.Item name={'tencentMaterialId'}>
                     <Input.TextArea rows={1} style={{ width: 190 }} allowClear placeholder="腾讯素材ID(多个逗号、换行等隔开)" />
                 </Form.Item></Col>
-                <Col><Form.Item name={'minCost'}>
-                    <InputNumber style={{ width: 80 }} placeholder="最小消耗" />
-                </Form.Item></Col>
                 <Col><Form.Item name={'useStatus'}>
                     <Select
                         placeholder="使用情况"
@@ -114,6 +117,9 @@ const SelectSearch: React.FC<Props> = ({ onSearch }) => {
                 <Col><Form.Item name={'uploadTime'}>
                     <DatePicker.RangePicker style={{ width: 260 }} placeholder={['上传时间开始', '上传时间结束']} />
                 </Form.Item></Col>
+                <Col><Form.Item name={'dataTime'}>
+                    <DatePicker.RangePicker style={{ width: 260 }} placeholder={['数据时间开始', '数据时间结束']} />
+                </Form.Item></Col>
                 <Col><Form.Item>
                     <Space>
                         <Button onClick={() => form.resetFields()}>重置</Button>

+ 60 - 2
src/pages/launchSystemV3/tencenTasset/wechatCanvasPage/index.tsx

@@ -1,7 +1,7 @@
-import { Button, Card, Input, Select, Table } from "antd"
+import { Button, Card, Input, message, Popconfirm, Select, Table } from "antd"
 import React, { useEffect, useState } from "react"
 import '../../tencentAdPutIn/index.less'
-import { getAdqLandingPageListApi, getWXDownPageAuthInfoListApi } from "@/services/adqV3/global";
+import { delPageApi, getAdqLandingPageListApi, getWXDownPageAuthInfoListApi } from "@/services/adqV3/global";
 import { useAjax } from "@/Hook/useAjax";
 import { useModel } from "umi";
 import { SearchOutlined } from "@ant-design/icons";
@@ -28,9 +28,11 @@ const WechatCanvasPage: React.FC = () => {
     const [queryParamsNew, setQueryParamsNew] = useState<AjaxProps>({ pageNum: 1, pageSize: 20 })
     const [visible, setVisible] = useState<boolean>(false)
     const [pageData, setPageData] = useState<any>()
+    const [selectedRows, setSelectedRows] = useState<any[]>([])
 
     const getAdqLandingPageList = useAjax((params) => getAdqLandingPageListApi(params))
     const getWXDownPageAuthInfoList = useAjax((params) => getWXDownPageAuthInfoListApi(params))
+    const delPage = useAjax((params) => delPageApi(params))
     /********************************/
 
     useEffect(() => {
@@ -60,6 +62,16 @@ const WechatCanvasPage: React.FC = () => {
         setPageData(data)
     }
 
+    const handleDel = () => {
+        delPage.run({ accountId: queryParamsNew.accountId, pageIds: selectedRows.map(item => item.pageId) }).then(res => {
+            if (res?.length === 0) {
+                message.success('删除成功,结果可能会延迟几分钟返回')
+                getAdqLandingPageList.refresh()
+                setSelectedRows([])
+            }
+        })
+    }
+
     return <Card
         className="cardResetCss"
         title={<div className="flexStart" style={{ gap: 8 }}>
@@ -104,6 +116,12 @@ const WechatCanvasPage: React.FC = () => {
             </>}
 
             <Button type="primary" icon={<SearchOutlined />} loading={getAdqLandingPageList.loading} onClick={() => getAdqLandingPageList.refresh()}>刷新</Button>
+            <Popconfirm
+                title="确定删除?"
+                onConfirm={() => handleDel?.()}
+            >
+                <Button danger loading={delPage.loading} disabled={selectedRows.length === 0 || !!queryParamsNew?.ownerUid}>删除</Button>
+            </Popconfirm>
         </div>}
     >
         <Table
@@ -124,6 +142,46 @@ const WechatCanvasPage: React.FC = () => {
                 const { current, pageSize } = pagination
                 setQueryParamsNew({ ...queryParamsNew, pageNum: current as number, pageSize: pageSize as number || 20 })
             }}
+            rowSelection={{
+                selectedRowKeys: selectedRows.map(item => item.pageId),
+                getCheckboxProps: (record: any) => {
+                    return {
+                        disabled: !!queryParamsNew?.ownerUid || record?.canvasType === 'COMMON_PAGE'
+                    }
+                },
+                onSelect: (record: { pageId: number }, selected: boolean) => {
+                    if (selected) {
+                        selectedRows.push({ ...record })
+                        setSelectedRows([...selectedRows])
+                    } else {
+                        let newSelectAccData = selectedRows.filter((item: { pageId: number }) => item.pageId !== record.pageId)
+                        setSelectedRows([...newSelectAccData])
+                    }
+                },
+                onSelectAll: (selected: boolean, selectedRowss: { pageId: number }[], changeRows: { pageId: number }[]) => {
+                    if (selected) {
+                        let newSelectAccData = [...selectedRows]
+                        changeRows.forEach((item: { pageId: number }) => {
+                            let index = newSelectAccData.findIndex((ite: { pageId: number }) => ite.pageId === item.pageId)
+                            if (index === -1) {
+                                let data: any = { ...item }
+                                newSelectAccData.push(data)
+                            }
+                        })
+                        setSelectedRows([...newSelectAccData])
+                    } else {
+                        let newSelectAccData = selectedRows.filter((item: { pageId: number }) => {
+                            let index = changeRows.findIndex((ite: { pageId: number }) => ite.pageId === item.pageId)
+                            if (index !== -1) {
+                                return false
+                            } else {
+                                return true
+                            }
+                        })
+                        setSelectedRows([...newSelectAccData])
+                    }
+                }
+            }}
         />
 
         {visible && <CopyPage

+ 1 - 1
src/pages/launchSystemV3/tencentAdPutIn/create/Material/index.tsx

@@ -90,7 +90,7 @@ const Material: React.FC<{ adData?: any[] }> = ({ adData }) => {
             <div className={style.detail_body}>
                 {(dynamicMaterialDTos && Object.keys(dynamicMaterialDTos).length > 0) ?
                     <>
-                        <Title level={5} style={{ fontSize: 12 }}>{mediaType === 0 ? '全账号复用' : mediaType === 1 ? '平均分配到广告' : mediaType === 2 ? '顺序分配到广告' : null}</Title>
+                        <Title level={5} style={{ fontSize: 12 }}>{mediaType === 0 ? '全账号复用' : mediaType === 1 ? '平均分配到广告' : mediaType === 2 ? '顺序分配到广告' : mediaType === 3 ? '账号下平均分配到广告' : null}</Title>
                         <div className={style.detail_body_m}>
                             {dynamicMaterialDTos.dynamicGroup.map((item: any, index: number) => {
                                 if (deliveryMode === 'DELIVERY_MODE_CUSTOMIZE') {

+ 2 - 2
src/pages/launchSystemV3/tencentAdPutIn/create/MaterialText/newText.tsx

@@ -12,7 +12,7 @@ import VideoNews from "@/pages/launchSystemNew/components/newsModal/videoNews"
 interface Props {
     textData: any,
     dynamicMaterialDTos: any,
-    mediaType: 0 | 1 | 2,
+    mediaType: 0 | 1 | 2 | 3,
     deliveryMode?: string,
     value?: any,
     visible?: boolean
@@ -184,7 +184,7 @@ const NewText: React.FC<Props> = ({ visible, onClose, onChange, value, textData,
                         }
                         form.setFieldsValue({ textDto: oldtextDto })
                     }}>
-                        {TextTypeList.filter(item => mediaType !== 1 ? item.value !== 4 : true).map(item => <Radio value={item.value} key={item.value}>{item.label}</Radio>)}
+                        {TextTypeList.filter(item => (mediaType !== 1 && mediaType !== 3) ? item.value !== 4 : true).map(item => <Radio value={item.value} key={item.value}>{item.label}</Radio>)}
                     </Radio.Group>
                 </Form.Item>
             </Card>

+ 131 - 102
src/pages/launchSystemV3/tencentAdPutIn/create/addDynamic.tsx

@@ -174,11 +174,10 @@ const AddDynamic: React.FC<PULLIN.NewAddDynamic> = ({ visible, onChange, onClose
 
         let newTableData: any = {}, newDynamicCount = 0
 
-        let textType = dynamicCreativesTextDTOS.type
-        let textDto = dynamicCreativesTextDTOS?.dynamicCreativesTextDetailDTOList || []
-        let textDtoLenth = textDto.length
-        let dynamicGroupLength = dynamicMaterialDTos?.dynamicGroup?.length || 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 || []
@@ -189,7 +188,7 @@ const AddDynamic: React.FC<PULLIN.NewAddDynamic> = ({ visible, onChange, onClose
                     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)) {
+                } 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 {
@@ -203,7 +202,7 @@ const AddDynamic: React.FC<PULLIN.NewAddDynamic> = ({ visible, onChange, onClose
 
         // 创意组平均分配到广告逻辑
         let averageAdDynamicList: any[] = []
-        if ((mediaType === 1 || mediaType === 2) && newDynamicGroup.length) {
+        if ((mediaType === 1 || mediaType === 2 || mediaType === 3) && newDynamicGroup.length) {
             let adLength = adData.length
             if (mediaType === 1) {
                 if (textType === 4) {
@@ -224,6 +223,18 @@ const AddDynamic: React.FC<PULLIN.NewAddDynamic> = ({ visible, onChange, onClose
                     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
+                }
             }
         }
         // 落地页平均分配判断数量
@@ -283,110 +294,128 @@ const AddDynamic: React.FC<PULLIN.NewAddDynamic> = ({ visible, onChange, onClose
                 newDynamicCount += item.pageList.length
             })
         } else {
-            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 && 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
+            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) {
-                        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 (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 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: aad?.textDto
+                                } else {
+                                    averageAdDynamic.forEach((aad: any, index: number) => {
+                                        newData.push({
+                                            ...ad,
+                                            id: ad.id + '_' + index,
+                                            dynamicGroup: aad,
+                                            textDto: aad?.textDto
+                                        })
                                     })
-                                })
-                            }
-                        })
-                    } 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
+                                }
+                            })
+                        } 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, ...dynamicGroup } = newDynamicGroup[accountIndex1 % newDynamicGroup.length]
                                     newData.push({
                                         ...ad,
-                                        id: ad.id + '_' + index,
-                                        dynamicGroup: aad,
-                                        textDto: textValue,
-                                        rowSpan: textDto.length
+                                        dynamicGroup,
+                                        textDto,
+                                        rowSpan: 1
                                     })
-                                })
-                            } else {
-                                let { textDto, ...dynamicGroup } = newDynamicGroup[accountIndex1 % newDynamicGroup.length]
-                                newData.push({
-                                    ...ad,
-                                    dynamicGroup,
-                                    textDto,
-                                    rowSpan: 1
-                                })
-                            }
-                            accountIndex1 += 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 {
-                        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
-                            }
-                        })
+                        averageAdDynamicList = distributeArray(newDynamicGroup, adLength)
                     }
-                }
-                newDynamicCount += newData.length
-                newTableData[ad.adgroupId] = newData
-            })
+                    handleDynamic(newAdData, averageAdDynamicList)
+                })
+            } else {
+                handleDynamic(adData, averageAdDynamicList)
+            }
+            
+            
         }
 
         setDynamicCount(newDynamicCount)

+ 45 - 13
src/pages/launchSystemV3/tencentAdPutIn/create/index.tsx

@@ -397,10 +397,10 @@ const Create: React.FC = () => {
 
         let newTableData: any = {}
         let newAdCount = 0, newdynamicCount = 0
-        let textType = dynamicCreativesTextDTOS.type
-        let textDto = dynamicCreativesTextDTOS?.dynamicCreativesTextDetailDTOList || []
-        let textDtoLenth = textDto.length
-        let dynamicGroupLength = dynamicMaterialDTos?.dynamicGroup?.length || 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 || []
@@ -411,7 +411,7 @@ const Create: React.FC = () => {
                     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)) {
+                } 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 {
@@ -424,7 +424,7 @@ const Create: React.FC = () => {
         }
         // 创意组平均分配到广告逻辑
         let averageAdDynamicList: any[] = []
-        if ((mediaType === 1 || mediaType === 2) && newDynamicGroup.length) {
+        if ((mediaType === 1 || mediaType === 2 || mediaType === 3) && newDynamicGroup.length) {
             let adLength = 0
             accountCreateLogs.forEach(item => {
                 let productList: any[] = []
@@ -440,7 +440,7 @@ const Create: React.FC = () => {
             if (mediaType === 1) {
                 if (textType === 4) {
                     if (adLength > newDynamicGroup.length) {
-                        message.error(`创意组分配规则选择“平均分配到广告”时,创意组总数必须大于等于广告总数。当前创意组数量:${dynamicGroupLength},广告数量:${adLength}`)
+                        message.error(`创意组分配规则选择“平均分配到广告”时,创意组总数必须大于等于广告总数。当前创意组数量:${newDynamicGroup.length},广告数量:${adLength}`)
                         return
                     }
                     averageAdDynamicList = splitArrayIntoRandomChunks(newDynamicGroup, adLength)
@@ -456,6 +456,26 @@ const Create: React.FC = () => {
                     message.error(`创意组分配规则选择“顺序分配到广告”时,创意组总数必须小于等于广告总数。当前创意组数量:${dynamicGroupLength},广告数量:${adLength}`)
                     return
                 }
+            } else if (mediaType === 3) {
+                const dynamicDataLength = textType === 4 ? newDynamicGroup.length : dynamicGroupLength
+                if (accountCreateLogs.some(item => {
+                    let productList: any[] = []
+                    if (['MARKETING_TARGET_TYPE_FICTION', 'MARKETING_TARGET_TYPE_SHORT_DRAMA'].includes(marketingAssetOuterSpec?.marketingTargetType)) { // 小说 短剧
+                        productList = item?.productList || []
+                    } else if (['MARKETING_TARGET_TYPE_WECHAT_OFFICIAL_ACCOUNT'].includes(marketingAssetOuterSpec?.marketingTargetType)) { // 公众号
+                        productList = item?.wechatChannelList || []
+                    } else {
+                        productList = [{}]
+                    }
+                    const adLength = productList.length * targeting.length
+                    if (adLength > dynamicDataLength) {
+                        message.error(`创意组分配规则选择“账号下平均分配到广告”时,创意组总数必须大于等于每个账号广告总数。当前创意组数量:${dynamicDataLength},当前账号(${item.accountId})下广告数量:${adLength}`)
+                        return true
+                    }
+                    return false
+                })) {
+                    return
+                }
             }
         }
         if (textType === 1) {
@@ -492,10 +512,18 @@ const Create: React.FC = () => {
             } else if (['MARKETING_TARGET_TYPE_WECHAT_OFFICIAL_ACCOUNT'].includes(marketingAssetOuterSpec?.marketingTargetType)) { // 公众号
                 productList = item?.wechatChannelList || []
             }
-            let data = cartesianProduct(productList, targeting).map(newD => {
+            if (mediaType === 3) {
+                const adLength = productList.length * targeting.length
+                if (textType === 4) {
+                    averageAdDynamicList = splitArrayIntoRandomChunks(newDynamicGroup, adLength)
+                } else {
+                    averageAdDynamicList = distributeArray(newDynamicGroup, adLength)
+                }
+            }
+            let data = cartesianProduct(productList, targeting).map((newD, dindex) => {
                 let [productDto, targetDto, index] = newD
                 let suffix = '_' + item.accountId + '_' + index
-                let averageAdDynamic = averageAdDynamicList?.[accountIndex]
+                let averageAdDynamic = mediaType === 3 ? averageAdDynamicList?.[dindex] : averageAdDynamicList?.[accountIndex]
                 let dat: any = {
                     id: item.accountId + '_' + index,
                     accountId: item.accountId,                    // 账户
@@ -513,7 +541,7 @@ const Create: React.FC = () => {
                     },
                     dynamicDto: dynamic,                          // 创意信息
                     averageAdDynamic,
-                    rowSpan: (mediaType === 1 && textType !== 4) ? averageAdDynamic.length : ([910].includes(dynamic.creativeTemplateId) ? item.pageList?.length : (textType === 3 ? textDtoLenth * dynamicGroupLength : dynamicGroupLength)) || 1
+                    rowSpan: ((mediaType === 1 || mediaType === 3) && textType !== 4) ? averageAdDynamic.length : ([910].includes(dynamic.creativeTemplateId) ? item.pageList?.length : (textType === 3 ? textDtoLenth * dynamicGroupLength : dynamicGroupLength)) || 1
                 }
                 if (marketingCarrierType === 'MARKETING_CARRIER_TYPE_WECHAT_OFFICIAL_ACCOUNT') { // 营销载体
                     dat.marketingCarrierDto = item?.wechatChannelList
@@ -561,7 +589,7 @@ const Create: React.FC = () => {
                     })
                 }
             } else {
-                if (mediaType === 1) {
+                if (mediaType === 1 || mediaType === 3) {
                     data.forEach(item => {
                         const { averageAdDynamic, ...ad } = item
                         if (textType === 3) {
@@ -597,7 +625,11 @@ const Create: React.FC = () => {
                                     id: ad.id + '_' + index,
                                     dynamicGroup: aad,
                                     textDto: aad?.textDto,
-                                    adLength: data.length
+                                    adLength: data.length,
+                                    ...(mediaType === 3 ? {
+                                        rowSpan: index === 0 ? averageAdDynamic.length : 0,
+                                        isRowSpan: true
+                                    } : {})
                                 })
                             })
                         }
@@ -1068,7 +1100,7 @@ const Create: React.FC = () => {
                             setSubVisible(true)
                         }}>提交创建</Button>
                     </Space>}
-                    items={accountCreateLogs.map(item => ({ label: item.accountId, key: item.accountId })) as any[]}
+                    items={accountCreateLogs.map(item => ({ label: item.accountId, key: item.accountId?.toString() })) as any[]}
                 />
                 {addelivery?.dynamicCreativesTextDTOS?.type === 4 && <Title level={5} style={{ color: 'red', fontSize: 12 }}>因为选择的是“创意组和文案叉乘打乱后分配”模式,会随机打乱,当前预览广告下创意内容会与实际建出来的创意有偏差,请以建出来的为准</Title>}
                 <div className={style.content} style={{ marginTop: 20 }}>

+ 1 - 1
src/pages/launchSystemV3/tencentAdPutIn/typings.d.ts

@@ -20,7 +20,7 @@ declare namespace PULLIN {
         dynamic: any,
         dynamicMaterialDTos: any
         dynamicCreativesTextDTOS: any,
-        mediaType: 0 | 1 | 2
+        mediaType: 0 | 1 | 2 | 3
     }
     interface DispatchAddelivery {
         addelivery: AddeliveryProps,