Преглед изворни кода

- 添加HandUpRequest类型定义
- 实现举手状态同步
- 创建互动消息面板
- 添加老师应答控制

yourname пре 7 месеци
родитељ
комит
2c438d9ef7
1 измењених фајлова са 120 додато и 1 уклоњено
  1. 120 1
      client/mobile/pages_classroom.tsx

+ 120 - 1
client/mobile/pages_classroom.tsx

@@ -30,6 +30,23 @@ enum ClassStatus {
 }
 
 // 课堂上下文类型
+// 互动消息类型
+type InteractionAction = 'hand_up' | 'cancel_hand_up' | 'answer_hand_up';
+
+// 互动消息基础接口
+interface InteractionMessage {
+  action: InteractionAction;
+  studentId: string;
+  studentName?: string;
+  timestamp?: number;
+  question?: string;
+}
+
+// 举手请求类型
+interface HandUpRequest extends InteractionMessage {
+  timestamp: number;
+}
+
 type ClassroomContextType = {
   userId: string;
   role: 'teacher' | 'student';
@@ -38,10 +55,15 @@ type ClassroomContextType = {
   messageList: string[];
   errorMessage: string;
   classStatus: ClassStatus;
+  handUpList: HandUpRequest[]; // 举手列表
+  questions: string[]; // 问题列表
   setRole: (role: 'teacher' | 'student') => void;
   startClass: () => Promise<void>;
   endClass: () => Promise<void>;
   toggleMuteMember: (userId: string, mute: boolean) => Promise<void>;
+  handUp: (question?: string) => Promise<void>; // 学生举手
+  answerHandUp: (studentId: string) => Promise<void>; // 老师应答
+  sendQuestion: (question: string) => Promise<void>; // 发送问题
 };
 
 const ClassroomContext = createContext<ClassroomContextType | null>(null);
@@ -108,6 +130,8 @@ export const ClassroomPage = () => {
   const [messageList, setMessageList] = useState<string[]>([]);
   const [errorMessage, setErrorMessage] = useState<string>('');
   const [classStatus, setClassStatus] = useState<ClassStatus>(ClassStatus.NOT_STARTED);
+  const [handUpList, setHandUpList] = useState<HandUpRequest[]>([]);
+  const [questions, setQuestions] = useState<string[]>([]);
 
   // SDK实例
   const imEngine = useRef<ImEngine | null>(null);
@@ -170,6 +194,40 @@ export const ClassroomPage = () => {
         }
       } else {
         showMessage(`收到消息: ${msg.data}`);
+      } else if (msg.type === 88891) { // 举手消息
+        try {
+          const data = JSON.parse(msg.data) as InteractionMessage;
+          if (data.action === 'hand_up') {
+            const handUpData: HandUpRequest = {
+              ...data,
+              timestamp: data.timestamp || Date.now()
+            };
+            setHandUpList([...handUpList, handUpData]);
+            showMessage(`${data.studentName || data.studentId} 举手了`);
+          } else if (data.action === 'cancel_hand_up') {
+            setHandUpList(handUpList.filter(h => h.studentId !== data.studentId));
+          }
+        } catch (err) {
+          console.error('解析举手消息失败', err);
+        }
+      } else if (msg.type === 88892) { // 问题消息
+        try {
+          const data = JSON.parse(msg.data) as {question: string};
+          setQuestions([...questions, data.question]);
+          showMessage(`收到问题: ${data.question}`);
+        } catch (err) {
+          console.error('解析问题消息失败', err);
+        }
+      } else if (msg.type === 88893) { // 应答消息
+        try {
+          const data = JSON.parse(msg.data) as InteractionMessage;
+          if (data.action === 'answer_hand_up' && data.studentId === userId) {
+            showMessage('老师已应答你的举手');
+            setHandUpList(handUpList.filter(h => h.studentId !== data.studentId));
+          }
+        } catch (err) {
+          console.error('解析应答消息失败', err);
+        }
       }
     });
   };
@@ -377,6 +435,62 @@ export const ClassroomPage = () => {
     };
   }, []);
 
+  // 学生举手
+  const handUp = async (question?: string): Promise<void> => {
+    if (!imMessageManager.current || !classId || role !== 'student') return;
+    
+    try {
+      await imMessageManager.current.sendGroupMessage({
+        groupId: classId,
+        data: JSON.stringify({
+          action: 'hand_up',
+          studentId: userId,
+          timestamp: Date.now(),
+          question
+        }),
+        type: 88891,
+        level: ImMessageLevel.NORMAL,
+      });
+    } catch (err: any) {
+      setErrorMessage(`举手失败: ${err.message}`);
+    }
+  };
+
+  // 老师应答举手
+  const answerHandUp = async (studentId: string): Promise<void> => {
+    if (!imMessageManager.current || !classId || role !== 'teacher') return;
+    
+    try {
+      await imMessageManager.current.sendGroupMessage({
+        groupId: classId,
+        data: JSON.stringify({
+          action: 'answer_hand_up',
+          studentId
+        }),
+        type: 88893,
+        level: ImMessageLevel.HIGH,
+      });
+    } catch (err: any) {
+      setErrorMessage(`应答失败: ${err.message}`);
+    }
+  };
+
+  // 发送问题
+  const sendQuestion = async (question: string): Promise<void> => {
+    if (!imMessageManager.current || !classId) return;
+    
+    try {
+      await imMessageManager.current.sendGroupMessage({
+        groupId: classId,
+        data: question,
+        type: 88892,
+        level: ImMessageLevel.NORMAL,
+      });
+    } catch (err: any) {
+      setErrorMessage(`问题发送失败: ${err.message}`);
+    }
+  };
+
   return (
     <ClassroomContext.Provider value={{
       userId,
@@ -386,10 +500,15 @@ export const ClassroomPage = () => {
       messageList,
       errorMessage,
       classStatus,
+      handUpList,
+      questions,
       setRole,
       startClass,
       endClass,
-      toggleMuteMember
+      toggleMuteMember,
+      handUp,
+      answerHandUp,
+      sendQuestion
     }}>
       <div className="container mx-auto p-4">
         <h1 className="text-2xl font-bold mb-4">互动课堂</h1>