feat: 本次提交更新内容如下

组件更新,先这样吧
This commit is contained in:
2025-07-23 14:12:07 +08:00
parent 4804bab90a
commit 7c33e8fa62
2 changed files with 114 additions and 256 deletions

View File

@@ -1,9 +1,12 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { SearchOutlined, DeleteOutlined } from "@ant-design/icons"; import { SearchOutlined, DeleteOutlined } from "@ant-design/icons";
import { Popup, Toast } from "antd-mobile"; import { Popup } from "antd-mobile";
import { Button, Input } from "antd"; import { Button, Input } from "antd";
import { getFriendList } from "./api"; import { getFriendList } from "./api";
import style from "./index.module.scss"; 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 { interface WechatFriend {
@@ -104,35 +107,18 @@ export default function FriendSelection({
params.keyword = keyword.trim(); params.keyword = keyword.trim();
} }
if (enableDeviceFilter) { if (enableDeviceFilter && deviceIds.length > 0) {
if (deviceIds.length === 0) { params.deviceIds = deviceIds;
setFriends([]);
setTotalFriends(0);
setTotalPages(1);
setLoading(false);
return;
}
params.deviceIds = deviceIds.join(",");
} }
const res = await getFriendList(params); const response = await getFriendList(params);
if (response && response.list) {
if (res && Array.isArray(res.list)) { setFriends(response.list);
setFriends( setTotalFriends(response.total || 0);
res.list.map((friend: any) => ({ setTotalPages(Math.ceil((response.total || 0) / 20));
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));
} }
} catch (error) { } catch (error) {
console.error("获取好友列表失败:", error); console.error("获取好友列表失败:", error);
Toast.show({ content: "获取好友列表失败", position: "top" });
} finally { } finally {
setLoading(false); setLoading(false);
} }
@@ -140,16 +126,20 @@ export default function FriendSelection({
// 处理好友选择 // 处理好友选择
const handleFriendToggle = (friendId: string) => { const handleFriendToggle = (friendId: string) => {
let newIds: string[]; if (readonly) return;
if (selectedFriends.includes(friendId)) {
newIds = selectedFriends.filter((id) => id !== friendId); const newSelectedFriends = selectedFriends.includes(friendId)
} else { ? selectedFriends.filter((id) => id !== friendId)
newIds = [...selectedFriends, friendId]; : [...selectedFriends, friendId];
}
onSelect(newIds); onSelect(newSelectedFriends);
// 如果有 onSelectDetail 回调,传递完整的好友对象
if (onSelectDetail) { if (onSelectDetail) {
const selectedObjs = friends.filter((f) => newIds.includes(f.id)); const selectedFriendObjs = friends.filter((friend) =>
onSelectDetail(selectedObjs); newSelectedFriends.includes(friend.id)
);
onSelectDetail(selectedFriendObjs);
} }
}; };
@@ -160,29 +150,22 @@ export default function FriendSelection({
}; };
// 获取已选好友详细信息 // 获取已选好友详细信息
const selectedFriendObjs = selectedFriends const selectedFriendObjs = friends.filter((friend) =>
.map((id) => friends.find((f) => f.id === id)) selectedFriends.includes(friend.id)
.filter(Boolean) as WechatFriend[]; );
// 删除已选好友 // 删除已选好友
const handleRemoveFriend = (id: string) => { const handleRemoveFriend = (id: string) => {
if (readonly) return; if (readonly) return;
onSelect(selectedFriends.filter((f) => f !== id)); onSelect(selectedFriends.filter((d) => d !== id));
}; };
// 确认按钮逻辑 // 确认选择
const handleConfirm = () => { const handleConfirm = () => {
setRealVisible(false);
if (onConfirm) { if (onConfirm) {
onConfirm(selectedFriends, selectedFriendObjs); onConfirm(selectedFriends, selectedFriendObjs);
} }
}; setRealVisible(false);
// 清空搜索
const handleClearSearch = () => {
setSearchQuery("");
setCurrentPage(1);
fetchFriends(1, "");
}; };
return ( return (
@@ -271,40 +254,30 @@ export default function FriendSelection({
position="bottom" position="bottom"
bodyStyle={{ height: "100vh" }} bodyStyle={{ height: "100vh" }}
> >
<div className={style.popupContainer}> <Layout
<div className={style.popupHeader}> header={
<div className={style.popupTitle}></div> <PopupHeader
<div className={style.searchWrapper}> title="选择微信好友"
<Input searchQuery={searchQuery}
placeholder="搜索好友" setSearchQuery={setSearchQuery}
value={searchQuery} searchPlaceholder="搜索好友"
onChange={(e) => setSearchQuery(e.target.value)} loading={loading}
disabled={readonly} onRefresh={() => fetchFriends(currentPage, searchQuery)}
prefix={<SearchOutlined />} />
allowClear }
size="large" footer={
/> <PopupFooter
{searchQuery && !readonly && ( total={totalFriends}
<Button currentPage={currentPage}
type="text" totalPages={totalPages}
icon={<DeleteOutlined />} loading={loading}
size="small" selectedCount={selectedFriends.length}
className={style.clearBtn} onPageChange={setCurrentPage}
onClick={handleClearSearch} onCancel={() => setRealVisible(false)}
style={{ onConfirm={handleConfirm}
color: "#ff4d4f", />
border: "none", }
background: "none", >
minWidth: 24,
height: 24,
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
/>
)}
</div>
</div>
<div className={style.friendList}> <div className={style.friendList}>
{loading ? ( {loading ? (
<div className={style.loadingBox}> <div className={style.loadingBox}>
@@ -372,50 +345,7 @@ export default function FriendSelection({
</div> </div>
)} )}
</div> </div>
{/* 分页栏 */} </Layout>
<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 }}
>
&lt;
</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 }}
>
&gt;
</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>
</Popup> </Popup>
</> </>
); );

View File

@@ -1,15 +1,12 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { import { SearchOutlined, DeleteOutlined } from "@ant-design/icons";
SearchOutlined,
CloseOutlined,
ArrowLeftOutlined,
ArrowRightOutlined,
DeleteOutlined,
} from "@ant-design/icons";
import { Button, Input } from "antd"; import { Button, Input } from "antd";
import { Popup, Toast } from "antd-mobile"; import { Popup } from "antd-mobile";
import { getGroupList } from "./api"; import { getGroupList } from "./api";
import style from "./index.module.scss"; 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 { interface WechatGroup {
@@ -61,9 +58,9 @@ export default function GroupSelection({
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
// 获取已选群聊详细信息 // 获取已选群聊详细信息
const selectedGroupObjs = selectedGroups const selectedGroupObjs = groups.filter((group) =>
.map((id) => groups.find((g) => g.id === id)) selectedGroups.includes(group.id)
.filter(Boolean) as WechatGroup[]; );
// 删除已选群聊 // 删除已选群聊
const handleRemoveGroup = (id: string) => { const handleRemoveGroup = (id: string) => {
@@ -101,58 +98,52 @@ export default function GroupSelection({
setCurrentPage(1); setCurrentPage(1);
fetchGroups(1, searchQuery); fetchGroups(1, searchQuery);
}, 500); }, 500);
return () => clearTimeout(timer); return () => clearTimeout(timer);
}, [searchQuery, realVisible]); }, [searchQuery, realVisible]);
// 获取群列表API - 支持keyword // 获取群列表API
const fetchGroups = async (page: number, keyword: string = "") => { const fetchGroups = async (page: number, keyword: string = "") => {
setLoading(true); setLoading(true);
try { try {
const params: any = { let params: any = {
page, page,
limit: 20, limit: 20,
}; };
if (keyword.trim()) { if (keyword.trim()) {
params.keyword = keyword.trim(); params.keyword = keyword.trim();
} }
const res = await getGroupList(params); const response = await getGroupList(params);
if (response && response.list) {
if (res && Array.isArray(res.list)) { setGroups(response.list);
setGroups( setTotalGroups(response.total || 0);
res.list.map((group: any) => ({ setTotalPages(Math.ceil((response.total || 0) / 20));
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));
} }
} catch (error) { } catch (error) {
console.error("获取群列表失败:", error); console.error("获取群列表失败:", error);
Toast.show({ content: "获取群组列表失败", position: "top" });
} finally { } finally {
setLoading(false); setLoading(false);
} }
}; };
// 处理群选择 // 处理群选择
const handleGroupToggle = (groupId: string) => { const handleGroupToggle = (groupId: string) => {
let newIds: string[]; if (readonly) return;
if (selectedGroups.includes(groupId)) {
newIds = selectedGroups.filter((id) => id !== groupId); const newSelectedGroups = selectedGroups.includes(groupId)
} else { ? selectedGroups.filter((id) => id !== groupId)
newIds = [...selectedGroups, groupId]; : [...selectedGroups, groupId];
}
onSelect(newIds); onSelect(newSelectedGroups);
// 如果有 onSelectDetail 回调,传递完整的群聊对象
if (onSelectDetail) { if (onSelectDetail) {
const selectedObjs = groups.filter((g) => newIds.includes(g.id)); const selectedGroupObjs = groups.filter((group) =>
onSelectDetail(selectedObjs); newSelectedGroups.includes(group.id)
);
onSelectDetail(selectedGroupObjs);
} }
}; };
@@ -162,19 +153,12 @@ export default function GroupSelection({
return `已选择 ${selectedGroups.length} 个群聊`; return `已选择 ${selectedGroups.length} 个群聊`;
}; };
// 确认按钮逻辑 // 确认选择
const handleConfirm = () => { const handleConfirm = () => {
setRealVisible(false);
if (onConfirm) { if (onConfirm) {
onConfirm(selectedGroups, selectedGroupObjs); onConfirm(selectedGroups, selectedGroupObjs);
} }
}; setRealVisible(false);
// 清空搜索
const handleClearSearch = () => {
setSearchQuery("");
setCurrentPage(1);
fetchGroups(1, "");
}; };
return ( return (
@@ -263,41 +247,30 @@ export default function GroupSelection({
position="bottom" position="bottom"
bodyStyle={{ height: "100vh" }} bodyStyle={{ height: "100vh" }}
> >
<div className={style.popupContainer}> <Layout
<div className={style.popupHeader}> header={
<div className={style.popupTitle}></div> <PopupHeader
<div className={style.searchWrapper}> title="选择群聊"
<Input searchQuery={searchQuery}
placeholder="搜索群聊" setSearchQuery={setSearchQuery}
value={searchQuery} searchPlaceholder="搜索群聊"
onChange={(e) => setSearchQuery(e.target.value)} loading={loading}
disabled={readonly} onRefresh={() => fetchGroups(currentPage, searchQuery)}
prefix={<SearchOutlined />} />
allowClear }
size="large" footer={
/> <PopupFooter
<SearchOutlined className={style.searchIcon} /> total={totalGroups}
{searchQuery && !readonly && ( currentPage={currentPage}
<Button totalPages={totalPages}
type="text" loading={loading}
icon={<CloseOutlined />} selectedCount={selectedGroups.length}
size="small" onPageChange={setCurrentPage}
className={style.clearBtn} onCancel={() => setRealVisible(false)}
onClick={handleClearSearch} onConfirm={handleConfirm}
style={{ />
color: "#ff4d4f", }
border: "none", >
background: "none",
minWidth: 24,
height: 24,
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
/>
)}
</div>
</div>
<div className={style.groupList}> <div className={style.groupList}>
{loading ? ( {loading ? (
<div className={style.loadingBox}> <div className={style.loadingBox}>
@@ -361,52 +334,7 @@ export default function GroupSelection({
</div> </div>
)} )}
</div> </div>
{/* 分页栏 */} </Layout>
<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>
</Popup> </Popup>
</> </>
); );