diff --git a/nkebao/src/components/DeviceSelection.tsx b/nkebao/src/components/DeviceSelection.tsx index 79fcdca8..4c670af0 100644 --- a/nkebao/src/components/DeviceSelection.tsx +++ b/nkebao/src/components/DeviceSelection.tsx @@ -41,18 +41,11 @@ export default function DeviceSelection({ const [statusFilter, setStatusFilter] = useState("all"); const [loading, setLoading] = useState(false); - // 当弹窗打开时获取设备列表 - useEffect(() => { - if (dialogOpen) { - fetchDevices(); - } - }, [dialogOpen]); - - // 获取设备列表 - const fetchDevices = async () => { + // 获取设备列表,支持keyword + const fetchDevices = async (keyword: string = "") => { setLoading(true); try { - const res = await fetchDeviceList(1, 100); + const res = await fetchDeviceList(1, 100, keyword.trim() || undefined); if (res && res.data && Array.isArray(res.data.list)) { setDevices( res.data.list.map((d) => ({ @@ -71,19 +64,29 @@ export default function DeviceSelection({ } }; - // 过滤设备 - const filteredDevices = devices.filter((device) => { - const matchesSearch = - device.name.toLowerCase().includes(searchQuery.toLowerCase()) || - device.imei.toLowerCase().includes(searchQuery.toLowerCase()) || - device.wechatId.toLowerCase().includes(searchQuery.toLowerCase()); + // 打开弹窗时获取设备列表 + const openDialog = () => { + setSearchQuery(""); + setDialogOpen(true); + fetchDevices(""); + }; + // 搜索防抖 + useEffect(() => { + if (!dialogOpen) return; + const timer = setTimeout(() => { + fetchDevices(searchQuery); + }, 500); + return () => clearTimeout(timer); + }, [searchQuery, dialogOpen]); + + // 过滤设备(只保留状态过滤) + const filteredDevices = devices.filter((device) => { const matchesStatus = statusFilter === "all" || (statusFilter === "online" && device.status === "online") || (statusFilter === "offline" && device.status === "offline"); - - return matchesSearch && matchesStatus; + return matchesStatus; }); // 处理设备选择 @@ -110,7 +113,7 @@ export default function DeviceSelection({ placeholder={placeholder} className="pl-10 h-14 rounded-xl border-gray-200 text-base" readOnly - onClick={() => setDialogOpen(true)} + onClick={openDialog} value={getDisplayText()} /> diff --git a/nkebao/src/components/DeviceSelectionDialog.tsx b/nkebao/src/components/DeviceSelectionDialog.tsx index 2ecc2950..67f4d1d0 100644 --- a/nkebao/src/components/DeviceSelectionDialog.tsx +++ b/nkebao/src/components/DeviceSelectionDialog.tsx @@ -42,62 +42,74 @@ export function DeviceSelectionDialog({ const [loading, setLoading] = useState(false); const [devices, setDevices] = useState([]); - // 获取设备列表 - const fetchDevices = useCallback(async () => { - setLoading(true); - try { - const response = await fetchDeviceList(1, 100, searchQuery); - if (response.code === 200 && response.data) { - // 转换服务端数据格式为组件需要的格式 - const convertedDevices: Device[] = response.data.list.map( - (serverDevice: ServerDevice) => ({ - 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 || "", - }) + // 获取设备列表,支持keyword + const fetchDevices = useCallback( + async (keyword: string = "") => { + setLoading(true); + try { + const response = await fetchDeviceList( + 1, + 100, + keyword.trim() || undefined ); - setDevices(convertedDevices); - } else { + if (response.code === 200 && response.data) { + // 转换服务端数据格式为组件需要的格式 + const convertedDevices: Device[] = response.data.list.map( + (serverDevice: ServerDevice) => ({ + 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); + } else { + toast({ + title: "获取设备列表失败", + description: response.msg, + variant: "destructive", + }); + } + } catch (error) { + console.error("获取设备列表失败:", error); toast({ title: "获取设备列表失败", - description: response.msg, + description: "请检查网络连接", variant: "destructive", }); + } finally { + setLoading(false); } - } catch (error) { - console.error("获取设备列表失败:", error); - toast({ - title: "获取设备列表失败", - description: "请检查网络连接", - variant: "destructive", - }); - } finally { - setLoading(false); - } - }, [searchQuery, toast]); + }, + [toast] + ); + // 打开弹窗时获取设备列表 useEffect(() => { if (open) { - fetchDevices(); + fetchDevices(""); } - }, [open, searchQuery, fetchDevices]); + }, [open, fetchDevices]); + // 搜索防抖 + useEffect(() => { + if (!open) return; + const timer = setTimeout(() => { + fetchDevices(searchQuery); + }, 500); + return () => clearTimeout(timer); + }, [searchQuery, open, fetchDevices]); + + // 过滤设备(只保留状态过滤) const filteredDevices = devices.filter((device) => { - const matchesSearch = - device.name.toLowerCase().includes(searchQuery.toLowerCase()) || - device.imei.toLowerCase().includes(searchQuery.toLowerCase()) || - device.wxid.toLowerCase().includes(searchQuery.toLowerCase()); - const matchesStatus = statusFilter === "all" || (statusFilter === "online" && device.status === "online") || (statusFilter === "offline" && device.status === "offline"); - - return matchesSearch && matchesStatus; + return matchesStatus; }); const handleDeviceSelect = (deviceId: string) => { @@ -137,7 +149,7 @@ export function DeviceSelectionDialog({ + {searchQuery && ( + + )} - +
{loading ? (
加载中...
- ) : filteredFriends.length > 0 ? ( + ) : friends.length > 0 ? (
- {filteredFriends.map((friend) => ( + {friends.map((friend) => (
)} - +
diff --git a/nkebao/src/components/GroupSelection.tsx b/nkebao/src/components/GroupSelection.tsx index 534cf146..0e1841b3 100644 --- a/nkebao/src/components/GroupSelection.tsx +++ b/nkebao/src/components/GroupSelection.tsx @@ -36,12 +36,17 @@ interface GroupsResponse { }; } +// 修改:支持keyword参数 const fetchGroupsList = async (params: { page: number; limit: number; + keyword?: string; }): Promise => { + const keywordParam = params.keyword + ? `&keyword=${encodeURIComponent(params.keyword)}` + : ""; return get( - `/v1/chatroom?page=${params.page}&limit=${params.limit}` + `/v1/chatroom?page=${params.page}&limit=${params.limit}${keywordParam}` ); }; @@ -71,23 +76,38 @@ export default function GroupSelection({ // 打开弹窗并请求第一页群组 const openDialog = () => { setCurrentPage(1); + setSearchQuery(""); // 重置搜索关键词 setDialogOpen(true); - fetchGroups(1); + fetchGroups(1, ""); }; // 当页码变化时,拉取对应页数据(弹窗已打开时) useEffect(() => { if (dialogOpen && currentPage !== 1) { - fetchGroups(currentPage); + fetchGroups(currentPage, searchQuery); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [currentPage]); - // 获取群组列表API - const fetchGroups = async (page: number) => { + // 搜索防抖 + useEffect(() => { + if (!dialogOpen) return; + const timer = setTimeout(() => { + setCurrentPage(1); + fetchGroups(1, searchQuery); + }, 500); + return () => clearTimeout(timer); + }, [searchQuery, dialogOpen]); + + // 获取群组列表API - 支持keyword + const fetchGroups = async (page: number, keyword: string = "") => { setLoading(true); try { - const res = await fetchGroupsList({ page, limit: 20 }); + const res = await fetchGroupsList({ + page, + limit: 20, + keyword: keyword.trim() || undefined, + }); if (res && res.code === 200 && res.data) { setGroups( res.data.list.map((group) => ({ @@ -110,13 +130,6 @@ export default function GroupSelection({ } }; - // 过滤群组 - const filteredGroups = groups.filter( - (group) => - group.name.toLowerCase().includes(searchQuery.toLowerCase()) || - group.chatroomId.toLowerCase().includes(searchQuery.toLowerCase()) - ); - // 处理群组选择 const handleGroupToggle = (groupId: string) => { let newIds: string[]; @@ -142,6 +155,13 @@ export default function GroupSelection({ setDialogOpen(false); }; + // 清空搜索 + const handleClearSearch = () => { + setSearchQuery(""); + setCurrentPage(1); + fetchGroups(1, ""); + }; + return ( <> {/* 输入框 */} @@ -186,25 +206,27 @@ export default function GroupSelection({ className="pl-10 py-2 rounded-full border-gray-200" /> - + {searchQuery && ( + + )}
- +
{loading ? (
加载中...
- ) : filteredGroups.length > 0 ? ( + ) : groups.length > 0 ? (
- {filteredGroups.map((group) => ( + {groups.map((group) => (
总计 {totalGroups} 个群聊 + {searchQuery && ` (搜索: "${searchQuery}")`}
-
+
+ +
} > -
+
- + setForm(f => ({ ...f, name: e.target.value }))} + onChange={(e) => + setForm((f) => ({ ...f, name: e.target.value })) + } placeholder="请输入内容库名称" required />
- setForm(f => ({ ...f, sourceType: val as 'friends' | 'groups' }))}> + + setForm((f) => ({ + ...f, + sourceType: val as "friends" | "groups", + })) + } + > 选择微信好友 选择聊天群 f.id)} - onSelect={ids => setForm(f => ({ - ...f, - selectedFriends: ids.map(id => ({ id, nickname: id, avatar: '' })) - }))} + selectedFriends={form.selectedFriends.map((f) => f.id)} + onSelect={(ids) => + setForm((f) => ({ + ...f, + selectedFriends: ids.map((id) => ({ + id, + nickname: id, + avatar: "", + })), + })) + } onSelectDetail={setSelectedFriendObjs} enableDeviceFilter={false} placeholder="选择微信好友" /> {selectedFriendObjs.length > 0 && (
- {selectedFriendObjs.map(friend => ( -
+ {selectedFriendObjs.map((friend) => ( +
{friend.avatar ? ( - {friend.nickname} + {friend.nickname} ) : ( -
{friend.nickname?.charAt(0) || '友'}
+
+ {friend.nickname?.charAt(0) || "友"} +
)} {friend.nickname}