|
@@ -122,6 +122,14 @@
|
|
|
<!-- <div class="recording-timer" v-if="isRecording">
|
|
|
<span class="timer-text">{{ recordingTimeDisplay || '00:00' }}</span>
|
|
|
</div> -->
|
|
|
+
|
|
|
+ <!-- 添加上传状态指示器 -->
|
|
|
+ <div class="upload-status-indicator" v-if="showUploadStatus && uploadStatusText">
|
|
|
+ <div class="upload-status-content">
|
|
|
+ <div class="upload-status-icon" :class="{'uploading': isUploading}"></div>
|
|
|
+ <span class="upload-status-text">{{ uploadStatusText }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
@@ -220,6 +228,14 @@ export default {
|
|
|
recordingStartTime: null, // 录制开始时间
|
|
|
recordingTimerCount: 0, // 录制计时器计数
|
|
|
recordingTimeDisplay: '00:00', // 格式化的录制时间显示
|
|
|
+
|
|
|
+ // 添加上传队列相关数据
|
|
|
+ uploadQueue: [], // 存储待上传的视频
|
|
|
+ isUploading: false, // 标记是否正在上传
|
|
|
+ uploadProgress: {}, // 存储每个视频的上传进度
|
|
|
+ uploadStatus: {}, // 存储每个视频的上传状态
|
|
|
+ showUploadStatus: false, // 是否显示上传状态指示器
|
|
|
+ uploadStatusText: '', // 上传状态文本
|
|
|
}
|
|
|
},
|
|
|
mounted() {
|
|
@@ -1428,17 +1444,6 @@ export default {
|
|
|
uploadRecordedVideo(fileOrPath) {
|
|
|
console.log('准备上传视频:', typeof fileOrPath === 'string' ? fileOrPath : fileOrPath.name);
|
|
|
|
|
|
- // 显示上传中提示
|
|
|
- uni.showLoading({
|
|
|
- title: '正在上传...',
|
|
|
- mask: true
|
|
|
- });
|
|
|
-
|
|
|
- // 获取用户信息
|
|
|
- const userInfo = uni.getStorageSync('userInfo');
|
|
|
- const openid = userInfo ? (JSON.parse(userInfo).openid || '') : '';
|
|
|
- const tenant_id = uni.getStorageSync('tenant_id') || '1';
|
|
|
-
|
|
|
// 根据当前视频索引映射到正确的问题ID
|
|
|
let questionId;
|
|
|
switch(this.currentVideoIndex) {
|
|
@@ -1458,93 +1463,168 @@ export default {
|
|
|
questionId = 10; // 默认值
|
|
|
}
|
|
|
|
|
|
- // 检查是否在浏览器环境中使用File对象
|
|
|
- if (typeof fileOrPath !== 'string') {
|
|
|
- // 在浏览器环境中,我们需要将File对象转换为FormData
|
|
|
- const formData = new FormData();
|
|
|
- formData.append('file', fileOrPath);
|
|
|
- formData.append('openid', openid);
|
|
|
- formData.append('tenant_id', tenant_id);
|
|
|
- formData.append('application_id', uni.getStorageSync('appId'));
|
|
|
- formData.append('question_id', questionId);
|
|
|
- formData.append('video_duration', 0);
|
|
|
- formData.append('has_audio', 'true'); // 明确标记视频包含音频
|
|
|
-
|
|
|
- // 使用XMLHttpRequest直接上传
|
|
|
- const xhr = new XMLHttpRequest();
|
|
|
- xhr.open('POST', `${apiBaseUrl}/api/system/upload/`, true);
|
|
|
- xhr.timeout = 120000; // 30秒超时
|
|
|
- xhr.onload = () => {
|
|
|
- uni.hideLoading();
|
|
|
- if (xhr.status === 200) {
|
|
|
- try {
|
|
|
- const res = JSON.parse(xhr.responseText);
|
|
|
- console.log('上传响应:', res);
|
|
|
- if (res.code === 2000) {
|
|
|
- // 获取上传后的视频URL
|
|
|
- const videoUrl = res.data.url || res.data.photoUrl || '';
|
|
|
- if (videoUrl) {
|
|
|
- // 提交到面试接口
|
|
|
- this.submitVideoToInterview(videoUrl);
|
|
|
- } else {
|
|
|
- uni.showToast({
|
|
|
- title: '视频URL获取失败',
|
|
|
- icon: 'none'
|
|
|
- });
|
|
|
- }
|
|
|
+ // 创建上传任务对象
|
|
|
+ const uploadTask = {
|
|
|
+ id: Date.now().toString(), // 生成唯一ID
|
|
|
+ file: fileOrPath,
|
|
|
+ questionId: questionId,
|
|
|
+ attempts: 0, // 上传尝试次数
|
|
|
+ maxAttempts: 3, // 最大尝试次数
|
|
|
+ };
|
|
|
+
|
|
|
+ // 添加到上传队列
|
|
|
+ this.uploadQueue.push(uploadTask);
|
|
|
+
|
|
|
+ // 初始化上传进度和状态
|
|
|
+ this.uploadProgress[uploadTask.id] = 0;
|
|
|
+ this.uploadStatus[uploadTask.id] = 'pending'; // pending, uploading, success, failed
|
|
|
+
|
|
|
+ // 显示简短的上传状态提示
|
|
|
+ uni.showToast({
|
|
|
+ title: '视频已加入上传队列',
|
|
|
+ icon: 'none',
|
|
|
+ duration: 1500
|
|
|
+ });
|
|
|
+
|
|
|
+ // 更新上传状态文本
|
|
|
+ this.updateUploadStatusText();
|
|
|
+
|
|
|
+ // 如果当前没有上传任务在进行,开始处理队列
|
|
|
+ if (!this.isUploading) {
|
|
|
+ this.processUploadQueue();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 立即进入下一个问题,不等待上传完成
|
|
|
+ this.proceedToNextQuestion();
|
|
|
+ },
|
|
|
+
|
|
|
+ // 添加新方法:处理上传队列
|
|
|
+ processUploadQueue() {
|
|
|
+ // 如果队列为空,结束处理
|
|
|
+ if (this.uploadQueue.length === 0) {
|
|
|
+ this.isUploading = false;
|
|
|
+ this.showUploadStatus = false;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 标记为正在上传
|
|
|
+ this.isUploading = true;
|
|
|
+ this.showUploadStatus = true;
|
|
|
+
|
|
|
+ // 获取队列中的第一个任务
|
|
|
+ const task = this.uploadQueue[0];
|
|
|
+
|
|
|
+ // 更新任务状态
|
|
|
+ this.uploadStatus[task.id] = 'uploading';
|
|
|
+ this.updateUploadStatusText();
|
|
|
+
|
|
|
+ // 增加尝试次数
|
|
|
+ task.attempts++;
|
|
|
+
|
|
|
+ // 根据文件类型选择上传方法
|
|
|
+ if (typeof task.file !== 'string') {
|
|
|
+ // 浏览器环境,使用XMLHttpRequest上传
|
|
|
+ this.uploadFileWithXHR(task);
|
|
|
+ } else {
|
|
|
+ // 小程序环境,使用uni.uploadFile上传
|
|
|
+ this.uploadFileWithUni(task);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 添加新方法:使用XMLHttpRequest上传文件
|
|
|
+ uploadFileWithXHR(task) {
|
|
|
+ // 获取用户信息
|
|
|
+ const userInfo = uni.getStorageSync('userInfo');
|
|
|
+ const openid = userInfo ? (JSON.parse(userInfo).openid || '') : '';
|
|
|
+ const tenant_id = uni.getStorageSync('tenant_id') || '1';
|
|
|
+
|
|
|
+ // 创建FormData
|
|
|
+ const formData = new FormData();
|
|
|
+ formData.append('file', task.file);
|
|
|
+ formData.append('openid', openid);
|
|
|
+ formData.append('tenant_id', tenant_id);
|
|
|
+ formData.append('application_id', uni.getStorageSync('appId'));
|
|
|
+ formData.append('question_id', task.questionId);
|
|
|
+ formData.append('video_duration', 0);
|
|
|
+ formData.append('has_audio', 'true');
|
|
|
+
|
|
|
+ // 创建XMLHttpRequest
|
|
|
+ const xhr = new XMLHttpRequest();
|
|
|
+ xhr.open('POST', `${apiBaseUrl}/api/upload/`, true);
|
|
|
+ xhr.timeout = 120000; // 2分钟超时
|
|
|
+
|
|
|
+ // 监听上传进度
|
|
|
+ xhr.upload.onprogress = (event) => {
|
|
|
+ if (event.lengthComputable) {
|
|
|
+ const percentComplete = Math.round((event.loaded / event.total) * 100);
|
|
|
+ this.uploadProgress[task.id] = percentComplete;
|
|
|
+ this.updateUploadStatusText();
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 监听请求完成
|
|
|
+ xhr.onload = () => {
|
|
|
+ if (xhr.status === 200) {
|
|
|
+ try {
|
|
|
+ const res = JSON.parse(xhr.responseText);
|
|
|
+ console.log('上传响应:', res);
|
|
|
+ if (res.code === 2000) {
|
|
|
+ // 获取上传后的视频URL
|
|
|
+ const videoUrl = res.data.url || res.data.photoUrl || '';
|
|
|
+ if (videoUrl) {
|
|
|
+ // 上传成功,更新状态
|
|
|
+ this.uploadStatus[task.id] = 'success';
|
|
|
+ this.updateUploadStatusText();
|
|
|
+
|
|
|
+ // 提交到面试接口
|
|
|
+ this.submitVideoToInterview(videoUrl, task);
|
|
|
} else {
|
|
|
- uni.showToast({
|
|
|
- title: res.msg || '上传失败,请重试',
|
|
|
- icon: 'none'
|
|
|
- });
|
|
|
+ this.handleUploadFailure(task, '视频URL获取失败');
|
|
|
}
|
|
|
- } catch (e) {
|
|
|
- console.error('解析响应失败:', e);
|
|
|
- uni.showToast({
|
|
|
- title: '解析响应失败',
|
|
|
- icon: 'none'
|
|
|
- });
|
|
|
+ } else {
|
|
|
+ this.handleUploadFailure(task, res.msg || '上传失败');
|
|
|
}
|
|
|
- } else {
|
|
|
- uni.showToast({
|
|
|
- title: '上传失败,HTTP状态: ' + xhr.status,
|
|
|
- icon: 'none'
|
|
|
- });
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- xhr.onerror = () => {
|
|
|
- uni.hideLoading();
|
|
|
- console.error('上传网络错误');
|
|
|
- uni.showToast({
|
|
|
- title: '网络错误,请重试',
|
|
|
- icon: 'none'
|
|
|
- });
|
|
|
- };
|
|
|
-
|
|
|
- xhr.upload.onprogress = (event) => {
|
|
|
- if (event.lengthComputable) {
|
|
|
- const percentComplete = Math.round((event.loaded / event.total) * 100);
|
|
|
- console.log('上传进度:', percentComplete + '%');
|
|
|
+ } catch (e) {
|
|
|
+ this.handleUploadFailure(task, '解析响应失败');
|
|
|
}
|
|
|
- };
|
|
|
-
|
|
|
- xhr.send(formData);
|
|
|
- return;
|
|
|
- }
|
|
|
+ } else {
|
|
|
+ this.handleUploadFailure(task, 'HTTP状态: ' + xhr.status);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 监听错误
|
|
|
+ xhr.onerror = () => {
|
|
|
+ this.handleUploadFailure(task, '网络错误');
|
|
|
+ };
|
|
|
|
|
|
- // 对于小程序环境,使用uni.uploadFile
|
|
|
- uni.uploadFile({
|
|
|
- url: `${apiBaseUrl}/api/system/upload/`,
|
|
|
- filePath: fileOrPath,
|
|
|
+ // 监听超时
|
|
|
+ xhr.ontimeout = () => {
|
|
|
+ this.handleUploadFailure(task, '上传超时');
|
|
|
+ };
|
|
|
+
|
|
|
+ // 发送请求
|
|
|
+ xhr.send(formData);
|
|
|
+ },
|
|
|
+
|
|
|
+ // 添加新方法:使用uni.uploadFile上传文件
|
|
|
+ uploadFileWithUni(task) {
|
|
|
+ // 获取用户信息
|
|
|
+ const userInfo = uni.getStorageSync('userInfo');
|
|
|
+ const openid = userInfo ? (JSON.parse(userInfo).openid || '') : '';
|
|
|
+ const tenant_id = uni.getStorageSync('tenant_id') || '1';
|
|
|
+
|
|
|
+ // 创建上传任务
|
|
|
+ const uploadTask = uni.uploadFile({
|
|
|
+ url: `${apiBaseUrl}/api/upload/`,
|
|
|
+ filePath: task.file,
|
|
|
name: 'file',
|
|
|
formData: {
|
|
|
openid: openid,
|
|
|
tenant_id: tenant_id,
|
|
|
application_id: uni.getStorageSync('appId'),
|
|
|
- question_id: questionId,
|
|
|
+ question_id: task.questionId,
|
|
|
video_duration: 0,
|
|
|
- has_audio: 'true' // 明确标记视频包含音频
|
|
|
+ has_audio: 'true'
|
|
|
},
|
|
|
success: (uploadRes) => {
|
|
|
try {
|
|
@@ -1554,71 +1634,106 @@ export default {
|
|
|
// 获取上传后的视频URL
|
|
|
const videoUrl = res.data.permanent_link || res.data.url || '';
|
|
|
if (videoUrl) {
|
|
|
+ // 上传成功,更新状态
|
|
|
+ this.uploadStatus[task.id] = 'success';
|
|
|
+ this.updateUploadStatusText();
|
|
|
+
|
|
|
// 提交到面试接口
|
|
|
- this.submitVideoToInterview(videoUrl);
|
|
|
+ this.submitVideoToInterview(videoUrl, task);
|
|
|
} else {
|
|
|
- uni.showToast({
|
|
|
- title: '视频URL获取失败',
|
|
|
- icon: 'none'
|
|
|
- });
|
|
|
+ this.handleUploadFailure(task, '视频URL获取失败');
|
|
|
}
|
|
|
} else {
|
|
|
- uni.showToast({
|
|
|
- title: res.msg || '上传失败,请重试',
|
|
|
- icon: 'none'
|
|
|
- });
|
|
|
+ this.handleUploadFailure(task, res.msg || '上传失败');
|
|
|
}
|
|
|
} catch (e) {
|
|
|
- console.error('解析响应失败:', e);
|
|
|
- uni.showToast({
|
|
|
- title: '解析响应失败',
|
|
|
- icon: 'none'
|
|
|
- });
|
|
|
+ this.handleUploadFailure(task, '解析响应失败');
|
|
|
}
|
|
|
},
|
|
|
fail: (err) => {
|
|
|
- console.error('上传失败:', err);
|
|
|
- uni.showToast({
|
|
|
- title: '上传失败,请重试',
|
|
|
- icon: 'none'
|
|
|
- });
|
|
|
- },
|
|
|
- complete: () => {
|
|
|
- uni.hideLoading();
|
|
|
+ this.handleUploadFailure(task, err.errMsg || '上传失败');
|
|
|
}
|
|
|
});
|
|
|
+
|
|
|
+ // 监听上传进度
|
|
|
+ uploadTask.onProgressUpdate((res) => {
|
|
|
+ this.uploadProgress[task.id] = res.progress;
|
|
|
+ this.updateUploadStatusText();
|
|
|
+ });
|
|
|
},
|
|
|
-
|
|
|
+
|
|
|
+ // 添加新方法:处理上传失败
|
|
|
+ handleUploadFailure(task, errorMsg) {
|
|
|
+ console.error('上传失败:', errorMsg);
|
|
|
+
|
|
|
+ // 更新任务状态
|
|
|
+ this.uploadStatus[task.id] = 'failed';
|
|
|
+ this.updateUploadStatusText();
|
|
|
+
|
|
|
+ // 检查是否还有重试机会
|
|
|
+ if (task.attempts < task.maxAttempts) {
|
|
|
+ console.log(`将在5秒后重试上传,当前尝试次数: ${task.attempts}/${task.maxAttempts}`);
|
|
|
+
|
|
|
+ // 5秒后重试
|
|
|
+ setTimeout(() => {
|
|
|
+ // 重置进度
|
|
|
+ this.uploadProgress[task.id] = 0;
|
|
|
+
|
|
|
+ // 重新开始上传
|
|
|
+ if (typeof task.file !== 'string') {
|
|
|
+ this.uploadFileWithXHR(task);
|
|
|
+ } else {
|
|
|
+ this.uploadFileWithUni(task);
|
|
|
+ }
|
|
|
+ }, 5000);
|
|
|
+ } else {
|
|
|
+ // 超过最大重试次数,移除任务并继续处理队列
|
|
|
+ console.log('超过最大重试次数,放弃上传');
|
|
|
+
|
|
|
+ // 显示错误提示
|
|
|
+ uni.showToast({
|
|
|
+ title: '视频上传失败,请稍后重试',
|
|
|
+ icon: 'none',
|
|
|
+ duration: 2000
|
|
|
+ });
|
|
|
+
|
|
|
+ // 从队列中移除当前任务
|
|
|
+ this.uploadQueue.shift();
|
|
|
+
|
|
|
+ // 继续处理队列中的下一个任务
|
|
|
+ this.processUploadQueue();
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
// 修改 submitVideoToInterview 方法
|
|
|
- submitVideoToInterview(videoUrl) {
|
|
|
+ submitVideoToInterview(videoUrl, task = null) {
|
|
|
console.log('提交视频URL到面试接口:', videoUrl);
|
|
|
|
|
|
- // 显示加载提示
|
|
|
- uni.showLoading({
|
|
|
- title: '正在提交...',
|
|
|
- mask: true
|
|
|
- });
|
|
|
-
|
|
|
- // 根据当前视频索引映射到正确的问题ID
|
|
|
+ // 确定问题ID
|
|
|
let questionId;
|
|
|
- switch(this.currentVideoIndex) {
|
|
|
- case 1: // 第一个问题(索引1是第二个视频,第一个是介绍视频)
|
|
|
- questionId = 10;
|
|
|
- break;
|
|
|
- case 2: // 第二个问题
|
|
|
- questionId = 11;
|
|
|
- break;
|
|
|
- case 3: // 第三个问题
|
|
|
- questionId = 12;
|
|
|
- break;
|
|
|
- case 4: // 第四个问题
|
|
|
- questionId = 13;
|
|
|
- break;
|
|
|
- default:
|
|
|
- questionId = 10; // 默认值,以防万一
|
|
|
+ if (task) {
|
|
|
+ questionId = task.questionId;
|
|
|
+ } else {
|
|
|
+ // 根据当前视频索引映射到正确的问题ID(兼容旧代码)
|
|
|
+ switch(this.currentVideoIndex) {
|
|
|
+ case 1:
|
|
|
+ questionId = 10;
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ questionId = 11;
|
|
|
+ break;
|
|
|
+ case 3:
|
|
|
+ questionId = 12;
|
|
|
+ break;
|
|
|
+ case 4:
|
|
|
+ questionId = 13;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ questionId = 10;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- // 准备请求参数,使用映射后的问题ID
|
|
|
+ // 准备请求参数
|
|
|
const requestData = {
|
|
|
application_id: uni.getStorageSync('appId'),
|
|
|
question_id: questionId,
|
|
@@ -1626,49 +1741,75 @@ export default {
|
|
|
tenant_id: uni.getStorageSync('tenant_id') || '1'
|
|
|
};
|
|
|
|
|
|
- // 发送请求到面试接口,使用form-data格式
|
|
|
+ // 发送请求到面试接口
|
|
|
uni.request({
|
|
|
- url: `${apiBaseUrl}/api/job/upload_question_video`,
|
|
|
+ url: `${apiBaseUrl}/api/job/upload_video`,
|
|
|
method: 'POST',
|
|
|
- data: requestData, // 使用data而不是formData
|
|
|
+ data: requestData,
|
|
|
header: {
|
|
|
- 'content-type': 'application/x-www-form-urlencoded' // 修改为form-data格式的content-type
|
|
|
+ 'content-type': 'application/x-www-form-urlencoded'
|
|
|
},
|
|
|
success: (res) => {
|
|
|
console.log('面试接口提交成功:', res);
|
|
|
- uni.hideLoading();
|
|
|
|
|
|
if (res.data.code === 0 || res.data.code === 2000) {
|
|
|
// 提交成功
|
|
|
- uni.showToast({
|
|
|
- title: '回答已提交',
|
|
|
- icon: 'success'
|
|
|
- });
|
|
|
-
|
|
|
- // 保存最后上传的视频URL
|
|
|
- this.lastUploadedVideoUrl = videoUrl;
|
|
|
-
|
|
|
- // 隐藏重试按钮(如果之前显示了)
|
|
|
- this.showRetryButton = false;
|
|
|
- this.lastVideoToRetry = null;
|
|
|
-
|
|
|
- // 延迟一下再进入下一题,让用户看到成功提示
|
|
|
- setTimeout(() => {
|
|
|
- // 检查是否完成了第五个视频问题(索引为4)
|
|
|
- if (this.currentVideoIndex === 4) {
|
|
|
- // 完成第五个问题后,跳转到相机页面
|
|
|
- uni.navigateTo({
|
|
|
- url: '/pages/camera/camera'
|
|
|
- });
|
|
|
- } else {
|
|
|
- // 否则继续正常流程
|
|
|
- this.proceedToNextQuestion();
|
|
|
- }
|
|
|
- }, 1500);
|
|
|
+ if (task) {
|
|
|
+ // 从队列中移除当前任务
|
|
|
+ this.uploadQueue.shift();
|
|
|
+
|
|
|
+ // 显示简短的成功提示
|
|
|
+ uni.showToast({
|
|
|
+ title: '视频提交成功',
|
|
|
+ icon: 'success',
|
|
|
+ duration: 1500
|
|
|
+ });
|
|
|
+
|
|
|
+ // 继续处理队列中的下一个任务
|
|
|
+ this.processUploadQueue();
|
|
|
+ } else {
|
|
|
+ // 兼容旧代码的处理逻辑
|
|
|
+ uni.showToast({
|
|
|
+ title: '回答已提交',
|
|
|
+ icon: 'success'
|
|
|
+ });
|
|
|
+
|
|
|
+ // 保存最后上传的视频URL
|
|
|
+ this.lastUploadedVideoUrl = videoUrl;
|
|
|
+
|
|
|
+ // 隐藏重试按钮(如果之前显示了)
|
|
|
+ this.showRetryButton = false;
|
|
|
+ this.lastVideoToRetry = null;
|
|
|
+ }
|
|
|
} else {
|
|
|
// 提交失败
|
|
|
+ if (task) {
|
|
|
+ this.handleSubmitFailure(task, res.data.msg || '提交失败');
|
|
|
+ } else {
|
|
|
+ // 兼容旧代码的处理逻辑
|
|
|
+ uni.showToast({
|
|
|
+ title: res.data.msg || '提交失败,请重试',
|
|
|
+ icon: 'none'
|
|
|
+ });
|
|
|
+
|
|
|
+ // 保存失败的视频URL,用于重试
|
|
|
+ this.lastVideoToRetry = videoUrl;
|
|
|
+
|
|
|
+ // 显示重试按钮
|
|
|
+ this.showRetryButton = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ fail: (err) => {
|
|
|
+ console.error('面试接口提交失败:', err);
|
|
|
+
|
|
|
+ if (task) {
|
|
|
+ this.handleSubmitFailure(task, err.errMsg || '网络错误');
|
|
|
+ } else {
|
|
|
+ // 兼容旧代码的处理逻辑
|
|
|
+ uni.hideLoading();
|
|
|
uni.showToast({
|
|
|
- title: res.data.msg || '提交失败,请重试',
|
|
|
+ title: '网络错误,请重试',
|
|
|
icon: 'none'
|
|
|
});
|
|
|
|
|
@@ -1678,25 +1819,82 @@ export default {
|
|
|
// 显示重试按钮
|
|
|
this.showRetryButton = true;
|
|
|
}
|
|
|
- },
|
|
|
- fail: (err) => {
|
|
|
- console.error('面试接口提交失败:', err);
|
|
|
- uni.hideLoading();
|
|
|
- uni.showToast({
|
|
|
- title: '网络错误,请重试',
|
|
|
- icon: 'none'
|
|
|
- });
|
|
|
-
|
|
|
- // 保存失败的视频URL,用于重试
|
|
|
- this.lastVideoToRetry = videoUrl;
|
|
|
-
|
|
|
- // 显示重试按钮
|
|
|
- this.showRetryButton = true;
|
|
|
}
|
|
|
});
|
|
|
},
|
|
|
-
|
|
|
- // 修改 proceedToNextQuestion 方法
|
|
|
+
|
|
|
+ // 添加新方法:处理提交失败
|
|
|
+ handleSubmitFailure(task, errorMsg) {
|
|
|
+ console.error('提交失败:', errorMsg);
|
|
|
+
|
|
|
+ // 更新任务状态
|
|
|
+ this.uploadStatus[task.id] = 'failed';
|
|
|
+ this.updateUploadStatusText();
|
|
|
+
|
|
|
+ // 检查是否还有重试机会
|
|
|
+ if (task.attempts < task.maxAttempts) {
|
|
|
+ console.log(`将在5秒后重试提交,当前尝试次数: ${task.attempts}/${task.maxAttempts}`);
|
|
|
+
|
|
|
+ // 5秒后重试
|
|
|
+ setTimeout(() => {
|
|
|
+ // 重新提交
|
|
|
+ this.submitVideoToInterview(task.videoUrl, task);
|
|
|
+ }, 5000);
|
|
|
+ } else {
|
|
|
+ // 超过最大重试次数,移除任务并继续处理队列
|
|
|
+ console.log('超过最大重试次数,放弃提交');
|
|
|
+
|
|
|
+ // 显示错误提示
|
|
|
+ uni.showToast({
|
|
|
+ title: '视频提交失败,请稍后重试',
|
|
|
+ icon: 'none',
|
|
|
+ duration: 2000
|
|
|
+ });
|
|
|
+
|
|
|
+ // 从队列中移除当前任务
|
|
|
+ this.uploadQueue.shift();
|
|
|
+
|
|
|
+ // 继续处理队列中的下一个任务
|
|
|
+ this.processUploadQueue();
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 添加新方法:更新上传状态文本
|
|
|
+ updateUploadStatusText() {
|
|
|
+ if (this.uploadQueue.length === 0) {
|
|
|
+ this.uploadStatusText = '';
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const currentTask = this.uploadQueue[0];
|
|
|
+ const progress = this.uploadProgress[currentTask.id] || 0;
|
|
|
+ const status = this.uploadStatus[currentTask.id] || 'pending';
|
|
|
+
|
|
|
+ let statusText = '';
|
|
|
+ switch (status) {
|
|
|
+ case 'pending':
|
|
|
+ statusText = '等待上传';
|
|
|
+ break;
|
|
|
+ case 'uploading':
|
|
|
+ statusText = `上传中 ${progress}%`;
|
|
|
+ break;
|
|
|
+ case 'success':
|
|
|
+ statusText = '上传成功,提交中...';
|
|
|
+ break;
|
|
|
+ case 'failed':
|
|
|
+ statusText = `上传失败,${currentTask.attempts < currentTask.maxAttempts ? '即将重试' : '已放弃'}`;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.uploadStatusText = `问题${currentTask.questionId - 9}:${statusText}`;
|
|
|
+
|
|
|
+ // 如果队列中有多个任务,显示总数
|
|
|
+ if (this.uploadQueue.length > 1) {
|
|
|
+ this.uploadStatusText += ` (${this.uploadQueue.length}个视频待处理)`;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 修改 proceedToNextQuestion 方法,不再等待上传完成
|
|
|
proceedToNextQuestion() {
|
|
|
// 检查是否完成了第五个视频问题(索引为4)
|
|
|
if (this.currentVideoIndex === 4) {
|
|
@@ -2561,4 +2759,36 @@ video::-webkit-media-controls-fullscreen-button {
|
|
|
font-size: 14px;
|
|
|
font-family: monospace; /* 使用等宽字体,使时间显示更稳定 */
|
|
|
}
|
|
|
+
|
|
|
+/* 添加上传状态指示器 */
|
|
|
+.upload-status-indicator {
|
|
|
+ position: absolute;
|
|
|
+ top: 20px;
|
|
|
+ left: 130px; /* 放在录制指示器旁边 */
|
|
|
+ background-color: rgba(0, 0, 0, 0.6);
|
|
|
+ padding: 5px 10px;
|
|
|
+ border-radius: 15px;
|
|
|
+ z-index: 20;
|
|
|
+}
|
|
|
+
|
|
|
+.upload-status-content {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
+
|
|
|
+.upload-status-icon {
|
|
|
+ width: 12px;
|
|
|
+ height: 12px;
|
|
|
+ border-radius: 50%;
|
|
|
+ margin-right: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.upload-status-text {
|
|
|
+ color: white;
|
|
|
+ font-size: 14px;
|
|
|
+}
|
|
|
+
|
|
|
+.uploading {
|
|
|
+ background-color: #e74c3c;
|
|
|
+}
|
|
|
</style>
|