feat(流量池管理): 新增流量池添加功能及筛选条件优化

在流量池管理模块中,新增了添加流量池的API接口,并更新了筛选条件的结构,支持初始值的设置和状态的同步。优化了筛选条件的管理逻辑,提升了用户体验和代码可读性。
This commit is contained in:
超级老白兔
2025-09-22 11:51:37 +08:00
parent ce1eddad68
commit deb0eb85b5
3 changed files with 106 additions and 63 deletions

View File

@@ -10,13 +10,21 @@ interface FilterModalProps {
visible: boolean;
onClose: () => void;
onConfirm: (filters: {
deviceld: string[]; // 更新为 deviceld
packageld: string; // 更新为 packageld
taskId: string; // 更新为 taskId
selectedDevices: DeviceSelectionItem[]; // 更新为 deviceld
packageld: number; // 更新为 packageld
sceneId: number; // 更新为 sceneId
userValue: number;
addStatus: number; // 更新为 addStatus
}) => void;
scenarioOptions: ScenarioOption[];
// 初始筛选值
initialFilters?: {
selectedDevices: DeviceSelectionItem[];
packageId: number;
scenarioId: number;
userValue: number;
userStatus: number;
};
}
const valueLevelOptions = [
@@ -37,17 +45,35 @@ const FilterModal: React.FC<FilterModalProps> = ({
visible,
onClose,
onConfirm,
initialFilters,
}) => {
const [selectedDevices, setSelectedDevices] = useState<DeviceSelectionItem[]>(
[],
initialFilters?.selectedDevices || [],
);
const [packageId, setPackageId] = useState<number>(initialFilters?.packageId);
const [scenarioId, setScenarioId] = useState<number>(
initialFilters?.scenarioId,
);
const [userValue, setUserValue] = useState<number>(
initialFilters?.userValue || 0,
);
const [userStatus, setUserStatus] = useState<number>(
initialFilters?.userStatus || 0,
);
const [packageId, setPackageId] = useState<string>("");
const [scenarioId, setScenarioId] = useState<string>("");
const [userValue, setUserValue] = useState<number>(0);
const [userStatus, setUserStatus] = useState<number>(0);
const [scenarioOptions, setScenarioOptions] = useState<any[]>([]);
const [packageOptions, setPackageOptions] = useState<any[]>([]);
// 同步初始值变化
useEffect(() => {
if (initialFilters) {
setSelectedDevices(initialFilters.selectedDevices || []);
setPackageId(initialFilters.packageId || 0);
setScenarioId(initialFilters.scenarioId || 0);
setUserValue(initialFilters.userValue || 0);
setUserStatus(initialFilters.userStatus || 0);
}
}, [initialFilters]);
useEffect(() => {
if (visible) {
fetchScenarioOptions()
@@ -72,9 +98,9 @@ const FilterModal: React.FC<FilterModalProps> = ({
const handleApply = () => {
const params = {
deviceld: selectedDevices.map(d => d.id.toString()), // 更新为 deviceld
selectedDevices: selectedDevices, // 更新为 deviceld
packageld: packageId, // 更新为 packageld
taskId: scenarioId, // 更新为 taskId
sceneId: scenarioId, // 更新为 sceneId
userValue,
addStatus: userStatus, // 更新为 addStatus
};
@@ -119,7 +145,7 @@ const FilterModal: React.FC<FilterModalProps> = ({
value={packageId}
onChange={setPackageId}
options={[
{ label: "全部流量池", value: "" },
{ label: "全部流量池", value: 0 },
...packageOptions.map(p => ({ label: p.name, value: p.id })),
]}
/>
@@ -131,7 +157,7 @@ const FilterModal: React.FC<FilterModalProps> = ({
value={scenarioId}
onChange={setScenarioId}
options={[
{ label: "全部场景", value: "" },
{ label: "全部场景", value: 0 },
...scenarioOptions.map(s => ({ label: s.name, value: s.id })),
]}
/>

View File

@@ -16,3 +16,20 @@ export async function fetchScenarioOptions() {
export async function fetchPackageOptions() {
return request("/v1/traffic/pool/getPackage", {}, "GET");
}
export async function addPackage(params: {
type: string; // 类型 1搜索 2选择用户 3文件上传
addPackageId?: string;
addStatus?: string;
deviceId?: string;
keyword?: string;
packageId?: string;
packageName?: string; // 添加的流量池名称
tableFile?: string;
taskId?: string; // 任务id j及场景获客id
"userIds[]"?: string[];
userValue?: string;
[property: string]: any;
}) {
return request("/v1/traffic/pool/addPackage", params, "POST");
}

View File

@@ -15,7 +15,8 @@ import type { TrafficPoolUser, ScenarioOption } from "./data";
import DataAnalysisPanel from "./DataAnalysisPanel";
import FilterModal from "./FilterModal";
import BatchAddModal from "./BatchAddModal";
import { DeviceSelectionItem } from "@/components/DeviceSelection/data";
import { join } from "path";
const defaultAvatar =
"https://cdn.jsdelivr.net/gh/maokaka/static/avatar-default.png";
@@ -33,11 +34,15 @@ const TrafficPoolList: React.FC = () => {
// 筛选相关
const [showFilter, setShowFilter] = useState(false);
const [scenarioOptions, setScenarioOptions] = useState<ScenarioOption[]>([]);
const [selectedDevices, setSelectedDevices] = useState<any[]>([]);
const [packageId, setPackageId] = useState<number>(0);
const [scenarioId, setScenarioId] = useState<number>(0);
const [userValue, setUserValue] = useState<number>(0);
const [userStatus, setUserStatus] = useState<number>(0);
// 公共筛选条件状态
const [filterParams, setFilterParams] = useState({
selectedDevices: [] as DeviceSelectionItem[],
packageId: 0,
scenarioId: 0,
userValue: 0,
userStatus: 0,
});
// 批量相关
const [selectedIds, setSelectedIds] = useState<number[]>([]);
@@ -47,23 +52,21 @@ const TrafficPoolList: React.FC = () => {
const [showStats, setShowStats] = useState(false);
// 获取列表
const getList = async () => {
const getList = async (customParams?: any) => {
setLoading(true);
try {
const params: any = {
page,
pageSize,
keyword: search,
packageld: packageId, // 更新为 packageld
taskId: scenarioId,
userValue,
addStatus: userStatus,
packageld: filterParams.packageId,
sceneId: filterParams.scenarioId,
userValue: filterParams.userValue,
addStatus: filterParams.userStatus,
deviceld: filterParams.selectedDevices.map(d => d.id).join(),
...customParams, // 允许传入自定义参数覆盖
};
// 添加筛选参数
if (selectedDevices.length > 0) {
params.deviceld = selectedDevices.map(d => d.id).join(","); // 更新为 deviceld
}
console.log("搜索条件:", params);
const res = await fetchTrafficPoolList(params);
setList(res.list || []);
@@ -85,20 +88,6 @@ const TrafficPoolList: React.FC = () => {
});
}, []);
// 筛选条件变化时刷新列表
useEffect(() => {
getList();
// eslint-disable-next-line
}, [
page,
search,
selectedDevices,
packageId,
scenarioId,
userValue,
userStatus,
]);
// 全选/反选
const handleSelectAll = (checked: boolean) => {
if (checked) {
@@ -118,6 +107,7 @@ const TrafficPoolList: React.FC = () => {
// 批量加入分组/流量池
const handleBatchAdd = options => {
console.log("批量加入分组", options);
// TODO: 实现批量加入逻辑
setBatchModal(false);
setSelectedIds([]);
@@ -129,10 +119,13 @@ const TrafficPoolList: React.FC = () => {
const debouncedSearch = useCallback(() => {
const timer = setTimeout(() => {
setSearch(searchInput);
// 搜索时重置到第一页并请求列表
setPage(1);
getList({ keyword: searchInput, page: 1 });
}, 500); // 500ms 防抖延迟
return () => clearTimeout(timer);
}, [searchInput, setSearch]);
}, [searchInput]);
useEffect(() => {
const cleanup = debouncedSearch();
@@ -168,7 +161,7 @@ const TrafficPoolList: React.FC = () => {
/>
</div>
<Button
onClick={getList}
onClick={() => getList()}
loading={loading}
size="large"
icon={<ReloadOutlined />}
@@ -189,7 +182,7 @@ const TrafficPoolList: React.FC = () => {
style={{
display: "flex",
alignItems: "center",
padding: "8px 12px",
padding: "8px 12px 8px 26px",
background: "#fff",
borderBottom: "1px solid #f0f0f0",
}}
@@ -233,7 +226,10 @@ const TrafficPoolList: React.FC = () => {
pageSize={20}
total={total}
showSizeChanger={false}
onChange={setPage}
onChange={newPage => {
setPage(newPage);
getList({ page: newPage });
}}
/>
</div>
}
@@ -244,7 +240,6 @@ const TrafficPoolList: React.FC = () => {
onClose={() => setBatchModal(false)}
selectedCount={selectedIds.length}
onConfirm={data => {
console.log("收到批量操作数据:", data);
// 处理批量加入逻辑
handleBatchAdd(data);
}}
@@ -254,24 +249,29 @@ const TrafficPoolList: React.FC = () => {
visible={showFilter}
onClose={() => setShowFilter(false)}
onConfirm={filters => {
// 更新筛选条件
setSelectedDevices(
filters.deviceld.map(id => ({
id: parseInt(id),
memo: "",
imei: "",
wechatId: "",
status: "offline" as const,
})),
);
setPackageId(filters.packageld ? parseInt(filters.packageld) : 0);
setScenarioId(filters.taskId ? parseInt(filters.taskId) : 0);
setUserValue(filters.userValue);
setUserStatus(filters.addStatus);
// 重新获取列表
getList();
// 更新公共筛选条件状态
const newFilterParams = {
selectedDevices: filters.selectedDevices,
packageId: filters.packageld,
scenarioId: filters.sceneId,
userValue: filters.userValue,
userStatus: filters.addStatus,
};
setFilterParams(newFilterParams);
// 重置到第一页并请求列表
setPage(1);
getList({
page: 1,
packageld: newFilterParams.packageId,
sceneId: newFilterParams.scenarioId,
userValue: newFilterParams.userValue,
addStatus: newFilterParams.userStatus,
deviceld: newFilterParams.selectedDevices.map(d => d.id).join(),
});
}}
scenarioOptions={scenarioOptions}
initialFilters={filterParams}
/>
<div className={styles.listWrap}>
{list.length === 0 && !loading ? (