diff --git a/Cunkebao/src/components/MemberSelection/index.tsx b/Cunkebao/src/components/MemberSelection/index.tsx new file mode 100644 index 00000000..06c219b1 --- /dev/null +++ b/Cunkebao/src/components/MemberSelection/index.tsx @@ -0,0 +1,51 @@ +import React, { useState } from 'react'; +import { Modal, Checkbox, Avatar, List, Button } from 'antd'; + +interface MemberSelectionProps { + visible: boolean; + members: { id: string; nickname: string; avatar: string }[]; + onCancel: () => void; + onConfirm: (selectedIds: string[]) => void; +} + +const MemberSelection: React.FC = ({ visible, members, onCancel, onConfirm }) => { + const [selectedIds, setSelectedIds] = useState([]); + + const handleToggle = (id: string) => { + const newSelectedIds = selectedIds.includes(id) + ? selectedIds.filter(memberId => memberId !== id) + : [...selectedIds, id]; + setSelectedIds(newSelectedIds); + }; + + const handleConfirm = () => { + onConfirm(selectedIds); + setSelectedIds([]); + }; + + return ( + + ( + handleToggle(member.id)} style={{ cursor: 'pointer' }}> + } + title={member.nickname} + /> + + + )} + /> + + ); +}; + +export default MemberSelection; \ No newline at end of file diff --git a/Cunkebao/src/pages/pc/ckbox/components/ChatWindow/components/Person/index.tsx b/Cunkebao/src/pages/pc/ckbox/components/ChatWindow/components/Person/index.tsx new file mode 100644 index 00000000..c584cd55 --- /dev/null +++ b/Cunkebao/src/pages/pc/ckbox/components/ChatWindow/components/Person/index.tsx @@ -0,0 +1,708 @@ +import React, { useState, useEffect } from "react"; +import { + Layout, + Input, + Button, + Avatar, + Tooltip, + Card, + Tag, + message, + Modal, +} from "antd"; +import { + PhoneOutlined, + VideoCameraOutlined, + UserOutlined, + TeamOutlined, + MailOutlined, + EnvironmentOutlined, + CalendarOutlined, + BankOutlined, + CloseOutlined, + StarOutlined, + EditOutlined, + CheckOutlined, + PlusOutlined, + NotificationOutlined, +} from "@ant-design/icons"; +import { ContractData, weChatGroup } from "@/pages/pc/ckbox/data"; +import { useCkChatStore } from "@/store/module/ckchat/ckchat"; +import { useWebSocketStore } from "@/store/module/websocket/websocket"; +import styles from "./Person.module.scss"; + +const { Sider } = Layout; + +interface PersonProps { + contract: ContractData | weChatGroup; + showProfile: boolean; + onToggleProfile?: () => void; +} + +const Person: React.FC = ({ + contract, + showProfile, + onToggleProfile, +}) => { + const [messageApi, contextHolder] = message.useMessage(); + const [isEditingRemark, setIsEditingRemark] = useState(false); + const [remarkValue, setRemarkValue] = useState(contract.conRemark || ""); + const [selectedTags, setSelectedTags] = useState( + contract.labels || [], + ); + const [allAvailableTags, setAllAvailableTags] = useState([]); + const [isAddingTag, setIsAddingTag] = useState(false); + const [newTagValue, setNewTagValue] = useState(""); + + // 判断是否为群聊 + const isGroup = 'chatroomId' in contract; + + // 群聊相关状态 + const [isEditingGroupName, setIsEditingGroupName] = useState(false); + 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 kfSelectedUser = useCkChatStore(state => + state.getKfUserInfo(contract.wechatAccountId || 0), + ); + const { sendCommand } = useWebSocketStore(); + + // 获取所有可用标签 + useEffect(() => { + const fetchAvailableTags = async () => { + try { + // 从kfSelectedUser.labels和contract.labels合并获取所有标签 + const kfTags = kfSelectedUser?.labels || []; + const contractTags = contract.labels || []; + const allTags = [...new Set([...kfTags, ...contractTags])]; + setAllAvailableTags(allTags); + } catch (error) { + console.error("获取标签失败:", error); + } + }; + fetchAvailableTags(); + }, [kfSelectedUser, contract.labels]); + + // 当contract变化时更新各种值 + useEffect(() => { + setRemarkValue(contract.conRemark || ""); + setIsEditingRemark(false); + setSelectedTags(contract.labels || []); + + if (isGroup) { + setGroupNameValue(contract.name || ''); + setIsEditingGroupName(false); + setGroupNoticeValue(contract.notice || ''); + setIsEditingGroupNotice(false); + setSelfDisplayNameValue(contract.selfDisplyName || ''); + setIsEditingSelfDisplayName(false); + } + }, [contract.conRemark, contract.labels, contract.name, contract.notice, contract.selfDisplyName, isGroup]); + + // 处理备注保存 + const handleSaveRemark = () => { + if (isGroup) { + // 群聊备注修改 + sendCommand("CmdModifyGroupRemark", { + wechatAccountId: contract.wechatAccountId, + chatroomId: contract.chatroomId, + newRemark: remarkValue, + }); + } else { + // 好友备注修改 + sendCommand("CmdModifyFriendRemark", { + wechatAccountId: contract.wechatAccountId, + wechatFriendId: contract.id, + newRemark: remarkValue, + }); + } + + messageApi.success("备注保存成功"); + setIsEditingRemark(false); + // 更新contract对象中的备注(实际项目中应该通过props回调或状态管理) + }; + + // 处理群名称保存 + const handleSaveGroupName = () => { + sendCommand("CmdChatroomOperate", { + wechatAccountId: contract.wechatAccountId, + wechatChatroomId: contract.id, + chatroomOperateType: 6, + extra: `{\"chatroomName\":\"${groupNameValue}\"}`, + }); + + messageApi.success("群名称修改成功"); + setIsEditingGroupName(false); + }; + + // 点击编辑群名称按钮 + const handleEditGroupName = () => { + setGroupNameValue(contract.name || ''); + setIsEditingGroupName(true); + }; + + // 处理群公告保存 + const handleSaveGroupNotice = () => { + sendCommand("CmdChatroomOperate", { + wechatAccountId: contract.wechatAccountId, + wechatChatroomId: contract.id, + chatroomOperateType: 5, + extra: `{\"announce\":\"${groupNoticeValue}\"}`, + }); + + messageApi.success("群公告修改成功"); + setIsEditingGroupNotice(false); + }; + + // 点击编辑群公告按钮 + const handleEditGroupNotice = () => { + setGroupNoticeValue(contract.notice || ''); + setIsGroupNoticeModalVisible(true); + }; + + // 处理我在本群中的昵称保存 + const handleSaveSelfDisplayName = () => { + sendCommand("CmdChatroomOperate", { + wechatAccountId: contract.wechatAccountId, + wechatChatroomId: contract.id, + chatroomOperateType: 8, + extra: `${selfDisplayNameValue}`, + }); + + messageApi.success("群昵称修改成功"); + setIsEditingSelfDisplayName(false); + }; + + // 点击编辑群昵称按钮 + const handleEditSelfDisplayName = () => { + setSelfDisplayNameValue(contract.selfDisplyName || ''); + setIsEditingSelfDisplayName(true); + }; + + // 处理取消编辑 + const handleCancelEdit = () => { + setRemarkValue(contract.conRemark || ""); + setIsEditingRemark(false); + }; + + // 处理标签点击切换 + const handleTagToggle = (tagName: string) => { + const newSelectedTags = selectedTags.includes(tagName) + ? selectedTags.filter(tag => tag !== tagName) + : [...selectedTags, tagName]; + + setSelectedTags(newSelectedTags); + + // 使用WebSocket发送修改标签命令 + if (isGroup) { + // 群聊标签修改 + sendCommand("CmdModifyGroupLabel", { + labels: newSelectedTags, + seq: +new Date(), + wechatAccountId: contract.wechatAccountId, + chatroomId: contract.chatroomId, + }); + } else { + // 好友标签修改 + sendCommand("CmdModifyFriendLabel", { + labels: newSelectedTags, + seq: +new Date(), + wechatAccountId: contract.wechatAccountId, + wechatFriendId: contract.id, + }); + } + + messageApi.success( + `标签"${tagName}"${selectedTags.includes(tagName) ? "已取消" : "已选中"}`, + ); + }; + + // 处理新增标签 + const handleAddTag = () => { + if (!newTagValue.trim()) { + messageApi.error("请输入标签名称"); + return; + } + + if (allAvailableTags.includes(newTagValue.trim())) { + messageApi.error("标签已存在"); + return; + } + + const newTag = newTagValue.trim(); + + // 添加到可用标签列表 + setAllAvailableTags(prev => [...prev, newTag]); + + // 自动选中新添加的标签 + setSelectedTags(prev => [...prev, newTag]); + + // 使用WebSocket发送新增标签命令 + if (isGroup) { + // 群聊标签修改 + sendCommand("CmdModifyGroupLabel", { + labels: [...selectedTags, newTag], + seq: +new Date(), + wechatAccountId: contract.wechatAccountId, + chatroomId: contract.chatroomId, + }); + } else { + // 好友标签修改 + sendCommand("CmdModifyFriendLabel", { + labels: [...selectedTags, newTag], + seq: +new Date(), + wechatAccountId: contract.wechatAccountId, + wechatFriendId: contract.id || contract.wechatId, + }); + } + + messageApi.success(`标签"${newTag}"添加成功`); + setNewTagValue(""); + setIsAddingTag(false); + }; + + // 处理取消新增标签 + const handleCancelAddTag = () => { + setNewTagValue(""); + setIsAddingTag(false); + }; + + // 构建联系人或群聊详细信息 + const contractInfo = { + name: contract.name || contract.nickname, + nickname: contract.nickname, + conRemark: remarkValue, // 使用当前编辑的备注值 + alias: contract.alias, + wechatId: contract.wechatId, + chatroomId: isGroup ? contract.chatroomId : undefined, + chatroomOwner: isGroup ? contract.chatroomOwner : undefined, + avatar: contract.avatar || contract.chatroomAvatar, + phone: contract.phone || "-", + email: contract.email || "-", + department: contract.department || "-", + position: contract.position || "-", + company: contract.company || "-", + region: contract.region || "-", + joinDate: contract.joinDate || "-", + notice: isGroup ? contract.notice : undefined, + selfDisplyName: isGroup ? contract.selfDisplyName : undefined, + status: "在线", + tags: selectedTags, + bio: contract.bio || contract.signature || "-", + }; + + if (!showProfile) { + return null; + } + + return ( + <> + {contextHolder} + +
+ {/* 关闭按钮 */} +
+
+ + {/* 头像和基本信息 */} +
+ } + /> +
+ {isGroup && isEditingGroupName ? ( +
+ setGroupNameValue(e.target.value)} + placeholder="请输入群名称" + size="small" + style={{ flex: 1 }} + /> +
+ ) : ( + +
+

+ {contractInfo.nickname || contractInfo.name} +

+ {isGroup && ( +
+
+ )} + +
+ + {contractInfo.status} +
+
+
+ + {/* 详细信息卡片 */} + + {isGroup ? ( + // 群聊信息 + <> +
+ + 群ID: + + {contractInfo.chatroomId} + +
+
+ + 群主: + {contractInfo.chatroomOwner} +
+
+ + 群昵称: +
+ {isEditingSelfDisplayName ? ( +
+ setSelfDisplayNameValue(e.target.value)} + placeholder="请输入群昵称" + size="small" + style={{ flex: 1 }} + /> +
+ ) : ( +
+ {contractInfo.selfDisplyName || "点击添加群昵称"} +
+ )} +
+
+ + ) : ( + // 好友信息 + <> +
+ + 微信号: + + {contractInfo.alias || contractInfo.wechatId} + +
+
+ + 电话: + {contractInfo.phone} +
+
+ + 地区: + {contractInfo.region} +
+ + )} + {!isGroup && ( +
+ + 备注: +
+ {isEditingRemark ? ( +
+ setRemarkValue(e.target.value)} + placeholder="请输入备注" + size="small" + style={{ flex: 1 }} + /> +
+ ) : ( +
+ {contractInfo.conRemark || "点击添加备注"} +
+ )} +
+
+ )} +
+ + {/* 标签 - 仅在非群聊时显示 */} + {!isGroup && ( + +
+ {/* 渲染所有可用标签,选中的排在前面 */} + {[...new Set([...selectedTags, ...allAvailableTags])].map( + (tag, index) => { + const isSelected = selectedTags.includes(tag); + return ( + handleTagToggle(tag)} + > + {tag} + + ); + }, + )} + + {/* 新增标签区域 */} + {isAddingTag ? ( +
+ setNewTagValue(e.target.value)} + placeholder="请输入标签名称" + size="small" + style={{ width: "120px" }} + onPressEnter={handleAddTag} + /> +
+ ) : ( + setIsAddingTag(true)} + > + 新增标签 + + )} + + {allAvailableTags.length === 0 && !isAddingTag && ( + + 暂无可用标签 + + )} +
+
+ )} + + {/* 个人简介或群公告 */} + + {isGroup ? ( + // 群聊简介(原群公告) +
+
+
+ {contractInfo.notice || "点击添加群公告"} +
+
+ ) : ( + // 个人简介 +

{contractInfo.bio}

+ )} + + + {/* 操作按钮 */} +
+ + +
+
+
+
+ + {/* 群公告编辑弹窗 */} + setIsGroupNoticeModalVisible(false)} + footer={[ + , + , + ]} + > + setGroupNoticeValue(e.target.value)} + placeholder="请输入内容" + rows={6} + style={{ width: '100%' }} + /> + + + ); +}; + +export default Person; diff --git a/Cunkebao/src/pages/pc/ckbox/components/ChatWindow/components/ProfileCard/Person.module.scss b/Cunkebao/src/pages/pc/ckbox/components/ChatWindow/components/ProfileCard/Person.module.scss index 10fb299b..1ef28153 100644 --- a/Cunkebao/src/pages/pc/ckbox/components/ChatWindow/components/ProfileCard/Person.module.scss +++ b/Cunkebao/src/pages/pc/ckbox/components/ChatWindow/components/ProfileCard/Person.module.scss @@ -168,6 +168,31 @@ } } + .groupManagement { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin-bottom: 16px; + } + + .groupMemberList { + .groupMember { + display: flex; + align-items: center; + margin-bottom: 12px; + + &:last-child { + margin-bottom: 0; + } + + span { + margin-left: 8px; + font-size: 14px; + color: #262626; + } + } + } + .profileActions { margin-top: auto; padding-top: 16px; diff --git a/Cunkebao/src/pages/pc/ckbox/components/ChatWindow/components/ProfileCard/index.tsx b/Cunkebao/src/pages/pc/ckbox/components/ChatWindow/components/ProfileCard/index.tsx index 3803956f..cca918b2 100644 --- a/Cunkebao/src/pages/pc/ckbox/components/ChatWindow/components/ProfileCard/index.tsx +++ b/Cunkebao/src/pages/pc/ckbox/components/ChatWindow/components/ProfileCard/index.tsx @@ -25,6 +25,8 @@ import { CheckOutlined, PlusOutlined, NotificationOutlined, + MinusOutlined, + SwapOutlined, } from "@ant-design/icons"; import { ContractData, weChatGroup } from "@/pages/pc/ckbox/data"; import { useCkChatStore } from "@/store/module/ckchat/ckchat"; @@ -65,6 +67,66 @@ const Person: React.FC = ({ const [isEditingSelfDisplayName, setIsEditingSelfDisplayName] = useState(false); const [selfDisplayNameValue, setSelfDisplayNameValue] = useState(contract.selfDisplyName || ''); const [isGroupNoticeModalVisible, setIsGroupNoticeModalVisible] = useState(false); + const [confirmLoading, setConfirmLoading] = useState(false); + const [groupMembers, setGroupMembers] = useState([ + { + "friendId": 17453058, + "wechatId": "WANGMINGZHENG000", + "nickname": "wong", + "avatar": " https://wx.qlogo.cn/mmhead/ver_1/W67xuTtrYxgP80VoJGiceswibsxibqhrC06ib8Lh49pwV3ibibdqfXaDvRD4obSWdVibkdPOHWaedqviazEiasAiciaib3HJrvv7C0yyKtMosCbWxLcNWtXuN0WPicKKaTrQMe1NicQ20G/0 ", + "isAdmin": false, + "isDeleted": false, + "deletedDate": "0001-01-01T00:00:00" + }, + { + "friendId": 10411197, + "wechatId": "wxid_480es52qsj2812", + "nickname": "老坑爹- 解放双手,释放时间", + "avatar": " https://wx.qlogo.cn/mmhead/ver_1/r7xs2IJVd2Yhkd7yObdJzJkkiayOahjHNKtCZdiaECWyqR0XBqqlhE46UwT7hPZSf7QzplQiadVFuZtMIBL1LSliaJBK2azvL9PPyPT8MEHZQMA/0 ", + "isAdmin": false, + "isDeleted": false, + "deletedDate": "0001-01-01T00:00:00" + }, + { + "friendId": 21168549, + "wechatId": "wxid_dlhi90odctcl22", + "nickname": "许永平", + "avatar": " https://wx.qlogo.cn/mmhead/ver_1/KF8xrYxmYgHbdZpaPw78NFx7RibwWv1jsy5dlLEjgBDYkLBv0dadXSyLHicI218a34G3pMVhOsy1jA0QrDDKicSsYyGMzkdOT2xbwSpw0LKbvQ7yPtibJgrNPsbia0MYbHZXb/0 ", + "isAdmin": false, + "isDeleted": false, + "deletedDate": "2025-08-26T15:42:54.9914073+08:00" + } + ]); + + const [hoveredMember, setHoveredMember] = useState(null); + const [isAddFriendModalVisible, setIsAddFriendModalVisible] = useState(false); + const [selectedMember, setSelectedMember] = useState(null); + const [greeting, setGreeting] = useState(""); + + const handleAddFriend = (member) => { + setSelectedMember(member); + setGreeting(`你好, 我来自群聊${contractInfo.name}`); + setIsAddFriendModalVisible(true); + }; + + const handleSendFriendRequest = () => { + if (!selectedMember) return; + + sendCommand("CmdChatroomOperate", { + chatroomOperateTyp: 1, + extra: JSON.stringify({ + wechatId: selectedMember.wechatId, + sendWord: greeting, + }), + wechatAccountId: contract.wechatAccountId, + wechatChatroomId: contract.id, + }); + + messageApi.success('好友请求已发送'); + setIsAddFriendModalVisible(false); + setSelectedMember(null); + setGreeting(''); + }; // 构建联系人或群聊详细信息 @@ -134,7 +196,7 @@ const Person: React.FC = ({ wechatAccountId: contract.wechatAccountId, wechatChatroomId: contract.id, chatroomOperateType: 6, - extra: `{\"chatroomName\":\"${groupNameValue}\"}`, + extra: `{"chatroomName":"${groupNameValue}"}`, }); messageApi.success("群名称修改成功"); @@ -143,21 +205,26 @@ const Person: React.FC = ({ // 点击编辑群名称按钮 const handleEditGroupName = () => { - setGroupNameValue(contract.name || ''); + setGroupNameValue(contractInfo.name || ''); setIsEditingGroupName(true); }; // 处理群公告保存 const handleSaveGroupNotice = () => { + setConfirmLoading(true); sendCommand("CmdChatroomOperate", { wechatAccountId: contract.wechatAccountId, wechatChatroomId: contract.id, chatroomOperateType: 5, - extra: `{\"announce\":\"${groupNoticeValue}\"}`, + extra: `{"announce":"${groupNoticeValue}"}`, }); - messageApi.success("群公告修改成功"); - setIsEditingGroupNotice(false); + // 模拟延迟 + setTimeout(() => { + messageApi.success("群公告修改成功"); + setIsGroupNoticeModalVisible(false); + setConfirmLoading(false); + }, 1000); }; // 点击编辑群公告按钮 @@ -273,6 +340,29 @@ const Person: React.FC = ({ setIsAddingTag(false); }; + // 处理退出群聊 + const handleLeaveGroup = () => { + Modal.confirm({ + title: "确定要退出群聊吗?", + content: "退出后将不再接收此群聊消息。", + okText: "确定", + cancelText: "取消", + onOk: () => { + sendCommand("CmdChatroomOperate", { + wechatAccountId: contract.wechatAccountId, + wechatChatroomId: contract.id, + chatroomOperateType: 4, // 4 for quit + extra: "", + }); + messageApi.success("已退出群聊"); + // 可能还需要一个回调来关闭侧边栏或切换到另一个聊天 + if (onToggleProfile) { + onToggleProfile(); + } + }, + }); + }; + // 构建联系人或群聊详细信息 const contractInfo = { name: contract.name || contract.nickname, @@ -317,71 +407,28 @@ const Person: React.FC = ({ {/* 头像和基本信息 */} -
+
} /> -
- {isGroup && isEditingGroupName ? ( -
- setGroupNameValue(e.target.value)} - placeholder="请输入群名称" - size="small" - style={{ flex: 1 }} - /> -
- ) : ( - -
-

- {contractInfo.nickname || contractInfo.name} -

- {isGroup && ( -
-
- )} - +
{contractInfo.status}
+ +

+ {contractInfo.nickname || contractInfo.name} +

+
@@ -390,6 +437,72 @@ const Person: React.FC = ({ {isGroup ? ( // 群聊信息 <> +
+ + 群名称: +
+ {isEditingGroupName ? ( +
+ setGroupNameValue(e.target.value)} + placeholder="请输入群名称" + size="small" + style={{ flex: 1 }} + /> +
+ ) : ( +
+ +

+ {contractInfo.nickname || contractInfo.name} +

+
+
+ )} +
+
群ID: @@ -624,49 +737,39 @@ const Person: React.FC = ({ {isGroup ? ( // 群聊简介(原群公告) -
- {isEditingGroupNotice ? ( +
{ + setGroupNoticeValue(contractInfo.notice || ""); + setIsGroupNoticeModalVisible(true); + }} + style={{ cursor: "pointer" }} + > +
- setGroupNoticeValue(e.target.value)} - placeholder="请输入内容" - rows={6} - style={{ width: '100%' }} - /> + {contractInfo.notice || "点击添加群公告"}
- ) : ( -
-
- {contractInfo.notice || "点击添加群公告"} -
-
- )} +
) : ( // 个人简介 @@ -674,6 +777,59 @@ const Person: React.FC = ({ )} + {isGroup && ( + +
+ + + + + +
+
+ {groupMembers.map(member => ( +
setHoveredMember(member.friendId)} + onMouseLeave={() => setHoveredMember(null)} + > + + {member.nickname} + {hoveredMember === member.friendId && ( +
+ ))} +
+ +
+ )} + + setIsAddFriendModalVisible(false)} + okText="确定" + cancelText="取消" + > + setGreeting(e.target.value)} + placeholder="请输入招呼语" + rows={4} + /> + + {/* 操作按钮 */}
, - , @@ -716,7 +870,6 @@ const Person: React.FC = ({ onChange={e => setGroupNoticeValue(e.target.value)} placeholder="请输入内容" rows={6} - style={{ width: '100%' }} />