新增获取群聊成员列表API,优化消息记录组件以支持群聊成员信息展示,调整状态管理以防止跨联系人数据串联。

This commit is contained in:
超级老白兔
2025-11-27 16:38:28 +08:00
parent ed4d305165
commit 10f876f2f6
5 changed files with 111 additions and 32 deletions

View File

@@ -1,6 +1,6 @@
// 朋友圈相关的API接口
import { useWebSocketStore } from "@/store/module/websocket/websocket";
import request from "@/api/request";
// 朋友圈请求参数接口
export interface FetchMomentParams {
friendMessageId: number;
@@ -30,3 +30,16 @@ export const fetchVoiceToTextApi = async (params: VoiceToTextParams) => {
seq: params.seq,
});
};
export const getChatroomMemberList = async (params: { groupId: number }) => {
return request(
"/v1/chatroom/getMemberList",
{
groupId: params.groupId,
keyword: "",
limit: 500,
page: 1,
},
"GET",
);
};

View File

@@ -14,7 +14,11 @@ import styles from "./com.module.scss";
import { useWeChatStore } from "@/store/module/weChat/weChat";
import { useContactStore } from "@/store/module/weChat/contacts";
import { useCustomerStore } from "@weChatStore/customer";
import { fetchReCallApi, fetchVoiceToTextApi } from "./api";
import {
fetchReCallApi,
fetchVoiceToTextApi,
getChatroomMemberList,
} from "./api";
import TransmitModal from "./components/TransmitModal";
const IMAGE_EXT_REGEX = /\.(jpg|jpeg|png|gif|webp|bmp|svg)$/i;
@@ -131,6 +135,16 @@ const tryParseContentJson = (content: string): Record<string, any> | null => {
interface MessageRecordProps {
contract: ContractData | weChatGroup;
}
type GroupRenderItem = {
id: number;
identifier: string;
nickname: string;
avatar: string;
groupId: number;
chatroomId?: string;
wechatId?: string;
};
const MessageRecord: React.FC<MessageRecordProps> = ({ contract }) => {
const messagesEndRef = useRef<HTMLDivElement>(null);
// 右键菜单状态
@@ -152,9 +166,6 @@ const MessageRecord: React.FC<MessageRecordProps> = ({ contract }) => {
const loadChatMessages = useWeChatStore(state => state.loadChatMessages);
const messagesLoading = useWeChatStore(state => state.messagesLoading);
const isLoadingData = useWeChatStore(state => state.isLoadingData);
const currentGroupMembers = useWeChatStore(
state => state.currentGroupMembers,
);
const showCheckbox = useWeChatStore(state => state.showCheckbox);
const prevMessagesRef = useRef(currentMessages);
const updateShowCheckbox = useWeChatStore(state => state.updateShowCheckbox);
@@ -168,6 +179,7 @@ const MessageRecord: React.FC<MessageRecordProps> = ({ contract }) => {
);
const setTransmitModal = useContactStore(state => state.setTransmitModal);
const [groupRender, setGroupRender] = useState<GroupRenderItem[]>([]);
const currentContract = useWeChatStore(state => state.currentContract);
const updateQuoteMessageContent = useWeChatStore(
@@ -345,6 +357,37 @@ const MessageRecord: React.FC<MessageRecordProps> = ({ contract }) => {
);
};
useEffect(() => {
const fetchGroupMembers = async () => {
if (!contract.chatroomId) {
setGroupRender([]);
return;
}
try {
const res = await getChatroomMemberList({ groupId: contract.id });
setGroupRender(res?.list || []);
} catch (error) {
console.error("获取群成员失败", error);
setGroupRender([]);
}
};
fetchGroupMembers();
}, [contract.id, contract.chatroomId]);
const renderGroupUser = (msg: ChatRecord) => {
if (!msg) {
return { avatar: "", nickname: "" };
}
const member =
groupRender.find(user => user?.identifier === msg?.sender?.wechatId) ||
groupRender.find(user => user?.wechatId === msg?.sender?.wechatId);
return {
avatar: member?.avatar || msg?.sender?.avatar || "",
nickname: member?.nickname || msg?.sender?.nickname || "",
};
};
useEffect(() => {
const prevMessages = prevMessagesRef.current;
const prevLength = prevMessages.length;
@@ -498,13 +541,6 @@ const MessageRecord: React.FC<MessageRecordProps> = ({ contract }) => {
};
// 获取群成员头像
const groupMemberAvatar = (msg: ChatRecord) => {
const groupMembers = currentGroupMembers.find(
v => v?.wechatId == msg?.sender?.wechatId,
);
return groupMembers?.avatar;
};
// 清理微信ID前缀
const clearWechatidInContent = (sender: any, content: string) => {
try {
@@ -579,6 +615,7 @@ const MessageRecord: React.FC<MessageRecordProps> = ({ contract }) => {
const isOwn = msg?.isSend;
const isGroup = !!contract.chatroomId;
const groupUser = isGroup ? renderGroupUser(msg) : null;
return (
<div
key={msg.id || `msg-${Date.now()}`}
@@ -619,7 +656,7 @@ const MessageRecord: React.FC<MessageRecordProps> = ({ contract }) => {
{/* 如果是群聊 */}
{isGroup && !isOwn && (
<>
{/* Checkbox 显示控制 */}
{/* 群聊场景下根据消息发送者匹配头像与昵称 */}
{showCheckbox && (
<div className={styles.checkboxContainer}>
<Checkbox
@@ -630,14 +667,14 @@ const MessageRecord: React.FC<MessageRecordProps> = ({ contract }) => {
)}
<Avatar
size={32}
src={groupMemberAvatar(msg)}
src={groupUser?.avatar}
icon={<UserOutlined />}
className={styles.messageAvatar}
/>
<div>
{!isOwn && (
<div className={styles.messageSender}>
{msg?.sender?.nickname}
{groupUser?.nickname}
</div>
)}
<>

View File

@@ -46,6 +46,8 @@ export interface WeChatState {
currentMessagesPageSize: number;
/** 是否还有更多历史消息 */
currentMessagesHasMore: boolean;
/** 当前消息请求ID用于防止跨联系人数据串联 */
currentMessagesRequestId: number;
/** 添加新消息 */
addMessage: (message: ChatRecord) => void;
/** 更新指定消息 */

View File

@@ -516,6 +516,7 @@ export const useWeChatStore = create<WeChatState>()(
currentMessagesPage: 1,
currentMessagesPageSize: DEFAULT_MESSAGE_PAGE_SIZE,
currentMessagesHasMore: true,
currentMessagesRequestId: 0,
// ==================== 聊天消息管理方法 ====================
/** 添加新消息到当前聊天 */
@@ -603,6 +604,7 @@ export const useWeChatStore = create<WeChatState>()(
currentMessagesPage: 1,
currentMessagesHasMore: true,
currentMessagesPageSize: DEFAULT_MESSAGE_PAGE_SIZE,
currentMessagesRequestId: 0,
});
},
/** 设置当前联系人并加载相关数据 */
@@ -616,6 +618,7 @@ export const useWeChatStore = create<WeChatState>()(
pendingMessages = [];
const state = useWeChatStore.getState();
const newRequestId = Date.now();
// 切换联系人时清空当前消息,等待重新加载
set({
currentMessages: [],
@@ -623,6 +626,7 @@ export const useWeChatStore = create<WeChatState>()(
currentMessagesHasMore: true,
currentMessagesPageSize: DEFAULT_MESSAGE_PAGE_SIZE,
isLoadingAiChat: false,
currentMessagesRequestId: newRequestId,
});
const params: any = {};
@@ -643,7 +647,10 @@ export const useWeChatStore = create<WeChatState>()(
set({ aiQuoteMessageContent: result });
});
// 注意会话列表的未读数清零在MessageList组件的onContactClick中处理
set({ currentContract: contract });
set({
currentContract: contract,
currentMessagesRequestId: newRequestId,
});
updateConfig({
id: contract.id,
config: { chat: true },
@@ -656,8 +663,10 @@ export const useWeChatStore = create<WeChatState>()(
loadChatMessages: async (Init: boolean, pageOverride?: number) => {
const state = useWeChatStore.getState();
const contact = state.currentContract;
const requestIdAtStart = state.currentMessagesRequestId;
const requestedContactId = contact?.id;
if (!contact) {
if (!contact || !requestedContactId) {
return;
}
@@ -716,22 +725,42 @@ export const useWeChatStore = create<WeChatState>()(
});
}
set(current => ({
currentMessages: Init
? sortedMessages
: [...sortedMessages, ...current.currentMessages],
currentGroupMembers:
Init && isGroup ? nextGroupMembers : current.currentGroupMembers,
currentMessagesPage: paginationMeta.page,
currentMessagesPageSize: paginationMeta.limit,
currentMessagesHasMore: paginationMeta.hasMore,
}));
set(current => {
if (
current.currentMessagesRequestId !== requestIdAtStart ||
!current.currentContract ||
current.currentContract.id !== requestedContactId
) {
return {};
}
return {
currentMessages: Init
? sortedMessages
: [...sortedMessages, ...current.currentMessages],
currentGroupMembers:
Init && isGroup
? nextGroupMembers
: current.currentGroupMembers,
currentMessagesPage: paginationMeta.page,
currentMessagesPageSize: paginationMeta.limit,
currentMessagesHasMore: paginationMeta.hasMore,
};
});
} catch (error) {
console.error("获取聊天消息失败:", error);
} finally {
set({
messagesLoading: false,
isLoadingData: false,
set(current => {
if (
current.currentMessagesRequestId !== requestIdAtStart ||
!current.currentContract ||
current.currentContract.id !== requestedContactId
) {
return {};
}
return {
messagesLoading: false,
isLoadingData: false,
};
});
}
},

View File

@@ -199,8 +199,6 @@ const messageHandlers: Record<string, MessageHandler> = {
});
}
},
// 可以继续添加更多处理器...
};
//消息异步同步
const goAsyncServiceData = (message: Messages) => {