shenwu 2 år sedan
förälder
incheckning
f2227f0f38

+ 28 - 34
src/pages/launchSystemNew/launchManage/localAd/adenum.ts

@@ -1,12 +1,14 @@
+import { AdcreativeTemplate } from '@/services/launchAdq';
 
 export const adcreativeTemplateList = [
   // 720
   {
-    adcreative_sample_image://创意规格示意图链接
+    //创意规格示意图链接
+    adcreative_sample_image:
       'http://qzonestyle.gtimg.cn/gdt_ui_proj/dist/gdt/imgbox/creative_template_720.svg',
-    adcreative_template_appellation: '横版视频 16:9',//创意形式名称
-    adcreative_template_id: 720,//创意形式 id
-    adcreative_template_style: '视频',//创意形式类型
+    adcreative_template_appellation: '横版视频 16:9', //创意形式名称
+    adcreative_template_id: 720, //创意形式 id
+    adcreative_template_style: '视频', //创意形式类型
     xd_show: true,
     sp_show: true,
     adcreativeElements: {
@@ -14,8 +16,8 @@ export const adcreativeTemplateList = [
       video:
         '视频比例(宽:高):9:16,最小尺寸(宽×高):720*1280,大小:不超过102400 KB,时长:5~30 s,格式:*.mp4|*.avi|*.mov;',
       end_page: {
-        end_page_type:'视频结束页类型',
-        end_page_desc:'结束页文案,字数:1~12;'
+        end_page_type: '视频结束页类型',
+        end_page_desc: '结束页文案,字数:1~12;',
       },
     },
     adcreative_attributes: [
@@ -255,7 +257,8 @@ export const adcreativeTemplateList = [
         struct_property: [],
       },
     ],
-    landing_page_config: {//支持的落地页类型
+    landing_page_config: {
+      //支持的落地页类型
       required: false,
       support_page_type_list: [
         {
@@ -331,17 +334,19 @@ export const adcreativeTemplateList = [
         },
       ],
     },
-    promoted_object_type: 'PROMOTED_OBJECT_TYPE_WECHAT_OFFICIAL_ACCOUNT',//推广目标类型
-    site_set: ['SITE_SET_MOMENTS', 'SITE_SET_WECHAT'],//投放版位集合
-    support_bid_mode_list: ['BID_MODE_CPM', 'BID_MODE_OCPM'],//支持的出价方式
-    support_billing_spec_list: [//支持的计费信息
+    promoted_object_type: 'PROMOTED_OBJECT_TYPE_WECHAT_OFFICIAL_ACCOUNT', //推广目标类型
+    site_set: ['SITE_SET_MOMENTS', 'SITE_SET_WECHAT'], //投放版位集合
+    support_bid_mode_list: ['BID_MODE_CPM', 'BID_MODE_OCPM'], //支持的出价方式
+    support_billing_spec_list: [
+      //支持的计费信息
       {
-        billing_event: 'BILLINGEVENT_IMPRESSION',//计费方式
-        max_price: 99900,//最高出价,单位分
-        min_price: 150,//最低出价,单位分
+        billing_event: 'BILLINGEVENT_IMPRESSION', //计费方式
+        max_price: 99900, //最高出价,单位分
+        min_price: 150, //最低出价,单位分
       },
     ],
-    support_dynamic_ability_spec_list: {//
+    support_dynamic_ability_spec_list: {
+      //
       dynamic_ability_type: ['DYNAMIC_TYPE_DYNAMIC_CREATIVE'],
       product_item_display_quantity: [],
     },
@@ -6582,22 +6587,11 @@ export const adcreativeTemplateList = [
   },
 ];
 
-
-
-//创意关联关系
-export const adcreativeTemplateListNew=[
-  // 微信公众号
-  {
-    promotedObjectType:'PROMOTED_OBJECT_TYPE_WECHAT_OFFICIAL_ACCOUNT',//推广目标
-    siteSet:{
-      SITE_SET_MOMENTS:[
-        {
-          adcreativeTemplateId:721,
-        }
-      ],//微信朋友圈
-      SITE_SET_WECHAT:[
-
-      ],//微信公众号与小程序
-    }
-  }
-]
+/**即将下线创意形式*/
+const outAdcreativeTemplateIdEnum = [
+  927, 876, 878, 716, 960, 998, 484, 616, 450, 588, 955, 730, 961, 717, 1030, 567, 608, 929, 538,
+  559, 1465, 1515, 877, 589, 452, 957, 560, 1480, 1064, 968, 254,
+];
+export function outAdcreativeTemplateIdFun(id: number) {
+  return outAdcreativeTemplateIdEnum.every((i) => i !== id);
+}

+ 40 - 1
src/pages/launchSystemNew/launchManage/localAd/creative/index.less

@@ -14,4 +14,43 @@
     align-items: center;
     justify-content: space-around;
     flex-flow: column;
-}
+}
+
+.video{
+  
+}
+.box {
+    width: 60%;
+    height: 200px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    background-color: #f5f7fa;
+    flex-direction: column;
+    color: rgba(0,0,0,.3);
+    border-radius: 5px;
+    >p{
+        display: flex;
+        align-items: center;
+        flex-flow: column;
+        font-size: 10px;
+        cursor: pointer;
+    }
+}
+
+.image_list{
+    flex-flow: row wrap;
+    background-color: transparent;
+    height:auto;
+    justify-content: flex-start;
+    >p{
+        width: 33%;
+        background-color: #f5f7fa;
+        height: 150px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        border: 1px solid #e6e8ed;
+        margin: 0;
+    }
+}

+ 255 - 161
src/pages/launchSystemNew/launchManage/localAd/creative/modal.tsx

@@ -1,9 +1,13 @@
 import React, { useCallback, useEffect, useMemo, useState } from 'react'
-import { Modal, Form, Input, Divider, Select, Radio, DatePicker, Switch } from 'antd'
+import { Modal, Form, Input, Divider, Select, Radio, DatePicker, Switch, Spin } from 'antd'
 import { SiteSetEnum, PromotedObjectType } from '@/services/launchAdq/enum'
 import { ModalConfig } from '.'
 import styles from './index.less'
-import { adcreativeTemplateList } from '../adenum';
+import { outAdcreativeTemplateIdFun } from '../adenum';
+import { useAjax } from '@/Hook/useAjax'
+import { get_adcreative_template, get_adcreative_template_list } from '@/services/launchAdq/global'
+import { AdcreativeTemplate, AdcreativeTemplateList } from '@/services/launchAdq'
+import { mySet } from '@/utils/arrFn'
 interface Props {
     title?: string,
     visible: boolean,
@@ -14,6 +18,13 @@ interface Props {
 /**创意模板*/
 function CreativeModal(props: Props) {
     let { visible, title, confirmLoading, PupFn, callback } = props
+    // 请求
+    const getAdcreativeTemplate = useAjax((params) => get_adcreative_template(params))
+    const getAdcreativeTemplateList = useAjax((params) => get_adcreative_template_list(params))
+    // 变量
+    const [adcreative_template, set_adcreative_template] = useState<AdcreativeTemplate>()
+    const [adcreative_template_list, set_adcreative_template_list] = useState<AdcreativeTemplateList[]>([])
+
     const [form] = Form.useForm();
     const [pupState, setPupState] = useState({
         kp_show: false,
@@ -41,32 +52,69 @@ function CreativeModal(props: Props) {
         })
         // PupFn({ visible: false })
     }, [form])
-    //获取对应创意形式列表
-    const adcreativeTemplateArr = useMemo(() => {
-        if (siteSet?.length > 0 && promotedObjectType && adcreativeElementsType) {
-            let arr = adcreativeTemplateList.filter(item => {
-                if (item.adcreative_template_style === adcreativeElementsType && item.promoted_object_type === promotedObjectType && siteSet.some((s: string) => item.site_set.some(i => s === i))) {
-                    return item
-                }
-                return null
+    // 获取创意形式列表
+    useEffect(() => {
+        if (siteSet?.length > 0 && promotedObjectType) {
+            getAdcreativeTemplateList.run({
+                siteSet,
+                promotedObjectType,
+                campaignType: 'CAMPAIGN_TYPE_NORMAL',
+            }).then(res => {
+                let newArr: any = []
+                // 过滤掉相同的和即将下线的
+                Object.values(res).forEach((arr: any) => {
+                    Array.isArray(arr) && arr?.forEach((item: any) => {
+                        if (newArr.length > 0) {
+                            if (outAdcreativeTemplateIdFun(item.adcreativeTemplateId) && newArr.every((i: { adcreativeTemplateId: any }) => i.adcreativeTemplateId !== item.adcreativeTemplateId)) {
+                                newArr.push(item)
+                            } else {
+                                // 找出通用创意
+                                newArr = newArr?.map((arr: { adcreativeTemplateId: any }) => {
+                                    if (arr.adcreativeTemplateId === item.adcreativeTemplateId) {
+                                        return { ...arr, isGeneral: true }
+                                    }
+                                    return arr
+                                })
+                            }
+                        } else {
+                            if (outAdcreativeTemplateIdFun(item.adcreativeTemplateId)) {
+                                newArr.push(item)
+                            }
+                        }
+                    })
+                })
+                set_adcreative_template_list(newArr)
             })
-            return arr
         }
-        return null
-    }, [siteSet, promotedObjectType, adcreativeElementsType])
+    }, [siteSet, promotedObjectType, form])
+    // 获取创意形式详情
+    useEffect(() => {
+        // CAMPAIGN_TYPE_NORMAL
+        if (siteSet?.length > 0 && promotedObjectType && adcreativeTemplateId) {
+            if (adcreativeTemplateId) {
+                getAdcreativeTemplate.run({
+                    siteSet,
+                    promotedObjectType,
+                    adcreativeTemplateId
+                }).then(res => {
+                    set_adcreative_template(res[0])
+                })
+            }
+        }
+    }, [siteSet, promotedObjectType, adcreativeTemplateId])
     // 获取对应落地页按钮
     const pageTypeList = useMemo(() => {
         if (adcreativeTemplateId) {
-            let arr: any = adcreativeTemplateArr?.filter(item => item.adcreative_template_id === adcreativeTemplateId)[0]?.landing_page_config.support_page_type_list
+            let arr: any = adcreative_template?.landingPageConfig?.supportPageTypeList
             return arr
         }
         return null
 
-    }, [adcreativeTemplateId, adcreativeTemplateArr])
+    }, [adcreativeTemplateId, adcreative_template])
     // 获取对应行动按钮数据
     const linkNameList = useMemo(() => {
         if (pageType) {
-            let arr = (pageTypeList?.filter((item: { page_type: any; }) => item.page_type === pageType)[0] as any)?.support_link_name_type?.list
+            let arr = (pageTypeList?.filter((item: { pageType: any; }) => item.pageType === pageType)[0] as any)?.supportLinkNameType?.list
             return arr
         }
         return null
@@ -74,89 +122,80 @@ function CreativeModal(props: Props) {
     // 跳转落地页
     const linkPageList = useMemo(() => {
         if (pageType) {
-            let arr = (pageTypeList?.filter((item: { page_type: any; }) => item.page_type === pageType)[0] as any)?.support_link_page_type?.list
+            let arr = (pageTypeList?.filter((item: { pageType: any; }) => item.pageType === pageType)[0] as any)?.supportLinkPageType?.list
             return arr
         }
         return null
     }, [pageType, pageTypeList])
-
-
-    // 切换形式类型
+    // 切换创意形式默认选中第一个
     useEffect(() => {
-        //默认选第一个选项
-        if (Array.isArray(adcreativeTemplateArr)) {
-            let values = {}
-            let adcreativeTemplateId = adcreativeTemplateArr[0]?.adcreative_template_id
-            let pageList = adcreativeTemplateArr?.filter(item => item.adcreative_template_id === adcreativeTemplateArr[0]?.adcreative_template_id)[0]?.landing_page_config.support_page_type_list
-            let pageType = pageList[0]?.page_type
-            //卡片组件存在
-            if (adcreativeTemplateArr[0]?.kp_show) {
-
-            }
-            //行动按钮组件存在
-            if (adcreativeTemplateArr[0]?.xd_show) {
-                let linkNameList = (pageList?.filter((item: { page_type: any; }) => item.page_type === pageType)[0] as any)?.support_link_name_type?.list
-                let linkPageList = (pageList?.filter((item: { page_type: any; }) => item.page_type === pageType)[0] as any)?.support_link_page_type?.list
-                let linkNameType = linkNameList[0]?.link_name_type
-                let linkPageType = linkPageList[0]?.link_page_type
-                values = { ...values, linkNameType, linkPageType }
-            }
-
-            //标签组件
-            if (adcreativeTemplateArr[0]?.bq_show) {
+        // 设置默认选中第一个
+        if (adcreativeElementsType && adcreative_template_list?.length > 0) {
+            let adcreativeTemplateIdArr = adcreative_template_list?.filter(item => item.adcreativeTemplateStyle === adcreativeElementsType)
+            form.setFieldsValue({ adcreativeTemplateId: adcreativeTemplateIdArr[0].adcreativeTemplateId })
+        }
+    }, [adcreativeElementsType, adcreative_template_list])
 
-            }
-            //视频结束页组件
-            if (adcreativeTemplateArr[0]?.sp_show) {
 
-            }
-            values = { ...values, adcreativeTemplateId, pageType }
-            form.setFieldsValue(values)
-        }
-    }, [adcreativeTemplateArr, form])
     //每次选中创意设置该展示的界面
     useEffect(() => {
-        if (adcreativeTemplateId && Array.isArray(adcreativeTemplateArr)) {
-            let adcreativeTemplate = adcreativeTemplateArr?.filter(item => item.adcreative_template_id === adcreativeTemplateId)[0]
+        let states = {
+            kp_show: false,
+            xd_show: true,
+            sj_show: false,
+            bq_show: false,
+            sp_show: false
+        }
+        let values: any = { pageType: 'PAGE_TYPE_CANVAS_WECHAT', }
+        if (adcreative_template) {
+            let pageList = adcreative_template?.landingPageConfig?.supportPageTypeList
+            let pageType = pageList?.length ? pageList[0]?.pageType : null
             //数据展示组件
-            if (adcreativeTemplate?.sj_show) {
-                let arr = (adcreativeTemplate.adcreative_attributes as any)?.filter((item: { name: string; }) => item.name === 'conversion_data_type' || item.name === 'conversion_target_type')
+            if (adcreative_template.adcreativeAttributes.some(item => item.name === 'conversion_data_type' || item.name === 'conversion_target_type')) {
+                let arr = adcreative_template.adcreativeAttributes?.filter((item: { name: string; }) => item.name === 'conversion_data_type' || item.name === 'conversion_target_type')
                 let newObj: any = {}
-                arr.forEach((item: { name: string | number; property_detail: { enum_detail: { enumeration: any[]; }; }; }) => {
-                    newObj[item.name] = item.property_detail.enum_detail.enumeration.filter((i: { category: any; }) => !i.category)
+                arr.forEach((item) => {
+                    let arr: any[] = mySet(item.propertyDetail.enumDetail.enumeration)
+                    newObj[item.name] = arr
                 })
                 setConversionList(newObj)
-                form.setFieldsValue({
-                    conversionDataType: newObj.conversion_data_type[0].value,
-                    conversionTargetType: newObj.conversion_target_type[0].value
-                })
+
+                states = { ...states, sj_show: true }
+                values = { ...values, conversionDataType: newObj.conversion_data_type[0].value, conversionTargetType: newObj.conversion_target_type[0].value }
             }
-            setPupState({
-                kp_show: !!adcreativeTemplate?.kp_show,//卡片组件
-                xd_show: !!adcreativeTemplate?.xd_show,//行动按钮组件
-                sj_show: !!adcreativeTemplate?.sj_show,//数据展示组件
-                bq_show: !!adcreativeTemplate?.bq_show,//标签组件
-                sp_show: !!adcreativeTemplate?.sp_show//视频结束页组件
-            })
+            //行动按钮组件存在
+            if (states.xd_show) {
+                let linkNameList = (pageList?.filter((item: { pageType: any; }) => item.pageType === pageType)[0] as any)?.supportLinkNameType?.list
+                let linkPageList = (pageList?.filter((item: { pageType: any; }) => item.pageType === pageType)[0] as any)?.supportLinkPageType?.list
+                if (linkNameList) {
+                    let linkNameType = linkNameList[0]?.linkNameType
+                    let linkPageType = linkPageList[0]?.linkPageType
+                    values = { ...values, linkNameType, linkPageType }
+                } else {
+                    states = { ...states, xd_show: false }
+                }
+            }
+            setPupState(states)
+            form.setFieldsValue(values)
         }
-    }, [adcreativeTemplateArr, adcreativeTemplateId])
-
+    }, [adcreative_template])
     return <Modal
         visible={visible}
         title={title + '创意'}
         onCancel={() => { PupFn({ visible: false }) }}
         onOk={handleOk}
-        width={900}
+        width={1200}
         confirmLoading={confirmLoading}
     >
         <Form
             form={form}
-            labelCol={{ span: 3 }}
+            labelCol={{ span: 5 }}
+            labelWrap={true}
             initialValues={
                 {
                     adcreativeElementsType: '视频',
                     promotedObjectType: 'PROMOTED_OBJECT_TYPE_WECHAT_OFFICIAL_ACCOUNT',
-                    siteSet: ['SITE_SET_MOMENTS'],
+                    siteSet: ['SITE_SET_MOMENTS', 'SITE_SET_WECHAT'],
                     actionBtn: true,//行动按钮
                     dataShow: true,//数据展示
                 }
@@ -199,113 +238,166 @@ function CreativeModal(props: Props) {
                     <Radio.Button value="图片">图片</Radio.Button>
                 </Radio.Group>
             </Form.Item>
-            <Form.Item style={{ marginLeft: 107 }} name='adcreativeTemplateId'>
-                <Radio.Group className={styles.adcreative_template}>
-                    {
-                        adcreativeTemplateArr?.map((item, index) => {
-                            return <Radio.Button value={item.adcreative_template_id} key={item.adcreative_template_id}>
-                                <div className={styles.adcreative_template_item}>
-                                    <img src={item.adcreative_sample_image} />
-                                    <span>{item.adcreative_template_appellation} </span>
-                                </div>
-                            </Radio.Button>
-                        })
-                    }
-                </Radio.Group>
-            </Form.Item>
-            {/* ============================================================创意内容============================================================= */}
-            <Divider orientation='center'>创意内容</Divider>
-             {/* ============================================================素材============================================================= */}
-             
-            {/* ============================================================落地页============================================================= */}
-            <Form.Item label={<strong>落地页</strong>} name='pageType'>
-                <Radio.Group>
-                    {
-                        pageTypeList?.map((item: { page_type: string | number | null | undefined; description: boolean | React.ReactChild | React.ReactFragment | React.ReactPortal | null | undefined; }, index: number) => {
-                            if (!pageType && index === 0) {
 
-                            }
-                            return <Radio.Button value={item.page_type} key={item.page_type}>{item.description}</Radio.Button>
-                        })
-                    }
-                </Radio.Group>
-            </Form.Item>
-            {/* ============================================================行动按钮============================================================= */}
-            {
-                pupState.xd_show && <Form.Item label={<strong>行动按钮</strong>} name='actionBtn' valuePropName="checked">
-                    <Switch checkedChildren="开启" unCheckedChildren="关闭" />
-                </Form.Item>
-            }
-            {
-                actionBtn && <>
-                    <div style={{ display: 'flex' }}>
-                        <p style={{ marginBottom: 5, marginLeft: 107 }}><strong style={{ marginRight: 20 }}>按钮文案</strong></p>
-                        <Form.Item name='linkNameType'>
-                            <Select style={{ width: 200 }} showSearch filterOption={(input, option) =>
-                                (option!.children as unknown as string).toLowerCase().includes(input.toLowerCase())
-                            } allowClear>
-                                {
-                                    linkNameList?.map((item: { link_name_type: string; description: string; }, index: number) => {
-                                        return <Select.Option value={item.link_name_type} key={item.link_name_type}>{item.description}</Select.Option>
-                                    })
-                                }
-                            </Select>
-                        </Form.Item>
-                    </div>
-                    <div style={{ display: 'flex' }}>
-                        <p style={{ marginBottom: 5, marginLeft: 107 }}><strong style={{ marginRight: 20 }}>跳转落地页</strong></p>
-                        <Form.Item name='linkPageType'>
-                            <Radio.Group>
-                                {
-                                    linkPageList?.map((item: { link_page_type: string; description: string; }, index: number) => {
-                                        return <Radio.Button value={item.link_page_type} key={item.link_page_type}>{item.description}</Radio.Button>
-                                    })
-                                }
-                            </Radio.Group>
-                        </Form.Item>
-                    </div>
-                </>
-            }
-            {/* ============================================================数据展示============================================================= */}
-            {pupState.sj_show && <Form.Item label={<strong>数据展示</strong>} name='dataShow' valuePropName="checked">
-                <Switch checkedChildren="开启" unCheckedChildren="关闭" />
-            </Form.Item>}
             {
-                dataShow && <>
-                    <div style={{ display: 'flex' }}>
-                        <p style={{ marginBottom: 5, marginLeft: 107 }}><strong style={{ marginRight: 20 }}>数据类型</strong></p>
-                        <Form.Item name='conversionDataType'>
-                            <Radio.Group>
+                getAdcreativeTemplateList?.loading ? <Spin tip="Loading..." style={{ width: '100%' }}></Spin> :
+                    <>
+                        <Form.Item style={{ marginLeft: 177 }} name='adcreativeTemplateId'>
+                            <Radio.Group className={styles.adcreative_template}>
                                 {
-                                    conversionList?.conversion_data_type?.map((item: { value: string; description: string; }, index: number) => {
-                                        return <Radio.Button value={item.value} key={item.value}>{item.description}</Radio.Button>
+                                    adcreative_template_list?.filter(item => item.adcreativeTemplateStyle === adcreativeElementsType)?.map((item: any) => {
+                                        return <Radio.Button value={item.adcreativeTemplateId} key={item.adcreativeTemplateId}>
+                                            <div className={styles.adcreative_template_item}>
+                                                {item.isGeneral && <span style={{ color: '#4080ff', fontSize: 10 }}>所选版位通投</span>}
+                                                <img src={item.adcreativeSampleImage} />
+                                                <span>{item.adcreativeTemplateAppellation} </span>
+                                            </div>
+                                        </Radio.Button>
                                     })
                                 }
                             </Radio.Group>
                         </Form.Item>
-                    </div>
-                    {conversionDataType === 'CONVERSION_DATA_ADMETRIC' && <div style={{ display: 'flex' }}>
-                        <p style={{ marginBottom: 5, marginLeft: 107 }}><strong style={{ marginRight: 20 }}>转化行为</strong></p>
-                        <Form.Item name='conversionTargetType'>
+                        {/* ============================================================创意内容============================================================= */}
+                        <Divider orientation='center'>创意内容</Divider>
+                        {/* ============================================================素材============================================================= */}
+                        {/* 优先展示视频或图片 */}
+                        {
+                            adcreative_template?.adcreativeElements?.filter(item => item.required && item.name === 'image_list' || item.name === 'short_video1' || item.name === 'video' || item.name === 'image').map(item => {
+                                return <Form.Item label={<strong>{item.description}</strong>} name={item.name} rules={[{ required: true, message: '请选择素材!' }]}>
+                                    {
+                                       ( item.name === 'short_video1'||item.name === 'video' )&& <div className={`${styles.box} ${styles.video}`}>
+                                            <p>
+                                                <span>{`推荐尺寸(${item.restriction.videoRestriction.minWidth} x ${item.restriction.videoRestriction.minHeight})`}</span>
+                                                <span>{`${item.restriction.videoRestriction.fileFormat?.map(str => str?.replace('MEDIA_TYPE_', ''))};< ${item.restriction.videoRestriction.fileSize / 1024}M;时长 ≥ ${item.restriction.videoRestriction.minDuration}s,≤ ${item.restriction.videoRestriction.maxDuration}s,必须带有声音`}</span>
+                                            </p>
+                                        </div>
+                                    }
+                                    {
+                                        item.name === 'image' && <div className={`${styles.box} ${styles.image}`}>
+                                        <p>
+                                            <span>{`推荐尺寸(${item.restriction.imageRestriction.width} x ${item.restriction.imageRestriction.height})`}</span>
+                                            <span>{`${item.restriction.imageRestriction.fileFormat?.map(str => str?.replace('IMAGE_TYPE_', ''))};小于 ${item.restriction.imageRestriction.fileSize}KB`}</span>
+                                        </p>
+                                    </div>
+                                    }
+                                     {
+                                        item.name === 'image_list' && <div className={`${styles.box} ${item.arrayProperty.maxNumber >= 3 ?styles.image_list : styles.image}`}>
+                                            {
+                                                Array(item.arrayProperty.maxNumber).fill('').map((arr,index)=>{
+                                                    return <p key={index}>
+                                                    <span>{`推荐尺寸(${item.restriction.imageRestriction.width} x ${item.restriction.imageRestriction.height})`}</span>
+                                                    <span>{`${item.restriction.imageRestriction.fileFormat?.map(str => str?.replace('IMAGE_TYPE_', ''))};小于 ${item.restriction.imageRestriction.fileSize}KB`}</span>
+                                                </p>
+                                                })
+                                            }
+                                    </div>
+                                    }
+                                </Form.Item>
+                            })
+                        }
+                        {/* 标题 */}
+                        {
+                            adcreative_template?.adcreativeElements?.filter(item => item.name === 'title').map(item => {
+                                return <Form.Item label={<strong>{item.description}(选填)</strong>} name={item.name} rules={[{ pattern: RegExp(item.restriction.textRestriction.textPattern), message: '请输入正确的' + item.description }]}>
+                                    <Input placeholder={'请输入' + item.description} style={{ width: 500 }} />
+                                </Form.Item>
+                            })
+                        }
+                        {//过滤了不必传和品牌名称,品牌标识图(外部传)短视频结构(组装使用)
+                            // adcreative_template?.adcreativeElements?.filter(item => item.required && item.name !== 'brand_name' && item.name !== 'brand_img' && item.name !== 'short_video_struct' && item.name !== 'image_list' && item.name !== 'short_video1' && item.name !== 'video' ).map(item => {
+                            adcreative_template?.adcreativeElements?.filter(item => item.required && item.name === 'description').map(item => {
+                                return <Form.Item label={<strong>{item.description}</strong>} name={item.name} rules={[{ required: true, pattern: RegExp(item.restriction.textRestriction.textPattern), message: '请输入正确的' + item.description }]}>
+                                    <Input placeholder={'请输入' + item.description} style={{ width: 500 }} />
+                                </Form.Item>
+                            })
+                        }
+
+                        {/* ============================================================落地页============================================================= */}
+                        <Form.Item label={<strong>落地页</strong>} name='pageType'>
                             <Radio.Group>
                                 {
-                                    conversionList?.conversion_target_type?.map((item: { value: string; description: string; }, index: number) => {
-                                        return <Radio.Button value={item.value} key={item.value}>{item.description}</Radio.Button>
+                                    pageTypeList?.map((item: any) => {
+                                        return <Radio.Button value={item.pageType} key={item.pageType} disabled={!item.description.includes('微信原生推广页')}>{item.description.includes('微信原生推广页') ? '微信原生推广页' : item.description}</Radio.Button>
                                     })
                                 }
                             </Radio.Group>
                         </Form.Item>
-                    </div>}
-                </>
-            }
-            {/* ============================================================视频结束页============================================================= */}
-            {/* {pupState.sp_show && <Form.Item label={<strong>视频结束页</strong>} name='videoOver' valuePropName="checked">
+                        {/* ============================================================行动按钮============================================================= */}
+                        {
+                            pupState.xd_show && <Form.Item label={<strong>行动按钮</strong>} name='actionBtn' valuePropName="checked">
+                                <Switch checkedChildren="开启" unCheckedChildren="关闭" />
+                            </Form.Item>
+                        }
+                        {
+                            actionBtn && <>
+                                <div style={{ display: 'flex' }}>
+                                    <p style={{ marginBottom: 5, marginLeft: 177 }}><strong style={{ marginRight: 20 }}>按钮文案</strong></p>
+                                    <Form.Item name='linkNameType'>
+                                        <Select style={{ width: 200 }} showSearch filterOption={(input, option) =>
+                                            (option!.children as unknown as string).toLowerCase().includes(input.toLowerCase())
+                                        } allowClear>
+                                            {
+                                                linkNameList?.map((item: any) => {
+                                                    return <Select.Option value={item.linkNameType} key={item.linkNameType}>{item.description}</Select.Option>
+                                                })
+                                            }
+                                        </Select>
+                                    </Form.Item>
+                                </div>
+                                <div style={{ display: 'flex' }}>
+                                    <p style={{ marginBottom: 5, marginLeft: 177 }}><strong style={{ marginRight: 20 }}>跳转落地页</strong></p>
+                                    <Form.Item name='linkPageType'>
+                                        <Radio.Group>
+                                            {
+                                                linkPageList?.map((item: { linkPageType: string; description: string; }, index: number) => {
+                                                    return <Radio.Button value={item.linkPageType} key={item.linkPageType}>{item.description}</Radio.Button>
+                                                })
+                                            }
+                                        </Radio.Group>
+                                    </Form.Item>
+                                </div>
+                            </>
+                        }
+                        {/* ============================================================数据展示============================================================= */}
+                        {pupState.sj_show && <Form.Item label={<strong>数据展示</strong>} name='dataShow' valuePropName="checked">
+                            <Switch checkedChildren="开启" unCheckedChildren="关闭" />
+                        </Form.Item>}
+                        {
+                            dataShow && <>
+                                <div style={{ display: 'flex' }}>
+                                    <p style={{ marginBottom: 5, marginLeft: 177 }}><strong style={{ marginRight: 20 }}>数据类型</strong></p>
+                                    <Form.Item name='conversionDataType'>
+                                        <Radio.Group>
+                                            {
+                                                conversionList?.conversion_data_type?.map((item: { value: string; description: string; }, index: number) => {
+                                                    return <Radio.Button value={item.value} key={item.value}>{item.description}</Radio.Button>
+                                                })
+                                            }
+                                        </Radio.Group>
+                                    </Form.Item>
+                                </div>
+                                {conversionDataType === 'CONVERSION_DATA_ADMETRIC' && <div style={{ display: 'flex' }}>
+                                    <p style={{ marginBottom: 5, marginLeft: 177 }}><strong style={{ marginRight: 20 }}>转化行为</strong></p>
+                                    <Form.Item name='conversionTargetType'>
+                                        <Radio.Group>
+                                            {
+                                                conversionList?.conversion_target_type?.map((item: { value: string; description: string; }, index: number) => {
+                                                    return <Radio.Button value={item.value} key={item.value}>{item.description}</Radio.Button>
+                                                })
+                                            }
+                                        </Radio.Group>
+                                    </Form.Item>
+                                </div>}
+                            </>
+                        }
+                        {/* ============================================================视频结束页============================================================= */}
+                        {/* {pupState.sp_show && <Form.Item label={<strong>视频结束页</strong>} name='videoOver' valuePropName="checked">
                 <Switch checkedChildren="开启" unCheckedChildren="关闭" />
             </Form.Item>}
             {
                 videoOver && <>
                     <div style={{ display: 'flex' }}>
-                        <p style={{ marginBottom: 5, marginLeft: 107 }}><strong style={{ marginRight: 20 }}>视频结束页类型</strong></p>
+                        <p style={{ marginBottom: 5, marginLeft: 177 }}><strong style={{ marginRight: 20 }}>视频结束页类型</strong></p>
                         <Form.Item name='linkNameType'>
                             <Select style={{ width: 200 }} showSearch filterOption={(input, option) =>
                                 (option!.children as unknown as string).toLowerCase().includes(input.toLowerCase())
@@ -319,13 +411,15 @@ function CreativeModal(props: Props) {
                         </Form.Item>
                     </div>
                     <div style={{ display: 'flex' }}>
-                        <p style={{ marginBottom: 5, marginLeft: 107 }}><strong style={{ marginRight: 20 }}>结束文案</strong></p>
+                        <p style={{ marginBottom: 5, marginLeft: 177 }}><strong style={{ marginRight: 20 }}>结束文案</strong></p>
                         <Form.Item name='linkPageType'>
                             <Input placeholder='请输入结束页文案'/>
                         </Form.Item>
                     </div>
                 </>
             }*/}
+                    </>
+            }
         </Form>
     </Modal >
 }

+ 0 - 4
src/services/launchAdq/enum.ts

@@ -245,8 +245,4 @@ export enum WechatAdBehaviorEnum{
   WECHAT_MOMENTS_AD_LIKE='曾对你的朋友圈广告感兴趣',
   MINI_GAME_WECHAT_REGISTERED='已关注过你的公众号'
  }
-/**创意形式*/
-export enum  AdcreativeEnum{
-
-}
 

+ 20 - 0
src/services/launchAdq/global.ts

@@ -19,4 +19,24 @@ export async function getTagsList(params:any){
         method:'POST',
         data:params
     })
+}
+/**
+ * 创意形式详细信息
+ * */ 
+
+ export async function get_adcreative_template(params:any){
+    return request(api+`/adq/launch/tools/adcreative/template`,{
+        method:'POST',
+        data:params
+    })
+}
+/**
+ * 创意形式列表信息
+ * */ 
+
+ export async function get_adcreative_template_list(params:any){
+    return request(api+`/adq/launch/tools/adcreative/template/list`,{
+        method:'POST',
+        data:params
+    })
 }

+ 148 - 93
src/services/launchAdq/index.d.ts

@@ -264,7 +264,7 @@ export interface FloatingZone {
 export interface WegameInfoSpec {
   wegameInfoSwitch: boolean;
 }
-/**落地页信息,根据不同 promoted_object_type 和 page_type,要求的 page_spec 信息不同*/
+/**落地页信息,根据不同 promotedObjectType 和 page_type,要求的 page_spec 信息不同*/
 export interface PageSpec {
   pageId: number; //落地页 id
   pageUrl: string; //落地页 url
@@ -289,7 +289,7 @@ export interface PageSpec {
     };
   };
 }
-/**文字链跳转信息,根据不同 promoted_object_type 和 page_type、link_page_type,要求的 link_page_spec 信息不同*/
+/**文字链跳转信息,根据不同 promotedObjectType 和 page_type、link_page_type,要求的 link_page_spec 信息不同*/
 export interface LinkPageSpec {
   pageId: number; //	落地页 id
   pageUrl: string; //落地页 url
@@ -358,10 +358,10 @@ export interface AndroidQuickAppSpec {
 export interface SysAdcreative {
   adcreativeName: string; //广告创意名称 *
   adcreativeTemplateId: number; //创意形式 id *
-  adcreativeElements: AdcreativeCreativeElementsMp; //创意元素,不同 adcreative_template_id 要求的元素不尽相同 *
+  adcreativeElements: AdcreativeCreativeElementsMp; //创意元素,不同 adcreativeTemplateId 要求的元素不尽相同 *
   promotedObjectType: string; //推广目标类型 *
   pageType: string; //落地页类型 *
-  automaticSiteEnabled: boolean; //是否开启自动版位功能(暂不包含 SITE_SET_WECHAT 和 SITE_SET_MOMENTS),此字段与 site_set 字段至少需要写入一个。
+  automaticSiteEnabled: boolean; //是否开启自动版位功能(暂不包含 SITE_SET_WECHAT 和 SITE_SET_MOMENTS),此字段与 siteSet 字段至少需要写入一个。
   siteSet: Array<string>; //投放版位集合
   pageSpec: PageSpec; //落地页信息
   linkPageType: string; //文字链跳转类型类型
@@ -477,49 +477,73 @@ export interface ListData<T> {
 
 /**==============================================================================创意形式=======================================================================================*/
 /**创意形式列表*/
-export interface AdcreativeTemplateList {}
+export interface AdcreativeTemplateList {
+  /**创意形式 id*/
+  adcreativeTemplateId: number;
+  /**创意形式类型*/
+  adcreativeTemplateStyle: string;
+  /**创意形式名称*/
+  adcreativeTemplateAppellation: string;
+  /**创意规格示意图链接*/
+  adcreativeSampleImage: string;
+  /**推广目标类型*/
+  promotedObjectType: string;
+  /**投放版位集合*/
+  siteSet: string[];
+  /**支持的计费信息*/
+  supportBillingSpecList: {
+    /**计费方式*/
+    billingEvent: string;
+    /**最低出价,单位分*/
+    minPrice: number;
+    /**最高出价,单位分*/
+    maxPrice: number;
+  }[];
+  /**支持的出价方式*/
+  supportBidModeList: string[];
+}
 
 /**创意形式详情*/
 export interface AdcreativeTemplate {
   /**创意形式 id*/
-  adcreative_template_id: number;
+  adcreativeTemplateId: number;
   /**创意形式类型*/
-  adcreative_template_style: string;
+  adcreativeTemplateStyle: string;
   /**创意形式名称*/
-  adcreative_template_appellation: string;
+  adcreativeTemplateAppellation: string;
   /**创意规格示意图链接*/
-  adcreative_sample_image: string;
+  adcreativeSampleImage: string;
   /**推广目标类型*/
-  promoted_object_type: string;
+  promotedObjectType: string;
   /**投放版位集合*/
-  site_set: string[];
+  siteSet: string[];
   /**支持的计费信息*/
-  support_billing_spec_list: {
+  supportBillingSpecList: {
     /**计费方式*/
-    billing_event: string;
+    billingEvent: string;
     /**最低出价,单位分*/
-    min_price: number;
+    minPrice: number;
     /**最高出价,单位分*/
-    max_price: number;
+    maxPrice: number;
   }[];
   /**支持的出价方式*/
-  support_bid_mode_list: string[];
+  supportBidModeList: string[];
   /**广告创意元素列表*/
-  adcreative_elements: {
-    /**广告创意接口要求的 adcreative_elements 结构中的元素字段名,如 image、title 等*/
+  adcreativeElements: {
+    /**广告创意接口要求的 adcreativeElements 结构中的元素字段名,如 image、title 等*/
     name: string;
     /**创意元素类型*/
-    element_type: string;
+    elementType: string;
     /**创意元素传参类型*/
-    field_type: string;
+    fieldType: string;
     /**创意元素是否必填,true 或 false*/
     required: boolean;
     /**该创意元素的描述,如图片、广告文案等*/
     description: string;
     /**创意元素父节点名称,为父节点的 name 字段*/
-    parent_name: string;
+    parentName: string;
     /**广告创意元素枚举值特性*/
-    enum_property: {
+    enumProperty: {
       /**创意元素枚举默认值*/
       default: string;
       /**创意元素枚举可选值数组*/
@@ -531,69 +555,69 @@ export interface AdcreativeTemplate {
       }[];
     };
     /**广告创意元素数组特性*/
-    array_property: {
+    arrayProperty: {
       /**广告创意元素数组个数最小值*/
-      min_number: number;
+      minNumber: number;
       /**广告创意元素数组个数最大值*/
-      max_number: number;
+      maxNumber: number;
     };
     /**广告创意元素结构体特性*/
     struct_property: {
       /**结构体中元素是否互斥,true: 是,仅能使用结构体中的一个元素字段; false: 否*/
-      element_mutual_exclusive: boolean;
+      elementMutualExclusive: boolean;
     };
     /**	广告创意元素需满足的限制条件*/
     restriction: {
-      /**文本需满足的限制条件,仅当 element_type 是 ELEMENT_TYPE_TEXT 时返回*/
-      text_restriction: {
+      /**文本需满足的限制条件,仅当 elementType 是 ELEMENT_TYPE_TEXT 时返回*/
+      textRestriction: {
         /**最小长度,文本类型适用*/
-        min_length: number;
+        minLength: number;
         /**最大长度,文本类型适用*/
-        max_length: number;
+        maxLength: number;
         /**text 的正则表达式*/
-        text_pattern: string;
+        textPattern: RegExp;
       };
-      /**图片需满足的限制条件,仅当 element_type 是 ELEMENT_TYPE_IMAGE_ARRAY 或 ELEMENT_TYPE_IMAGE 时返回*/
-      image_restriction: {
+      /**图片需满足的限制条件,仅当 elementType 是 ELEMENT_TYPE_IMAGE_ARRAY 或 ELEMENT_TYPE_IMAGE 时返回*/
+      imageRestriction: {
         /**	宽度,单位 px,图片适用*/
         width: number;
         /**高度,单位 px,图片适用*/
         height: number;
         /**支持的文件大小最大值,单位 KB,1KB=1024B, 图片、视频适用*/
-        file_size: number;
+        fileSize: number;
         /**支持的图片文件格式数组*/
-        file_format: string[];
+        fileFormat: string[];
       };
-      /**链接需满足的限制条件,仅当 element_type 是 ELEMENT_TYPE_URL 时返回*/
-      url_restriction: {
+      /**链接需满足的限制条件,仅当 elementType 是 ELEMENT_TYPE_URL 时返回*/
+      urlRestriction: {
         /**url 的正则表达式*/
-        url_pattern: string;
+        urlPattern: RegExp;
       };
-      /**	视频需满足的限制条件,仅当 element_type 是 ELEMENT_TYPE_VIDEO 时返回*/
-      video_restriction: {
+      /**	视频需满足的限制条件,仅当 elementType 是 ELEMENT_TYPE_VIDEO 时返回*/
+      videoRestriction: {
         /**宽度*/
         width: number;
         /**高度*/
         height: number;
         /**最小宽度*/
-        min_width: number;
+        minWidth: number;
         /**最小高度*/
-        min_height: number;
+        minHeight: number;
         /**宽比例*/
-        ratio_width: number;
+        ratioWidth: number;
         /**高比例*/
-        ratio_height: number;
+        ratioHeight: number;
         /**支持的文件大小最大值,单位 KB,1KB=1024B, 图片、视频适用*/
-        file_size: number;
+        fileSize: number;
         /**支持的流媒体文件格式数组*/
-        file_format: string[];
+        fileFormat: string[];
         /**最小时长*/
-        min_duration: number;
+        minDuration: number;
         /**最大时长*/
-        max_duration: number;
+        maxDuration: number;
       };
-      /**数值型需满足的限制条件,仅当 element_type 是 ELEMENT_TYPE_INTEGER 时返回*/
-      number_restriction: {
+      /**数值型需满足的限制条件,仅当 elementType 是 ELEMENT_TYPE_INTEGER 时返回*/
+      numberRestriction: {
         /**最小长度*/
         min: number;
         /**最大长度*/
@@ -602,40 +626,71 @@ export interface AdcreativeTemplate {
     };
   }[];
   /**支持的落地页类型*/
-  landing_page_config: {
+  landingPageConfig: {
     /**是否必填*/
     required: boolean;
+    /**支持落地页类型列表*/
+    supportPageTypeList: {
+      /**名称*/
+      pageType: string;
+      /**描述*/
+      description: string;
+      /**文字链跳转类型*/
+      supportLinkNameType: {
+        /**是否必填*/
+        required: boolean;
+        /**文字链跳转类型列表*/
+        list: {
+          /**名称*/
+          linkNameType: string;
+          /**描述*/
+          description: string;
+        }[];
+      };
+      /**文字链支持落地页类型*/
+      supportLinkPageType: {
+        /**是否必填*/
+        required: boolean;
+        /**文字链跳转类型列表*/
+        list: {
+          /**名称*/
+          linkNameType: string;
+          /**描述*/
+          description: string;
+        }[];
+      };
+    }[];
   };
   /**广告创意能力项列表*/
-  adcreative_attributes: {
+  adcreativeAttributes: {
     /**是否必填*/
     required: boolean;
-    /**广告创意接口要求的 adcreative_elements 结构中的元素字段名,如 image、title 等*/
+    /**广告创意接口要求的 adcreativeElements 结构中的元素字段名,如 image、title 等*/
     name: string;
     /**该创意元素的描述,如图片、广告文案等*/
     description: string;
     /**创意元素传参类型*/
-    field_type: string;
+    fieldType: string;
     /**能力项详情*/
-    property_detail: {
-      /**文本需满足的限制条件,仅当 element_type 是 ELEMENT_TYPE_TEXT 时返回*/
-      string_detail: {
+    propertyDetail: {
+      /**文本需满足的限制条件,仅当 elementType 是 ELEMENT_TYPE_TEXT 时返回*/
+      stringDetail: {
         /**最小长度,文本类型适用*/
-        min_length: number;
+        minLength: number;
         /**最大长度,文本类型适用*/
-        max_length: number;
+        maxLength: number;
         /**text 的正则表达式*/
-        text_pattern: string;
+        textPattern: RegExp;
       };
-      /**数值型需满足的限制条件,仅当 element_type 是 ELEMENT_TYPE_INTEGER 时返回*/
-      integer_detail: {
+      /**数值型需满足的限制条件,仅当 elementType 是 ELEMENT_TYPE_INTEGER 时返回*/
+      integerDetail: {
         /**最小长度,文本类型适用*/
         min: number;
         /**最大长度,文本类型适用*/
         max: number;
       };
       /**广告创意元素枚举值特性*/
-      enum_detail: {
+      enumDetail: {
         /**创意元素枚举默认值*/
         default: string;
         /**创意元素枚举可选值数组*/
@@ -647,37 +702,37 @@ export interface AdcreativeTemplate {
         }[];
       };
       /**广告创意能力项子节点列表*/
-      struct_detail: {
+      structDetail: {
         /**广告创意能力项子节点列表*/
-        element_list: {
+        elementList: {
           /**是否必填*/
           required: boolean;
-          /**广告创意接口要求的 adcreative_elements 结构中的元素字段名,如 image、title 等*/
+          /**广告创意接口要求的 adcreativeElements 结构中的元素字段名,如 image、title 等*/
           name: string;
           /**该创意元素的描述,如图片、广告文案等*/
           description: string;
           /**创意元素传参类型*/
-          field_type: string;
+          fieldType: string;
           /**能力项详情*/
-          property_detail: {
-            /**文本需满足的限制条件,仅当 element_type 是 ELEMENT_TYPE_TEXT 时返回*/
-            string_detail: {
+          propertyDetail: {
+            /**文本需满足的限制条件,仅当 elementType 是 ELEMENT_TYPE_TEXT 时返回*/
+            stringDetail: {
               /**最小长度,文本类型适用*/
-              min_length: number;
+              minLength: number;
               /**最大长度,文本类型适用*/
-              max_length: number;
+              maxLength: number;
               /**text 的正则表达式*/
-              text_pattern: string;
+              textPattern: RegExp;
             };
-            /**数值型需满足的限制条件,仅当 element_type 是 ELEMENT_TYPE_INTEGER 时返回*/
-            integer_detail: {
+            /**数值型需满足的限制条件,仅当 elementType 是 ELEMENT_TYPE_INTEGER 时返回*/
+            integerDetail: {
               /**最小长度,文本类型适用*/
               min: number;
               /**最大长度,文本类型适用*/
               max: number;
             };
             /**广告创意元素枚举值特性*/
-            enum_detail: {
+            enumDetail: {
               /**创意元素枚举默认值*/
               default: string;
               /**创意元素枚举可选值数组*/
@@ -688,11 +743,11 @@ export interface AdcreativeTemplate {
                 description: string;
               }[];
               /**广告创意元素数组特性*/
-              array_restriction: {
+              arrayRestriction: {
                 /**广告创意元素数组个数最小值*/
-                min_number: number;
+                minNumber: number;
                 /**广告创意元素数组个数最大值*/
-                max_number: number;
+                maxNumber: number;
               };
             };
           };
@@ -701,35 +756,35 @@ export interface AdcreativeTemplate {
     };
   }[];
   /**动态广告支持情况*/
-  support_dynamic_ability_spec_list: {
+  supportDynamicAbilitySpecList: {
     /**动态广告投放能力类型*/
-    dynamic_ability_type: string[];
+    dynamicAbilityType: string[];
     /**在该规格位置上单个广告上的创意可展示商品数量*/
-    product_item_display_quantity: string[];
+    productItemDisplayQuantity: string[];
   };
   /**不支持播放的版位信息列表*/
-  unsupport_siteset_detail_spec: {
+  unsupportSitesetDetailSpec: {
     /**投放版位集合,当前单版位或者 SITE_SET_TENCENT_NEWS+SITE_SET_TENCENT_VIDEO+SITE_SET_MOBILE_UNION+SITE_SET_KANDIAN+SITE_SET_QQ_MUSIC_GAME 的组合*/
-    site_set: string[];
+    siteSet: string[];
   }[];
   /**不支持的出价方式*/
-  unsupport_bid_mode_list: {
+  unsupportBidModeList: {
     /**投放版位集合,当前单版位或者 SITE_SET_TENCENT_NEWS+SITE_SET_TENCENT_VIDEO+SITE_SET_MOBILE_UNION+SITE_SET_KANDIAN+SITE_SET_QQ_MUSIC_GAME 的组合*/
-    site_set: string[];
+    siteSet: string[];
     /**支持的出价方式*/
-    bid_mode_list: string[];
+    bidModeList: string[];
   }[];
   /**不支持的计费信息*/
-  unsupport_billing_spec_list: {
+  unsupportBillingSpecList: {
     /**投放版位集合,当前单版位或者 SITE_SET_TENCENT_NEWS+SITE_SET_TENCENT_VIDEO+SITE_SET_MOBILE_UNION+SITE_SET_KANDIAN+SITE_SET_QQ_MUSIC_GAME 的组合*/
-    site_set: string[];
+    siteSet: string[];
     /**计费方式*/
-    billing_event: string;
+    billingEvent: string;
     /**最低出价,单位分*/
-    min_price: number;
+    minPrice: number;
     /**最高出价,单位分*/
-    max_price: number;
+    maxPrice: number;
     /**不支持类型*/
-    unsupport_type: string;
+    unsupportType: string;
   }[];
 }

+ 15 - 0
src/utils/arrFn.ts

@@ -0,0 +1,15 @@
+/**数组对象去重
+ * @param arr 原数组
+ */
+export function mySet(arr: any[]) {
+  let newArr: any[] = [];
+  arr.forEach((item) => {
+    if (newArr.length === 0) {
+      newArr.push(item);
+    }
+    if (newArr.length > 0 && newArr.every((a) => JSON.stringify(a) !== JSON.stringify(item))) {
+      newArr.push(item);
+    }
+  });
+  return newArr;
+}