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 (
+ setSearchQuery(e.target.value)} - prefix={} - allowClear - size="large" + onChange={(val) => setSearchQuery(val)} + className={style.popupSearchInput} />
IMEI: {device.imei}
-
微信号: {device.wxid || "-"}
+
微信号: {device.wxid || "-"}
昵称: {device.nickname || "-"}
{device.usedInPlans > 0 && ( @@ -194,6 +209,35 @@ export function DeviceSelectionDialog({
)}
+ {/* 分页栏 */} +
+
总计 {total} 个设备
+
+ + + {currentPage} / {totalPages} + + +
+
已选择 {selectedDevices.length} 个设备