Browse Source

fix: 修复消息同步和计时器停止的逻辑问题

注释掉了追平和激光笔消息的旧同步逻辑,修改计时器停止消息仅在创建者时触发,过滤计时器和画板类型的业务消息,修复投屏数据格式问题
lsc 1 week ago
parent
commit
5734fe2231

+ 2 - 2
src/views/Student/components/choiceQuestionDetailDialog.vue

@@ -1254,7 +1254,7 @@ const processWorkContent = async (content: string, toolType: number): Promise<an
         parsed.forEach((item: any) => {
         parsed.forEach((item: any) => {
           if (item.messages && item.messages.length) {
           if (item.messages && item.messages.length) {
             item.messages.forEach((item2: any) => {
             item.messages.forEach((item2: any) => {
-               item2.content = item2.content.replace(/&lt;/g, '<').replace(/&quot;/g, '"').replace(/&gt;/g, '>')
+              item2.content = item2.content.replace(/&lt;/g, '<').replace(/&quot;/g, '"').replace(/&gt;/g, '>')
               // 如果已经包含html标签则不再渲染
               // 如果已经包含html标签则不再渲染
               if (
               if (
                 !/^(\s*<[^>]+>.*<\/[^>]+>\s*|<[^>]+\/>\s*)$/s.test(
                 !/^(\s*<[^>]+>.*<\/[^>]+>\s*|<[^>]+\/>\s*)$/s.test(
@@ -1475,7 +1475,7 @@ const castScreen = (item: any) => {
   emit('sendMessage', {
   emit('sendMessage', {
     type: 'cast_screen',
     type: 'cast_screen',
     courseid: props.courseid,
     courseid: props.courseid,
-    workerData: item
+    workerData: JSON.stringify(item)
   })
   })
   console.log(item)
   console.log(item)
 }
 }

+ 41 - 38
src/views/Student/index.vue

@@ -3324,16 +3324,16 @@ const messageInit = () => {
 
 
   // ★ 追平:连接建立后立即读取当前 latest 和 slideIndex,
   // ★ 追平:连接建立后立即读取当前 latest 和 slideIndex,
   // 防止老师在学生 observe 注册之前发的消息丢失(尤其是当前所在幻灯片)
   // 防止老师在学生 observe 注册之前发的消息丢失(尤其是当前所在幻灯片)
-  const latest = yMessage.value.get('latest')
-  if (latest && latest.mId !== mId.value) {
-    console.log('🔗 追平当前 latest 消息:', latest)
-    getMessages(latest)
-  }
-  const slideIdx = yMessage.value.get('slideIndex')
-  if (slideIdx && slideIdx.mId !== mId.value) {
-    console.log('🔗 追平当前 slideIndex 消息:', slideIdx)
-    getMessages(slideIdx)
-  }
+  // const latest = yMessage.value.get('latest')
+  // if (latest && latest.mId !== mId.value) {
+  //   console.log('🔗 追平当前 latest 消息:', latest)
+  //   getMessages(latest)
+  // }
+  // const slideIdx = yMessage.value.get('slideIndex')
+  // if (slideIdx && slideIdx.mId !== mId.value) {
+  //   console.log('🔗 追平当前 slideIndex 消息:', slideIdx)
+  //   getMessages(slideIdx)
+  // }
 
 
   // 计时器消息数组
   // 计时器消息数组
   yTimerMessages.value = doc.getArray('timerMessages')
   yTimerMessages.value = doc.getArray('timerMessages')
@@ -3358,26 +3358,26 @@ const messageInit = () => {
   })
   })
 
 
   // 激光笔消息数组
   // 激光笔消息数组
-  yLaserMessages.value = doc.getArray('laserMessages')
-  if (yLaserMessages.value.length > 500 && isCreator.value) {
-    smartCleanupMessages(yLaserMessages.value, 500, 'laser', doc)
-  }
-  yLaserMessages.value.observe((e: any) => {
-    if (yLaserMessages.value.length > 500 && isCreator.value) {
-      setTimeout(() => {
-        if (yLaserMessages.value && yLaserMessages.value.length > 500) {
-          smartCleanupMessages(yLaserMessages.value, 500, 'laser', doc)
-        }
-      }, 0)
-    }
-    e.changes.added.forEach((i: any) => {
-      const message = i.content.getContent()[0]
-      // 只处理开关消息,位置消息直接通过 Map 同步
-      if (message.type === 'laser_toggle' && message.mId !== mId.value) {
-        getMessages(message)
-      }
-    })
-  })
+  // yLaserMessages.value = doc.getArray('laserMessages')
+  // if (yLaserMessages.value.length > 500 && isCreator.value) {
+  //   smartCleanupMessages(yLaserMessages.value, 500, 'laser', doc)
+  // }
+  // yLaserMessages.value.observe((e: any) => {
+  //   if (yLaserMessages.value.length > 500 && isCreator.value) {
+  //     setTimeout(() => {
+  //       if (yLaserMessages.value && yLaserMessages.value.length > 500) {
+  //         smartCleanupMessages(yLaserMessages.value, 500, 'laser', doc)
+  //       }
+  //     }, 0)
+  //   }
+  //   e.changes.added.forEach((i: any) => {
+  //     const message = i.content.getContent()[0]
+  //     // 只处理开关消息,位置消息直接通过 Map 同步
+  //     if (message.type === 'laser_toggle' && message.mId !== mId.value) {
+  //       // getMessages(message)
+  //     }
+  //   })
+  // })
 
 
   // 画图消息数组
   // 画图消息数组
   yWritingBoardMessages.value = doc.getArray('writingBoardMessages')
   yWritingBoardMessages.value = doc.getArray('writingBoardMessages')
@@ -3416,7 +3416,7 @@ const messageInit = () => {
     e.changes.added.forEach((i: any) => {
     e.changes.added.forEach((i: any) => {
       const message = i.content.getContent()[0]
       const message = i.content.getContent()[0]
       if (message.mId !== mId.value) {
       if (message.mId !== mId.value) {
-        getMessages(message)
+        // getMessages(message)
       }
       }
     })
     })
   })
   })
@@ -3741,7 +3741,7 @@ const getMessages = (msgObj: any) => {
   if (msgObj.type === 'timer_reset' && msgObj.courseid === props.courseid) {
   if (msgObj.type === 'timer_reset' && msgObj.courseid === props.courseid) {
     applyTimerReset()
     applyTimerReset()
   }
   }
-  if (msgObj.type === 'timer_stop' && msgObj.courseid === props.courseid) {
+  if (msgObj.type === 'timer_stop' && msgObj.courseid === props.courseid && msgObj.isCreator === 'T') {
     applyTimerStop()
     applyTimerStop()
   }
   }
   if (msgObj.type === 'timer_finish' && msgObj.courseid === props.courseid) {
   if (msgObj.type === 'timer_finish' && msgObj.courseid === props.courseid) {
@@ -3853,7 +3853,7 @@ const getMessages = (msgObj: any) => {
     openChoiceQuestionDetail3(slideIndex.value)
     openChoiceQuestionDetail3(slideIndex.value)
     setTimeout(() => {
     setTimeout(() => {
       is_cast_screen.value = true
       is_cast_screen.value = true
-      choiceQuestionDetailDialogRef.value?.castScreen?.(msgObj.workerData)
+      choiceQuestionDetailDialogRef.value?.castScreen?.(JSON.parse(msgObj.workerData))
     }, 500)
     }, 500)
   }
   }
 
 
@@ -3927,7 +3927,7 @@ const openChoiceQuestionDetail3 = (index:number) => {
 
 
 const handlePageUnload = () => {
 const handlePageUnload = () => {
   if (isCreator.value && timerIndicator.value.visible && props.type === '1') {
   if (isCreator.value && timerIndicator.value.visible && props.type === '1') {
-    sendMessage({ type: 'timer_stop', courseid: props.courseid })
+    sendMessage({ type: 'timer_stop', courseid: props.courseid, isCreator: isCreator.value ? 'T' : 'F' })
   }
   }
   // 创建老师刷新/关闭页面时,清空所有同步状态
   // 创建老师刷新/关闭页面时,清空所有同步状态
   if (isCreator.value && props.type === '1') {
   if (isCreator.value && props.type === '1') {
@@ -4164,7 +4164,7 @@ onMounted(() => {
       // 页面被隐藏时,清空所有同步状态
       // 页面被隐藏时,清空所有同步状态
       clearAllSyncStates()
       clearAllSyncStates()
       if (timerIndicator.value.visible && isCreator.value) {
       if (timerIndicator.value.visible && isCreator.value) {
-        sendMessage({ type: 'timer_stop', courseid: props.courseid })
+        sendMessage({ type: 'timer_stop', courseid: props.courseid, isCreator: isCreator.value ? 'T' : 'F' })
       }
       }
     }
     }
   }
   }
@@ -4515,7 +4515,8 @@ const createWebSocketConnection = async (type = 1) => {
     providerSocket.value.on('raw-message', (data: Uint8Array) => {
     providerSocket.value.on('raw-message', (data: Uint8Array) => {
       const objs = parseYjsMessage(data)
       const objs = parseYjsMessage(data)
       if (!objs || objs.length === 0) return
       if (!objs || objs.length === 0) return
-
+      const timerTypes = ['timer_start', 'timer_pause', 'timer_reset', 'timer_stop', 'timer_finish', 'timer_update']
+      const writingBoardTypes = ['writing_board_update', 'writing_board_close', 'writing_board_blackboard']
       for (const obj of objs) {
       for (const obj of objs) {
         // 过滤掉不带业务字段的
         // 过滤掉不带业务字段的
         if (!obj.type && obj.slideIndex === undefined) continue
         if (!obj.type && obj.slideIndex === undefined) continue
@@ -4523,7 +4524,9 @@ const createWebSocketConnection = async (type = 1) => {
         if (obj.mId && obj.mId === mId.value) continue
         if (obj.mId && obj.mId === mId.value) continue
 
 
         console.log('📨 解析业务消息:', obj)
         console.log('📨 解析业务消息:', obj)
-        getMessages(obj)
+        if (!timerTypes.includes(obj.type) && !writingBoardTypes.includes(obj.type)) {
+          getMessages(obj)
+        }
       }
       }
 
 
       // ★ 消息处理后检查特殊消息数组长度,超出则清理(替代 observe 里的清理逻辑)
       // ★ 消息处理后检查特殊消息数组长度,超出则清理(替代 observe 里的清理逻辑)
@@ -4824,7 +4827,7 @@ const onTimerStop = () => {
   }
   }
   timerIndicator.value = { visible: false, isCountdown: false, startAt: null, durationSec: null, elapsedSec: null, remainingSec: null, finished: false }
   timerIndicator.value = { visible: false, isCountdown: false, startAt: null, durationSec: null, elapsedSec: null, remainingSec: null, finished: false }
   if (isCreator.value) {
   if (isCreator.value) {
-    sendMessage({ type: 'timer_stop', courseid: props.courseid })
+    sendMessage({ type: 'timer_stop', courseid: props.courseid, isCreator: isCreator.value ? 'T' : 'F' })
     clearTimerState()
     clearTimerState()
   }
   }
 }
 }