2
0
فهرست منبع

✨ feat(classroom): 添加老师全员禁言功能

- 新增AllMuteToggleButton组件,实现全员禁言切换按钮
- 添加确认对话框,防止误操作
- 在ClassroomLayout中集成全员禁言按钮
- 实现checkAllMuteStatus方法查询全员禁言状态
- 仅教师角色可见该功能按钮
- 支持禁言状态切换和加载状态显示
yourname 6 ماه پیش
والد
کامیت
6b87438144

+ 117 - 0
src/client/mobile/components/Classroom/AllMuteToggleButton.tsx

@@ -0,0 +1,117 @@
+import React, { useState, useEffect } from 'react';
+import { useClassroomContext } from './ClassroomProvider';
+import { Button } from '@/client/components/ui/button';
+import { Role } from './useClassroom';
+import { SpeakerXMarkIcon } from '@heroicons/react/24/outline';
+import {
+  AlertDialog,
+  AlertDialogAction,
+  AlertDialogCancel,
+  AlertDialogContent,
+  AlertDialogDescription,
+  AlertDialogFooter,
+  AlertDialogHeader,
+  AlertDialogTitle,
+} from '@/client/components/ui/alert-dialog';
+
+export const AllMuteToggleButton: React.FC = () => {
+  const { role, muteAllIM, unmuteAllIM, classId, checkAllMuteStatus } = useClassroomContext();
+  const [isAllMuted, setIsAllMuted] = useState(false);
+  const [loading, setLoading] = useState(false);
+
+  // 组件挂载时查询全员禁言状态
+  useEffect(() => {
+    const fetchAllMuteStatus = async () => {
+      if (!classId) return;
+      
+      try {
+        const muted = await checkAllMuteStatus();
+        setIsAllMuted(muted);
+      } catch (error) {
+        console.error('查询全员禁言状态失败:', error);
+      }
+    };
+    
+    fetchAllMuteStatus();
+  }, [classId, checkAllMuteStatus]);
+  const [confirmDialog, setConfirmDialog] = useState<{
+    open: boolean;
+    action: 'muteAll' | 'unmuteAll' | null;
+  }>({
+    open: false,
+    action: null,
+  });
+
+  // 只有老师才能看到全员禁言按钮
+  if (role !== Role.Teacher) {
+    return null;
+  }
+
+  const handleToggleAllMute = async () => {
+    if (loading || !classId) return;
+    
+    setLoading(true);
+    try {
+      if (isAllMuted) {
+        await unmuteAllIM();
+        setIsAllMuted(false);
+      } else {
+        await muteAllIM();
+        setIsAllMuted(true);
+      }
+    } catch (error) {
+      console.error('切换全员禁言状态失败:', error);
+    } finally {
+      setLoading(false);
+      setConfirmDialog({ open: false, action: null });
+    }
+  };
+
+  const openConfirmDialog = (action: 'muteAll' | 'unmuteAll') => {
+    setConfirmDialog({
+      open: true,
+      action,
+    });
+  };
+
+  const handleCancel = () => {
+    setConfirmDialog({ open: false, action: null });
+  };
+
+  return (
+    <>
+      <Button
+        onClick={() => openConfirmDialog(isAllMuted ? 'unmuteAll' : 'muteAll')}
+        className={`p-2 rounded-full ${
+          isAllMuted
+            ? 'bg-green-500 text-white hover:bg-green-600'
+            : 'bg-red-500 text-white hover:bg-red-600'
+        } transition-colors`}
+        disabled={loading}
+        title={isAllMuted ? '取消全员禁言(IM聊天)' : '全员禁言(IM聊天)'}
+        size="icon"
+        variant="ghost"
+      >
+        <SpeakerXMarkIcon className="w-4 h-4" />
+      </Button>
+
+      <AlertDialog open={confirmDialog.open} onOpenChange={(open) => !open && handleCancel()}>
+        <AlertDialogContent>
+          <AlertDialogHeader>
+            <AlertDialogTitle>操作确认</AlertDialogTitle>
+            <AlertDialogDescription>
+              {confirmDialog.action === 'muteAll' && '确定要对所有学生进行全员禁言吗?(IM聊天)'}
+              {confirmDialog.action === 'unmuteAll' && '确定要取消全员禁言吗?(IM聊天)'}
+            </AlertDialogDescription>
+          </AlertDialogHeader>
+          <AlertDialogFooter>
+            <AlertDialogCancel>取消</AlertDialogCancel>
+            <AlertDialogAction onClick={handleToggleAllMute}>
+              确定
+            </AlertDialogAction>
+          </AlertDialogFooter>
+        </AlertDialogContent>
+      </AlertDialog>
+    </>
+  );
+};

+ 2 - 0
src/client/mobile/components/Classroom/ClassroomLayout.tsx

@@ -16,6 +16,7 @@ import { TeacherClassControlButton } from './TeacherClassControlButton';
 import { TeacherStudentManagementButton } from './TeacherStudentManagementButton';
 import { TeacherHandUpManagementButton } from './TeacherHandUpManagementButton';
 import { TeacherQuestionManagementButton } from './TeacherQuestionManagementButton';
+import { AllMuteToggleButton } from './AllMuteToggleButton';
 import { StudentHandUpButton } from './StudentHandUpButton';
 import { StudentQuestionButton } from './StudentQuestionButton';
 
@@ -167,6 +168,7 @@ export const ClassroomLayout = ({ children, role }: ClassroomLayoutProps) => {
                   <TeacherStudentManagementButton />
                   <TeacherHandUpManagementButton />
                   <TeacherQuestionManagementButton />
+                  <AllMuteToggleButton />
                 </>
               )}
 

+ 15 - 1
src/client/mobile/components/Classroom/useClassroom.ts

@@ -1063,6 +1063,19 @@ export const useClassroom = ({ user }:{ user : User }) => {
     }
   };
 
+  // 查询全员禁言状态
+  const checkAllMuteStatus = async (): Promise<boolean> => {
+    if (!imGroupManager.current || !classId) return false;
+    
+    try {
+      const groupInfo = await imGroupManager.current.queryGroup(classId);
+      return groupInfo.muteStatus?.muteAll || false;
+    } catch (error) {
+      console.error('查询全员禁言状态失败:', error);
+      return false;
+    }
+  };
+
   const answerHandUp = async (studentId: string): Promise<void> => {
     if (!imMessageManager.current || !classId || role !== Role.Teacher) return;
     
@@ -1169,7 +1182,8 @@ export const useClassroom = ({ user }:{ user : User }) => {
     unmuteStudentIM,
     muteAllIM,
     unmuteAllIM,
-    checkMuteStatus
+    checkMuteStatus,
+    checkAllMuteStatus
   };
 };