refactor: 重构TwoColumnSelection组件并移动至新目录

将TwoColumnSelection组件从FriendSelection目录移动到新的TwoColumnSelection目录
优化组件代码格式和样式文件结构
更新相关引用路径
This commit is contained in:
超级老白兔
2025-09-10 10:46:02 +08:00
parent 04589154ca
commit e08c290a66
3 changed files with 299 additions and 234 deletions

View File

@@ -27,7 +27,7 @@
.searchWrapper { .searchWrapper {
padding: 16px; padding: 16px;
border-bottom: 1px solid #e8e8e8; border-bottom: 1px solid #e8e8e8;
.ant-input { .ant-input {
border-radius: 6px; border-radius: 6px;
} }
@@ -45,15 +45,15 @@
padding: 12px 16px; padding: 12px 16px;
cursor: pointer; cursor: pointer;
transition: background-color 0.2s; transition: background-color 0.2s;
&:hover { &:hover {
background-color: #f5f5f5; background-color: #f5f5f5;
} }
&.selected { &.selected {
background-color: #e6f7ff; background-color: #e6f7ff;
} }
.ant-checkbox { .ant-checkbox {
margin-right: 12px; margin-right: 12px;
} }
@@ -119,7 +119,7 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
&:hover { &:hover {
color: #ff4d4f; color: #ff4d4f;
background: #fff2f0; background: #fff2f0;
@@ -150,4 +150,4 @@
height: 100px; height: 100px;
color: #999; color: #999;
font-size: 14px; font-size: 14px;
} }

View File

@@ -1,9 +1,9 @@
import React, { useState, useCallback, useEffect, useMemo, memo } from 'react'; import React, { useState, useCallback, useEffect, useMemo, memo } from "react";
import { Modal, Input, Avatar, Button, Checkbox, message } from 'antd'; import { Modal, Input, Avatar, Button, Checkbox, message } from "antd";
import { SearchOutlined } from '@ant-design/icons'; import { SearchOutlined } from "@ant-design/icons";
import { getFriendList } from './api'; import { getFriendList } from "../FriendSelection/api";
import type { FriendSelectionItem } from './data'; import type { FriendSelectionItem } from "../FriendSelection/data";
import styles from './TwoColumnSelection.module.scss'; import styles from "./TwoColumnSelection.module.scss";
// 使用 React.memo 优化好友列表项组件 // 使用 React.memo 优化好友列表项组件
const FriendListItem = memo<{ const FriendListItem = memo<{
@@ -13,7 +13,7 @@ const FriendListItem = memo<{
}>(({ friend, isSelected, onSelect }) => { }>(({ friend, isSelected, onSelect }) => {
return ( return (
<div <div
className={`${styles.friendItem} ${isSelected ? styles.selected : ''}`} className={`${styles.friendItem} ${isSelected ? styles.selected : ""}`}
onClick={() => onSelect(friend)} onClick={() => onSelect(friend)}
> >
<Checkbox checked={isSelected} /> <Checkbox checked={isSelected} />
@@ -28,12 +28,15 @@ const FriendListItem = memo<{
); );
}); });
FriendListItem.displayName = 'FriendListItem'; FriendListItem.displayName = "FriendListItem";
interface TwoColumnSelectionProps { interface TwoColumnSelectionProps {
visible: boolean; visible: boolean;
onCancel: () => void; onCancel: () => void;
onConfirm: (selectedIds: string[], selectedItems: FriendSelectionItem[]) => void; onConfirm: (
selectedIds: string[],
selectedItems: FriendSelectionItem[],
) => void;
title?: string; title?: string;
deviceIds?: number[]; deviceIds?: number[];
enableDeviceFilter?: boolean; enableDeviceFilter?: boolean;
@@ -44,14 +47,16 @@ const TwoColumnSelection: React.FC<TwoColumnSelectionProps> = ({
visible, visible,
onCancel, onCancel,
onConfirm, onConfirm,
title = '选择好友', title = "选择好友",
deviceIds = [], deviceIds = [],
enableDeviceFilter = true, enableDeviceFilter = true,
dataSource, dataSource,
}) => { }) => {
const [rawFriends, setRawFriends] = useState<FriendSelectionItem[]>([]); const [rawFriends, setRawFriends] = useState<FriendSelectionItem[]>([]);
const [selectedFriends, setSelectedFriends] = useState<FriendSelectionItem[]>([]); const [selectedFriends, setSelectedFriends] = useState<FriendSelectionItem[]>(
const [searchQuery, setSearchQuery] = useState(''); [],
);
const [searchQuery, setSearchQuery] = useState("");
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [currentPage, setCurrentPage] = useState(1); const [currentPage, setCurrentPage] = useState(1);
const [totalPages, setTotalPages] = useState(1); const [totalPages, setTotalPages] = useState(1);
@@ -64,9 +69,10 @@ const TwoColumnSelection: React.FC<TwoColumnSelectionProps> = ({
} }
const query = searchQuery.toLowerCase(); const query = searchQuery.toLowerCase();
return sourceData.filter(item => return sourceData.filter(
item.name?.toLowerCase().includes(query) || item =>
item.nickname?.toLowerCase().includes(query) item.name?.toLowerCase().includes(query) ||
item.nickname?.toLowerCase().includes(query),
); );
}, [dataSource, rawFriends, searchQuery]); }, [dataSource, rawFriends, searchQuery]);
@@ -92,38 +98,41 @@ const TwoColumnSelection: React.FC<TwoColumnSelectionProps> = ({
}, [selectedFriends]); }, [selectedFriends]);
// 获取好友列表 // 获取好友列表
const fetchFriends = useCallback(async (page: number, keyword: string = '') => { const fetchFriends = useCallback(
setLoading(true); async (page: number, keyword: string = "") => {
try { setLoading(true);
const params: any = { try {
page, const params: any = {
pageSize: 20, page,
}; pageSize: 20,
};
if (keyword) { if (keyword) {
params.keyword = keyword; params.keyword = keyword;
}
if (enableDeviceFilter && deviceIds.length > 0) {
params.deviceIds = deviceIds;
}
const response = await getFriendList(params);
if (response.success) {
setRawFriends(response.data.list || []);
setTotalPages(Math.ceil((response.data.total || 0) / 20));
} else {
setRawFriends([]);
message.error(response.message || "获取好友列表失败");
}
} catch (error) {
console.error("获取好友列表失败:", error);
message.error("获取好友列表失败");
} finally {
setLoading(false);
} }
},
if (enableDeviceFilter && deviceIds.length > 0) { [deviceIds, enableDeviceFilter],
params.deviceIds = deviceIds; );
}
const response = await getFriendList(params);
if (response.success) {
setRawFriends(response.data.list || []);
setTotalPages(Math.ceil((response.data.total || 0) / 20));
} else {
setRawFriends([]);
message.error(response.message || '获取好友列表失败');
}
} catch (error) {
console.error('获取好友列表失败:', error);
message.error('获取好友列表失败');
} finally {
setLoading(false);
}
}, [deviceIds, enableDeviceFilter]);
// 初始化数据加载 // 初始化数据加载
useEffect(() => { useEffect(() => {
@@ -137,7 +146,7 @@ const TwoColumnSelection: React.FC<TwoColumnSelectionProps> = ({
// 重置搜索状态 // 重置搜索状态
useEffect(() => { useEffect(() => {
if (visible) { if (visible) {
setSearchQuery(''); setSearchQuery("");
setSelectedFriends([]); setSelectedFriends([]);
setLoading(false); setLoading(false);
} }
@@ -158,11 +167,14 @@ const TwoColumnSelection: React.FC<TwoColumnSelectionProps> = ({
}, [dataSource, fetchFriends])(); }, [dataSource, fetchFriends])();
// API搜索处理当没有外部数据源时 // API搜索处理当没有外部数据源时
const handleApiSearch = useCallback(async (keyword: string) => { const handleApiSearch = useCallback(
if (!dataSource) { async (keyword: string) => {
await fetchFriends(1, keyword); if (!dataSource) {
} await fetchFriends(1, keyword);
}, [dataSource, fetchFriends]); }
},
[dataSource, fetchFriends],
);
// 加载更多好友 // 加载更多好友
const handleLoadMore = useCallback(() => { const handleLoadMore = useCallback(() => {
@@ -201,13 +213,13 @@ const TwoColumnSelection: React.FC<TwoColumnSelectionProps> = ({
const selectedIds = selectedFriends.map(f => f.id.toString()); const selectedIds = selectedFriends.map(f => f.id.toString());
onConfirm(selectedIds, selectedFriends); onConfirm(selectedIds, selectedFriends);
setSelectedFriends([]); setSelectedFriends([]);
setSearchQuery(''); setSearchQuery("");
}, [selectedFriends, onConfirm]); }, [selectedFriends, onConfirm]);
// 取消选择 - 使用 useCallback 优化性能 // 取消选择 - 使用 useCallback 优化性能
const handleCancel = useCallback(() => { const handleCancel = useCallback(() => {
setSelectedFriends([]); setSelectedFriends([]);
setSearchQuery(''); setSearchQuery("");
onCancel(); onCancel();
}, [onCancel]); }, [onCancel]);
@@ -232,15 +244,15 @@ const TwoColumnSelection: React.FC<TwoColumnSelectionProps> = ({
<div className={styles.leftColumn}> <div className={styles.leftColumn}>
<div className={styles.searchWrapper}> <div className={styles.searchWrapper}>
<Input <Input
placeholder="请输入昵称或微信号" placeholder="请输入昵称或微信号"
value={searchQuery} value={searchQuery}
onChange={(e) => { onChange={e => {
const value = e.target.value; const value = e.target.value;
setSearchQuery(value); // 立即更新显示 setSearchQuery(value); // 立即更新显示
handleSearch(value); // 防抖处理搜索 handleSearch(value); // 防抖处理搜索
}} }}
prefix={<SearchOutlined />} prefix={<SearchOutlined />}
allowClear allowClear
/> />
</div> </div>
@@ -262,17 +274,15 @@ const TwoColumnSelection: React.FC<TwoColumnSelectionProps> = ({
}) })
) : ( ) : (
<div className={styles.empty}> <div className={styles.empty}>
{searchQuery ? `没有找到包含"${searchQuery}"的好友` : '暂无好友'} {searchQuery
? `没有找到包含"${searchQuery}"的好友`
: "暂无好友"}
</div> </div>
)} )}
{hasMoreFriends && ( {hasMoreFriends && (
<div className={styles.loadMoreWrapper}> <div className={styles.loadMoreWrapper}>
<Button <Button type="link" onClick={handleLoadMore} loading={loading}>
type="link"
onClick={handleLoadMore}
loading={loading}
>
</Button> </Button>
</div> </div>
@@ -307,9 +317,7 @@ const TwoColumnSelection: React.FC<TwoColumnSelectionProps> = ({
</div> </div>
)) ))
) : ( ) : (
<div className={styles.emptySelected}> <div className={styles.emptySelected}></div>
</div>
)} )}
</div> </div>
</div> </div>

View File

@@ -34,14 +34,13 @@ import { useWebSocketStore } from "@/store/module/websocket/websocket";
import styles from "./Person.module.scss"; import styles from "./Person.module.scss";
import { useWeChatStore } from "@/store/module/weChat/weChat"; import { useWeChatStore } from "@/store/module/weChat/weChat";
import FriendSelection from "@/components/FriendSelection"; import FriendSelection from "@/components/FriendSelection";
import TwoColumnSelection from "@/components/FriendSelection/TwoColumnSelection"; import TwoColumnSelection from "@/components/TwoColumnSelection/TwoColumnSelection";
import MemberSelection from "@/components/MemberSelection"; import MemberSelection from "@/components/MemberSelection";
import TwoColumnMemberSelection from "@/components/MemberSelection/TwoColumnMemberSelection"; import TwoColumnMemberSelection from "@/components/MemberSelection/TwoColumnMemberSelection";
import { FriendSelectionItem } from "@/components/FriendSelection/data"; import { FriendSelectionItem } from "@/components/FriendSelection/data";
const { Sider } = Layout; const { Sider } = Layout;
interface PersonProps { interface PersonProps {
contract: ContractData | weChatGroup; contract: ContractData | weChatGroup;
showProfile: boolean; showProfile: boolean;
@@ -64,87 +63,100 @@ const Person: React.FC<PersonProps> = ({
const [newTagValue, setNewTagValue] = useState(""); const [newTagValue, setNewTagValue] = useState("");
// 判断是否为群聊 // 判断是否为群聊
const isGroup = 'chatroomId' in contract; const isGroup = "chatroomId" in contract;
// 群聊相关状态 // 群聊相关状态
const [isEditingGroupName, setIsEditingGroupName] = useState(false); const [isEditingGroupName, setIsEditingGroupName] = useState(false);
const [groupNameValue, setGroupNameValue] = useState(contract.name || ''); const [groupNameValue, setGroupNameValue] = useState(contract.name || "");
const [isEditingGroupNotice, setIsEditingGroupNotice] = useState(false); const [isEditingGroupNotice, setIsEditingGroupNotice] = useState(false);
const [groupNoticeValue, setGroupNoticeValue] = useState(contract.notice || ''); const [groupNoticeValue, setGroupNoticeValue] = useState(
const [isEditingSelfDisplayName, setIsEditingSelfDisplayName] = useState(false); contract.notice || "",
const [selfDisplayNameValue, setSelfDisplayNameValue] = useState(contract.selfDisplyName || ''); );
const [isGroupNoticeModalVisible, setIsGroupNoticeModalVisible] = useState(false); const [isEditingSelfDisplayName, setIsEditingSelfDisplayName] =
useState(false);
const [selfDisplayNameValue, setSelfDisplayNameValue] = useState(
contract.selfDisplyName || "",
);
const [isGroupNoticeModalVisible, setIsGroupNoticeModalVisible] =
useState(false);
const [confirmLoading, setConfirmLoading] = useState(false); const [confirmLoading, setConfirmLoading] = useState(false);
const currentGroupMembers = useWeChatStore(
const currentGroupMembers = useWeChatStore(
state => state.currentGroupMembers, state => state.currentGroupMembers,
); );
const [hoveredMember, setHoveredMember] = useState<string | null>(null); const [hoveredMember, setHoveredMember] = useState<string | null>(null);
const [isAddFriendModalVisible, setIsAddFriendModalVisible] = useState(false); const [isAddFriendModalVisible, setIsAddFriendModalVisible] = useState(false);
const [selectedMember, setSelectedMember] = useState(null); const [selectedMember, setSelectedMember] = useState(null);
const [greeting, setGreeting] = useState(""); const [greeting, setGreeting] = useState("");
// 群管理弹窗状态 // 群管理弹窗状态
const [isFriendSelectionVisible, setIsFriendSelectionVisible] = useState(false); const [isFriendSelectionVisible, setIsFriendSelectionVisible] =
const [isMemberSelectionVisible, setIsMemberSelectionVisible] = useState(false); useState(false);
const [isMemberSelectionVisible, setIsMemberSelectionVisible] =
useState(false);
const [isAdminSelectionVisible, setIsAdminSelectionVisible] = useState(false); const [isAdminSelectionVisible, setIsAdminSelectionVisible] = useState(false);
const [isRemoveAdminSelectionVisible, setIsRemoveAdminSelectionVisible] = useState(false); const [isRemoveAdminSelectionVisible, setIsRemoveAdminSelectionVisible] =
const [isTransferOwnerSelectionVisible, setIsTransferOwnerSelectionVisible] = useState(false); useState(false);
const [selectedFriends, setSelectedFriends] = useState<FriendSelectionItem[]>([]); const [isTransferOwnerSelectionVisible, setIsTransferOwnerSelectionVisible] =
useState(false);
const [selectedFriends, setSelectedFriends] = useState<FriendSelectionItem[]>(
[],
);
const [contractList, setContractList] = useState<any[]>([]); const [contractList, setContractList] = useState<any[]>([]);
const handleAddFriend = (member) => { const handleAddFriend = member => {
setSelectedMember(member); setSelectedMember(member);
setGreeting(`你好, 我来自群聊${contractInfo.name}`); setGreeting(`你好, 我来自群聊${contractInfo.name}`);
setIsAddFriendModalVisible(true); setIsAddFriendModalVisible(true);
}; };
// 群管理操作处理函数 // 群管理操作处理函数
const handleAddMember = (selectedIds: number[], selectedItems: FriendSelectionItem[]) => { const handleAddMember = (
console.log('添加成员:', selectedIds, selectedItems); selectedIds: number[],
sendCommand("CmdChatroomInvite", { selectedItems: FriendSelectionItem[],
wechatChatroomId: contract.id, ) => {
wechatFriendIds: selectedIds console.log("添加成员:", selectedIds, selectedItems);
}); sendCommand("CmdChatroomInvite", {
wechatChatroomId: contract.id,
wechatFriendIds: selectedIds,
});
messageApi.success(`已添加 ${selectedItems.length} 个成员`); messageApi.success(`已添加 ${selectedItems.length} 个成员`);
setIsFriendSelectionVisible(false); setIsFriendSelectionVisible(false);
}; };
//删除群成员 //删除群成员
const handleRemoveMember = (selectedIds: string[]) => { const handleRemoveMember = (selectedIds: string[]) => {
console.log('删除成员:', selectedIds); console.log("删除成员:", selectedIds);
sendCommand("CmdChatroomOperate", { sendCommand("CmdChatroomOperate", {
wechatAccountId: contract.wechatAccountId, wechatAccountId: contract.wechatAccountId,
wechatChatroomId: contract.id, wechatChatroomId: contract.id,
chatroomOperateType: 2, chatroomOperateType: 2,
extra: JSON.stringify({ extra: JSON.stringify({
friendIdList: selectedIds friendIdList: selectedIds,
}) }),
}); });
messageApi.success(`已删除 ${selectedIds.length} 个成员`); messageApi.success(`已删除 ${selectedIds.length} 个成员`);
setIsMemberSelectionVisible(false); setIsMemberSelectionVisible(false);
}; };
//添加管理员 //添加管理员
const handleAddAdmin = (selectedIds: string[]) => { const handleAddAdmin = (selectedIds: string[]) => {
console.log('添加管理员:', selectedIds); console.log("添加管理员:", selectedIds);
sendCommand("CmdChatroomOperate", { sendCommand("CmdChatroomOperate", {
wechatAccountId: contract.wechatAccountId, wechatAccountId: contract.wechatAccountId,
wechatChatroomId: contract.id, wechatChatroomId: contract.id,
chatroomOperateType: 12, chatroomOperateType: 12,
extra: JSON.stringify({ extra: JSON.stringify({
wechatIds: selectedIds wechatIds: selectedIds,
}) }),
}); });
messageApi.success(`已添加 ${selectedIds.length} 个管理员`); messageApi.success(`已添加 ${selectedIds.length} 个管理员`);
setIsAdminSelectionVisible(false); setIsAdminSelectionVisible(false);
}; };
//删除管理员 //删除管理员
const handleRemoveAdmin = (selectedIds: string[]) => { const handleRemoveAdmin = (selectedIds: string[]) => {
console.log('删除管理员:', selectedIds); console.log("删除管理员:", selectedIds);
selectedIds.forEach(wechatId => { selectedIds.forEach(wechatId => {
sendCommand("CmdChatroomOperate", { sendCommand("CmdChatroomOperate", {
@@ -152,8 +164,8 @@ const Person: React.FC<PersonProps> = ({
wechatChatroomId: contract.id, wechatChatroomId: contract.id,
chatroomOperateType: 8, // 8 for remove admin chatroomOperateType: 8, // 8 for remove admin
extra: JSON.stringify({ extra: JSON.stringify({
wechatId: wechatId wechatId: wechatId,
}) }),
}); });
}); });
@@ -164,7 +176,7 @@ const Person: React.FC<PersonProps> = ({
//群主转让 √ //群主转让 √
const handleTransferOwner = (selectedIds: string[]) => { const handleTransferOwner = (selectedIds: string[]) => {
if (selectedIds.length !== 1) { if (selectedIds.length !== 1) {
messageApi.error('只能选择一个成员作为新群主'); messageApi.error("只能选择一个成员作为新群主");
return; return;
} }
sendCommand("CmdChatroomOperate", { sendCommand("CmdChatroomOperate", {
@@ -172,10 +184,10 @@ const Person: React.FC<PersonProps> = ({
wechatChatroomId: contract.id, wechatChatroomId: contract.id,
chatroomOperateType: 10, chatroomOperateType: 10,
extra: JSON.stringify({ extra: JSON.stringify({
wechatId: selectedIds[0] wechatId: selectedIds[0],
}) }),
}); });
messageApi.success('群主转让成功'); messageApi.success("群主转让成功");
setIsTransferOwnerSelectionVisible(false); setIsTransferOwnerSelectionVisible(false);
}; };
@@ -192,19 +204,19 @@ const Person: React.FC<PersonProps> = ({
wechatChatroomId: contract.id, wechatChatroomId: contract.id,
}); });
messageApi.success('好友请求已发送'); messageApi.success("好友请求已发送");
setIsAddFriendModalVisible(false); setIsAddFriendModalVisible(false);
setSelectedMember(null); setSelectedMember(null);
setGreeting(''); setGreeting("");
}; };
// 构建联系人或群聊详细信息 // 构建联系人或群聊详细信息
const kfSelectedUser = useCkChatStore( const kfSelectedUser = useCkChatStore(state =>
state => state.getKfUserInfo(contract.wechatAccountId || 0), state.getKfUserInfo(contract.wechatAccountId || 0),
); );
const getSomeContractList = useCkChatStore( const getSomeContractList = useCkChatStore(
state => state.getSomeContractList, state => state.getSomeContractList,
); );
@@ -240,14 +252,21 @@ const getSomeContractList = useCkChatStore(
setSelectedTags(contract.labels || []); setSelectedTags(contract.labels || []);
if (isGroup) { if (isGroup) {
setGroupNameValue(contract.name || ''); setGroupNameValue(contract.name || "");
setIsEditingGroupName(false); setIsEditingGroupName(false);
setGroupNoticeValue(contract.notice || ''); setGroupNoticeValue(contract.notice || "");
setIsEditingGroupNotice(false); setIsEditingGroupNotice(false);
setSelfDisplayNameValue(contract.selfDisplyName || ''); setSelfDisplayNameValue(contract.selfDisplyName || "");
setIsEditingSelfDisplayName(false); setIsEditingSelfDisplayName(false);
} }
}, [contract.conRemark, contract.labels, contract.name, contract.notice, contract.selfDisplyName, isGroup]); }, [
contract.conRemark,
contract.labels,
contract.name,
contract.notice,
contract.selfDisplyName,
isGroup,
]);
// 处理备注保存 // 处理备注保存
const handleSaveRemark = () => { const handleSaveRemark = () => {
@@ -287,7 +306,7 @@ const getSomeContractList = useCkChatStore(
// 点击编辑群名称按钮 // 点击编辑群名称按钮
const handleEditGroupName = () => { const handleEditGroupName = () => {
setGroupNameValue(contractInfo.name || ''); setGroupNameValue(contractInfo.name || "");
setIsEditingGroupName(true); setIsEditingGroupName(true);
}; };
@@ -311,7 +330,7 @@ const getSomeContractList = useCkChatStore(
// 点击编辑群公告按钮 // 点击编辑群公告按钮
const handleEditGroupNotice = () => { const handleEditGroupNotice = () => {
setGroupNoticeValue(contract.notice || ''); setGroupNoticeValue(contract.notice || "");
setIsGroupNoticeModalVisible(true); setIsGroupNoticeModalVisible(true);
}; };
@@ -330,7 +349,7 @@ const getSomeContractList = useCkChatStore(
// 点击编辑群昵称按钮 // 点击编辑群昵称按钮
const handleEditSelfDisplayName = () => { const handleEditSelfDisplayName = () => {
setSelfDisplayNameValue(contract.selfDisplyName || ''); setSelfDisplayNameValue(contract.selfDisplyName || "");
setIsEditingSelfDisplayName(true); setIsEditingSelfDisplayName(true);
}; };
@@ -594,7 +613,9 @@ const getSomeContractList = useCkChatStore(
<div className={styles.infoItem}> <div className={styles.infoItem}>
<UserOutlined className={styles.infoIcon} /> <UserOutlined className={styles.infoIcon} />
<span className={styles.infoLabel}>:</span> <span className={styles.infoLabel}>:</span>
<span className={styles.infoValue}>{contractInfo.chatroomOwner}</span> <span className={styles.infoValue}>
{contractInfo.chatroomOwner}
</span>
</div> </div>
<div className={styles.infoItem}> <div className={styles.infoItem}>
<UserOutlined className={styles.infoIcon} /> <UserOutlined className={styles.infoIcon} />
@@ -610,7 +631,9 @@ const getSomeContractList = useCkChatStore(
> >
<Input <Input
value={selfDisplayNameValue} value={selfDisplayNameValue}
onChange={e => setSelfDisplayNameValue(e.target.value)} onChange={e =>
setSelfDisplayNameValue(e.target.value)
}
placeholder="请输入群昵称" placeholder="请输入群昵称"
size="small" size="small"
style={{ flex: 1 }} style={{ flex: 1 }}
@@ -627,7 +650,9 @@ const getSomeContractList = useCkChatStore(
size="small" size="small"
icon={<CloseOutlined />} icon={<CloseOutlined />}
onClick={() => { onClick={() => {
setSelfDisplayNameValue(contract.selfDisplyName || ''); setSelfDisplayNameValue(
contract.selfDisplyName || "",
);
setIsEditingSelfDisplayName(false); setIsEditingSelfDisplayName(false);
}} }}
style={{ color: "#ff4d4f" }} style={{ color: "#ff4d4f" }}
@@ -641,7 +666,9 @@ const getSomeContractList = useCkChatStore(
gap: "8px", gap: "8px",
}} }}
> >
<span>{contractInfo.selfDisplyName || "点击添加群昵称"}</span> <span>
{contractInfo.selfDisplyName || "点击添加群昵称"}
</span>
<Button <Button
type="text" type="text"
size="small" size="small"
@@ -671,7 +698,9 @@ const getSomeContractList = useCkChatStore(
<div className={styles.infoItem}> <div className={styles.infoItem}>
<EnvironmentOutlined className={styles.infoIcon} /> <EnvironmentOutlined className={styles.infoIcon} />
<span className={styles.infoLabel}>:</span> <span className={styles.infoLabel}>:</span>
<span className={styles.infoValue}>{contractInfo.region}</span> <span className={styles.infoValue}>
{contractInfo.region}
</span>
</div> </div>
</> </>
)} )}
@@ -815,7 +844,10 @@ const getSomeContractList = useCkChatStore(
)} )}
{/* 个人简介或群公告 */} {/* 个人简介或群公告 */}
<Card title={isGroup ? "群公告" : "个人简介"} className={styles.profileCard}> <Card
title={isGroup ? "群公告" : "个人简介"}
className={styles.profileCard}
>
{isGroup ? ( {isGroup ? (
// 群聊简介(原群公告) // 群聊简介(原群公告)
<div <div
@@ -860,49 +892,58 @@ const getSomeContractList = useCkChatStore(
{isGroup && ( {isGroup && (
<Card title="群成员" className={styles.profileCard}> <Card title="群成员" className={styles.profileCard}>
<div className={styles.groupManagement} style={{ <div
display: 'flex', className={styles.groupManagement}
flexDirection: 'column', style={{
gap: '12px', display: "flex",
marginBottom: '20px', flexDirection: "column",
padding: '12px', gap: "12px",
backgroundColor: '#fafafa', marginBottom: "20px",
borderRadius: '8px', padding: "12px",
border: '1px solid #f0f0f0' backgroundColor: "#fafafa",
}}> borderRadius: "8px",
<div style={{ border: "1px solid #f0f0f0",
display: 'flex', }}
gap: '12px' >
}}> <div
style={{
display: "flex",
gap: "12px",
}}
>
<Button <Button
icon={<PlusOutlined />} icon={<PlusOutlined />}
onClick={async () => { onClick={async () => {
try { try {
const contractData = await getSomeContractList(contract.wechatAccountId); const contractData = await getSomeContractList(
// 转换 ContractData[] 为 FriendSelectionItem[] contract.wechatAccountId,
const friendSelectionData = (contractData || []).map(item => ({ );
id: item.id || item.serverId, // 转换 ContractData[] 为 FriendSelectionItem[]
wechatId: item.wechatId, const friendSelectionData = (contractData || []).map(
nickname: item.nickname, item => ({
avatar: item.avatar || '', id: item.id || item.serverId,
conRemark: item.conRemark, wechatId: item.wechatId,
name: item.conRemark || item.nickname, // 用于搜索显示 nickname: item.nickname,
})); avatar: item.avatar || "",
setContractList(friendSelectionData); conRemark: item.conRemark,
setIsFriendSelectionVisible(true); name: item.conRemark || item.nickname, // 用于搜索显示
} catch (error) { }),
console.error('获取联系人列表失败:', error); );
messageApi.error('获取联系人列表失败'); setContractList(friendSelectionData);
} setIsFriendSelectionVisible(true);
}} } catch (error) {
console.error("获取联系人列表失败:", error);
messageApi.error("获取联系人列表失败");
}
}}
size="small" size="small"
type="primary" type="primary"
ghost ghost
style={{ style={{
flex: 1, flex: 1,
height: '32px', height: "32px",
borderRadius: '6px', borderRadius: "6px",
fontWeight: '500' fontWeight: "500",
}} }}
> >
@@ -916,9 +957,9 @@ const getSomeContractList = useCkChatStore(
danger danger
style={{ style={{
flex: 1, flex: 1,
height: '32px', height: "32px",
borderRadius: '6px', borderRadius: "6px",
fontWeight: '500' fontWeight: "500",
}} }}
> >
@@ -926,10 +967,12 @@ const getSomeContractList = useCkChatStore(
)} )}
</div> </div>
{hasGroupManagePermission() && ( {hasGroupManagePermission() && (
<div style={{ <div
display: 'flex', style={{
gap: '8px' display: "flex",
}}> gap: "8px",
}}
>
<Button <Button
icon={<PlusOutlined />} icon={<PlusOutlined />}
onClick={() => setIsAdminSelectionVisible(true)} onClick={() => setIsAdminSelectionVisible(true)}
@@ -937,9 +980,9 @@ const getSomeContractList = useCkChatStore(
type="default" type="default"
style={{ style={{
flex: 1, flex: 1,
height: '28px', height: "28px",
borderRadius: '4px', borderRadius: "4px",
fontSize: '12px' fontSize: "12px",
}} }}
> >
@@ -951,9 +994,9 @@ const getSomeContractList = useCkChatStore(
type="default" type="default"
style={{ style={{
flex: 1, flex: 1,
height: '28px', height: "28px",
borderRadius: '4px', borderRadius: "4px",
fontSize: '12px' fontSize: "12px",
}} }}
> >
@@ -965,13 +1008,14 @@ const getSomeContractList = useCkChatStore(
type="primary" type="primary"
style={{ style={{
flex: 1, flex: 1,
height: '28px', height: "28px",
borderRadius: '4px', borderRadius: "4px",
fontSize: '12px', fontSize: "12px",
fontWeight: '600', fontWeight: "600",
background: 'linear-gradient(135deg, #1890ff 0%, #096dd9 100%)', background:
border: 'none', "linear-gradient(135deg, #1890ff 0%, #096dd9 100%)",
boxShadow: '0 2px 4px rgba(24, 144, 255, 0.2)' border: "none",
boxShadow: "0 2px 4px rgba(24, 144, 255, 0.2)",
}} }}
> >
@@ -989,16 +1033,20 @@ const getSomeContractList = useCkChatStore(
className={styles.groupMember} className={styles.groupMember}
onMouseEnter={() => setHoveredMember(member.wechatId)} onMouseEnter={() => setHoveredMember(member.wechatId)}
onMouseLeave={() => setHoveredMember(null)} onMouseLeave={() => setHoveredMember(null)}
style={{ display: "flex", alignItems: "center", width: "100%" }} style={{
display: "flex",
alignItems: "center",
width: "100%",
}}
> >
<Avatar size={32} src={member.avatar} /> <Avatar size={32} src={member.avatar} />
<span <span
style={{ style={{
marginLeft: '8px', marginLeft: "8px",
whiteSpace: 'nowrap', whiteSpace: "nowrap",
overflow: 'hidden', overflow: "hidden",
textOverflow: 'ellipsis', textOverflow: "ellipsis",
width: '66%' width: "66%",
}} }}
> >
{member.nickname} {member.nickname}
@@ -1008,7 +1056,7 @@ const getSomeContractList = useCkChatStore(
icon={<PlusOutlined />} icon={<PlusOutlined />}
size="small" size="small"
type="text" type="text"
onClick={(e) => { onClick={e => {
e.stopPropagation(); e.stopPropagation();
handleAddFriend(member); handleAddFriend(member);
}} }}
@@ -1021,30 +1069,33 @@ const getSomeContractList = useCkChatStore(
))} ))}
</div> </div>
<Button type="link" danger block style={{ marginTop: '16px' }} onClick={handleLeaveGroup}> <Button
退 type="link"
</Button> danger
block
</Card> style={{ marginTop: "16px" }}
)} onClick={handleLeaveGroup}
>
<Modal 退
title={`请求添加${selectedMember?.nickname}为好友`} </Button>
visible={isAddFriendModalVisible} </Card>
onOk={handleSendFriendRequest} )}
onCancel={() => setIsAddFriendModalVisible(false)}
okText="确定"
cancelText="取消"
>
<Input.TextArea
value={greeting}
onChange={(e) => setGreeting(e.target.value)}
placeholder="请输入招呼语"
rows={4}
/>
</Modal>
<Modal
title={`请求添加${selectedMember?.nickname}为好友`}
visible={isAddFriendModalVisible}
onOk={handleSendFriendRequest}
onCancel={() => setIsAddFriendModalVisible(false)}
okText="确定"
cancelText="取消"
>
<Input.TextArea
value={greeting}
onChange={e => setGreeting(e.target.value)}
placeholder="请输入招呼语"
rows={4}
/>
</Modal>
</div> </div>
</Sider> </Sider>
@@ -1054,7 +1105,10 @@ const getSomeContractList = useCkChatStore(
open={isGroupNoticeModalVisible} open={isGroupNoticeModalVisible}
onCancel={() => setIsGroupNoticeModalVisible(false)} onCancel={() => setIsGroupNoticeModalVisible(false)}
footer={[ footer={[
<Button key="cancel" onClick={() => setIsGroupNoticeModalVisible(false)}> <Button
key="cancel"
onClick={() => setIsGroupNoticeModalVisible(false)}
>
</Button>, </Button>,
<Button <Button
@@ -1082,7 +1136,10 @@ const getSomeContractList = useCkChatStore(
onCancel={() => setIsFriendSelectionVisible(false)} onCancel={() => setIsFriendSelectionVisible(false)}
onConfirm={(selectedIds, selectedItems) => { onConfirm={(selectedIds, selectedItems) => {
setSelectedFriends(selectedItems); setSelectedFriends(selectedItems);
handleAddMember(selectedIds.map(id => parseInt(id)), selectedItems); handleAddMember(
selectedIds.map(id => parseInt(id)),
selectedItems,
);
}} }}
dataSource={contractList} dataSource={contractList}
title="添加群成员" title="添加群成员"
@@ -1094,7 +1151,7 @@ const getSomeContractList = useCkChatStore(
members={currentGroupMembers.map(member => ({ members={currentGroupMembers.map(member => ({
id: member.wechatId, id: member.wechatId,
nickname: member.nickname, nickname: member.nickname,
avatar: member.avatar avatar: member.avatar,
}))} }))}
onCancel={() => setIsMemberSelectionVisible(false)} onCancel={() => setIsMemberSelectionVisible(false)}
onConfirm={handleRemoveMember} onConfirm={handleRemoveMember}
@@ -1108,7 +1165,7 @@ const getSomeContractList = useCkChatStore(
members={currentGroupMembers.map(member => ({ members={currentGroupMembers.map(member => ({
id: member.wechatId, id: member.wechatId,
nickname: member.nickname, nickname: member.nickname,
avatar: member.avatar avatar: member.avatar,
}))} }))}
onCancel={() => setIsAdminSelectionVisible(false)} onCancel={() => setIsAdminSelectionVisible(false)}
onConfirm={handleAddAdmin} onConfirm={handleAddAdmin}
@@ -1122,7 +1179,7 @@ const getSomeContractList = useCkChatStore(
members={currentGroupMembers.map(member => ({ members={currentGroupMembers.map(member => ({
id: member.wechatId, id: member.wechatId,
nickname: member.nickname, nickname: member.nickname,
avatar: member.avatar avatar: member.avatar,
}))} }))}
onCancel={() => setIsRemoveAdminSelectionVisible(false)} onCancel={() => setIsRemoveAdminSelectionVisible(false)}
onConfirm={handleRemoveAdmin} onConfirm={handleRemoveAdmin}
@@ -1136,7 +1193,7 @@ const getSomeContractList = useCkChatStore(
members={currentGroupMembers.map(member => ({ members={currentGroupMembers.map(member => ({
id: member.wechatId, id: member.wechatId,
nickname: member.nickname, nickname: member.nickname,
avatar: member.avatar avatar: member.avatar,
}))} }))}
onCancel={() => setIsTransferOwnerSelectionVisible(false)} onCancel={() => setIsTransferOwnerSelectionVisible(false)}
onConfirm={handleTransferOwner} onConfirm={handleTransferOwner}