diff --git a/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageRecord/components/TransmitModal/README.md b/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageRecord/components/TransmitModal/README.md deleted file mode 100644 index 74a15a0d..00000000 --- a/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageRecord/components/TransmitModal/README.md +++ /dev/null @@ -1,95 +0,0 @@ -# TransmitModal 转发模态框组件 - -## 功能特性 - -- 🔍 支持联系人搜索(姓名和拼音) -- 👥 支持个人和群组联系人 -- ✅ 多选功能,可设置最大选择数量 -- 📱 响应式设计,适配移动端 -- 🎨 微信风格UI设计 -- ♿ 无障碍支持 - -## 使用方法 - -```tsx -import TransmitModal, { Contact } from './components/TransmitModal'; - -const contacts: Contact[] = [ - { - id: '1', - name: '张三', - avatar: 'https://example.com/avatar1.jpg', - type: 'user', - pinyin: 'zhangsan' - }, - { - id: '2', - name: '开发群', - type: 'group', - pinyin: 'kaifaqun' - } -]; - -function App() { - const [showModal, setShowModal] = useState(false); - - const handleConfirm = (selectedContacts: Contact[]) => { - console.log('选择的联系人:', selectedContacts); - // 执行转发逻辑 - setShowModal(false); - }; - - return ( - setShowModal(false)} - onConfirm={handleConfirm} - contacts={contacts} - title="转发" - maxSelection={9} - /> - ); -} -``` - -## Props - -| 属性 | 类型 | 默认值 | 说明 | -|------|------|--------|------| -| open | boolean | - | 是否显示模态框 | -| onCancel | () => void | - | 取消回调 | -| onConfirm | (contacts: Contact[]) => void | - | 确认回调 | -| contacts | Contact[] | - | 联系人列表 | -| title | string | '转发' | 模态框标题 | -| confirmText | string | '确定' | 确认按钮文本 | -| cancelText | string | '取消' | 取消按钮文本 | -| maxSelection | number | 9 | 最大选择数量 | - -## Contact 接口 - -```tsx -interface Contact { - id: string; // 唯一标识 - name: string; // 显示名称 - avatar?: string; // 头像URL - type: 'user' | 'group'; // 类型:用户或群组 - pinyin?: string; // 拼音,用于搜索 -} -``` - -## 样式定制 - -组件使用 CSS Modules,可以通过覆盖以下类名来定制样式: - -- `.transmitModal` - 模态框容器 -- `.contactList` - 左侧联系人列表 -- `.selectedList` - 右侧已选择列表 -- `.contactItem` - 联系人项 -- `.selectedItem` - 已选择项 - -## 注意事项 - -1. 确保传入的 `contacts` 数组中每个联系人的 `id` 唯一 -2. `pinyin` 字段可选,但建议提供以支持拼音搜索 -3. 组件会自动处理选择状态,无需外部维护 -4. 达到最大选择数量时,未选择的联系人会被禁用 \ No newline at end of file diff --git a/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageRecord/components/TransmitModal/TransmitModal.module.scss b/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageRecord/components/TransmitModal/TransmitModal.module.scss index 57bd53c6..57e2796f 100644 --- a/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageRecord/components/TransmitModal/TransmitModal.module.scss +++ b/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageRecord/components/TransmitModal/TransmitModal.module.scss @@ -1,26 +1,12 @@ -// TransmitModal 组件样式 - 微信风格 .transmitModal { - :global(.ant-modal-content) { - padding: 0; - border-radius: 8px; + .ant-modal-content { + height: 500px; + } + + .ant-modal-body { + height: calc(500px - 110px); overflow: hidden; - } - - :global(.ant-modal-header) { - padding: 16px 20px; - border-bottom: 1px solid #e8e8e8; - margin: 0; - } - - :global(.ant-modal-body) { - padding: 0; - height: 400px; - } - - :global(.ant-modal-footer) { - padding: 12px 20px; - border-top: 1px solid #e8e8e8; - text-align: right; + padding: 16px; } } @@ -31,96 +17,65 @@ } .searchContainer { - padding: 16px 20px; - border-bottom: 1px solid #e8e8e8; - background: #fafafa; -} + margin-bottom: 16px; -.searchInput { - border-radius: 20px; - - :global(.ant-input) { - border-radius: 20px; - background: #ffffff; + .searchInput { + width: 100%; } } .contentBody { flex: 1; display: flex; - height: calc(100% - 60px); -} - -.contactList { - flex: 1; - border-right: 1px solid #e8e8e8; - display: flex; - flex-direction: column; + gap: 16px; + min-height: 0; } +.contactList, .selectedList { - width: 200px; + flex: 1; display: flex; flex-direction: column; - background: #f8f8f8; + border: 1px solid #d9d9d9; + border-radius: 6px; + overflow: hidden; } .listHeader { padding: 12px 16px; - background: #f0f0f0; - border-bottom: 1px solid #e8e8e8; - font-size: 14px; + background-color: #fafafa; + border-bottom: 1px solid #d9d9d9; font-weight: 500; - color: #333; + font-size: 14px; + color: #262626; } .listContent { - flex: 1; + height: 60vh; overflow-y: auto; - padding: 8px 0; + padding: 8px; +} - &::-webkit-scrollbar { - width: 6px; +.contactItem, +.selectedItem { + display: flex; + align-items: center; + padding: 8px 12px; + border-radius: 4px; + margin-bottom: 4px; + transition: background-color 0.2s; + + &:hover { + background-color: #f5f5f5; } - &::-webkit-scrollbar-track { - background: transparent; - } - - &::-webkit-scrollbar-thumb { - background: #d9d9d9; - border-radius: 3px; - } - - &::-webkit-scrollbar-thumb:hover { - background: #bfbfbf; + &:last-child { + margin-bottom: 0; } } -.contactItem { - padding: 8px 16px; - cursor: pointer; - transition: background-color 0.2s ease; - - &:hover { - background: #f5f5f5; - } - - :global(.ant-checkbox-wrapper) { - width: 100%; - margin: 0; - } - - :global(.ant-checkbox) { - margin-right: 12px; - } - - :global(.ant-checkbox-disabled) { - :global(.ant-checkbox-inner) { - background-color: #f5f5f5; - border-color: #d9d9d9; - } - } +.selectedItem { + justify-content: space-between; } .contactInfo { @@ -128,109 +83,75 @@ align-items: center; gap: 8px; flex: 1; + min-width: 0; } .contactName { font-size: 14px; - color: #333; - flex: 1; + color: #262626; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; - white-space: nowrap; } .groupIcon { + color: #1890ff; font-size: 12px; - color: #999; - margin-left: auto; -} - -.selectedItem { - display: flex; - align-items: center; - justify-content: space-between; - padding: 8px 12px; - margin: 4px 8px; - background: #ffffff; - border-radius: 6px; - border: 1px solid #e8e8e8; - transition: all 0.2s ease; - - &:hover { - border-color: #d9d9d9; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); - } + margin-left: 4px; } .removeIcon { - font-size: 12px; - color: #999; + color: #8c8c8c; cursor: pointer; padding: 4px; - border-radius: 50%; - transition: all 0.2s ease; + border-radius: 2px; + transition: all 0.2s; &:hover { color: #ff4d4f; - background: #fff2f0; + background-color: #fff2f0; } } -// 空状态样式 -:global(.ant-empty) { - margin: 40px 0; - - :global(.ant-empty-description) { - color: #999; - font-size: 13px; - } +.loadingContainer { + display: flex; + justify-content: center; + align-items: center; + height: 200px; + flex-direction: column; + gap: 12px; + color: #8c8c8c; +} + +.errorContainer { + display: flex; + justify-content: center; + align-items: center; + height: 200px; + flex-direction: column; + gap: 12px; + color: #ff4d4f; } // 响应式设计 @media (max-width: 768px) { .transmitModal { - :global(.ant-modal) { - width: 90% !important; - max-width: none; + .ant-modal-content { + max-height: 600px; + } + + .ant-modal-body { + max-height: calc(600px - 110px); } } + .contentBody { + flex-direction: column; + gap: 12px; + } + + .contactList, .selectedList { - width: 160px; - } - - .contactName { - font-size: 13px; + min-height: 200px; } } - -// 按钮样式优化 -:global(.ant-btn-primary) { - background: #07c160; - border-color: #07c160; - - &:hover { - background: #06ad56; - border-color: #06ad56; - } - - &:disabled { - background: #f5f5f5; - border-color: #d9d9d9; - color: #bfbfbf; - } -} - -// 复选框样式优化 -:global(.ant-checkbox-checked) { - :global(.ant-checkbox-inner) { - background-color: #07c160; - border-color: #07c160; - } -} - -:global(.ant-checkbox-wrapper:hover) { - :global(.ant-checkbox-inner) { - border-color: #07c160; - } -} \ No newline at end of file diff --git a/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageRecord/components/TransmitModal/TransmitModal.tsx b/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageRecord/components/TransmitModal/TransmitModal.tsx deleted file mode 100644 index 51bce619..00000000 --- a/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageRecord/components/TransmitModal/TransmitModal.tsx +++ /dev/null @@ -1,218 +0,0 @@ -import React, { useState, useEffect, useMemo } from "react"; -import { Modal, Input, Button, Avatar, Checkbox, Empty } from "antd"; -import { - SearchOutlined, - CloseOutlined, - UserOutlined, - TeamOutlined, -} from "@ant-design/icons"; -import styles from "./TransmitModal.module.scss"; - -export interface Contact { - id: string; - name: string; - avatar?: string; - type: "user" | "group"; - pinyin?: string; // 用于搜索 -} - -export interface TransmitModalProps { - open: boolean; - onCancel: () => void; - onConfirm: (selectedContacts: Contact[]) => void; - contacts: Contact[]; - title?: string; - confirmText?: string; - cancelText?: string; - maxSelection?: number; -} - -const TransmitModal: React.FC = ({ - open, - onCancel, - onConfirm, - contacts, - title = "转发", - confirmText = "确定", - cancelText = "取消", - maxSelection = 9, -}) => { - const [searchValue, setSearchValue] = useState(""); - const [selectedContacts, setSelectedContacts] = useState([]); - - // 重置状态 - useEffect(() => { - if (!open) { - setSearchValue(""); - setSelectedContacts([]); - } - }, [open]); - - // 过滤联系人 - const filteredContacts = useMemo(() => { - if (!searchValue.trim()) return contacts; - - const keyword = searchValue.toLowerCase(); - return contacts.filter( - contact => - contact.name.toLowerCase().includes(keyword) || - contact.pinyin?.toLowerCase().includes(keyword), - ); - }, [contacts, searchValue]); - - // 处理联系人选择 - const handleContactSelect = (contact: Contact, checked: boolean) => { - if (checked) { - if (selectedContacts.length >= maxSelection) { - return; // 达到最大选择数量 - } - setSelectedContacts(prev => [...prev, contact]); - } else { - setSelectedContacts(prev => prev.filter(item => item.id !== contact.id)); - } - }; - - // 移除已选择的联系人 - const handleRemoveSelected = (contactId: string) => { - setSelectedContacts(prev => prev.filter(item => item.id !== contactId)); - }; - - // 确认转发 - const handleConfirm = () => { - onConfirm(selectedContacts); - }; - - // 检查联系人是否已选择 - const isContactSelected = (contactId: string) => { - return selectedContacts.some(contact => contact.id === contactId); - }; - - return ( - - {cancelText} - , - , - ]} - > -
- {/* 搜索框 */} -
- } - value={searchValue} - onChange={e => setSearchValue(e.target.value)} - className={styles.searchInput} - /> -
- -
- {/* 左侧联系人列表 */} -
-
- 联系人 -
-
- {filteredContacts.length > 0 ? ( - filteredContacts.map(contact => ( -
- - handleContactSelect(contact, e.target.checked) - } - disabled={ - !isContactSelected(contact.id) && - selectedContacts.length >= maxSelection - } - > -
- - ) : ( - - ) - } - /> - - {contact.name} - - {contact.type === "group" && ( - - )} -
-
-
- )) - ) : ( - - )} -
-
- - {/* 右侧已选择列表 */} -
-
- 已选择 {selectedContacts.length} 个联系人 -
-
- {selectedContacts.length > 0 ? ( - selectedContacts.map(contact => ( -
-
- - ) : ( - - ) - } - /> - {contact.name} -
- handleRemoveSelected(contact.id)} - /> -
- )) - ) : ( - - )} -
-
-
-
-
- ); -}; - -export default TransmitModal; diff --git a/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageRecord/components/TransmitModal/index.ts b/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageRecord/components/TransmitModal/index.ts deleted file mode 100644 index fb2de0a0..00000000 --- a/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageRecord/components/TransmitModal/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from "./TransmitModal"; -export type { TransmitModalProps, Contact } from "./TransmitModal"; diff --git a/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageRecord/components/TransmitModal/index.tsx b/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageRecord/components/TransmitModal/index.tsx new file mode 100644 index 00000000..8bbe17e4 --- /dev/null +++ b/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageRecord/components/TransmitModal/index.tsx @@ -0,0 +1,315 @@ +import React, { useState, useEffect, useMemo } from "react"; +import { + Modal, + Input, + Button, + Avatar, + Checkbox, + Empty, + Spin, + message, +} from "antd"; +import { + SearchOutlined, + CloseOutlined, + UserOutlined, + TeamOutlined, +} from "@ant-design/icons"; +import styles from "./TransmitModal.module.scss"; +import { weChatGroupService, contractService } from "@/utils/db"; +import { useWeChatStore } from "@/store/module/weChat/weChat"; +import { ContractData, weChatGroup } from "@/pages/pc/ckbox/data"; + +export interface Contact { + id: string; + name: string; + avatar?: string; + type: "user" | "group"; + pinyin?: string; // 用于搜索 + originalData?: ContractData | weChatGroup; // 保存原始数据 +} + +export interface TransmitModalProps { + onConfirm?: (selectedTransmitContact: ContractData[] | weChatGroup[]) => void; // 可选,因为会自动更新到store +} + +const TransmitModal: React.FC = ({ onConfirm }) => { + const [searchValue, setSearchValue] = useState(""); + const [allContacts, setAllContacts] = useState([]); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(""); + + const selectedTransmitContact = useWeChatStore( + state => state.selectedTransmitContact, + ); + // 从 Zustand store 获取更新方法 + const { updateSelectedTransmitContact } = useWeChatStore(); + const openTransmitModal = useWeChatStore(state => state.openTransmitModal); + const updateTransmitModal = useWeChatStore( + state => state.updateTransmitModal, + ); + // 加载联系人数据 + const loadContacts = async () => { + setLoading(true); + setError(""); + try { + // 并行加载联系人和群组数据 + const [contractsData, groupsData] = await Promise.all([ + contractService.findAll(), + weChatGroupService.findAll(), + ]); + + // 转换联系人数据格式 + const contacts: Contact[] = contractsData.map( + (contract: ContractData) => ({ + id: contract.id.toString(), + name: + contract.nickname || + contract.alias || + contract.wechatId || + "未知联系人", + avatar: contract.avatar, + type: "user" as const, + pinyin: contract.quanPin, + originalData: contract, + }), + ); + + // 转换群组数据格式 + const groups: Contact[] = groupsData.map((group: weChatGroup) => ({ + id: group.id.toString(), + name: group.nickname || group.conRemark || "未知群组", + avatar: group.chatroomAvatar, + type: "group" as const, + pinyin: group.nickname, // 群组可能没有拼音,使用昵称 + originalData: group, + })); + + // 合并并排序(联系人在前,群组在后) + const allContactsData = [...contacts, ...groups]; + setAllContacts(allContactsData); + } catch (err) { + console.error("加载联系人数据失败:", err); + setError("加载联系人数据失败,请重试"); + message.error("加载联系人数据失败"); + } finally { + setLoading(false); + } + }; + + // 重置状态 + useEffect(() => { + if (openTransmitModal) { + setSearchValue(""); + updateSelectedTransmitContact([]); + setError(""); + loadContacts(); + } + }, [openTransmitModal]); + + // 过滤联系人 - 支持名称和拼音搜索 + const filteredContacts = useMemo(() => { + if (!searchValue.trim()) return allContacts; + + const keyword = searchValue.toLowerCase(); + return allContacts.filter( + contact => + contact.name.toLowerCase().includes(keyword) || + contact.pinyin?.toLowerCase().includes(keyword) || + contact.id.toLowerCase().includes(keyword), + ); + }, [allContacts, searchValue]); + + // 处理联系人选择 + const handleContactSelect = (contact: Contact, checked: boolean) => { + console.log(contact); + console.log(checked); + }; + + // 移除已选择的联系人 + const handleRemoveSelected = (contactId: string) => { + // updateSelectedTransmitContact(prev => + // selectedTransmitContact.filter(item => item.id !== contactId), + // ); + }; + + // 确认转发 + const handleConfirm = () => { + if (selectedTransmitContact.length === 0) { + message.warning("请至少选择一个联系人"); + return; + } + + // 更新到 Zustand store + const originalDataList = selectedTransmitContact + .map(contact => contact.originalData) + .filter(Boolean) as (ContractData | weChatGroup)[]; + + // updateSelectedTransmitContact(originalDataList); + + // 如果有外部回调,也调用它 + if (onConfirm) { + onConfirm(selectedTransmitContact); + } + + message.success(`已选择${selectedTransmitContact.length}个联系人`); + }; + + // 检查联系人是否已选择 + const isContactSelected = (contactId: string) => { + console.log(contactId); + + return selectedTransmitContact.some(contact => contact.id === contactId); + }; + + // 重试加载 + const handleRetry = () => { + loadContacts(); + }; + + return ( + updateTransmitModal(false)} + width={800} + className={styles.transmitModal} + footer={[ + , + , + ]} + > +
+ {/* 搜索框 */} +
+ } + value={searchValue} + onChange={e => setSearchValue(e.target.value)} + className={styles.searchInput} + disabled={loading} + /> +
+ +
+ {/* 左侧联系人列表 */} +
+
+ 联系人 ({filteredContacts.length}) +
+
+ {loading ? ( +
+ + 加载联系人中... +
+ ) : error ? ( +
+ {error} + +
+ ) : filteredContacts.length > 0 ? ( + filteredContacts.map(contact => ( +
+ + handleContactSelect(contact, e.target.checked) + } + disabled={!isContactSelected(contact.id)} + > +
+ + ) : ( + + ) + } + /> + + {contact.name} + + {contact.type === "group" && ( + + )} +
+
+
+ )) + ) : ( + + )} +
+
+ + {/* 右侧已选择列表 */} +
+
+ 已选择 {selectedTransmitContact.length} 个联系人 +
+
+ {selectedTransmitContact.length > 0 ? ( + selectedTransmitContact.map(contact => ( +
+
+ + ) : ( + + ) + } + /> + {contact.name} + {contact.type === "group" && ( + + )} +
+ handleRemoveSelected(contact.id)} + /> +
+ )) + ) : ( + + )} +
+
+
+
+
+ ); +}; + +export default TransmitModal; 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 502e6e1f..f68741b6 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 @@ -12,6 +12,8 @@ import styles from "./MessageRecord.module.scss"; import { useWeChatStore } from "@/store/module/weChat/weChat"; import { useCkChatStore } from "@/store/module/ckchat/ckchat"; import { fetchReCallApi } from "./api"; +import TransmitModal from "./components/TransmitModal"; + interface MessageRecordProps { contract: ContractData | weChatGroup; } @@ -44,6 +46,11 @@ const MessageRecord: React.FC = ({ contract }) => { state.kfUserList.find(kf => kf.id === contract.wechatAccountId), ); + const openTransmitModal = useWeChatStore(state => state.openTransmitModal); + const updateTransmitModal = useWeChatStore( + state => state.updateTransmitModal, + ); + // 判断是否为表情包URL的工具函数 const isEmojiUrl = (content: string): boolean => { return ( @@ -662,6 +669,7 @@ const MessageRecord: React.FC = ({ contract }) => { }; const handleForwardMessage = (messageData: ChatRecord) => { + updateTransmitModal(true); // 转发消息的处理逻辑 console.log("转发消息:", messageData); }; @@ -702,6 +710,13 @@ const MessageRecord: React.FC = ({ contract }) => { } }; + const handleConfirmTransmit = ( + selectedContacts: ContractData[] | weChatGroup[], + ) => { + // 确认转发逻辑 + console.log("确认转发:", selectedContacts); + }; + return (
loadMoreMessages()}> @@ -727,7 +742,6 @@ const MessageRecord: React.FC = ({ contract }) => { ))}
- {/* 右键菜单组件 */} = ({ contract }) => { onClose={handleCloseContextMenu} onCommad={handCommad} /> + {/* 转发模态框 */} + + handleConfirmTransmit(selectedContacts) + } + />
); }; diff --git a/Touchkebao/src/store/module/weChat/weChat.data.ts b/Touchkebao/src/store/module/weChat/weChat.data.ts index 14bf3506..477d740b 100644 --- a/Touchkebao/src/store/module/weChat/weChat.data.ts +++ b/Touchkebao/src/store/module/weChat/weChat.data.ts @@ -4,64 +4,104 @@ import { likeListItem, FriendsCircleItem, } from "@/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/index.data"; -// 微信聊天相关的类型定义 -export interface WeChatState { - //选择聊天记录 - selectedMessage: ChatRecord[]; - updateSelectedMessage: (message: ChatRecord[]) => void; - //选择用户或群 - selectedContact: ContractData[] | weChatGroup[]; - updateSelectedContact: (contact: ContractData[] | weChatGroup[]) => void; +/** + * 微信聊天状态管理接口定义 + * 包含聊天消息、联系人管理、朋友圈等功能的状态和方法 + */ +export interface WeChatState { + // ==================== Transmit Module =========Start=========== + /** 选中的聊天记录列表 */ + selectedChatRecords: ChatRecord[]; + /** 更新选中的聊天记录 */ + updateSelectedChatRecords: (message: ChatRecord[]) => void; + + /** 选中的联系人或群组列表 */ + selectedTransmitContact: ContractData[] | weChatGroup[]; + /** 更新选中的联系人或群组 */ + updateSelectedTransmitContact: ( + contact: ContractData[] | weChatGroup[], + ) => void; + + /** 转发弹窗开启状态 */ openTransmitModal: boolean; + /** 更新转发弹窗状态 */ updateTransmitModal: (open: boolean) => void; - // 当前选中的联系人/群组 + // ==================== Transmit Module =========END=========== + + // ==================== 当前联系人管理 ==================== + /** 当前选中的联系人/群组 */ currentContract: ContractData | weChatGroup | null; - // CurrentContact 相关方法 + /** 清空当前联系人 */ clearCurrentContact: () => void; + /** 设置当前联系人 */ setCurrentContact: ( contract: ContractData | weChatGroup, isExist?: boolean, ) => void; - // 当前聊天用户的消息列表(只存储当前聊天用户的消息) + // ==================== 聊天消息管理 ==================== + /** 当前聊天的消息列表 */ currentMessages: ChatRecord[]; - // 添加消息 + /** 添加新消息 */ addMessage: (message: ChatRecord) => void; - // 替换消息 + /** 更新指定消息 */ updateMessage: (messageId: number, updates: Partial) => void; - // 撤回消息 + /** 撤回指定消息 */ recallMessage: (messageId: number) => void; - // 消息加载状态 + /** 消息加载状态 */ messagesLoading: boolean; + /** 数据初始化加载状态 */ isLoadingData: boolean; + /** 当前群组成员列表 */ currentGroupMembers: any[]; - showCheckbox: boolean; - updateShowCheckbox: (show: boolean) => void; - EnterModule: string; - // EnterModule 相关方法 - updateEnterModule: (module: string) => void; - MomentCommon: FriendsCircleItem[]; - // MomentCommon 相关方法 - clearMomentCommon: () => void; - addMomentCommon: (moment: FriendsCircleItem[]) => void; - updateMomentCommon: (moments: FriendsCircleItem[]) => void; + // ==================== 界面状态管理 ==================== + /** 是否显示复选框 */ + showCheckbox: boolean; + /** 更新复选框显示状态 */ + updateShowCheckbox: (show: boolean) => void; + /** 进入模块类型 (common | multipleForwarding) */ + EnterModule: string; + /** 更新进入模块类型 */ + updateEnterModule: (module: string) => void; + + // ==================== 朋友圈相关 ==================== + /** 朋友圈数据列表 */ + MomentCommon: FriendsCircleItem[]; + /** 朋友圈数据加载状态 */ MomentCommonLoading: boolean; - // MomentCommon 相关方法 + /** 清空朋友圈数据 */ + clearMomentCommon: () => void; + /** 添加朋友圈数据 */ + addMomentCommon: (moment: FriendsCircleItem[]) => void; + /** 更新朋友圈数据 */ + updateMomentCommon: (moments: FriendsCircleItem[]) => void; + /** 更新朋友圈加载状态 */ updateMomentCommonLoading: (loading: boolean) => void; + /** 更新朋友圈点赞 */ updateLikeMoment: (snsId: string, likeList: likeListItem[]) => void; + /** 更新朋友圈评论 */ updateComment: (snsId: string, commentList: CommentItem[]) => void; + // ==================== 消息加载方法 ==================== + /** 加载聊天消息 */ loadChatMessages: (Init: boolean, To?: number) => Promise; + /** 搜索消息 */ SearchMessage: (params: { From: number; To: number; keyword: string; Count?: number; }) => Promise; - // 视频消息处理方法 + + // ==================== 视频消息处理 ==================== + /** 设置视频消息加载状态 */ setVideoLoading: (messageId: number, isLoading: boolean) => void; + /** 设置视频消息URL */ setVideoUrl: (messageId: number, videoUrl: string) => void; + + // ==================== 消息接收处理 ==================== + /** 接收新消息处理 */ receivedMsg: (message: ChatRecord) => void; } diff --git a/Touchkebao/src/store/module/weChat/weChat.ts b/Touchkebao/src/store/module/weChat/weChat.ts index 6ae89b95..6a2d04b4 100644 --- a/Touchkebao/src/store/module/weChat/weChat.ts +++ b/Touchkebao/src/store/module/weChat/weChat.ts @@ -20,36 +20,52 @@ import { useCkChatStore, } from "@/store/module/ckchat/ckchat"; +/** + * 微信聊天状态管理 Store + * 使用 Zustand 管理微信聊天相关的状态和操作 + */ export const useWeChatStore = create()( persist( (set, get) => ({ - //选择聊天记录 - selectedMessage: [], - updateSelectedMessage: (message: ChatRecord[]) => { - set({ selectedMessage: message }); + // ==================== Transmit Module =========Start=========== + /** 选中的聊天记录列表 */ + selectedChatRecords: [], + /** 更新选中的聊天记录 */ + updateSelectedChatRecords: (message: ChatRecord[]) => { + set({ selectedChatRecords: message }); }, - //选择用户或群 - selectedContact: [], - updateSelectedContact: (contact: ContractData[] | weChatGroup[]) => { - set({ selectedContact: contact }); - }, - //打开转发弹窗 - openTransmitModal: false, + /** 选中的联系人或群组列表 */ + selectedTransmitContact: [], + /** 更新选中的联系人或群组 */ + updateSelectedTransmitContact: ( + contact: ContractData[] | weChatGroup[], + ) => { + set({ selectedTransmitContact: contact }); + }, + + /** 转发弹窗开启状态 */ + openTransmitModal: false, + /** 更新转发弹窗状态 */ updateTransmitModal: (open: boolean) => { set({ openTransmitModal: open }); }, + // ==================== Transmit Module =========END=========== - // 初始状态 + // ==================== 当前联系人管理状态 ==================== + /** 当前选中的联系人/群组 */ currentContract: null, + /** 当前聊天的消息列表 */ currentMessages: [], - //添加消息 + + // ==================== 聊天消息管理方法 ==================== + /** 添加新消息到当前聊天 */ addMessage: message => { set(state => ({ currentMessages: [...state.currentMessages, message], })); }, - //替换消息 + /** 更新指定消息内容 */ updateMessage: (messageId, updates) => { set(state => ({ currentMessages: state.currentMessages.map(msg => @@ -57,7 +73,7 @@ export const useWeChatStore = create()( ), })); }, - //撤回消息 + /** 撤回指定消息 */ recallMessage: (messageId: number) => { set(state => ({ currentMessages: state.currentMessages.filter( @@ -66,31 +82,44 @@ export const useWeChatStore = create()( })); }, + // ==================== 加载状态管理 ==================== + /** 消息加载状态 */ messagesLoading: false, + /** 数据初始化加载状态 */ isLoadingData: false, + /** 当前群组成员列表 */ currentGroupMembers: [], + + // ==================== 界面状态管理 ==================== + /** 是否显示复选框 */ showCheckbox: false, + /** 更新复选框显示状态 */ updateShowCheckbox: (show: boolean) => { set({ showCheckbox: show }); }, - EnterModule: "common", //common | multipleForwarding + /** 进入模块类型 (common | multipleForwarding) */ + EnterModule: "common", + /** 更新进入模块类型 */ updateEnterModule: (module: string) => { set({ EnterModule: module }); }, - MomentCommon: [], //朋友圈数据 - MomentCommonLoading: false, //朋友圈数据是否正在加载 - // MomentCommon 相关方法 + // ==================== 朋友圈相关状态 ==================== + /** 朋友圈数据列表 */ + MomentCommon: [], + /** 朋友圈数据加载状态 */ + MomentCommonLoading: false, + /** 更新朋友圈加载状态 */ updateMomentCommonLoading: (loading: boolean) => { set({ MomentCommonLoading: loading }); }, - //============方法列表============ - //清空当前联系人 + // ==================== 当前联系人管理方法 ==================== + /** 清空当前联系人和消息 */ clearCurrentContact: () => { set({ currentContract: null, currentMessages: [] }); }, - // Actions + /** 设置当前联系人并加载相关数据 */ setCurrentContact: ( contract: ContractData | weChatGroup, isExist?: boolean, @@ -112,6 +141,9 @@ export const useWeChatStore = create()( state.loadChatMessages(true, 4704624000000); }); }, + + // ==================== 消息加载方法 ==================== + /** 加载聊天消息 */ loadChatMessages: async (Init: boolean, To?: number) => { const state = useWeChatStore.getState(); const contact = state.currentContract; @@ -127,6 +159,7 @@ export const useWeChatStore = create()( }; if ("chatroomId" in contact && contact.chatroomId) { + // 群聊消息加载 params.wechatChatroomId = contact.id; const messages = await getChatroomMessages(params); const currentGroupMembers = await getGroupMembers({ @@ -143,6 +176,7 @@ export const useWeChatStore = create()( }); } } else { + // 私聊消息加载 params.wechatFriendId = contact.id; const messages = await getChatMessages(params); if (Init) { @@ -163,6 +197,8 @@ export const useWeChatStore = create()( set({ messagesLoading: false }); } }, + + /** 搜索消息 */ SearchMessage: async ({ From = 1, To = 4704624000000, @@ -189,6 +225,7 @@ export const useWeChatStore = create()( }; if ("chatroomId" in contact && contact.chatroomId) { + // 群聊消息搜索 params.wechatChatroomId = contact.id; const messages = await getChatroomMessages(params); const currentGroupMembers = await getGroupMembers({ @@ -196,6 +233,7 @@ export const useWeChatStore = create()( }); set({ currentMessages: messages || [], currentGroupMembers }); } else { + // 私聊消息搜索 params.wechatFriendId = contact.id; const messages = await getChatMessages(params); set({ currentMessages: messages || [] }); @@ -208,29 +246,34 @@ export const useWeChatStore = create()( } }, + /** 设置消息加载状态 */ setMessageLoading: loading => { set({ messagesLoading: Boolean(loading) }); }, + // ==================== 消息接收处理 ==================== + /** 接收新消息处理 */ receivedMsg: async message => { const currentContract = useWeChatStore.getState().currentContract; - //判断群还是好友 + // 判断是群聊还是私聊 const getMessageId = message?.wechatChatroomId || message.wechatFriendId; const isWechatGroup = message?.wechatChatroomId; - //当前选中聊天的群或好友 + + // 如果是当前选中的聊天,直接添加到消息列表 if (currentContract && currentContract.id == getMessageId) { set(state => ({ currentMessages: [...state.currentMessages, message], })); } else { - //更新消息列表unread数值,根据接收的++1 这样 + // 更新其他聊天的未读消息数 const chatSessions = useCkChatStore.getState().chatSessions; const session = chatSessions.find(item => item.id == getMessageId); if (session) { session.unreadCount = Number(session.unreadCount) + 1; updateChatSession(session); } else { + // 如果会话不存在,创建新会话 if (isWechatGroup) { const [group] = await weChatGroupService.findByIds(getMessageId); if (group) { @@ -250,12 +293,16 @@ export const useWeChatStore = create()( } }, - // 便捷选择器 + // ==================== 便捷选择器方法 ==================== + /** 获取当前联系人 */ getCurrentContact: () => get().currentContract, + /** 获取当前消息列表 */ getCurrentMessages: () => get().currentMessages, + /** 获取消息加载状态 */ getMessagesLoading: () => get().messagesLoading, - // 视频消息处理方法 + // ==================== 视频消息处理方法 ==================== + /** 设置视频消息加载状态 */ setVideoLoading: (messageId: number, isLoading: boolean) => { set(state => ({ currentMessages: state.currentMessages.map(msg => { @@ -278,6 +325,7 @@ export const useWeChatStore = create()( })); }, + /** 设置视频消息URL */ setVideoUrl: (messageId: number, videoUrl: string) => { set(state => ({ currentMessages: state.currentMessages.map(msg => { @@ -309,6 +357,9 @@ export const useWeChatStore = create()( }), })); }, + + // ==================== 数据清理方法 ==================== + /** 清空所有数据 */ clearAllData: () => { set({ currentContract: null, @@ -317,21 +368,25 @@ export const useWeChatStore = create()( }); }, - // MomentCommon 相关方法 + // ==================== 朋友圈管理方法 ==================== + /** 清空朋友圈数据 */ clearMomentCommon: () => { set({ MomentCommon: [] }); }, + /** 添加朋友圈数据 */ addMomentCommon: moment => { set(state => ({ MomentCommon: [...state.MomentCommon, ...moment], })); }, + /** 更新朋友圈数据 */ updateMomentCommon: moments => { set({ MomentCommon: moments }); }, + /** 更新朋友圈点赞 */ updateLikeMoment: (snsId: string, likeList: likeListItem[]) => { set(state => ({ MomentCommon: state.MomentCommon.map(moment => @@ -340,6 +395,7 @@ export const useWeChatStore = create()( })); }, + /** 更新朋友圈评论 */ updateComment: (snsId: string, commentList: CommentItem[]) => { set(state => ({ MomentCommon: state.MomentCommon.map(moment => @@ -357,12 +413,16 @@ export const useWeChatStore = create()( ), ); -// 导出便捷的选择器函数 +// ==================== 便捷选择器导出 ==================== +/** 获取当前联系人的 Hook */ export const useCurrentContact = () => useWeChatStore(state => state.currentContract); +/** 获取当前消息列表的 Hook */ export const useCurrentMessages = () => useWeChatStore(state => state.currentMessages); +/** 获取消息加载状态的 Hook */ export const useMessagesLoading = () => useWeChatStore(state => state.messagesLoading); +/** 获取复选框显示状态的 Hook */ export const useShowCheckbox = () => useWeChatStore(state => state.showCheckbox);