import { Button, Checkbox, InputNumber, message, Modal, Popconfirm, Radio, Select, Space, Spin } from "antd"; import React, { useCallback, useEffect, useState } from "react"; import style1 from './index.less' import { TopImg, TopVideo, TopSlider } from '../../req' import { DeleteOutlined, PlusOutlined, RetweetOutlined } from "@ant-design/icons"; import { SortableUlList, SortableItemNoLi, SortableItemLi } from '../../components/addLandingPage/sortable' import arrayMove from "array-move" import SelectCloud from '../selectCloud' import { topsliderContent, topimgContent, topvideoNewContent } from '../../components/addLandingPage/content' import { BcForm } from "@/pages/launchSystem/launchManage/weChat/components/createPlan/components/AdBasicConfig"; import { useModel } from "umi"; import { getTypeKey } from "@/utils/utils"; import moment from "moment"; import { bdSysMediaAdd } from '@/services/launchAdq/material'; interface Props { visible: boolean, id: number, onChange?: () => void, onClose?: () => void, ajaxHome?: any } /** * 批量复制落地页 * @param props * @returns */ function BathLauCopy(props: Props) { const { visible, id, onChange, onClose, ajaxHome } = props /** ==============数据参数开始=============== */ const [elementType, setElementType] = useState(undefined) // 顶部素材类型 const [adLocation, setAdLocation] = useState('sns') // 广告位 const [outerStyle, setOuterStyle] = useState(0) // 外层样式 const [componentCount, setComponentCount] = useState(3) // 图片数量 const [selectImgVisible, setSelectImgVisible] = useState(false) // 选择图片弹窗 const [isFootlock, setIsFootlock] = useState(false) // 是否横板视频 const [sliderImgContent, setSliderImgContent] = useState<{ url: string, width?: number, height?: number }[]>([]) // 保存回填数据 const [groupIndex, setGroupIndex] = useState(-1) // 保存正在操作的组 下标 const [loading, setLoading] = useState(false) // 确定按钮loading const { init, get } = useModel('useLaunchAdq.useBdMediaPup') const { state: { parentId, belongUser } } = useModel('useLaunchAdq.useBdMedia') const [data, setData] = useState({}) const [topData, setTopData] = useState>([]) // 顶部素材数据 const [sort, setSort] = useState(0) // 排序 /** ===============数据参数结束=============== */ // 回填 useEffect(() => { if (id) { get.run({ sysMediaId: id, mediaType: 'PAGE' }).then(res => { if (res) { setData(res) const { pageSpecsList } = res let pageElementsSpec = pageSpecsList[0]?.pageElementsSpecList[0] setElementType(pageElementsSpec?.elementType) let typeKey = getTypeKey(pageElementsSpec?.elementType) setTopData([{ elementType: pageElementsSpec?.elementType as any, ...pageElementsSpec[typeKey] }]) if (pageElementsSpec?.elementType === 'TOP_IMAGE' || pageElementsSpec?.elementType === 'TOP_VIDEO') { setAdLocation(() => pageElementsSpec[typeKey]?.adLocation) setOuterStyle(() => pageElementsSpec[typeKey]?.outerStyle) setComponentCount(1) } else if (pageElementsSpec?.elementType === 'TOP_SLIDER') { setComponentCount(pageElementsSpec[typeKey]?.imageUrlList?.length || 3) } setSort(res?.sort || 0) } }) } }, [id]) // 设置选择的图片参数 /** 获取选中内容 */ useEffect(() => { if (elementType === 'TOP_IMAGE') { setIsFootlock(() => false) if (adLocation === 'sns') { // 朋友圈信息流 if (outerStyle === 0) { // 常规广告 init({ mediaType: 'IMG', cloudSize: [[{ relation: '=', width: 800, height: 800 }]] }) } else { // 卡片广告 init({ mediaType: 'IMG', cloudSize: [[{ relation: '=', width: 800, height: 450 }]] }) } } else { // 公众号及其他 init({ mediaType: 'IMG', cloudSize: [[{ relation: '=', width: 800, height: 800 }], [{ relation: '=', width: 800, height: 450 }], [{ relation: '=', width: 800, height: 640 }], [{ relation: '=', width: 640, height: 800 }]] }) } } else if (elementType === 'TOP_SLIDER') { // 轮播图 setIsFootlock(() => false) init({ mediaType: 'IMG', num: componentCount, cloudSize: [[{ relation: '=', width: 800, height: 800 }]] }) } else if (elementType === 'TOP_VIDEO') { // 视频 if (adLocation === 'sns') { // 朋友圈信息流 if (outerStyle === 0) { // 常规广告 init({ mediaType: 'VIDEO', cloudSize: [[{ relation: '=', width: 640, height: 480 }], [{ relation: '=', width: 640, height: 360 }], [{ relation: '=', width: 750, height: 1334 }], [{ relation: '=', width: 720, height: 1280 }]] }) } else { // 卡片广告 init({ mediaType: 'VIDEO', cloudSize: [[{ relation: '=', width: 750, height: null }, { relation: '<=', width: null, height: 1536 }]] }) } } else { // 公众号及其它 init({ mediaType: 'VIDEO', cloudSize: [[{ relation: '=', width: 750, height: null }, { relation: '<=', width: null, height: 1536 }]] }) setIsFootlock(() => false) } } }, [elementType, adLocation, outerStyle, componentCount]) // 关闭弹窗 const hideHandle = () => { onClose && onClose() } const handleOk = useCallback(() => { if (elementType === 'TOP_SLIDER' && !topData?.every((item1: any) => { if (!item1.imageUrlList?.every((item: string) => item)) { return false } else { return true } })) { message.error('顶部轮播图组缺少图片') return } else if (elementType === 'TOP_IMAGE' && !topData?.every((item: any) => item.imageUrl)) { message.error('顶部图片组缺少图片') return } else if (elementType === 'TOP_VIDEO' && !topData?.every((item: any) => item.videoUrl)) { message.error('顶部视频组缺少视频') return } setLoading(true) let ajax = topData?.map((item: any, index: number) => { const { elementType, ...newItem } = item let newTopPage = { elementType } let typeKey = getTypeKey(elementType) newTopPage[typeKey] = { ...newItem } let pageSpecsList: any[] = JSON.parse(JSON.stringify(data?.pageSpecsList)) pageSpecsList[0].pageElementsSpecList[0] = { ...newTopPage } let params = { mediaType: 'PAGE', folder: false, parentId, title: `批量复制` + moment().format("YYYYMMDDHHmmss"), pageName: `批量复制` + moment().format("YYYYMMDDHHmmss"), belongUser: belongUser === '0' ? false : true, sort, pageSpecsList, globalSpec: data?.globalSpec, shareContentSpec: data?.shareContentSpec } return bdSysMediaAdd(params as any) }) Promise.all(ajax).then((res: any) => { setLoading(false) if (res && res.length > 0) { let data = res[res.length - 1] if (data?.code === 200) { onClose && onClose() ajaxHome && ajaxHome?.refresh() message.success('新增成功') } } }).catch(() => { setLoading(false) }) }, [topData, elementType, sort, data, adLocation, outerStyle, loading, componentCount, parentId, belongUser]) // 切换顶部素材类型 const changeType = useCallback((value: string) => { setElementType(value) switch (value) { case 'TOP_IMAGE': setTopData([{ ...topimgContent }]) setComponentCount(1) break; case 'TOP_SLIDER': setTopData([{ ...topsliderContent }]) setComponentCount(3) break; case 'topvideo': setTopData([{ ...topvideoNewContent }]) break; } }, [elementType, topData, componentCount]) /** 轮播图位置拖动切换顺序 */ const onSortEndSlider = useCallback(({ oldIndex, newIndex }: { oldIndex: number, newIndex: number }) => { let topDataNew = JSON.parse(JSON.stringify(topData)) let selectCon = topDataNew[groupIndex] let imageUrlList = selectCon?.imageUrlList imageUrlList = arrayMove(imageUrlList, oldIndex, newIndex) selectCon = { ...selectCon, imageUrlList } topDataNew[groupIndex] = selectCon setTopData(topDataNew) }, [groupIndex, topData]) /** 轮播图选择图片 */ const sliderSelect = useCallback((index: number, indexGroup: number) => { let topDataNew = JSON.parse(JSON.stringify(topData)) // 保存点击了第几组的选择图片 setGroupIndex(indexGroup) // 设置activeIndex activeIndexHancdle(index, indexGroup) // 回填图片 let selectCon = topDataNew[indexGroup] let imgList: any[] = [] selectCon?.imageUrlList?.forEach((item: string) => { if (item) { imgList.push({ url: item }) } }) setSliderImgContent(imgList) setSelectImgVisible(true) }, [groupIndex, topData, sliderImgContent, selectImgVisible]) /** 选择单张图片 */ const clickUpdateImg = useCallback((index: number) => { setSliderImgContent([]) setSelectImgVisible(true) setGroupIndex(index) }, [sliderImgContent, selectImgVisible, groupIndex]) /** 添加素材组 */ const addTopData = useCallback(() => { switch (elementType) { case 'TOP_IMAGE': topData.push({ ...topimgContent }) setTopData([...topData]) break case 'TOP_SLIDER': let imageUrlList = Array(Number(componentCount)).fill('').map(() => "") topData.push({ ...topsliderContent, imageUrlList }) setTopData([...topData]) break case 'TOP_VIDEO': topData.push({ ...topvideoNewContent }) setTopData([...topData]) break } }, [elementType, topData, componentCount]) /**删除组 */ const del = useCallback((index: number) => { let newTopData = topData.filter((item, eq) => eq !== index) setTopData(newTopData) }, [topData]) /** 设置轮播图个数 */ const setCount = useCallback((value: number) => { setComponentCount(value) if (topData?.length > 0) { let selectCon = topData[0] as TopSlider if (selectCon?.elementType === 'TOP_SLIDER') { let imageUrlList = selectCon?.imageUrlList if (imageUrlList?.length > value) { // 减少 let newTopData = topData.map((item: any) => { let imageUrlList = item?.imageUrlList return { ...item, imageUrlList: [...imageUrlList?.splice(0, Number(value))] } }) setTopData([...newTopData]) } else { // 增加 let newList = Array(value - imageUrlList?.length).fill('').map(() => "") let newTopData = topData.map((item: any) => { let imageUrlList = item?.imageUrlList return { ...item, imageUrlList: [...imageUrlList, ...newList] } }) setTopData([...newTopData]) } } } }, [componentCount, topData]) /** 设置图片外层样式 */ const setImgViewType = useCallback((value: number) => { setOuterStyle(value) setTopData(topData.map((item: any) => ({ ...item, pureImageUrl: '' }))) }, [outerStyle, topData]) // 设置选择的图片 const setImg = useCallback((value: any[]) => { let topDataNew = JSON.parse(JSON.stringify(topData)) switch (elementType) { case 'TOP_IMAGE': topDataNew[groupIndex] = { ...topDataNew[groupIndex], imageUrl: value[0]?.url } break; case 'TOP_SLIDER': let imageUrlList = value?.map((item: { url: string }) => item.url) topDataNew[groupIndex] = { ...topDataNew[groupIndex], imageUrlList: topDataNew[groupIndex]?.imageUrlList?.reduce((prev: any[], cur: any, index: number) => { prev.push(imageUrlList[index] || "") return prev }, []) } break; case 'TOP_VIDEO': topDataNew[groupIndex] = { ...topDataNew[groupIndex], videoUrl: value[0]?.url } break; } setSelectImgVisible(false) setTopData(topDataNew) }, [elementType, groupIndex, topData, adLocation, outerStyle]) /** 设置activeIndex */ const activeIndexHancdle = useCallback((index: number, indexGroup: number) => { let topDataNew = JSON.parse(JSON.stringify(topData)) // 设置activeIndex topDataNew[indexGroup] = { ...topDataNew[indexGroup], activeIndex: index } setTopData(topDataNew) }, [topData]) return {/* 选择素材 */} {selectImgVisible && setSelectImgVisible(false)} onChange={setImg} />}
{data?.title}
{data?.shareContentSpec?.shareTitle}
{data?.shareContentSpec?.shareDescription}
顶部素材设置
{elementType === "TOP_IMAGE" ? <>
广告位与样式
{ setAdLocation(e.target.value) if (topData?.length > 0) { setTopData(topData?.map((item: any) => ({ ...item, imageUrl: '' }))) } }} value={adLocation} size='small'> 朋友圈信息流 公众号及其他 {adLocation === 'sns' && } : elementType === "TOP_SLIDER" ? <>
素材设置
{ setCount(e.target.value) }} value={componentCount} size='small'> 3张 4张 6张 : elementType === "TOP_VIDEO" ? <>
广告位与样式
{ setAdLocation(e.target.value); if (topData?.length > 0) { setTopData(topData?.map((item: any) => ({ ...item, videoUrl: '' }))) } setOuterStyle(0); }} value={adLocation} size='small'> 朋友圈信息流 公众号及其他 {adLocation === 'sns' && } : <> } { setSort(e) }} />
{ elementType === "TOP_IMAGE" || elementType === "TOP_SLIDER" || elementType === "TOP_VIDEO" ? <>
顶部素材 * 素材组数量:{topData.length} 组
{elementType === "TOP_IMAGE" ?
{ topData?.map((item: any, index: number) => { return
素材组{index >= 9 ? (index + 1).toString() : '0' + (index + 1).toString()}
图片({item.imageUrl ? 1 : 0}/1)
} flex='flex-start' >
{item.imageUrl ?
{ clickUpdateImg(index) }}>
:
{ clickUpdateImg(index) }}>
}
{topData?.length > 1 && { del(index) }} okText="Yes" cancelText="No"> }
}) } : elementType === "TOP_SLIDER" ?
{topData.map((item1: any, index1: number) => { return
{ setGroupIndex(index1) }}> 素材组{index1 >= 9 ? (index1 + 1).toString() : '0' + (index1 + 1).toString()}
图片({item1?.imageUrlList?.reduce((prev: number, cur: { url: string }) => cur?.url ? prev + 1 : prev, 0)}/{componentCount})
} flex='flex-start' >
{item1?.imageUrlList?.map((item: any, index: number) => { if (item) { return { sliderSelect(index, index1) }} setActiveIndex={() => { activeIndexHancdle(index, index1) }}> } else { return { sliderSelect(index, index1) }}> } })} {topData?.length > 1 && { del(index1) }} okText="Yes" cancelText="No"> }
})} : <> {/* TOP_VIDEO */}
{ topData?.map((item: any, index: number) => { return
素材组{index >= 9 ? (index + 1).toString() : '0' + (index + 1).toString()}
视频({item.videoUrl ? 1 : 0}/1)
} flex='flex-start' >
{item.videoUrl ?
{ clickUpdateImg(index) }}>
:
{ clickUpdateImg(index) }}>
}
{topData?.length > 1 && { del(index) }} okText="Yes" cancelText="No"> }
}) } } : <> }
} export default React.memo(BathLauCopy)