import React, { useCallback, useEffect, useState } from 'react' import { Modal, Form, Input, Divider, Select, Radio, DatePicker, Switch, Checkbox, message, Tooltip, Row, Col, Space, TimePicker, Button } from 'antd' import { BidModeEnum, OptimizationGoalEnum, BidStrategyEnum, AdStatus, GoalRoasEnum } from '@/services/launchAdq/enum' import { ModalConfig } from '../index' import moment from 'moment'; import { useAjax } from '@/Hook/useAjax'; import { getSceneTagsList } from '@/services/launchAdq/global'; import { ExclamationCircleOutlined } from '@ant-design/icons'; import { CreateAdProps } from '@/services/launchAdq/createAd'; import { createSysAdgroups } from '@/services/launchAdq/localAd'; import AdPositionList from './adPositionList'; import { SiteSetPackageDataProps } from './leadAd'; import BidAdjustment from './bidAdjustment'; import { useModel } from 'umi'; const { RangePicker }: { RangePicker: any } = DatePicker; let DatePickers: any = DatePicker interface Props { queryForm: Partial, visible: boolean, PupFn: (arg: ModalConfig) => void, callback: (params: any) => void, confirmLoading?: boolean, type?: 'add' | 'look' | 'edit',//新增,查看,编辑 dataInfo?: any, ajax: any } /**微信公众号广告弹窗*/ function WeChatAdModal(props: Props) { /*******************************/ let { visible, confirmLoading, PupFn, callback, type, dataInfo, queryForm, ajax } = props const { currentUser }: any = useModel('@@initialState', model => ({ currentUser: model.initialState?.currentUser })) const createSysAdgroup = useAjax((params) => createSysAdgroups(params)) let [state, setState] = useState({ isShowTime: [] }) let [template_checked, settemplate_checked] = useState(dataInfo?.isTemplate || false) let arg = type === 'look' ? { footer: null } : {} const sceneTagsList = useAjax((params) => getSceneTagsList(params)) const [form] = Form.useForm(); let dateType = Form.useWatch('dateType', form) let bidMode = Form.useWatch('bidMode', form) let smartBidType = Form.useWatch('smartBidType', form) let autoAcquisitionEnabled = Form.useWatch('autoAcquisitionEnabled', form) let siteSet = Form.useWatch('siteSet', form) let wechatPositionType = Form.useWatch('wechatPositionType', form) let wechatSceneType = Form.useWatch('wechatSceneType', form) let automaticSiteEnabled = Form.useWatch('automaticSiteEnabled', form) let optimizationGoal = Form.useWatch('optimizationGoal', form) let depthConversionEnabled = Form.useWatch('depthConversionEnabled', form) let deepConversionType = Form.useWatch('deepConversionType', form) let goal = Form.useWatch('goal', form) let bidAdjustmentEnabled = Form.useWatch('bidAdjustmentEnabled', form) let siteSetPackage = Form.useWatch('siteSetPackage', form) let deepBidAmount = Form.useWatch('deepBidAmount', form) let bidAmountAdjustmentEnabled = Form.useWatch('bidAmountAdjustmentEnabled', form) let bidAmount = Form.useWatch('bidAmount', form) const [behaviorList, setBehaviorList] = useState([]) const [worthList, setWorthList] = useState([]) /*******************************/ // 确定事件 const handleOk = useCallback(() => { form.validateFields().then(values => { let newValues = JSON.parse(JSON.stringify(values)) newValues.sceneSpec = {} if (newValues.dateType === '2') { newValues['beginDate'] = moment(newValues.date).format('YYYY-MM-DD') } else { newValues['beginDate'] = moment(newValues.date[0]).format('YYYY-MM-DD') newValues['endDate'] = moment(newValues.date[1]).format('YYYY-MM-DD') } if (newValues.firstDayBeginTime) { newValues['firstDayBeginTime'] = moment(newValues.firstDayBeginTime).format('HH:mm:ss') } Object.keys(newValues).forEach(key => { switch (key) { case 'wechatPositionType': if (newValues[key] === '1') { newValues.sceneSpec = { ...newValues.sceneSpec, wechatPosition: newValues.wechatPosition } } break; case 'wechatSceneType': if (newValues[key] === '1') { newValues.sceneSpec = { ...newValues.sceneSpec, wechatScene: { officialAccountMediaCategory: newValues.officialAccountMediaCategory, miniProgramAndMiniGame: newValues.miniProgramAndMiniGame, payScene: newValues.payScene } } } break; case 'siteSetPackage': // 处理分版位出价 if (newValues[key]?.length > 0) { let newSiteSetPackage: SiteSetPackageDataProps[] = JSON.parse(JSON.stringify(newValues[key])) if (!newValues?.bidAmountAdjustmentEnabled) { newSiteSetPackage = newSiteSetPackage.map(item => { let { bidCoefficient, ...newItem } = item return { ...newItem } }) } if (!newValues?.bidAdjustmentEnabled) { newSiteSetPackage = newSiteSetPackage.map(item => { let { deepBidCoefficient, ...newItem } = item return { ...newItem } }) } newValues.bidAdjustment = { siteSetPackage: newSiteSetPackage } delete newValues.siteSetPackage } break case 'deepConversionType': // 处理深度优化 let deepConversionSpec: any = { deepConversionType: newValues[key] } if (newValues[key] === 'DEEP_CONVERSION_WORTH') { // 优化 ROI deepConversionSpec.deepConversionWorthSpec = { goal: newValues.goal, expectedRoi: newValues.deepBidAmount } } else if (newValues[key] === 'DEEP_CONVERSION_BEHAVIOR') { // 优化转化行为 deepConversionSpec.deepConversionBehaviorSpec = { goal: newValues.goal, bidAmount: newValues.deepBidAmount * 100 } } newValues.deepConversionSpec = deepConversionSpec delete newValues.deepBidAmount delete newValues.goal delete newValues.optimizationMode delete newValues.deepConversionType delete newValues.depthConversionEnabled break } }) if (newValues.sceneSpec.wechatPosition?.length === 0) { delete newValues.sceneSpec.wechatPosition } if (newValues.sceneSpec.wechatScene) { newValues.sceneSpec.wechatScene.officialAccountMediaCategory?.length === 0 && (delete newValues.sceneSpec.wechatScene.officialAccountMediaCategory) newValues.sceneSpec.wechatScene.miniProgramAndMiniGame?.length === 0 && (delete newValues.sceneSpec.wechatScene.miniProgramAndMiniGame) newValues.sceneSpec.wechatScene.payScene?.length === 0 && (delete newValues.sceneSpec.wechatScene.payScene) } if (!newValues.sceneSpec.wechatPosition && !newValues.sceneSpec.wechatScene) { delete newValues.sceneSpec } delete newValues.officialAccountMediaCategory delete newValues.miniProgramAndMiniGame delete newValues?.bidAmountAdjustmentEnabled delete newValues?.bidAdjustmentEnabled delete newValues.payScene delete newValues.wechatPositionType delete newValues.wechatPosition delete newValues.wechatScene delete newValues['dateType'] delete newValues['date'] newValues['timeSeries'] = Array(336).fill(1).join('') newValues['promotedObjectType'] = queryForm.promotedObjectType newValues['isTemplate'] = template_checked console.log(newValues) // 开启存为模板开关执行 // if (template_checked && type === 'add') { // createSysAdgroup.run(newValues).then(res => { // if (res) { // callback(newValues) // } // }) // } else { callback(newValues) // } }) }, [form, template_checked, queryForm, type]) // 场景定向 useEffect(() => { sceneTagsList.run({ typeList: ['WECHAT_POSITION', 'OFFICIAL_ACCOUNT_MEDIA_CATEGORY', 'MINI_PROGRAM_AND_MINI_GAME', 'PAY_SCENE'] }) }, []) // 数据回填 useEffect(() => { if (dataInfo) { let formData: any = { adgroupName: dataInfo?.adgroupName,//广告名称 promotedObjectType: dataInfo?.promotedObjectType,//推广目标 siteSet: dataInfo?.siteSet,//广告版位 autoAcquisitionEnabled: dataInfo?.autoAcquisitionEnabled,//一键起量 bidAmount: dataInfo?.bidAmount,//出价 smartBidType: dataInfo?.smartBidType,//出价类型 bidStrategy: dataInfo?.bidStrategy,//出价策略 bidMode: dataInfo?.bidMode,//出价方式 optimizationGoal: dataInfo?.optimizationGoal,//优化目标 dateType: dataInfo?.endDate ? '1' : '2',//投放日期 dailyBudget: dataInfo?.dailyBudget,//广告日预算 date: dataInfo?.endDate ? [moment(dataInfo?.beginDate), moment(dataInfo?.endDate)] : moment(dataInfo?.beginDate),//日期 autoAcquisitionBudget: dataInfo?.autoAcquisitionBudget,//起量预算 wechatPositionType: dataInfo?.sceneSpec?.wechatPosition ? '1' : '0',//微信公众号与小程序定投 wechatPosition: dataInfo?.sceneSpec?.wechatPosition,//微信公众号与小程序定投 wechatSceneType: dataInfo?.sceneSpec?.wechatScene?.officialAccountMediaCategory || dataInfo?.sceneSpec?.wechatScene?.miniProgramAndMiniGame || dataInfo?.sceneSpec?.wechatScene?.payScene ? '1' : '0',//微信公众号与小程序场景 officialAccountMediaCategory: dataInfo?.sceneSpec?.wechatScene?.officialAccountMediaCategory,//公众号媒体类型 miniProgramAndMiniGame: dataInfo?.sceneSpec?.wechatScene?.miniProgramAndMiniGame,//小程序小游戏流量类型 payScene: dataInfo?.sceneSpec?.wechatScene?.payScene,//订单详情页消费场景 firstDayBeginTime: dataInfo?.firstDayBeginTime ? moment(`${dataInfo?.beginDate} ${dataInfo?.firstDayBeginTime}`) : undefined,//首日开始时间 configuredStatus: dataInfo?.configuredStatus || 'AD_STATUS_SUSPEND',//广告启停 } Object.keys(dataInfo).forEach(key => { switch (key) { case 'bidAdjustment': // 处理分版位出价 if (dataInfo[key]?.siteSetPackage && dataInfo[key]?.siteSetPackage?.length > 0) { let siteSetPackage: SiteSetPackageDataProps[] = dataInfo[key].siteSetPackage if (siteSetPackage.some(item => item.bidCoefficient)) { // 判断出价是否开启了分版位 formData.bidAmountAdjustmentEnabled = true } else { siteSetPackage = siteSetPackage.map(item => ({ ...item, bidCoefficient: 1 })) } if (siteSetPackage.some(item => item.deepBidCoefficient)) { // 判断深度出价是否开启了分版位 formData.bidAdjustmentEnabled = true } else { siteSetPackage = siteSetPackage.map(item => ({ ...item, deepBidCoefficient: 1 })) } formData.siteSetPackage = siteSetPackage } break case 'deepConversionSpec': // 处理深度优化 if (dataInfo[key]?.deepConversionType === 'DEEP_CONVERSION_WORTH') { formData = { ...formData, optimizationMode: 'DEEP_CONVERSION_TARGET', depthConversionEnabled: true, deepConversionType: dataInfo[key]?.deepConversionType, goal: dataInfo[key]?.deepConversionWorthSpec?.goal, deepBidAmount: dataInfo[key]?.deepConversionWorthSpec?.expectedRoi, } } else if (dataInfo[key]?.deepConversionType === 'DEEP_CONVERSION_BEHAVIOR') { formData = { ...formData, optimizationMode: 'DEEP_CONVERSION_TARGET', depthConversionEnabled: true, deepConversionType: dataInfo[key]?.deepConversionType, goal: dataInfo[key]?.deepConversionBehaviorSpec?.goal, deepBidAmount: dataInfo[key]?.deepConversionBehaviorSpec?.bidAmount / 100, } } break } }) form.setFieldsValue(formData) if (dataInfo?.firstDayBeginTime) {//存在首日开始时间,选中开关 setState({ ...state, isShowTime: ['1'] }) } } else { form.setFieldsValue({ adgroupName: '广告_微信朋友圈_' + moment().format('YYYYMMDDhhmmss') + '_' + currentUser.userId, date: moment().startOf('day').add(4, 'M'), optimizationGoal: "OPTIMIZATIONGOAL_ECOMMERCE_ORDER", bidStrategy: "BID_STRATEGY_TARGET_COST", bidAmount: '1000' }) } }, [dataInfo]) // 出价方式改变清空某些数据 const bidModeChange = useCallback((props) => { form.setFieldsValue({ ...props, optimizationGoal: null, smartBidType: null, // bidAmount:null, bidStrategy: null, autoAcquisitionEnabled: false, autoAcquisitionBudget: null, dailyBudget: null, }) }, []) // 出价和版位改变时查询 useEffect(() => { if (bidMode && siteSet && siteSet?.length > 0) { let obj: any = { siteSet, promotedObjectType: queryForm.promotedObjectType } if (bidMode === 'BID_MODE_OCPC' || bidMode === 'BID_MODE_OCPM') { obj = { ...obj, bidMode } } ajax.run(obj).then((res: any) => { console.log(res) }) } }, [bidMode, siteSet]) // 处理深度转化优化 useEffect(() => { if (optimizationGoal && ajax?.data) { let { deepBehaviorOptimizationGoalPermissionList, deepWorthOptimizationGoalPermissionList } = ajax?.data // deepBehaviorOptimizationGoalPermissionList 优化转化行为 // deepWorthOptimizationGoalPermissionList 优化ROI let behavior = deepBehaviorOptimizationGoalPermissionList?.find((item: { optimizationGoal: string }) => item.optimizationGoal === optimizationGoal) let worth = deepWorthOptimizationGoalPermissionList?.find((item: { optimizationGoal: string }) => item.optimizationGoal === optimizationGoal) setBehaviorList(behavior?.deepBehaviorOptimizationGoalList || []) setWorthList(worth?.deepWorthOptimizationGoalList || []) } }, [optimizationGoal, ajax?.data]) /**处理分版位数据 */ const setSiteSetHandle = (siteSet: string[]) => { let data: SiteSetPackageDataProps[] = [] if (siteSet && siteSet?.length > 0) { data = siteSet?.map((item: string) => ({ siteSet: [item], bidCoefficient: 1, deepBidCoefficient: 1 })) } else { data = [] } form.setFieldsValue({ siteSetPackage: data }) } return { PupFn({ visible: false, dataInfo: null, type: 'add' }) }} width={900} confirmLoading={createSysAdgroup?.loading} footer={ { { let checked = e.target.checked settemplate_checked(checked) }}>存为模板} } {...arg} >
{/* ============================================================基本信息============================================================= */} 基本信息 广告名称} name='adgroupName' rules={[{ required: true, message: '请输入广告名称!' }]}> 广告版位}> 自动版位 选择特定版位 {!automaticSiteEnabled && { bidModeChange({ bidMode: 'BID_MODE_OCPM' }); setSiteSetHandle(e as string[]) }}> 微信朋友圈 微信公众号与小程序 微信新闻插件 优量汇 腾讯新闻 腾讯视频 QQ 浏览器 QQ、腾讯音乐及游戏 } { siteSet?.some((s: string) => s === 'SITE_SET_WECHAT') && <> 微信公众号与小程序定投} name='wechatPositionType' style={wechatPositionType === '1' ? { marginBottom: 5 } : {}}> 不限 自定义 {wechatPositionType === '1' && ({ label: item.description, value: item.id }))} /> } 微信公众号与小程序场景} name='wechatSceneType' style={wechatSceneType === '1' ? { marginBottom: 5 } : {}} > 不限 自定义 {wechatSceneType === '1' && <>

公众号媒体类型

i.description !== '不限')?.map((item: { description: any; id: any; }) => ({ label: item.description, value: item.id }))} />

小程序小游戏流量类型

i.description !== '不限')?.map((item: { description: any; id: any; }) => ({ label: item.description, value: item.id }))} />

订单详情页消费场景

i.description !== '不限')?.map((item: { description: any; id: any; }) => ({ label: item.description, value: item.id }))} /> } } {/* ============================================================排期与出价============================================================= */} 排期与出价 投放日期} name='dateType'> { if (e.target.value === "1") { form.setFieldsValue({ date: [moment().startOf('day').add(4, 'M'), moment().startOf('day').add(12, 'M')] }) } if (e.target.value === "2") { form.setFieldsValue({ date: moment().startOf('day').add(4, 'M') }) } }}> 选择开始与结束日期 长期投放 {/* 投放日期的不同展示不同的日期选择 */} { dateType === '1' ? : } 投放时段}> 全天投放 { setState({ ...state, isShowTime: checkedValue }) } } value={state.isShowTime} /> {state?.isShowTime?.length > 0 && } 出价方式} name='bidMode' rules={[{ required: true, message: '请选择出价方式' }]}> { if (e.target.value === "BID_MODE_CPM") { form.setFieldsValue({ optimizationGoal: null, smartBidType: null, // bidAmount:null, bidStrategy: null, autoAcquisitionEnabled: false, autoAcquisitionBudget: null, dailyBudget: null, }) } else { form.setFieldsValue({ optimizationGoal: "OPTIMIZATIONGOAL_ECOMMERCE_ORDER", smartBidType: "SMART_BID_TYPE_CUSTOM", bidAmount: '1000', bidStrategy: "BID_STRATEGY_TARGET_COST", autoAcquisitionEnabled: false, autoAcquisitionBudget: null, dailyBudget: null, }) } }}> { Object.keys(BidModeEnum).filter(key => { if (siteSet?.some((name: string) => name === "SITE_SET_MOMENTS")) { return key === 'BID_MODE_OCPM' || key === 'BID_MODE_CPM' } else { return true } })?.map(key => { return {BidModeEnum[key]} }) } {/* 出价方式为OCPM才展示 */} { bidMode === 'BID_MODE_OCPM' && <> 优化目标} name='optimizationGoal' rules={[{ required: true, message: '请选择优化目标' }]}> 出价类型} name='smartBidType' rules={[{ required: true, message: '请选择出价类型' }]}> 手动出价 自动出价 出价策略} name='bidStrategy' rules={[{ required: true, message: '请选择出价策略' }]}> { Object.keys(BidStrategyEnum).map(key => { return {BidStrategyEnum[key]} }) } } {/* 出价类型为手动出价才展示 */} {smartBidType !== 'SMART_BID_TYPE_SYSTEMATIC' && <> 出价} name='bidAmount' rules={[{ required: true, message: '请输入价格' }]}> {bidMode === 'BID_MODE_OCPM' && <> {/* 当版位选择大于1时才出现 */} {siteSet?.length > 1 && 分版位出价} name='bidAmountAdjustmentEnabled' valuePropName="checked"> } {bidAmountAdjustmentEnabled && 分版位出价} name='siteSetPackage' rules={[{ required: bidAmountAdjustmentEnabled ? true : false, message: '请设置系数' }]} > { form.setFieldsValue({ siteSetPackage: data }) }} /> } 一键起量} name='autoAcquisitionEnabled' valuePropName="checked"> {/* 一键起量开启时才出现 */} {autoAcquisitionEnabled && 起量预算} name='autoAcquisitionBudget' rules={[{ required: true, message: '请输入起量预算' }]}> } {/* 深度优化 */} {(behaviorList?.length > 0 || worthList?.length > 0) && 深度转化优化} name='depthConversionEnabled' valuePropName="checked"> { if (e) { form.setFieldsValue({ optimizationMode: 'DEEP_CONVERSION_TARGET', deepConversionType: behaviorList?.length > 0 ? 'DEEP_CONVERSION_BEHAVIOR' : worthList?.length > 0 ? 'DEEP_CONVERSION_WORTH' : '' }) } }} /> } {depthConversionEnabled &&
深度优化方式} name='optimizationMode' rules={[{ required: true, message: '请选择深度优化方式' }]}> 深度目标优化 深度优化类型} name='deepConversionType' rules={[{ required: true, message: '请选择深度优化类型' }]}> { form.setFieldsValue({ goal: undefined, deepBidAmount: undefined }) }}> {behaviorList?.length > 0 && 优化转化行为} {worthList?.length > 0 && 优化 ROI} 深度优化目标} name='goal' rules={[{ required: true, message: '请选择深度优化目标' }]}> {deepConversionType === 'DEEP_CONVERSION_BEHAVIOR' ? <> 深度目标出价} name='deepBidAmount' rules={[{ required: true, message: '请输入深度目标出价' }]}> : deepConversionType === 'DEEP_CONVERSION_WORTH' ? <> 期望ROI} name='deepBidAmount' rules={[{ required: true, message: '请输入期望ROI' }]}> : null} {siteSet?.length > 1 && 开启分版位深度目标出价} name='bidAdjustmentEnabled' valuePropName="checked"> } {bidAdjustmentEnabled && 分版位深度目标出价} name='siteSetPackage' rules={[{ required: bidAdjustmentEnabled ? true : false, message: '请设置系数' }]} > {!(bidAmountAdjustmentEnabled) ? { form.setFieldsValue({ siteSetPackage: data }) }} /> : <>} }
} } } 广告日预算} name='dailyBudget'> 广告状态} name="configuredStatus" rules={[{ required: true, message: '请选择广告状态' }]}>
} export default WeChatAdModal