新增获取群聊成员列表API,优化消息记录组件以支持群聊成员信息展示,调整状态管理以防止跨联系人数据串联。
This commit is contained in:
@@ -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",
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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>
|
||||
)}
|
||||
<>
|
||||
|
||||
@@ -46,6 +46,8 @@ export interface WeChatState {
|
||||
currentMessagesPageSize: number;
|
||||
/** 是否还有更多历史消息 */
|
||||
currentMessagesHasMore: boolean;
|
||||
/** 当前消息请求ID,用于防止跨联系人数据串联 */
|
||||
currentMessagesRequestId: number;
|
||||
/** 添加新消息 */
|
||||
addMessage: (message: ChatRecord) => void;
|
||||
/** 更新指定消息 */
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -199,8 +199,6 @@ const messageHandlers: Record<string, MessageHandler> = {
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 可以继续添加更多处理器...
|
||||
};
|
||||
//消息异步同步
|
||||
const goAsyncServiceData = (message: Messages) => {
|
||||
|
||||
Reference in New Issue
Block a user