Procházet zdrojové kódy

♻️ refactor(classroom): restructure message saving logic

- remove duplicate saveMessageToDatabase calls from message display functions
- add senderId and sender default values to history message mapping
- implement centralized message saving before sending for all message types
- add check to prevent duplicate processing of own messages
- update saveMessageToDatabase to handle all message types consistently

✨ feat(classroom): enhance message persistence reliability

- change message saving to synchronous before sending for better data consistency
- add detailed system message logging for classroom actions
- include fileId in image message storage instead of full URL
- add proper sender information to all system messages
- ensure all interaction events are properly logged in database

🐛 fix(classroom): resolve message duplication issue

- add check to prevent processing own sent messages
- remove redundant message saving from multiple event handlers
- ensure message senderId and sender fields are always populated
- fix potential undefined values in message sender information
yourname před 6 měsíci
rodič
revize
f496cf2c8a

+ 96 - 29
src/client/mobile/components/Classroom/useClassroom.ts

@@ -128,10 +128,6 @@ export const useClassroom = ({ user }:{ user : User }) => {
       timestamp: Date.now()
     };
     setMessageList((prevMessageList) => [...prevMessageList, message]);
-    // 异步保存消息到数据库
-    saveMessageToDatabase(message).catch(() => {
-      // 静默失败,已经在saveMessageToDatabase中处理了错误
-    });
   };
 
   const showImageMessage = (imageUrl: string, senderName: string, senderId?: string): void => {
@@ -143,10 +139,6 @@ export const useClassroom = ({ user }:{ user : User }) => {
       timestamp: Date.now()
     };
     setMessageList((prevMessageList) => [...prevMessageList, message]);
-    // 异步保存消息到数据库
-    saveMessageToDatabase(message).catch(() => {
-      // 静默失败,已经在saveMessageToDatabase中处理了错误
-    });
   };
 
   const showSystemMessage = (text: string): void => {
@@ -156,10 +148,6 @@ export const useClassroom = ({ user }:{ user : User }) => {
       timestamp: Date.now()
     };
     setMessageList((prevMessageList) => [...prevMessageList, message]);
-    // 异步保存系统消息到数据库
-    saveMessageToDatabase(message).catch(() => {
-      // 静默失败,已经在saveMessageToDatabase中处理了错误
-    });
   };
 
   // 保存消息到数据库
@@ -339,13 +327,9 @@ export const useClassroom = ({ user }:{ user : User }) => {
           if (data.action === 'start_class') {
             setClassStatus(ClassStatus.IN_PROGRESS);
             showSystemMessage('老师已开始上课');
-            // 保存课堂开始消息到数据库
-            saveImMessageToDatabase(msg, 'system', '老师已开始上课', '系统').catch(() => {});
           } else if (data.action === 'end_class') {
             setClassStatus(ClassStatus.ENDED);
             showSystemMessage('老师已结束上课');
-            // 保存课堂结束消息到数据库
-            saveImMessageToDatabase(msg, 'system', '老师已结束上课', '系统').catch(() => {});
             
             // 学生端收到结束课堂消息后,立即自动离开群组
             if (role === Role.Student) {
@@ -377,8 +361,6 @@ export const useClassroom = ({ user }:{ user : User }) => {
           const data = JSON.parse(msg.data);
           if (data.action === 'toggle_mute' && data.userId === userId) {
             showSystemMessage(data.mute ? '你已被老师静音' : '老师已取消你的静音');
-            // 保存静音消息到数据库
-            saveImMessageToDatabase(msg, 'system', data.mute ? '你已被老师静音' : '老师已取消你的静音', '系统').catch(() => {});
           }
         } catch (err) {
           console.error('解析静音指令失败', err);
@@ -393,8 +375,6 @@ export const useClassroom = ({ user }:{ user : User }) => {
             };
             setHandUpList([...handUpList, handUpData]);
             showSystemMessage(`${data.studentName || data.studentId} 举手了`);
-            // 保存举手消息到数据库
-            saveImMessageToDatabase(msg, 'system', `${data.studentName || data.studentId} 举手了`, '系统').catch(() => {});
           } else if (data.action === InteractionAction.CancelHandUp) {
             setHandUpList(handUpList.filter(h => h.studentId !== data.studentId));
           }
@@ -420,8 +400,6 @@ export const useClassroom = ({ user }:{ user : User }) => {
             setQuestions([...questions, question]);
           }
           showSystemMessage(`收到问题: ${data.question}`);
-          // 保存问题消息到数据库
-          saveImMessageToDatabase(msg, 'system', `收到问题: ${data.question}`, '系统').catch(() => {});
         } catch (err) {
           console.error('解析问题消息失败', err);
         }
@@ -431,8 +409,6 @@ export const useClassroom = ({ user }:{ user : User }) => {
           if (data.action === InteractionAction.AnswerHandUp && data.studentId === userId) {
             showSystemMessage('老师已应答你的举手');
             setHandUpList(handUpList.filter(h => h.studentId !== data.studentId));
-            // 保存应答消息到数据库
-            saveImMessageToDatabase(msg, 'system', '老师已应答你的举手', '系统').catch(() => {});
           }
         } catch (err) {
           console.error('解析应答消息失败', err);
@@ -442,8 +418,6 @@ export const useClassroom = ({ user }:{ user : User }) => {
           const data = JSON.parse(msg.data) as InteractionMessage;
           if (data.action === InteractionAction.KickStudent && data.studentId === userId) {
             showSystemMessage('您已被老师移出课堂');
-            // 保存踢人消息到数据库
-            saveImMessageToDatabase(msg, 'system', '您已被老师移出课堂', '系统').catch(() => {});
             // 学生被踢出后自动离开课堂
             setTimeout(() => {
               leaveClass();
@@ -454,6 +428,10 @@ export const useClassroom = ({ user }:{ user : User }) => {
         }
       } else if (msg.type === 88888) { // 普通文本消息
         const sender = msg.sender;
+        // 检查消息来源,避免重复处理自己发送的消息
+        if (sender?.userId === userId) {
+          return; // 自己发送的消息已经在发送时处理过了,不再重复显示
+        }
         // 使用正确的 ImUser 类型处理发送者信息
         const userExtension = sender?.userExtension ? JSON.parse(sender.userExtension) : {};
         const senderName = userExtension.nickname || userExtension.username || sender?.userId || '未知用户';
@@ -463,6 +441,10 @@ export const useClassroom = ({ user }:{ user : User }) => {
           const data = JSON.parse(msg.data);
           if (data.type === 'image' && data.fileId) {
             const sender = msg.sender;
+            // 检查消息来源,避免重复处理自己发送的消息
+            if (sender?.userId === userId) {
+              return; // 自己发送的消息已经在发送时处理过了,不再重复显示
+            }
             // 使用正确的 ImUser 类型处理发送者信息
             const userExtension = sender?.userExtension ? JSON.parse(sender.userExtension) : {};
             const senderName = userExtension.nickname || userExtension.username || sender?.userId || '未知用户';
@@ -765,11 +747,11 @@ export const useClassroom = ({ user }:{ user : User }) => {
           const historyData = await response.json();
           if (historyData.data && historyData.data.length > 0) {
             // 将历史消息添加到消息列表
-            const historyMessages: Message[] = historyData.data.map((msg: any) => ({
+            const historyMessages: Message[] = historyData.data.map((msg) => ({
               type: msg.type,
               content: msg.content,
-              sender: msg.senderName || msg.senderId,
-              senderId: msg.senderId,
+              sender: msg.senderName || msg.senderId || '',
+              senderId: msg.senderId || '',
               timestamp: msg.timestamp
             }));
             
@@ -873,6 +855,17 @@ export const useClassroom = ({ user }:{ user : User }) => {
     }
 
     try {
+      // 先保存消息到数据库
+      const message: Message = {
+        type: 'text',
+        content: msgText,
+        sender: user?.nickname || user?.username || '',
+        senderId: userId,
+        timestamp: Date.now()
+      };
+      await saveMessageToDatabase(message);
+      
+      // 然后发送IM消息
       await imMessageManager.current.sendGroupMessage({
         groupId: classId,
         data: msgText,
@@ -895,6 +888,17 @@ export const useClassroom = ({ user }:{ user : User }) => {
     if (!imMessageManager.current || !classId) return;
 
     try {
+      // 先保存消息到数据库,保存fileId而不是完整的URL
+      const message: Message = {
+        type: 'image',
+        content: fileId.toString(),
+        sender: user?.nickname || user?.username || '',
+        senderId: userId,
+        timestamp: Date.now()
+      };
+      await saveMessageToDatabase(message);
+      
+      // 然后发送IM消息
       await imMessageManager.current!.sendGroupMessage({
         groupId: classId,
         data: JSON.stringify({
@@ -920,6 +924,15 @@ export const useClassroom = ({ user }:{ user : User }) => {
     if (!imMessageManager.current || !classId || role !== Role.Teacher) return;
     
     try {
+      // 先保存开始上课消息到数据库
+      await saveMessageToDatabase({
+        type: 'system',
+        content: '老师已开始上课',
+        sender: user?.nickname || user?.username || '老师',
+        senderId: userId,
+        timestamp: Date.now()
+      });
+      
       await imMessageManager.current.sendGroupMessage({
         groupId: classId,
         data: JSON.stringify({ action: 'start_class' }),
@@ -937,6 +950,15 @@ export const useClassroom = ({ user }:{ user : User }) => {
     if (!imMessageManager.current || !classId || role !== Role.Teacher) return;
     
     try {
+      // 先保存结束上课消息到数据库
+      await saveMessageToDatabase({
+        type: 'system',
+        content: '老师已结束上课',
+        sender: user?.nickname || user?.username || '老师',
+        senderId: userId,
+        timestamp: Date.now()
+      });
+      
       // 1. 发送结束课堂消息
       await imMessageManager.current.sendGroupMessage({
         groupId: classId,
@@ -982,6 +1004,15 @@ export const useClassroom = ({ user }:{ user : User }) => {
     if (!imMessageManager.current || !classId || role !== Role.Teacher) return;
     
     try {
+      // 先保存静音消息到数据库
+      await saveMessageToDatabase({
+        type: 'system',
+        content: mute ? `老师已将用户 ${userId} 静音` : `老师已取消用户 ${userId} 的静音`,
+        sender: user?.nickname || user?.username || '老师',
+        senderId: userId,
+        timestamp: Date.now()
+      });
+      
       // 1. 发送IM消息通知静音状态变化
       await imMessageManager.current.sendGroupMessage({
         groupId: classId,
@@ -1196,6 +1227,15 @@ export const useClassroom = ({ user }:{ user : User }) => {
     if (!imMessageManager.current || !classId || role !== 'student') return;
     
     try {
+      // 先保存举手消息到数据库
+      await saveMessageToDatabase({
+        type: 'system',
+        content: question ? `学生 ${userId} 举手提问: ${question}` : `学生 ${userId} 举手`,
+        sender: user?.nickname || user?.username || `学生${userId}`,
+        senderId: userId,
+        timestamp: Date.now()
+      });
+      
       await imMessageManager.current.sendGroupMessage({
         groupId: classId,
         data: JSON.stringify({
@@ -1248,6 +1288,15 @@ export const useClassroom = ({ user }:{ user : User }) => {
     if (!imGroupManager.current || !classId || role !== Role.Teacher) return;
     
     try {
+      // 先保存踢人消息到数据库
+      await saveMessageToDatabase({
+        type: 'system',
+        content: `老师已将用户 ${studentId} 移出课堂`,
+        sender: user?.nickname || user?.username || '老师',
+        senderId: userId,
+        timestamp: Date.now()
+      });
+      
       // 使用InteractionAction发送踢人消息
       await imMessageManager.current?.sendGroupMessage({
         groupId: classId,
@@ -1404,6 +1453,15 @@ export const useClassroom = ({ user }:{ user : User }) => {
     if (!imMessageManager.current || !classId || role !== Role.Teacher) return;
     
     try {
+      // 先保存应答举手消息到数据库
+      await saveMessageToDatabase({
+        type: 'system',
+        content: `老师已应答学生 ${studentId} 的举手`,
+        sender: user?.nickname || user?.username || '老师',
+        senderId: userId,
+        timestamp: Date.now()
+      });
+      
       await imMessageManager.current.sendGroupMessage({
         groupId: classId,
         data: JSON.stringify({
@@ -1423,6 +1481,15 @@ export const useClassroom = ({ user }:{ user : User }) => {
     if (!imMessageManager.current || !classId) return;
     
     try {
+      // 先保存问题消息到数据库
+      await saveMessageToDatabase({
+        type: 'system',
+        content: `问题: ${question}`,
+        sender: user?.nickname || user?.username || `用户${userId}`,
+        senderId: userId,
+        timestamp: Date.now()
+      });
+      
       await imMessageManager.current.sendGroupMessage({
         groupId: classId,
         data: question,