wjx 9 maanden geleden
bovenliggende
commit
fc4b2b5b20

+ 13 - 2
src/pages/launchSystemV3/tencentAdPutIn/create/Target/dataItem.tsx

@@ -2,7 +2,7 @@ import TargetingTooltip from "@/pages/launchSystemV3/components/TargetingTooltip
 import { Popover, Tooltip } from "antd"
 import React from "react"
 import style from './index.less'
-import { CloseOutlined, FormOutlined } from "@ant-design/icons"
+import { CloseOutlined, CopyOutlined, FormOutlined } from "@ant-design/icons"
 
 interface Props {
     targeting: any
@@ -10,8 +10,9 @@ interface Props {
     modelList?: any
     onModify?: (e: React.MouseEvent<HTMLSpanElement, MouseEvent>) => void
     onClear?: (e: React.MouseEvent<HTMLSpanElement, MouseEvent>) => void
+    onCopy?: (e: React.MouseEvent<HTMLSpanElement, MouseEvent>) => void
 }
-const DataItem: React.FC<Props> = ({ targeting, onModify, onClear, geoLocationList, modelList }) => {
+const DataItem: React.FC<Props> = ({ targeting, onModify, onClear, onCopy, geoLocationList, modelList }) => {
 
 
     return <Popover
@@ -26,6 +27,16 @@ const DataItem: React.FC<Props> = ({ targeting, onModify, onClear, geoLocationLi
     >
         <div className={style.dataItem}>
             <span className={style.targetingName}>{targeting?.targetingName}</span>
+            <Tooltip title="根据地域一键生成多个定向">
+                <CopyOutlined
+                    className={style.edit}
+                    onClick={(e) => {
+                        e.stopPropagation()
+                        e.preventDefault()
+                        onCopy?.(e)
+                    }}
+                />
+            </Tooltip>
             <Tooltip title="修改当前">
                 <FormOutlined
                     className={style.edit}

+ 164 - 0
src/pages/launchSystemV3/tencentAdPutIn/create/Target/generateTarget.tsx

@@ -0,0 +1,164 @@
+import { Button, Card, Form, InputNumber, Modal, Select, Space, message } from "antd"
+import React from "react"
+import '../../index.less'
+import { getRandomElements } from "@/utils/utils"
+
+interface Props {
+    target: any
+    visible?: boolean,
+    onClose?: () => void
+    onChange?: (value: any) => void
+}
+const GenerateTarget: React.FC<Props> = ({ target, visible, onChange, onClose }) => {
+
+    /*********************************/
+    const [form] = Form.useForm();
+
+    /*********************************/
+
+    const handleOk = (values: any) => {
+        console.log(values)
+        /**
+         * 上海 310000
+         * "上海市未知" 319900 "黄浦区" 310101 "徐汇区" 310104 "长宁区" 310105 "静安区" 310106 "普陀区" 310107 "虹口区" 310109
+         * "杨浦区" 310110 "闵行区" 310112  "宝山区" 310113 "嘉定区" 310114 "浦东新区" 310115 "金山区" 310116 "松江区" 310117
+         * "青浦区" 310118 "奉贤区" 310120 "崇明区" 310230
+         * "北京市" 110000
+         * "北京市未知" 119900  "东城区" 110101 "西城区" 110102 "朝阳区" 110105 "丰台区" 110106 "石景山区" 110107 "海淀区" 110108
+         * "门头沟区" 110109 "房山区" 110111 "通州区" 110112 "顺义区" 110113 "昌平区" 110114 "大兴区" 110115 "怀柔区" 110116
+         * "平谷区" 110117 "密云区" 110228 "延庆区" 110229
+         */
+        const shanghai = [319900, 310101, 310104, 310105, 310106, 310107, 310109, 310110, 310112, 310113, 310114, 310115, 310116, 310117, 310118, 310120, 310230]
+        const shanghaiDto = {
+            319900: '上海市未知', 310101: '黄浦区', 310104: '徐汇区', 310105: '长宁区', 310106: '静安区', 310107: '普陀区', 310109: '虹口区', 310110: '杨浦区', 310112: '闵行区',
+            310113: '宝山区', 310114: '嘉定区', 310115: '浦东新区', 310116: '金山区', 310117: '松江区', 310118: '青浦区', 310120: '奉贤区', 310230: '崇明区'
+        }
+        const beijin = [119900, 110101, 110102, 110105, 110106, 110107, 110108, 110109, 110111, 110112, 110113, 110114, 110115, 110116, 110117, 110228, 110229]
+        const beijinDto = {
+            119900: '北京市未知', 110101: '东城区', 110102: '西城区', 110105: '朝阳区', 110106: '丰台区', 110107: '石景山区', 110108: '海淀区', 110109: '门头沟区', 110111: '房山区',
+            110112: '通州区', 110113: '顺义区', 110114: '昌平区', 110115: '大兴区', 110116: '怀柔区', 110117: '平谷区', 110228: '密云区', 110229: '延庆区'
+        }
+        const zhongguo = [156, 540000, 630000, 510000, 450000, 320000, 220000, 370000, 340000, 150000, 140000, 420000, 130000, 360000, 310000, 330000, 650000, 350000, 120000, 110000, 640000, 530000, 210000, 610000, 520000, 230000, 460000, 440000, 500000, 410000, 620000, 430000]
+        const locationTypes = ["LIVE_IN"]
+        const { regions, count } = values
+        let regionsList = regions === 310000 ? shanghai : regions === 110000 ? beijin : []
+        let regionsNameList = regions === 310000 ? shanghaiDto : regions === 110000 ? beijinDto : []
+        if (regionsList.length === 0) {
+            message.error('请联系管理员')
+            return
+        }
+        const getTarget = (count: number, regionsList: number[]): any => {
+            let dataRandom = getRandomElements(regionsList, count)
+            return dataRandom.map(r => {
+                let rName = regionsNameList[r]
+                return {
+                    targetingName: `${regions === 310000 ? '上海' : regions === 110000 ? '北京' : ''}无${rName}+` + target.targetingName,
+                    targeting: {
+                        ...target?.targeting || {},
+                        geoLocation: {
+                            locationTypes,
+                            regions: [...zhongguo.filter(item => item !== regions), ...regionsList.filter(item => item !== r)]
+                        }
+                    }
+                }
+            })
+        }
+        let data: any[] = []
+        if (target?.targeting?.geoLocation) {
+            let oldregions: number[] = target.targeting.geoLocation.regions
+            if (oldregions.includes(regions)) {
+                data = data.concat(getTarget(count, regionsList))
+            } else { // 不包含 regionsList
+                let ooregions = oldregions.filter(r => regionsList.toString().includes(r.toString()))
+                if (ooregions.length > 0) {
+                    if (count > ooregions.length) {
+                        message.error(`区县不够,生成数量太多,剩余区县:${ooregions.length}`)
+                        return
+                    }
+                    data = data.concat(getTarget(count, ooregions))
+                } else {
+                    message.error('当前地域已经全部排除了该城市')
+                    return
+                }
+            }
+        } else {
+            data.push({
+                ...target,
+                targetingName: target.targetingName + '+全国',
+                targeting: {
+                    ...target?.targeting || {},
+                    geoLocation: {
+                        locationTypes,
+                        regions: zhongguo
+                    }
+                }
+            })
+            data = data.concat(getTarget(count - 1, regionsList))
+        }
+        onChange?.(data)
+    }
+
+    return <Modal
+        title={<strong>一键生成定向配置</strong>}
+        visible={visible}
+        className='modalResetCss'
+        onCancel={onClose}
+        bodyStyle={{ padding: '0 0 40px', position: 'relative', borderRadius: '0 0 8px 8px' }}
+        footer={null}
+    >
+        <Form
+            form={form}
+            name="generateTarget"
+            labelAlign='left'
+            labelCol={{ span: 4 }}
+            colon={false}
+            style={{ backgroundColor: '#f1f4fc', maxHeight: 600, overflow: 'hidden', overflowY: 'auto', padding: '10px 10px 10px', borderRadius: '0 0 8px 8px' }}
+            scrollToFirstError
+            onFinishFailed={({ errorFields }) => {
+                message.error(errorFields?.[0]?.errors?.[0])
+            }}
+            onFinish={handleOk}
+            initialValues={{
+                regions: 310000,
+                count: 3
+            }}
+        >
+            <Card
+                title={<strong style={{ fontSize: 18 }}>生成设置</strong>}
+                className="cardResetCss"
+            >
+                <Form.Item
+                    label={<strong>地域差异</strong>}
+                    name='regions'
+                    rules={[
+                        { required: true, message: '请选择' }
+                    ]}
+                >
+                    <Select placeholder="请选择">
+                        <Select.Option value={310000}>上海</Select.Option>
+                        <Select.Option value={110000}>北京</Select.Option>
+                    </Select>
+                </Form.Item>
+                <Form.Item
+                    label={<strong>生成数量</strong>}
+                    name='count'
+                    rules={[
+                        { required: true, message: '请输入生成数量' }
+                    ]}
+                >
+                    <InputNumber max={10} style={{ width: '100%' }} placeholder="请输入生成数量" />
+                </Form.Item>
+            </Card>
+            <Form.Item className="submit_pull">
+                <Space>
+                    <Button onClick={onClose}>取消</Button>
+                    <Button type="primary" htmlType="submit" className="modalResetCss">
+                        确定
+                    </Button>
+                </Space>
+            </Form.Item>
+        </Form>
+    </Modal>
+}
+
+export default React.memo(GenerateTarget)

+ 2 - 1
src/pages/launchSystemV3/tencentAdPutIn/create/Target/index.less

@@ -13,9 +13,10 @@
     border-radius: 4px;
     align-items: center;
     font-size: 12px;
+    gap: 6px;
 
     .targetingName {
-        max-width: 80%;
+        // max-width: 80%;
         flex: 1;
         overflow: hidden;
         white-space: nowrap;

+ 26 - 0
src/pages/launchSystemV3/tencentAdPutIn/create/Target/index.tsx

@@ -7,6 +7,7 @@ import { DispatchAddelivery } from ".."
 import { useModel } from "umi"
 import DataItem from "./dataItem"
 import AddTarget from "./addTarget"
+import GenerateTarget from "./generateTarget"
 const { Title } = Typography;
 
 /**
@@ -23,6 +24,8 @@ const Target: React.FC = () => {
     const [addTemVisible, setAddTemVisible] = useState<boolean>(false)
     const [modifyDta, setModifyDta] = useState<any>()
     const [modifyLength, setModifyLength] = useState<number>()
+    const [copyDta, setCopyDta] = useState<any>()
+    const [copyVisible, setCopyVisible] = useState<boolean>(false)
     /***************************************/
 
 
@@ -51,6 +54,10 @@ const Target: React.FC = () => {
                                     setModifyDta({ targetingName: item?.id ? ('修_' + item.targetingName) : item.targetingName, ...item.targeting })
                                     setAddTemVisible(true)
                                 }}
+                                onCopy={() => {
+                                    setCopyDta(item)
+                                    setCopyVisible(true)
+                                }}
                             />
                         </div>)}
                     </>}
@@ -100,6 +107,7 @@ const Target: React.FC = () => {
                 setModifyDta(undefined)
             }}
             onChange={(newTargeting) => {
+                console.log('----->', newTargeting)
                 setAddTemVisible(false)
                 setModifyDta(undefined)
                 let newTarget: any[] = JSON.parse(JSON.stringify(targeting || []))
@@ -113,6 +121,24 @@ const Target: React.FC = () => {
                 clearData()
             }}
         />}
+
+        {/* 一键生成 */}
+        {copyVisible && <GenerateTarget 
+            target={copyDta}
+            visible={copyVisible}
+            onClose={() => {
+                setCopyDta(undefined)
+                setCopyVisible(false)
+            }}
+            onChange={(value) => {
+                let newTarget: any[] = JSON.parse(JSON.stringify(targeting || []))
+                newTarget = newTarget.concat(value)
+                setCopyDta(undefined)
+                setCopyVisible(false)
+                setAddelivery({ ...addelivery, targeting: newTarget })
+                clearData()
+            }}
+        />}
     </>
 }
 

+ 26 - 1
src/utils/utils.ts

@@ -391,4 +391,29 @@ export const distributeArray = (originalArray: any[], numGroups: number): any[][
   });
 
   return result;
-};
+};
+
+
+/**
+ * 随机取几个值
+ * @param arr 
+ * @param n 
+ * @returns 
+ */
+export function getRandomElements<T>(arr: T[], n: number): T[] {
+  if (n > arr.length) {
+      throw new RangeError("getRandomElements: more elements taken than available");
+  }
+
+  const result: T[] = new Array(n);
+  let len: number = arr.length;
+  const taken: number[] = new Array(len);
+
+  while (n--) {
+      const x: number = Math.floor(Math.random() * len);
+      result[n] = arr[x in taken ? taken[x] : x];
+      taken[x] = --len in taken ? taken[len] : len;
+  }
+
+  return result;
+}