|
@@ -0,0 +1,896 @@
|
|
|
+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 '../../tencentAdPutIn/index.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 SetTime from "./setTime"
|
|
|
+import { adAddTaskApi, addOnceTaskAutoAcquisitionApi, addTaskAutoAcquisitionApi, delAdgroupQuantTaskAdApi, delAdgroupQuantTaskApi, getAdgroupQuantTaskAdDetailsListApi, getAdgroupQuantTaskAdLogListApi, getAdgroupQuantTaskListApi, getTaskAllListApi, updateTaskAutoAcquisitionApi } from "@/services/launchAdq/adqv3"
|
|
|
+import { copy } from "@/utils/utils"
|
|
|
+
|
|
|
+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 }))
|
|
|
+ }
|
|
|
+ console.log(values, params);
|
|
|
+ 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) {
|
|
|
+ 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) {
|
|
|
+ message.success('添加成功')
|
|
|
+ onChange?.()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } else { // 立即执行
|
|
|
+ addOnceTaskAutoAcquisition.run(params).then(res => {
|
|
|
+ if (res) {
|
|
|
+ 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>
|
|
|
+ <DatePicker placeholder="开始日期" disabledDate={disabledDateStart} />
|
|
|
+ </Form.Item>
|
|
|
+ <span>-</span>
|
|
|
+ <Form.Item name="endDay" rules={[{ required: true, message: '请选择结束日期!' }]} noStyle>
|
|
|
+ <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">百分比上下浮动修改</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) {
|
|
|
+ setTaskList(Object.keys(res).map(key => ({ label: res[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) {
|
|
|
+ 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?.label ?? '') as any).toLowerCase().includes(input.toLowerCase())
|
|
|
+ }
|
|
|
+ options={taskList}
|
|
|
+ />
|
|
|
+ </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) {
|
|
|
+ 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
|
|
|
+ />
|
|
|
+ <DatePicker placeholder="开始日期" value={queryForm?.startDay ? moment(queryForm.startDay) : undefined} onChange={(_, dateString) => setQueryForm({ ...queryForm, startDay: dateString, pageNum: 1 })} />
|
|
|
+ <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?.records}
|
|
|
+ rowKey={'id'}
|
|
|
+ scroll={{ y: 400 }}
|
|
|
+ pagination={{
|
|
|
+ pageSize: getAdgroupQuantTaskList?.data?.size || 50,
|
|
|
+ current: getAdgroupQuantTaskList?.data?.current || 1,
|
|
|
+ showTotal: total => `总共 ${total} 数据`,
|
|
|
+ total: getAdgroupQuantTaskList?.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 />
|
|
|
+ <DatePicker placeholder="开始日期" style={{ width: 130 }} value={queryForm?.startDay ? moment(queryForm.startDay) : undefined} onChange={(_, dateString) => setQueryForm({ ...queryForm, startDay: dateString, pageNum: 1 })} />
|
|
|
+ <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?.records}
|
|
|
+ rowKey={'id'}
|
|
|
+ scroll={{ y: 400 }}
|
|
|
+ pagination={{
|
|
|
+ pageSize: getAdgroupQuantTaskAdLogList?.data?.size || 50,
|
|
|
+ current: getAdgroupQuantTaskAdLogList?.data?.current || 1,
|
|
|
+ showTotal: total => `总共 ${total} 数据`,
|
|
|
+ total: getAdgroupQuantTaskAdLogList?.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) {
|
|
|
+ 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?.records}
|
|
|
+ rowKey={'id'}
|
|
|
+ scroll={{ y: 400 }}
|
|
|
+ pagination={{
|
|
|
+ pageSize: getAdgroupQuantTaskAdDetailsList?.data?.size || 50,
|
|
|
+ current: getAdgroupQuantTaskAdDetailsList?.data?.current || 1,
|
|
|
+ showTotal: total => `总共 ${total} 数据`,
|
|
|
+ total: getAdgroupQuantTaskAdDetailsList?.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);
|