解决搜索组件传参问题

This commit is contained in:
Lrd
2026-06-30 18:45:10 +08:00
parent 976fa1b5a6
commit 7c5580c76a
8 changed files with 1065 additions and 249 deletions
@@ -278,16 +278,6 @@ const AuthAccountPage: React.FC = () => {
>
</Button>
<Button
size="medium"
onClick={() => {
setSearchParams({ advertiser_id: '', oauth_id: '', advertiser_name: '' });
setCurrentPage(1);
loadOAuthList(1, pageSize);
}}
>
</Button>
</div>
</div>
+3 -10
View File
@@ -298,6 +298,7 @@ const AuthorizationPage: React.FC = () => {
value={searchParams.account_userid}
onChange={(e) => setSearchParams(prev => ({ ...prev, account_userid: e.target.value }))}
style={{ width: 180 }}
allowClear
onPressEnter={() => { setCurrentPage(1); loadOAuthList(1, pageSize); }}
/>
<Select
@@ -305,6 +306,7 @@ const AuthorizationPage: React.FC = () => {
value={searchParams.open_type}
onChange={(value) => setSearchParams(prev => ({ ...prev, open_type: value }))}
style={{ width: 140 }}
allowClear
options={openTypeOptions}
/>
<Input
@@ -312,6 +314,7 @@ const AuthorizationPage: React.FC = () => {
value={searchParams.account_id}
onChange={(e) => setSearchParams(prev => ({ ...prev, account_id: e.target.value }))}
style={{ width: 180 }}
allowClear
onPressEnter={() => { setCurrentPage(1); loadOAuthList(1, pageSize); }}
/>
<Button
@@ -321,16 +324,6 @@ const AuthorizationPage: React.FC = () => {
>
</Button>
<Button
size="medium"
onClick={() => {
setSearchParams({ account_userid: '', open_type: undefined, account_id: '' });
setCurrentPage(1);
loadOAuthList(1, pageSize);
}}
>
</Button>
</div>
<Button
type="primary"
+1 -6
View File
@@ -176,6 +176,7 @@ const ConsumePage: React.FC = () => {
value={advertiserId}
onChange={(e) => setAdvertiserId(e.target.value)}
style={{ width: 180 }}
allowClear
onPressEnter={() => { setCurrentPage(1); loadData(1, pageSize); }}
/>
<RangePicker
@@ -195,12 +196,6 @@ const ConsumePage: React.FC = () => {
>
</Button>
<Button
size="medium"
onClick={handleReset}
>
</Button>
</div>
<div style={{ display: 'flex', gap: 12 }}>
<Button
+170 -59
View File
@@ -1,8 +1,8 @@
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 { FolderOpenOutlined, EyeOutlined } from '@ant-design/icons';
import { getResourcesMaterialList } from '../api';
import { getResourcesMaterialList, getPreTestList } from '../api';
import PreResultDisplay from '../components/PreResultDisplay';
// 格式化时间 2026-06-12T03:47:28.542988Z -> 2026-06-12 03:47:28
@@ -82,11 +82,17 @@ interface MaterialData {
const MaterialListPage: React.FC = () => {
const { message } = App.useApp();
const navigate = useNavigate();
const [records, setRecords] = useState<any[]>([]);
const [materials, setMaterials] = useState<MaterialData[]>([]);
const [listLoading, setListLoading] = useState(false);
const [currentPage, setCurrentPage] = useState(1);
const [pageSize, setPageSize] = useState(10);
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({
advertiser_id: '',
material_id: '',
@@ -113,6 +119,7 @@ const MaterialListPage: React.FC = () => {
});
if (response?.code === 0) {
setMaterials(response.data || []);
setRecords(response.data || []);
setTotal(response.total || 0);
} else {
setMaterials([]);
@@ -303,6 +310,40 @@ const MaterialListPage: React.FC = () => {
index: index + 1,
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 (
<div style={{ minHeight: '94vh' }}>
@@ -310,64 +351,77 @@ const MaterialListPage: React.FC = () => {
<FolderOpenOutlined style={{ color: '#6366f1', fontSize: 16 }} />
<Typography.Text strong style={{ fontSize: 16 }}></Typography.Text>
</div>
<div style={{ display: 'flex', gap: 12, marginBottom: 16, flexWrap: 'wrap' }}>
<Input
placeholder="广告主ID"
value={searchParams.advertiser_id}
onChange={(e) => setSearchParams(prev => ({ ...prev, advertiser_id: e.target.value }))}
style={{ width: 160 }}
onPressEnter={() => { setCurrentPage(1); loadMaterialList(1, pageSize); }}
/>
<Input
placeholder="素材ID"
value={searchParams.material_id}
onChange={(e) => setSearchParams(prev => ({ ...prev, material_id: e.target.value }))}
style={{ width: 160 }}
onPressEnter={() => { setCurrentPage(1); loadMaterialList(1, pageSize); }}
/>
<Input
placeholder="上传ID"
value={searchParams.upload_id}
onChange={(e) => setSearchParams(prev => ({ ...prev, upload_id: e.target.value }))}
style={{ width: 160 }}
onPressEnter={() => { setCurrentPage(1); loadMaterialList(1, pageSize); }}
/>
<Input
placeholder="文件名"
value={searchParams.file_name}
onChange={(e) => setSearchParams(prev => ({ ...prev, file_name: e.target.value }))}
style={{ width: 140 }}
onPressEnter={() => { setCurrentPage(1); loadMaterialList(1, pageSize); }}
/>
<Select
placeholder="资源类型"
value={searchParams.resource_type}
onChange={(value) => setSearchParams(prev => ({ ...prev, resource_type: value }))}
style={{ width: 120 }}
allowClear
options={[
{ value: 'image', label: '图片' },
{ value: 'video', label: '视频' },
]}
/>
<Button
type="primary"
onClick={() => { setCurrentPage(1); loadMaterialList(1, pageSize); }}
>
</Button>
<Button
onClick={() => {
setSearchParams({ advertiser_id: '', material_id: '', upload_id: '', file_name: '', resource_type: undefined });
setCurrentPage(1);
loadMaterialList(1, pageSize);
}}
>
</Button>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'top', marginBottom: 16 }}>
<div style={{ display: 'flex', gap: 16, alignItems: 'center', flexWrap: 'wrap' }}>
<Input
placeholder="广告主ID"
value={searchParams.advertiser_id}
onChange={(e) => setSearchParams(prev => ({ ...prev, advertiser_id: e.target.value }))}
style={{ width: 160 }}
allowClear
onPressEnter={() => { setCurrentPage(1); loadMaterialList(1, pageSize); }}
/>
<Input
placeholder="素材ID"
value={searchParams.material_id}
onChange={(e) => setSearchParams(prev => ({ ...prev, material_id: e.target.value }))}
style={{ width: 160 }}
allowClear
onPressEnter={() => { setCurrentPage(1); loadMaterialList(1, pageSize); }}
/>
<Input
placeholder="上传ID"
value={searchParams.upload_id}
onChange={(e) => setSearchParams(prev => ({ ...prev, upload_id: e.target.value }))}
style={{ width: 160 }}
allowClear
onPressEnter={() => { setCurrentPage(1); loadMaterialList(1, pageSize); }}
/>
<Input
placeholder="文件名"
value={searchParams.file_name}
onChange={(e) => setSearchParams(prev => ({ ...prev, file_name: e.target.value }))}
style={{ width: 140 }}
allowClear
onPressEnter={() => { setCurrentPage(1); loadMaterialList(1, pageSize); }}
/>
<Select
placeholder="资源类型"
value={searchParams.resource_type}
onChange={(value) => setSearchParams(prev => ({ ...prev, resource_type: value }))}
style={{ width: 120 }}
allowClear
options={[
{ value: 'image', label: '图片' },
{ value: 'video', label: '视频' },
]}
/>
<Button
type="primary"
onClick={() => { setCurrentPage(1); loadMaterialList(1, pageSize); }}
>
</Button>
</div>
{/* <div style={{ display: 'flex', gap: 12 }}>
<Button
type="primary"
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 style={{ background: '#fff', borderRadius: 12, boxShadow: '0 1px 3px rgba(0,0,0,0.05)' }}>
<Table
dataSource={tableData}
@@ -377,6 +431,13 @@ const MaterialListPage: React.FC = () => {
rowKey="id"
bordered={false}
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' }}>
<Pagination
@@ -394,6 +455,56 @@ const MaterialListPage: React.FC = () => {
/>
</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>
);
};
+6 -163
View File
@@ -10,8 +10,6 @@ interface PreTestRecord {
selectedFields: string[];
status: string;
createdAt: string;
name: string;
platform: string;
}
interface PreTestField {
@@ -153,12 +151,6 @@ const PreTest: React.FC = () => {
const [areaOptions, setAreaOptions] = useState<any[]>([]);
const [cityCodeMap, setCityCodeMap] = 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(() => {
loadRecords();
@@ -168,10 +160,14 @@ const PreTest: React.FC = () => {
loadProvinceOptions();
}, []);
const loadRecords = async () => {
const loadRecords = async (params?: { page?: number; pageSize?: number; platform?: string }) => {
setLoading(true);
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 || []);
setTotal(res.pagination?.total || 0);
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 targetOption = selectedOptions[selectedOptions.length - 1];
console.log(targetOption);
targetOption.loading = true;
try {
const res = await getArea({ level: 'TWO_LEVEL', parent_code: targetOption.value });
@@ -476,15 +466,12 @@ const PreTest: React.FC = () => {
const regionPaths: string[][] = [];
for (const code of regionCodes) {
const cityCode = String(code);
console.log(cityCode);
if (cityCode.length >= 6) {
const provinceCode = cityCode.slice(0, 2);
console.log(provinceCode, cityCode);
loadCityOptions(provinceCode);
regionPaths.push([provinceCode, cityCode]);
}
}
console.log(regionPaths);
form.setFieldsValue({
name: data.name,
note: data.note,
@@ -558,7 +545,6 @@ const PreTest: React.FC = () => {
try {
const values = await form.validateFields();
setSubmitLoading(true);
console.log(values.audience_region);
const regionCodes: string[] = [];
(values.audience_region || []).forEach((path: string[]) => {
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) => {
setCurrentPage(page);
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 (
<div style={{ minHeight: 'calc(100vh - 80px)' }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 12 }}>
@@ -685,33 +631,8 @@ const PreTest: React.FC = () => {
>
</Button>
<Button
onClick={() => {
setSearchPlatform(undefined);
setCurrentPage(1);
loadRecords();
}}
>
</Button>
</div>
<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
type="primary"
size="medium"
@@ -744,13 +665,6 @@ const PreTest: React.FC = () => {
rowKey="id"
bordered={false}
scroll={{ x: 'max-content' }}
rowSelection={{
type: 'checkbox',
selectedRowKeys: Array.from(selectedRows),
onChange: (keys) => {
setSelectedRows(new Set(keys as string[]));
},
}}
onRow={() => ({
style: {
cursor: 'pointer',
@@ -1083,77 +997,6 @@ const PreTest: React.FC = () => {
</Form.Item>
</Form>
</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>
);
};