wjx 1 giorno fa
parent
commit
7b6aa039a8

+ 1 - 2
src/pages/launchSystemV3/components/TargetingTooltip/index.tsx

@@ -79,8 +79,7 @@ const TargetingTooltip: React.FC<Props> = (props) => {
                         }
                         break
                     case 'age':
-                        let newAge = data[item][0]
-                        newConten.age = `${newAge.min}至${newAge.max > 65 ? '66岁及以上' : newAge.max + '岁'}`
+                        newConten.age = data[item].map((newAge: { min: number; max: number }) => `${newAge.min}至${newAge.max > 65 ? '66岁及以上' : newAge.max + '岁'}`)?.join('、')
                         break
                     case 'gender':
                         newConten.gender = data[item][0]

+ 74 - 25
src/pages/launchSystemV3/tencentAdPutIn/create/Target/addTarget.tsx

@@ -2,7 +2,7 @@ import { Button, Card, Checkbox, Form, Input, Modal, Radio, Select, Space, Spin,
 import React, { useEffect, useState } from "react"
 import style from '../index.less'
 import { DEVICE_PRICE_ENUM, EDUCATION_ENUM, EXCLUDED_DAY_ENUM, EXCLUDED_DIMENSION_ENUM, GAME_CONSUMPTION_LEVEL_ENUM, GENDER_ENUM, LOCATION_TYPES_ENUM, MARITAL_STATUS_ENUM, NETWORK_ENUM, OPTIMIZATIONGOAL_ENUM, USER_OS_ENUM, WECHAT_AD_NEHAVIOR_ENUM, WECHAT_AD_NEHAVIOR_GAME_ENUM } from "../../const"
-import { QuestionCircleFilled } from "@ant-design/icons"
+import { DeleteOutlined, PlusOutlined, QuestionCircleFilled } from "@ant-design/icons"
 import { getTargetingGagsApi } from "@/services/adqV3/global"
 import { useAjax } from "@/Hook/useAjax"
 import { DefaultOptionType } from "antd/lib/select"
@@ -35,6 +35,7 @@ const AddTarget: React.FC<Props> = ({ isBackVal, putInType, value, visible, onCh
     const ageType = Form.useWatch('ageType', form);
     const min = Form.useWatch(['age', 'min'], form);
     const max = Form.useWatch(['age', 'max'], form);
+    const age = Form.useWatch('age', form);
     const education = Form.useWatch('education', form);
     const networkType = Form.useWatch('networkType', form);
     const devicePrice = Form.useWatch('devicePrice', form);
@@ -225,7 +226,7 @@ const AddTarget: React.FC<Props> = ({ isBackVal, putInType, value, visible, onCh
             let [min, max] = ageType.split('_')
             targetValues.age = [{ min: Number(min), max: Number(max) }]
         } else if (ageType === '1') {
-            targetValues.age = [age]
+            targetValues.age = age
         }
         // 排除已转化用户
         if (excludedConvertedAudience?.excludedDimension !== '0') {
@@ -266,6 +267,7 @@ const AddTarget: React.FC<Props> = ({ isBackVal, putInType, value, visible, onCh
             accountId,
             targeting: targetValues
         }
+
         if (isBackVal && !isAdd) {
             delete targetingDTO.accountId
             delete targetingDTO.description
@@ -319,7 +321,7 @@ const AddTarget: React.FC<Props> = ({ isBackVal, putInType, value, visible, onCh
             } = JSON.parse(JSON.stringify(value))
             let targetValues: any = {
                 ...surplusValues,
-                age: age?.[0] || undefined,
+                age: age?.length > 0 ? age : undefined,
                 gender: gender?.[0] || '0',
                 education: education || '0',
                 networkType: networkType || '0',
@@ -349,8 +351,8 @@ const AddTarget: React.FC<Props> = ({ isBackVal, putInType, value, visible, onCh
                 }
             }
             if (age?.length > 0) {
-                let g = age?.[0]?.min + '_' + age?.[0]?.max
-                if (['14_18', '19_24', '25_29', '30_39', '40_49', '50_66'].includes(g)) {
+                const g = age?.[0]?.min + '_' + age?.[0]?.max
+                if (age?.length === 1 && ['14_18', '19_24', '25_29', '30_39', '40_49', '50_66'].includes(g)) {
                     targetValues.ageType = g
                 } else {
                     targetValues.ageType = '1'
@@ -396,6 +398,18 @@ const AddTarget: React.FC<Props> = ({ isBackVal, putInType, value, visible, onCh
         }
     }, [value, regionsList])
 
+    /** 判断数组是否重叠 */
+    const hasOverlap = (intervals: any[]) => {
+        intervals = intervals.filter(item => item)
+        for (let i = 0; i < intervals.length; i++) {
+            for (let j = i + 1; j < intervals.length; j++) {
+                const a = intervals[i], b = intervals[j];
+                if (a?.min < b?.max && a?.max > b?.min) return true;
+            }
+        }
+        return false;
+    }
+
     return <Modal
         title={isBackVal ? <strong style={{ fontSize: 20 }}>
             {(value && Object.keys(value).length > 0) ? `修改定向` : `新增定向`}
@@ -433,10 +447,7 @@ const AddTarget: React.FC<Props> = ({ isBackVal, putInType, value, visible, onCh
                 userOsType: '0',
                 ageType: '0',
                 wechatAdBehaviorType: ['0'],
-                age: {
-                    min: 14,
-                    max: 66
-                },
+                age: [{}],
                 gender: '0',
                 education: ['0'],
                 networkType: ['0'],
@@ -541,23 +552,61 @@ const AddTarget: React.FC<Props> = ({ isBackVal, putInType, value, visible, onCh
                             <Radio value="1">自定义</Radio>
                         </Radio.Group>
                     </Form.Item>
-                    {ageType === '1' && <div className={`${style.newSpace_bottom} flexStart`} style={{ '--g': '5px' } as React.CSSProperties}>
-                        <Form.Item name={['age', 'min']} style={{ marginBottom: 0 }}>
-                            <Select style={{ width: 185 }} placeholder="请选择">
-                                {Array(66 - 13).fill('').map((_, i) => i + 14).filter(i => i !== 15 && i !== 16 && i !== 17).map(i => {
-                                    return <Select.Option disabled={i > max} value={i} key={i}>{i === 66 ? '66 岁及以上' : i + ' 岁'}</Select.Option>
-                                })}
-                            </Select>
-                        </Form.Item>
-                        <span>-</span>
-                        <Form.Item name={['age', 'max']} style={{ marginBottom: 0 }}>
-                            <Select style={{ width: 185 }} placeholder="请选择">
-                                {Array(66 - 17).fill('').map((_, i) => {
-                                    return <Select.Option disabled={i + 18 < min} value={i + 18} key={i + 18}>{i + 18 === 66 ? '66 岁及以上' : i + 18 + ' 岁'}</Select.Option>
+                    {ageType === '1' && <Form.List
+                        name='age'
+                        rules={[
+                            {
+                                validator: (_, ranges) => {
+                                    console.log('ranges', ranges)
+                                    if (hasOverlap(ranges)) {
+                                        return Promise.reject('年龄存在区间重叠,请修改');
+                                    }
+                                    return Promise.resolve();
+                                }
+                            }
+                        ]}
+                    >
+                        {(fields, { add, remove }) => {
+                            return <>
+                                {fields.map(({ key, name, ...restField }, index) => {
+                                    const ag = age?.[index]
+                                    return <div className={`${style.newSpace_bottom} flexStart`} key={key} style={{ '--g': '5px', padding: '10px 16px' } as React.CSSProperties}>
+                                        <Form.Item
+                                            {...restField}
+                                            name={[name, 'min']}
+                                            style={{ marginBottom: 0 }}
+                                            rules={[{ required: true, message: '请选择最小年龄!' }]}
+                                        >
+                                            <Select style={{ width: 185 }} placeholder="请选择">
+                                                {Array(66 - 13).fill('').map((_, i) => i + 14).filter(i => i !== 15 && i !== 16 && i !== 17).map(i => {
+                                                    return <Select.Option disabled={i > ag?.max} value={i} key={i}>{i === 66 ? '66 岁及以上' : i + ' 岁'}</Select.Option>
+                                                })}
+                                            </Select>
+                                        </Form.Item>
+                                        <span>-</span>
+                                        <Form.Item
+                                            {...restField}
+                                            name={[name, 'max']}
+                                            style={{ marginBottom: 0 }}
+                                            rules={[{ required: true, message: '请选择最大年龄!' }]}
+                                        >
+                                            <Select style={{ width: 185 }} placeholder="请选择">
+                                                {Array(66 - 17).fill('').map((_, i) => {
+                                                    return <Select.Option disabled={i + 18 < ag?.min} value={i + 18} key={i + 18}>{i + 18 === 66 ? '66 岁及以上' : i + 18 + ' 岁'}</Select.Option>
+                                                })}
+                                            </Select>
+                                        </Form.Item>
+                                        {age?.length > 1 && <Button danger onClick={() => remove(name)}><DeleteOutlined /></Button>}
+                                    </div>
                                 })}
-                            </Select>
-                        </Form.Item>
-                    </div>}
+                                {age?.length < 5 && <Form.Item noStyle>
+                                    <Button type="dashed" onClick={() => add()} style={{ width: '100%' }} icon={<PlusOutlined />}>
+                                        新增年龄段
+                                    </Button>
+                                </Form.Item>}
+                            </>
+                        }}
+                    </Form.List>}
                 </div>
 
                 <div className={style.newSpace}>