diff --git a/nkebao/src/components/DeviceSelection/index.module.scss b/nkebao/src/components/DeviceSelection/index.module.scss
index 89a396c9..d457fa24 100644
--- a/nkebao/src/components/DeviceSelection/index.module.scss
+++ b/nkebao/src/components/DeviceSelection/index.module.scss
@@ -154,3 +154,35 @@
display: flex;
gap: 12px;
}
+.refreshBtn {
+ width: 36px;
+ height: 36px;
+}
+.paginationRow {
+ border-top: 1px solid #f0f0f0;
+ padding: 16px;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ background: #fff;
+}
+.totalCount {
+ font-size: 14px;
+ color: #888;
+}
+.paginationControls {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+.pageBtn {
+ padding: 0 8px;
+ height: 32px;
+ min-width: 32px;
+ border-radius: 16px;
+}
+.pageInfo {
+ font-size: 14px;
+ color: #222;
+ margin: 0 8px;
+}
diff --git a/nkebao/src/components/DeviceSelection/index.tsx b/nkebao/src/components/DeviceSelection/index.tsx
index b4a63ac7..b59e8104 100644
--- a/nkebao/src/components/DeviceSelection/index.tsx
+++ b/nkebao/src/components/DeviceSelection/index.tsx
@@ -33,17 +33,19 @@ export default function DeviceSelection({
const [searchQuery, setSearchQuery] = useState("");
const [statusFilter, setStatusFilter] = useState("all");
const [loading, setLoading] = useState(false);
+ const [currentPage, setCurrentPage] = useState(1); // 新增
+ const [total, setTotal] = useState(0); // 新增
+ const pageSize = 20; // 每页条数
- // 获取设备列表,支持keyword
- const fetchDevices = async (keyword: string = "") => {
+ // 获取设备列表,支持keyword和分页
+ const fetchDevices = async (keyword: string = "", page: number = 1) => {
setLoading(true);
try {
const res = await getDeviceList({
- page: 1,
- limit: 100,
+ page,
+ limit: pageSize,
keyword: keyword.trim() || undefined,
});
-
if (res && Array.isArray(res.list)) {
setDevices(
res.list.map((d: any) => ({
@@ -54,30 +56,41 @@ export default function DeviceSelection({
status: d.alive === 1 ? "online" : "offline",
}))
);
+ setTotal(res.total || 0);
}
} catch (error) {
console.error("获取设备列表失败:", error);
+ Toast.show({ content: "获取设备列表失败", position: "top" });
} finally {
setLoading(false);
}
};
- // 打开弹窗时获取设备列表
+ // 打开弹窗时获取第一页
const openPopup = () => {
setSearchQuery("");
+ setCurrentPage(1);
setPopupVisible(true);
- fetchDevices("");
+ fetchDevices("", 1);
};
// 搜索防抖
useEffect(() => {
if (!popupVisible) return;
const timer = setTimeout(() => {
- fetchDevices(searchQuery);
+ setCurrentPage(1);
+ fetchDevices(searchQuery, 1);
}, 500);
return () => clearTimeout(timer);
}, [searchQuery, popupVisible]);
+ // 翻页时重新请求
+ useEffect(() => {
+ if (!popupVisible) return;
+ fetchDevices(searchQuery, currentPage);
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [currentPage]);
+
// 过滤设备(只保留状态过滤)
const filteredDevices = devices.filter((device) => {
const matchesStatus =
@@ -87,6 +100,8 @@ export default function DeviceSelection({
return matchesStatus;
});
+ const totalPages = Math.max(1, Math.ceil(total / pageSize));
+
// 处理设备选择
const handleDeviceToggle = (deviceId: string) => {
if (selectedDevices.includes(deviceId)) {
@@ -129,13 +144,12 @@ export default function DeviceSelection({
+
setSearchQuery(e.target.value)}
- prefix={}
- allowClear
- size="large"
+ onChange={(val) => setSearchQuery(val)}
+ className={style.popupSearchInput}
/>
-
{loading ? (
@@ -198,6 +199,35 @@ export default function DeviceSelection({
)}
+ {/* 分页栏 */}
+
+
总计 {total} 个设备
+
+
+
+ {currentPage} / {totalPages}
+
+
+
+
已选择 {selectedDevices.length} 个设备
diff --git a/nkebao/src/components/DeviceSelectionDialog/index.module.scss b/nkebao/src/components/DeviceSelectionDialog/index.module.scss
index bfde5d72..e0961f10 100644
--- a/nkebao/src/components/DeviceSelectionDialog/index.module.scss
+++ b/nkebao/src/components/DeviceSelectionDialog/index.module.scss
@@ -163,3 +163,35 @@
display: flex;
gap: 12px;
}
+.refreshBtn {
+ width: 36px;
+ height: 36px;
+}
+.paginationRow {
+ border-top: 1px solid #f0f0f0;
+ padding: 16px;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ background: #fff;
+}
+.totalCount {
+ font-size: 14px;
+ color: #888;
+}
+.paginationControls {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+.pageBtn {
+ padding: 0 8px;
+ height: 32px;
+ min-width: 32px;
+ border-radius: 16px;
+}
+.pageInfo {
+ font-size: 14px;
+ color: #222;
+ margin: 0 8px;
+}
diff --git a/nkebao/src/components/DeviceSelectionDialog/index.tsx b/nkebao/src/components/DeviceSelectionDialog/index.tsx
index 1c9ba4ae..588d774a 100644
--- a/nkebao/src/components/DeviceSelectionDialog/index.tsx
+++ b/nkebao/src/components/DeviceSelectionDialog/index.tsx
@@ -32,47 +32,53 @@ export function DeviceSelectionDialog({
const [statusFilter, setStatusFilter] = useState("all");
const [loading, setLoading] = useState(false);
const [devices, setDevices] = useState
([]);
+ const [currentPage, setCurrentPage] = useState(1); // 新增
+ const [total, setTotal] = useState(0); // 新增
+ const pageSize = 20; // 每页条数
- // 获取设备列表,支持keyword
- const fetchDevices = useCallback(async (keyword: string = "") => {
- setLoading(true);
- try {
- const response = await getDeviceList({
- page: 1,
- limit: 100,
- keyword: keyword.trim() || undefined,
- });
-
- if (response && Array.isArray(response.list)) {
- // 转换服务端数据格式为组件需要的格式
- const convertedDevices: Device[] = response.list.map(
- (serverDevice: any) => ({
- id: serverDevice.id.toString(),
- name: serverDevice.memo || `设备 ${serverDevice.id}`,
- imei: serverDevice.imei,
- wxid: serverDevice.wechatId || "",
- status: serverDevice.alive === 1 ? "online" : "offline",
- usedInPlans: 0, // 这个字段需要从其他API获取
- nickname: serverDevice.nickname || "",
- })
- );
- setDevices(convertedDevices);
+ // 获取设备列表,支持keyword和分页
+ const fetchDevices = useCallback(
+ async (keyword: string = "", page: number = 1) => {
+ setLoading(true);
+ try {
+ const response = await getDeviceList({
+ page,
+ limit: pageSize,
+ keyword: keyword.trim() || undefined,
+ });
+ if (response && Array.isArray(response.list)) {
+ const convertedDevices: Device[] = response.list.map(
+ (serverDevice: any) => ({
+ id: serverDevice.id.toString(),
+ name: serverDevice.memo || `设备 ${serverDevice.id}`,
+ imei: serverDevice.imei,
+ wxid: serverDevice.wechatId || "",
+ status: serverDevice.alive === 1 ? "online" : "offline",
+ usedInPlans: 0,
+ nickname: serverDevice.nickname || "",
+ })
+ );
+ setDevices(convertedDevices);
+ setTotal(response.total || 0);
+ }
+ } catch (error) {
+ console.error("获取设备列表失败:", error);
+ Toast.show({
+ content: "获取设备列表失败,请检查网络连接",
+ position: "top",
+ });
+ } finally {
+ setLoading(false);
}
- } catch (error) {
- console.error("获取设备列表失败:", error);
- Toast.show({
- content: "获取设备列表失败,请检查网络连接",
- position: "top",
- });
- } finally {
- setLoading(false);
- }
- }, []);
+ },
+ []
+ );
- // 打开弹窗时获取设备列表
+ // 打开弹窗时获取第一页
useEffect(() => {
if (open) {
- fetchDevices("");
+ setCurrentPage(1);
+ fetchDevices("", 1);
}
}, [open, fetchDevices]);
@@ -80,11 +86,19 @@ export function DeviceSelectionDialog({
useEffect(() => {
if (!open) return;
const timer = setTimeout(() => {
- fetchDevices(searchQuery);
+ setCurrentPage(1);
+ fetchDevices(searchQuery, 1);
}, 500);
return () => clearTimeout(timer);
}, [searchQuery, open, fetchDevices]);
+ // 翻页时重新请求
+ useEffect(() => {
+ if (!open) return;
+ fetchDevices(searchQuery, currentPage);
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [currentPage]);
+
// 过滤设备(只保留状态过滤)
const filteredDevices = devices.filter((device) => {
const matchesStatus =
@@ -102,6 +116,8 @@ export function DeviceSelectionDialog({
}
};
+ const totalPages = Math.max(1, Math.ceil(total / pageSize));
+
return (
IMEI: {device.imei}
-
微信号: {device.wxid || "-"}
+
微信号: {device.wxid || "-"}
昵称: {device.nickname || "-"}
{device.usedInPlans > 0 && (
@@ -194,6 +209,35 @@ export function DeviceSelectionDialog({
)}
+ {/* 分页栏 */}
+
+
总计 {total} 个设备
+
+
+
+ {currentPage} / {totalPages}
+
+
+
+
已选择 {selectedDevices.length} 个设备