From d5e609aa3751c182aa66e278b40cad37a25690b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B6=85=E7=BA=A7=E8=80=81=E7=99=BD=E5=85=94?= Date: Tue, 2 Sep 2025 15:21:54 +0800 Subject: [PATCH 01/29] =?UTF-8?q?feat(=E8=81=8A=E5=A4=A9=E7=AA=97=E5=8F=A3?= =?UTF-8?q?):=20=E9=87=8D=E6=9E=84=E6=B6=88=E6=81=AF=E8=BE=93=E5=85=A5?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=E5=B9=B6=E6=B7=BB=E5=8A=A0=E5=BE=AE=E4=BF=A1?= =?UTF-8?q?=E9=A3=8E=E6=A0=BC=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将消息输入功能从ChatWindow组件中拆分为独立的MessageEnter组件 添加微信风格的样式和交互效果 新增消息处理逻辑和素材选择功能 重命名getMessages为getChatMessages以保持命名一致性 --- Cunkebao/src/pages/pc/ckbox/api.ts | 15 +- .../ChatWindow/ChatWindow.module.scss | 130 -------- .../MessageEnter/MessageEnter.module.scss | 181 ++++++++++ .../components/MessageEnter/index.tsx | 310 ++++++++++++++++++ .../pc/ckbox/components/ChatWindow/index.tsx | 305 +---------------- .../src/store/module/websocket/msgManage.ts | 16 + 6 files changed, 517 insertions(+), 440 deletions(-) create mode 100644 Cunkebao/src/pages/pc/ckbox/components/ChatWindow/components/MessageEnter/MessageEnter.module.scss diff --git a/Cunkebao/src/pages/pc/ckbox/api.ts b/Cunkebao/src/pages/pc/ckbox/api.ts index 1d27fdb0..9bf2e54c 100644 --- a/Cunkebao/src/pages/pc/ckbox/api.ts +++ b/Cunkebao/src/pages/pc/ckbox/api.ts @@ -23,7 +23,7 @@ export function clearUnreadCount(params) { return request("/api/WechatFriend/clearUnreadCount", params, "PUT"); } //获取聊天记录-2 获取列表 -export function getMessages(params: { +export function getChatMessages(params: { wechatAccountId: number; wechatFriendId?: number; wechatChatroomId?: number; @@ -73,19 +73,6 @@ export const getControlTerminalList = params => { return request("/api/wechataccount", params, "GET"); }; -// 搜索联系人 -export const getChatMessage = (params: { - wechatAccountId: number; - wechatFriendId: number; - From: number; - To: number; - Count: number; - olderData: boolean; - keyword: string; -}) => { - return request("/api/FriendMessage/SearchMessage", params, "GET"); -}; - // 获取聊天历史 export const getChatHistory = ( chatId: string, diff --git a/Cunkebao/src/pages/pc/ckbox/components/ChatWindow/ChatWindow.module.scss b/Cunkebao/src/pages/pc/ckbox/components/ChatWindow/ChatWindow.module.scss index c2515179..355cb2a4 100644 --- a/Cunkebao/src/pages/pc/ckbox/components/ChatWindow/ChatWindow.module.scss +++ b/Cunkebao/src/pages/pc/ckbox/components/ChatWindow/ChatWindow.module.scss @@ -128,127 +128,8 @@ } } -.chatFooter { - background: #fff; - border-top: 1px solid #f0f0f0; - padding: 0; - height: auto; - min-height: auto; - flex-shrink: 0; - .inputContainer { - .inputToolbar { - display: flex; - border-bottom: 1px solid #f0f0f0; - background: #fafafa; - justify-content: space-between; - .leftTool { - display: flex; - gap: 4px; - } - - .rightTool { - display: flex; - gap: 8px; - padding: 8px; - } - - .toolbarButton { - color: #666; - border: none; - padding: 8px; - border-radius: 4px; - font-size: 18px; - width: 36px; - height: 36px; - display: flex; - align-items: center; - justify-content: center; - background: transparent; - transition: all 0.2s; - - &:hover { - color: #1890ff; - background: #e6f7ff; - } - - &:active { - background: #bae7ff; - } - } - } - - .inputArea { - display: flex; - padding: 12px 16px; - gap: 8px; - align-items: flex-end; - background: #fff; - - .messageInput { - flex: 1; - border: 1px solid #d9d9d9; - border-radius: 4px; - resize: none; - padding: 8px 12px; - font-size: 14px; - line-height: 1.5; - min-height: 36px; - max-height: 120px; - background: #fff; - transition: all 0.2s; - - &:focus { - border-color: #1890ff; - box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2); - outline: none; - } - - &::placeholder { - color: #bfbfbf; - } - } - - .sendButton { - border-radius: 4px; - height: 36px; - padding: 0 16px; - font-size: 14px; - font-weight: 500; - background: #1890ff; - border: 1px solid #1890ff; - color: #fff; - transition: all 0.2s; - - &:hover { - background: #40a9ff; - border-color: #40a9ff; - } - - &:active { - background: #096dd9; - border-color: #096dd9; - } - - &:disabled { - background: #f5f5f5; - border-color: #d9d9d9; - color: #bfbfbf; - cursor: not-allowed; - } - } - } - - .inputHint { - padding: 4px 16px 8px; - font-size: 12px; - color: #8c8c8c; - background: #fff; - border-top: 1px solid #f0f0f0; - } - } -} // 右侧个人资料卡片 .profileSider { @@ -748,18 +629,7 @@ } } - .chatFooter { - padding: 12px; - .inputContainer { - .inputArea { - .sendButton { - height: 28px; - padding: 0 12px; - } - } - } - } .messageItem { .messageContent { diff --git a/Cunkebao/src/pages/pc/ckbox/components/ChatWindow/components/MessageEnter/MessageEnter.module.scss b/Cunkebao/src/pages/pc/ckbox/components/ChatWindow/components/MessageEnter/MessageEnter.module.scss new file mode 100644 index 00000000..36977bd1 --- /dev/null +++ b/Cunkebao/src/pages/pc/ckbox/components/ChatWindow/components/MessageEnter/MessageEnter.module.scss @@ -0,0 +1,181 @@ +// MessageEnter 组件样式 - 微信风格 +.chatFooter { + background: #f7f7f7; + border-top: 1px solid #e1e1e1; + padding: 0; + height: auto; + min-height: 100px; +} + +.inputContainer { + padding: 8px 12px; + display: flex; + flex-direction: column; + gap: 6px; +} + +.inputToolbar { + display: flex; + justify-content: space-between; + align-items: center; + padding: 4px 0; + border-bottom: none; +} + +.leftTool { + display: flex; + gap: 2px; + align-items: center; +} + +.toolbarButton { + width: 28px; + height: 28px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + color: #666; + font-size: 16px; + transition: all 0.15s; + border: none; + background: transparent; + + &:hover { + background: #e6e6e6; + color: #333; + } + + &:active { + background: #d9d9d9; + } +} + +.rightTool { + display: flex; + gap: 12px; + align-items: center; +} + +.rightToolItem { + display: flex; + align-items: center; + gap: 3px; + color: #666; + font-size: 11px; + cursor: pointer; + padding: 3px 6px; + border-radius: 3px; + transition: all 0.15s; + + &:hover { + background: #e6e6e6; + color: #333; + } +} + +.inputArea { + display: flex; + flex-direction: column; + padding: 4px 0; +} + +.inputWrapper { + border: 1px solid #d1d1d1; + border-radius: 4px; + background: #fff; + overflow: hidden; + + &:focus-within { + border-color: #07c160; + } +} + +.messageInput { + width: 100%; + border: none; + resize: none; + font-size: 13px; + line-height: 1.4; + padding: 8px 10px; + background: transparent; + + &:focus { + box-shadow: none; + outline: none; + } + + &::placeholder { + color: #b3b3b3; + } +} + +.sendButtonArea { + padding: 8px 10px; + display: flex; + justify-content: flex-end; +} + +.sendButton { + height: 32px; + border-radius: 4px; + font-weight: normal; + min-width: 60px; + font-size: 13px; + background: #07c160; + border-color: #07c160; + + &:hover { + background: #06ad56; + border-color: #06ad56; + } + + &:active { + background: #059748; + border-color: #059748; + } + + &:disabled { + background: #b3b3b3; + border-color: #b3b3b3; + opacity: 1; + } +} + +.inputHint { + font-size: 11px; + color: #999; + text-align: right; + margin-top: 2px; +} + +// 响应式设计 +@media (max-width: 768px) { + .inputContainer { + padding: 8px 12px; + } + + .inputToolbar { + flex-wrap: wrap; + gap: 8px; + } + + .rightTool { + gap: 8px; + } + + .rightToolItem { + font-size: 11px; + padding: 2px 6px; + } + + .inputArea { + flex-direction: column; + gap: 8px; + } + + .sendButton { + align-self: flex-end; + min-width: 60px; + } +} diff --git a/Cunkebao/src/pages/pc/ckbox/components/ChatWindow/components/MessageEnter/index.tsx b/Cunkebao/src/pages/pc/ckbox/components/ChatWindow/components/MessageEnter/index.tsx index e69de29b..e869a45d 100644 --- a/Cunkebao/src/pages/pc/ckbox/components/ChatWindow/components/MessageEnter/index.tsx +++ b/Cunkebao/src/pages/pc/ckbox/components/ChatWindow/components/MessageEnter/index.tsx @@ -0,0 +1,310 @@ +import React, { useState } from "react"; +import { Layout, Input, Button, Dropdown, Menu, Tooltip, Modal } from "antd"; +import { + ShareAltOutlined, + SendOutlined, + SmileOutlined, + FolderOutlined, + AudioOutlined, + AudioOutlined as AudioHoldOutlined, + CodeSandboxOutlined, + MessageOutlined, + EnvironmentOutlined, + StarOutlined, +} from "@ant-design/icons"; +import { ChatRecord, ContractData, weChatGroup } from "@/pages/pc/ckbox/data"; +import { useWebSocketStore } from "@/store/module/websocket/websocket"; +import styles from "./MessageEnter.module.scss"; + +const { Footer } = Layout; +const { TextArea } = Input; + +interface MessageEnterProps { + contract: ContractData | weChatGroup; + onSendMessage: (message: string) => void; +} + +const { sendCommand } = useWebSocketStore.getState(); + +const MessageEnter: React.FC = ({ + contract, + onSendMessage, +}) => { + const [inputValue, setInputValue] = useState(""); + const [showMaterialModal, setShowMaterialModal] = useState(false); + + const handleSend = async () => { + if (!inputValue.trim()) return; + console.log("发送消息", contract); + const params = { + wechatAccountId: contract.wechatAccountId, + wechatChatroomId: contract?.chatroomId || 0, + wechatFriendId: contract?.chatroomId ? 0 : contract.id, + msgSubType: 0, + msgType: 1, + content: inputValue, + }; + sendCommand("CmdSendMessage", params); + // try { + // onSendMessage(inputValue); + // setInputValue(""); + // } catch (error) { + // console.error("发送失败", error); + // } + }; + + const handleKeyPress = (e: React.KeyboardEvent) => { + if (e.key === "Enter" && !e.shiftKey && !e.ctrlKey) { + e.preventDefault(); + handleSend(); + } + // Ctrl+Enter 换行由 TextArea 自动处理,不需要阻止默认行为 + }; + + // 素材菜单项 + const materialMenuItems = [ + { + key: "text", + label: "文字素材", + icon: 📝, + }, + { + key: "audio", + label: "语音素材", + icon: 🎵, + }, + { + key: "image", + label: "图片素材", + icon: 🖼️, + }, + { + key: "video", + label: "视频素材", + icon: 🎬, + }, + { + key: "link", + label: "链接素材", + icon: 🔗, + }, + { + key: "card", + label: "名片素材", + icon: 📇, + }, + ]; + + const handleMaterialSelect = (key: string) => { + console.log("选择素材类型:", key); + setShowMaterialModal(true); + // 这里可以根据不同的素材类型显示不同的模态框 + }; + + return ( + <> + {/* 聊天输入 */} +