|
@@ -71,6 +71,26 @@
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
+ <!-- 眼动情绪检测弹窗 -->
|
|
|
|
+ <el-dialog
|
|
|
|
+ v-model="eyeEmotionDialogVisible"
|
|
|
|
+ title="眼动情绪检测"
|
|
|
|
+ width="80%"
|
|
|
|
+ :before-close="handleEyeEmotionDialogClose"
|
|
|
|
+ >
|
|
|
|
+ <div class="eye-emotion-content">
|
|
|
|
+ <!-- 这里添加眼动情绪检测的内容 -->
|
|
|
|
+ <div class="emotion-data">
|
|
|
|
+ <h3>眼动追踪数据</h3>
|
|
|
|
+ <!-- 这里可以添加图表或详细数据 -->
|
|
|
|
+ </div>
|
|
|
|
+ <div class="emotion-analysis">
|
|
|
|
+ <h3>情绪分析结果</h3>
|
|
|
|
+ <!-- 这里可以添加分析结果 -->
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </el-dialog>
|
|
|
|
+
|
|
<!-- 修改导航选项卡部分 -->
|
|
<!-- 修改导航选项卡部分 -->
|
|
<div
|
|
<div
|
|
class="nav-tabs"
|
|
class="nav-tabs"
|
|
@@ -256,7 +276,15 @@
|
|
<div ref="cheat" class="detection-section">
|
|
<div ref="cheat" class="detection-section">
|
|
<div class="detection-section-header">
|
|
<div class="detection-section-header">
|
|
<div class="section-title">作弊检测</div>
|
|
<div class="section-title">作弊检测</div>
|
|
- <div class="status-tag normal">无异常</div>
|
|
|
|
|
|
+ <div class="status-tag normal" v-if="true">无异常</div>
|
|
|
|
+ <el-button
|
|
|
|
+ v-if="!true"
|
|
|
|
+ type="primary"
|
|
|
|
+ link
|
|
|
|
+ @click="showCheatVerification = true"
|
|
|
|
+ >
|
|
|
|
+ 查看异常详情
|
|
|
|
+ </el-button>
|
|
</div>
|
|
</div>
|
|
<div class="detection-section-content">
|
|
<div class="detection-section-content">
|
|
<div class="detection-items">
|
|
<div class="detection-items">
|
|
@@ -840,6 +868,64 @@
|
|
|
|
|
|
|
|
|
|
</el-dialog>
|
|
</el-dialog>
|
|
|
|
+
|
|
|
|
+<!-- 添加作弊检测详情弹窗 -->
|
|
|
|
+<el-dialog
|
|
|
|
+ title="作弊检测详情"
|
|
|
|
+ v-model="showCheatVerification"
|
|
|
|
+ width="80%"
|
|
|
|
+ :before-close="handleCheatVerificationClose"
|
|
|
|
+ class="cheat-verification-dialog"
|
|
|
|
+>
|
|
|
|
+ <div class="cheat-verification">
|
|
|
|
+ <div class="verification-content">
|
|
|
|
+ <!-- 转移、替考检测 -->
|
|
|
|
+ <div class="verification-item">
|
|
|
|
+ <div class="item-header">
|
|
|
|
+ <span class="item-title">转移、替考检测</span>
|
|
|
|
+ <span class="item-status normal">无风险</span>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="item-details">
|
|
|
|
+ <p>通过AI人脸识别技术,对考生面部特征进行实时监控,未发现替考或转移行为。</p>
|
|
|
|
+ <div class="detail-images" v-if="false">
|
|
|
|
+ <!-- 如果有异常图片证据,这里可以展示 -->
|
|
|
|
+ <img src="" alt="异常证据" />
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <!-- 读稿检测 -->
|
|
|
|
+ <div class="verification-item">
|
|
|
|
+ <div class="item-header">
|
|
|
|
+ <span class="item-title">读稿检测</span>
|
|
|
|
+ <span class="item-status normal">无风险</span>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="item-details">
|
|
|
|
+ <p>通过眼动追踪和头部姿态分析,未发现考生有明显读稿行为。</p>
|
|
|
|
+ <div class="detail-images" v-if="false">
|
|
|
|
+ <!-- 如果有异常图片证据,这里可以展示 -->
|
|
|
|
+ <img src="" alt="异常证据" />
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <!-- 录屏/切屏检测 -->
|
|
|
|
+ <div class="verification-item">
|
|
|
|
+ <div class="item-header">
|
|
|
|
+ <span class="item-title">录屏/切屏检测</span>
|
|
|
|
+ <span class="item-status normal">无风险</span>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="item-details">
|
|
|
|
+ <p>系统监控显示考生未进行录屏或切屏操作,面试过程保持正常。</p>
|
|
|
|
+ <div class="detail-images" v-if="false">
|
|
|
|
+ <!-- 如果有异常图片证据,这里可以展示 -->
|
|
|
|
+ <img src="" alt="异常证据" />
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+</el-dialog>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</template>
|
|
|
|
|
|
@@ -900,6 +986,7 @@ export default {
|
|
{ id: 'cheat', name: '作弊检测' },
|
|
{ id: 'cheat', name: '作弊检测' },
|
|
{ id: 'psychology', name: '心理检测' },
|
|
{ id: 'psychology', name: '心理检测' },
|
|
{ id: 'body', name: '肢体检测' },
|
|
{ id: 'body', name: '肢体检测' },
|
|
|
|
+ { id: 'eye-emotion', name: '眼动/情绪检测', isDialog: true },
|
|
{ id: 'personal-info', name: '个人详细信息', isInfo: true },
|
|
{ id: 'personal-info', name: '个人详细信息', isInfo: true },
|
|
{ id: 'answers', name: '问答记录' },
|
|
{ id: 'answers', name: '问答记录' },
|
|
{ id: 'other-answers', name: '其余答题详情', isLink: true }
|
|
{ id: 'other-answers', name: '其余答题详情', isLink: true }
|
|
@@ -971,6 +1058,19 @@ export default {
|
|
department: '',
|
|
department: '',
|
|
},
|
|
},
|
|
showBodyVerification: false, // 添加控制弹窗显示的数据
|
|
showBodyVerification: false, // 添加控制弹窗显示的数据
|
|
|
|
+ eyeEmotionDialogVisible: false, // 控制眼动情绪检测弹窗显示
|
|
|
|
+ eyeEmotionData: {
|
|
|
|
+ eyeTrackingData: {
|
|
|
|
+ focusPoints: [],
|
|
|
|
+ dwellTime: [],
|
|
|
|
+ scanPath: []
|
|
|
|
+ },
|
|
|
|
+ emotionAnalysis: {
|
|
|
|
+ mainEmotion: '',
|
|
|
|
+ emotionDetails: [],
|
|
|
|
+ suggestions: []
|
|
|
|
+ }
|
|
|
|
+ },
|
|
competencyMap: {
|
|
competencyMap: {
|
|
'communication_cooperation': '团队协作能力',
|
|
'communication_cooperation': '团队协作能力',
|
|
'learning_ability': '应变能力',
|
|
'learning_ability': '应变能力',
|
|
@@ -995,7 +1095,8 @@ export default {
|
|
radarChartInstance: null,
|
|
radarChartInstance: null,
|
|
interviewRecords: [], // 存储问答记录
|
|
interviewRecords: [], // 存储问答记录
|
|
followUpQuestions: [], // 存储追问题
|
|
followUpQuestions: [], // 存储追问题
|
|
- noTableHeight: 0
|
|
|
|
|
|
+ noTableHeight: 0,
|
|
|
|
+ showCheatVerification: false, // 添加控制作弊检测详情弹窗显示
|
|
}
|
|
}
|
|
},
|
|
},
|
|
async created() {
|
|
async created() {
|
|
@@ -1441,10 +1542,51 @@ export default {
|
|
this.showInfoDialog = true;
|
|
this.showInfoDialog = true;
|
|
} else if (tab.isLink) {
|
|
} else if (tab.isLink) {
|
|
this.scrollToSection(tab.id);
|
|
this.scrollToSection(tab.id);
|
|
|
|
+ } else if (tab.isDialog) {
|
|
|
|
+ // 处理弹窗类型的标签点击
|
|
|
|
+ if (tab.id === 'eye-emotion') {
|
|
|
|
+ this.openEyeEmotionDialog();
|
|
|
|
+ }
|
|
} else {
|
|
} else {
|
|
this.scrollToSection(tab.id);
|
|
this.scrollToSection(tab.id);
|
|
}
|
|
}
|
|
},
|
|
},
|
|
|
|
+
|
|
|
|
+ // 打开眼动情绪检测弹窗
|
|
|
|
+ async openEyeEmotionDialog() {
|
|
|
|
+ this.eyeEmotionDialogVisible = true;
|
|
|
|
+ /* await this.fetchEyeEmotionData(); */
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ // 关闭眼动情绪检测弹窗
|
|
|
|
+ handleEyeEmotionDialogClose() {
|
|
|
|
+ this.eyeEmotionDialogVisible = false;
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ // 获取眼动情绪数据
|
|
|
|
+ async fetchEyeEmotionData() {
|
|
|
|
+ try {
|
|
|
|
+ const application_id = this.$route.query.id || this.$route.params.id;
|
|
|
|
+ const response = await fetch(
|
|
|
|
+ `${import.meta.env.VITE_API_URL}/api/job/eye_emotion_analysis?tenant_id=${1}&application_id=${application_id}`
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ if (!response.ok) {
|
|
|
|
+ throw new Error('获取眼动情绪数据失败');
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const data = await response.json();
|
|
|
|
+
|
|
|
|
+ if (data.code === 2000) {
|
|
|
|
+ this.eyeEmotionData = data.data || this.eyeEmotionData;
|
|
|
|
+ } else {
|
|
|
|
+ ElMessage.error('获取眼动情绪数据失败');
|
|
|
|
+ }
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error('获取眼动情绪数据失败:', error);
|
|
|
|
+ ElMessage.error('获取眼动情绪数据失败');
|
|
|
|
+ }
|
|
|
|
+ },
|
|
handleDialogClose() {
|
|
handleDialogClose() {
|
|
this.showInfoDialog = false;
|
|
this.showInfoDialog = false;
|
|
},
|
|
},
|
|
@@ -2127,6 +2269,9 @@ export default {
|
|
// 其他情况返回默认文本
|
|
// 其他情况返回默认文本
|
|
return '暂无回答';
|
|
return '暂无回答';
|
|
},
|
|
},
|
|
|
|
+ handleCheatVerificationClose() {
|
|
|
|
+ this.showCheatVerification = false;
|
|
|
|
+ },
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
</script>
|
|
@@ -2806,7 +2951,7 @@ export default {
|
|
|
|
|
|
.tab-item {
|
|
.tab-item {
|
|
position: relative;
|
|
position: relative;
|
|
- padding: 5px 22px;
|
|
|
|
|
|
+ padding: 5px 15px;
|
|
font-size: 14px;
|
|
font-size: 14px;
|
|
color: #606266;
|
|
color: #606266;
|
|
cursor: pointer;
|
|
cursor: pointer;
|
|
@@ -3684,6 +3829,112 @@ export default {
|
|
border-radius: 12px;
|
|
border-radius: 12px;
|
|
overflow: hidden;
|
|
overflow: hidden;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+// 眼动情绪检测弹窗样式
|
|
|
|
+.eye-emotion-content {
|
|
|
|
+ padding: 20px;
|
|
|
|
+
|
|
|
|
+ .emotion-data {
|
|
|
|
+ margin-bottom: 30px;
|
|
|
|
+
|
|
|
|
+ h3 {
|
|
|
|
+ font-size: 16px;
|
|
|
|
+ font-weight: bold;
|
|
|
|
+ color: #333;
|
|
|
|
+ margin-bottom: 20px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .data-charts {
|
|
|
|
+ display: grid;
|
|
|
|
+ grid-template-columns: repeat(2, 1fr);
|
|
|
|
+ gap: 20px;
|
|
|
|
+ margin-bottom: 20px;
|
|
|
|
+
|
|
|
|
+ .chart-item {
|
|
|
|
+ background: #f8f8f8;
|
|
|
|
+ padding: 15px;
|
|
|
|
+ border-radius: 8px;
|
|
|
|
+
|
|
|
|
+ .chart-title {
|
|
|
|
+ font-size: 14px;
|
|
|
|
+ color: #666;
|
|
|
|
+ margin-bottom: 10px;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .emotion-analysis {
|
|
|
|
+ h3 {
|
|
|
|
+ font-size: 16px;
|
|
|
|
+ font-weight: bold;
|
|
|
|
+ color: #333;
|
|
|
|
+ margin-bottom: 20px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .analysis-content {
|
|
|
|
+ background: #f8f8f8;
|
|
|
|
+ padding: 20px;
|
|
|
|
+ border-radius: 8px;
|
|
|
|
+
|
|
|
|
+ .main-emotion {
|
|
|
|
+ font-size: 14px;
|
|
|
|
+ color: #333;
|
|
|
|
+ margin-bottom: 15px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .emotion-details {
|
|
|
|
+ margin-bottom: 20px;
|
|
|
|
+
|
|
|
|
+ .detail-item {
|
|
|
|
+ margin-bottom: 10px;
|
|
|
|
+ padding: 10px;
|
|
|
|
+ background: #fff;
|
|
|
|
+ border-radius: 6px;
|
|
|
|
+
|
|
|
|
+ .emotion-type {
|
|
|
|
+ font-weight: 500;
|
|
|
|
+ color: #333;
|
|
|
|
+ margin-bottom: 5px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .emotion-desc {
|
|
|
|
+ color: #666;
|
|
|
|
+ font-size: 13px;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .suggestions {
|
|
|
|
+ .suggestion-title {
|
|
|
|
+ font-weight: 500;
|
|
|
|
+ color: #333;
|
|
|
|
+ margin-bottom: 10px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .suggestion-list {
|
|
|
|
+ list-style: none;
|
|
|
|
+ padding: 0;
|
|
|
|
+
|
|
|
|
+ li {
|
|
|
|
+ color: #666;
|
|
|
|
+ font-size: 13px;
|
|
|
|
+ margin-bottom: 8px;
|
|
|
|
+ padding-left: 15px;
|
|
|
|
+ position: relative;
|
|
|
|
+
|
|
|
|
+ &:before {
|
|
|
|
+ content: "•";
|
|
|
|
+ position: absolute;
|
|
|
|
+ left: 0;
|
|
|
|
+ color: #333;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
// 移动端适配
|
|
// 移动端适配
|
|
@media screen and (max-width: 768px) {
|
|
@media screen and (max-width: 768px) {
|
|
.qa-section {
|
|
.qa-section {
|
|
@@ -3911,4 +4162,82 @@ export default {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+/* 作弊检测弹窗样式 */
|
|
|
|
+.cheat-verification-dialog {
|
|
|
|
+ :deep(.el-dialog__body) {
|
|
|
|
+ padding: 20px;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.cheat-verification {
|
|
|
|
+ .verification-content {
|
|
|
|
+ .verification-item {
|
|
|
|
+ background: #f8f8f8;
|
|
|
|
+ border-radius: 8px;
|
|
|
|
+ padding: 16px;
|
|
|
|
+ margin-bottom: 16px;
|
|
|
|
+
|
|
|
|
+ &:last-child {
|
|
|
|
+ margin-bottom: 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .item-header {
|
|
|
|
+ display: flex;
|
|
|
|
+ align-items: center;
|
|
|
|
+ margin-bottom: 12px;
|
|
|
|
+
|
|
|
|
+ .item-title {
|
|
|
|
+ font-size: 16px;
|
|
|
|
+ font-weight: 500;
|
|
|
|
+ color: #333;
|
|
|
|
+ margin-right: 12px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .item-status {
|
|
|
|
+ padding: 4px 12px;
|
|
|
|
+ border-radius: 4px;
|
|
|
|
+ font-size: 14px;
|
|
|
|
+
|
|
|
|
+ &.normal {
|
|
|
|
+ background: #e1f3d8;
|
|
|
|
+ color: #67c23a;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ &.warning {
|
|
|
|
+ background: #fdf6ec;
|
|
|
|
+ color: #e6a23c;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ &.error {
|
|
|
|
+ background: #fef0f0;
|
|
|
|
+ color: #f56c6c;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .item-details {
|
|
|
|
+ p {
|
|
|
|
+ color: #666;
|
|
|
|
+ font-size: 14px;
|
|
|
|
+ line-height: 1.6;
|
|
|
|
+ margin: 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .detail-images {
|
|
|
|
+ margin-top: 12px;
|
|
|
|
+ display: flex;
|
|
|
|
+ gap: 12px;
|
|
|
|
+
|
|
|
|
+ img {
|
|
|
|
+ width: 120px;
|
|
|
|
+ height: 90px;
|
|
|
|
+ object-fit: cover;
|
|
|
|
+ border-radius: 4px;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
</style>
|
|
</style>
|