|
@@ -161,6 +161,13 @@
|
|
|
<div class="countdown-text">准备开始回答</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
+
|
|
|
+ <!-- 添加重新录制按钮 -->
|
|
|
+ <div class="rerecord-button-container" v-if="showRerecordButton">
|
|
|
+ <button class="rerecord-button" @click="handleRerecordButtonClick">
|
|
|
+ 重新作答
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
@@ -224,6 +231,19 @@ export default {
|
|
|
countdownTimer: null,
|
|
|
showGif: false, // 控制是否显示GIF
|
|
|
gifUrl: '', // GIF图片的URL
|
|
|
+ globalSocketTask: null, // 添加全局 WebSocket 连接对象
|
|
|
+ lowScoreVideoUrl: 'https://data.qicai321.com/minlong/latentsync/0530e7f5-1957-422d-8f34-ba4a92608081_result.mp4', // 低分提示视频URL
|
|
|
+ showRerecordButton: false, // 控制重新录制按钮显示
|
|
|
+ isPlayingLowScoreVideo: false, // 标记是否正在播放低分提示视频
|
|
|
+ lowScoreVideoSubtitles: [
|
|
|
+ {
|
|
|
+ startTime: 0,
|
|
|
+ endTime: 10, // 假设视频长度为10秒,可根据实际情况调整
|
|
|
+ text: '我未听清楚您在说什么,请您再说一遍!'
|
|
|
+ }
|
|
|
+ ], // 用于存储低分提示视频的字幕
|
|
|
+ retryCount: 0, // 添加重试次数计数器
|
|
|
+ maxRetryAttempts: 2, // 最大重试次数限制
|
|
|
}
|
|
|
},
|
|
|
mounted() {
|
|
@@ -242,9 +262,13 @@ export default {
|
|
|
this.testAudioInput();
|
|
|
}
|
|
|
}, 3000);
|
|
|
- uni.setKeepScreenOn({
|
|
|
- keepScreenOn: true
|
|
|
- });
|
|
|
+
|
|
|
+ // 初始化 WebSocket 连接
|
|
|
+ this.initWebSocketConnection();
|
|
|
+
|
|
|
+ uni.setKeepScreenOn({
|
|
|
+ keepScreenOn: true
|
|
|
+ });
|
|
|
},
|
|
|
beforeDestroy() {
|
|
|
// 组件销毁前停止摄像头
|
|
@@ -252,6 +276,9 @@ export default {
|
|
|
|
|
|
// 清除倒计时定时器
|
|
|
this.clearCountdown();
|
|
|
+
|
|
|
+ // 关闭 WebSocket 连接
|
|
|
+ this.closeWebSocketConnection();
|
|
|
},
|
|
|
methods: {
|
|
|
// 初始化相机
|
|
@@ -798,24 +825,34 @@ export default {
|
|
|
console.log('视频播放结束');
|
|
|
this.videoPlaying = false;
|
|
|
|
|
|
- /* // 设置对应问题的GIF图片URL
|
|
|
- if (this.currentVideoIndex === 0) {
|
|
|
- this.gifUrl = 'http://121.36.251.245:9000/minlong/cae2da8f92ce4af278d3929ab8c5973f.mp4';
|
|
|
- } else if (this.currentVideoIndex === 1) {
|
|
|
- this.gifUrl = 'http://121.36.251.245:9000/minlong/cae2da8f92ce4af278d3929ab8c5973f.mp4';
|
|
|
- } else if (this.currentVideoIndex === 2) {
|
|
|
- this.gifUrl = 'http://121.36.251.245:9000/minlong/cae2da8f92ce4af278d3929ab8c5973f.mp4';
|
|
|
- } else if (this.currentVideoIndex === 3) {
|
|
|
- this.gifUrl = 'http://121.36.251.245:9000/minlong/cae2da8f92ce4af278d3929ab8c5973f.mp4';
|
|
|
- } else if (this.currentVideoIndex === 4) {
|
|
|
- this.gifUrl = 'http://121.36.251.245:9000/minlong/cae2da8f92ce4af278d3929ab8c5973f.mp4';
|
|
|
- } else if (this.currentVideoIndex === 5) {
|
|
|
- this.gifUrl = 'http://121.36.251.245:9000/minlong/cae2da8f92ce4af278d3929ab8c5973f.mp4';
|
|
|
- }
|
|
|
-
|
|
|
- // 显示GIF图片
|
|
|
- this.showGif = true; */
|
|
|
+ // 检查是否是低分提示视频
|
|
|
+ if (this.isPlayingLowScoreVideo) {
|
|
|
+ console.log('低分提示视频播放完成');
|
|
|
+
|
|
|
+ // 检查重试次数
|
|
|
+ if (this.retryCount < this.maxRetryAttempts) {
|
|
|
+ console.log(`显示重新录制按钮 (重试次数: ${this.retryCount + 1}/${this.maxRetryAttempts})`);
|
|
|
+
|
|
|
+ // 显示重新录制按钮
|
|
|
+ this.showRerecordButton = true;
|
|
|
+ } else {
|
|
|
+ console.log('已达到最大重试次数,继续下一题');
|
|
|
+
|
|
|
+ // 重置重试次数
|
|
|
+ this.retryCount = 0;
|
|
|
+
|
|
|
+ // 继续下一个问题
|
|
|
+ this.proceedToNextQuestion();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 重置标记和清除字幕
|
|
|
+ this.isPlayingLowScoreVideo = false;
|
|
|
+ this.currentSubtitle = '';
|
|
|
+
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
+ // 恢复原有的视频结束处理逻辑
|
|
|
// 对于所有视频,都显示相应的按钮
|
|
|
if (this.currentVideoIndex >= 1) {
|
|
|
// 对于问题视频,显示"开始回答"按钮
|
|
@@ -1600,8 +1637,8 @@ export default {
|
|
|
this.processUploadQueue();
|
|
|
}
|
|
|
|
|
|
- // 立即进入下一个问题,不等待上传完成
|
|
|
- this.proceedToNextQuestion();
|
|
|
+ // 注意:不再自动进入下一个问题
|
|
|
+ // 我们会在WebSocket回调中决定是否进入下一个问题
|
|
|
},
|
|
|
|
|
|
// 添加新方法:处理上传队列
|
|
@@ -1811,7 +1848,7 @@ export default {
|
|
|
}
|
|
|
},
|
|
|
|
|
|
- // 修改 submitVideoToInterview 方法
|
|
|
+ // 修改 submitVideoToInterview 方法,添加 WebSocket 连接和分数检查
|
|
|
submitVideoToInterview(videoUrl, task = null) {
|
|
|
console.log('提交视频URL到面试接口:', videoUrl);
|
|
|
|
|
@@ -1862,7 +1899,7 @@ export default {
|
|
|
success: (res) => {
|
|
|
console.log('面试接口提交成功:', res);
|
|
|
|
|
|
- if (res.data.code === 0 || res.data.code === 2000) {
|
|
|
+ if (res.data.code === 200 || res.data.code === 200) {
|
|
|
// 提交成功
|
|
|
if (task) {
|
|
|
// 从队列中移除当前任务
|
|
@@ -1875,6 +1912,9 @@ export default {
|
|
|
// duration: 1500
|
|
|
// });
|
|
|
|
|
|
+ // 连接WebSocket获取分析结果
|
|
|
+ this.connectToWebSocketForAnalysis(questionId, videoUrl);
|
|
|
+
|
|
|
// 继续处理队列中的下一个任务
|
|
|
this.processUploadQueue();
|
|
|
} else {
|
|
@@ -1884,6 +1924,9 @@ export default {
|
|
|
icon: 'success'
|
|
|
});
|
|
|
|
|
|
+ // 连接WebSocket获取分析结果
|
|
|
+ this.connectToWebSocketForAnalysis(questionId, videoUrl);
|
|
|
+
|
|
|
// 保存最后上传的视频URL
|
|
|
this.lastUploadedVideoUrl = videoUrl;
|
|
|
|
|
@@ -2004,8 +2047,12 @@ export default {
|
|
|
}
|
|
|
},
|
|
|
|
|
|
- // 修改 proceedToNextQuestion 方法
|
|
|
+ // 修改 proceedToNextQuestion 方法,不要自动进入下一个问题
|
|
|
+ // 因为现在我们会在WebSocket回调中决定是否进入下一个问题
|
|
|
proceedToNextQuestion() {
|
|
|
+ // 重置重试计数器
|
|
|
+ this.retryCount = 0;
|
|
|
+
|
|
|
// 检查是否完成了第五个视频问题(索引为4)
|
|
|
if (this.currentVideoIndex === 4) {
|
|
|
// 完成第五个问题后,跳转到相机页面
|
|
@@ -2158,6 +2205,18 @@ export default {
|
|
|
this.recordingTimeDisplay = this.formatTime(this.recordingTimerCount);
|
|
|
}
|
|
|
|
|
|
+ // 如果正在播放低分提示视频,使用专门的字幕数组
|
|
|
+ if (this.isPlayingLowScoreVideo) {
|
|
|
+ if (this.lowScoreVideoSubtitles) {
|
|
|
+ const subtitle = this.lowScoreVideoSubtitles.find(
|
|
|
+ sub => currentTime >= sub.startTime && currentTime < sub.endTime
|
|
|
+ );
|
|
|
+ this.currentSubtitle = subtitle ? subtitle.text : '';
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 以下是原有的字幕处理逻辑
|
|
|
// 根据当前播放的视频索引选择对应的字幕数组
|
|
|
let currentSubtitles;
|
|
|
if (this.currentVideoIndex === 0) {
|
|
@@ -2780,6 +2839,292 @@ 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('重置录制状态,准备重新回答');
|
|
|
+
|
|
|
+ // 重置录制状态
|
|
|
+ this.isRecording = false;
|
|
|
+ this.showStopRecordingButton = false;
|
|
|
+
|
|
|
+ // 显示"开始回答"按钮
|
|
|
+ this.showStartRecordingButton = true;
|
|
|
+
|
|
|
+ // 清除倒计时
|
|
|
+ this.clearCountdown();
|
|
|
+
|
|
|
+ // 重置录制计时器
|
|
|
+ if (this.recordingTimer) {
|
|
|
+ clearInterval(this.recordingTimer);
|
|
|
+ this.recordingTimer = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 重置录制时间显示
|
|
|
+ this.recordingTimerCount = 0;
|
|
|
+ this.recordingTimeDisplay = '00:00 / 05:00';
|
|
|
+ this.remainingTime = this.maxRecordingTime;
|
|
|
+
|
|
|
+ // 如果是浏览器环境,停止MediaRecorder
|
|
|
+ if (this.mediaRecorder && this.mediaRecorder.state !== 'inactive') {
|
|
|
+ this.mediaRecorder.stop();
|
|
|
+ this.recordedChunks = [];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果是小程序环境,停止相机录制
|
|
|
+ if (this.cameraContext) {
|
|
|
+ this.cameraContext.stopRecord({
|
|
|
+ success: () => {
|
|
|
+ console.log('相机录制已停止');
|
|
|
+ },
|
|
|
+ fail: (err) => {
|
|
|
+ console.error('停止相机录制失败:', err);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 添加新方法:初始化 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('播放低分提示视频');
|
|
|
+
|
|
|
+ // 标记正在播放低分提示视频
|
|
|
+ this.isPlayingLowScoreVideo = true;
|
|
|
+
|
|
|
+ // 隐藏其他按钮
|
|
|
+ this.showStartRecordingButton = false;
|
|
|
+ this.showStopRecordingButton = false;
|
|
|
+ this.showRerecordButton = false;
|
|
|
+
|
|
|
+ // 设置视频URL
|
|
|
+ this.videoUrl = this.lowScoreVideoUrl;
|
|
|
+ this.videoPlaying = true;
|
|
|
+
|
|
|
+ // 清除现有字幕
|
|
|
+ this.currentSubtitle = '';
|
|
|
+
|
|
|
+ // 使用 nextTick 确保 DOM 更新后再播放视频
|
|
|
+ this.$nextTick(() => {
|
|
|
+ const videoContext = uni.createVideoContext('myVideo', this);
|
|
|
+ if (videoContext) {
|
|
|
+ videoContext.play();
|
|
|
+
|
|
|
+ // 视频开始播放后短暂延迟显示字幕,确保用户注意到
|
|
|
+ setTimeout(() => {
|
|
|
+ // 设置低分提示视频的字幕
|
|
|
+ this.currentSubtitle = '我未听清楚您在说什么,请您再说一遍!';
|
|
|
+
|
|
|
+ // 创建专门的字幕数组用于低分提示视频
|
|
|
+ this.lowScoreVideoSubtitles = [
|
|
|
+ {
|
|
|
+ startTime: 0,
|
|
|
+ endTime: 10, // 假设视频长度为10秒,可根据实际情况调整
|
|
|
+ text: '我未听清楚您在说什么,请您再说一遍!'
|
|
|
+ }
|
|
|
+ ];
|
|
|
+ }, 500);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ // 添加新方法:处理重新录制按钮点击
|
|
|
+ handleRerecordButtonClick() {
|
|
|
+ console.log('点击重新录制按钮');
|
|
|
+
|
|
|
+ // 增加重试计数
|
|
|
+ this.retryCount++;
|
|
|
+ console.log(`当前重试次数: ${this.retryCount}/${this.maxRetryAttempts}`);
|
|
|
+
|
|
|
+ // 隐藏重新录制按钮
|
|
|
+ this.showRerecordButton = false;
|
|
|
+
|
|
|
+ // 直接调用开始录制的方法
|
|
|
+ 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() {
|
|
|
+ console.log('页面卸载,关闭 WebSocket 连接');
|
|
|
+ this.closeWebSocketConnection();
|
|
|
+ },
|
|
|
+
|
|
|
+ // 添加 onHide 生命周期钩子,在页面隐藏时也关闭连接
|
|
|
+ onHide() {
|
|
|
+ console.log('页面隐藏,关闭 WebSocket 连接');
|
|
|
+ this.closeWebSocketConnection();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -3189,4 +3534,33 @@ video::-webkit-media-controls-fullscreen-button {
|
|
|
left: 0;
|
|
|
z-index: 5; /* 确保GIF在视频上方但在字幕和按钮下方 */
|
|
|
}
|
|
|
+
|
|
|
+/* 重新录制按钮容器样式 */
|
|
|
+.rerecord-button-container {
|
|
|
+ position: absolute;
|
|
|
+ bottom: 50px; /* 统一与其他按钮的位置 */
|
|
|
+ left: 50%;
|
|
|
+ transform: translateX(-50%);
|
|
|
+ z-index: 20;
|
|
|
+}
|
|
|
+
|
|
|
+/* 重新录制按钮样式 */
|
|
|
+.rerecord-button {
|
|
|
+ width: 120px;
|
|
|
+ height: 40px;
|
|
|
+ border-radius: 20px;
|
|
|
+ background-color: #ffffff;
|
|
|
+ color: #333;
|
|
|
+ font-size: 16px;
|
|
|
+ border: none;
|
|
|
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ cursor: pointer;
|
|
|
+}
|
|
|
+
|
|
|
+.rerecord-button:hover {
|
|
|
+ background-color: #f0f0f0;
|
|
|
+}
|
|
|
</style>
|