Browse Source

修改判断逻辑及修改禁止拖动

yangg 1 tháng trước cách đây
mục cha
commit
b8e542f556
1 tập tin đã thay đổi với 179 bổ sung239 xóa
  1. 179 239
      pages/identity-verify/identity-verify.vue

+ 179 - 239
pages/identity-verify/identity-verify.vue

@@ -30,7 +30,9 @@
           :controls="false"
           @error="handleVideoError"
           @ended="handleVideoEnded"
-          @timeupdate="handleTimeUpdate">
+          @timeupdate="handleTimeUpdate"
+          @click.prevent="preventVideoControl"
+          @touchstart.prevent="preventVideoControl">
         </video>
          <div class="answer-button-container" v-if="showAnswerButton">
           <button class="answer-button" @click="handleAnswerButtonClick">
@@ -244,6 +246,9 @@ export default {
       ], // 用于存储低分提示视频的字幕
       retryCount: 0, // 添加重试次数计数器
       maxRetryAttempts: 2, // 最大重试次数限制
+      needPlayLowScoreVideo: false, // 是否需要播放低分视频
+      finalRecordingDuration: 0, // 最终录制时长
+      historyTime: 0, // 添加历史时间记录
     }
   },
   mounted() {
@@ -263,8 +268,8 @@ export default {
       }
     }, 3000);
     
-    // 初始化 WebSocket 连接
-    this.initWebSocketConnection();
+    // 初始化历史时间记录
+    this.historyTime = 0;
     
     uni.setKeepScreenOn({
       keepScreenOn: true
@@ -277,8 +282,8 @@ export default {
     // 清除倒计时定时器
     this.clearCountdown();
     
-    // 关闭 WebSocket 连接
-    this.closeWebSocketConnection();
+    // 移除 WebSocket 连接关闭
+    // this.closeWebSocketConnection();
   },
   methods: {
     // 初始化相机
@@ -822,7 +827,36 @@ export default {
 
     // 处理视频结束事件
     handleVideoEnded() {
-      console.log('视频播放结束');
+      console.log('视频播放结束事件触发');
+      
+      // 获取视频元素和当前时间
+      const videoElement = this.$refs.videoPlayer;
+      if (videoElement) {
+        const currentTime = videoElement.currentTime || 0;
+        const duration = videoElement.duration || 0;
+        
+        // 更严格的检查:只有当前时间非常接近视频总时长时才认为是真正结束
+        if (duration > 0 && (duration - currentTime > 0.5)) {
+          console.log('检测到可能的误触发结束事件,继续播放', currentTime, duration);
+          // 继续播放视频
+          setTimeout(() => {
+            const videoContext = uni.createVideoContext('myVideo', this);
+            if (videoContext) {
+              // 如果距离结束还很远,回到历史位置
+              if (duration - currentTime > 2) {
+                videoContext.seek(this.historyTime || 0);
+              } else {
+                // 如果接近结束但还没完全结束,继续播放
+                videoContext.play();
+              }
+            }
+          }, 100);
+          return;
+        }
+        
+        console.log('视频确认结束,当前时间:', currentTime, '总时长:', duration);
+      }
+      
       this.videoPlaying = false;
       
       // 检查是否是低分提示视频
@@ -908,19 +942,20 @@ export default {
       this.startRecordingAnswer();
     },
 
-    // 修改 stopRecordingAnswer 方法,确保清除倒计时
+    // 修改 stopRecordingAnswer 方法,添加录制时长检查
     stopRecordingAnswer() {
       // 如果倒计时正在进行,先清除倒计时
       this.clearCountdown();
       
       // 检查录制时长
       const recordingDuration = this.getRecordingDuration();
-      const minimumDuration = 5; // 最小录制时长(秒)
+      const minimumDuration = 3; // 最小录制时长(秒),改为3秒
+      const lowScoreDuration = 7; // 低分阈值时长(秒),少于7秒视为低分
       
       if (recordingDuration < minimumDuration) {
         // 录制时间过短,显示提示
         uni.showToast({
-          title: '录制时间过短,请至少录制5秒',
+          title: '录制时间过短,请至少录制3秒',
           icon: 'none',
           duration: 2000
         });
@@ -928,8 +963,17 @@ export default {
         return;
       }
       
-      // 录制时长足够,直接停止
+      // 录制时长足够,停止录制
       this.completeRecordingStop();
+      
+      // 检查是否需要播放低分视频(录制时间少于7秒)
+      if (recordingDuration < lowScoreDuration) {
+        console.log(`录制时间 ${recordingDuration} 秒,少于 ${lowScoreDuration} 秒,将播放低分提示视频`);
+        // 设置标记,在上传完成后播放低分视频
+        this.needPlayLowScoreVideo = true;
+      } else {
+        this.needPlayLowScoreVideo = false;
+      }
     },
 
     // 添加新方法:开始录制用户回答
@@ -1386,12 +1430,13 @@ export default {
       
       // 检查录制时长
       const recordingDuration = this.getRecordingDuration();
-      const minimumDuration = 5; // 最小录制时长(秒),从3秒改为5秒
+      const minimumDuration = 3; // 最小录制时长(秒),改为3秒
+      const lowScoreDuration = 7; // 低分阈值时长(秒),少于7秒视为低分
       
       if (recordingDuration < minimumDuration) {
         // 录制时间过短,显示提示
         uni.showToast({
-          title: '录制时间过短,请至少录制5秒',
+          title: '录制时间过短,请至少录制3秒',
           icon: 'none',
           duration: 2000
         });
@@ -1399,8 +1444,17 @@ export default {
         return;
       }
       
-      // 录制时长足够,直接停止
+      // 录制时长足够,停止录制
       this.completeRecordingStop();
+      
+      // 检查是否需要播放低分视频(录制时间少于7秒)
+      if (recordingDuration < lowScoreDuration) {
+        console.log(`录制时间 ${recordingDuration} 秒,少于 ${lowScoreDuration} 秒,将播放低分提示视频`);
+        // 设置标记,在上传完成后播放低分视频
+        this.needPlayLowScoreVideo = true;
+      } else {
+        this.needPlayLowScoreVideo = false;
+      }
     },
 
     // 添加新方法:获取录制时长
@@ -1475,7 +1529,7 @@ export default {
       });
     },
 
-    // 添加新方法:完成录制停止流程
+    // 修改 completeRecordingStop 方法,添加录制时长检查
     completeRecordingStop() {
       this.isRecording = false;
       
@@ -1497,6 +1551,9 @@ export default {
       // 隐藏停止录制按钮
       this.showStopRecordingButton = false;
       
+      // 保存最终录制时长
+      this.finalRecordingDuration = this.getRecordingDuration();
+      
       // 根据平台选择不同的停止录制方法
       const systemInfo = uni.getSystemInfoSync();
       const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith('mp-');
@@ -1637,11 +1694,10 @@ export default {
         this.processUploadQueue();
       }
       
-      // 注意:不再自动进入下一个问题
-      // 我们会在WebSocket回调中决定是否进入下一个问题
+      // 注意:不再使用WebSocket回调,而是根据录制时长决定是否播放低分视频
     },
     
-    // 添加新方法:处理上传队列
+    // 修改 processUploadQueue 方法,在上传完成后检查是否需要播放低分视频
     processUploadQueue() {
       // 如果队列为空,结束处理
       if (this.uploadQueue.length === 0) {
@@ -1848,7 +1904,7 @@ export default {
       }
     },
     
-    // 修改 submitVideoToInterview 方法,添加 WebSocket 连接和分数检查
+    // 修改 submitVideoToInterview 方法,在提交成功后检查是否需要播放低分视频
     submitVideoToInterview(videoUrl, task = null) {
       console.log('提交视频URL到面试接口:', videoUrl);
       
@@ -1912,8 +1968,17 @@ export default {
               //   duration: 1500
               // });
               
-              // 连接WebSocket获取分析结果
-              this.connectToWebSocketForAnalysis(questionId, videoUrl);
+              // 检查是否需要播放低分视频
+              if (this.needPlayLowScoreVideo && this.retryCount < 1) {
+                // 播放低分提示视频
+                this.playLowScoreVideo();
+                // 重置标记
+                this.needPlayLowScoreVideo = false;
+              } else {
+                // 重置重试次数并继续下一题
+                this.retryCount = 0;
+                this.proceedToNextQuestion();
+              }
               
               // 继续处理队列中的下一个任务
               this.processUploadQueue();
@@ -1924,8 +1989,17 @@ export default {
                 icon: 'success'
               });
               
-              // 连接WebSocket获取分析结果
-              this.connectToWebSocketForAnalysis(questionId, videoUrl);
+              // 检查是否需要播放低分视频
+              if (this.needPlayLowScoreVideo && this.retryCount < 1) {
+                // 播放低分提示视频
+                this.playLowScoreVideo();
+                // 重置标记
+                this.needPlayLowScoreVideo = false;
+              } else {
+                // 重置重试次数并继续下一题
+                this.retryCount = 0;
+                this.proceedToNextQuestion();
+              }
               
               // 保存最后上传的视频URL
               this.lastUploadedVideoUrl = videoUrl;
@@ -2047,36 +2121,21 @@ export default {
       }
     },
     
-    // 修改 proceedToNextQuestion 方法,不要自动进入下一个问题
-    // 因为现在我们会在WebSocket回调中决定是否进入下一个问题
+    // 修改 proceedToNextQuestion 方法,确保在切换视频时重置历史时间
     proceedToNextQuestion() {
-      // 重置重试计数器
-      this.retryCount = 0;
-      
-      // 检查是否完成了第五个视频问题(索引为4)
-      if (this.currentVideoIndex === 4) {
-        // 完成第五个问题后,跳转到相机页面
-        uni.navigateTo({
-          url: '/pages/camera/camera'
-        });
-        return;
-      }
+      console.log('继续下一个问题');
       
-      // 切换到下一个视频
+      // 增加当前视频索引,切换到下一个视频
       this.currentVideoIndex++;
+      
+      // 重置历史时间,避免触发异常跳转检测
+      this.historyTime = 0;
+      
+      // 如果还有视频,播放下一个视频
       if (this.currentVideoIndex < this.videoList.length) {
-        // 还有下一段视频,播放它
         this.videoUrl = this.videoList[this.currentVideoIndex];
         this.videoPlaying = true;
         
-        // 重置GIF状态
-        /* this.showGif = false;
-        this.gifUrl = ''; */
-        
-        // 重置当前字幕
-        this.currentSubtitle = '';
-        
-        // 使用 nextTick 确保 DOM 更新后再播放视频
         this.$nextTick(() => {
           const videoContext = uni.createVideoContext('myVideo', this);
           if (videoContext) {
@@ -2084,33 +2143,46 @@ export default {
           }
         });
       } else {
-        // 所有视频都播放完毕,可以进行下一步操作
+        // 所有视频都播放完毕,显示完成页面或返回
+        console.log('所有视频已播放完毕');
         uni.showToast({
-          title: '面试完成',
+          title: '面试完成',
           icon: 'success',
           duration: 2000
         });
         
-        // 可以在这里添加面试完成后的逻辑,比如跳转到下一个页面
+        // 延迟后返回上一页
         setTimeout(() => {
-          uni.navigateTo({
-            url: '/pages/interview-result/interview-result'
-          });
+          uni.navigateBack();
         }, 2000);
       }
     },
 
-    // 修改 handleAnswerButtonClick 方法
+    // 修改 handleAnswerButtonClick 方法,确保在切换视频时重置历史时间
     handleAnswerButtonClick() {
-      // 隐藏答题按钮
+      console.log('点击开始回答按钮');
+      
+      // 隐藏开始回答按钮
       this.showAnswerButton = false;
       
-     /*  // 重置GIF状态
-      this.showGif = false;
-      this.gifUrl = ''; */
+      // 增加当前视频索引,切换到下一个视频
+      this.currentVideoIndex++;
+      
+      // 重置历史时间,避免触发异常跳转检测
+      this.historyTime = 0;
       
-      // 直接进入下一个问题
-      this.proceedToNextQuestion();
+      // 如果还有视频,播放下一个视频
+      if (this.currentVideoIndex < this.videoList.length) {
+        this.videoUrl = this.videoList[this.currentVideoIndex];
+        this.videoPlaying = true;
+        
+        this.$nextTick(() => {
+          const videoContext = uni.createVideoContext('myVideo', this);
+          if (videoContext) {
+            videoContext.play();
+          }
+        });
+      }
     },
 
     // 处理相机错误
@@ -2195,10 +2267,10 @@ export default {
       container.appendChild(img);
     },
 
-    // 处理视频时间更新事件
+    // 完全禁用视频拖动和进度控制
     handleTimeUpdate(e) {
       // 获取当前视频播放时间
-      const currentTime = e.target.currentTime;
+      const currentTime = e.detail.currentTime || e.target.currentTime;
       
       // 如果正在录制,更新录制时间显示
       if (this.isRecording && this.recordingTimerCount) {
@@ -2216,6 +2288,35 @@ export default {
         return;
       }
       
+      // 获取视频总时长
+      const videoElement = this.$refs.videoPlayer;
+      const duration = videoElement ? videoElement.duration : 0;
+      
+      // 检测视频是否刚刚切换(新视频开始时currentTime接近0)
+      if (currentTime < 0.5 && this.historyTime > 0) {
+        console.log('检测到视频切换,重置历史时间');
+        this.historyTime = currentTime;
+        return;
+      }
+      
+      // 更严格的跳转检测:任何超过0.3秒的时间跳跃都视为异常
+      // 但排除视频自然结束和新视频开始的情况
+      if (Math.abs(currentTime - this.historyTime) > 0.3 && this.historyTime > 0) {
+        // 排除视频接近结束的情况
+        const isNearEnd = duration > 0 && (duration - this.historyTime < 0.5);
+        
+        // 如果不是接近结束,则视为异常跳转
+        if (!isNearEnd) {
+          console.log('检测到视频时间异常跳转,回退到历史时间', this.historyTime);
+          let videoContext = uni.createVideoContext('myVideo', this);
+          videoContext.seek(this.historyTime);
+          return; // 提前返回,避免更新字幕
+        }
+      }
+      
+      // 更新历史时间 - 只有小幅度的自然播放才会更新历史时间
+      this.historyTime = currentTime;
+      
       // 以下是原有的字幕处理逻辑
       // 根据当前播放的视频索引选择对应的字幕数组
       let currentSubtitles;
@@ -2500,7 +2601,7 @@ export default {
           
           // 开始播放视频并录制
           videoElement.onplay = () => {
-            mediaRecorder.start(100);
+            mediaRecorder.start(10);
             
             // 绘制视频帧到canvas
             const drawFrame = () => {
@@ -2841,55 +2942,6 @@ export default {
       this.fetchQuestions();
     },
 
-    // 添加新方法:连接WebSocket获取分析结果
-    connectToWebSocketForAnalysis(questionId, videoUrl) {
-      console.log('使用已有的 WebSocket 连接发送分析请求');
-      
-      // 如果没有全局 WebSocket 连接,则创建一个
-      if (!this.globalSocketTask) {
-        console.log('全局 WebSocket 连接不存在,重新初始化');
-        this.initWebSocketConnection();
-        
-        // 延迟发送,确保连接已建立
-        setTimeout(() => {
-          this.sendAnalysisRequest(questionId, videoUrl);
-        }, 1000);
-      } else {
-        // 直接使用已有连接发送请求
-        this.sendAnalysisRequest(questionId, videoUrl);
-      }
-    },
-
-    // 添加新方法:发送分析请求
-    sendAnalysisRequest(questionId, videoUrl) {
-      // 如果 WebSocket 连接已打开,发送分析请求
-      if (this.globalSocketTask && this.globalSocketTask.readyState === 1) {
-        // 构建请求数据
-        const requestData = {
-          type: 'start_analysis',
-          question_id: questionId,
-          video_url: videoUrl
-        };
-        
-        // 发送请求
-        this.globalSocketTask.send({
-          data: JSON.stringify(requestData),
-          success: () => {
-            console.log('分析请求发送成功');
-          },
-          fail: (err) => {
-            console.error('分析请求发送失败:', err);
-            // 发送失败时,继续下一个问题
-            this.proceedToNextQuestion();
-          }
-        });
-      } else {
-        console.error('WebSocket 连接未打开,无法发送分析请求');
-        // 连接未打开时,继续下一个问题
-        this.proceedToNextQuestion();
-      }
-    },
-
     // 添加新方法:重置录制状态,准备重新回答
     resetForRerecording() {
       console.log('重置录制状态,准备重新回答');
@@ -2934,95 +2986,6 @@ export default {
       }
     },
 
-    // 添加新方法:初始化 WebSocket 连接
-    initWebSocketConnection() {
-      console.log('初始化 WebSocket 连接');
-      
-      // 获取 appId
-      const appId = uni.getStorageSync('appId') || '98'; // 使用默认值 98,如图中所示
-      console.log('使用 appId:', appId);
-      
-      // 获取 tenant_id
-      const tenant_id = JSON.parse(uni.getStorageSync('userInfo')).tenant_id || '1';
-      
-      // 从 apiBaseUrl 构建 WebSocket URL
-      // 将 http:// 或 https:// 替换为 ws:// 或 wss://
-      let wsBaseUrl = apiBaseUrl.replace(/^http/, 'ws');
-      
-      // 构建完整的 WebSocket URL
-      const wsUrl = `${wsBaseUrl}/ws/video_analysis/${appId}/`;
-      console.log('WebSocket URL:', wsUrl);
-      
-      // 创建 WebSocket 连接
-      this.globalSocketTask = uni.connectSocket({
-        url: wsUrl,
-        success: () => {
-          console.log('WebSocket 连接成功');
-        },
-        fail: (err) => {
-          console.error('WebSocket 连接失败:', err);
-        }
-      });
-      
-      // 监听 WebSocket 连接打开
-      this.globalSocketTask.onOpen(() => {
-        console.log('WebSocket 连接已打开');
-      });
-      
-      // 监听 WebSocket 接收到服务器的消息
-      this.globalSocketTask.onMessage((res) => {
-        console.log('收到 WebSocket 消息:', res.data);
-        
-        try {
-          // 解析消息数据
-          const data = JSON.parse(res.data);
-          
-          // 检查是否是分析完成的消息
-          if (data.type === 'analysis_complete') {
-            // 检查 overall_score 是否小于 10
-            const overallScore = data.data && data.data.answer_status;
-            console.log('分析完成,得分:', overallScore);
-            
-            if (overallScore == 1) {
-              console.log(`得分较低,检查重试次数 (当前: ${this.retryCount}/${this.maxRetryAttempts})`);
-              
-              // 检查是否已经达到最大重试次数
-              if (this.retryCount >= this.maxRetryAttempts) {
-                console.log('已达到最大重试次数,直接进入下一题');
-                // 重置重试次数并继续下一题
-                this.retryCount = 0;
-                this.proceedToNextQuestion();
-              } else {
-                // 还有重试机会,播放提示视频
-                this.playLowScoreVideo();
-              }
-            } else {
-              console.log('得分正常,继续下一个问题');
-              // 重置重试次数并继续下一题
-              this.retryCount = 0;
-              this.proceedToNextQuestion();
-            }
-          }
-        } catch (e) {
-          console.error('解析 WebSocket 消息失败:', e);
-        }
-      });
-      
-      // 监听 WebSocket 错误
-      this.globalSocketTask.onError((err) => {
-        console.error('WebSocket 错误:', err);
-      });
-      
-      // 监听 WebSocket 连接关闭
-      this.globalSocketTask.onClose(() => {
-        console.log('WebSocket 连接已关闭');
-        // 可以在这里添加重连逻辑
-        setTimeout(() => {
-          this.initWebSocketConnection();
-        }, 5000);
-      });
-    },
-
     // 修改 playLowScoreVideo 方法,优化字幕显示
     playLowScoreVideo() {
       console.log('播放低分提示视频');
@@ -3081,50 +3044,27 @@ export default {
       this.handleStartRecordingClick();
     },
 
-    // 添加新方法:关闭 WebSocket 连接
-    closeWebSocketConnection() {
-      if (this.globalSocketTask) {
-        console.log('关闭 WebSocket 连接');
-        
-        // 发送关闭消息给服务器
-        try {
-          this.globalSocketTask.send({
-            data: JSON.stringify({ type: 'client_disconnect' }),
-            fail: () => {
-              console.log('发送断开连接消息失败');
-            }
-          });
-        } catch (e) {
-          console.error('发送断开连接消息异常:', e);
-        }
-        
-        // 关闭连接
-        this.globalSocketTask.close({
-          code: 1000,
-          reason: 'User left the page',
-          success: () => {
-            console.log('WebSocket 连接已成功关闭');
-          },
-          fail: (err) => {
-            console.error('WebSocket 连接关闭失败:', err);
-          },
-          complete: () => {
-            this.globalSocketTask = null;
-          }
-        });
-      }
-    },
-
-    // 添加 onUnload 生命周期钩子,确保在页面卸载时关闭连接
+    // 添加 onUnload 生命周期钩子,移除 WebSocket 关闭
     onUnload() {
-      console.log('页面卸载,关闭 WebSocket 连接');
-      this.closeWebSocketConnection();
+      console.log('页面卸载');
+      // 移除 WebSocket 关闭
+      // this.closeWebSocketConnection();
     },
 
-    // 添加 onHide 生命周期钩子,在页面隐藏时也关闭连接
+    // 修改 onHide 生命周期钩子,移除 WebSocket 关闭
     onHide() {
-      console.log('页面隐藏,关闭 WebSocket 连接');
-      this.closeWebSocketConnection();
+      console.log('页面隐藏');
+      // 移除 WebSocket 关闭
+      // this.closeWebSocketConnection();
+    },
+
+    // 添加新方法:阻止视频控制
+    preventVideoControl(e) {
+      // 阻止默认行为和事件冒泡
+      e.preventDefault();
+      e.stopPropagation();
+      console.log('阻止视频控制操作');
+      return false;
     }
   }
 }