wjx 10 月之前
父節點
當前提交
e433c8851a

+ 2 - 2
src/pages/launchSystemNew/account/components/openV3All.tsx

@@ -34,10 +34,10 @@ const OpenV3All: React.FC<Props> = ({ accountId, onChange }) => {
     }
 
     return <Space>
-        <Tooltip title="广告业务单元广告主账号同步">
+        <Tooltip title="广告业务单元广告主账号全量转3.0">
             <Button size="small" style={{ color: "#0eb83a" }} onClick={openAllV3}>{openAllV3a.loading ? <LoadingOutlined /> : <span>全3.0</span>}</Button>
         </Tooltip>
-        <Tooltip title="广告业务单元广告主账号全量转3.0">
+        <Tooltip title="广告业务单元广告主账号同步">
             <Button size="small" style={{ color: "#ea5506" }} onClick={asyncAllV3} loading={authSync.loading} icon={<SyncOutlined />}></Button>
         </Tooltip>
     </Space>

+ 31 - 5
src/pages/launchSystemNew/account/game/index.tsx

@@ -181,11 +181,17 @@ const AdAuthorize: React.FC = () => {
                     size="small"
                     scroll={{ y: 600 }}
                     leftChild={<Space wrap>
-                        <Radio.Group value={switchType} onChange={(e) => { setSwitchType(e.target.value); setSelectAccData([]) }}>
-                            <Radio.Button value="account">批量切号</Radio.Button>
-                            <Radio.Button value="putUser">批量指派投放助理</Radio.Button>
-                            <Radio.Button value="setServer">批量配置服务商</Radio.Button>
-                        </Radio.Group>
+                        <Select
+                            style={{ width: 120 }}
+                            placeholder="选择操作类型"
+                            onChange={(e) => {
+                                setSwitchType(e); 
+                                setSelectAccData([])
+                            }}
+                            value={switchType}
+                            dropdownMatchSelectWidth={false}
+                            options={[{ label: '批量切号', value: 'account' }, { label: '批量指派投放助理', value: 'putUser' }, { label: '批量配置服务商', value: 'setServer' }]}
+                        />
                         <Input.TextArea
                             placeholder="多个广告账号以,隔开(id1,id2)"
                             allowClear
@@ -196,6 +202,26 @@ const AdAuthorize: React.FC = () => {
                                 setQueryForm({ ...queryForm, accountIds: e.target.value.replaceAll(/\s/ig, '') })
                             }}
                         />
+                        <Select
+                            style={{ width: 120 }}
+                            placeholder="是3.0账号?"
+                            allowClear
+                            onChange={(e) => {
+                                setQueryForm({ ...queryForm, addV3: e })
+                            }}
+                            value={queryForm?.addV3}
+                            options={[{ label: '是', value: true }, { label: '否', value: false }]}
+                        />
+                        <Select
+                            style={{ width: 120 }}
+                            placeholder="是业务单元?"
+                            allowClear
+                            onChange={(e) => {
+                                setQueryForm({ ...queryForm, adUnitAccount: e })
+                            }}
+                            value={queryForm?.adUnitAccount}
+                            options={[{ label: '是', value: true }, { label: '否', value: false }]}
+                        />
                         <Button onClick={getList} type='primary' loading={getAdAccountList.loading}>搜索</Button>
                         <AddAccountToGroup onChange={() => getAdAccountList.refresh()} />
                         <Button type='primary' onClick={() => setVisible(true)}><PlusOutlined />广告账号授权</Button>

+ 33 - 7
src/pages/launchSystemNew/account/novel/index.tsx

@@ -141,7 +141,7 @@ const AdAuthorize: React.FC = () => {
             }
         })
     }
-    
+
 
     return <div style={{ height: '100%' }}>
         <Tabs
@@ -182,11 +182,17 @@ const AdAuthorize: React.FC = () => {
                     size="small"
                     scroll={{ y: 600 }}
                     leftChild={<Space wrap>
-                        <Radio.Group value={switchType} onChange={(e) => { setSwitchType(e.target.value); setSelectAccData([]) }}>
-                            <Radio.Button value="account">批量切号</Radio.Button>
-                            <Radio.Button value="putUser">批量指派投放助理</Radio.Button>
-                            <Radio.Button value="setServer">批量配置服务商</Radio.Button>
-                        </Radio.Group>
+                        <Select
+                            style={{ width: 120 }}
+                            placeholder="选择操作类型"
+                            onChange={(e) => {
+                                setSwitchType(e); 
+                                setSelectAccData([])
+                            }}
+                            value={switchType}
+                            dropdownMatchSelectWidth={false}
+                            options={[{ label: '批量切号', value: 'account' }, { label: '批量指派投放助理', value: 'putUser' }, { label: '批量配置服务商', value: 'setServer' }]}
+                        />
                         <Input.TextArea
                             placeholder="多个广告账号以,隔开(id1,id2)"
                             allowClear
@@ -197,13 +203,33 @@ const AdAuthorize: React.FC = () => {
                                 setQueryForm({ ...queryForm, accountIds: e.target.value.replaceAll(/\s/ig, '') })
                             }}
                         />
+                        <Select
+                            style={{ width: 120 }}
+                            placeholder="是3.0账号?"
+                            allowClear
+                            onChange={(e) => {
+                                setQueryForm({ ...queryForm, addV3: e })
+                            }}
+                            value={queryForm?.addV3}
+                            options={[{ label: '是', value: true }, { label: '否', value: false }]}
+                        />
+                        <Select
+                            style={{ width: 120 }}
+                            placeholder="是业务单元?"
+                            allowClear
+                            onChange={(e) => {
+                                setQueryForm({ ...queryForm, adUnitAccount: e })
+                            }}
+                            value={queryForm?.adUnitAccount}
+                            options={[{ label: '是', value: true }, { label: '否', value: false }]}
+                        />
                         <Button onClick={getList} type='primary' loading={getAdAccountList.loading}>搜索</Button>
                         <AddAccountToGroup onChange={() => getAdAccountList.refresh()} />
                         <Button type='primary' onClick={() => setVisible(true)}><PlusOutlined />广告账号授权</Button>
                         {switchType === 'account' ?
                             (selectAccData?.length > 0 && <>
                                 <Button type="primary" ghost icon={<SwapOutlined />} onClick={() => { checkAccount(selectAccData) }}>批量切号</Button>
-                                <SetEarlyWarningsAccount onChange={() => { setSelectAccData([]); }} accountIds={selectAccData.map(item => item.accountId)?.toString()}/>
+                                <SetEarlyWarningsAccount onChange={() => { setSelectAccData([]); }} accountIds={selectAccData.map(item => item.accountId)?.toString()} />
                             </>) :
                             switchType === 'putUser' ? (selectAccData?.length > 0 && <Button type="primary" ghost icon={<SwapOutlined />} onClick={() => { putUserHandle(selectAccData) }}>批量指派投放助理</Button>) :
                                 selectAccData?.length > 0 && <Button type="primary" ghost icon={<SwapOutlined />} onClick={() => { setOpenServer(selectAccData) }}>批量配置服务商</Button>

+ 66 - 10
src/pages/launchSystemV3/adqv3/ad/index.tsx

@@ -1,6 +1,6 @@
 import { useAjax } from "@/Hook/useAjax";
 import { PauseCircleOutlined, PlayCircleOutlined, PlusOutlined, QuestionCircleOutlined, TransactionOutlined } from "@ant-design/icons";
-import { Button, Checkbox, Col, Input, Row, Select, Space, Tooltip, message } from "antd"
+import { Button, Checkbox, Col, Input, Row, Select, Space, Tooltip, Typography, message } from "antd"
 import React, { useCallback, useEffect, useState } from "react"
 import { ADGROUP_STATUS } from "../const";
 import { getAdqV3AdListApi, modifyStatusBatchApi, syncBatchApi } from "@/services/launchAdq/adqv3";
@@ -9,7 +9,9 @@ import { txAdConfig } from "../config";
 import UpdateAd from "./updateAd";
 import TableData from "@/pages/launchSystemNew/components/TableData";
 import AddDynamic from "../../tencentAdPutIn/create/addDynamic";
-
+import { arraysHaveSameValues } from "@/utils/utils";
+import { MARKETING_GOAL_ENUM } from "../../tencentAdPutIn/const";
+const { Text } = Typography;
 
 const Ad: React.FC<ADQV3.AdProps> = ({ userId, creativeHandle }) => {
 
@@ -19,6 +21,7 @@ const Ad: React.FC<ADQV3.AdProps> = ({ userId, creativeHandle }) => {
     const [selectedRows, setSelectedRows] = useState<any[]>([])
     const [update, setUpdate] = useState<{ visible: boolean }>({ visible: false })
     const [addDynamicVisible, setAddDynamicVisible] = useState<boolean>(false)
+    const [handleType, setHandleType] = useState<number>(1)
 
     const syncBatch = useAjax((params) => syncBatchApi(params))
     const modifyStatusBatch = useAjax((params) => modifyStatusBatchApi(params))
@@ -230,17 +233,54 @@ const Ad: React.FC<ADQV3.AdProps> = ({ userId, creativeHandle }) => {
             configName="腾讯广告3.0"
             leftChild={<Space direction='vertical'>
                 <Row gutter={[10, 10]} align='middle'>
-                    <Col><Button type='primary' style={{ background: '#67c23a', borderColor: '#67c23a' }} loading={modifyStatusBatch.loading} icon={<PlayCircleOutlined />} disabled={selectedRows.length === 0} onClick={() => adStatus(true)}>启动</Button></Col>
-                    <Col><Button type='primary' style={{ background: '#e6a23c', borderColor: '#e6a23c' }} loading={modifyStatusBatch.loading} icon={<PauseCircleOutlined />} disabled={selectedRows.length === 0} onClick={() => adStatus(false)}>暂停</Button></Col>
-                    <Col><Button type='primary' icon={<TransactionOutlined />} disabled={selectedRows.length === 0} onClick={() => setUpdate({ visible: true })}>修改出价</Button></Col>
-                    {/* <Col><Button type='primary' icon={<PlusOutlined />} disabled={selectedRows.length === 0} onClick={addDynamic}>添加创意</Button></Col> */}
+                    <Col><Select
+                        style={{ width: 120 }}
+                        onChange={(e) => {
+                            setHandleType(e)
+                            setSelectedRows([])
+                        }}
+                        value={handleType}
+                        options={[{ label: '广告操作', value: 1 }]}
+                    /></Col>
+                    {handleType === 1 ? <>
+                        <Col><Button type='primary' style={{ background: '#67c23a', borderColor: '#67c23a' }} loading={modifyStatusBatch.loading} icon={<PlayCircleOutlined />} disabled={selectedRows.length === 0} onClick={() => adStatus(true)}>启动</Button></Col>
+                        <Col><Button type='primary' style={{ background: '#e6a23c', borderColor: '#e6a23c' }} loading={modifyStatusBatch.loading} icon={<PauseCircleOutlined />} disabled={selectedRows.length === 0} onClick={() => adStatus(false)}>暂停</Button></Col>
+                        <Col><Button type='primary' icon={<TransactionOutlined />} disabled={selectedRows.length === 0} onClick={() => setUpdate({ visible: true })}>修改出价</Button></Col>
+                    </> : handleType === 2 ? <>
+                        <Col><Button type='primary' icon={<PlusOutlined />} disabled={selectedRows.length === 0} onClick={addDynamic}>添加创意</Button></Col>
+                        <Col>
+                            {selectedRows?.length > 0 && <Text type="danger" strong style={{ fontSize: 12, marginRight: 6 }}>
+                                {`当前选择:营销目的:${MARKETING_GOAL_ENUM[selectedRows?.[0]?.marketingGoal]}`}
+                            </Text>}
+                            <Tooltip title="选择的广告必须与已选广告的营销目的、营销载体、推广内容、广告版位一致">
+                                <QuestionCircleOutlined style={{ color: 'red' }} />
+                            </Tooltip>
+                        </Col>
+                    </> : null}
                 </Row>
             </Space>}
             rowSelection={{
                 selectedRowKeys: selectedRows.map(item => item.adgroupId.toString()),
-                getCheckboxProps: (record: any) => ({
-                    disabled: record.isDeleted
-                }),
+                getCheckboxProps: (record: any) => {
+                    if (handleType === 2 && selectedRows?.length > 0) {
+                        const { siteSet, marketingCarrierType, marketingGoal, marketingTargetType, sceneSpec, automaticSiteEnabled } = selectedRows[0]
+                        return {
+                            disabled: record.isDeleted || !(
+                                record?.marketingGoal === marketingGoal &&  // 营销内容
+                                record?.marketingCarrierType === marketingCarrierType && // 营销载体
+                                record?.marketingTargetType === marketingTargetType && // 推广产品
+                                record?.automaticSiteEnabled === automaticSiteEnabled &&   // 自动版位
+                                arraysHaveSameValues(siteSet || [], record?.siteSet || []) && // 版位选择
+                                arraysHaveSameValues(record?.sceneSpec?.wechatPosition || [], sceneSpec?.wechatPosition || []) // 微信公众号与小程序定投
+                            )
+                        }
+                    } else {
+                        return {
+                            disabled: record.isDeleted
+                        }
+                    }
+
+                },
                 onSelect: (record: { adgroupId: number, mpName: string }, selected: boolean) => {
                     if (selected) {
                         selectedRows.push({ ...record })
@@ -253,10 +293,26 @@ const Ad: React.FC<ADQV3.AdProps> = ({ userId, creativeHandle }) => {
                 onSelectAll: (selected: boolean, selectedRowss: { adgroupId: number }[], changeRows: { adgroupId: number }[]) => {
                     if (selected) {
                         let newSelectAccData = [...selectedRows]
+                        let firstRow = newSelectAccData?.[0] || changeRows?.[0] || {}
                         changeRows.forEach((item: { adgroupId: number }) => {
                             let index = newSelectAccData.findIndex((ite: { adgroupId: number }) => ite.adgroupId === item.adgroupId)
                             if (index === -1) {
-                                newSelectAccData.push({ ...item })
+                                let data: any = { ...item }
+                                if (handleType === 2) {
+                                    const { siteSet, marketingCarrierType, marketingGoal, marketingTargetType, sceneSpec, automaticSiteEnabled } = firstRow
+                                    if (
+                                        data?.marketingGoal === marketingGoal &&  // 营销内容
+                                        data?.marketingCarrierType === marketingCarrierType && // 营销载体
+                                        data?.marketingTargetType === marketingTargetType && // 推广产品
+                                        data?.automaticSiteEnabled === automaticSiteEnabled &&   // 自动版位
+                                        arraysHaveSameValues(siteSet || [], data?.siteSet || []) && // 版位选择
+                                        arraysHaveSameValues(data?.sceneSpec?.wechatPosition || [], sceneSpec?.wechatPosition || []) // 微信公众号与小程序定投
+                                    ) {
+                                        newSelectAccData.push(data)
+                                    }
+                                } else {
+                                    newSelectAccData.push(data)
+                                }
                             }
                         })
                         setSelectedRows([...newSelectAccData])

+ 2 - 2
src/pages/launchSystemV3/tencentAdPutIn/create/Ad/index.tsx

@@ -20,7 +20,7 @@ const Ad: React.FC = () => {
     const { adgroups } = addelivery
     const {
         marketingGoal, marketingAssetOuterSpec, marketingCarrierType, automaticSiteEnabled, siteSet, searchExpandTargetingSwitch, bidMode, smartBidType, bidAmount, optimizationGoal,
-        deepConversionSpec, autoAcquisitionEnabled, autoAcquisitionBudget, dailyBudget, endDate, beginDate, timeSeries, firstDayBeginTime, configuredStatus, adgroupName, wechatPosition
+        deepConversionSpec, autoAcquisitionEnabled, autoAcquisitionBudget, dailyBudget, endDate, beginDate, timeSeries, firstDayBeginTime, configuredStatus, adgroupName, sceneSpec
     } = adgroups
     const [newVisible, setNewVisible] = useState<boolean>(false)
     /*****************************/
@@ -92,7 +92,7 @@ const Ad: React.FC = () => {
                     adgroups.marketingAssetOuterSpec.marketingTargetType === marketingAssetOuterSpec.marketingTargetType && // 推广产品
                     adgroups.automaticSiteEnabled === automaticSiteEnabled &&  // 版位选择
                     arraysHaveSameValues(adgroups?.siteSet || [], siteSet || []) &&  // 版位
-                    arraysHaveSameValues(adgroups?.wechatPosition || [], wechatPosition || []) // 微信公众号与小程序定投
+                    arraysHaveSameValues(adgroups?.sceneSpec?.wechatPosition || [], sceneSpec?.wechatPosition || []) // 微信公众号与小程序定投
                 ) {
                     setAddelivery({ ...addelivery, adgroups })
                 } else {

+ 3 - 1
src/services/launchAdq/adAuthorize.ts

@@ -10,7 +10,9 @@ export interface GetAdAccountParams {
     pageSize: number,
     groupId?: number,
     accountIds?: string[] | string
-    putUserId?: number
+    putUserId?: number,
+    addV3?: boolean,
+    adUnitAccount?: boolean
 }
 export async function getAdAccountListApi(data: GetAdAccountParams) {
     return request(api + '/adq/adAccount/accountListOfNovel', {