8 Commits 59540de377 ... 1fea20e5a5

Author SHA1 Message Date
  wjx 1fea20e5a5 fix 2 months ago
  wjx 78a9957306 fix 2 months ago
  wjx 8277b17a87 fix 2 months ago
  wjx fcc9ac0eb4 fix 2 months ago
  wjx a258bee38b fix 2 months ago
  wjx ee788f7eef fix 2 months ago
  wjx 2ba56b06c6 fix 2 months ago
  wjx 2d297d5778 fix 2 months ago

+ 5 - 2
src/components/CustomList/index.tsx

@@ -60,7 +60,8 @@ interface DataProps {
         saveField: string,
         defaultValue: any[],
         data: any[]
-    }
+    },
+    bcColor?: string
 }
 
 /**
@@ -328,7 +329,9 @@ function CustomListModel(props: customProps) {
                                     </div>
                                 </div>}
                                 <dt>
-                                    <Checkbox onChange={(e) => { checkAllHandle(e.target.checked, item.label) }} className='checkbox'>{item.label}</Checkbox>
+                                    <Checkbox onChange={(e) => { checkAllHandle(e.target.checked, item.label) }} className='checkbox'>
+                                        <span style={item?.bcColor ? { backgroundColor: item?.bcColor } : {}}>{item.label}</span>
+                                    </Checkbox>
                                 </dt>
                                 {item.data?.map((listItem: dataProps, listIndex: number) => {
                                     return <dd key={item.label + listIndex}>

+ 21 - 0
src/global.less

@@ -371,6 +371,7 @@ body {
   }
 }
 
+// 平台上报
 .green2ColorClass {
   background-color: #f6ffed;
 
@@ -389,6 +390,26 @@ body {
   }
 }
 
+// 应用端数据
+.appColorClass {
+  background-color: #fff0f6;
+
+  &.ant-table-cell-fix-left,
+  &.ant-table-cell-fix-right {
+    background-color: #fff0f6;
+  }
+}
+
+// 广告端数据
+.adColorClass {
+  background-color: #e6fffb;
+
+  &.ant-table-cell-fix-left,
+  &.ant-table-cell-fix-right {
+    background-color: #e6fffb;
+  }
+}
+
 .padding_0.ant-table-cell {
   padding: 0 !important;
 

+ 902 - 0
src/pages/iaaData/components/AutoAcquisitionSet/autoAcquisitionSetTask.tsx

@@ -0,0 +1,902 @@
+import { Badge, Button, Card, DatePicker, Drawer, Dropdown, Form, Input, InputNumber, message, Modal, Popconfirm, Radio, Select, Space, Table, Tag, Tooltip } from "antd"
+import React, { useEffect, useState } from "react"
+import './index1.less'
+import style from './index.less'
+import { DownOutlined, QuestionCircleOutlined } from "@ant-design/icons"
+import { useAjax } from "@/Hook/useAjax"
+import { RangePickerProps } from "antd/lib/date-picker"
+import moment from "moment"
+import { copy } from "@/utils/utils"
+import SetTime from "./setTime"
+import { adAddTaskApi, addOnceTaskAutoAcquisitionApi, addTaskAutoAcquisitionApi, delAdgroupQuantTaskAdApi, delAdgroupQuantTaskApi, getAdgroupQuantTaskAdDetailsListApi, getAdgroupQuantTaskAdLogListApi, getAdgroupQuantTaskListApi, getTaskAllListApi, updateTaskAutoAcquisitionApi } from "@/services/gameData"
+
+interface AutoAcquisitionSetTaskProps {
+    selectAdList: any[]
+    onChange?: (type?: number) => void
+}
+/**
+ * 一键起量任务
+ * @returns 
+ */
+const AutoAcquisitionSetTask: React.FC<AutoAcquisitionSetTaskProps> = ({ selectAdList = [], onChange }) => {
+
+    /*********************************/
+    const [visible, setVisible] = useState<boolean>(false)
+    const [taskVisible, setTaskVisible] = useState<boolean>(false)
+    const [addTaskVisible, setAddTaskVisible] = useState<boolean>(false)
+    /*********************************/
+
+    return <>
+        <Dropdown
+            menu={{
+                items: [
+                    {
+                        label: <span style={{ display: 'inline-block', width: 120 }}>创建一键起量任务</span>,
+                        key: '1',
+                        onClick: () => { setVisible(true) }
+                    },
+                    {
+                        label: '添加到任务',
+                        key: '2',
+                        disabled: selectAdList.length === 0,
+                        onClick: () => { setAddTaskVisible(true) }
+                    },
+                    {
+                        label: '起量任务列表',
+                        key: '3',
+                        onClick: () => { setTaskVisible(true) }
+                    }
+                ]
+            }}
+            placement="bottomLeft"
+            arrow
+        >
+            <Button>
+                <Space>
+                    一键起量
+                    <DownOutlined />
+                </Space>
+            </Button>
+        </Dropdown>
+
+        {/* 任务创建 */}
+        {visible && <AutoAcquisitionSet
+            selectAdList={selectAdList}
+            visible={visible}
+            onClose={() => {
+                setVisible(false)
+            }}
+            onChange={(val) => {
+                onChange?.(val)
+                setVisible(false)
+            }}
+        />}
+
+        {/* 广告加人到任务 */}
+        {addTaskVisible && <AdAddTask
+            selectAdList={selectAdList}
+            visible={addTaskVisible}
+            onClose={() => {
+                setAddTaskVisible(false)
+            }}
+            onChange={(val) => {
+                setAddTaskVisible(false)
+            }}
+        />}
+
+        {/* 任务列表 */}
+        {taskVisible && <TaskLog
+            visible={taskVisible}
+            onClose={() => setTaskVisible(false)}
+        />}
+    </>;
+};
+
+interface Props {
+    selectAdList?: any[]
+    initialValues?: any
+    visible?: boolean
+    onClose?: () => void
+    onChange?: (type?: number) => void
+}
+
+/**
+ * 设置一键起量任务
+ * @param param0 
+ * @returns 
+ */
+const AutoAcquisitionSet: React.FC<Props> = ({ selectAdList = [], initialValues, visible, onChange, onClose }) => {
+
+    /****************************************/
+    const [form] = Form.useForm<ADQV3.AddTaskAutoAcquisitionProps>();
+    const startDay = Form.useWatch('startDay', form);
+    const endDay = Form.useWatch('endDay', form);
+    const addType = Form.useWatch('addType', form);
+    const taskType = Form.useWatch('taskType', form);
+
+    const addTaskAutoAcquisition = useAjax((params) => addTaskAutoAcquisitionApi(params))
+    const updateTaskAutoAcquisition = useAjax((params) => updateTaskAutoAcquisitionApi(params))
+    const addOnceTaskAutoAcquisition = useAjax((params) => addOnceTaskAutoAcquisitionApi(params))
+    /****************************************/
+
+    const handleOk = () => {
+        form.validateFields().then((values) => {
+
+            const { taskType, addType, startDay, endDay, budgetPercent, ...val } = values;
+            const params: ADQV3.AddTaskAutoAcquisitionProps = {
+                ...val,
+            }
+            if (addType === 'percent' && budgetPercent) {
+                params.budgetPercent = budgetPercent / 100;
+            }
+
+            if (selectAdList?.length) {
+                params.adgroupBeanList = selectAdList.map(item => ({ accountId: item.accountId, adgroupId: item.adgroupId }))
+            }
+            if (initialValues?.id) {
+                params.startDay = moment(startDay).format('YYYY-MM-DD')
+                params.endDay = moment(endDay).format('YYYY-MM-DD')
+                updateTaskAutoAcquisition.run({ ...params, idList: [initialValues.id] }).then(res => {
+                    if (res?.data) {
+                        message.success('修改成功')
+                        onChange?.()
+                    }
+                })
+            } else {
+                if (taskType === 'cyc') { // 循环
+                    params.startDay = moment(startDay).format('YYYY-MM-DD')
+                    params.endDay = moment(endDay).format('YYYY-MM-DD')
+                    addTaskAutoAcquisition.run(params).then(res => {
+                        if (res?.data) {
+                            message.success('添加成功')
+                            onChange?.()
+                        }
+                    })
+                } else { // 立即执行
+                    addOnceTaskAutoAcquisition.run(params).then(res => {
+                        if (res?.data) {
+                            message.success('添加成功')
+                            onChange?.(1)
+                        }
+                    })
+                }
+            }
+        }).catch(() => {
+            form.submit()
+        });
+    }
+
+    const disabledDateStart: RangePickerProps['disabledDate'] = current => {
+        // Can not select days before today and today
+        if (endDay) {
+            return current && current < moment().startOf('day') || current > moment(endDay) || current < moment(endDay).subtract(10, 'days');
+        }
+        return current && current < moment().startOf('day');
+    };
+
+    const disabledDateEnd: RangePickerProps['disabledDate'] = current => {
+        // Can not select days before today and today
+        if (startDay) {
+            return current && current < moment().startOf('day') || current < moment(startDay) || current > moment(startDay).add(10, 'days');
+        }
+        return current && current < moment().startOf('day');
+    };
+
+    return <Modal
+        title={<strong>{initialValues?.id ? '修改' : '新增'}一键起量任务
+            <Tooltip title={<div>
+                <p>1. 一键起量期间产生的消耗不赔付,但转化计入赔付门槛判断;</p>
+                <p>2. 一键起量可能导致转化成本高于预期,且起量结束后不一定能持续消耗。</p>
+            </div>}>
+                <QuestionCircleOutlined />
+            </Tooltip>
+        </strong>}
+        open={visible}
+        onCancel={onClose}
+        onOk={handleOk}
+        className='modalResetCss'
+        width={750}
+        confirmLoading={addTaskAutoAcquisition.loading || addOnceTaskAutoAcquisition.loading || updateTaskAutoAcquisition.loading}
+    >
+        <div className={style.autoAcquisitionSet}>
+            {selectAdList?.length > 0 && <div className={style.left}>
+                <Table
+                    dataSource={selectAdList}
+                    size="small"
+                    scroll={{ x: 400, y: 450 }}
+                    bordered
+                    rowKey={'adgroupId'}
+                    pagination={false}
+                    columns={[
+                        {
+                            title: '广告名称',
+                            dataIndex: 'adgroupName',
+                            key: 'adgroupName',
+                            width: 200,
+                            render(value) {
+                                return <span style={{ wordBreak: 'break-all' }}>{value}</span>
+                            },
+                        },
+                        {
+                            title: '原设置',
+                            dataIndex: 'beforeSet',
+                            key: 'beforeSet',
+                            width: 120,
+                            render(value, record) {
+                                if (!record?.autoAcquisitionEnabled) {
+                                    return '未开启'
+                                }
+                                return `一键起量中,起量预算:${record?.autoAcquisitionBudget} 元`
+                            },
+                        }
+                    ]}
+                />
+            </div>}
+            <div className={style.right}>
+                <div className={style.edit}>
+                    <div>
+                        <Form
+                            form={form}
+                            name="newTaks"
+                            layout={selectAdList?.length > 0 ? 'vertical' : 'horizontal'}
+                            labelCol={selectAdList?.length > 0 ? undefined : { span: 5 }}
+                            labelAlign="left"
+                            colon={false}
+                            scrollToFirstError={{
+                                behavior: 'smooth',
+                                block: 'center'
+                            }}
+                            onFinishFailed={({ errorFields }) => {
+                                message.error(errorFields?.[0]?.errors?.[0])
+                            }}
+                            onFinish={handleOk}
+                            initialValues={initialValues?.id ? initialValues : { addType: 'fixed', taskType: 'cyc' }}
+                        >
+                            <Form.Item label={<strong>任务类型</strong>} name="taskType" rules={[{ required: true, message: '请输入任务类型!' }]}>
+                                <Radio.Group buttonStyle="solid">
+                                    <Radio.Button value="cyc">循环执行</Radio.Button>
+                                    <Radio.Button value="imm" disabled={selectAdList.length === 0 || initialValues?.id}>立即执行</Radio.Button>
+                                </Radio.Group>
+                            </Form.Item>
+                            <Form.Item label={<strong>任务名称</strong>} name="taskName" rules={[{ required: true, message: '请输入任务名称!' }]}>
+                                <Input placeholder="请输入任务名称" />
+                            </Form.Item>
+                            {taskType === 'cyc' && <>
+                                <Form.Item label={<strong>执行日期</strong>} required>
+                                    <Space>
+                                        <Form.Item name="startDay" rules={[{ required: true, message: '请选择开始日期!' }]} noStyle>
+                                            {/*  @ts-ignore */}
+                                            <DatePicker placeholder="开始日期" disabledDate={disabledDateStart} />
+                                        </Form.Item>
+                                        <span>-</span>
+                                        <Form.Item name="endDay" rules={[{ required: true, message: '请选择结束日期!' }]} noStyle>
+                                            {/* @ts-ignore */}
+                                            <DatePicker placeholder="结束日期" disabledDate={disabledDateEnd} />
+                                        </Form.Item>
+                                    </Space>
+                                </Form.Item>
+                                <Form.Item label={<strong>执行时间</strong>} name="timeList" rules={[{ required: true, message: '请添加执行时间!' }]}>
+                                    <SetTime />
+                                </Form.Item>
+                            </>}
+                            <Form.Item label={<strong>修改预算类型</strong>} name="addType" rules={[{ required: true, message: '请选择修改预算类型!' }]}>
+                                <Radio.Group buttonStyle="solid">
+                                    <Radio.Button value="fixed">固定值</Radio.Button>
+                                    <Radio.Button value="percent" disabled={taskType === 'cyc'}>百分比上下浮动修改</Radio.Button>
+                                </Radio.Group>
+                            </Form.Item>
+                            {addType === 'fixed' ? <Form.Item label={<strong>一键起量预算</strong>} name="budget">
+                                <InputNumber placeholder="起量预算,建议设置为出价的10倍" min={200} max={100000} style={{ width: '100%' }} />
+                            </Form.Item> : <>
+                                <Form.Item label={<strong>默认起量预算</strong>} name="defaultBudget" rules={[{ required: true, message: '请输入默认起量预算!' }]}>
+                                    <InputNumber placeholder="默认起量预算,建议设置为出价的10倍" min={200} max={100000} style={{ width: '100%' }} />
+                                </Form.Item>
+                                <Form.Item label={<strong>起量预算百分比</strong>} name="budgetPercent" rules={[{ required: true, message: '请输入起量预算百分比!' }]}>
+                                    <InputNumber placeholder="起量预算,原有基础上下调百分比" style={{ width: '100%' }} addonAfter="%" />
+                                </Form.Item>
+                            </>}
+                        </Form>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </Modal>
+}
+
+interface AdAddTaskProps {
+    selectAdList?: any[]
+    visible?: boolean
+    onClose?: () => void
+    onChange?: (type?: number) => void
+}
+
+const AdAddTask: React.FC<AdAddTaskProps> = ({ selectAdList = [], visible, onClose, onChange }) => {
+
+    /*************************************/
+    const [form] = Form.useForm();
+    const [taskList, setTaskList] = useState<{ label: string, value: number }[]>([])
+
+    const getTaskAllList = useAjax(() => getTaskAllListApi())
+    const adAddTask = useAjax((params) => adAddTaskApi(params))
+    /*************************************/
+
+    useEffect(() => {
+        getTaskAllList.run().then(res => {
+            if (res?.data) {
+                setTaskList(Object.keys(res?.data).map(key => ({ label: res.data[key], value: Number(key) })))
+            }
+        })
+    }, [])
+
+    const handleOk = () => {
+        form.validateFields().then((values) => {
+            adAddTask.run({ ...values, adgroupBeanList: selectAdList.map(item => ({ accountId: item.accountId, adgroupId: item.adgroupId })) }).then(res => {
+                if (res?.data) {
+                    message.success('添加成功')
+                    onChange?.(1)
+                }
+            })
+        })
+    }
+
+    return <Modal
+        title={<strong>添加至一键起量任务</strong>}
+        open={visible}
+        onCancel={onClose}
+        onOk={handleOk}
+        className='modalResetCss'
+        width={600}
+    >
+        <Form
+            form={form}
+            name="addTaks"
+            labelCol={{ span: 5 }}
+            labelAlign="left"
+            colon={false}
+            scrollToFirstError={{
+                behavior: 'smooth',
+                block: 'center'
+            }}
+            onFinishFailed={({ errorFields }) => {
+                message.error(errorFields?.[0]?.errors?.[0])
+            }}
+            onFinish={handleOk}
+        >
+            <Form.Item label={<strong>任务</strong>} name="taskId" rules={[{ required: true, message: '请一键起量任务!' }]}>
+                <Select
+                    showSearch
+                    allowClear
+                    placeholder="一键起量任务"
+                    filterOption={(input, option) =>
+                        ((option?.children ?? '') as any).toLowerCase().includes(input.toLowerCase())
+                    }
+                >
+                    {taskList.map(item => <Select.Option key={item.value} value={item.value}>{item.label}</Select.Option>)}
+                </Select>
+            </Form.Item>
+        </Form>
+    </Modal>
+}
+
+interface TaskLogProps {
+    visible?: boolean
+    onClose?: () => void
+}
+const TaskLog: React.FC<TaskLogProps> = ({ visible, onClose }) => {
+
+    /******************************************/
+    const [queryForm, setQueryForm] = useState<ADQV3.GetAdgroupQuantTaskListProps>({ pageNum: 1, pageSize: 20 })
+    const [adLogData, setAdLogData] = useState<{ taskData: any, visible?: boolean }>({ taskData: {}, visible: false })
+    const [adDetailsData, setAdDetailsData] = useState<{ taskData: any, visible?: boolean }>({ taskData: {}, visible: false })
+    const [adEditData, setAdEditData] = useState<{ initialValues: any, visible?: boolean }>({ initialValues: {}, visible: false })
+    const getAdgroupQuantTaskList = useAjax((params) => getAdgroupQuantTaskListApi(params))
+    const delAdgroupQuantTask = useAjax((params) => delAdgroupQuantTaskApi(params))
+    /******************************************/
+
+    useEffect(() => {
+        getAdgroupQuantTaskList.run(queryForm)
+    }, [queryForm])
+
+    const handleDel = (id: number) => {
+        const hide = message.loading('正在删除...', 0)
+        delAdgroupQuantTask.run({ id }).then((res) => {
+            hide()
+            if (res?.data) {
+                message.success('删除成功')
+                getAdgroupQuantTaskList.refresh()
+            }
+        }).catch(() => hide())
+    }
+
+    return <Drawer
+        title={<strong>一键起量任务列表</strong>}
+        open={visible}
+        onClose={onClose}
+        width={1200}
+        headerStyle={{ padding: '10px 16px' }}
+        maskClosable={false}
+        className={`modalResetCss targetingSelect`}
+    >
+        <Card className="cardResetCss">
+            <div style={{ display: 'flex', flexDirection: 'column', gap: 8, width: '100%' }}>
+                <div style={{ display: 'flex', gap: 8 }}>
+                    <Input.Search placeholder="任务名称" style={{ width: 200 }} onSearch={(val) => setQueryForm({ ...queryForm, taskName: val, pageNum: 1 })} allowClear enterButton />
+                    <Input.Search
+                        placeholder="广告ID(多个,,空格换行)"
+                        style={{ width: 250 }}
+                        onSearch={(val) => {
+                            let valArr: any = []
+                            if (val) {
+                                valArr = val.replace(/[,,\s]/g, ',').split(',').filter((a: any) => a)
+                            }
+                            setQueryForm({ ...queryForm, adgroupIdList: valArr, pageNum: 1 })
+                        }}
+                        allowClear
+                        enterButton
+                    />
+                    {/* @ts-ignore */}
+                    <DatePicker placeholder="开始日期" value={queryForm?.startDay ? moment(queryForm.startDay) : undefined} onChange={(_, dateString) => setQueryForm({ ...queryForm, startDay: dateString, pageNum: 1 })} />
+                    {/* @ts-ignore */}
+                    <DatePicker placeholder="结束日期" value={queryForm?.endDay ? moment(queryForm.endDay) : undefined} onChange={(_, dateString) => setQueryForm({ ...queryForm, endDay: dateString, pageNum: 1 })} />
+                </div>
+                <Table
+                    size={'small'}
+                    bordered
+                    dataSource={getAdgroupQuantTaskList?.data?.data?.records}
+                    rowKey={'id'}
+                    scroll={{ y: 400 }}
+                    pagination={{
+                        pageSize: getAdgroupQuantTaskList?.data?.data?.size || 50,
+                        current: getAdgroupQuantTaskList?.data?.data?.current || 1,
+                        showTotal: total => `总共 ${total} 数据`,
+                        total: getAdgroupQuantTaskList?.data?.data?.total,
+                        showSizeChanger: true,
+                        showLessItems: true,
+                        defaultCurrent: 1,
+                        defaultPageSize: 50,//默认初始的每页条数
+                        onChange: (page, pageSize) => {
+                            setQueryForm({ ...queryForm, pageNum: page, pageSize })
+                        }
+                    }}
+                    loading={getAdgroupQuantTaskList.loading}
+                    columns={[
+                        {
+                            title: '操作',
+                            dataIndex: 'cz',
+                            key: 'cz',
+                            width: 135,
+                            align: 'center',
+                            fixed: 'left',
+                            render(_, record) {
+                                return <div style={{ display: 'flex', gap: 10 }}>
+                                    <a style={{ fontSize: 12 }} onClick={() => {
+                                        setAdDetailsData({ taskData: record, visible: true })
+                                    }}>详情</a>
+                                    <a style={{ fontSize: 12 }} onClick={() => {
+                                        setAdLogData({ taskData: record, visible: true })
+                                    }}>执行日志</a>
+                                    {record?.type === 1 && <a style={{ fontSize: 12 }} onClick={() => {
+                                        setAdEditData({
+                                            initialValues: {
+                                                id: record.id,
+                                                taskType: record.type === 1 ? 'cyc' : 'imm',
+                                                taskName: record.taskName,
+                                                startDay: record?.startDay ? moment(record.startDay) : undefined,
+                                                endDay: record?.endDay ? moment(record.endDay) : undefined,
+                                                timeList: record.timeList,
+                                                addType: record?.budget ? 'fixed' : 'percent',
+                                                budget: record?.budget || 0,
+                                                defaultBudget: record?.defaultBudget || 0,
+                                                budgetPercent: record?.budgetPercent ? record.budgetPercent * 100 : 0,
+                                            }, visible: true
+                                        })
+                                    }}>修改</a>}
+                                    <Popconfirm
+                                        title="确定删除?"
+                                        onConfirm={() => handleDel(record.id)}
+                                    >
+                                        <a style={{ color: 'red', fontSize: 12 }}>删除</a>
+                                    </Popconfirm>
+                                </div>
+                            }
+                        },
+                        {
+                            title: '任务名称',
+                            dataIndex: 'taskName',
+                            key: 'taskName',
+                            width: 80,
+                            align: 'center',
+                            render(value) {
+                                return <span style={{ fontSize: 12 }}>{value}</span>
+                            }
+                        },
+                        {
+                            title: '任务类型',
+                            dataIndex: 'type',
+                            key: 'type',
+                            width: 100,
+                            align: 'center',
+                            render(value) {
+                                return value === 1 ? <Tag color="magenta"><span style={{ fontSize: 12 }}>循环任务</span></Tag> : <Tag color="red"><span style={{ fontSize: 12 }}>立即执行</span></Tag>
+                            }
+                        },
+                        {
+                            title: '任务状态',
+                            dataIndex: 'status',
+                            key: 'status',
+                            align: 'center',
+                            width: 100,
+                            render(value) {
+                                return value === 0 ? <Badge status="warning" text={<span style={{ fontSize: 12 }}>等待执行</span>} /> :
+                                    value === 1 ? <Badge status="processing" text={<span style={{ fontSize: 12 }}>正在执行</span>} /> :
+                                        value === 2 ? <Badge status="success" text={<span style={{ fontSize: 12 }}>执行完成</span>} /> : '--'
+                            }
+                        },
+                        {
+                            title: '执行日期',
+                            dataIndex: 'startDay',
+                            key: 'startDay',
+                            width: 150,
+                            ellipsis: true,
+                            render(value, record) {
+                                return <span style={{ fontSize: 12 }}>{value ? value + '~' + record.endDay : '--'}</span>
+                            }
+                        },
+                        {
+                            title: '执行时间',
+                            dataIndex: 'timeList',
+                            key: 'timeList',
+                            width: 100,
+                            align: 'center',
+                            ellipsis: true,
+                            render(value) {
+                                return <span style={{ fontSize: 12 }}>{value?.length > 0 ? value.toString() : '--'}</span>
+                            }
+                        },
+                        {
+                            title: '一键起量预算',
+                            dataIndex: 'budget',
+                            key: 'budget',
+                            width: 150,
+                            render(value, record) {
+                                return <span style={{ fontSize: 12 }}>{value ? value + '元' : record?.budgetPercent ? (record?.budgetPercent * 100 + `% 默认${record?.defaultBudget}元`) : '--'}</span>
+                            }
+                        },
+                        {
+                            title: '关联广告个数',
+                            dataIndex: 'adCount',
+                            key: 'adCount',
+                            width: 85,
+                            align: 'center',
+                            render(value) {
+                                return <span style={{ fontSize: 12, color: value > 0 ? '#52C41A' : 'red' }}>{(value || value === 0) ? value : '--'}</span>
+                            }
+                        }
+                    ]}
+                />
+            </div>
+        </Card>
+
+        {/* 广告执行记录 */}
+        {adLogData?.visible && <TaskAdLog
+            {...adLogData}
+            onClose={() => {
+                setAdLogData({ visible: false, taskData: {} })
+            }}
+        />}
+
+        {/* 详情 */}
+        {adDetailsData?.visible && <TaskAdDetails
+            {...adDetailsData}
+            onClose={() => {
+                setAdDetailsData({ visible: false, taskData: {} })
+            }}
+        />}
+
+        {/* 修改 */}
+        {adEditData?.visible && <AutoAcquisitionSet
+            {...adEditData}
+            onChange={() => {
+                getAdgroupQuantTaskList?.refresh()
+                setAdEditData({ visible: false, initialValues: {} })
+            }}
+            onClose={() => {
+                setAdEditData({ visible: false, initialValues: {} })
+            }}
+        />}
+    </Drawer>
+}
+
+interface TaskAdLogProps {
+    taskData: any
+    visible?: boolean
+    onClose?: () => void
+}
+
+/**
+ * 广告执行日志
+ * @param param0 
+ */
+const TaskAdLog: React.FC<TaskAdLogProps> = ({ taskData, visible, onClose }) => {
+
+    /************************************/
+    const [queryForm, setQueryForm] = useState<ADQV3.GetAdgroupQuantTaskAdLogListProps>({ pageNum: 1, pageSize: 20, taskId: taskData.id })
+    const getAdgroupQuantTaskAdLogList = useAjax((params) => getAdgroupQuantTaskAdLogListApi(params))
+    /************************************/
+
+    useEffect(() => {
+        getAdgroupQuantTaskAdLogList.run(queryForm)
+    }, [queryForm])
+
+    return <Modal
+        title={<strong>{taskData.taskName} 广告执行日志</strong>}
+        open={visible}
+        onCancel={onClose}
+        className='modalResetCss'
+        width={1000}
+    >
+        <div style={{ display: 'flex', flexDirection: 'column', gap: 8, width: '100%' }}>
+            <div style={{ display: 'flex', gap: 8 }}>
+                <Input.Search placeholder="媒体账号" style={{ width: 160 }} onSearch={(val) => setQueryForm({ ...queryForm, accountId: val, pageNum: 1 })} allowClear enterButton />
+                <Input.Search placeholder="广告ID" style={{ width: 160 }} onSearch={(val) => setQueryForm({ ...queryForm, adgroupId: val, pageNum: 1 })} allowClear enterButton />
+                {/* @ts-ignore */}
+                <DatePicker placeholder="开始日期" style={{ width: 130 }} value={queryForm?.startDay ? moment(queryForm.startDay) : undefined} onChange={(_, dateString) => setQueryForm({ ...queryForm, startDay: dateString, pageNum: 1 })} />
+                {/* @ts-ignore */}
+                <DatePicker placeholder="结束日期" style={{ width: 130 }} value={queryForm?.endDay ? moment(queryForm.endDay) : undefined} onChange={(_, dateString) => setQueryForm({ ...queryForm, endDay: dateString, pageNum: 1 })} />
+                <Select
+                    style={{ width: 110 }}
+                    showSearch
+                    allowClear
+                    placeholder="执行状态"
+                    filterOption={(input, option) =>
+                        ((option?.label ?? '') as any).toLowerCase().includes(input.toLowerCase())
+                    }
+                    value={queryForm.status}
+                    onChange={(e) => setQueryForm({ ...queryForm, status: e, pageNum: 1 })}
+                    options={[{ label: '成功', value: 0 }, { label: '失败', value: 1 }]}
+                />
+            </div>
+            <Table
+                size={'small'}
+                bordered
+                dataSource={getAdgroupQuantTaskAdLogList?.data?.data?.records}
+                rowKey={'id'}
+                scroll={{ y: 400 }}
+                pagination={{
+                    pageSize: getAdgroupQuantTaskAdLogList?.data?.data?.size || 50,
+                    current: getAdgroupQuantTaskAdLogList?.data?.data?.current || 1,
+                    showTotal: total => `总共 ${total} 数据`,
+                    total: getAdgroupQuantTaskAdLogList?.data?.data?.total,
+                    showSizeChanger: true,
+                    showLessItems: true,
+                    defaultCurrent: 1,
+                    defaultPageSize: 50,//默认初始的每页条数
+                    onChange: (page, pageSize) => {
+                        setQueryForm({ ...queryForm, pageNum: page, pageSize })
+                    }
+                }}
+                loading={getAdgroupQuantTaskAdLogList.loading}
+                columns={[
+                    {
+                        title: '起量操作',
+                        dataIndex: 'enabled',
+                        key: 'enabled',
+                        width: 80,
+                        align: 'center',
+                        render(value) {
+                            return <span style={{ fontSize: 12 }}>{value ? '开启' : '关闭'}</span>
+                        }
+                    },
+                    {
+                        title: '媒体账号',
+                        dataIndex: 'accountId',
+                        key: 'accountId',
+                        width: 80,
+                        align: 'center',
+                        render(value) {
+                            return <span style={{ fontSize: 12 }}>{value}</span>
+                        }
+                    },
+                    {
+                        title: '广告ID',
+                        dataIndex: 'adgroupId',
+                        key: 'adgroupId',
+                        width: 96,
+                        align: 'center',
+                        render(value) {
+                            return <span style={{ fontSize: 12 }}>{value}</span>
+                        }
+                    },
+                    {
+                        title: '广告名称',
+                        dataIndex: 'adgroupName',
+                        key: 'adgroupName',
+                        width: 180,
+                        ellipsis: true,
+                        render(value) {
+                            return <span style={{ fontSize: 12 }}>{value}</span>
+                        }
+                    },
+                    {
+                        title: '执行时间',
+                        dataIndex: 'createTime',
+                        key: 'createTime',
+                        width: 135,
+                        ellipsis: true,
+                        align: 'center',
+                        render(value) {
+                            return <span style={{ fontSize: 12 }}>{value}</span>
+                        }
+                    },
+                    {
+                        title: '执行状态',
+                        dataIndex: 'status',
+                        key: 'status',
+                        width: 90,
+                        align: 'center',
+                        render(value) {
+                            return value === 0 ? <Tag color='success'><span style={{ fontSize: 12 }}>成功</span></Tag> : <Tag color="error"><span style={{ fontSize: 12 }}>失败</span></Tag>
+                        }
+                    },
+                    {
+                        title: '结果消息',
+                        dataIndex: 'msg',
+                        key: 'msg',
+                        width: 250,
+                        ellipsis: true,
+                        render(value) {
+                            return <a style={{ fontSize: 12 }} onClick={() => copy(value)}>{value}</a>
+                        }
+                    }
+                ]}
+            />
+        </div>
+    </Modal>
+}
+
+/**
+ * 任务下广告详情
+ * @param param0 
+ * @returns 
+ */
+const TaskAdDetails: React.FC<TaskAdLogProps> = ({ taskData, visible, onClose }) => {
+
+    /************************************/
+    const [queryForm, setQueryForm] = useState<ADQV3.GetAdgroupQuantTaskAdDetailsListProps>({ pageNum: 1, pageSize: 20, taskId: taskData.id })
+    const [selectRowData, setSelectRowData] = useState<any[]>([])
+    const getAdgroupQuantTaskAdDetailsList = useAjax((params) => getAdgroupQuantTaskAdDetailsListApi(params))
+    const delAdgroupQuantTaskAd = useAjax((params) => delAdgroupQuantTaskAdApi(params))
+    /************************************/
+
+    useEffect(() => {
+        getAdgroupQuantTaskAdDetailsList.run(queryForm)
+    }, [queryForm])
+
+    const handleDel = () => {
+        delAdgroupQuantTaskAd.run({
+            taskId: taskData.id,
+            adgroupBeanList: selectRowData.map(item => ({ accountId: item.accountId, adgroupId: item.adgroupId }))
+        }).then(res => {
+            if (res?.data) {
+                message.success('删除成功')
+                getAdgroupQuantTaskAdDetailsList.refresh()
+            }
+        })
+    }
+
+    return <Modal
+        title={<strong>{taskData.taskName} 广告执行日志</strong>}
+        open={visible}
+        onCancel={onClose}
+        className='modalResetCss'
+        width={800}
+    >
+        <div style={{ display: 'flex', flexDirection: 'column', gap: 8, width: '100%' }}>
+            <div style={{ display: 'flex', gap: 8 }}>
+                <Input.Search placeholder="媒体账号" style={{ width: 180 }} onSearch={(val) => setQueryForm({ ...queryForm, accountId: val, pageNum: 1 })} allowClear enterButton />
+                <Input.Search placeholder="广告ID" style={{ width: 180 }} onSearch={(val) => setQueryForm({ ...queryForm, adgroupId: val, pageNum: 1 })} allowClear enterButton />
+                {taskData.type === 1 && <Button type="primary" danger style={{ height: 32, padding: '4px 15px' }} loading={delAdgroupQuantTaskAd.loading} disabled={selectRowData?.length === 0} onClick={handleDel}>删除</Button>}
+            </div>
+            <Table
+                size={'small'}
+                bordered
+                dataSource={getAdgroupQuantTaskAdDetailsList?.data?.data?.records}
+                rowKey={'id'}
+                scroll={{ y: 400 }}
+                pagination={{
+                    pageSize: getAdgroupQuantTaskAdDetailsList?.data?.data?.size || 50,
+                    current: getAdgroupQuantTaskAdDetailsList?.data?.data?.current || 1,
+                    showTotal: total => `总共 ${total} 数据`,
+                    total: getAdgroupQuantTaskAdDetailsList?.data?.data?.total,
+                    showSizeChanger: true,
+                    showLessItems: true,
+                    defaultCurrent: 1,
+                    defaultPageSize: 50,//默认初始的每页条数
+                    onChange: (page, pageSize) => {
+                        setQueryForm({ ...queryForm, pageNum: page, pageSize })
+                    }
+                }}
+                loading={getAdgroupQuantTaskAdDetailsList.loading}
+                columns={[
+                    {
+                        title: '媒体账号',
+                        dataIndex: 'accountId',
+                        key: 'accountId',
+                        width: 80,
+                        align: 'center',
+                        render(value) {
+                            return <span style={{ fontSize: 12 }}>{value}</span>
+                        }
+                    },
+                    {
+                        title: '广告ID',
+                        dataIndex: 'adgroupId',
+                        key: 'adgroupId',
+                        width: 96,
+                        align: 'center',
+                        render(value) {
+                            return <span style={{ fontSize: 12 }}>{value}</span>
+                        }
+                    },
+                    {
+                        title: '广告名称',
+                        dataIndex: 'adgroupName',
+                        key: 'adgroupName',
+                        width: 180,
+                        ellipsis: true,
+                        render(value) {
+                            return <span style={{ fontSize: 12 }}>{value}</span>
+                        }
+                    },
+                    {
+                        title: '加入任务时间',
+                        dataIndex: 'createTime',
+                        key: 'createTime',
+                        width: 135,
+                        ellipsis: true,
+                        align: 'center',
+                        render(value) {
+                            return <span style={{ fontSize: 12 }}>{value}</span>
+                        }
+                    }
+                ]}
+                rowSelection={taskData.type === 1 ? {
+                    selectedRowKeys: selectRowData?.map((item: any) => item.id),
+                    onSelect: (record: { id: number, mpName: string }, selected: boolean) => {
+                        if (selected) {
+                            selectRowData.push({ ...record })
+                            setSelectRowData([...selectRowData])
+                        } else {
+                            let newSelectAccData = selectRowData.filter((item: { id: number }) => item.id !== record.id)
+                            setSelectRowData([...newSelectAccData])
+                        }
+                    },
+                    onSelectAll: (selected: boolean, selectedRows: { id: number }[], changeRows: { id: number }[]) => {
+                        if (selected) {
+                            let newSelectAccData = [...selectRowData]
+                            changeRows.forEach((item: { id: number }) => {
+                                let index = newSelectAccData.findIndex((ite: { id: number }) => ite.id === item.id)
+                                if (index === -1) {
+                                    newSelectAccData.push({ ...item })
+                                }
+                            })
+                            setSelectRowData([...newSelectAccData])
+                        } else {
+                            let newSelectAccData = selectRowData.filter((item: { id: number }) => {
+                                let index = changeRows.findIndex((ite: { id: number }) => ite.id === item.id)
+                                if (index !== -1) {
+                                    return false
+                                } else {
+                                    return true
+                                }
+                            })
+                            setSelectRowData([...newSelectAccData])
+                        }
+                    }
+                } : undefined}
+            />
+        </div>
+    </Modal>
+}
+
+export default React.memo(AutoAcquisitionSetTask);

+ 49 - 0
src/pages/iaaData/components/AutoAcquisitionSet/index.less

@@ -0,0 +1,49 @@
+.autoAcquisitionSet {
+    display: flex;
+
+    .left {
+        width: 60%;
+    }
+
+    .right {
+        flex: auto;
+        overflow: hidden;
+        border: 1px solid #f0f0f0;
+        display: flex;
+        flex-direction: column;
+
+        .header {
+            padding: 8px;
+            font-size: 14px;
+            font-weight: 600;
+            border-bottom: 1px solid #f0f0f0;
+            background: #fafafa;
+        }
+
+        .edit {
+            flex: 1;
+            display: flex;
+            align-items: center;
+            padding: 8px;
+            box-sizing: border-box;
+            width: 100%;
+
+            >div {
+                display: flex;
+                flex-direction: column;
+                gap: 10px;
+                width: 100%;
+            }
+        }
+
+        .tips {
+            border: 1px solid #D4E1FC;
+            border-radius: 18px;
+            display: flex;
+            gap: 8px;
+            padding: 7px 12px;
+            background-color: #f5f8ff;
+            margin-bottom: 10px;
+        }
+    }
+}

+ 182 - 0
src/pages/iaaData/components/AutoAcquisitionSet/index1.less

@@ -0,0 +1,182 @@
+.modalResetCss {
+    // font-family: PingFang SC,Microsoft YaHei UI,Microsoft YaHei,Helvetica Neue,Helvetica,Hiragino Sans GB,Arial,sans-serif;
+    --boder: 8px;
+
+    .ant-modal-content {
+        border-radius: var(--boder) !important;
+    }
+
+    .ant-modal-header {
+        border-radius: var(--boder) var(--boder) 0 0;
+        padding: 8px 16px;
+    }
+
+    .ant-modal-body {
+        padding: 16px;
+    }
+
+    .ant-modal-footer {
+        border-radius: 0 0 var(--boder) var(--boder);
+        padding: 4px 8px;
+
+    }
+
+    .ant-modal-close-x {
+        width: 39px;
+        height: 39px;
+        line-height: 39px;
+    }
+
+    .ant-btn {
+        height: 28px;
+        line-height: normal;
+        border-radius: 6px !important;
+        padding: 3px 11px;
+    }
+
+    .ant-transfer .ant-btn {
+        padding: 0px 0;
+        height: 24px;
+    }
+
+    .ant-space .ant-form-item {
+        margin-bottom: 16px;
+    }
+
+    .ant-transfer-list,
+    .ant-picker,
+    .ant-input,
+    .ant-select-selector,
+    .ant-input-affix-wrapper,
+    .ant-input-number-input,
+    .ant-input-number {
+        border-radius: var(--boder) !important;
+    }
+
+    .ant-transfer-list-header {
+        border-radius: var(--boder) var(--boder) 0 0 !important;
+    }
+
+    .ant-input-group {
+        .ant-input-affix-wrapper:not(:last-child) {
+            border-top-right-radius: 0 !important;
+            border-bottom-right-radius: 0 !important;
+            .ant-input {
+                border-top-right-radius: 0 !important;
+                border-bottom-right-radius: 0 !important;
+            }
+        }
+        .ant-btn {
+            border-radius: 0 6px 6px 0 !important;
+            height: 32px;
+            padding: 4px 15px;
+        }
+    }
+
+    .ant-table-tbody td {
+        font-size: 12px;
+        font-family: PingFang SC, Microsoft YaHei UI, Microsoft YaHei, Helvetica Neue, Helvetica, Hiragino Sans GB, Arial, sans-serif;
+    }
+}
+
+.selectModal {
+    .ant-modal-footer {
+        padding: 0 8px;
+    }
+}
+
+.cardResetCss {
+    --boder: 8px;
+    border-radius: var(--boder);
+
+    .ant-card-head {
+        padding: 0 16px;
+        min-height: auto;
+        border-radius: var(--boder) var(--boder) 0 0;
+    }
+
+    .ant-card-extra,
+    .ant-card-head-title {
+        padding: 8px 0;
+    }
+
+    .ant-card-body {
+        padding: 16px;
+    }
+
+}
+
+.newCss {
+    .ant-form-item-label {
+        padding: 0 !important;
+    }
+}
+
+// .ant-radio-button-wrapper {
+//     height: 28px;
+//     line-height: 28px;
+//     padding: 0 6px;
+// }
+
+.ant-radio-button-wrapper:first-child {
+    border-radius: 6px 0 0 6px !important;
+}
+
+.ant-radio-button-wrapper:last-child {
+    border-radius: 0 6px 6px 0 !important;
+}
+
+.submit_pull {
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    padding: 4px 8px !important;
+    background-color: #FFF;
+    border-radius: 0 0 8px 8px;
+    margin-bottom: 0 !important;
+    text-align: right;
+}
+
+.targetingSelect .ant-drawer-body {
+    height: 100%;
+    overflow: hidden;
+    padding: 8px;
+    background-color: rgb(241, 244, 252);
+}
+
+
+.flexSpaceBetween {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+}
+
+.flexStart {
+    display: flex;
+    align-items: center;
+    gap: var(--g, 0);
+}
+
+.flexColumnStart {
+    display: flex;
+    flex-direction: column;
+    gap: var(--g, 0);
+}
+
+
+.buttonResetCss {
+    .ant-btn {
+        font-size: 12px;
+        height: 28px;
+        padding: 3px 11px;
+        border-radius: 6px;
+    }
+    
+}
+
+.formItemResetCss {
+    .ant-form-item-control-input {
+        min-height: auto;
+    }
+}

+ 117 - 0
src/pages/iaaData/components/AutoAcquisitionSet/setTime.tsx

@@ -0,0 +1,117 @@
+import { Button, DatePicker, Form, message, Modal, Popconfirm, Table } from 'antd';
+import React, { useState } from 'react';
+import './index1.less'
+import moment from 'moment';
+
+interface SetConfigProps {
+    value?: string[]
+    onChange?: (value: string[]) => void
+}
+
+const SetTime: React.FC<SetConfigProps> = ({ value = [], onChange }) => {
+
+    /*************************************/
+    const [visible, setVisible] = useState<boolean>(false)
+    /*************************************/
+
+    return <div>
+        <Button type="primary" onClick={() => setVisible(true)}>添加执行时间</Button>
+        {value?.length > 0 && <Table
+            style={{ marginTop: 10 }}
+            dataSource={value.map((item, index) => ({ time: item, id: index + 1 }))}
+            columns={[
+                {
+                    title: '执行时间',
+                    dataIndex: 'time',
+                    key: 'time',
+                    align: 'center',
+                    width: 100
+                },
+                {
+                    title: '操作',
+                    dataIndex: 'cz',
+                    key: 'cz',
+                    render(_, record) {
+                        return <Popconfirm
+                            title="确定删除该项?"
+                            onConfirm={() => {
+                                onChange?.(value?.filter((_, index) => record.id !== (index + 1)))
+                            }}
+                        >
+                            <a>删除</a>
+                        </Popconfirm>
+                    },
+                },
+            ]}
+            rowKey={'id'}
+            size='small'
+            bordered
+            pagination={false}
+        />}
+        {visible && <SetConfigModal
+            visible={visible}
+            onClose={() => setVisible(false)}
+            onChange={(newValue) => {
+                setVisible(false)
+                const oldValue = JSON.parse(JSON.stringify(value || []))
+                oldValue.push(newValue)
+                const set = new Set(oldValue)
+                onChange?.([...set] as string[])
+            }}
+        />}
+    </div>
+};
+
+interface SetConfigModalProps {
+    onChange?: (value: string) => void
+    visible?: boolean;
+    onClose?: () => void;
+}
+const SetConfigModal: React.FC<SetConfigModalProps> = ({ visible, onChange, onClose }) => {
+
+    /***********************************/
+    const [form] = Form.useForm();
+    /***********************************/
+
+    const handleOk = () => {
+        form.validateFields().then((values) => {
+            onChange?.(moment(values.time).format('HH:mm'))
+        })
+    }
+
+    return <Modal
+        title={<strong>添加执行时间</strong>}
+        open={visible}
+        onCancel={onClose}
+        onOk={handleOk}
+        className='modalResetCss'
+    >
+        <Form
+            form={form}
+            name="newConfig"
+            labelAlign='left'
+            labelCol={{ span: 5 }}
+            colon={false}
+            scrollToFirstError={{
+                behavior: 'smooth',
+                block: 'center'
+            }}
+            onFinishFailed={({ errorFields }) => {
+                message.error(errorFields?.[0]?.errors?.[0])
+            }}
+            onFinish={handleOk}
+        >
+            <Form.Item label={<strong>执行时间</strong>} name="time" rules={[{ required: true, message: '请选择充值类型!' }]}>
+                {/* @ts-ignore */}
+                <DatePicker
+                    picker={'time'}
+                    format={'HH:mm'}
+                    minuteStep={15}
+                    style={{ width: '100%' }}
+                />
+            </Form.Item>
+        </Form>
+    </Modal>
+};
+
+export default React.memo(SetTime);

+ 11 - 0
src/pages/iaaData/const.tsx

@@ -123,6 +123,17 @@ export enum MARKETING_TARGET_TYPE_ENUM {
     MARKETING_TARGET_TYPE_WECHAT_WORK = '企业微信'
 }
 
+/** 成本保障状态 */
+export enum COST_GUARANTEE_STATUS_ENUM {
+	COST_GUARANTEE_STATUS_NONE = '无成本保障状态',
+	COST_GUARANTEE_STATUS_EFFECTIVE = '成本保障生效中',
+	COST_GUARANTEE_STATUS_FAILED = '成本保障已失效',
+	COST_GUARANTEE_STATUS_FINISHED = '成本保障已结束',
+	COST_GUARANTEE_STATUS_CONFIRMING = '成本保障确认中',
+	COST_GUARANTEE_STATUS_SUCCEEDED = '超成本赔付已完成',
+	COST_GUARANTEE_STATUS_FROZEN = '成本保障已冻结'
+}
+
 /**广告组推广目标类型*/
 export enum PromotedObjectType {
     PROMOTED_OBJECT_TYPE_WECHAT_OFFICIAL_ACCOUNT = '微信公众号',

+ 21 - 2
src/pages/iaaData/game/tencent/adList/index.tsx

@@ -1,4 +1,4 @@
-import React, { useEffect, useState } from "react"
+import React, { useCallback, useEffect, useState } from "react"
 import { useAjax } from "@/Hook/useAjax"
 import { getGDTListApi, GetGDTListProps, getGDTTotalApi } from "@/services/iaaData"
 import TablePro from "@/components/TablePro"
@@ -7,11 +7,12 @@ import QueryForm from "@/components/QueryForm"
 import moment from "moment"
 import { useModel } from "umi"
 import { Button, Dropdown, message, Space } from "antd"
-import { modifyStatusBatchApi } from "@/services/gameData"
+import { modifyStatusBatchApi, syncBatchApi } from "@/services/gameData"
 import { DeleteOutlined, DownOutlined, PauseCircleOutlined, PlayCircleOutlined } from "@ant-design/icons"
 import DayAd from "./dayAd"
 import AutoAcquisitionSet from "@/pages/iaaData/novel/tencent/adList/autoAcquisitionSet"
 import UpdateAd3 from "@/pages/iaaData/components/UpdateAd3"
+import AutoAcquisitionSetTask from "@/pages/iaaData/components/AutoAcquisitionSet/autoAcquisitionSetTask"
 
 /**
  * 腾讯广告列表
@@ -38,6 +39,7 @@ const TencentIaaAd: React.FC = () => {
     const modifyStatusBatch = useAjax((params) => modifyStatusBatchApi(params))
     const getGDTList = useAjax((params) => getGDTListApi(params))
     const getGDTTotal = useAjax((params) => getGDTTotalApi(params))
+    const syncBatch = useAjax((params) => syncBatchApi(params))
     /****************************************/
 
     useEffect(() => {
@@ -90,6 +92,19 @@ const TencentIaaAd: React.FC = () => {
         })
     }
 
+    // 同步 
+    const sync = useCallback(() => {
+        if (selectedRows?.length > 0) {
+            let accountAdgroupMaps = [...new Set(selectedRows?.map(item => item.accountId + ',' + item.promotionId))]
+            syncBatch.run({ accountAdgroupMaps }).then(res => {
+                res?.data && getGDTList.refresh()
+                res?.data ? message.success('同步成功!') : message.error('同步失败!')
+            })
+        } else {
+            message.error('请勾选需要同步的广告')
+        }
+
+    }, [getGDTList, selectedRows])
 
     return <div>
         <TablePro
@@ -97,6 +112,7 @@ const TencentIaaAd: React.FC = () => {
                 {/* <Switch checkedChildren="开启全选" unCheckedChildren="关闭全选" checked={!isZj} onChange={(e) => { setIsZj(!e); }} /> */}
                 <Button type='primary' style={{ background: '#67c23a', borderColor: '#67c23a' }} loading={modifyStatusBatch.loading} icon={<PlayCircleOutlined />} disabled={selectedRows.length === 0} onClick={() => adStatus(true)}>启动</Button>
                 <Button type='primary' style={{ background: '#e6a23c', borderColor: '#e6a23c' }} loading={modifyStatusBatch.loading} icon={<PauseCircleOutlined />} disabled={selectedRows.length === 0} onClick={() => adStatus(false)}>暂停</Button>
+                <Button type='primary' loading={syncBatch.loading} disabled={selectedRows.length === 0} onClick={sync}>同步</Button>
                 <Button type='primary' danger icon={<DeleteOutlined />} disabled={selectedRows.length === 0} onClick={() => {
                     setUpdateDate({ visible: true, type: '删除' })
                 }}>删除</Button>
@@ -151,6 +167,9 @@ const TencentIaaAd: React.FC = () => {
                         </Space>
                     </Button>
                 </Dropdown>
+                <AutoAcquisitionSetTask
+                    selectAdList={selectedRows.map(item => ({ ...item, adgroupId: item.promotionId }))}
+                />
                 <span style={{ color: 'red' }}>操作完数据结果延时5分钟之内,即时结果去腾讯后台查看</span>
             </Space>}
             leftChild={<QueryForm

+ 22 - 2
src/pages/iaaData/novel/tencent/adList/index.tsx

@@ -1,4 +1,4 @@
-import React, { useEffect, useState } from "react"
+import React, { useCallback, useEffect, useState } from "react"
 import { useAjax } from "@/Hook/useAjax"
 import { getNovelGDTListApi, GetNovelGDTListProps, getNovelGDTTotalApi } from "@/services/iaaData"
 import TablePro from "@/components/TablePro"
@@ -6,12 +6,13 @@ import columns12 from "./tableConfig"
 import moment from "moment"
 import { useModel } from "umi"
 import { Button, Dropdown, message, Select, Space, Switch } from "antd"
-import { modifyStatusBatchApi } from "@/services/gameData"
+import { modifyStatusBatchApi, syncBatchApi } from "@/services/gameData"
 import { DeleteOutlined, DownOutlined, PauseCircleOutlined, PlayCircleOutlined } from "@ant-design/icons"
 import DayAd from "./dayAd"
 import QueryFormNovel from "@/components/QueryForm/queryFormNovel"
 import UpdateAd3 from "@/pages/iaaData/components/UpdateAd3"
 import AutoAcquisitionSet from "./autoAcquisitionSet"
+import AutoAcquisitionSetTask from "@/pages/iaaData/components/AutoAcquisitionSet/autoAcquisitionSetTask"
 
 /**
  * 腾讯广告列表
@@ -40,6 +41,7 @@ const TencentNovelAd: React.FC<{ configName?: string, dayConfigName?: string }>
     const modifyStatusBatch = useAjax((params) => modifyStatusBatchApi(params))
     const getGDTList = useAjax((params) => getNovelGDTListApi(params))
     const getGDTTotal = useAjax((params) => getNovelGDTTotalApi(params))
+    const syncBatch = useAjax((params) => syncBatchApi(params))
     /****************************************/
 
     useEffect(() => {
@@ -95,6 +97,20 @@ const TencentNovelAd: React.FC<{ configName?: string, dayConfigName?: string }>
         })
     }
 
+    // 同步 
+    const sync = useCallback(() => {
+        if (selectedRows?.length > 0) {
+            let accountAdgroupMaps = [...new Set(selectedRows?.map(item => item.accountId + ',' + item.adgroupId))]
+            syncBatch.run({ accountAdgroupMaps }).then(res => {
+                res?.data && getGDTList.refresh()
+                res?.data ? message.success('同步成功!') : message.error('同步失败!')
+            })
+        } else {
+            message.error('请勾选需要同步的广告')
+        }
+
+    }, [getGDTList, selectedRows])
+
     return <div>
         <TablePro
             czChild={<Space>
@@ -111,6 +127,7 @@ const TencentNovelAd: React.FC<{ configName?: string, dayConfigName?: string }>
                 />
                 <Button type='primary' style={{ background: '#67c23a', borderColor: '#67c23a' }} loading={modifyStatusBatch.loading} icon={<PlayCircleOutlined />} disabled={selectedRows.length === 0} onClick={() => adStatus(true)}>启动</Button>
                 <Button type='primary' style={{ background: '#e6a23c', borderColor: '#e6a23c' }} loading={modifyStatusBatch.loading} icon={<PauseCircleOutlined />} disabled={selectedRows.length === 0} onClick={() => adStatus(false)}>暂停</Button>
+                <Button type='primary' loading={syncBatch.loading} disabled={selectedRows.length === 0} onClick={sync}>同步</Button>
                 {handleType === 1 ? <>
                     <Button type='primary' danger icon={<DeleteOutlined />} disabled={selectedRows.length === 0} onClick={() => {
                         setUpdateDate({ visible: true, type: '删除' })
@@ -166,6 +183,9 @@ const TencentNovelAd: React.FC<{ configName?: string, dayConfigName?: string }>
                             </Space>
                         </Button>
                     </Dropdown>
+                    <AutoAcquisitionSetTask
+                        selectAdList={selectedRows}
+                    />
                 </> : handleType === 3 ? <>
                     <Button type='primary' disabled={selectedRows.length === 0} onClick={() => {
                         setUpdateDate({ visible: true, type: '深度优化ROI' })

+ 16 - 3
src/pages/iaaData/novel/tencent/adList/tableConfig.tsx

@@ -1,13 +1,13 @@
 import WidthEllipsis from "@/components/widthEllipsis"
 import { Badge, Progress, Space, Statistic, Tag } from "antd"
 import React from "react"
-import { ADGROUP_STATUS, BID_MODE_ENUM, MARKETING_GOAL_ENUM, MARKETING_TARGET_TYPE_ENUM, OPTIMIZATIONGOAL_ENUM, PRODUCT_TYPE_ENUM, SMART_BID_TYPE_ENUM } from "../../../const"
+import { ADGROUP_STATUS, BID_MODE_ENUM, COST_GUARANTEE_STATUS_ENUM, MARKETING_GOAL_ENUM, MARKETING_TARGET_TYPE_ENUM, OPTIMIZATIONGOAL_ENUM, PRODUCT_TYPE_ENUM, SMART_BID_TYPE_ENUM } from "../../../const"
 import SwitchStatus from "./switchStatus"
 import CreativePreview from "../../../components/CreativePreview"
 import TimeSeriesLook from "@/pages/iaaData/components/TimeSeriesLook"
 import { AUTO_ACQUISTION_STATUS } from "./const"
 
-function columns12(dayHandle: (data: any) => void, onChange?: () => void): { label: string, fieldSHow?: { label: string, saveField: string, defaultValue: any[], data: any[] }, data: any[] }[] {
+function columns12(dayHandle: (data: any) => void, onChange?: () => void): { label: string, fieldSHow?: { label: string, saveField: string, defaultValue: any[], data: any[] }, data: any[], bcColor?: string }[] {
 
 
     return [
@@ -151,6 +151,16 @@ function columns12(dayHandle: (data: any) => void, onChange?: () => void): { lab
                     title: '书名', dataIndex: 'bookName', label: '广告基本信息', align: 'center', width: 110, default: 23,
                     render: (a: string) => (<WidthEllipsis value={a} />)
                 },
+                {
+                    title: '成本保障状态', dataIndex: 'costGuaranteeStatus', label: '广告基本信息', align: 'center', width: 85,
+                    render: (a: string) => (<WidthEllipsis value={COST_GUARANTEE_STATUS_ENUM[a as keyof typeof COST_GUARANTEE_STATUS_ENUM]} />)
+                },
+                {
+                    title: '成本保障赔付金额', dataIndex: 'costGuaranteeMoney', label: '广告基本信息', align: 'right', width: 70, sorter: true,
+                    render: (a: string) => {
+                        return <Statistic value={a || 0} precision={2} />
+                    }
+                },
                 {
                     title: '标记备注', dataIndex: 'tagRemark', label: '广告基本信息', align: 'center', width: 80, default: 24,
                     render: (a: string) => (<WidthEllipsis value={a} />)
@@ -351,6 +361,7 @@ function columns12(dayHandle: (data: any) => void, onChange?: () => void): { lab
         },
         {
             label: '其他业务(平台上报指标)',
+            bcColor: '#f6ffed',
             data: [
                 {
                     title: '激活首24小时广告变现ARPPU(平台上报)', dataIndex: 'firstDayAdPurArppuCost24hPla', label: '其他业务(平台上报指标)', width: 130, align: 'center', sorter: true, className: 'green2ColorClass',
@@ -416,6 +427,7 @@ function columns12(dayHandle: (data: any) => void, onChange?: () => void): { lab
         },
         {
             label: '其他业务(其他指标)',
+            bcColor: '#fff2e8',
             data: [
                 {
                     title: '激活首24小时广告变现ARPPU', dataIndex: 'firstDayAdPurArppuCost24h', label: '其他业务(其他指标)', width: 100, align: 'center', sorter: true, className: 'volcanoColorClass',
@@ -534,7 +546,7 @@ function columns12(dayHandle: (data: any) => void, onChange?: () => void): { lab
                     render: (a: string) => <Statistic value={a || 0} precision={2} />
                 },
                 {
-                    title: '注册率', dataIndex: 'regRate', label: '其他业务(其他指标)', width: 110, align: 'center', sorter: true, className: 'purple1ColorClass',
+                    title: '注册率', dataIndex: 'regRate', label: '其他业务(其他指标)', width: 110, align: 'center', sorter: true, className: 'volcanoColorClass',
                     render: (a: number) => <Statistic value={a ? a * 100 : 0} precision={2} valueStyle={!a ? {} : a >= 0.5 ? { color: 'red' } : { color: '#0f990f' }} suffix="%" />
                 },
                 {
@@ -573,6 +585,7 @@ function columns12(dayHandle: (data: any) => void, onChange?: () => void): { lab
         },
         {
             label: '小游戏(平台上报)',
+            bcColor: '#f9f0ff',
             data: [
                 {
                     title: '小游戏注册首日广告变现ARPU(平台上报)', dataIndex: 'miniGameFirstDayAdPayingArpu', label: '小游戏(平台上报)', width: 130, align: 'center', sorter: true, className: 'purple1ColorClass',

+ 5 - 2
src/pages/iaaData/novel/tencent/adList/tableConfigDay.tsx

@@ -1,9 +1,9 @@
 import WidthEllipsis from "@/components/widthEllipsis"
 import { Progress, Statistic } from "antd"
 import React from "react"
-import { AdUnitType_Enum, MARKETING_GOAL_ENUM, MARKETING_TARGET_TYPE_ENUM, PRODUCT_TYPE_ENUM } from "../../../const"
+import { PRODUCT_TYPE_ENUM } from "../../../const"
 
-function columns12(): { label: string, fieldSHow?: { label: string, saveField: string, defaultValue: any[], data: any[] }, data: any[] }[] {
+function columns12(): { label: string, fieldSHow?: { label: string, saveField: string, defaultValue: any[], data: any[] }, data: any[], bcColor?: string }[] {
 
 
     return [
@@ -225,6 +225,7 @@ function columns12(): { label: string, fieldSHow?: { label: string, saveField: s
         },
         {
             label: '其他业务(平台上报指标)',
+            bcColor: '#f6ffed',
             data: [
                 {
                     title: '激活首24小时广告变现ARPPU(平台上报)', dataIndex: 'firstDayAdPurArppuCost24hPla', label: '其他业务(平台上报指标)', width: 130, align: 'center', sorter: true, className: 'green2ColorClass',
@@ -290,6 +291,7 @@ function columns12(): { label: string, fieldSHow?: { label: string, saveField: s
         },
         {
             label: '其他业务(其他指标)',
+            bcColor: '#fff2e8',
             data: [
                 {
                     title: '激活首24小时广告变现ARPPU', dataIndex: 'firstDayAdPurArppuCost24h', label: '其他业务(其他指标)', width: 100, align: 'center', sorter: true, className: 'volcanoColorClass',
@@ -447,6 +449,7 @@ function columns12(): { label: string, fieldSHow?: { label: string, saveField: s
         },
         {
             label: '小游戏(平台上报)',
+            bcColor: '#f9f0ff',
             data: [
                 {
                     title: '小游戏注册首日广告变现ARPU(平台上报)', dataIndex: 'miniGameFirstDayAdPayingArpu', label: '小游戏(平台上报)', width: 130, align: 'center', sorter: true, className: 'purple1ColorClass',

+ 59 - 51
src/pages/iaaData/novel/tencent/appEveryDayData/tableConfig.tsx

@@ -5,7 +5,7 @@ import { PRODUCT_TYPE_ENUM } from "../../../const"
 import { APPTYPE } from "@/pages/iaaSystem/manage/const"
 import './index.less'
 
-function columns12(): { label: string, fieldSHow?: { label: string, saveField: string, defaultValue: any[], data: any[] }, data: any[] }[] {
+function columns12(): { label: string, fieldSHow?: { label: string, saveField: string, defaultValue: any[], data: any[] }, data: any[], bcColor?: string }[] {
 
     return [
         {
@@ -289,118 +289,126 @@ function columns12(): { label: string, fieldSHow?: { label: string, saveField: s
             ]
         },
         {
-            label: '应用数据',
+            label: '广告数据(颜色:明青)',
+            bcColor: '#e6fffb',
             data: [
                 {
-                    title: '点击数(应用端)', dataIndex: 'appClickCount', label: '应用数据', align: 'center', width: 80, sorter: true, className: 'payDataBackColorClass',
-                    render: (a: number) => <Statistic value={a || 0} />
-                },
-                {
-                    title: '曝光次数(应用端)', dataIndex: 'appExposureCount', label: '应用数据', align: 'center', width: 80, sorter: true, className: 'payDataBackColorClass',
-                    render: (a: number) => <Statistic value={a || 0} />
-                },
-                {
-                    title: '拉取次数(应用端)', dataIndex: 'appReqSuccCount', label: '应用数据', align: 'center', width: 80, sorter: true, className: 'payDataBackColorClass',
-                    render: (a: number) => <Statistic value={a || 0} />
+                    title: '累计消耗(广告端)', dataIndex: 'totalCost', label: '广告数据', align: 'right', width: 110, sorter: true, className: 'adColorClass',
+                    render: (a: string) => <Statistic value={a || 0} precision={2} />
                 },
                 {
-                    title: '曝光率(应用端)', dataIndex: 'appExposureRate', label: '应用数据', align: 'center', width: 70, sorter: true, className: 'payDataBackColorClass',
-                    render: (a: number) => <Statistic value={a ? a * 100 : 0} precision={2} valueStyle={!a ? {} : a >= 50 ? { color: 'red' } : { color: '#0f990f' }} suffix="%" />
+                    title: '广告端累计变现收入(广告端)', dataIndex: 'adTotalIncome', label: '广告数据', align: 'right', width: 95, sorter: true, className: 'adColorClass',
+                    render: (a: string) => <Statistic value={a || 0} precision={2} />
                 },
                 {
-                    title: '点击率(应用端)', dataIndex: 'appClickRate', label: '应用数据', align: 'center', width: 70, sorter: true, className: 'payDataBackColorClass',
+                    title: '广告端累计回收(广告端)', dataIndex: 'adTotalRecycle', label: '广告数据', align: 'right', width: 90, sorter: true, className: 'adColorClass',
                     render: (a: number) => <Statistic value={a ? a * 100 : 0} precision={2} valueStyle={!a ? {} : a >= 50 ? { color: 'red' } : { color: '#0f990f' }} suffix="%" />
                 },
                 {
-                    title: 'eCPM(应用端)', tips: '计算公式:单日总广告收入/曝光次数*1000', dataIndex: 'appEcpm', label: '应用数据', align: 'center', width: 80, sorter: true, className: 'payDataBackColorClass',
-                    render: (a: number, b: any) => <Statistic value={a || 0} precision={2} />
-                },
-                {
-                    title: '累计消耗(广告端)', dataIndex: 'totalCost', label: '应用数据', align: 'right', width: 75, sorter: true, className: 'payDataBackColorClass',
+                    title: '广告端变现累计利润(广告端)', dataIndex: 'adTotalRate', label: '广告数据', align: 'right', width: 95, sorter: true, className: 'adColorClass',
                     render: (a: string) => <Statistic value={a || 0} precision={2} />
                 },
                 {
-                    title: '广告端累计变现收入(广告端)', dataIndex: 'adTotalIncome', label: '应用数据', align: 'right', width: 95, sorter: true, className: 'payDataBackColorClass',
-                    render: (a: string) => <Statistic value={a || 0} precision={2} />
+                    title: '广告端变现利润率(广告端)', dataIndex: 'appTotalProfitRate', tips: '计算公式:(广告端累计变现收入-累计消耗)/累计消耗*100%', label: '广告数据', align: 'center', width: 110, sorter: true, className: 'adColorClass',
+                    render: (a: number) => <Statistic value={a ? a * 100 : 0} precision={2} valueStyle={!a ? {} : a >= 50 ? { color: 'red' } : { color: '#0f990f' }} suffix="%" />
                 },
                 {
-                    title: '应用端每日变现收入(应用端)', dataIndex: 'appIncome', label: '应用数据', align: 'right', width: 95, sorter: true, className: 'payDataBackColorClass',
-                    render: (a: string) => <Statistic value={a || 0} precision={2} />
+                    title: '广告新增ARPU(广告端)', dataIndex: 'adNewArpu', tips: ' 计算公式:广告端变现收入/每日新增注册人数', label: '广告数据', align: 'center', width: 105, sorter: true, className: 'adColorClass',
+                    render: (a: number) => <Statistic value={a || 0} precision={2} />
                 },
                 {
-                    title: '应用端累计变现收入(应用端)', dataIndex: 'appTotalIncome', label: '应用数据', align: 'right', width: 95, sorter: true, className: 'payDataBackColorClass',
-                    render: (a: string) => <Statistic value={a || 0} precision={2} />
-                },
+                    title: '广告总ARPU(广告端)', dataIndex: 'adTotalArpu', tips: '计算公式:广告端累计变现收入/累计注册人数', label: '广告数据', align: 'center', width: 105, sorter: true, className: 'adColorClass',
+                    render: (a: number) => <Statistic value={a || 0} precision={2} />
+                }
+            ]
+        },
+        {
+            label: '应用数据(颜色:法式洋红)',
+            bcColor: '#fff0f6',
+            data: [
                 {
-                    title: '每日新增注册人数(应用端)', dataIndex: 'appNewRegUser', label: '应用数据', align: 'center', width: 95, sorter: true, className: 'payDataBackColorClass',
+                    title: '点击数(应用端)', dataIndex: 'appClickCount', label: '应用数据', align: 'center', width: 80, sorter: true, className: 'appColorClass',
                     render: (a: number) => <Statistic value={a || 0} />
                 },
                 {
-                    title: '新增注册成本(应用端)', dataIndex: 'appNewRegUserCost', label: '应用数据', align: 'right', width: 90, sorter: true, className: 'payDataBackColorClass',
-                    render: (a: string) => <Statistic value={a || 0} precision={2} />
+                    title: '曝光次数(应用端)', dataIndex: 'appExposureCount', label: '应用数据', align: 'center', width: 80, sorter: true, className: 'appColorClass',
+                    render: (a: number) => <Statistic value={a || 0} />
                 },
                 {
-                    title: '每日活跃人数(DAU)(应用端)', dataIndex: 'appActiveUser', label: '应用数据', align: 'center', width: 95, sorter: true, className: 'payDataBackColorClass',
+                    title: '拉取次数(应用端)', dataIndex: 'appReqSuccCount', label: '应用数据', align: 'center', width: 80, sorter: true, className: 'appColorClass',
                     render: (a: number) => <Statistic value={a || 0} />
                 },
                 {
-                    title: '活跃用户次日留存人数(应用端)', dataIndex: 'appNextActiveUser', label: '应用数据', align: 'center', width: 95, sorter: true, className: 'payDataBackColorClass',
-                    render: (a: number) => <Statistic value={a || 0} />
+                    title: '曝光率(应用端)', dataIndex: 'appExposureRate', label: '应用数据', align: 'center', width: 70, sorter: true, className: 'appColorClass',
+                    render: (a: number) => <Statistic value={a ? a * 100 : 0} precision={2} valueStyle={!a ? {} : a >= 50 ? { color: 'red' } : { color: '#0f990f' }} suffix="%" />
                 },
                 {
-                    title: '活跃用户次日留存率(应用端)', dataIndex: 'appNextActiveUserRate', tips: '计算公式:活跃用户次日留存人数/每日活跃人数DAU', label: '应用数据', align: 'center', width: 110, sorter: true, className: 'payDataBackColorClass',
+                    title: '点击率(应用端)', dataIndex: 'appClickRate', label: '应用数据', align: 'center', width: 70, sorter: true, className: 'appColorClass',
                     render: (a: number) => <Statistic value={a ? a * 100 : 0} precision={2} valueStyle={!a ? {} : a >= 50 ? { color: 'red' } : { color: '#0f990f' }} suffix="%" />
                 },
                 {
-                    title: '人均活跃成本(应用端)', dataIndex: 'appAvgActiveCost', tips: '计算公式:累计消耗/每日活跃人数DAU', label: '应用数据', align: 'right', width: 100, sorter: true, className: 'payDataBackColorClass',
+                    title: 'eCPM(应用端)', tips: '计算公式:单日总广告收入/曝光次数*1000', dataIndex: 'appEcpm', label: '应用数据', align: 'center', width: 80, sorter: true, className: 'appColorClass',
+                    render: (a: number, b: any) => <Statistic value={a || 0} precision={2} />
+                },
+                {
+                    title: '应用端每日变现收入(应用端)', dataIndex: 'appIncome', label: '应用数据', align: 'right', width: 95, sorter: true, className: 'appColorClass',
                     render: (a: string) => <Statistic value={a || 0} precision={2} />
                 },
                 {
-                    title: '新增占比(应用端)', dataIndex: 'newProportion', tips: '计算公式:每日新增注册人数/每日活跃人数DAU', label: '应用数据', align: 'center', width: 85, sorter: true, className: 'payDataBackColorClass',
-                    render: (a: number) => <Statistic value={a ? a * 100 : 0} precision={2} valueStyle={!a ? {} : a >= 50 ? { color: 'red' } : { color: '#0f990f' }} suffix="%" />
+                    title: '应用端累计变现收入(应用端)', dataIndex: 'appTotalIncome', label: '应用数据', align: 'right', width: 95, sorter: true, className: 'appColorClass',
+                    render: (a: string) => <Statistic value={a || 0} precision={2} />
                 },
                 {
-                    title: '累计注册人数(应用端)', dataIndex: 'appTotalRegUser', label: '应用数据', align: 'center', width: 85, sorter: true, className: 'payDataBackColorClass',
+                    title: '每日新增注册人数(应用端)', dataIndex: 'appNewRegUser', label: '应用数据', align: 'center', width: 95, sorter: true, className: 'appColorClass',
                     render: (a: number) => <Statistic value={a || 0} />
                 },
                 {
-                    title: '人均新增成本(应用端)', dataIndex: 'appUserAvgCost', label: '应用数据', align: 'right', width: 80, sorter: true, className: 'payDataBackColorClass',
+                    title: '新增注册成本(应用端)', dataIndex: 'appNewRegUserCost', label: '应用数据', align: 'right', width: 90, sorter: true, className: 'appColorClass',
                     render: (a: string) => <Statistic value={a || 0} precision={2} />
                 },
                 {
-                    title: '广告端累计回收(广告端)', dataIndex: 'adTotalRecycle', label: '应用数据', align: 'right', width: 90, sorter: true, className: 'payDataBackColorClass',
-                    render: (a: number) => <Statistic value={a ? a * 100 : 0} precision={2} valueStyle={!a ? {} : a >= 50 ? { color: 'red' } : { color: '#0f990f' }} suffix="%" />
+                    title: '每日活跃人数(DAU)(应用端)', dataIndex: 'appActiveUser', label: '应用数据', align: 'center', width: 95, sorter: true, className: 'appColorClass',
+                    render: (a: number) => <Statistic value={a || 0} />
                 },
                 {
-                    title: '应用端累计回收(应用端)', dataIndex: 'appTotalRecycle', label: '应用数据', align: 'right', width: 90, sorter: true, className: 'payDataBackColorClass',
+                    title: '活跃用户次日留存人数(应用端)', dataIndex: 'appNextActiveUser', label: '应用数据', align: 'center', width: 95, sorter: true, className: 'appColorClass',
+                    render: (a: number) => <Statistic value={a || 0} />
+                },
+                {
+                    title: '活跃用户次日留存率(应用端)', dataIndex: 'appNextActiveUserRate', tips: '计算公式:活跃用户次日留存人数/每日活跃人数DAU', label: '应用数据', align: 'center', width: 110, sorter: true, className: 'appColorClass',
                     render: (a: number) => <Statistic value={a ? a * 100 : 0} precision={2} valueStyle={!a ? {} : a >= 50 ? { color: 'red' } : { color: '#0f990f' }} suffix="%" />
                 },
                 {
-                    title: '广告端变现累计利润(广告端)', dataIndex: 'adTotalRate', label: '应用数据', align: 'right', width: 95, sorter: true, className: 'payDataBackColorClass',
+                    title: '人均活跃成本(应用端)', dataIndex: 'appAvgActiveCost', tips: '计算公式:累计消耗/每日活跃人数DAU', label: '应用数据', align: 'right', width: 100, sorter: true, className: 'appColorClass',
                     render: (a: string) => <Statistic value={a || 0} precision={2} />
                 },
                 {
-                    title: '广告端变现利润率(广告端)', dataIndex: 'appTotalProfitRate', tips: '计算公式:(广告端累计变现收入-累计消耗)/累计消耗*100%', label: '应用数据', align: 'center', width: 110, sorter: true, className: 'payDataBackColorClass',
+                    title: '新增占比(应用端)', dataIndex: 'newProportion', tips: '计算公式:每日新增注册人数/每日活跃人数DAU', label: '应用数据', align: 'center', width: 85, sorter: true, className: 'appColorClass',
                     render: (a: number) => <Statistic value={a ? a * 100 : 0} precision={2} valueStyle={!a ? {} : a >= 50 ? { color: 'red' } : { color: '#0f990f' }} suffix="%" />
                 },
                 {
-                    title: '广告新增ARPU(广告端)', dataIndex: 'adNewArpu', tips: ' 计算公式:广告端变现收入/每日新增注册人数', label: '应用数据', align: 'center', width: 105, sorter: true, className: 'payDataBackColorClass',
-                    render: (a: number) => <Statistic value={a || 0} precision={2} />
+                    title: '累计注册人数(应用端)', dataIndex: 'appTotalRegUser', label: '应用数据', align: 'center', width: 85, sorter: true, className: 'appColorClass',
+                    render: (a: number) => <Statistic value={a || 0} />
                 },
                 {
-                    title: '广告总ARPU(广告端)', dataIndex: 'adTotalArpu', tips: '计算公式:广告端累计变现收入/累计注册人数', label: '应用数据', align: 'center', width: 105, sorter: true, className: 'payDataBackColorClass',
-                    render: (a: number) => <Statistic value={a || 0} precision={2} />
+                    title: '人均新增成本(应用端)', dataIndex: 'appUserAvgCost', label: '应用数据', align: 'right', width: 80, sorter: true, className: 'appColorClass',
+                    render: (a: string) => <Statistic value={a || 0} precision={2} />
                 },
                 {
-                    title: '人均广告曝光次数(应用端)', dataIndex: 'avgExposureCount', tips: '计算公式:曝光量/每日活跃人数DAU', label: '应用数据', align: 'center', width: 100, sorter: true, className: 'payDataBackColorClass',
+                    title: '应用端累计回收(应用端)', dataIndex: 'appTotalRecycle', label: '应用数据', align: 'right', width: 90, sorter: true, className: 'appColorClass',
+                    render: (a: number) => <Statistic value={a ? a * 100 : 0} precision={2} valueStyle={!a ? {} : a >= 50 ? { color: 'red' } : { color: '#0f990f' }} suffix="%" />
+                },
+
+                {
+                    title: '人均广告曝光次数(应用端)', dataIndex: 'avgExposureCount', tips: '计算公式:曝光量/每日活跃人数DAU', label: '应用数据', align: 'center', width: 100, sorter: true, className: 'appColorClass',
                     render: (a: number) => <Statistic value={a || 0} />
                 },
                 {
-                    title: '应用端广告ARPU(应用端)', dataIndex: 'appAdArpu', tips: '计算公式:应用端每日变现收入/每日活跃人数DAU', label: '应用数据', align: 'center', width: 100, sorter: true, className: 'payDataBackColorClass',
+                    title: '应用端广告ARPU(应用端)', dataIndex: 'appAdArpu', tips: '计算公式:应用端每日变现收入/每日活跃人数DAU', label: '应用数据', align: 'center', width: 100, sorter: true, className: 'appColorClass',
                     render: (a: number) => <Statistic value={a || 0} precision={2} />
                 },
                 {
-                    title: '应用端广告总ARPU(应用端)', dataIndex: 'appAdTotalArpu', tips: '计算公式:应用端累计变现收入/累计注册人数', label: '应用数据', align: 'center', width: 110, sorter: true, className: 'payDataBackColorClass',
+                    title: '应用端广告总ARPU(应用端)', dataIndex: 'appAdTotalArpu', tips: '计算公式:应用端累计变现收入/累计注册人数', label: '应用数据', align: 'center', width: 110, sorter: true, className: 'appColorClass',
                     render: (a: number) => <Statistic value={a || 0} precision={2} />
                 },
             ]

+ 5 - 2
src/pages/iaaData/novel/tencent/dynamic/tableConfig.tsx

@@ -6,7 +6,7 @@ import SwitchStatus from "./switchStatus"
 import CreativePreview from "../../../components/CreativePreview"
 import { DELIVERY_MODE_Enum } from "./const"
 
-function columns12(dayHandle: (data: any) => void, onChange?: (data: any) => void): { label: string, fieldSHow?: { label: string, saveField: string, defaultValue: any[], data: any[] }, data: any[] }[] {
+function columns12(dayHandle: (data: any) => void, onChange?: (data: any) => void): { label: string, fieldSHow?: { label: string, saveField: string, defaultValue: any[], data: any[] }, data: any[], bcColor?: string }[] {
 
 
     return [
@@ -224,7 +224,7 @@ function columns12(dayHandle: (data: any) => void, onChange?: (data: any) => voi
                     render: (a: number) => <Statistic value={a ? a * 100 : 0} precision={2} valueStyle={!a ? {} : a >= 50 ? { color: 'red' } : { color: '#0f990f' }} suffix="%" />
                 },
                 {
-                    title: '下单成本', dataIndex: 'orderCost', label: '商品转化', align: 'right', sorter: true,
+                    title: '下单成本', dataIndex: 'orderCost', label: '商品转化', align: 'right',  width: 70, sorter: true,
                     render: (a: string) => <Statistic value={a || 0} precision={2} />
                 },
                 {
@@ -352,6 +352,7 @@ function columns12(dayHandle: (data: any) => void, onChange?: (data: any) => voi
         },
         {
             label: '其他业务(平台上报指标)',
+            bcColor: '#f6ffed',
             data: [
                 {
                     title: '激活首24小时广告变现ARPPU(平台上报)', dataIndex: 'firstDayAdPurArppuCost24hPla', label: '其他业务(平台上报指标)', width: 130, align: 'center', sorter: true, className: 'green2ColorClass',
@@ -417,6 +418,7 @@ function columns12(dayHandle: (data: any) => void, onChange?: (data: any) => voi
         },
         {
             label: '其他业务(其他指标)',
+            bcColor: '#fff2e8',
             data: [
                 {
                     title: '激活首24小时广告变现ARPPU', dataIndex: 'firstDayAdPurArppuCost24h', label: '其他业务(其他指标)', width: 100, align: 'center', sorter: true, className: 'volcanoColorClass',
@@ -574,6 +576,7 @@ function columns12(dayHandle: (data: any) => void, onChange?: (data: any) => voi
         },
         {
             label: '小游戏(平台上报)',
+            bcColor: '#f9f0ff',
             data: [
                 {
                     title: '小游戏注册首日广告变现ARPU(平台上报)', dataIndex: 'miniGameFirstDayAdPayingArpu', label: '小游戏(平台上报)', width: 130, align: 'center', sorter: true, className: 'purple1ColorClass',

+ 19 - 16
src/pages/iaaData/novel/tencent/dynamic/tableConfigDay.tsx

@@ -3,7 +3,7 @@ import { Progress, Statistic } from "antd"
 import React from "react"
 import { AdUnitType_Enum, PRODUCT_TYPE_ENUM } from "../../../const"
 
-function columns12(): { label: string, fieldSHow?: { label: string, saveField: string, defaultValue: any[], data: any[] }, data: any[] }[] {
+function columns12(): { label: string, fieldSHow?: { label: string, saveField: string, defaultValue: any[], data: any[] }, data: any[], bcColor?: string }[] {
 
 
     return [
@@ -52,7 +52,7 @@ function columns12(): { label: string, fieldSHow?: { label: string, saveField: s
             label: '广告消耗信息',
             data: [
                 {
-                    title: '消耗', dataIndex: 'cost', label: '广告消耗信息', align: 'center', width: 85, default: 10, sorter: true, 
+                    title: '消耗', dataIndex: 'cost', label: '广告消耗信息', align: 'center', width: 85, default: 10, sorter: true,
                     className: 'padding_0',
                     render: (a: number) => <div style={{ height: 27, position: 'relative' }}>
                         <Progress
@@ -102,7 +102,7 @@ function columns12(): { label: string, fieldSHow?: { label: string, saveField: s
                 },
                 {
                     title: '公众号关注成本(点击归因)', dataIndex: 'fromFollowByClickCost', label: '广告转化信息', align: 'right', width: 80, sorter: true,
-                    render: (a: string) => <Statistic value={a || 0} precision={2}/>
+                    render: (a: string) => <Statistic value={a || 0} precision={2} />
                 },
                 {
                     title: '公众号关注率(点击归因)', dataIndex: 'fromFollowByClickRate', label: '广告转化信息', align: 'center', width: 80, sorter: true,
@@ -114,7 +114,7 @@ function columns12(): { label: string, fieldSHow?: { label: string, saveField: s
                 },
                 {
                     title: '公众号关注成本(平台上报)', dataIndex: 'bizFollowCost', label: '广告转化信息', align: 'right', width: 80, sorter: true,
-                    render: (a: string) => <Statistic value={a || 0} precision={2}/>
+                    render: (a: string) => <Statistic value={a || 0} precision={2} />
                 },
                 {
                     title: '公众号关注率(平台上报)', dataIndex: 'bizFollowRate', label: '广告转化信息', align: 'center', width: 80, sorter: true,
@@ -310,10 +310,11 @@ function columns12(): { label: string, fieldSHow?: { label: string, saveField: s
         },
         {
             label: '其他业务(平台上报指标)',
+            bcColor: '#f6ffed',
             data: [
                 {
                     title: '激活首24小时广告变现ARPPU(平台上报)', dataIndex: 'firstDayAdPurArppuCost24hPla', label: '其他业务(平台上报指标)', width: 130, align: 'center', sorter: true, className: 'green2ColorClass',
-                    render: (a: string) => <Statistic value={a || 0} precision={2}/>
+                    render: (a: string) => <Statistic value={a || 0} precision={2} />
                 },
                 {
                     title: '激活首24小时广告变现ROI(平台上报)', dataIndex: 'incomeRoi124hPla', label: '其他业务(平台上报指标)', width: 110, align: 'center', sorter: true, className: 'green2ColorClass',
@@ -375,18 +376,19 @@ function columns12(): { label: string, fieldSHow?: { label: string, saveField: s
         },
         {
             label: '其他业务(其他指标)',
+            bcColor: '#fff2e8',
             data: [
                 {
                     title: '激活首24小时广告变现ARPPU', dataIndex: 'firstDayAdPurArppuCost24h', label: '其他业务(其他指标)', width: 100, align: 'center', sorter: true, className: 'volcanoColorClass',
-                    render: (a: string) => <Statistic value={a || 0} precision={2}/>
+                    render: (a: string) => <Statistic value={a || 0} precision={2} />
                 },
                 {
                     title: '激活首日广告变现ARPPU', dataIndex: 'firstDayAdPurArppuCost', label: '其他业务(其他指标)', width: 90, align: 'center', sorter: true, className: 'volcanoColorClass',
-                    render: (a: string) => <Statistic value={a || 0} precision={2}/>
+                    render: (a: string) => <Statistic value={a || 0} precision={2} />
                 },
                 {
                     title: '广告变现ARPPU', dataIndex: 'adMonetizationArppu', label: '其他业务(其他指标)', width: 80, align: 'center', sorter: true, className: 'volcanoColorClass',
-                    render: (a: string) => <Statistic value={a || 0} precision={2}/>
+                    render: (a: string) => <Statistic value={a || 0} precision={2} />
                 },
                 {
                     title: '激活首24小时广告变现ROI', dataIndex: 'incomeRoi124h', label: '其他业务(其他指标)', width: 90, align: 'center', sorter: true, className: 'volcanoColorClass',
@@ -532,6 +534,7 @@ function columns12(): { label: string, fieldSHow?: { label: string, saveField: s
         },
         {
             label: '小游戏(平台上报)',
+            bcColor: '#f9f0ff',
             data: [
                 {
                     title: '小游戏注册首日广告变现ARPU(平台上报)', dataIndex: 'miniGameFirstDayAdPayingArpu', label: '小游戏(平台上报)', width: 130, align: 'center', sorter: true, className: 'purple1ColorClass',
@@ -611,7 +614,7 @@ function columns12(): { label: string, fieldSHow?: { label: string, saveField: s
                     render: (a: number) => <Statistic value={a ? a * 100 : 0} precision={2} valueStyle={!a ? {} : a >= 0.5 ? { color: 'red' } : { color: '#0f990f' }} suffix="%" />
                 },
                 {
-                    title: '回流次日留存人数', dataIndex: 'retentionPlaDedupPv', label: 'App相关字段', width: 80, align: 'center', sorter: true, 
+                    title: '回流次日留存人数', dataIndex: 'retentionPlaDedupPv', label: 'App相关字段', width: 80, align: 'center', sorter: true,
                     render: (a: string) => <Statistic value={a || 0} />
                 },
                 {
@@ -619,7 +622,7 @@ function columns12(): { label: string, fieldSHow?: { label: string, saveField: s
                     render: (a: number) => <Statistic value={a ? a * 100 : 0} precision={2} valueStyle={!a ? {} : a >= 0.5 ? { color: 'red' } : { color: '#0f990f' }} suffix="%" />
                 },
                 {
-                    title: '回流人数(平台上报)', dataIndex: 'miniGameBfUv', label: 'App相关字段', width: 80, align: 'center', sorter: true, 
+                    title: '回流人数(平台上报)', dataIndex: 'miniGameBfUv', label: 'App相关字段', width: 80, align: 'center', sorter: true,
                     render: (a: string) => <Statistic value={a || 0} />
                 },
                 {
@@ -627,7 +630,7 @@ function columns12(): { label: string, fieldSHow?: { label: string, saveField: s
                     render: (a: string) => <Statistic value={a || 0} precision={2} />
                 },
                 {
-                    title: '广告变现人数(平台上报)', dataIndex: 'adMonetizationPlaDedupPv', label: 'App相关字段', width: 90, align: 'center', sorter: true, 
+                    title: '广告变现人数(平台上报)', dataIndex: 'adMonetizationPlaDedupPv', label: 'App相关字段', width: 90, align: 'center', sorter: true,
                     render: (a: string) => <Statistic value={a || 0} />
                 },
                 {
@@ -639,7 +642,7 @@ function columns12(): { label: string, fieldSHow?: { label: string, saveField: s
                     render: (a: string) => <Statistic value={a || 0} precision={2} />
                 },
                 {
-                    title: '回流广告变现人数(平台上报)', dataIndex: 'adMonetizationBkPlaDedupPv', label: 'App相关字段', width: 90, align: 'center', sorter: true, 
+                    title: '回流广告变现人数(平台上报)', dataIndex: 'adMonetizationBkPlaDedupPv', label: 'App相关字段', width: 90, align: 'center', sorter: true,
                     render: (a: string) => <Statistic value={a || 0} />
                 },
                 {
@@ -647,7 +650,7 @@ function columns12(): { label: string, fieldSHow?: { label: string, saveField: s
                     render: (a: number) => <Statistic value={a ? a * 100 : 0} precision={2} valueStyle={!a ? {} : a >= 0.5 ? { color: 'red' } : { color: '#0f990f' }} suffix="%" />
                 },
                 {
-                    title: '回流广告变现ARPU(平台上报)', dataIndex: 'miniGameBfIncomePlaArpu', label: 'App相关字段', width: 100, align: 'center', sorter: true, 
+                    title: '回流广告变现ARPU(平台上报)', dataIndex: 'miniGameBfIncomePlaArpu', label: 'App相关字段', width: 100, align: 'center', sorter: true,
                     render: (a: string) => <Statistic value={a || 0} />
                 },
                 {
@@ -655,7 +658,7 @@ function columns12(): { label: string, fieldSHow?: { label: string, saveField: s
                     render: (a: string) => <Statistic value={a || 0} precision={2} />
                 },
                 {
-                    title: '回流首日广告变现人数(平台上报)', dataIndex: 'adMonetizationBkPlaDedupActive1dPv', label: 'App相关字段', width: 100, align: 'center', sorter: true, 
+                    title: '回流首日广告变现人数(平台上报)', dataIndex: 'adMonetizationBkPlaDedupActive1dPv', label: 'App相关字段', width: 100, align: 'center', sorter: true,
                     render: (a: string) => <Statistic value={a || 0} />
                 },
                 {
@@ -663,7 +666,7 @@ function columns12(): { label: string, fieldSHow?: { label: string, saveField: s
                     render: (a: string) => <Statistic value={a || 0} precision={2} />
                 },
                 {
-                    title: '回流首24小时广告变现人数(平台上报)', dataIndex: 'adMonetizationBkPlaDedupActive24hPv', label: 'App相关字段', width: 110, align: 'center', sorter: true, 
+                    title: '回流首24小时广告变现人数(平台上报)', dataIndex: 'adMonetizationBkPlaDedupActive24hPv', label: 'App相关字段', width: 110, align: 'center', sorter: true,
                     render: (a: string) => <Statistic value={a || 0} />
                 },
                 {
@@ -671,7 +674,7 @@ function columns12(): { label: string, fieldSHow?: { label: string, saveField: s
                     render: (a: number) => <Statistic value={a ? a * 100 : 0} precision={2} valueStyle={!a ? {} : a >= 0.5 ? { color: 'red' } : { color: '#0f990f' }} suffix="%" />
                 },
                 {
-                    title: '回流首24小时广告变现ARPU(平台上报)', dataIndex: 'adMonetizationBkPlaDedupActive24hArpu', label: 'App相关字段', width: 120, align: 'center', sorter: true, 
+                    title: '回流首24小时广告变现ARPU(平台上报)', dataIndex: 'adMonetizationBkPlaDedupActive24hArpu', label: 'App相关字段', width: 120, align: 'center', sorter: true,
                     render: (a: string) => <Statistic value={a || 0} />
                 },
                 {

+ 4 - 1
src/pages/iaaData/novel/tencent/pitcherEveryDayGroup/index.tsx

@@ -1,11 +1,12 @@
 import { useAjax } from "@/Hook/useAjax";
-import { getNovelPutUserGroupListApi, GetNovelPutUserGroupListProps, getNovelPutUserGroupTotalApi } from "@/services/iaaData";
+import { downloadNovelPutUserGroupApi, getNovelPutUserGroupListApi, GetNovelPutUserGroupListProps, getNovelPutUserGroupTotalApi } from "@/services/iaaData";
 import React, { useEffect, useState } from "react"
 import { useModel } from "umi";
 import moment from "moment";
 import TablePro from "@/components/TablePro";
 import QueryFormNovel from "@/components/QueryForm/queryFormNovel";
 import columns12 from "./tableConfig";
+import DownloadExcel from "@/components/DownloadExcel";
 
 /**
  * 投手每日汇总
@@ -25,6 +26,7 @@ const PitcherEveryDayGroupNovel: React.FC<{ configName?: string }> = ({ configNa
 
     const getNovelPutUserGroupList = useAjax((params) => getNovelPutUserGroupListApi(params))
     const getNovelPutUserGroupTotal = useAjax((params) => getNovelPutUserGroupTotalApi(params))
+    const downloadNovelPutUserGroup = useAjax((params) => downloadNovelPutUserGroupApi(params))
     /****************************************/
 
     useEffect(() => {
@@ -66,6 +68,7 @@ const PitcherEveryDayGroupNovel: React.FC<{ configName?: string }> = ({ configNa
                     setQueryForm({ ...newQueryForm, ...params })
                 }}
             />}
+            czChild={(initialState && initialState.iaaApp && initialState.productType) && <DownloadExcel api={downloadNovelPutUserGroup} querys={{ ...queryForm, appId: initialState.iaaApp, productType: initialState.productType }} />}
             isZj
             totalData={totalData}
             config={columns12()}

+ 1 - 1
src/pages/iaaData/novel/tencent/pitcherPayTrend/tableConfig.tsx

@@ -113,7 +113,7 @@ function columns12(): { label: string, fieldSHow?: { label: string, saveField: s
                     render: (a: number) => <Statistic value={a || 0} precision={2} />
                 },
                 {
-                    title: '广告变现金额', dataIndex: 'appAdPayingAmount', label: '基本信息', align: 'center', width: 110, default: 12, sorter: true,
+                    title: '广告变现金额', dataIndex: 'appAdPayingAmount', label: '基本信息', align: 'right', width: 110, default: 12, sorter: true,
                     render: (a: number) => <Statistic value={a || 0} precision={2} />
                 },
                 {

+ 3 - 2
src/pages/iaaSystem/manage/application/modalApp.tsx

@@ -108,7 +108,7 @@ const ModalApp: React.FC<Props> = ({ appAllList, userList, apptypeEnum, onChange
                     {(fields, { add, remove }) => {
                         return <>
                             {fields.map(({ key, name, ...restField }) => (
-                                <Space key={key} style={{ display: 'flex', marginBottom: 8, width: '100%' }} align="center">
+                                <Space key={key} style={{ display: 'flex', marginBottom: 8, width: '100%' }} align="start">
                                     <Form.Item
                                         {...restField}
                                         label={<strong>应用类型</strong>}
@@ -129,7 +129,7 @@ const ModalApp: React.FC<Props> = ({ appAllList, userList, apptypeEnum, onChange
                                     <Form.Item
                                         {...restField}
                                         label={<strong>应用</strong>}
-                                        name={[name, 'iaaAppId']}
+                                        name={[name, 'iaaAppIdList']}
                                         rules={[{ required: true, message: '请选选择应用' }]}
                                     >
                                         <Select
@@ -137,6 +137,7 @@ const ModalApp: React.FC<Props> = ({ appAllList, userList, apptypeEnum, onChange
                                             showSearch
                                             allowClear
                                             placeholder="选择应用"
+                                            mode="multiple"
                                             filterOption={(input, option) =>
                                                 (option?.label as any)?.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                             }

+ 133 - 0
src/services/gameData/index.ts

@@ -239,6 +239,18 @@ export async function modifyStatusBatchApi(data: ADQV3.ModifyStatusBatchProps) {
     });
 }
 
+/**
+ * 同步
+ * @param data 
+ * @returns 
+ */
+export async function syncBatchApi(data: ADQV3.AccountAdgroupMapsProps) {
+    return request(api + '/adq/adgroup/syncBatch', {
+        method: 'PUT',
+        data
+    });
+}
+
 /**
  * 删除广告
  * @param data 
@@ -322,4 +334,125 @@ export async function updateBatchDynamicCreativesInfoApi(data: any) {
         method: 'PUT',
         data
     });
+}
+
+
+/**
+ * 新增任务
+ * @param data 
+ * @returns 
+ */
+export async function addTaskAutoAcquisitionApi(data: ADQV3.AddTaskAutoAcquisitionProps) {
+    return request(api + '/adq/adgroupQuant/task/add', {
+        method: 'POST',
+        data
+    });
+}
+
+/**
+ * 修改
+ * @param data 
+ * @returns 
+ */
+export async function updateTaskAutoAcquisitionApi(data: ADQV3.AddTaskAutoAcquisitionProps) {
+    return request(api + '/adq/adgroupQuant/task/modifyById', {
+        method: 'POST',
+        data
+    });
+}
+
+/**
+ * 立即执行
+ * @param data 
+ * @returns 
+ */
+export async function addOnceTaskAutoAcquisitionApi(data: ADQV3.AddTaskAutoAcquisitionProps) {
+    return request(api + '/adq/adgroupQuant/task/add/once', {
+        method: 'POST',
+        data
+    });
+}
+
+
+/**
+ * 查询一键起量任务列表
+ * @param data 
+ * @returns 
+ */
+export async function getAdgroupQuantTaskListApi(data: ADQV3.GetAdgroupQuantTaskListProps) {
+    return request(api + '/adq/adgroupQuant/task/listOfPage', {
+        method: 'POST',
+        data
+    });
+}
+
+/**
+ * 删除任务
+ * @param params 
+ * @returns 
+ */
+export async function delAdgroupQuantTaskApi(params: {id: number}) {
+    return request(api + '/adq/adgroupQuant/task/delete', {
+        method: 'DELETE',
+        params
+    });
+}
+
+
+/**
+ * 一键起量广告日志-分页查询任务的广告执行日志
+ * @param data 
+ * @returns 
+ */
+export async function getAdgroupQuantTaskAdLogListApi(data: ADQV3.GetAdgroupQuantTaskAdLogListProps) {
+    return request(api + '/adq/adgroupQuant/adLog/listOfPage', {
+        method: 'POST',
+        data
+    });
+}
+
+/**
+ * 一键起量广告-从任务中批量删除广告
+ * @param data 
+ * @returns 
+ */
+export async function delAdgroupQuantTaskAdApi(data: ADQV3.DelAdgroupQuantTaskAdProps) {
+    return request(api + '/adq/adgroupQuant/ad/removeFromTask', {
+        method: 'POST',
+        data
+    });
+}
+
+/**
+ * 一键起量广告-分页查询任务关联的广告列表
+ * @param data 
+ * @returns 
+ */
+export async function getAdgroupQuantTaskAdDetailsListApi(data: ADQV3.GetAdgroupQuantTaskAdDetailsListProps) {
+    return request(api + '/adq/adgroupQuant/ad/listOfPage', {
+        method: 'POST',
+        data
+    });
+}
+
+/**
+ * 所有任务列表
+ * @returns 
+ */
+export async function getTaskAllListApi() {
+    return request(api + '/adq/adgroupQuant/task/all', {
+        method: 'GET'
+    });
+}
+
+/**
+ * 添加到任务
+ * @param data 
+ * @returns 
+ */
+export async function adAddTaskApi(data: ADQV3.AdAddTaskProps) {
+    return request(api + '/adq/adgroupQuant/ad/addToTask', {
+        method: 'POST',
+        data
+    });
 }

+ 54 - 0
src/services/gameData/typings.d.ts

@@ -65,4 +65,58 @@ declare namespace ADQV3 {
         creativeName?: string,
         userId?: number
     }
+    interface AddTaskAutoAcquisitionProps {
+        taskName: string,
+        timeList?: string[]
+        startDay?: string,
+        endDay?: string,
+        adgroupBeanList?: {
+            accountId: number,
+            adgroupId: number
+        }[],
+        budget?: number
+        budgetPercent?: number
+        defaultBudget?: number,
+        addType?: 'fixed' | 'percent',
+        taskType?: 'imm' | 'cyc'
+    }
+    interface GetAdgroupQuantTaskListProps {
+        pageNum: number,
+        pageSize: number,
+        startDay?: string,
+        endDay?: string,
+        taskName?: string,
+        adgroupIdList?: number[]
+    }
+    interface GetAdgroupQuantTaskAdLogListProps {
+        pageNum: number,
+        pageSize: number,
+        taskId: number,
+        accountId?: string
+        adgroupId?: string
+        startDay?: string,
+        endDay?: string,
+        status?: 0 | 1
+    }
+    interface GetAdgroupQuantTaskAdDetailsListProps {
+        pageNum: number,
+        pageSize: number,
+        taskId: number,
+        accountId?: string
+        adgroupId?: string
+    }
+    interface DelAdgroupQuantTaskAdProps {
+        taskId: number,
+        adgroupBeanList: {
+            accountId: number,
+            adgroupId: number
+        }[]
+    }
+    interface AdAddTaskProps {
+        adgroupBeanList: {
+            accountId: number,
+            adgroupId: number
+        }[]
+        taskId: number
+    }
 }

+ 12 - 0
src/services/iaaData/index.ts

@@ -584,6 +584,18 @@ export async function getNovelPutUserGroupTotalApi(data: GetNovelPutUserGroupLis
     });
 }
 
+/**
+ * 下载
+ * @param data 
+ * @returns 
+ */
+export async function downloadNovelPutUserGroupApi(data: GetNovelPutUserGroupListProps) {
+    return request(`${wapi}/monitor/novel/putUser/group/listOfPage/excel`, {
+        method: 'POST',
+        data,
+        responseType: 'blob'
+    })
+}
 
 export interface GetNovelAppListProps extends Paging, SortProps {
     costDayBegin?: string