FEAT => 本次更新项目为:
This commit is contained in:
@@ -1,28 +1,54 @@
|
||||
import React from "react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { Popup, Selector, Button } from "antd-mobile";
|
||||
import { fetchPackageOptions } from "./api";
|
||||
import type { PackageOption } from "./data";
|
||||
|
||||
interface BatchAddModalProps {
|
||||
visible: boolean;
|
||||
onClose: () => void;
|
||||
packageOptions: PackageOption[];
|
||||
batchTarget: string;
|
||||
setBatchTarget: (v: string) => void;
|
||||
selectedCount: number;
|
||||
onConfirm: (options) => void;
|
||||
onConfirm: (data: {
|
||||
packageOptions: PackageOption[];
|
||||
selectedPackageId: string;
|
||||
}) => void;
|
||||
}
|
||||
|
||||
const BatchAddModal: React.FC<BatchAddModalProps> = ({
|
||||
visible,
|
||||
onClose,
|
||||
packageOptions = [],
|
||||
batchTarget,
|
||||
setBatchTarget,
|
||||
selectedCount,
|
||||
onConfirm,
|
||||
}) => {
|
||||
const handSubmit = () => {
|
||||
onConfirm(packageOptions);
|
||||
const [packageOptions, setPackageOptions] = useState<PackageOption[]>([]);
|
||||
const [selectedPackageId, setSelectedPackageId] = useState<string>("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
// 获取分组选项
|
||||
useEffect(() => {
|
||||
if (visible) {
|
||||
setLoading(true);
|
||||
fetchPackageOptions()
|
||||
.then(res => {
|
||||
setPackageOptions(res.list || []);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("获取分组选项失败:", error);
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
}
|
||||
}, [visible]);
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (!selectedPackageId) {
|
||||
// 可以添加提示
|
||||
return;
|
||||
}
|
||||
onConfirm({
|
||||
packageOptions,
|
||||
selectedPackageId,
|
||||
});
|
||||
};
|
||||
return (
|
||||
<Popup
|
||||
@@ -33,11 +59,15 @@ const BatchAddModal: React.FC<BatchAddModalProps> = ({
|
||||
>
|
||||
<div style={{ marginBottom: 12, padding: 10 }}>
|
||||
<div style={{ marginBottom: 12 }}>选择目标分组</div>
|
||||
<Selector
|
||||
options={packageOptions.map(p => ({ label: p.name, value: p.id }))}
|
||||
value={[batchTarget]}
|
||||
onChange={v => setBatchTarget(v[0])}
|
||||
/>
|
||||
{loading ? (
|
||||
<div style={{ textAlign: "center", padding: 20 }}>加载中...</div>
|
||||
) : (
|
||||
<Selector
|
||||
options={packageOptions.map(p => ({ label: p.name, value: p.id }))}
|
||||
value={[selectedPackageId]}
|
||||
onChange={v => setSelectedPackageId(v[0])}
|
||||
/>
|
||||
)}
|
||||
<div
|
||||
style={{
|
||||
color: "#888",
|
||||
@@ -48,7 +78,12 @@ const BatchAddModal: React.FC<BatchAddModalProps> = ({
|
||||
>
|
||||
将选中的{selectedCount}个用户加入所选分组
|
||||
</div>
|
||||
<Button onClick={handSubmit} color="primary" block>
|
||||
<Button
|
||||
onClick={handleSubmit}
|
||||
color="primary"
|
||||
block
|
||||
disabled={!selectedPackageId || loading}
|
||||
>
|
||||
确定
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -1,24 +1,77 @@
|
||||
import React from "react";
|
||||
import React, { useState, useEffect, useMemo } from "react";
|
||||
import { Card, Button } from "antd-mobile";
|
||||
import { fetchTrafficPoolList } from "./api";
|
||||
import type { TrafficPoolUser } from "./data";
|
||||
|
||||
interface DataAnalysisPanelProps {
|
||||
stats: {
|
||||
showStats: boolean;
|
||||
setShowStats: (v: boolean) => void;
|
||||
onConfirm: (stats: {
|
||||
total: number;
|
||||
highValue: number;
|
||||
added: number;
|
||||
pending: number;
|
||||
failed: number;
|
||||
addSuccessRate: number;
|
||||
};
|
||||
showStats: boolean;
|
||||
setShowStats: (v: boolean) => void;
|
||||
}) => void;
|
||||
}
|
||||
|
||||
const DataAnalysisPanel: React.FC<DataAnalysisPanelProps> = ({
|
||||
stats,
|
||||
showStats,
|
||||
setShowStats,
|
||||
onConfirm,
|
||||
}) => {
|
||||
const [list, setList] = useState<TrafficPoolUser[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
// 计算统计数据
|
||||
const stats = useMemo(() => {
|
||||
const total = list.length;
|
||||
const highValue = list.filter(
|
||||
u => u.tags && u.tags.includes("高价值客户池"),
|
||||
).length;
|
||||
const added = list.filter(u => u.status === 1).length;
|
||||
const pending = list.filter(u => u.status === 0).length;
|
||||
const failed = list.filter(u => u.status === -1).length;
|
||||
const addSuccessRate = total ? Math.round((added / total) * 100) : 0;
|
||||
return { total, highValue, added, pending, failed, addSuccessRate };
|
||||
}, [list]);
|
||||
|
||||
// 获取数据
|
||||
useEffect(() => {
|
||||
if (showStats) {
|
||||
setLoading(true);
|
||||
fetchTrafficPoolList({ page: 1, pageSize: 1000 }) // 获取所有数据进行统计
|
||||
.then(res => {
|
||||
setList(res.list || []);
|
||||
// 通过 onConfirm 抛出统计数据
|
||||
const total = res.list?.length || 0;
|
||||
const highValue =
|
||||
res.list?.filter(u => u.tags && u.tags.includes("高价值客户池"))
|
||||
.length || 0;
|
||||
const added = res.list?.filter(u => u.status === 1).length || 0;
|
||||
const pending = res.list?.filter(u => u.status === 0).length || 0;
|
||||
const failed = res.list?.filter(u => u.status === -1).length || 0;
|
||||
const addSuccessRate = total ? Math.round((added / total) * 100) : 0;
|
||||
|
||||
onConfirm({
|
||||
total,
|
||||
highValue,
|
||||
added,
|
||||
pending,
|
||||
failed,
|
||||
addSuccessRate,
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("获取统计数据失败:", error);
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
}
|
||||
}, [showStats, onConfirm]);
|
||||
|
||||
if (!showStats) return null;
|
||||
return (
|
||||
<div
|
||||
@@ -30,46 +83,54 @@ const DataAnalysisPanel: React.FC<DataAnalysisPanelProps> = ({
|
||||
boxShadow: "0 2px 8px rgba(0,0,0,0.04)",
|
||||
}}
|
||||
>
|
||||
<div style={{ display: "flex", gap: 16, marginBottom: 12 }}>
|
||||
<Card style={{ flex: 1 }}>
|
||||
<div style={{ fontSize: 18, fontWeight: 600, color: "#1677ff" }}>
|
||||
{stats.total}
|
||||
{loading ? (
|
||||
<div style={{ textAlign: "center", padding: 20 }}>
|
||||
加载统计数据中...
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<div style={{ display: "flex", gap: 16, marginBottom: 12 }}>
|
||||
<Card style={{ flex: 1 }}>
|
||||
<div style={{ fontSize: 18, fontWeight: 600, color: "#1677ff" }}>
|
||||
{stats.total}
|
||||
</div>
|
||||
<div style={{ fontSize: 13, color: "#888" }}>总用户数</div>
|
||||
</Card>
|
||||
<Card style={{ flex: 1 }}>
|
||||
<div style={{ fontSize: 18, fontWeight: 600, color: "#eb2f96" }}>
|
||||
{stats.highValue}
|
||||
</div>
|
||||
<div style={{ fontSize: 13, color: "#888" }}>高价值用户</div>
|
||||
</Card>
|
||||
</div>
|
||||
<div style={{ fontSize: 13, color: "#888" }}>总用户数</div>
|
||||
</Card>
|
||||
<Card style={{ flex: 1 }}>
|
||||
<div style={{ fontSize: 18, fontWeight: 600, color: "#eb2f96" }}>
|
||||
{stats.highValue}
|
||||
<div style={{ display: "flex", gap: 16 }}>
|
||||
<Card style={{ flex: 1 }}>
|
||||
<div style={{ fontSize: 18, fontWeight: 600, color: "#52c41a" }}>
|
||||
{stats.addSuccessRate}%
|
||||
</div>
|
||||
<div style={{ fontSize: 13, color: "#888" }}>添加成功率</div>
|
||||
</Card>
|
||||
<Card style={{ flex: 1 }}>
|
||||
<div style={{ fontSize: 18, fontWeight: 600, color: "#faad14" }}>
|
||||
{stats.added}
|
||||
</div>
|
||||
<div style={{ fontSize: 13, color: "#888" }}>已添加</div>
|
||||
</Card>
|
||||
<Card style={{ flex: 1 }}>
|
||||
<div style={{ fontSize: 18, fontWeight: 600, color: "#bfbfbf" }}>
|
||||
{stats.pending}
|
||||
</div>
|
||||
<div style={{ fontSize: 13, color: "#888" }}>待添加</div>
|
||||
</Card>
|
||||
<Card style={{ flex: 1 }}>
|
||||
<div style={{ fontSize: 18, fontWeight: 600, color: "#ff4d4f" }}>
|
||||
{stats.failed}
|
||||
</div>
|
||||
<div style={{ fontSize: 13, color: "#888" }}>添加失败</div>
|
||||
</Card>
|
||||
</div>
|
||||
<div style={{ fontSize: 13, color: "#888" }}>高价值用户</div>
|
||||
</Card>
|
||||
</div>
|
||||
<div style={{ display: "flex", gap: 16 }}>
|
||||
<Card style={{ flex: 1 }}>
|
||||
<div style={{ fontSize: 18, fontWeight: 600, color: "#52c41a" }}>
|
||||
{stats.addSuccessRate}%
|
||||
</div>
|
||||
<div style={{ fontSize: 13, color: "#888" }}>添加成功率</div>
|
||||
</Card>
|
||||
<Card style={{ flex: 1 }}>
|
||||
<div style={{ fontSize: 18, fontWeight: 600, color: "#faad14" }}>
|
||||
{stats.added}
|
||||
</div>
|
||||
<div style={{ fontSize: 13, color: "#888" }}>已添加</div>
|
||||
</Card>
|
||||
<Card style={{ flex: 1 }}>
|
||||
<div style={{ fontSize: 18, fontWeight: 600, color: "#bfbfbf" }}>
|
||||
{stats.pending}
|
||||
</div>
|
||||
<div style={{ fontSize: 13, color: "#888" }}>待添加</div>
|
||||
</Card>
|
||||
<Card style={{ flex: 1 }}>
|
||||
<div style={{ fontSize: 18, fontWeight: 600, color: "#ff4d4f" }}>
|
||||
{stats.failed}
|
||||
</div>
|
||||
<div style={{ fontSize: 13, color: "#888" }}>添加失败</div>
|
||||
</Card>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<Button
|
||||
size="small"
|
||||
style={{ marginTop: 12 }}
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { useState, useEffect } from "react";
|
||||
import { Popup } from "antd-mobile";
|
||||
import { Select, Button } from "antd";
|
||||
import DeviceSelection from "@/components/DeviceSelection";
|
||||
import type { UserStatus, ScenarioOption } from "./data";
|
||||
import type { ScenarioOption } from "./data";
|
||||
import { fetchScenarioOptions, fetchPackageOptions } from "./api";
|
||||
import { DeviceSelectionItem } from "@/components/DeviceSelection/data";
|
||||
|
||||
@@ -10,11 +10,11 @@ interface FilterModalProps {
|
||||
visible: boolean;
|
||||
onClose: () => void;
|
||||
onConfirm: (filters: {
|
||||
deviceIds: string[];
|
||||
packageId: string;
|
||||
scenarioId: string;
|
||||
deviceld: string[]; // 更新为 deviceld
|
||||
packageld: string; // 更新为 packageld
|
||||
taskId: string; // 更新为 taskId
|
||||
userValue: number;
|
||||
userStatus: number;
|
||||
addStatus: number; // 更新为 addStatus
|
||||
}) => void;
|
||||
scenarioOptions: ScenarioOption[];
|
||||
}
|
||||
@@ -72,11 +72,11 @@ const FilterModal: React.FC<FilterModalProps> = ({
|
||||
|
||||
const handleApply = () => {
|
||||
const params = {
|
||||
deviceIds: selectedDevices.map(d => d.id.toString()),
|
||||
packageId,
|
||||
scenarioId,
|
||||
deviceld: selectedDevices.map(d => d.id.toString()), // 更新为 deviceld
|
||||
packageld: packageId, // 更新为 packageld
|
||||
taskId: scenarioId, // 更新为 taskId
|
||||
userValue,
|
||||
userStatus,
|
||||
addStatus: userStatus, // 更新为 addStatus
|
||||
};
|
||||
console.log(params);
|
||||
|
||||
|
||||
@@ -1,183 +0,0 @@
|
||||
import { useState, useEffect, useMemo } from "react";
|
||||
import {
|
||||
fetchTrafficPoolList,
|
||||
fetchPackageOptions,
|
||||
fetchScenarioOptions,
|
||||
} from "./api";
|
||||
import type { TrafficPoolUser, PackageOption, ScenarioOption } from "./data";
|
||||
|
||||
export function useTrafficPoolListLogic() {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [list, setList] = useState<TrafficPoolUser[]>([]);
|
||||
const [page, setPage] = useState(1);
|
||||
const [pageSize] = useState(10);
|
||||
const [total, setTotal] = useState(0);
|
||||
const [search, setSearch] = useState("");
|
||||
|
||||
// 筛选相关
|
||||
const [showFilter, setShowFilter] = useState(false);
|
||||
const [packageOptions, setPackageOptions] = useState<PackageOption[]>([]);
|
||||
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 [selectedIds, setSelectedIds] = useState<number[]>([]);
|
||||
const [batchModal, setBatchModal] = useState(false);
|
||||
const [batchTarget, setBatchTarget] = useState<string>("");
|
||||
|
||||
// 数据分析
|
||||
const [showStats, setShowStats] = useState(false);
|
||||
const stats = useMemo(() => {
|
||||
const total = list.length;
|
||||
const highValue = list.filter(
|
||||
u => u.tags && u.tags.includes("高价值客户池"),
|
||||
).length;
|
||||
const added = list.filter(u => u.status === 1).length;
|
||||
const pending = list.filter(u => u.status === 0).length;
|
||||
const failed = list.filter(u => u.status === -1).length;
|
||||
const addSuccessRate = total ? Math.round((added / total) * 100) : 0;
|
||||
return { total, highValue, added, pending, failed, addSuccessRate };
|
||||
}, [list]);
|
||||
|
||||
// 获取列表
|
||||
const getList = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const params: any = {
|
||||
page,
|
||||
pageSize,
|
||||
keyword: search,
|
||||
packageId,
|
||||
taskId: scenarioId,
|
||||
userValue,
|
||||
addStatus: userStatus,
|
||||
};
|
||||
|
||||
// 添加筛选参数
|
||||
if (selectedDevices.length > 0) {
|
||||
params.deviceId = selectedDevices.map(d => d.id).join(",");
|
||||
}
|
||||
|
||||
const res = await fetchTrafficPoolList(params);
|
||||
setList(res.list || []);
|
||||
setTotal(res.total || 0);
|
||||
} catch (error) {
|
||||
// 忽略请求过于频繁的错误,避免页面崩溃
|
||||
if (error !== "请求过于频繁,请稍后再试") {
|
||||
console.error("获取列表失败:", error);
|
||||
}
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 获取筛选项
|
||||
useEffect(() => {
|
||||
fetchPackageOptions().then(res => {
|
||||
setPackageOptions(res.list || []);
|
||||
});
|
||||
fetchScenarioOptions().then(res => {
|
||||
setScenarioOptions(res.list || []);
|
||||
});
|
||||
}, []);
|
||||
|
||||
// 筛选条件变化时刷新列表
|
||||
useEffect(() => {
|
||||
getList();
|
||||
// eslint-disable-next-line
|
||||
}, [
|
||||
page,
|
||||
search,
|
||||
selectedDevices,
|
||||
packageId,
|
||||
scenarioId,
|
||||
userValue,
|
||||
userStatus,
|
||||
]);
|
||||
|
||||
// 全选/反选
|
||||
const handleSelectAll = (checked: boolean) => {
|
||||
if (checked) {
|
||||
setSelectedIds(list.map(item => item.id));
|
||||
} else {
|
||||
setSelectedIds([]);
|
||||
}
|
||||
};
|
||||
// 单选
|
||||
const handleSelect = (id: number, checked: boolean) => {
|
||||
setSelectedIds(prev =>
|
||||
checked ? [...prev, id] : prev.filter(i => i !== id),
|
||||
);
|
||||
};
|
||||
|
||||
// 批量加入分组/流量池
|
||||
const handleBatchAdd = options => {
|
||||
console.log("批量加入分组", options);
|
||||
|
||||
// if (!batchTarget) {
|
||||
// Toast.show({ content: "请选择目标分组", position: "top" });
|
||||
// return;
|
||||
// }
|
||||
// // TODO: 调用后端批量接口,这里仅模拟
|
||||
// Toast.show({
|
||||
// content: `已将${selectedIds.length}个用户加入${packageOptions.find(p => p.id === batchTarget)?.name || ""}`,
|
||||
// position: "top",
|
||||
// });
|
||||
// setBatchModal(false);
|
||||
// setSelectedIds([]);
|
||||
// setBatchTarget("");
|
||||
// 可刷新列表
|
||||
};
|
||||
|
||||
// 筛选重置
|
||||
const resetFilter = () => {
|
||||
setSelectedDevices([]);
|
||||
setPackageId(0);
|
||||
setScenarioId(0);
|
||||
setUserValue(0);
|
||||
setUserStatus(0);
|
||||
};
|
||||
|
||||
return {
|
||||
loading,
|
||||
list,
|
||||
page,
|
||||
setPage,
|
||||
pageSize,
|
||||
total,
|
||||
search,
|
||||
setSearch,
|
||||
showFilter,
|
||||
setShowFilter,
|
||||
packageOptions,
|
||||
scenarioOptions,
|
||||
selectedDevices,
|
||||
setSelectedDevices,
|
||||
packageId,
|
||||
setPackageId,
|
||||
scenarioId,
|
||||
setScenarioId,
|
||||
userValue,
|
||||
setUserValue,
|
||||
userStatus,
|
||||
setUserStatus,
|
||||
selectedIds,
|
||||
setSelectedIds,
|
||||
handleSelectAll,
|
||||
handleSelect,
|
||||
batchModal,
|
||||
setBatchModal,
|
||||
batchTarget,
|
||||
setBatchTarget,
|
||||
handleBatchAdd,
|
||||
showStats,
|
||||
setShowStats,
|
||||
stats,
|
||||
getList,
|
||||
resetFilter,
|
||||
};
|
||||
}
|
||||
@@ -10,7 +10,8 @@ import styles from "./index.module.scss";
|
||||
import { Empty, Avatar } from "antd-mobile";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import NavCommon from "@/components/NavCommon";
|
||||
import { useTrafficPoolListLogic } from "./dataAnyx";
|
||||
import { fetchTrafficPoolList, fetchScenarioOptions } from "./api";
|
||||
import type { TrafficPoolUser, ScenarioOption } from "./data";
|
||||
import DataAnalysisPanel from "./DataAnalysisPanel";
|
||||
import FilterModal from "./FilterModal";
|
||||
import BatchAddModal from "./BatchAddModal";
|
||||
@@ -20,36 +21,107 @@ const defaultAvatar =
|
||||
|
||||
const TrafficPoolList: React.FC = () => {
|
||||
const navigate = useNavigate();
|
||||
const {
|
||||
loading,
|
||||
list,
|
||||
|
||||
// 基础状态
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [list, setList] = useState<TrafficPoolUser[]>([]);
|
||||
const [page, setPage] = useState(1);
|
||||
const [pageSize] = useState(10);
|
||||
const [total, setTotal] = useState(0);
|
||||
const [search, setSearch] = useState("");
|
||||
|
||||
// 筛选相关
|
||||
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 [selectedIds, setSelectedIds] = useState<number[]>([]);
|
||||
const [batchModal, setBatchModal] = useState(false);
|
||||
|
||||
// 数据分析
|
||||
const [showStats, setShowStats] = useState(false);
|
||||
|
||||
// 获取列表
|
||||
const getList = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const params: any = {
|
||||
page,
|
||||
pageSize,
|
||||
keyword: search,
|
||||
packageld: packageId, // 更新为 packageld
|
||||
taskId: scenarioId,
|
||||
userValue,
|
||||
addStatus: userStatus,
|
||||
};
|
||||
|
||||
// 添加筛选参数
|
||||
if (selectedDevices.length > 0) {
|
||||
params.deviceld = selectedDevices.map(d => d.id).join(","); // 更新为 deviceld
|
||||
}
|
||||
|
||||
const res = await fetchTrafficPoolList(params);
|
||||
setList(res.list || []);
|
||||
setTotal(res.total || 0);
|
||||
} catch (error) {
|
||||
// 忽略请求过于频繁的错误,避免页面崩溃
|
||||
if (error !== "请求过于频繁,请稍后再试") {
|
||||
console.error("获取列表失败:", error);
|
||||
}
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 获取筛选项
|
||||
useEffect(() => {
|
||||
fetchScenarioOptions().then(res => {
|
||||
setScenarioOptions(res.list || []);
|
||||
});
|
||||
}, []);
|
||||
|
||||
// 筛选条件变化时刷新列表
|
||||
useEffect(() => {
|
||||
getList();
|
||||
// eslint-disable-next-line
|
||||
}, [
|
||||
page,
|
||||
setPage,
|
||||
total,
|
||||
search,
|
||||
setSearch,
|
||||
showFilter,
|
||||
setShowFilter,
|
||||
packageOptions,
|
||||
scenarioOptions,
|
||||
setSelectedDevices,
|
||||
setPackageId,
|
||||
setScenarioId,
|
||||
setUserValue,
|
||||
setUserStatus,
|
||||
selectedIds,
|
||||
handleSelectAll,
|
||||
handleSelect,
|
||||
batchModal,
|
||||
setBatchModal,
|
||||
batchTarget,
|
||||
setBatchTarget,
|
||||
handleBatchAdd,
|
||||
showStats,
|
||||
setShowStats,
|
||||
stats,
|
||||
getList,
|
||||
} = useTrafficPoolListLogic();
|
||||
selectedDevices,
|
||||
packageId,
|
||||
scenarioId,
|
||||
userValue,
|
||||
userStatus,
|
||||
]);
|
||||
|
||||
// 全选/反选
|
||||
const handleSelectAll = (checked: boolean) => {
|
||||
if (checked) {
|
||||
setSelectedIds(list.map(item => item.id));
|
||||
} else {
|
||||
setSelectedIds([]);
|
||||
}
|
||||
};
|
||||
|
||||
// 单选
|
||||
const handleSelect = (id: number, checked: boolean) => {
|
||||
setSelectedIds(prev =>
|
||||
checked ? [...prev, id] : prev.filter(i => i !== id),
|
||||
);
|
||||
};
|
||||
|
||||
// 批量加入分组/流量池
|
||||
const handleBatchAdd = options => {
|
||||
console.log("批量加入分组", options);
|
||||
// TODO: 实现批量加入逻辑
|
||||
setBatchModal(false);
|
||||
setSelectedIds([]);
|
||||
};
|
||||
|
||||
// 搜索防抖处理
|
||||
const [searchInput, setSearchInput] = useState(search);
|
||||
@@ -104,9 +176,12 @@ const TrafficPoolList: React.FC = () => {
|
||||
</div>
|
||||
{/* 数据分析面板 */}
|
||||
<DataAnalysisPanel
|
||||
stats={stats}
|
||||
showStats={showStats}
|
||||
setShowStats={setShowStats}
|
||||
onConfirm={statsData => {
|
||||
// 可以在这里处理统计数据,比如更新本地状态或发送到父组件
|
||||
console.log("收到统计数据:", statsData);
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 批量操作栏 */}
|
||||
@@ -167,11 +242,12 @@ const TrafficPoolList: React.FC = () => {
|
||||
<BatchAddModal
|
||||
visible={batchModal}
|
||||
onClose={() => setBatchModal(false)}
|
||||
packageOptions={packageOptions}
|
||||
batchTarget={batchTarget}
|
||||
setBatchTarget={setBatchTarget}
|
||||
selectedCount={selectedIds.length}
|
||||
onConfirm={handleBatchAdd}
|
||||
onConfirm={data => {
|
||||
console.log("收到批量操作数据:", data);
|
||||
// 处理批量加入逻辑
|
||||
handleBatchAdd(data);
|
||||
}}
|
||||
/>
|
||||
{/* 筛选弹窗 */}
|
||||
<FilterModal
|
||||
@@ -180,7 +256,7 @@ const TrafficPoolList: React.FC = () => {
|
||||
onConfirm={filters => {
|
||||
// 更新筛选条件
|
||||
setSelectedDevices(
|
||||
filters.deviceIds.map(id => ({
|
||||
filters.deviceld.map(id => ({
|
||||
id: parseInt(id),
|
||||
memo: "",
|
||||
imei: "",
|
||||
@@ -188,10 +264,10 @@ const TrafficPoolList: React.FC = () => {
|
||||
status: "offline" as const,
|
||||
})),
|
||||
);
|
||||
setPackageId(filters.packageId ? parseInt(filters.packageId) : 0);
|
||||
setScenarioId(filters.scenarioId ? parseInt(filters.scenarioId) : 0);
|
||||
setPackageId(filters.packageld ? parseInt(filters.packageld) : 0);
|
||||
setScenarioId(filters.taskId ? parseInt(filters.taskId) : 0);
|
||||
setUserValue(filters.userValue);
|
||||
setUserStatus(filters.userStatus);
|
||||
setUserStatus(filters.addStatus);
|
||||
// 重新获取列表
|
||||
getList();
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user