feat: 本次提交更新内容如下
组件更新,先这样吧
This commit is contained in:
@@ -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 }}
|
|
||||||
>
|
|
||||||
<
|
|
||||||
</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>
|
|
||||||
</Popup>
|
</Popup>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user