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

View File

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

View File

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