feat: 本次提交更新内容如下
组件更新,先这样吧
This commit is contained in:
@@ -1,9 +1,12 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { SearchOutlined, DeleteOutlined } from "@ant-design/icons";
|
||||
import { Popup, Toast } from "antd-mobile";
|
||||
import { Popup } from "antd-mobile";
|
||||
import { Button, Input } from "antd";
|
||||
import { getFriendList } from "./api";
|
||||
import style from "./index.module.scss";
|
||||
import Layout from "@/components/Layout/Layout";
|
||||
import PopupHeader from "@/components/PopuLayout/header";
|
||||
import PopupFooter from "@/components/PopuLayout/footer";
|
||||
|
||||
// 微信好友接口类型
|
||||
interface WechatFriend {
|
||||
@@ -104,35 +107,18 @@ export default function FriendSelection({
|
||||
params.keyword = keyword.trim();
|
||||
}
|
||||
|
||||
if (enableDeviceFilter) {
|
||||
if (deviceIds.length === 0) {
|
||||
setFriends([]);
|
||||
setTotalFriends(0);
|
||||
setTotalPages(1);
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
params.deviceIds = deviceIds.join(",");
|
||||
if (enableDeviceFilter && deviceIds.length > 0) {
|
||||
params.deviceIds = deviceIds;
|
||||
}
|
||||
|
||||
const res = await getFriendList(params);
|
||||
|
||||
if (res && Array.isArray(res.list)) {
|
||||
setFriends(
|
||||
res.list.map((friend: any) => ({
|
||||
id: friend.id?.toString() || "",
|
||||
nickname: friend.nickname || "",
|
||||
wechatId: friend.wechatId || "",
|
||||
avatar: friend.avatar || "",
|
||||
customer: friend.customer || "",
|
||||
}))
|
||||
);
|
||||
setTotalFriends(res.total || 0);
|
||||
setTotalPages(Math.ceil((res.total || 0) / 20));
|
||||
const response = await getFriendList(params);
|
||||
if (response && response.list) {
|
||||
setFriends(response.list);
|
||||
setTotalFriends(response.total || 0);
|
||||
setTotalPages(Math.ceil((response.total || 0) / 20));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("获取好友列表失败:", error);
|
||||
Toast.show({ content: "获取好友列表失败", position: "top" });
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
@@ -140,16 +126,20 @@ export default function FriendSelection({
|
||||
|
||||
// 处理好友选择
|
||||
const handleFriendToggle = (friendId: string) => {
|
||||
let newIds: string[];
|
||||
if (selectedFriends.includes(friendId)) {
|
||||
newIds = selectedFriends.filter((id) => id !== friendId);
|
||||
} else {
|
||||
newIds = [...selectedFriends, friendId];
|
||||
}
|
||||
onSelect(newIds);
|
||||
if (readonly) return;
|
||||
|
||||
const newSelectedFriends = selectedFriends.includes(friendId)
|
||||
? selectedFriends.filter((id) => id !== friendId)
|
||||
: [...selectedFriends, friendId];
|
||||
|
||||
onSelect(newSelectedFriends);
|
||||
|
||||
// 如果有 onSelectDetail 回调,传递完整的好友对象
|
||||
if (onSelectDetail) {
|
||||
const selectedObjs = friends.filter((f) => newIds.includes(f.id));
|
||||
onSelectDetail(selectedObjs);
|
||||
const selectedFriendObjs = friends.filter((friend) =>
|
||||
newSelectedFriends.includes(friend.id)
|
||||
);
|
||||
onSelectDetail(selectedFriendObjs);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -160,29 +150,22 @@ export default function FriendSelection({
|
||||
};
|
||||
|
||||
// 获取已选好友详细信息
|
||||
const selectedFriendObjs = selectedFriends
|
||||
.map((id) => friends.find((f) => f.id === id))
|
||||
.filter(Boolean) as WechatFriend[];
|
||||
const selectedFriendObjs = friends.filter((friend) =>
|
||||
selectedFriends.includes(friend.id)
|
||||
);
|
||||
|
||||
// 删除已选好友
|
||||
const handleRemoveFriend = (id: string) => {
|
||||
if (readonly) return;
|
||||
onSelect(selectedFriends.filter((f) => f !== id));
|
||||
onSelect(selectedFriends.filter((d) => d !== id));
|
||||
};
|
||||
|
||||
// 确认按钮逻辑
|
||||
// 确认选择
|
||||
const handleConfirm = () => {
|
||||
setRealVisible(false);
|
||||
if (onConfirm) {
|
||||
onConfirm(selectedFriends, selectedFriendObjs);
|
||||
}
|
||||
};
|
||||
|
||||
// 清空搜索
|
||||
const handleClearSearch = () => {
|
||||
setSearchQuery("");
|
||||
setCurrentPage(1);
|
||||
fetchFriends(1, "");
|
||||
setRealVisible(false);
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -271,40 +254,30 @@ export default function FriendSelection({
|
||||
position="bottom"
|
||||
bodyStyle={{ height: "100vh" }}
|
||||
>
|
||||
<div className={style.popupContainer}>
|
||||
<div className={style.popupHeader}>
|
||||
<div className={style.popupTitle}>选择微信好友</div>
|
||||
<div className={style.searchWrapper}>
|
||||
<Input
|
||||
placeholder="搜索好友"
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
disabled={readonly}
|
||||
prefix={<SearchOutlined />}
|
||||
allowClear
|
||||
size="large"
|
||||
/>
|
||||
{searchQuery && !readonly && (
|
||||
<Button
|
||||
type="text"
|
||||
icon={<DeleteOutlined />}
|
||||
size="small"
|
||||
className={style.clearBtn}
|
||||
onClick={handleClearSearch}
|
||||
style={{
|
||||
color: "#ff4d4f",
|
||||
border: "none",
|
||||
background: "none",
|
||||
minWidth: 24,
|
||||
height: 24,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<Layout
|
||||
header={
|
||||
<PopupHeader
|
||||
title="选择微信好友"
|
||||
searchQuery={searchQuery}
|
||||
setSearchQuery={setSearchQuery}
|
||||
searchPlaceholder="搜索好友"
|
||||
loading={loading}
|
||||
onRefresh={() => fetchFriends(currentPage, searchQuery)}
|
||||
/>
|
||||
}
|
||||
footer={
|
||||
<PopupFooter
|
||||
total={totalFriends}
|
||||
currentPage={currentPage}
|
||||
totalPages={totalPages}
|
||||
loading={loading}
|
||||
selectedCount={selectedFriends.length}
|
||||
onPageChange={setCurrentPage}
|
||||
onCancel={() => setRealVisible(false)}
|
||||
onConfirm={handleConfirm}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<div className={style.friendList}>
|
||||
{loading ? (
|
||||
<div className={style.loadingBox}>
|
||||
@@ -372,50 +345,7 @@ export default function FriendSelection({
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{/* 分页栏 */}
|
||||
<div className={style.paginationRow}>
|
||||
<div className={style.totalCount}>总计 {totalFriends} 个好友</div>
|
||||
<div className={style.paginationControls}>
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
onClick={() => setCurrentPage(Math.max(1, currentPage - 1))}
|
||||
disabled={currentPage === 1 || loading}
|
||||
className={style.pageBtn}
|
||||
style={{ borderRadius: 16 }}
|
||||
>
|
||||
<
|
||||
</Button>
|
||||
<span className={style.pageInfo}>
|
||||
{currentPage} / {totalPages}
|
||||
</span>
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
onClick={() =>
|
||||
setCurrentPage(Math.min(totalPages, currentPage + 1))
|
||||
}
|
||||
disabled={currentPage === totalPages || loading}
|
||||
className={style.pageBtn}
|
||||
style={{ borderRadius: 16 }}
|
||||
>
|
||||
>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
{/* 底部按钮栏 */}
|
||||
<div className={style.popupFooter}>
|
||||
<div className={style.selectedCount}>
|
||||
已选择 {selectedFriends.length} 个好友
|
||||
</div>
|
||||
<div className={style.footerBtnGroup}>
|
||||
<Button onClick={() => setRealVisible(false)}>取消</Button>
|
||||
<Button type="primary" onClick={handleConfirm}>
|
||||
确定
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
</Popup>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import {
|
||||
SearchOutlined,
|
||||
CloseOutlined,
|
||||
ArrowLeftOutlined,
|
||||
ArrowRightOutlined,
|
||||
DeleteOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import { SearchOutlined, DeleteOutlined } from "@ant-design/icons";
|
||||
import { Button, Input } from "antd";
|
||||
import { Popup, Toast } from "antd-mobile";
|
||||
import { Popup } from "antd-mobile";
|
||||
import { getGroupList } from "./api";
|
||||
import style from "./index.module.scss";
|
||||
import Layout from "@/components/Layout/Layout";
|
||||
import PopupHeader from "@/components/PopuLayout/header";
|
||||
import PopupFooter from "@/components/PopuLayout/footer";
|
||||
|
||||
// 群组接口类型
|
||||
interface WechatGroup {
|
||||
@@ -61,9 +58,9 @@ export default function GroupSelection({
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
// 获取已选群聊详细信息
|
||||
const selectedGroupObjs = selectedGroups
|
||||
.map((id) => groups.find((g) => g.id === id))
|
||||
.filter(Boolean) as WechatGroup[];
|
||||
const selectedGroupObjs = groups.filter((group) =>
|
||||
selectedGroups.includes(group.id)
|
||||
);
|
||||
|
||||
// 删除已选群聊
|
||||
const handleRemoveGroup = (id: string) => {
|
||||
@@ -101,58 +98,52 @@ export default function GroupSelection({
|
||||
setCurrentPage(1);
|
||||
fetchGroups(1, searchQuery);
|
||||
}, 500);
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
}, [searchQuery, realVisible]);
|
||||
|
||||
// 获取群组列表API - 支持keyword
|
||||
// 获取群聊列表API
|
||||
const fetchGroups = async (page: number, keyword: string = "") => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const params: any = {
|
||||
let params: any = {
|
||||
page,
|
||||
limit: 20,
|
||||
};
|
||||
|
||||
if (keyword.trim()) {
|
||||
params.keyword = keyword.trim();
|
||||
}
|
||||
|
||||
const res = await getGroupList(params);
|
||||
|
||||
if (res && Array.isArray(res.list)) {
|
||||
setGroups(
|
||||
res.list.map((group: any) => ({
|
||||
id: group.id?.toString() || "",
|
||||
chatroomId: group.chatroomId || "",
|
||||
name: group.name || "",
|
||||
avatar: group.avatar || "",
|
||||
ownerWechatId: group.ownerWechatId || "",
|
||||
ownerNickname: group.ownerNickname || "",
|
||||
ownerAvatar: group.ownerAvatar || "",
|
||||
}))
|
||||
);
|
||||
setTotalGroups(res.total || 0);
|
||||
setTotalPages(Math.ceil((res.total || 0) / 20));
|
||||
const response = await getGroupList(params);
|
||||
if (response && response.list) {
|
||||
setGroups(response.list);
|
||||
setTotalGroups(response.total || 0);
|
||||
setTotalPages(Math.ceil((response.total || 0) / 20));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("获取群组列表失败:", error);
|
||||
Toast.show({ content: "获取群组列表失败", position: "top" });
|
||||
console.error("获取群聊列表失败:", error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 处理群组选择
|
||||
// 处理群聊选择
|
||||
const handleGroupToggle = (groupId: string) => {
|
||||
let newIds: string[];
|
||||
if (selectedGroups.includes(groupId)) {
|
||||
newIds = selectedGroups.filter((id) => id !== groupId);
|
||||
} else {
|
||||
newIds = [...selectedGroups, groupId];
|
||||
}
|
||||
onSelect(newIds);
|
||||
if (readonly) return;
|
||||
|
||||
const newSelectedGroups = selectedGroups.includes(groupId)
|
||||
? selectedGroups.filter((id) => id !== groupId)
|
||||
: [...selectedGroups, groupId];
|
||||
|
||||
onSelect(newSelectedGroups);
|
||||
|
||||
// 如果有 onSelectDetail 回调,传递完整的群聊对象
|
||||
if (onSelectDetail) {
|
||||
const selectedObjs = groups.filter((g) => newIds.includes(g.id));
|
||||
onSelectDetail(selectedObjs);
|
||||
const selectedGroupObjs = groups.filter((group) =>
|
||||
newSelectedGroups.includes(group.id)
|
||||
);
|
||||
onSelectDetail(selectedGroupObjs);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -162,19 +153,12 @@ export default function GroupSelection({
|
||||
return `已选择 ${selectedGroups.length} 个群聊`;
|
||||
};
|
||||
|
||||
// 确认按钮逻辑
|
||||
// 确认选择
|
||||
const handleConfirm = () => {
|
||||
setRealVisible(false);
|
||||
if (onConfirm) {
|
||||
onConfirm(selectedGroups, selectedGroupObjs);
|
||||
}
|
||||
};
|
||||
|
||||
// 清空搜索
|
||||
const handleClearSearch = () => {
|
||||
setSearchQuery("");
|
||||
setCurrentPage(1);
|
||||
fetchGroups(1, "");
|
||||
setRealVisible(false);
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -263,41 +247,30 @@ export default function GroupSelection({
|
||||
position="bottom"
|
||||
bodyStyle={{ height: "100vh" }}
|
||||
>
|
||||
<div className={style.popupContainer}>
|
||||
<div className={style.popupHeader}>
|
||||
<div className={style.popupTitle}>选择群聊</div>
|
||||
<div className={style.searchWrapper}>
|
||||
<Input
|
||||
placeholder="搜索群聊"
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
disabled={readonly}
|
||||
prefix={<SearchOutlined />}
|
||||
allowClear
|
||||
size="large"
|
||||
/>
|
||||
<SearchOutlined className={style.searchIcon} />
|
||||
{searchQuery && !readonly && (
|
||||
<Button
|
||||
type="text"
|
||||
icon={<CloseOutlined />}
|
||||
size="small"
|
||||
className={style.clearBtn}
|
||||
onClick={handleClearSearch}
|
||||
style={{
|
||||
color: "#ff4d4f",
|
||||
border: "none",
|
||||
background: "none",
|
||||
minWidth: 24,
|
||||
height: 24,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<Layout
|
||||
header={
|
||||
<PopupHeader
|
||||
title="选择群聊"
|
||||
searchQuery={searchQuery}
|
||||
setSearchQuery={setSearchQuery}
|
||||
searchPlaceholder="搜索群聊"
|
||||
loading={loading}
|
||||
onRefresh={() => fetchGroups(currentPage, searchQuery)}
|
||||
/>
|
||||
}
|
||||
footer={
|
||||
<PopupFooter
|
||||
total={totalGroups}
|
||||
currentPage={currentPage}
|
||||
totalPages={totalPages}
|
||||
loading={loading}
|
||||
selectedCount={selectedGroups.length}
|
||||
onPageChange={setCurrentPage}
|
||||
onCancel={() => setRealVisible(false)}
|
||||
onConfirm={handleConfirm}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<div className={style.groupList}>
|
||||
{loading ? (
|
||||
<div className={style.loadingBox}>
|
||||
@@ -361,52 +334,7 @@ export default function GroupSelection({
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{/* 分页栏 */}
|
||||
<div className={style.paginationRow}>
|
||||
<div className={style.totalCount}>总计 {totalGroups} 个群聊</div>
|
||||
<div className={style.paginationControls}>
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
onClick={() => setCurrentPage(Math.max(1, currentPage - 1))}
|
||||
disabled={currentPage === 1 || loading}
|
||||
className={style.pageBtn}
|
||||
style={{ borderRadius: 16 }}
|
||||
>
|
||||
<ArrowLeftOutlined />
|
||||
</Button>
|
||||
<span className={style.pageInfo}>
|
||||
{currentPage} / {totalPages}
|
||||
</span>
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
onClick={() =>
|
||||
setCurrentPage(Math.min(totalPages, currentPage + 1))
|
||||
}
|
||||
disabled={currentPage === totalPages || loading}
|
||||
className={style.pageBtn}
|
||||
style={{ borderRadius: 16 }}
|
||||
>
|
||||
<ArrowRightOutlined />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
{/* 底部按钮栏 */}
|
||||
<div className={style.popupFooter}>
|
||||
<div className={style.selectedCount}>
|
||||
已选择 {selectedGroups.length} 个群聊
|
||||
</div>
|
||||
<div className={style.footerBtnGroup}>
|
||||
<Button type="default" onClick={() => setRealVisible(false)}>
|
||||
取消
|
||||
</Button>
|
||||
<Button type="primary" onClick={handleConfirm}>
|
||||
确定
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
</Popup>
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user