diff --git a/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageRecord/MessageRecord.module.scss b/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageRecord/MessageRecord.module.scss index 99f889ae..d20bd680 100644 --- a/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageRecord/MessageRecord.module.scss +++ b/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageRecord/MessageRecord.module.scss @@ -49,6 +49,7 @@ .messageItem { display: flex; margin-bottom: 12px; + align-items: flex-start; &.ownMessage { justify-content: flex-end; @@ -77,6 +78,15 @@ } } +// Checkbox 容器 +.checkboxContainer { + display: flex; + align-items: flex-start; + margin-right: 8px; + margin-top: 4px; + flex-shrink: 0; +} + // 消息内容容器 .messageContent { display: flex; diff --git a/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageRecord/components/ClickMeau/index.tsx b/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageRecord/components/ClickMeau/index.tsx index bcd19fce..4dff012a 100644 --- a/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageRecord/components/ClickMeau/index.tsx +++ b/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageRecord/components/ClickMeau/index.tsx @@ -2,10 +2,8 @@ import React, { useState, useEffect, useRef } from "react"; import { Menu, message } from "antd"; import { CopyOutlined, - DeleteOutlined, CheckSquareOutlined, RollbackOutlined, - ReloadOutlined, ExportOutlined, LinkOutlined, } from "@ant-design/icons"; @@ -18,10 +16,7 @@ interface ClickMenuProps { y: number; messageData: ChatRecord | null; onClose: () => void; - onCopy?: (content: string) => void; - onDelete?: (messageId: string) => void; - onForward?: (messageData: ChatRecord) => void; - onRetry?: (messageData: ChatRecord) => void; + onCommad: (action: string) => void; } const ClickMenu: React.FC = ({ @@ -30,10 +25,7 @@ const ClickMenu: React.FC = ({ y, messageData, onClose, - onCopy, - onDelete, - onForward, - onRetry, + onCommad, }) => { const menuRef = useRef(null); const [position, setPosition] = useState({ x, y }); @@ -90,10 +82,9 @@ const ClickMenu: React.FC = ({ } const handleCopy = () => { - if (messageData.content && onCopy) { + if (messageData.content) { // 提取纯文本内容,去除HTML标签 const textContent = messageData.content.replace(/<[^>]*>/g, ""); - onCopy(textContent); navigator.clipboard .writeText(textContent) .then(() => { @@ -106,75 +97,34 @@ const ClickMenu: React.FC = ({ onClose(); }; - const handleDelete = () => { - if (messageData.id && onDelete) { - onDelete(messageData.id.toString()); - message.success("消息已删除"); - } - onClose(); - }; - - const handleForward = () => { - if (onForward) { - onForward(messageData); - message.info("转发功能待实现"); - } - onClose(); - }; - - const handleRetry = () => { - if (onRetry) { - onRetry(messageData); - message.info("重新发送"); - } - onClose(); - }; - const menuItems = [ { - key: "copy", + key: "transmit", icon: , label: "转发", - onClick: handleCopy, - disabled: !messageData.content || messageData.msgType === 3, // 图片消息不能复制文本 - }, - { - key: "forward", - icon: , - label: "复制", - onClick: handleForward, }, { key: "copy", + icon: , + label: "复制", + }, + { + key: "multipleForwarding", icon: , label: "多条转发", - onClick: handleCopy, - disabled: !messageData.content || messageData.msgType === 3, // 图片消息不能复制文本 }, { - key: "delete", + key: "quote", icon: , label: "引用", - onClick: handleDelete, }, { - key: "delete", + key: "recall", icon: , label: "撤回", - onClick: handleDelete, }, ]; - // 如果是自己发送的消息且发送失败,显示重试选项 - if (messageData.isSend && messageData.status === "failed") { - menuItems.unshift({ - key: "retry", - icon: , - label: "重新发送", - onClick: handleRetry, - }); - } - return (
= ({ }} > ({ + ...item, + onClick: value => { + if (value.key === "copy") { + handleCopy(); + } else { + onCommad(value.key); + } + }, + }))} mode="vertical" selectable={false} className={styles.menu} diff --git a/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageRecord/index.tsx b/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageRecord/index.tsx index a2dc5dbf..8417cd81 100644 --- a/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageRecord/index.tsx +++ b/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageRecord/index.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useRef, useState } from "react"; -import { Avatar } from "antd"; +import { Avatar, Checkbox } from "antd"; import { UserOutlined, LoadingOutlined } from "@ant-design/icons"; import AudioMessage from "./components/AudioMessage/AudioMessage"; import SmallProgramMessage from "./components/SmallProgramMessage"; @@ -10,13 +10,12 @@ import { formatWechatTime } from "@/utils/common"; import { getEmojiPath } from "@/components/EmojiSeclection/wechatEmoji"; import styles from "./MessageRecord.module.scss"; import { useWeChatStore } from "@/store/module/weChat/weChat"; - +import { useCkChatStore } from "@/store/module/ckchat/ckchat"; interface MessageRecordProps { contract: ContractData | weChatGroup; } const MessageRecord: React.FC = ({ contract }) => { const messagesEndRef = useRef(null); - // 右键菜单状态 const [contextMenu, setContextMenu] = useState({ visible: false, @@ -25,6 +24,9 @@ const MessageRecord: React.FC = ({ contract }) => { messageData: null as ChatRecord | null, }); + // 选中的聊天记录状态 + const [selectedRecords, setSelectedRecords] = useState([]); + const currentMessages = useWeChatStore(state => state.currentMessages); const loadChatMessages = useWeChatStore(state => state.loadChatMessages); const messagesLoading = useWeChatStore(state => state.messagesLoading); @@ -32,8 +34,13 @@ const MessageRecord: React.FC = ({ contract }) => { const currentGroupMembers = useWeChatStore( state => state.currentGroupMembers, ); + const showCheckbox = useWeChatStore(state => state.showCheckbox); const prevMessagesRef = useRef(currentMessages); - + const updateShowCheckbox = useWeChatStore(state => state.updateShowCheckbox); + const updateEnterModule = useWeChatStore(state => state.updateEnterModule); + const currentKf = useCkChatStore(state => + state.kfUserList.find(kf => kf.id === state.kfSelected), + ); // 判断是否为表情包URL的工具函数 const isEmojiUrl = (content: string): boolean => { return ( @@ -503,6 +510,22 @@ const MessageRecord: React.FC = ({ contract }) => { console.log("重试发送:", messageData); }; + // 处理checkbox选中状态变化 + const handleCheckboxChange = (checked: boolean, msg: ChatRecord) => { + if (checked) { + // 添加到选中记录 + setSelectedRecords(prev => [...prev, msg]); + } else { + // 从选中记录中移除 + setSelectedRecords(prev => prev.filter(record => record.id !== msg.id)); + } + }; + + // 检查消息是否被选中 + const isMessageSelected = (msg: ChatRecord) => { + return selectedRecords.some(record => record.id === msg.id); + }; + // 用于分组消息并添加时间戳的辅助函数 const groupMessagesByTime = (messages: ChatRecord[]) => { return messages @@ -532,6 +555,15 @@ const MessageRecord: React.FC = ({ contract }) => { {/* 如果不是群聊 */} {!isGroup && !isOwn && ( <> + {/* Checkbox 显示控制 */} + {showCheckbox && ( +
+ handleCheckboxChange(e.target.checked, msg)} + /> +
+ )} = ({ contract }) => { {/* 如果是群聊 */} {isGroup && !isOwn && ( <> + {/* Checkbox 显示控制 */} + {showCheckbox && ( +
+ handleCheckboxChange(e.target.checked, msg)} + /> +
+ )} = ({ contract }) => { )} {isOwn && ( <> + {/* Checkbox 显示控制 */} + {showCheckbox && ( +
+ handleCheckboxChange(e.target.checked, msg)} + /> +
+ )} } className={styles.messageAvatar} /> @@ -617,6 +667,26 @@ const MessageRecord: React.FC = ({ contract }) => { loadChatMessages(false, timestamp); }; + const handCommad = (action: string) => { + switch (action) { + case "transmit": + handleForwardMessage(contextMenu.messageData); + break; + case "multipleForwarding": + // 多条转发逻辑 + updateShowCheckbox(!showCheckbox); + updateEnterModule(!showCheckbox ? "common" : "multipleForwarding"); + break; + case "quote": + // 引用逻辑 + break; + case "recall": + // 撤回逻辑 + break; + default: + break; + } + }; return (
@@ -638,7 +708,6 @@ const MessageRecord: React.FC = ({ contract }) => { {group.messages .filter(v => ![10000].includes(v.msgType)) .map(msg => { - console.log("Rendering message with msgType:", msg.msgType); return renderMessage(msg); })} @@ -652,10 +721,7 @@ const MessageRecord: React.FC = ({ contract }) => { y={contextMenu.y} messageData={contextMenu.messageData} onClose={handleCloseContextMenu} - onCopy={handleCopyMessage} - onDelete={handleDeleteMessage} - onForward={handleForwardMessage} - onRetry={handleRetryMessage} + onCommad={handCommad} />
); diff --git a/Touchkebao/src/store/module/weChat/weChat.data.ts b/Touchkebao/src/store/module/weChat/weChat.data.ts index 4060245e..3591cce7 100644 --- a/Touchkebao/src/store/module/weChat/weChat.data.ts +++ b/Touchkebao/src/store/module/weChat/weChat.data.ts @@ -21,6 +21,11 @@ export interface WeChatState { messagesLoading: boolean; isLoadingData: boolean; currentGroupMembers: any[]; + showCheckbox: boolean; + updateShowCheckbox: (show: boolean) => void; + EnterModule: string; + // EnterModule 相关方法 + updateEnterModule: (module: string) => void; MomentCommon: FriendsCircleItem[]; // MomentCommon 相关方法 clearMomentCommon: () => void; diff --git a/Touchkebao/src/store/module/weChat/weChat.ts b/Touchkebao/src/store/module/weChat/weChat.ts index b96a26e5..331b3f07 100644 --- a/Touchkebao/src/store/module/weChat/weChat.ts +++ b/Touchkebao/src/store/module/weChat/weChat.ts @@ -28,6 +28,14 @@ export const useWeChatStore = create()( messagesLoading: false, isLoadingData: false, currentGroupMembers: [], + showCheckbox: false, + updateShowCheckbox: (show: boolean) => { + set({ showCheckbox: show }); + }, + EnterModule: "common", + updateEnterModule: (module: string) => { + set({ EnterModule: module }); + }, MomentCommon: [], //朋友圈数据 MomentCommonLoading: false, //朋友圈数据是否正在加载 @@ -329,3 +337,5 @@ export const useCurrentMessages = () => useWeChatStore(state => state.currentMessages); export const useMessagesLoading = () => useWeChatStore(state => state.messagesLoading); +export const useShowCheckbox = () => + useWeChatStore(state => state.showCheckbox);