refactor: 重构TwoColumnSelection组件并移动至新目录
将TwoColumnSelection组件从FriendSelection目录移动到新的TwoColumnSelection目录 优化组件代码格式和样式文件结构 更新相关引用路径
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user