feat: 本次提交更新内容如下
选择栏做了修改
This commit is contained in:
@@ -3,12 +3,7 @@ import { Search, X } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog";
|
||||
import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog";
|
||||
import { get } from "@/api/request";
|
||||
|
||||
// 微信好友接口类型
|
||||
@@ -38,11 +33,12 @@ interface FriendsResponse {
|
||||
};
|
||||
}
|
||||
|
||||
// 获取好友列表API函数
|
||||
// 获取好友列表API函数 - 添加 keyword 参数
|
||||
const fetchFriendsList = async (params: {
|
||||
page: number;
|
||||
limit: number;
|
||||
deviceIds?: string[];
|
||||
keyword?: string;
|
||||
}): Promise<FriendsResponse> => {
|
||||
if (params.deviceIds && params.deviceIds.length === 0) {
|
||||
return {
|
||||
@@ -58,8 +54,12 @@ const fetchFriendsList = async (params: {
|
||||
}
|
||||
|
||||
const deviceIdsParam = params?.deviceIds?.join(",") || "";
|
||||
const keywordParam = params?.keyword
|
||||
? `&keyword=${encodeURIComponent(params.keyword)}`
|
||||
: "";
|
||||
|
||||
return get<FriendsResponse>(
|
||||
`/v1/friend?page=${params.page}&limit=${params.limit}&deviceIds=${deviceIdsParam}`
|
||||
`/v1/friend?page=${params.page}&limit=${params.limit}&deviceIds=${deviceIdsParam}${keywordParam}`
|
||||
);
|
||||
};
|
||||
|
||||
@@ -94,20 +94,33 @@ export default function FriendSelection({
|
||||
// 打开弹窗并请求第一页好友
|
||||
const openDialog = () => {
|
||||
setCurrentPage(1);
|
||||
setSearchQuery(""); // 重置搜索关键词
|
||||
setDialogOpen(true);
|
||||
fetchFriends(1);
|
||||
fetchFriends(1, "");
|
||||
};
|
||||
|
||||
// 当页码变化时,拉取对应页数据(弹窗已打开时)
|
||||
useEffect(() => {
|
||||
if (dialogOpen && currentPage !== 1) {
|
||||
fetchFriends(currentPage);
|
||||
fetchFriends(currentPage, searchQuery);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [currentPage]);
|
||||
|
||||
// 获取好友列表API
|
||||
const fetchFriends = async (page: number) => {
|
||||
// 搜索防抖
|
||||
useEffect(() => {
|
||||
if (!dialogOpen) return;
|
||||
|
||||
const timer = setTimeout(() => {
|
||||
setCurrentPage(1); // 重置到第一页
|
||||
fetchFriends(1, searchQuery);
|
||||
}, 500); // 500 防抖
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
}, [searchQuery, dialogOpen]);
|
||||
|
||||
// 获取好友列表API - 添加 keyword 参数
|
||||
const fetchFriends = async (page: number, keyword: string = "") => {
|
||||
setLoading(true);
|
||||
try {
|
||||
let res;
|
||||
@@ -119,9 +132,18 @@ export default function FriendSelection({
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
res = await fetchFriendsList({ page, limit: 20, deviceIds: deviceIds });
|
||||
res = await fetchFriendsList({
|
||||
page,
|
||||
limit: 20,
|
||||
deviceIds: deviceIds,
|
||||
keyword: keyword.trim() || undefined,
|
||||
});
|
||||
} else {
|
||||
res = await fetchFriendsList({ page, limit: 20 });
|
||||
res = await fetchFriendsList({
|
||||
page,
|
||||
limit: 20,
|
||||
keyword: keyword.trim() || undefined,
|
||||
});
|
||||
}
|
||||
|
||||
if (res && res.code === 200 && res.data) {
|
||||
@@ -144,13 +166,6 @@ export default function FriendSelection({
|
||||
}
|
||||
};
|
||||
|
||||
// 过滤好友
|
||||
const filteredFriends = friends.filter(
|
||||
(friend) =>
|
||||
friend.nickname.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
friend.wechatId.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
);
|
||||
|
||||
// 处理好友选择
|
||||
const handleFriendToggle = (friendId: string) => {
|
||||
let newIds: string[];
|
||||
@@ -176,6 +191,13 @@ export default function FriendSelection({
|
||||
setDialogOpen(false);
|
||||
};
|
||||
|
||||
// 清空搜索
|
||||
const handleClearSearch = () => {
|
||||
setSearchQuery("");
|
||||
setCurrentPage(1);
|
||||
fetchFriends(1, "");
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* 输入框 */}
|
||||
@@ -221,25 +243,27 @@ export default function FriendSelection({
|
||||
className="pl-10 py-2 rounded-full border-gray-200"
|
||||
/>
|
||||
<Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" />
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="absolute right-2 top-1/2 -translate-y-1/2 h-6 w-6 rounded-full"
|
||||
onClick={() => setSearchQuery("")}
|
||||
>
|
||||
<X className="h-4 w-4" />
|
||||
</Button>
|
||||
{searchQuery && (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="absolute right-2 top-1/2 -translate-y-1/2 h-6 w-6 rounded-full"
|
||||
onClick={handleClearSearch}
|
||||
>
|
||||
<X className="h-4 w-4" />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ScrollArea className="flex-1 overflow-y-auto">
|
||||
<div className="flex-1 overflow-y-auto h-[50vh]">
|
||||
{loading ? (
|
||||
<div className="flex items-center justify-center h-full">
|
||||
<div className="text-gray-500">加载中...</div>
|
||||
</div>
|
||||
) : filteredFriends.length > 0 ? (
|
||||
) : friends.length > 0 ? (
|
||||
<div className="divide-y">
|
||||
{filteredFriends.map((friend) => (
|
||||
{friends.map((friend) => (
|
||||
<label
|
||||
key={friend.id}
|
||||
className="flex items-center px-6 py-4 hover:bg-gray-50 cursor-pointer"
|
||||
@@ -288,11 +312,15 @@ export default function FriendSelection({
|
||||
) : (
|
||||
<div className="flex items-center justify-center h-full">
|
||||
<div className="text-gray-500">
|
||||
{deviceIds.length === 0 ? "请先选择设备" : "没有找到好友"}
|
||||
{deviceIds.length === 0
|
||||
? "请先选择设备"
|
||||
: searchQuery
|
||||
? `没有找到包含"${searchQuery}"的好友`
|
||||
: "没有找到好友"}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</ScrollArea>
|
||||
</div>
|
||||
|
||||
<div className="border-t p-4 flex items-center justify-between bg-white">
|
||||
<div className="text-sm text-gray-500">
|
||||
|
||||
@@ -36,12 +36,17 @@ interface GroupsResponse {
|
||||
};
|
||||
}
|
||||
|
||||
// 修改:支持keyword参数
|
||||
const fetchGroupsList = async (params: {
|
||||
page: number;
|
||||
limit: number;
|
||||
keyword?: string;
|
||||
}): Promise<GroupsResponse> => {
|
||||
const keywordParam = params.keyword
|
||||
? `&keyword=${encodeURIComponent(params.keyword)}`
|
||||
: "";
|
||||
return get<GroupsResponse>(
|
||||
`/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"
|
||||
/>
|
||||
<Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" />
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="absolute right-2 top-1/2 -translate-y-1/2 h-6 w-6 rounded-full"
|
||||
onClick={() => setSearchQuery("")}
|
||||
>
|
||||
<X className="h-4 w-4" />
|
||||
</Button>
|
||||
{searchQuery && (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="absolute right-2 top-1/2 -translate-y-1/2 h-6 w-6 rounded-full"
|
||||
onClick={handleClearSearch}
|
||||
>
|
||||
<X className="h-4 w-4" />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ScrollArea className="flex-1 overflow-y-auto">
|
||||
<div className="flex-1 overflow-y-auto h-[50vh]">
|
||||
{loading ? (
|
||||
<div className="flex items-center justify-center h-full">
|
||||
<div className="text-gray-500">加载中...</div>
|
||||
</div>
|
||||
) : filteredGroups.length > 0 ? (
|
||||
) : groups.length > 0 ? (
|
||||
<div className="divide-y">
|
||||
{filteredGroups.map((group) => (
|
||||
{groups.map((group) => (
|
||||
<label
|
||||
key={group.id}
|
||||
className="flex items-center px-6 py-4 hover:bg-gray-50 cursor-pointer"
|
||||
@@ -252,14 +274,19 @@ export default function GroupSelection({
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex items-center justify-center h-full">
|
||||
<div className="text-gray-500">没有找到群聊</div>
|
||||
<div className="text-gray-500">
|
||||
{searchQuery
|
||||
? `没有找到包含"${searchQuery}"的群聊`
|
||||
: "没有找到群聊"}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</ScrollArea>
|
||||
</div>
|
||||
|
||||
<div className="border-t p-4 flex items-center justify-between bg-white">
|
||||
<div className="text-sm text-gray-500">
|
||||
总计 {totalGroups} 个群聊
|
||||
{searchQuery && ` (搜索: "${searchQuery}")`}
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Button
|
||||
|
||||
@@ -215,11 +215,7 @@ export default function NewPlan() {
|
||||
<header className="sticky top-0 z-10 bg-white border-b">
|
||||
<div className="flex items-center justify-between h-14 px-4">
|
||||
<div className="flex items-center">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={() => router("/scenarios")}
|
||||
>
|
||||
<Button variant="ghost" size="icon" onClick={() => router(-1)}>
|
||||
<ChevronLeft className="h-5 w-5" />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user