解决搜索组件传参问题
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-BvgCzUzu.js"></script>
|
<script type="module" crossorigin src="/assets/index-Lr6H0Lbj.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-BhPFzWLH.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-BhPFzWLH.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -278,16 +278,6 @@ const AuthAccountPage: React.FC = () => {
|
|||||||
>
|
>
|
||||||
搜索
|
搜索
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
|
||||||
size="medium"
|
|
||||||
onClick={() => {
|
|
||||||
setSearchParams({ advertiser_id: '', oauth_id: '', advertiser_name: '' });
|
|
||||||
setCurrentPage(1);
|
|
||||||
loadOAuthList(1, pageSize);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
重置
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -298,6 +298,7 @@ const AuthorizationPage: React.FC = () => {
|
|||||||
value={searchParams.account_userid}
|
value={searchParams.account_userid}
|
||||||
onChange={(e) => setSearchParams(prev => ({ ...prev, account_userid: e.target.value }))}
|
onChange={(e) => setSearchParams(prev => ({ ...prev, account_userid: e.target.value }))}
|
||||||
style={{ width: 180 }}
|
style={{ width: 180 }}
|
||||||
|
allowClear
|
||||||
onPressEnter={() => { setCurrentPage(1); loadOAuthList(1, pageSize); }}
|
onPressEnter={() => { setCurrentPage(1); loadOAuthList(1, pageSize); }}
|
||||||
/>
|
/>
|
||||||
<Select
|
<Select
|
||||||
@@ -305,6 +306,7 @@ const AuthorizationPage: React.FC = () => {
|
|||||||
value={searchParams.open_type}
|
value={searchParams.open_type}
|
||||||
onChange={(value) => setSearchParams(prev => ({ ...prev, open_type: value }))}
|
onChange={(value) => setSearchParams(prev => ({ ...prev, open_type: value }))}
|
||||||
style={{ width: 140 }}
|
style={{ width: 140 }}
|
||||||
|
allowClear
|
||||||
options={openTypeOptions}
|
options={openTypeOptions}
|
||||||
/>
|
/>
|
||||||
<Input
|
<Input
|
||||||
@@ -312,6 +314,7 @@ const AuthorizationPage: React.FC = () => {
|
|||||||
value={searchParams.account_id}
|
value={searchParams.account_id}
|
||||||
onChange={(e) => setSearchParams(prev => ({ ...prev, account_id: e.target.value }))}
|
onChange={(e) => setSearchParams(prev => ({ ...prev, account_id: e.target.value }))}
|
||||||
style={{ width: 180 }}
|
style={{ width: 180 }}
|
||||||
|
allowClear
|
||||||
onPressEnter={() => { setCurrentPage(1); loadOAuthList(1, pageSize); }}
|
onPressEnter={() => { setCurrentPage(1); loadOAuthList(1, pageSize); }}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
@@ -321,16 +324,6 @@ const AuthorizationPage: React.FC = () => {
|
|||||||
>
|
>
|
||||||
搜索
|
搜索
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
|
||||||
size="medium"
|
|
||||||
onClick={() => {
|
|
||||||
setSearchParams({ account_userid: '', open_type: undefined, account_id: '' });
|
|
||||||
setCurrentPage(1);
|
|
||||||
loadOAuthList(1, pageSize);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
重置
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
|
|||||||
@@ -176,6 +176,7 @@ const ConsumePage: React.FC = () => {
|
|||||||
value={advertiserId}
|
value={advertiserId}
|
||||||
onChange={(e) => setAdvertiserId(e.target.value)}
|
onChange={(e) => setAdvertiserId(e.target.value)}
|
||||||
style={{ width: 180 }}
|
style={{ width: 180 }}
|
||||||
|
allowClear
|
||||||
onPressEnter={() => { setCurrentPage(1); loadData(1, pageSize); }}
|
onPressEnter={() => { setCurrentPage(1); loadData(1, pageSize); }}
|
||||||
/>
|
/>
|
||||||
<RangePicker
|
<RangePicker
|
||||||
@@ -195,12 +196,6 @@ const ConsumePage: React.FC = () => {
|
|||||||
>
|
>
|
||||||
搜索
|
搜索
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
|
||||||
size="medium"
|
|
||||||
onClick={handleReset}
|
|
||||||
>
|
|
||||||
重置
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: 'flex', gap: 12 }}>
|
<div style={{ display: 'flex', gap: 12 }}>
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { Button, Table, Tag, Input, Pagination, Typography, Select, App } from 'antd';
|
import { Button, Table, Tag, Input, Pagination, Typography, Select, App, Modal } from 'antd';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { FolderOpenOutlined, EyeOutlined } from '@ant-design/icons';
|
import { FolderOpenOutlined, EyeOutlined } from '@ant-design/icons';
|
||||||
import { getResourcesMaterialList } from '../api';
|
import { getResourcesMaterialList, getPreTestList } from '../api';
|
||||||
import PreResultDisplay from '../components/PreResultDisplay';
|
import PreResultDisplay from '../components/PreResultDisplay';
|
||||||
|
|
||||||
// 格式化时间 2026-06-12T03:47:28.542988Z -> 2026-06-12 03:47:28
|
// 格式化时间 2026-06-12T03:47:28.542988Z -> 2026-06-12 03:47:28
|
||||||
@@ -82,11 +82,17 @@ interface MaterialData {
|
|||||||
const MaterialListPage: React.FC = () => {
|
const MaterialListPage: React.FC = () => {
|
||||||
const { message } = App.useApp();
|
const { message } = App.useApp();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const [records, setRecords] = useState<any[]>([]);
|
||||||
const [materials, setMaterials] = useState<MaterialData[]>([]);
|
const [materials, setMaterials] = useState<MaterialData[]>([]);
|
||||||
const [listLoading, setListLoading] = useState(false);
|
const [listLoading, setListLoading] = useState(false);
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
const [pageSize, setPageSize] = useState(10);
|
const [pageSize, setPageSize] = useState(10);
|
||||||
const [total, setTotal] = useState(0);
|
const [total, setTotal] = useState(0);
|
||||||
|
const [selectedRows, setSelectedRows] = useState<Set<string>>(new Set());
|
||||||
|
const [pushModalOpen, setPushModalOpen] = useState(false);
|
||||||
|
const [pushPreTestTemplate, setPushPreTestTemplate] = useState<string>('');
|
||||||
|
const [pushTemplates, setPushTemplates] = useState<any[]>([]);
|
||||||
|
const [pushTemplatesLoading, setPushTemplatesLoading] = useState(false);
|
||||||
const [searchParams, setSearchParams] = useState({
|
const [searchParams, setSearchParams] = useState({
|
||||||
advertiser_id: '',
|
advertiser_id: '',
|
||||||
material_id: '',
|
material_id: '',
|
||||||
@@ -113,6 +119,7 @@ const MaterialListPage: React.FC = () => {
|
|||||||
});
|
});
|
||||||
if (response?.code === 0) {
|
if (response?.code === 0) {
|
||||||
setMaterials(response.data || []);
|
setMaterials(response.data || []);
|
||||||
|
setRecords(response.data || []);
|
||||||
setTotal(response.total || 0);
|
setTotal(response.total || 0);
|
||||||
} else {
|
} else {
|
||||||
setMaterials([]);
|
setMaterials([]);
|
||||||
@@ -304,70 +311,117 @@ const MaterialListPage: React.FC = () => {
|
|||||||
key: item.id,
|
key: item.id,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const handleOpenPushModal = async () => {
|
||||||
|
if (selectedRows.size === 0) {
|
||||||
|
message.warning('请先选择要推送的前测模板');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setPushTemplatesLoading(true);
|
||||||
|
try {
|
||||||
|
const res = await getPreTestList({ page: 1, pageSize: 100 });
|
||||||
|
setPushTemplates(res.data || []);
|
||||||
|
} catch (error) {
|
||||||
|
message.error('获取前测模板列表失败');
|
||||||
|
} finally {
|
||||||
|
setPushTemplatesLoading(false);
|
||||||
|
}
|
||||||
|
setPushPreTestTemplate('');
|
||||||
|
setPushModalOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePushSubmit = async () => {
|
||||||
|
if (selectedRows.size === 0) {
|
||||||
|
message.warning('请先选择要推送的素材');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!pushPreTestTemplate) {
|
||||||
|
message.warning('请选择前测模板');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
message.success('推送素材成功');
|
||||||
|
setPushModalOpen(false);
|
||||||
|
setSelectedRows(new Set());
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectedRecords = records.filter(record => selectedRows.has(record.id));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ minHeight: '94vh' }}>
|
<div style={{ minHeight: '94vh' }}>
|
||||||
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 12 }}>
|
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 12 }}>
|
||||||
<FolderOpenOutlined style={{ color: '#6366f1', fontSize: 16 }} />
|
<FolderOpenOutlined style={{ color: '#6366f1', fontSize: 16 }} />
|
||||||
<Typography.Text strong style={{ fontSize: 16 }}>素材列表</Typography.Text>
|
<Typography.Text strong style={{ fontSize: 16 }}>素材列表</Typography.Text>
|
||||||
</div>
|
</div>
|
||||||
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'top', marginBottom: 16 }}>
|
||||||
<div style={{ display: 'flex', gap: 12, marginBottom: 16, flexWrap: 'wrap' }}>
|
<div style={{ display: 'flex', gap: 16, alignItems: 'center', flexWrap: 'wrap' }}>
|
||||||
<Input
|
<Input
|
||||||
placeholder="广告主ID"
|
placeholder="广告主ID"
|
||||||
value={searchParams.advertiser_id}
|
value={searchParams.advertiser_id}
|
||||||
onChange={(e) => setSearchParams(prev => ({ ...prev, advertiser_id: e.target.value }))}
|
onChange={(e) => setSearchParams(prev => ({ ...prev, advertiser_id: e.target.value }))}
|
||||||
style={{ width: 160 }}
|
style={{ width: 160 }}
|
||||||
onPressEnter={() => { setCurrentPage(1); loadMaterialList(1, pageSize); }}
|
allowClear
|
||||||
/>
|
onPressEnter={() => { setCurrentPage(1); loadMaterialList(1, pageSize); }}
|
||||||
<Input
|
/>
|
||||||
placeholder="素材ID"
|
<Input
|
||||||
value={searchParams.material_id}
|
placeholder="素材ID"
|
||||||
onChange={(e) => setSearchParams(prev => ({ ...prev, material_id: e.target.value }))}
|
value={searchParams.material_id}
|
||||||
style={{ width: 160 }}
|
onChange={(e) => setSearchParams(prev => ({ ...prev, material_id: e.target.value }))}
|
||||||
onPressEnter={() => { setCurrentPage(1); loadMaterialList(1, pageSize); }}
|
style={{ width: 160 }}
|
||||||
/>
|
allowClear
|
||||||
<Input
|
onPressEnter={() => { setCurrentPage(1); loadMaterialList(1, pageSize); }}
|
||||||
placeholder="上传ID"
|
/>
|
||||||
value={searchParams.upload_id}
|
<Input
|
||||||
onChange={(e) => setSearchParams(prev => ({ ...prev, upload_id: e.target.value }))}
|
placeholder="上传ID"
|
||||||
style={{ width: 160 }}
|
value={searchParams.upload_id}
|
||||||
onPressEnter={() => { setCurrentPage(1); loadMaterialList(1, pageSize); }}
|
onChange={(e) => setSearchParams(prev => ({ ...prev, upload_id: e.target.value }))}
|
||||||
/>
|
style={{ width: 160 }}
|
||||||
<Input
|
allowClear
|
||||||
placeholder="文件名"
|
onPressEnter={() => { setCurrentPage(1); loadMaterialList(1, pageSize); }}
|
||||||
value={searchParams.file_name}
|
/>
|
||||||
onChange={(e) => setSearchParams(prev => ({ ...prev, file_name: e.target.value }))}
|
<Input
|
||||||
style={{ width: 140 }}
|
placeholder="文件名"
|
||||||
onPressEnter={() => { setCurrentPage(1); loadMaterialList(1, pageSize); }}
|
value={searchParams.file_name}
|
||||||
/>
|
onChange={(e) => setSearchParams(prev => ({ ...prev, file_name: e.target.value }))}
|
||||||
<Select
|
style={{ width: 140 }}
|
||||||
placeholder="资源类型"
|
allowClear
|
||||||
value={searchParams.resource_type}
|
onPressEnter={() => { setCurrentPage(1); loadMaterialList(1, pageSize); }}
|
||||||
onChange={(value) => setSearchParams(prev => ({ ...prev, resource_type: value }))}
|
/>
|
||||||
style={{ width: 120 }}
|
<Select
|
||||||
allowClear
|
placeholder="资源类型"
|
||||||
options={[
|
value={searchParams.resource_type}
|
||||||
{ value: 'image', label: '图片' },
|
onChange={(value) => setSearchParams(prev => ({ ...prev, resource_type: value }))}
|
||||||
{ value: 'video', label: '视频' },
|
style={{ width: 120 }}
|
||||||
]}
|
allowClear
|
||||||
/>
|
options={[
|
||||||
<Button
|
{ value: 'image', label: '图片' },
|
||||||
type="primary"
|
{ value: 'video', label: '视频' },
|
||||||
onClick={() => { setCurrentPage(1); loadMaterialList(1, pageSize); }}
|
]}
|
||||||
>
|
/>
|
||||||
搜索
|
<Button
|
||||||
</Button>
|
type="primary"
|
||||||
<Button
|
onClick={() => { setCurrentPage(1); loadMaterialList(1, pageSize); }}
|
||||||
onClick={() => {
|
>
|
||||||
setSearchParams({ advertiser_id: '', material_id: '', upload_id: '', file_name: '', resource_type: undefined });
|
搜索
|
||||||
setCurrentPage(1);
|
</Button>
|
||||||
loadMaterialList(1, pageSize);
|
</div>
|
||||||
}}
|
{/* <div style={{ display: 'flex', gap: 12 }}>
|
||||||
>
|
<Button
|
||||||
重置
|
type="primary"
|
||||||
</Button>
|
loading={pushTemplatesLoading}
|
||||||
|
onClick={handleOpenPushModal}
|
||||||
|
disabled={selectedRows.size === 0}
|
||||||
|
style={{
|
||||||
|
borderRadius: 12,
|
||||||
|
fontSize: 14,
|
||||||
|
background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)',
|
||||||
|
border: 'none',
|
||||||
|
color: '#fff',
|
||||||
|
boxShadow: '0 4px 14px rgba(99,102,241,0.3)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
推送前测 ({selectedRows.size})
|
||||||
|
</Button>
|
||||||
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={{ background: '#fff', borderRadius: 12, boxShadow: '0 1px 3px rgba(0,0,0,0.05)' }}>
|
<div style={{ background: '#fff', borderRadius: 12, boxShadow: '0 1px 3px rgba(0,0,0,0.05)' }}>
|
||||||
<Table
|
<Table
|
||||||
dataSource={tableData}
|
dataSource={tableData}
|
||||||
@@ -377,6 +431,13 @@ const MaterialListPage: React.FC = () => {
|
|||||||
rowKey="id"
|
rowKey="id"
|
||||||
bordered={false}
|
bordered={false}
|
||||||
scroll={{ x: 'max-content' }}
|
scroll={{ x: 'max-content' }}
|
||||||
|
// rowSelection={{
|
||||||
|
// type: 'checkbox',
|
||||||
|
// selectedRowKeys: Array.from(selectedRows),
|
||||||
|
// onChange: (keys) => {
|
||||||
|
// setSelectedRows(new Set(keys as string[]));
|
||||||
|
// },
|
||||||
|
// }}
|
||||||
/>
|
/>
|
||||||
<div style={{ padding: '16px', textAlign: 'right' }}>
|
<div style={{ padding: '16px', textAlign: 'right' }}>
|
||||||
<Pagination
|
<Pagination
|
||||||
@@ -394,6 +455,56 @@ const MaterialListPage: React.FC = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<Modal
|
||||||
|
title="推送前测"
|
||||||
|
open={pushModalOpen}
|
||||||
|
onCancel={() => { setPushModalOpen(false); setSelectedRows(new Set()); }}
|
||||||
|
onOk={handlePushSubmit}
|
||||||
|
okText="推送"
|
||||||
|
cancelText="取消"
|
||||||
|
width={600}
|
||||||
|
style={{ borderRadius: 16 }}
|
||||||
|
>
|
||||||
|
<div style={{ display: 'flex', gap: 16, marginBottom: 24 }}>
|
||||||
|
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
|
||||||
|
<Typography.Text style={{ fontSize: 14, color: '#475569' }}>前测模板:</Typography.Text>
|
||||||
|
<Select
|
||||||
|
value={pushPreTestTemplate}
|
||||||
|
onChange={(value) => setPushPreTestTemplate(value)}
|
||||||
|
style={{ width: 200 }}
|
||||||
|
loading={pushTemplatesLoading}
|
||||||
|
placeholder="选择前测模板"
|
||||||
|
options={pushTemplates.map((item) => ({
|
||||||
|
value: item.id,
|
||||||
|
label: item.name,
|
||||||
|
}))}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{ marginBottom: 12 }}>
|
||||||
|
<Typography.Text strong style={{ fontSize: 14, color: '#1e293b', display: 'block', marginBottom: 12 }}>
|
||||||
|
已选素材 ({selectedRows.size})
|
||||||
|
</Typography.Text>
|
||||||
|
<div style={{ maxHeight: 200, overflowY: 'auto' }}>
|
||||||
|
{selectedRecords.length > 0 ? (
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
|
||||||
|
{selectedRecords.map(record => (
|
||||||
|
<div key={record.id} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: 12, background: '#f8fafc', borderRadius: 8 }}>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
||||||
|
<Typography.Text strong style={{ fontSize: 14, color: '#1e293b' }}>{record.resource.fileName}</Typography.Text>
|
||||||
|
<Typography.Text style={{ fontSize: 12, color: '#94a3b8' }}>ID: {record.id}</Typography.Text>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<Typography.Text style={{ color: '#94a3b8' }}>暂无选中的前测模板</Typography.Text>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,8 +10,6 @@ interface PreTestRecord {
|
|||||||
selectedFields: string[];
|
selectedFields: string[];
|
||||||
status: string;
|
status: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
name: string;
|
|
||||||
platform: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PreTestField {
|
interface PreTestField {
|
||||||
@@ -153,12 +151,6 @@ const PreTest: React.FC = () => {
|
|||||||
const [areaOptions, setAreaOptions] = useState<any[]>([]);
|
const [areaOptions, setAreaOptions] = useState<any[]>([]);
|
||||||
const [cityCodeMap, setCityCodeMap] = useState<Record<string, string>>({});
|
const [cityCodeMap, setCityCodeMap] = useState<Record<string, string>>({});
|
||||||
const [provinceCityMap, setProvinceCityMap] = useState<Record<string, string[]>>({});
|
const [provinceCityMap, setProvinceCityMap] = useState<Record<string, string[]>>({});
|
||||||
const [selectedRows, setSelectedRows] = useState<Set<string>>(new Set());
|
|
||||||
const [pushModalOpen, setPushModalOpen] = useState(false);
|
|
||||||
const [pushIsPreTest, setPushIsPreTest] = useState<'1' | '2'>('2');
|
|
||||||
const [pushPreTestTemplate, setPushPreTestTemplate] = useState<string>('');
|
|
||||||
const [pushTemplates, setPushTemplates] = useState<any[]>([]);
|
|
||||||
const [pushTemplatesLoading, setPushTemplatesLoading] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
loadRecords();
|
loadRecords();
|
||||||
@@ -168,10 +160,14 @@ const PreTest: React.FC = () => {
|
|||||||
loadProvinceOptions();
|
loadProvinceOptions();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const loadRecords = async () => {
|
const loadRecords = async (params?: { page?: number; pageSize?: number; platform?: string }) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const res = await getPreTestList({ page: currentPage, pageSize, platform: searchPlatform });
|
console.log(params);
|
||||||
|
const page = params?.page ?? currentPage;
|
||||||
|
const size = params?.pageSize ?? pageSize;
|
||||||
|
const platform = params?.platform ?? searchPlatform;
|
||||||
|
const res = await getPreTestList({ page, pageSize: size, platform });
|
||||||
setRecords(res.data || []);
|
setRecords(res.data || []);
|
||||||
setTotal(res.pagination?.total || 0);
|
setTotal(res.pagination?.total || 0);
|
||||||
setCurrentPage(res.pagination?.page || 1);
|
setCurrentPage(res.pagination?.page || 1);
|
||||||
@@ -237,14 +233,8 @@ const PreTest: React.FC = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadProvince = async () => {
|
|
||||||
const cityRes = await getArea({ level: 'TWO_LEVEL' });
|
|
||||||
console.log(cityRes);
|
|
||||||
}
|
|
||||||
|
|
||||||
const loadCityOptions = async (selectedOptions: any) => {
|
const loadCityOptions = async (selectedOptions: any) => {
|
||||||
const targetOption = selectedOptions[selectedOptions.length - 1];
|
const targetOption = selectedOptions[selectedOptions.length - 1];
|
||||||
console.log(targetOption);
|
|
||||||
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 });
|
||||||
@@ -476,15 +466,12 @@ const PreTest: React.FC = () => {
|
|||||||
const regionPaths: string[][] = [];
|
const regionPaths: string[][] = [];
|
||||||
for (const code of regionCodes) {
|
for (const code of regionCodes) {
|
||||||
const cityCode = String(code);
|
const cityCode = String(code);
|
||||||
console.log(cityCode);
|
|
||||||
if (cityCode.length >= 6) {
|
if (cityCode.length >= 6) {
|
||||||
const provinceCode = cityCode.slice(0, 2);
|
const provinceCode = cityCode.slice(0, 2);
|
||||||
console.log(provinceCode, cityCode);
|
|
||||||
loadCityOptions(provinceCode);
|
loadCityOptions(provinceCode);
|
||||||
regionPaths.push([provinceCode, cityCode]);
|
regionPaths.push([provinceCode, cityCode]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log(regionPaths);
|
|
||||||
form.setFieldsValue({
|
form.setFieldsValue({
|
||||||
name: data.name,
|
name: data.name,
|
||||||
note: data.note,
|
note: data.note,
|
||||||
@@ -558,7 +545,6 @@ const PreTest: React.FC = () => {
|
|||||||
try {
|
try {
|
||||||
const values = await form.validateFields();
|
const values = await form.validateFields();
|
||||||
setSubmitLoading(true);
|
setSubmitLoading(true);
|
||||||
console.log(values.audience_region);
|
|
||||||
const regionCodes: string[] = [];
|
const regionCodes: string[] = [];
|
||||||
(values.audience_region || []).forEach((path: string[]) => {
|
(values.audience_region || []).forEach((path: string[]) => {
|
||||||
if (path.length === 1) {
|
if (path.length === 1) {
|
||||||
@@ -614,51 +600,11 @@ const PreTest: React.FC = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// [['34', '340800'],['35', '350100']]
|
|
||||||
// [['35', '350100']]
|
|
||||||
// [['34'],['35']]
|
|
||||||
// [['50']]
|
|
||||||
|
|
||||||
const handlePageChange = (page: number, size: number) => {
|
const handlePageChange = (page: number, size: number) => {
|
||||||
setCurrentPage(page);
|
setCurrentPage(page);
|
||||||
setPageSize(size);
|
setPageSize(size);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleOpenPushModal = async () => {
|
|
||||||
if (selectedRows.size === 0) {
|
|
||||||
message.warning('请先选择要推送的前测模板');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setPushTemplatesLoading(true);
|
|
||||||
try {
|
|
||||||
const res = await getPreTestList({ page: 1, pageSize: 100 });
|
|
||||||
setPushTemplates(res.data || []);
|
|
||||||
} catch (error) {
|
|
||||||
message.error('获取前测模板列表失败');
|
|
||||||
} finally {
|
|
||||||
setPushTemplatesLoading(false);
|
|
||||||
}
|
|
||||||
setPushIsPreTest('2');
|
|
||||||
setPushPreTestTemplate('');
|
|
||||||
setPushModalOpen(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handlePushSubmit = async () => {
|
|
||||||
if (selectedRows.size === 0) {
|
|
||||||
message.warning('请先选择要推送的前测模板');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (pushIsPreTest === '1' && !pushPreTestTemplate) {
|
|
||||||
message.warning('请选择前测模板');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
message.success('推送前测成功');
|
|
||||||
setPushModalOpen(false);
|
|
||||||
setSelectedRows(new Set());
|
|
||||||
};
|
|
||||||
|
|
||||||
const selectedRecords = records.filter(record => selectedRows.has(record.id));
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ minHeight: 'calc(100vh - 80px)' }}>
|
<div style={{ minHeight: 'calc(100vh - 80px)' }}>
|
||||||
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 12 }}>
|
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 12 }}>
|
||||||
@@ -685,33 +631,8 @@ const PreTest: React.FC = () => {
|
|||||||
>
|
>
|
||||||
搜索
|
搜索
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
|
||||||
onClick={() => {
|
|
||||||
setSearchPlatform(undefined);
|
|
||||||
setCurrentPage(1);
|
|
||||||
loadRecords();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
重置
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: 'flex', gap: 12 }}>
|
<div style={{ display: 'flex', gap: 12 }}>
|
||||||
<Button
|
|
||||||
type="primary"
|
|
||||||
size="medium"
|
|
||||||
loading={pushTemplatesLoading}
|
|
||||||
onClick={handleOpenPushModal}
|
|
||||||
disabled={selectedRows.size === 0}
|
|
||||||
style={{
|
|
||||||
borderRadius: 12,
|
|
||||||
fontSize: 14,
|
|
||||||
background: 'linear-gradient(135deg, #10b981 0%, #059669 100%)',
|
|
||||||
border: 'none',
|
|
||||||
boxShadow: '0 4px 14px rgba(16,185,129,0.3)',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
推送前测 ({selectedRows.size})
|
|
||||||
</Button>
|
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
size="medium"
|
size="medium"
|
||||||
@@ -744,13 +665,6 @@ const PreTest: React.FC = () => {
|
|||||||
rowKey="id"
|
rowKey="id"
|
||||||
bordered={false}
|
bordered={false}
|
||||||
scroll={{ x: 'max-content' }}
|
scroll={{ x: 'max-content' }}
|
||||||
rowSelection={{
|
|
||||||
type: 'checkbox',
|
|
||||||
selectedRowKeys: Array.from(selectedRows),
|
|
||||||
onChange: (keys) => {
|
|
||||||
setSelectedRows(new Set(keys as string[]));
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
onRow={() => ({
|
onRow={() => ({
|
||||||
style: {
|
style: {
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
@@ -1083,77 +997,6 @@ const PreTest: React.FC = () => {
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Form>
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<Modal
|
|
||||||
title="推送前测"
|
|
||||||
open={pushModalOpen}
|
|
||||||
onCancel={() => { setPushModalOpen(false); setSelectedRows(new Set()); }}
|
|
||||||
onOk={handlePushSubmit}
|
|
||||||
okText="推送"
|
|
||||||
cancelText="取消"
|
|
||||||
width={600}
|
|
||||||
style={{ borderRadius: 16 }}
|
|
||||||
>
|
|
||||||
<div style={{ display: 'flex', gap: 16, marginBottom: 24 }}>
|
|
||||||
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
|
|
||||||
<Typography.Text style={{ fontSize: 14, color: '#475569' }}>是否开启前测:</Typography.Text>
|
|
||||||
<Select
|
|
||||||
value={pushIsPreTest}
|
|
||||||
onChange={(value) => {
|
|
||||||
setPushIsPreTest(value);
|
|
||||||
if (value !== '1') {
|
|
||||||
setPushPreTestTemplate('');
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
style={{ width: 120 }}
|
|
||||||
options={[
|
|
||||||
{ value: '1', label: '是' },
|
|
||||||
{ value: '2', label: '否' },
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
|
|
||||||
<Typography.Text style={{ fontSize: 14, color: '#475569' }}>前测模板:</Typography.Text>
|
|
||||||
<Select
|
|
||||||
value={pushPreTestTemplate}
|
|
||||||
onChange={(value) => setPushPreTestTemplate(value)}
|
|
||||||
style={{ width: 200 }}
|
|
||||||
disabled={pushIsPreTest !== '1'}
|
|
||||||
loading={pushTemplatesLoading}
|
|
||||||
placeholder={pushIsPreTest !== '1' ? '请先开启前测' : '选择前测模板'}
|
|
||||||
options={pushTemplates.map((item) => ({
|
|
||||||
value: item.id,
|
|
||||||
label: item.name,
|
|
||||||
}))}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style={{ marginBottom: 12 }}>
|
|
||||||
<Typography.Text strong style={{ fontSize: 14, color: '#1e293b', display: 'block', marginBottom: 12 }}>
|
|
||||||
已选前测模板 ({selectedRows.size})
|
|
||||||
</Typography.Text>
|
|
||||||
<div style={{ maxHeight: 200, overflowY: 'auto' }}>
|
|
||||||
{selectedRecords.length > 0 ? (
|
|
||||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
|
|
||||||
{selectedRecords.map(record => (
|
|
||||||
<div key={record.id} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: 12, background: '#f8fafc', borderRadius: 8 }}>
|
|
||||||
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
|
||||||
<Typography.Text strong style={{ fontSize: 14, color: '#1e293b' }}>{record.name}</Typography.Text>
|
|
||||||
<Typography.Text style={{ fontSize: 12, color: '#94a3b8' }}>ID: {record.id}</Typography.Text>
|
|
||||||
</div>
|
|
||||||
<Tag color={record.platform === 'AD' ? 'blue' : record.platform === 'QIANCHUAN' ? 'green' : 'orange'} style={{ borderRadius: 6, fontSize: 12 }}>
|
|
||||||
{record.platform === 'AD' ? 'AD' : record.platform === 'QIANCHUAN' ? '千川' : '本地推'}
|
|
||||||
</Tag>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<Typography.Text style={{ color: '#94a3b8' }}>暂无选中的前测模板</Typography.Text>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Modal>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user