|
@@ -5,6 +5,11 @@ import style from '../index.less'
|
|
|
import New1Radio from "@/pages/launchSystemV3/components/New1Radio";
|
|
|
import { useUpdateEffect } from "ahooks";
|
|
|
import { QuestionCircleFilled } from "@ant-design/icons";
|
|
|
+import { txtLength } from "@/utils/utils";
|
|
|
+import TextAideInput from "@/pages/launchSystemV3/components/TextAideInput";
|
|
|
+import styles from '../Material/index.less'
|
|
|
+import { useModel } from "umi";
|
|
|
+import SelectCloud from "@/pages/launchSystemNew/components/selectCloud";
|
|
|
|
|
|
/**
|
|
|
* 营销组件
|
|
@@ -21,9 +26,32 @@ const CreativeConversionAssistant: React.FC<{ automaticSiteEnabled?: boolean }>
|
|
|
const linkNameType = Form.useWatch(['textLink', 'value', 'linkNameType'], form)
|
|
|
const conversionDataType = Form.useWatch(['showData', 'value', 'conversionDataType'], form)
|
|
|
const conversionTargetType = Form.useWatch(['showData', 'value', 'conversionTargetType'], form)
|
|
|
+ const floatingZone = Form.useWatch('floatingZone', form)
|
|
|
+ const floatingZoneSwitch = Form.useWatch(['floatingZone', 'value', 'floatingZoneSwitch'], form)
|
|
|
+ const floatingZoneType = Form.useWatch(['floatingZone', 'value', 'floatingZoneType'], form)
|
|
|
+ const image = Form.useWatch(['floatingZone', 'value', 'image'], form)
|
|
|
const creativeTemplateId = Form.useWatch('creativeTemplateId', form)
|
|
|
const cardType: string[] = Form.useWatch('cardType', form)
|
|
|
const [cardData, setCardData] = useState<{ label: string, value: string, disabled?: boolean }[]>([])
|
|
|
+ const { init } = useModel('useLaunchAdq.useBdMediaPup')
|
|
|
+ const [materialConfig, setMaterialConfig] = useState<{
|
|
|
+ adcreativeTemplateId?: number,
|
|
|
+ type: string,
|
|
|
+ cloudSize: { relation: string, width: number, height: number }[],
|
|
|
+ list: any[],
|
|
|
+ index: number,
|
|
|
+ max: number,
|
|
|
+ sliderImgContent: any,
|
|
|
+ isGroup?: boolean
|
|
|
+ }>({
|
|
|
+ type: '',//类型
|
|
|
+ cloudSize: [],//素材搜索条件
|
|
|
+ list: [],//素材
|
|
|
+ index: 0, // 素材组下标
|
|
|
+ max: 1,//素材数量
|
|
|
+ sliderImgContent: undefined
|
|
|
+ })//图片素材配置
|
|
|
+ const [selectVideoVisible, setSelectVideoVisible] = useState(false)
|
|
|
/**************************************/
|
|
|
|
|
|
useUpdateEffect(() => {
|
|
@@ -220,6 +248,7 @@ const CreativeConversionAssistant: React.FC<{ automaticSiteEnabled?: boolean }>
|
|
|
return null
|
|
|
}, [creativeComponents?.action_button, pageSpec, actionButtonShow, cardType, creativeTemplateId])
|
|
|
|
|
|
+ /** 数据外显 */
|
|
|
const showDataContent = useMemo(() => {
|
|
|
let showData = creativeComponents?.show_data;
|
|
|
if (showData) {
|
|
@@ -294,6 +323,174 @@ const CreativeConversionAssistant: React.FC<{ automaticSiteEnabled?: boolean }>
|
|
|
return null
|
|
|
}, [creativeComponents?.show_data, linkNameType, showDataShow, creativeTemplateId])
|
|
|
|
|
|
+ /** 浮层卡片 */
|
|
|
+ const floatingZoneContent = useMemo(() => {
|
|
|
+ let floatingZone = creativeComponents?.floating_zone;
|
|
|
+ if (floatingZone) {
|
|
|
+ let required = floatingZone?.required
|
|
|
+ let children = floatingZone.children
|
|
|
+ const { floating_zone_type, floating_zone_image_id, floating_zone_single_image_id, floating_zone_name, floating_zone_desc, floating_zone_button_text } = children
|
|
|
+ const floatingZoneTypeList: PULLIN.DataType[] = []
|
|
|
+ if (floating_zone_image_id) {
|
|
|
+ floatingZoneTypeList.push({ label: "图文复合类型", value: "FLOATING_ZONE_TYPE_IMAGE_TEXT" })
|
|
|
+ }
|
|
|
+ if (floating_zone_single_image_id) {
|
|
|
+ floatingZoneTypeList.push({ label: "单图类型", value: "FLOATING_ZONE_TYPE_SINGLE_IMAGE" })
|
|
|
+ }
|
|
|
+ let floatingZoneButtonTextEnumeration: { label: string, value: string }[] = [];
|
|
|
+ if (floating_zone_button_text) {
|
|
|
+ floatingZoneButtonTextEnumeration = (floating_zone_button_text.enumProperty.enumeration as { value: string, description: string }[]).map(item => ({ label: item.value, value: item.value }))
|
|
|
+ }
|
|
|
+
|
|
|
+ return <>
|
|
|
+ <Form.Item style={{ marginBottom: 0 }}>
|
|
|
+ <div className={style.newSpace} style={{ border: 'none' }}>
|
|
|
+ <div className={style.newSpace_top}>
|
|
|
+ <div className={style.newSpace_title}>浮层卡片</div>
|
|
|
+ <Form.Item name={['floatingZone', 'value', 'floatingZoneSwitch']} rules={[{ required, message: '请选择浮层卡片!' }]} valuePropName="checked" style={{ marginBottom: 0 }}>
|
|
|
+ <Switch disabled={required} />
|
|
|
+ </Form.Item>
|
|
|
+ </div>
|
|
|
+ {floatingZoneSwitch && <Form.Item name={['floatingZone', 'value', 'floatingZoneType']} rules={[{ required: floating_zone_type?.required, message: `请选择` + floating_zone_type?.description }]} style={{ marginTop: 10, marginBottom: 0 }}>
|
|
|
+ <New1Radio data={floatingZoneTypeList} />
|
|
|
+ </Form.Item>}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {(floatingZoneSwitch && floatingZoneType === 'FLOATING_ZONE_TYPE_IMAGE_TEXT') ? <Card bordered className="cardResetCss newCss" bodyStyle={{ padding: 0 }}>
|
|
|
+ <div className={style.newSpace}>
|
|
|
+ <div className={style.newSpace_top} style={{ alignItems: 'flex-start' }}>
|
|
|
+ <div className={style.newSpace_title}>{floating_zone_image_id?.description}</div>
|
|
|
+ <Form.Item
|
|
|
+ rules={[{ required: true, message: '请选择素材!' }]}
|
|
|
+ name={['floatingZone', 'value', 'image']}
|
|
|
+ >
|
|
|
+ <div className={`${styles.box} ${styles.image}`} style={{ width: 300, height: 160 }} onClick={() => {
|
|
|
+ init({ mediaType: 'IMG', cloudSize: [[{ relation: '=', width: floating_zone_image_id.restriction.imageRestriction.width, height: floating_zone_image_id.restriction.imageRestriction.height }]], maxSize: floating_zone_image_id.restriction.imageRestriction.fileSize * 1024 })
|
|
|
+ setMaterialConfig({
|
|
|
+ ...materialConfig,
|
|
|
+ type: 'floatingZoneImage',
|
|
|
+ max: 1,
|
|
|
+ index: 1,
|
|
|
+ adcreativeTemplateId: creativeTemplateId
|
|
|
+ })
|
|
|
+ setTimeout(() => {
|
|
|
+ setSelectVideoVisible(true)
|
|
|
+ }, 100)
|
|
|
+ }}>
|
|
|
+ <p>
|
|
|
+ {image?.floatingZoneImageUrl ? <img src={image?.floatingZoneImageUrl} /> : <>
|
|
|
+ <span>{`推荐尺寸(${floating_zone_image_id.restriction.imageRestriction.width} x ${floating_zone_image_id.restriction.imageRestriction.height})`}</span>
|
|
|
+ <span>{`${floating_zone_image_id.restriction.imageRestriction.fileFormat?.map((str: any) => str?.replace('IMAGE_TYPE_', ''))};小于 ${floating_zone_image_id.restriction.imageRestriction.fileSize}KB`}</span>
|
|
|
+ </>}
|
|
|
+ </p>
|
|
|
+ </div>
|
|
|
+ </Form.Item>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className={style.newSpace}>
|
|
|
+ <div className={style.newSpace_top}>
|
|
|
+ <div className={style.newSpace_title}>{floating_zone_name?.description}</div>
|
|
|
+ <Form.Item
|
|
|
+ name={['floatingZone', 'value', 'floatingZoneName']}
|
|
|
+ rules={[{
|
|
|
+ required: floating_zone_name.required, message: '请输入正确的' + floating_zone_name.description, validator: (rule, value) => {
|
|
|
+ if (!value) {
|
|
|
+ return Promise.reject()
|
|
|
+ } else if (!value.match(RegExp(floating_zone_name.restriction.textRestriction.textPattern))) {
|
|
|
+ return Promise.reject()
|
|
|
+ } else if (txtLength(value) > floating_zone_name.restriction.textRestriction.maxLength) {
|
|
|
+ return Promise.reject()
|
|
|
+ }
|
|
|
+ return Promise.resolve()
|
|
|
+ }
|
|
|
+ }]}
|
|
|
+ style={{ marginBottom: 0 }}
|
|
|
+ >
|
|
|
+ <TextAideInput isShowAjax={false} placeholder={'请输入' + floating_zone_name.description} style={{ width: 480 }} maxTextLength={floating_zone_name.restriction.textRestriction.maxLength} />
|
|
|
+ </Form.Item>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className={style.newSpace}>
|
|
|
+ <div className={style.newSpace_top}>
|
|
|
+ <div className={style.newSpace_title}>{floating_zone_desc?.description}</div>
|
|
|
+ <Form.Item
|
|
|
+ name={['floatingZone', 'value', 'floatingZoneDesc']}
|
|
|
+ rules={[{
|
|
|
+ required: floating_zone_desc.required, message: '请输入正确的' + floating_zone_desc.description, validator: (rule, value) => {
|
|
|
+ if (!value) {
|
|
|
+ return Promise.reject()
|
|
|
+ } else if (!value.match(RegExp(floating_zone_desc.restriction.textRestriction.textPattern))) {
|
|
|
+ return Promise.reject()
|
|
|
+ } else if (txtLength(value) > floating_zone_desc.restriction.textRestriction.maxLength) {
|
|
|
+ return Promise.reject()
|
|
|
+ }
|
|
|
+ return Promise.resolve()
|
|
|
+ }
|
|
|
+ }]}
|
|
|
+ style={{ marginBottom: 0 }}
|
|
|
+ >
|
|
|
+ <TextAideInput isShowAjax={false} placeholder={'请输入' + floating_zone_desc.description} style={{ width: 480 }} maxTextLength={floating_zone_desc.restriction.textRestriction.maxLength} />
|
|
|
+ </Form.Item>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className={style.newSpace}>
|
|
|
+ <div className={style.newSpace_top}>
|
|
|
+ <div className={style.newSpace_title}>按钮文案</div>
|
|
|
+ <Form.Item
|
|
|
+ name={['floatingZone', 'value', 'floatingZoneButtonText']}
|
|
|
+ rules={[{ required: true, message: '请选择按钮文案' }]}
|
|
|
+ style={{ marginBottom: 0 }}
|
|
|
+ >
|
|
|
+ <Select
|
|
|
+ style={{ width: 480 }}
|
|
|
+ showSearch
|
|
|
+ placeholder="请选择按钮文案"
|
|
|
+ optionFilterProp="children"
|
|
|
+ filterOption={(input, option: any) =>
|
|
|
+ (option?.label ?? '').toLowerCase().includes(input.toLowerCase())
|
|
|
+ }
|
|
|
+ options={floatingZoneButtonTextEnumeration}
|
|
|
+ />
|
|
|
+ </Form.Item>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </Card> : (floatingZoneSwitch && floatingZoneType === 'FLOATING_ZONE_TYPE_SINGLE_IMAGE') ? <Card bordered className="cardResetCss newCss" bodyStyle={{ padding: 0 }}>
|
|
|
+ <div className={style.newSpace}>
|
|
|
+ <div className={style.newSpace_top} style={{ alignItems: 'flex-start' }}>
|
|
|
+ <div className={style.newSpace_title}>{floating_zone_single_image_id?.description}</div>
|
|
|
+ <Form.Item
|
|
|
+ rules={[{ required: true, message: '请选择素材!' }]}
|
|
|
+ name={['floatingZone', 'value', 'image']}
|
|
|
+ >
|
|
|
+ <div className={`${styles.box} ${styles.image}`} style={{ width: 300, height: 160 }} onClick={() => {
|
|
|
+ init({ mediaType: 'IMG', cloudSize: [[{ relation: '=', width: floating_zone_single_image_id.restriction.imageRestriction.width, height: floating_zone_single_image_id.restriction.imageRestriction.height }]], maxSize: floating_zone_single_image_id.restriction.imageRestriction.fileSize * 1024 })
|
|
|
+ setMaterialConfig({
|
|
|
+ ...materialConfig,
|
|
|
+ type: 'floatingZoneSingleImage',
|
|
|
+ max: 1,
|
|
|
+ index: 1,
|
|
|
+ adcreativeTemplateId: creativeTemplateId
|
|
|
+ })
|
|
|
+ setTimeout(() => {
|
|
|
+ setSelectVideoVisible(true)
|
|
|
+ }, 100)
|
|
|
+ }}>
|
|
|
+ <p>
|
|
|
+ {image?.floatingZoneSingleImageUrl ? <img src={image?.floatingZoneSingleImageUrl} /> : <>
|
|
|
+ <span>{`推荐尺寸(${floating_zone_single_image_id.restriction.imageRestriction.width} x ${floating_zone_single_image_id.restriction.imageRestriction.height})`}</span>
|
|
|
+ <span>{`${floating_zone_single_image_id.restriction.imageRestriction.fileFormat?.map((str: any) => str?.replace('IMAGE_TYPE_', ''))};小于 ${floating_zone_single_image_id.restriction.imageRestriction.fileSize}KB`}</span>
|
|
|
+ </>}
|
|
|
+ </p>
|
|
|
+ </div>
|
|
|
+ </Form.Item>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </Card> : null}
|
|
|
+ </Form.Item>
|
|
|
+ </>
|
|
|
+ }
|
|
|
+ return null
|
|
|
+ }, [creativeComponents?.floating_zone, floatingZoneSwitch, floatingZoneType, image])
|
|
|
|
|
|
useEffect(() => {
|
|
|
let data = [
|
|
@@ -320,7 +517,7 @@ const CreativeConversionAssistant: React.FC<{ automaticSiteEnabled?: boolean }>
|
|
|
}
|
|
|
}, [cardType])
|
|
|
|
|
|
- if (Object.keys(creativeComponents).some(key => ['text_link', 'action_button', 'show_data'].includes(key))) {
|
|
|
+ if (Object.keys(creativeComponents).some(key => ['text_link', 'action_button', 'show_data', 'floating_zone'].includes(key))) {
|
|
|
return <Card
|
|
|
title={<strong style={{ fontSize: 18 }}>营销组件</strong>}
|
|
|
className="cardResetCss"
|
|
@@ -364,11 +561,44 @@ const CreativeConversionAssistant: React.FC<{ automaticSiteEnabled?: boolean }>
|
|
|
</Form.Item>
|
|
|
</div>
|
|
|
</div>
|
|
|
-
|
|
|
</Form.Item>}
|
|
|
{textLinkContent}
|
|
|
{actionButtonContent}
|
|
|
{showDataContent}
|
|
|
+ {floatingZoneContent}
|
|
|
+
|
|
|
+ {/* 选择视频素材 */}
|
|
|
+ {selectVideoVisible && <SelectCloud
|
|
|
+ visible={selectVideoVisible}
|
|
|
+ onClose={() => setSelectVideoVisible(false)}
|
|
|
+ sliderImgContent={materialConfig.type === 'floatingZoneSingleImage' ? image?.floatingZoneSingleImageUrl ? [{ url: image.floatingZoneSingleImageUrl }] : undefined : image?.floatingZoneImageUrl ? [{ url: image.floatingZoneImageUrl }] : undefined}
|
|
|
+ onChange={(content: any) => {
|
|
|
+ if (content.length > 0) {
|
|
|
+ if (materialConfig.type === 'floatingZoneSingleImage') {
|
|
|
+ form.setFieldsValue({
|
|
|
+ floatingZone: {
|
|
|
+ ...floatingZone,
|
|
|
+ value: {
|
|
|
+ ...floatingZone?.value,
|
|
|
+ image: { floatingZoneSingleImageId: content[0]?.id, floatingZoneSingleImageUrl: content[0]?.url, floatingZoneSingleImageMaterialType: 0 }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ form.setFieldsValue({
|
|
|
+ floatingZone: {
|
|
|
+ ...floatingZone,
|
|
|
+ value: {
|
|
|
+ ...floatingZone?.value,
|
|
|
+ image: { floatingZoneImageId: content[0]?.id, floatingZoneImageUrl: content[0]?.url, floatingZoneImageMaterialType: 0 }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ setSelectVideoVisible(false)
|
|
|
+ }}
|
|
|
+ />}
|
|
|
</Card>
|
|
|
} else {
|
|
|
return null
|