433 lines
22 KiB
TypeScript
433 lines
22 KiB
TypeScript
import React, { useState, useEffect } from 'react';
|
|
import { Table, Tag, Button, Typography, Space, Modal, Form, Input, Select, message } from 'antd';
|
|
import { PlusOutlined, EditOutlined } from '@ant-design/icons';
|
|
import { getPreTestList, createPreTest } from '../api';
|
|
|
|
interface PreTestRecord {
|
|
id: string;
|
|
authorizationId: string;
|
|
templateName: string;
|
|
selectedFields: string[];
|
|
status: string;
|
|
createdAt: string;
|
|
}
|
|
|
|
interface PreTestField {
|
|
id: string;
|
|
name: string;
|
|
label: string;
|
|
description?: string;
|
|
}
|
|
|
|
const statusConfig = {
|
|
completed: { label: '已完成', color: 'success' },
|
|
pending: { label: '待测试', color: 'default' },
|
|
testing: { label: '测试中', color: 'processing' },
|
|
failed: { label: '测试失败', color: 'error' },
|
|
};
|
|
|
|
const PRETEST_FIELDS: PreTestField[] = [
|
|
{ id: 'AD_APP_ACTIVATE', name: 'AD_APP_ACTIVATE', label: 'AD:应用-激活', description: '应用激活行为' },
|
|
{ id: 'AD_APP_AUTH', name: 'AD_APP_AUTH', label: 'AD:应用-授信', description: '应用授信行为' },
|
|
{ id: 'AD_APP_BOOK', name: 'AD_APP_BOOK', label: 'AD:应用-预约表单', description: '应用预约表单' },
|
|
{ id: 'AD_APP_BUY', name: 'AD_APP_BUY', label: 'AD:应用-APP内付费', description: 'APP内付费行为' },
|
|
{ id: 'AD_APP_CLICKS', name: 'AD_APP_CLICKS', label: 'AD:应用-点击量', description: '应用点击量' },
|
|
{ id: 'AD_APP_DETAIL', name: 'AD_APP_DETAIL', label: 'AD:应用-APP内详情页到站UV', description: 'APP内详情页到站UV' },
|
|
{ id: 'AD_APP_DOWNLOADED', name: 'AD_APP_DOWNLOADED', label: 'AD:应用-下载完成', description: '应用下载完成' },
|
|
{ id: 'AD_APP_INSTALLED', name: 'AD_APP_INSTALLED', label: 'AD:应用-安装完成', description: '应用安装完成' },
|
|
{ id: 'AD_APP_KEY_BEHAVIOR', name: 'AD_APP_KEY_BEHAVIOR', label: 'AD:应用-关键行为', description: '应用关键行为' },
|
|
{ id: 'AD_APP_ORDER', name: 'AD_APP_ORDER', label: 'AD:应用-APP内下单', description: 'APP内下单行为' },
|
|
{ id: 'AD_APP_PAY', name: 'AD_APP_PAY', label: 'AD:应用-付费', description: '应用付费行为' },
|
|
{ id: 'AD_APP_PRE_AUTH', name: 'AD_APP_PRE_AUTH', label: 'AD:应用-预授信', description: '应用预授信行为' },
|
|
{ id: 'AD_APP_PRE_DOWNLOAD', name: 'AD_APP_PRE_DOWNLOAD', label: 'AD:应用-预约下载', description: '应用预约下载' },
|
|
{ id: 'AD_APP_PUSH_ORDER', name: 'AD_APP_PUSH_ORDER', label: 'AD:应用-首次发单(乘客)', description: '首次发单行为' },
|
|
{ id: 'AD_APP_REGISTER', name: 'AD_APP_REGISTER', label: 'AD:应用-注册', description: '应用注册行为' },
|
|
{ id: 'AD_APP_SHOW', name: 'AD_APP_SHOW', label: 'AD:应用-展示量', description: '应用展示量' },
|
|
{ id: 'AD_APP_SUBMIT', name: 'AD_APP_SUBMIT', label: 'AD:应用-提交认证', description: '应用提交认证' },
|
|
{ id: 'AD_APP_VIEW', name: 'AD_APP_VIEW', label: 'AD:应用-APP内访问', description: 'APP内访问行为' },
|
|
{ id: 'AD_CLUE_AUTH', name: 'AD_CLUE_AUTH', label: 'AD:销售线索收集-授信', description: '销售线索授信' },
|
|
{ id: 'AD_CLUE_BUTTON', name: 'AD_CLUE_BUTTON', label: 'AD:销售线索收集-按钮跳转', description: '按钮跳转' },
|
|
{ id: 'AD_CLUE_CLICKS', name: 'AD_CLUE_CLICKS', label: 'AD:销售线索收集-点击量', description: '点击量' },
|
|
{ id: 'AD_CLUE_CONFIRM', name: 'AD_CLUE_CONFIRM', label: 'AD:销售线索收集-回访-信息确认', description: '回访信息确认' },
|
|
{ id: 'AD_CLUE_CONSULT', name: 'AD_CLUE_CONSULT', label: 'AD:销售线索收集-有效咨询', description: '有效咨询' },
|
|
{ id: 'AD_CLUE_CONSULT_MSG', name: 'AD_CLUE_CONSULT_MSG', label: 'AD:销售线索收集-留资咨询', description: '留资咨询' },
|
|
{ id: 'AD_CLUE_COUPON', name: 'AD_CLUE_COUPON', label: 'AD:销售线索收集-卡券领取', description: '卡券领取' },
|
|
{ id: 'AD_CLUE_CUSTOMER', name: 'AD_CLUE_CUSTOMER', label: 'AD:销售线索收集-有效获客', description: '有效获客' },
|
|
{ id: 'AD_CLUE_CVT', name: 'AD_CLUE_CVT', label: 'AD:销售线索收集-多转化', description: '多转化' },
|
|
{ id: 'AD_CLUE_DONE', name: 'AD_CLUE_DONE', label: 'AD:销售线索收集-完件', description: '完件' },
|
|
{ id: 'AD_CLUE_FORM', name: 'AD_CLUE_FORM', label: 'AD:销售线索收集-表单提交', description: '表单提交' },
|
|
{ id: 'AD_CLUE_FRIENDS', name: 'AD_CLUE_FRIENDS', label: 'AD:销售线索收集-回访-加为好友', description: '回访加为好友' },
|
|
{ id: 'AD_CLUE_INSURANCE', name: 'AD_CLUE_INSURANCE', label: 'AD:销售线索收集-保险支付', description: '保险支付' },
|
|
{ id: 'AD_CLUE_INTENTION', name: 'AD_CLUE_INTENTION', label: 'AD:销售线索收集-存在意向', description: '存在意向' },
|
|
{ id: 'AD_CLUE_INTENTION_FORM', name: 'AD_CLUE_INTENTION_FORM', label: 'AD:销售线索收集-意向表单', description: '意向表单' },
|
|
{ id: 'AD_CLUE_INTENTION_TEL', name: 'AD_CLUE_INTENTION_TEL', label: 'AD:销售线索收集-意向话单', description: '意向话单' },
|
|
{ id: 'AD_CLUE_MESSAGE', name: 'AD_CLUE_MESSAGE', label: 'AD:销售线索收集-私信消息', description: '私信消息' },
|
|
{ id: 'AD_CLUE_MONEY', name: 'AD_CLUE_MONEY', label: 'AD:销售线索收集-放款', description: '放款' },
|
|
{ id: 'AD_CLUE_MSG', name: 'AD_CLUE_MSG', label: 'AD:销售线索收集-私信留资', description: '私信留资' },
|
|
{ id: 'AD_CLUE_PAGE', name: 'AD_CLUE_PAGE', label: 'AD:销售线索收集-访问目标页面', description: '访问目标页面' },
|
|
{ id: 'AD_CLUE_PAY', name: 'AD_CLUE_PAY', label: 'AD:销售线索收集-付费', description: '付费' },
|
|
{ id: 'AD_CLUE_PRE_AUTH', name: 'AD_CLUE_PRE_AUTH', label: 'AD:销售线索收集-预授信', description: '预授信' },
|
|
{ id: 'AD_CLUE_PROTENTIAL_DEAL', name: 'AD_CLUE_PROTENTIAL_DEAL', label: 'AD:销售线索收集-回访-高潜成交', description: '回访高潜成交' },
|
|
{ id: 'AD_CLUE_PUSH_ORDER', name: 'AD_CLUE_PUSH_ORDER', label: 'AD:销售线索收集-首次发单(乘客)', description: '首次发单' },
|
|
{ id: 'AD_CLUE_REGISTER', name: 'AD_CLUE_REGISTER', label: 'AD:销售线索收集-注册', description: '注册' },
|
|
{ id: 'AD_CLUE_SHOW', name: 'AD_CLUE_SHOW', label: 'AD:销售线索收集-展示量', description: '展示量' },
|
|
{ id: 'AD_CLUE_SUBMIT', name: 'AD_CLUE_SUBMIT', label: 'AD:销售线索收集-提交认证', description: '提交认证' },
|
|
{ id: 'AD_CLUE_TEL', name: 'AD_CLUE_TEL', label: 'AD:销售线索收集-智能电话确认接通', description: '智能电话确认接通' },
|
|
{ id: 'AD_CLUE_TEL_CALL', name: 'AD_CLUE_TEL_CALL', label: 'AD:销售线索收集-电话接通', description: '电话接通' },
|
|
{ id: 'AD_CLUE_WX_ADD', name: 'AD_CLUE_WX_ADD', label: 'AD:销售线索收集-微信-添加企业微信', description: '添加企业微信' },
|
|
{ id: 'AD_CLUE_WX_COPY', name: 'AD_CLUE_WX_COPY', label: 'AD:销售线索收集-微信复制', description: '微信复制' },
|
|
{ id: 'AD_CLUE_WX_MSG', name: 'AD_CLUE_WX_MSG', label: 'AD:销售线索收集-微信-用户首次消息', description: '用户首次消息' },
|
|
{ id: 'AD_ECP_APP_BUY', name: 'AD_ECP_APP_BUY', label: 'AD:电商-app内下单', description: '电商app内下单' },
|
|
{ id: 'AD_ECP_APP_DETAIL', name: 'AD_ECP_APP_DETAIL', label: 'AD:电商-app内详情页到站uv', description: '电商app内详情页到站uv' },
|
|
{ id: 'AD_ECP_APP_VIEW', name: 'AD_ECP_APP_VIEW', label: 'AD:电商-app内访问', description: '电商app内访问' },
|
|
{ id: 'AD_ECP_BUTTON', name: 'AD_ECP_BUTTON', label: 'AD:电商-按钮跳转', description: '电商按钮跳转' },
|
|
{ id: 'AD_ECP_INTEREST', name: 'AD_ECP_INTEREST', label: 'AD:电商-引流电商种草', description: '引流电商种草' },
|
|
{ id: 'AD_ECP_SHOP', name: 'AD_ECP_SHOP', label: 'AD:电商-调起店铺', description: '调起店铺' },
|
|
{ id: 'AD_ECP_SHOP_STAY', name: 'AD_ECP_SHOP_STAY', label: 'AD:电商-店铺停留', description: '店铺停留' },
|
|
{ id: 'AD_MINIAPP_ACTIVATE', name: 'AD_MINIAPP_ACTIVATE', label: 'AD:快应用-激活', description: '快应用激活' },
|
|
{ id: 'AD_MINIAPP_KEY_BEHAVIOR', name: 'AD_MINIAPP_KEY_BEHAVIOR', label: 'AD:快应用-关键行为', description: '快应用关键行为' },
|
|
{ id: 'AD_MINIAPP_PAY', name: 'AD_MINIAPP_PAY', label: 'AD:快应用-付费', description: '快应用付费' },
|
|
{ id: 'AD_MINIAPP_REGISTER', name: 'AD_MINIAPP_REGISTER', label: 'AD:快应用-注册', description: '快应用注册' },
|
|
{ id: 'AD_NATIVE_ACTIVATE', name: 'AD_NATIVE_ACTIVATE', label: 'AD:原声互动-激活', description: '原声互动激活' },
|
|
{ id: 'AD_NATIVE_CLICKS', name: 'AD_NATIVE_CLICKS', label: 'AD:原声互动-组件点击', description: '组件点击' },
|
|
{ id: 'AD_NATIVE_FANS_GROUP', name: 'AD_NATIVE_FANS_GROUP', label: 'AD:原声互动-粉丝入群', description: '粉丝入群' },
|
|
{ id: 'AD_NATIVE_FOLLOW', name: 'AD_NATIVE_FOLLOW', label: 'AD:原声互动-帐号关注', description: '帐号关注' },
|
|
{ id: 'AD_NATIVE_INTERACTIVE', name: 'AD_NATIVE_INTERACTIVE', label: 'AD:原声互动-互动', description: '互动' },
|
|
{ id: 'AD_NATIVE_LIVE', name: 'AD_NATIVE_LIVE', label: 'AD:原声互动-预约直播', description: '预约直播' },
|
|
{ id: 'AD_NATIVE_LIVE_DONATE', name: 'AD_NATIVE_LIVE_DONATE', label: 'AD:原声互动-直播间营销捐赠', description: '直播间营销捐赠' },
|
|
{ id: 'AD_NATIVE_LIVE_PAY', name: 'AD_NATIVE_LIVE_PAY', label: 'AD:原声互动-直播间打赏', description: '直播间打赏' },
|
|
{ id: 'AD_NATIVE_LIVE_STAY', name: 'AD_NATIVE_LIVE_STAY', label: 'AD:原声互动-直播间停留', description: '直播间停留' },
|
|
{ id: 'AD_NATIVE_LIVE_VIEW', name: 'AD_NATIVE_LIVE_VIEW', label: 'AD:原声互动-直播间观看', description: '直播间观看' },
|
|
{ id: 'AD_NATIVE_PAY', name: 'AD_NATIVE_PAY', label: 'AD:原声互动-付费', description: '原声互动付费' },
|
|
{ id: 'AD_PRODUCT_ACTIVATE', name: 'AD_PRODUCT_ACTIVATE', label: 'AD:商品-激活', description: '商品激活' },
|
|
{ id: 'AD_PRODUCT_APP_BUY', name: 'AD_PRODUCT_APP_BUY', label: 'AD:商品-app内下单', description: '商品app内下单' },
|
|
{ id: 'AD_PRODUCT_APP_DETAIL', name: 'AD_PRODUCT_APP_DETAIL', label: 'AD:商品-app内详情页到站uv', description: '商品app内详情页到站uv' },
|
|
{ id: 'AD_PRODUCT_APP_PAY', name: 'AD_PRODUCT_APP_PAY', label: 'AD:商品-app内付费', description: '商品app内付费' },
|
|
{ id: 'AD_PRODUCT_APP_VIEW', name: 'AD_PRODUCT_APP_VIEW', label: 'AD:商品-app内访问', description: '商品app内访问' },
|
|
{ id: 'AD_PRODUCT_FORM', name: 'AD_PRODUCT_FORM', label: 'AD:商品-表单提交', description: '商品表单提交' },
|
|
{ id: 'AD_PRODUCT_KEY_BEHAVIOR', name: 'AD_PRODUCT_KEY_BEHAVIOR', label: 'AD:商品-关键行为', description: '商品关键行为' },
|
|
{ id: 'AD_PRODUCT_PAY', name: 'AD_PRODUCT_PAY', label: 'AD:商品-付费', description: '商品付费' },
|
|
{ id: 'AD_TINYAPP_ACTIVATE', name: 'AD_TINYAPP_ACTIVATE', label: '千川:小程序-激活', description: '小程序激活' },
|
|
{ id: 'AD_TINYAPP_KEY_BEHAVIOR', name: 'AD_TINYAPP_KEY_BEHAVIOR', label: '千川:小程序-关键行为', description: '小程序关键行为' },
|
|
{ id: 'AD_TINYAPP_PAY', name: 'AD_TINYAPP_PAY', label: '千川:小程序-付费', description: '小程序付费' },
|
|
{ id: 'QC_LIVE_BUY', name: 'QC_LIVE_BUY', label: '千川:直播投放-直播间下单', description: '直播间下单' },
|
|
{ id: 'QC_LIVE_CHECK', name: 'QC_LIVE_CHECK', label: '千川:直播投放-直播间结算', description: '直播间结算' },
|
|
{ id: 'QC_LIVE_COMMENTS', name: 'QC_LIVE_COMMENTS', label: '千川:直播投放-直播间评论', description: '直播间评论' },
|
|
{ id: 'QC_LIVE_DEAL', name: 'QC_LIVE_DEAL', label: '千川:直播投放-直播间成交', description: '直播间成交' },
|
|
{ id: 'QC_LIVE_ENTRY', name: 'QC_LIVE_ENTRY', label: '千川:直播投放-进入直播间', description: '进入直播间' },
|
|
{ id: 'QC_LIVE_FANS', name: 'QC_LIVE_FANS', label: '千川:直播投放-直播间粉丝提升', description: '直播间粉丝提升' },
|
|
{ id: 'QC_LIVE_HIT', name: 'QC_LIVE_HIT', label: '千川:直播投放-直播加热', description: '直播加热' },
|
|
{ id: 'QC_LIVE_PRODUCT_CLICKS', name: 'QC_LIVE_PRODUCT_CLICKS', label: '千川:直播投放-直播间商品点击', description: '直播间商品点击' },
|
|
{ id: 'QC_LIVE_ROI_CHECK', name: 'QC_LIVE_ROI_CHECK', label: '千川:直播投放-结算roi', description: '结算roi' },
|
|
{ id: 'QC_LIVE_ROI_DEAL', name: 'QC_LIVE_ROI_DEAL', label: '千川:直播投放-支付roi-直播间成交', description: '支付roi直播间成交' },
|
|
{ id: 'QC_LIVE_ROI_QC', name: 'QC_LIVE_ROI_QC', label: '千川:直播投放-支付roi-千川直接+间接订单', description: '支付roi千川订单' },
|
|
{ id: 'QC_PRODUCT_BUY', name: 'QC_PRODUCT_BUY', label: '千川:商品投放-商品购买', description: '商品购买' },
|
|
{ id: 'QC_PRODUCT_COMMENTS', name: 'QC_PRODUCT_COMMENTS', label: '千川:商品投放-点赞评论', description: '点赞评论' },
|
|
{ id: 'QC_PRODUCT_FANS', name: 'QC_PRODUCT_FANS', label: '千川:商品投放-粉丝提升', description: '粉丝提升' },
|
|
{ id: 'QC_PRODUCT_INTEREST', name: 'QC_PRODUCT_INTEREST', label: '千川:商品投放-人群种草', description: '人群种草' },
|
|
{ id: 'QC_PRODUCT_QC', name: 'QC_PRODUCT_QC', label: '千川:商品投放-千川直接+间接订单', description: '千川订单' },
|
|
{ id: 'QC_PRODUCT_ROI', name: 'QC_PRODUCT_ROI', label: '千川:商品投放-商品支付roi', description: '商品支付roi' },
|
|
];
|
|
|
|
const columns = [
|
|
{
|
|
title: '序号',
|
|
dataIndex: 'index',
|
|
key: 'index',
|
|
width: 70,
|
|
render: (text: number) => <Typography.Text style={{ color: '#94a3b8', fontSize: 13 }}>{text}</Typography.Text>,
|
|
},
|
|
{
|
|
title: '前测模板ID',
|
|
dataIndex: 'id',
|
|
key: 'id',
|
|
ellipsis: true,
|
|
width: 100,
|
|
render: (text: string) => <Typography.Text strong style={{ color: '#1e293b', fontSize: 13 }}>{text}</Typography.Text>,
|
|
},
|
|
{
|
|
title: '模板名称',
|
|
dataIndex: 'templateName',
|
|
key: 'templateName',
|
|
ellipsis: true,
|
|
width: 150,
|
|
render: (text: string) => (
|
|
<span style={{ color: '#1e293b', fontWeight: 500, fontSize: 13 }}>{text}</span>
|
|
),
|
|
},
|
|
{
|
|
title: '选中的字段',
|
|
dataIndex: 'selectedFields',
|
|
key: 'selectedFields',
|
|
render: (fields: string[]) => (
|
|
<Space wrap size={6}>
|
|
{fields.map((field) => {
|
|
const fieldInfo = PRETEST_FIELDS.find(f => f.name === field);
|
|
return (
|
|
<Tag
|
|
key={field}
|
|
style={{
|
|
background: 'rgba(99,102,241,0.08)',
|
|
color: '#6366f1',
|
|
border: 'none',
|
|
borderRadius: 6,
|
|
fontSize: 11,
|
|
padding: '2px 8px',
|
|
}}
|
|
>
|
|
{fieldInfo?.label || field}
|
|
</Tag>
|
|
);
|
|
})}
|
|
</Space>
|
|
),
|
|
},
|
|
{
|
|
title: '状态',
|
|
dataIndex: 'status',
|
|
key: 'status',
|
|
width: 100,
|
|
render: (text: string) => {
|
|
const config = statusConfig[text as keyof typeof statusConfig] || statusConfig.pending;
|
|
return (
|
|
<Tag color={config.color} style={{ borderRadius: 6, fontSize: 12, fontWeight: 500 }}>
|
|
{config.label}
|
|
</Tag>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
title: '创建时间',
|
|
dataIndex: 'createdAt',
|
|
key: 'createdAt',
|
|
width: 160,
|
|
render: (text: string) => <Typography.Text style={{ color: '#94a3b8', fontSize: 12 }}>{text}</Typography.Text>,
|
|
},
|
|
{
|
|
title: '操作',
|
|
dataIndex: 'operation',
|
|
key: 'operation',
|
|
width: 140,
|
|
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 [records, setRecords] = useState<PreTestRecord[]>([]);
|
|
const [total, setTotal] = useState(0);
|
|
const [loading, setLoading] = useState(false);
|
|
const [modalOpen, setModalOpen] = useState(false);
|
|
const [form] = Form.useForm();
|
|
const [submitLoading, setSubmitLoading] = useState(false);
|
|
const [currentPage, setCurrentPage] = useState(1);
|
|
const [pageSize, setPageSize] = useState(10);
|
|
|
|
useEffect(() => {
|
|
loadRecords();
|
|
}, [currentPage, pageSize]);
|
|
|
|
const loadRecords = async () => {
|
|
setLoading(true);
|
|
try {
|
|
const data = await getPreTestList({ page: currentPage, pageSize });
|
|
setRecords(data.items || []);
|
|
setTotal(data.total || 0);
|
|
} catch (error) {
|
|
message.error('获取前测列表失败');
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
const tableData = records.map((item, index) => ({
|
|
...item,
|
|
index: (currentPage - 1) * pageSize + index + 1,
|
|
key: item.id,
|
|
}));
|
|
|
|
const handleOpenModal = () => {
|
|
form.resetFields();
|
|
setModalOpen(true);
|
|
};
|
|
|
|
const handleCloseModal = () => {
|
|
setModalOpen(false);
|
|
form.resetFields();
|
|
};
|
|
|
|
const handleSubmit = async () => {
|
|
try {
|
|
const values = await form.validateFields();
|
|
setSubmitLoading(true);
|
|
|
|
const result = await createPreTest({
|
|
templateName: values.templateName,
|
|
selectedFields: values.selectedFields,
|
|
status: values.status,
|
|
});
|
|
|
|
message.success('前测模板创建成功');
|
|
setModalOpen(false);
|
|
form.resetFields();
|
|
loadRecords();
|
|
} catch (error) {
|
|
message.error('创建失败,请重试');
|
|
} finally {
|
|
setSubmitLoading(false);
|
|
}
|
|
};
|
|
|
|
const handlePageChange = (page: number, size: number) => {
|
|
setCurrentPage(page);
|
|
setPageSize(size);
|
|
};
|
|
|
|
return (
|
|
<div style={{ minHeight: 'calc(100vh - 80px)', background: '#f1f5f9', padding: 12, borderRadius: 12 }}>
|
|
<div>
|
|
<h1 style={{ lineHeight: '32px', fontSize: 26, fontWeight: 700, color: '#1e293b', marginBottom: 4, marginTop: 0 }}>
|
|
前测管理
|
|
</h1>
|
|
</div>
|
|
<div style={{ display: 'flex', justifyContent: 'flex-end', gap: 12, marginBottom: 16 }}>
|
|
<Button
|
|
type="primary"
|
|
size="medium"
|
|
icon={<PlusOutlined />}
|
|
loading={loading}
|
|
onClick={handleOpenModal}
|
|
style={{
|
|
borderRadius: 12,
|
|
fontSize: 14,
|
|
background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)',
|
|
border: 'none',
|
|
boxShadow: '0 4px 14px rgba(99,102,241,0.3)',
|
|
}}
|
|
>
|
|
新增前测
|
|
</Button>
|
|
</div>
|
|
<div style={{
|
|
background: '#fff',
|
|
borderRadius: 16,
|
|
boxShadow: '0 4px 20px rgba(0,0,0,0.04)',
|
|
overflow: 'hidden',
|
|
}}>
|
|
<Table
|
|
dataSource={tableData}
|
|
columns={columns}
|
|
loading={loading}
|
|
pagination={{
|
|
current: currentPage,
|
|
pageSize: pageSize,
|
|
total: total,
|
|
showSizeChanger: true,
|
|
showTotal: (total) => `共 ${total} 条记录`,
|
|
pageSizeOptions: ['10', '20', '50', '100'],
|
|
onChange: handlePageChange,
|
|
style: { padding: '16px 24px', borderTop: '1px solid #f1f5f9' },
|
|
}}
|
|
rowKey="id"
|
|
bordered={false}
|
|
style={{ padding: 0 }}
|
|
scroll={{ x: 'max-content' }}
|
|
onRow={() => ({
|
|
style: {
|
|
cursor: 'pointer',
|
|
transition: 'background-color 0.15s',
|
|
},
|
|
onMouseEnter: (e: React.MouseEvent) => {
|
|
(e.currentTarget as HTMLElement).style.backgroundColor = '#f8fafc';
|
|
},
|
|
onMouseLeave: (e: React.MouseEvent) => {
|
|
(e.currentTarget as HTMLElement).style.backgroundColor = 'transparent';
|
|
},
|
|
})}
|
|
/>
|
|
</div>
|
|
|
|
<Modal
|
|
title={<Space><PlusOutlined />新增前测模板</Space>}
|
|
open={modalOpen}
|
|
onCancel={handleCloseModal}
|
|
onOk={handleSubmit}
|
|
okText="提交"
|
|
cancelText="取消"
|
|
width={520}
|
|
confirmLoading={submitLoading}
|
|
style={{ borderRadius: 16 }}
|
|
>
|
|
<Form
|
|
form={form}
|
|
layout="vertical"
|
|
style={{ marginTop: 16 }}
|
|
>
|
|
<Form.Item
|
|
name="templateName"
|
|
label="模板名称"
|
|
rules={[{ required: true, message: '请输入模板名称' }]}
|
|
>
|
|
<Input
|
|
placeholder="请输入模板名称"
|
|
style={{ borderRadius: 8, height: 40 }}
|
|
/>
|
|
</Form.Item>
|
|
|
|
<Form.Item
|
|
name="selectedFields"
|
|
label="前测字段"
|
|
rules={[{ required: true, message: '请选择前测字段' }]}
|
|
>
|
|
<Select
|
|
mode="multiple"
|
|
placeholder="请选择前测字段(可多选)"
|
|
style={{ borderRadius: 8, minHeight: 40 }}
|
|
maxTagCount="responsive"
|
|
options={PRETEST_FIELDS.map(field => ({
|
|
value: field.name,
|
|
label: (
|
|
<span>
|
|
{field.label}
|
|
{field.description && (
|
|
<Typography.Text style={{ color: '#94a3b8', fontSize: 12, marginLeft: 4 }}>
|
|
({field.description})
|
|
</Typography.Text>
|
|
)}
|
|
</span>
|
|
),
|
|
}))}
|
|
/>
|
|
</Form.Item>
|
|
|
|
<Form.Item
|
|
name="status"
|
|
label="状态"
|
|
initialValue="pending"
|
|
>
|
|
<Select
|
|
placeholder="请选择状态"
|
|
style={{ borderRadius: 8, height: 40 }}
|
|
options={[
|
|
{ value: 'pending', label: '待测试' },
|
|
{ value: 'testing', label: '测试中' },
|
|
]}
|
|
/>
|
|
</Form.Item>
|
|
</Form>
|
|
</Modal>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default PreTest; |