前测功能完善详情编辑删除
This commit is contained in:
+442
File diff suppressed because one or more lines are too long
+442
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -28,7 +28,7 @@
|
|||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
<script type="module" crossorigin src="/assets/index-1NS8asx8.js"></script>
|
<script type="module" crossorigin src="/assets/index-BVNhLxFb.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-D3IaMBsq.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-D3IaMBsq.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -250,8 +250,15 @@ const MaterialListPage: React.FC = () => {
|
|||||||
dataIndex: 'note',
|
dataIndex: 'note',
|
||||||
key: 'note',
|
key: 'note',
|
||||||
width: 150,
|
width: 150,
|
||||||
ellipsis: true,
|
render: (text: string) => (
|
||||||
render: (text: string) => <span style={{ color: '#94a3b8' }}>{text || '-'}</span>,
|
<Input.TextArea
|
||||||
|
value={text || ''}
|
||||||
|
readOnly
|
||||||
|
autoSize={{ minRows: 1, maxRows: 4 }}
|
||||||
|
style={{ color: '#94a3b8', resize: 'none', border: 'none', background: 'transparent', padding: 0 }}
|
||||||
|
placeholder="-"
|
||||||
|
/>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '用户ID',
|
title: '用户ID',
|
||||||
|
|||||||
+274
-185
@@ -1,7 +1,7 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { Table, Tag, Button, Typography, Space, Modal, Form, Input, Select, Cascader, App, Pagination } from 'antd';
|
import { Table, Tag, Button, Typography, Space, Modal, Form, Input, Select, Cascader, App, Pagination } from 'antd';
|
||||||
import { PlusOutlined, EditOutlined, FileTextOutlined } from '@ant-design/icons';
|
import { PlusOutlined, EditOutlined, FileTextOutlined, DeleteOutlined, EyeOutlined } from '@ant-design/icons';
|
||||||
import { getPreTestList, createPreTest, getArea } from '../api';
|
import { getPreTestList, createPreTest, getArea, getPreTestDetail, updatePreTest, deletePreTest } from '../api';
|
||||||
|
|
||||||
interface PreTestRecord {
|
interface PreTestRecord {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -134,178 +134,14 @@ const formatDateTime = (dateStr: string) => {
|
|||||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const columns = [
|
|
||||||
{
|
|
||||||
title: '前测模板编号',
|
|
||||||
dataIndex: 'id',
|
|
||||||
key: 'id',
|
|
||||||
width: 120,
|
|
||||||
render: (text: string) => <Typography.Text strong style={{ color: '#1e293b', fontSize: 13 }}>{text}</Typography.Text>,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '模板名称',
|
|
||||||
dataIndex: 'name',
|
|
||||||
key: 'name',
|
|
||||||
ellipsis: true,
|
|
||||||
render: (text: string) => (
|
|
||||||
<span style={{ color: '#1e293b', fontWeight: 500, fontSize: 13 }}>{text}</span>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '平台',
|
|
||||||
dataIndex: 'platform',
|
|
||||||
key: 'platform',
|
|
||||||
render: (text: string) => (
|
|
||||||
<Tag color={text === 'AD' ? 'blue' : text === 'QIANCHUAN' ? 'green' : 'orange'} style={{ borderRadius: 6, fontSize: 12 }}>
|
|
||||||
{text === 'AD' ? 'AD' : text === 'QIANCHUAN' ? '千川' : '本地推'}
|
|
||||||
</Tag>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '转化目标',
|
|
||||||
dataIndex: 'externalAction',
|
|
||||||
key: 'externalAction',
|
|
||||||
ellipsis: true,
|
|
||||||
width: 200,
|
|
||||||
render: (text: string) => {
|
|
||||||
if (!text) return <span style={{ color: '#94a3b8', fontSize: 13 }}>-</span>;
|
|
||||||
const actionArray = text.split(',').filter(item => item.trim());
|
|
||||||
const labels = actionArray.map(action => {
|
|
||||||
const field = PRETEST_FIELDS.find(f => f.name === action.trim());
|
|
||||||
return field ? field.label : action;
|
|
||||||
});
|
|
||||||
return (
|
|
||||||
<span style={{ color: '#1e293b', fontSize: 13 }}>{labels.join(', ')}</span>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '目标转化成本',
|
|
||||||
dataIndex: 'cpaBid',
|
|
||||||
key: 'cpaBid',
|
|
||||||
width: 120,
|
|
||||||
render: (text: number) => (
|
|
||||||
<span style={{ color: '#1e293b', fontSize: 13 }}>{text !== undefined ? text : '-'}</span>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '受众性别',
|
|
||||||
dataIndex: 'audienceGender',
|
|
||||||
key: 'audienceGender',
|
|
||||||
width: 90,
|
|
||||||
render: (text: string) => (
|
|
||||||
<span style={{ color: '#1e293b', fontSize: 13 }}>{text === 'ALL' ? '不限' : text === 'MALE' ? '男' : text === 'FEMALE' ? '女' : text || '-'}</span>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '受众年龄',
|
|
||||||
dataIndex: 'audienceAge',
|
|
||||||
key: 'audienceAge',
|
|
||||||
width: 90,
|
|
||||||
render: (text: string[]) => (
|
|
||||||
<span style={{ color: '#1e293b', fontSize: 13 }}>{Array.isArray(text) ? text.join(', ') : text || '-'}</span>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '受众地区',
|
|
||||||
dataIndex: 'audience_region',
|
|
||||||
key: 'audience_region',
|
|
||||||
ellipsis: true,
|
|
||||||
width: 150,
|
|
||||||
render: (text: string[]) => (
|
|
||||||
<span style={{ color: '#1e293b', fontSize: 13 }}>{Array.isArray(text) ? text.join(', ') : text || '-'}</span>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '网络类型',
|
|
||||||
dataIndex: 'audienceNetwork',
|
|
||||||
key: 'audienceNetwork',
|
|
||||||
width: 90,
|
|
||||||
render: (text: string[]) => (
|
|
||||||
<span style={{ color: '#1e293b', fontSize: 13 }}>{Array.isArray(text) ? text.join(', ') : text || '-'}</span>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '客户主体名称',
|
|
||||||
dataIndex: 'cusName',
|
|
||||||
key: 'cusName',
|
|
||||||
ellipsis: true,
|
|
||||||
width: 120,
|
|
||||||
render: (text: string) => (
|
|
||||||
<span style={{ color: '#1e293b', fontSize: 13 }}>{text || '-'}</span>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '出价类型',
|
|
||||||
dataIndex: 'pricingType',
|
|
||||||
key: 'pricingType',
|
|
||||||
width: 90,
|
|
||||||
render: (text: string) => (
|
|
||||||
<span style={{ color: '#1e293b', fontSize: 13 }}>{text || '-'}</span>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '目标点击成本',
|
|
||||||
dataIndex: 'cpcBid',
|
|
||||||
key: 'cpcBid',
|
|
||||||
width: 120,
|
|
||||||
render: (text: number) => (
|
|
||||||
<span style={{ color: '#1e293b', fontSize: 13 }}>{text !== undefined ? text : '-'}</span>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '预算金额',
|
|
||||||
dataIndex: 'budget',
|
|
||||||
key: 'budget',
|
|
||||||
width: 100,
|
|
||||||
render: (text: number) => (
|
|
||||||
<span style={{ color: '#1e293b', fontSize: 13 }}>{text !== undefined ? text : '-'}</span>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '默认模板',
|
|
||||||
dataIndex: 'isDefault',
|
|
||||||
key: 'isDefault',
|
|
||||||
width: 90,
|
|
||||||
render: (text: boolean) => (
|
|
||||||
<Tag color={text ? 'green' : 'default'} style={{ borderRadius: 6, fontSize: 12 }}>
|
|
||||||
{text ? '是' : '否'}
|
|
||||||
</Tag>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '创建时间',
|
|
||||||
dataIndex: 'createdAt',
|
|
||||||
key: 'createdAt',
|
|
||||||
width: 160,
|
|
||||||
render: (text: string) => <Typography.Text style={{ color: '#94a3b8', fontSize: 12 }}>{formatDateTime(text)}</Typography.Text>,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '操作',
|
|
||||||
dataIndex: 'operation',
|
|
||||||
fixed: 'right' as const,
|
|
||||||
key: 'operation',
|
|
||||||
render: (_: any, record: PreTestRecord) => (
|
|
||||||
<Space size={4}>
|
|
||||||
<Button
|
|
||||||
type="text"
|
|
||||||
size="small"
|
|
||||||
icon={<EditOutlined />}
|
|
||||||
style={{ color: '#6366f1', fontSize: 12 }}
|
|
||||||
>
|
|
||||||
编辑
|
|
||||||
</Button>
|
|
||||||
</Space>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const PreTest: React.FC = () => {
|
const PreTest: React.FC = () => {
|
||||||
const { message } = App.useApp();
|
const { message } = App.useApp();
|
||||||
const [records, setRecords] = useState<PreTestRecord[]>([]);
|
const [records, setRecords] = useState<PreTestRecord[]>([]);
|
||||||
const [total, setTotal] = useState(0);
|
const [total, setTotal] = useState(0);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [modalOpen, setModalOpen] = useState(false);
|
const [modalOpen, setModalOpen] = useState(false);
|
||||||
|
const [modalMode, setModalMode] = useState<'create' | 'edit' | 'detail'>('create');
|
||||||
|
const [currentRecord, setCurrentRecord] = useState<PreTestRecord | null>(null);
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const [submitLoading, setSubmitLoading] = useState(false);
|
const [submitLoading, setSubmitLoading] = useState(false);
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
@@ -353,7 +189,6 @@ const PreTest: React.FC = () => {
|
|||||||
const loadCityOptions = async (selectedOptions: any) => {
|
const loadCityOptions = async (selectedOptions: any) => {
|
||||||
const targetOption = selectedOptions[selectedOptions.length - 1];
|
const targetOption = selectedOptions[selectedOptions.length - 1];
|
||||||
targetOption.loading = true;
|
targetOption.loading = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await getArea({ level: 'TWO_LEVEL', parent_code: targetOption.value });
|
const res = await getArea({ level: 'TWO_LEVEL', parent_code: targetOption.value });
|
||||||
targetOption.children = (res.data || []).map((item: any) => ({
|
targetOption.children = (res.data || []).map((item: any) => ({
|
||||||
@@ -376,12 +211,263 @@ const PreTest: React.FC = () => {
|
|||||||
key: item.id,
|
key: item.id,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: '前测模板编号',
|
||||||
|
dataIndex: 'id',
|
||||||
|
key: 'id',
|
||||||
|
width: 120,
|
||||||
|
render: (text: string) => <Typography.Text strong style={{ color: '#1e293b', fontSize: 13 }}>{text}</Typography.Text>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '模板名称',
|
||||||
|
dataIndex: 'name',
|
||||||
|
key: 'name',
|
||||||
|
ellipsis: true,
|
||||||
|
render: (text: string) => (
|
||||||
|
<span style={{ color: '#1e293b', fontWeight: 500, fontSize: 13 }}>{text}</span>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '平台',
|
||||||
|
dataIndex: 'platform',
|
||||||
|
key: 'platform',
|
||||||
|
render: (text: string) => (
|
||||||
|
<Tag color={text === 'AD' ? 'blue' : text === 'QIANCHUAN' ? 'green' : 'orange'} style={{ borderRadius: 6, fontSize: 12 }}>
|
||||||
|
{text === 'AD' ? 'AD' : text === 'QIANCHUAN' ? '千川' : '本地推'}
|
||||||
|
</Tag>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '转化目标',
|
||||||
|
dataIndex: 'externalAction',
|
||||||
|
key: 'externalAction',
|
||||||
|
ellipsis: true,
|
||||||
|
width: 200,
|
||||||
|
render: (text: string) => {
|
||||||
|
if (!text) return <span style={{ color: '#94a3b8', fontSize: 13 }}>-</span>;
|
||||||
|
const field = PRETEST_FIELDS.find(f => f.name === text.trim());
|
||||||
|
return (
|
||||||
|
<span style={{ color: '#1e293b', fontSize: 13 }}>{field ? field.label : text}</span>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '目标转化成本',
|
||||||
|
dataIndex: 'cpaBid',
|
||||||
|
key: 'cpaBid',
|
||||||
|
width: 120,
|
||||||
|
render: (text: number) => (
|
||||||
|
<span style={{ color: '#1e293b', fontSize: 13 }}>{text !== undefined ? text : '-'}</span>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '受众性别',
|
||||||
|
dataIndex: 'audienceGender',
|
||||||
|
key: 'audienceGender',
|
||||||
|
width: 90,
|
||||||
|
render: (text: string) => (
|
||||||
|
<span style={{ color: '#1e293b', fontSize: 13 }}>{text === 'ALL' ? '不限' : text === 'MALE' ? '男' : text === 'FEMALE' ? '女' : text || '-'}</span>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '受众年龄',
|
||||||
|
dataIndex: 'audienceAge',
|
||||||
|
key: 'audienceAge',
|
||||||
|
width: 90,
|
||||||
|
render: (text: string[]) => (
|
||||||
|
<span style={{ color: '#1e293b', fontSize: 13 }}>{Array.isArray(text) ? text.join(', ') : text || '-'}</span>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '受众地区',
|
||||||
|
dataIndex: 'audience_region',
|
||||||
|
key: 'audience_region',
|
||||||
|
ellipsis: true,
|
||||||
|
width: 150,
|
||||||
|
render: (text: string[]) => (
|
||||||
|
<span style={{ color: '#1e293b', fontSize: 13 }}>{Array.isArray(text) ? text.join(', ') : text || '-'}</span>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '网络类型',
|
||||||
|
dataIndex: 'audienceNetwork',
|
||||||
|
key: 'audienceNetwork',
|
||||||
|
width: 90,
|
||||||
|
render: (text: string[]) => (
|
||||||
|
<span style={{ color: '#1e293b', fontSize: 13 }}>{Array.isArray(text) ? text.join(', ') : text || '-'}</span>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '客户主体名称',
|
||||||
|
dataIndex: 'cusName',
|
||||||
|
key: 'cusName',
|
||||||
|
ellipsis: true,
|
||||||
|
width: 120,
|
||||||
|
render: (text: string) => (
|
||||||
|
<span style={{ color: '#1e293b', fontSize: 13 }}>{text || '-'}</span>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '出价类型',
|
||||||
|
dataIndex: 'pricingType',
|
||||||
|
key: 'pricingType',
|
||||||
|
width: 90,
|
||||||
|
render: (text: string) => (
|
||||||
|
<span style={{ color: '#1e293b', fontSize: 13 }}>{text || '-'}</span>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '目标点击成本',
|
||||||
|
dataIndex: 'cpcBid',
|
||||||
|
key: 'cpcBid',
|
||||||
|
width: 120,
|
||||||
|
render: (text: number) => (
|
||||||
|
<span style={{ color: '#1e293b', fontSize: 13 }}>{text !== undefined ? text : '-'}</span>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '预算金额',
|
||||||
|
dataIndex: 'budget',
|
||||||
|
key: 'budget',
|
||||||
|
width: 100,
|
||||||
|
render: (text: number) => (
|
||||||
|
<span style={{ color: '#1e293b', fontSize: 13 }}>{text !== undefined ? text : '-'}</span>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '默认模板',
|
||||||
|
dataIndex: 'isDefault',
|
||||||
|
key: 'isDefault',
|
||||||
|
width: 90,
|
||||||
|
render: (text: boolean) => (
|
||||||
|
<Tag color={text ? 'green' : 'default'} style={{ borderRadius: 6, fontSize: 12 }}>
|
||||||
|
{text ? '是' : '否'}
|
||||||
|
</Tag>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
dataIndex: 'createdAt',
|
||||||
|
key: 'createdAt',
|
||||||
|
width: 160,
|
||||||
|
render: (text: string) => <Typography.Text style={{ color: '#94a3b8', fontSize: 12 }}>{formatDateTime(text)}</Typography.Text>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
dataIndex: 'operation',
|
||||||
|
fixed: 'right' as const,
|
||||||
|
key: 'operation',
|
||||||
|
render: (_: any, record: PreTestRecord) => (
|
||||||
|
<Space size={4}>
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
icon={<EyeOutlined />}
|
||||||
|
style={{ color: '#6366f1', fontSize: 12 }}
|
||||||
|
onClick={() => handleDetail(record)}
|
||||||
|
>
|
||||||
|
详情
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
icon={<EditOutlined />}
|
||||||
|
style={{ color: '#6366f1', fontSize: 12 }}
|
||||||
|
onClick={() => handleEdit(record)}
|
||||||
|
>
|
||||||
|
编辑
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
icon={<DeleteOutlined />}
|
||||||
|
style={{ color: '#ef4444', fontSize: 12 }}
|
||||||
|
onClick={() => handleDelete(record)}
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const handleOpenModal = () => {
|
const handleOpenModal = () => {
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
setPlatform('AD');
|
setPlatform('AD');
|
||||||
|
setModalMode('create');
|
||||||
|
setCurrentRecord(null);
|
||||||
setModalOpen(true);
|
setModalOpen(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const fillFormWithDetail = (data: any) => {
|
||||||
|
setCurrentRecord(data);
|
||||||
|
setPlatform(data.platform || 'AD');
|
||||||
|
const regionCodes = data.audience_region || [];
|
||||||
|
const regionPaths = regionCodes.map((code: any) => [String(code)]);
|
||||||
|
form.setFieldsValue({
|
||||||
|
name: data.name,
|
||||||
|
note: data.note,
|
||||||
|
platform: data.platform,
|
||||||
|
external_action: data.externalAction,
|
||||||
|
cpa_bid: data.cpaBid,
|
||||||
|
audience_gender: data.audienceGender,
|
||||||
|
audience_age: data.audienceAge || [],
|
||||||
|
audience_region: regionPaths,
|
||||||
|
audience_network: data.audienceNetwork || [],
|
||||||
|
cus_name: data.cusName,
|
||||||
|
pricing_type: data.pricingType,
|
||||||
|
cost_cap: data.costCap !== undefined ? data.costCap : false,
|
||||||
|
target_cost: data.targetCost !== undefined ? data.targetCost : false,
|
||||||
|
nobid: data.nobid !== undefined ? data.nobid : false,
|
||||||
|
cpc_bid: data.cpcBid,
|
||||||
|
budget: data.budget,
|
||||||
|
is_default: data.isDefault !== undefined ? data.isDefault : false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDetail = async (record: PreTestRecord) => {
|
||||||
|
try {
|
||||||
|
const res = await getPreTestDetail(record.id);
|
||||||
|
const data = res.data;
|
||||||
|
setModalMode('detail');
|
||||||
|
fillFormWithDetail(data);
|
||||||
|
setModalOpen(true);
|
||||||
|
} catch (error) {
|
||||||
|
message.error('获取详情失败');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEdit = async (record: PreTestRecord) => {
|
||||||
|
try {
|
||||||
|
const res = await getPreTestDetail(record.id);
|
||||||
|
const data = res.data;
|
||||||
|
setModalMode('edit');
|
||||||
|
fillFormWithDetail(data);
|
||||||
|
setModalOpen(true);
|
||||||
|
} catch (error) {
|
||||||
|
message.error('获取详情失败');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDelete = (record: PreTestRecord) => {
|
||||||
|
Modal.confirm({
|
||||||
|
title: '确认删除',
|
||||||
|
content: '确定要删除该前测模板吗?',
|
||||||
|
okText: '确定',
|
||||||
|
cancelText: '取消',
|
||||||
|
onOk: async () => {
|
||||||
|
try {
|
||||||
|
await deletePreTest(record.id);
|
||||||
|
message.success('删除成功');
|
||||||
|
loadRecords();
|
||||||
|
} catch (error) {
|
||||||
|
message.error('删除失败');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const handleCloseModal = () => {
|
const handleCloseModal = () => {
|
||||||
setModalOpen(false);
|
setModalOpen(false);
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
@@ -393,12 +479,11 @@ const PreTest: React.FC = () => {
|
|||||||
const values = await form.validateFields();
|
const values = await form.validateFields();
|
||||||
setSubmitLoading(true);
|
setSubmitLoading(true);
|
||||||
const regionCodes = (values.audience_region || []).map((path: string[]) => path[path.length - 1]);
|
const regionCodes = (values.audience_region || []).map((path: string[]) => path[path.length - 1]);
|
||||||
const externalActionStr = (values.external_action || []).join(',');
|
const params = {
|
||||||
const result = await createPreTest({
|
|
||||||
name: values.name,
|
name: values.name,
|
||||||
note: values.note,
|
note: values.note,
|
||||||
platform: values.platform,
|
platform: values.platform,
|
||||||
external_action: externalActionStr,
|
external_action: values.external_action,
|
||||||
cpa_bid: values.cpa_bid || 0,
|
cpa_bid: values.cpa_bid || 0,
|
||||||
audience_gender: values.audience_gender,
|
audience_gender: values.audience_gender,
|
||||||
audience_age: values.audience_age || [],
|
audience_age: values.audience_age || [],
|
||||||
@@ -412,9 +497,17 @@ const PreTest: React.FC = () => {
|
|||||||
cpc_bid: values.cpc_bid || 0,
|
cpc_bid: values.cpc_bid || 0,
|
||||||
budget: values.budget || 0,
|
budget: values.budget || 0,
|
||||||
is_default: values.is_default || false,
|
is_default: values.is_default || false,
|
||||||
});
|
};
|
||||||
|
|
||||||
|
let result;
|
||||||
|
if (modalMode === 'edit' && currentRecord) {
|
||||||
|
result = await updatePreTest(currentRecord.id, params);
|
||||||
|
message.success('前测模板更新成功');
|
||||||
|
} else {
|
||||||
|
result = await createPreTest(params);
|
||||||
|
message.success('前测模板创建成功');
|
||||||
|
}
|
||||||
|
|
||||||
message.success('前测模板创建成功');
|
|
||||||
setModalOpen(false);
|
setModalOpen(false);
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
loadRecords();
|
loadRecords();
|
||||||
@@ -424,7 +517,7 @@ const PreTest: React.FC = () => {
|
|||||||
} else if (error?.response?.data?.message) {
|
} else if (error?.response?.data?.message) {
|
||||||
message.error(error.response.data.message);
|
message.error(error.response.data.message);
|
||||||
} else {
|
} else {
|
||||||
message.error('创建失败,请重试');
|
message.error(modalMode === 'edit' ? '更新失败,请重试' : '创建失败,请重试');
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
setSubmitLoading(false);
|
setSubmitLoading(false);
|
||||||
@@ -502,21 +595,23 @@ const PreTest: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Modal
|
<Modal
|
||||||
title={<Space>新增前测模板</Space>}
|
title={<Space>{modalMode === 'create' ? '新增前测模板' : modalMode === 'edit' ? '编辑前测模板' : '前测模板详情'}</Space>}
|
||||||
open={modalOpen}
|
open={modalOpen}
|
||||||
onCancel={handleCloseModal}
|
onCancel={handleCloseModal}
|
||||||
onOk={handleSubmit}
|
onOk={handleSubmit}
|
||||||
okText="提交"
|
okText={modalMode === 'detail' ? '' : '提交'}
|
||||||
cancelText="取消"
|
cancelText="取消"
|
||||||
width={720}
|
width={720}
|
||||||
height={600}
|
height={600}
|
||||||
confirmLoading={submitLoading}
|
confirmLoading={submitLoading}
|
||||||
style={{ borderRadius: 16 }}
|
style={{ borderRadius: 16 }}
|
||||||
|
footer={modalMode === 'detail' ? null : undefined}
|
||||||
>
|
>
|
||||||
<Form
|
<Form
|
||||||
form={form}
|
form={form}
|
||||||
layout="vertical"
|
layout="vertical"
|
||||||
style={{ marginTop: 16 }}
|
style={{ marginTop: 16 }}
|
||||||
|
disabled={modalMode === 'detail'}
|
||||||
>
|
>
|
||||||
<div style={{ display: 'flex', gap: 16 }}>
|
<div style={{ display: 'flex', gap: 16 }}>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
@@ -557,10 +652,8 @@ const PreTest: React.FC = () => {
|
|||||||
label="转化目标"
|
label="转化目标"
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
mode="multiple"
|
placeholder="请选择转化目标"
|
||||||
placeholder="请选择转化目标(可多选)"
|
style={{ borderRadius: 8, height: 40 }}
|
||||||
style={{ borderRadius: 8, minHeight: 40 }}
|
|
||||||
maxTagCount="responsive"
|
|
||||||
options={PRETEST_FIELDS.filter(field => {
|
options={PRETEST_FIELDS.filter(field => {
|
||||||
if (platform === 'AD') {
|
if (platform === 'AD') {
|
||||||
return field.name.startsWith('AD_');
|
return field.name.startsWith('AD_');
|
||||||
@@ -713,7 +806,6 @@ const PreTest: React.FC = () => {
|
|||||||
style={{ flex: 1 }}
|
style={{ flex: 1 }}
|
||||||
name="cost_cap"
|
name="cost_cap"
|
||||||
label="是否最优成本出价"
|
label="是否最优成本出价"
|
||||||
valuePropName="checked"
|
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
placeholder="是否最优成本出价"
|
placeholder="是否最优成本出价"
|
||||||
@@ -729,7 +821,6 @@ const PreTest: React.FC = () => {
|
|||||||
style={{ flex: 1 }}
|
style={{ flex: 1 }}
|
||||||
name="target_cost"
|
name="target_cost"
|
||||||
label="是否稳定成本出价"
|
label="是否稳定成本出价"
|
||||||
valuePropName="checked"
|
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
placeholder="是否稳定成本出价"
|
placeholder="是否稳定成本出价"
|
||||||
@@ -745,7 +836,6 @@ const PreTest: React.FC = () => {
|
|||||||
style={{ flex: 1 }}
|
style={{ flex: 1 }}
|
||||||
name="nobid"
|
name="nobid"
|
||||||
label="是否最大转化出价"
|
label="是否最大转化出价"
|
||||||
valuePropName="checked"
|
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
placeholder="是否最大转化出价"
|
placeholder="是否最大转化出价"
|
||||||
@@ -799,7 +889,6 @@ const PreTest: React.FC = () => {
|
|||||||
name="is_default"
|
name="is_default"
|
||||||
label="默认模板"
|
label="默认模板"
|
||||||
initialValue={false}
|
initialValue={false}
|
||||||
valuePropName="checked"
|
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
placeholder="请选择默认模板"
|
placeholder="请选择默认模板"
|
||||||
|
|||||||
Reference in New Issue
Block a user