Browse Source

feat: 为视频元素添加 preload="none" 属性优化加载性能

优化多个视频组件的加载行为,添加 preload="none" 属性避免视频在页面加载时预加载,减少初始资源消耗。同时修正了课程 ID 相关的 WebSocket 连接逻辑,简化消息处理流程,提升性能和代码可维护性。
lsc 1 week ago
parent
commit
2faeac00ab

+ 1 - 1
src/components/CollapsibleToolbar/cocolearnCom/KwlDetail.vue

@@ -91,7 +91,7 @@
           class="upload-preview-item"
         >
           <img v-if="file.type.startsWith('image/')" :src="file.url" :alt="file.name" @click="openPreview(index)" />
-          <video v-else :src="file.url" muted @click="openPreview(index)"></video>
+          <video v-else :src="file.url" preload="none" muted @click="openPreview(index)"></video>
           <div class="preview-delete" @click="removeFile(index)">
             <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
               <line x1="18" y1="6" x2="6" y2="18" />

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

@@ -498,7 +498,7 @@
               :src="lookWorkData.content.fileList[lookWorkIndex].url"
               @click.stop="lookImage(lookWorkData.content.fileList[lookWorkIndex])" />
             <!-- 视频 -->
-            <video v-else-if="getFileType(lookWorkData.content.fileList[lookWorkIndex].url) === 'video'"
+            <video preload="none" v-else-if="getFileType(lookWorkData.content.fileList[lookWorkIndex].url) === 'video'"
               :src="lookWorkData.content.fileList[lookWorkIndex].url" controls
               @click.stop="lookImage(lookWorkData.content.fileList[lookWorkIndex])" />
             <!-- 文档/PDF/Office -->
@@ -1017,7 +1017,7 @@
             <line x1="6" y1="6" x2="18" y2="18" />
           </svg>
         </div>
-        <video :src="videoPreviewUrl" controls autoplay class="file-preview-video"></video>
+        <video preload="none" :src="videoPreviewUrl" controls autoplay class="file-prvideo-video"></video>
       </div>
     </Teleport>
 

+ 14 - 17
src/views/Student/index.vue

@@ -2868,7 +2868,7 @@ const getCourseDetail = async () => {
   try {
     const res = await api.getCourseDetail(props.courseid as string)
     const opRes1 = await api.selectPPTOp({
-      id: props.courseid + '-' + props.cid,
+      id: props.courseid, //  + '-' + props.cid
       type: '1',
       index: 0
     })
@@ -4468,7 +4468,7 @@ const createWebSocketConnection = async (type = 1) => {
     docSocket.value.gc = true
     providerSocket.value = new YjsRedisProvider(
       api.yweb_socket,
-      'PPT' + props.courseid + props.cid,
+      'PPT' + props.courseid,
       docSocket.value,
       {
         params: { yauth: authToken.value },
@@ -4619,21 +4619,18 @@ const createWebSocketConnection = async (type = 1) => {
       const isReplay = subType === 1
       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']
-      // 按类型去重:同一类消息只保留最后一条(latest 与 slideIndex 是两条独立通道,
-      // 一次 syncStep2 重放会同时带上它们,不能只留全局最后一条,否则 sopen 被丢弃,
-      // 学生 isFollowModeActive 一直为 false → 之后所有 slideIndex 都被忽略,表现为"不跟随")
-      const lastByType = new Map<string, Record<string, any>>()
-      for (const obj of validObjs) {
-        const key = obj.type === 'slideIndex' ? 'slideIndex' : (obj.type || 'other')
-        lastByType.set(key, obj)
-      }
-      // slideIndex 必须最后执行(依赖 sopen 先打开跟随模式)
-      const orderedObjs = [...lastByType.entries()]
-        .sort(([a], [b]) => (a === 'slideIndex' ? 1 : 0) - (b === 'slideIndex' ? 1 : 0))
-        .map(([, v]) => v)
-      for (const obj of orderedObjs) {
-        console.log('📨 解析业务消息:', obj)
-        getMessages(obj)
+      // 过滤出有效业务消息:不带业务字段的、自己发的、历史重放的 timer_* 全部剔除
+      const validObjs = objs.filter((obj: Record<string, any>) => {
+        if (!obj.type && obj.slideIndex === undefined) return false
+        if (obj.mId && obj.mId === mId.value) return false
+        if (isReplay && typeof obj.type === 'string' && obj.type.startsWith('timer_')) return false
+        return true
+      })
+      // 一次 update 可能带多个 struct(同一 Map 多次 set),只取最后一条处理
+      const lastObj = validObjs[validObjs.length - 1]
+      if (lastObj) {
+        console.log('📨 解析业务消息:', lastObj)
+        getMessages(lastObj)
       }
 
       // ★ 消息处理后检查特殊消息数组长度,超出则清理(替代 observe 里的清理逻辑)

+ 1 - 0
src/views/components/element/FrameElement/index.vue

@@ -21,6 +21,7 @@
       >
         <!-- 视频类型(type 74):使用 video 标签 -->
         <video 
+          preload="none"
           v-if="elementInfo.toolType === 74"
           :src="elementInfo.url"
           :width="elementInfo.width"

+ 1 - 0
src/views/components/element/VideoElement/VideoPlayer/index.vue

@@ -16,6 +16,7 @@
       <canvas ref="bgCanvasRef" class="bg-canvas"></canvas>
       <video
         class="video"
+        preload="none"
         ref="videoRef"
         :src="src"
         :autoplay="autoplay"