|
@@ -46,9 +46,20 @@ interface CandidateInfo {
|
|
|
is_correct?: boolean | string
|
|
|
question_image_url?: string
|
|
|
options?: {
|
|
|
+ id: number
|
|
|
option_text: string
|
|
|
is_correct: boolean
|
|
|
+ sort: number
|
|
|
}[]
|
|
|
+ answer_data?: {
|
|
|
+ text_answer: string
|
|
|
+ selected_options: number[]
|
|
|
+ selected_option_details: {
|
|
|
+ id: number
|
|
|
+ is_correct: boolean
|
|
|
+ option_text: string
|
|
|
+ }[]
|
|
|
+ }
|
|
|
}[]
|
|
|
videoRecords: {
|
|
|
category: string
|
|
@@ -277,7 +288,13 @@ const candidateInfo = ref<CandidateInfo>({
|
|
|
thumbnail: '',
|
|
|
question_form: 0,
|
|
|
is_correct: false,
|
|
|
- question_image_url: ''
|
|
|
+ question_image_url: '',
|
|
|
+ options: [],
|
|
|
+ answer_data: {
|
|
|
+ text_answer: '',
|
|
|
+ selected_options: [],
|
|
|
+ selected_option_details: []
|
|
|
+ }
|
|
|
},
|
|
|
{
|
|
|
question: '',
|
|
@@ -288,7 +305,13 @@ const candidateInfo = ref<CandidateInfo>({
|
|
|
thumbnail: '',
|
|
|
question_form: 0,
|
|
|
is_correct: false,
|
|
|
- question_image_url: ''
|
|
|
+ question_image_url: '',
|
|
|
+ options: [],
|
|
|
+ answer_data: {
|
|
|
+ text_answer: '',
|
|
|
+ selected_options: [],
|
|
|
+ selected_option_details: []
|
|
|
+ }
|
|
|
}
|
|
|
],
|
|
|
videoRecords: [
|
|
@@ -598,33 +621,49 @@ const updateCandidateInfo = (data: any) => {
|
|
|
// 更新面试记录
|
|
|
if (interview_progress && interview_progress.length > 0) {
|
|
|
candidateInfo.value.interviewRecord = interview_progress
|
|
|
- .filter((q: any) => q.video_answer)
|
|
|
+ .filter((q: any) => q.video_answer || q.answer_data)
|
|
|
.map((q: any) => {
|
|
|
- // 处理答案文本
|
|
|
- let answerText = q.video_answer?.transcript || '';
|
|
|
- let is_correct = false;
|
|
|
- // 如果有answer_data且包含选项,则使用选项文本
|
|
|
- if (q.answer_data && q.answer_data.selected_option_details && q.answer_data.selected_option_details.length > 0) {
|
|
|
- answerText = q.answer_data.selected_option_details
|
|
|
- .map((option: any) => option.option_text)
|
|
|
- .join(', ');
|
|
|
- is_correct = q.answer_data.selected_option_details
|
|
|
- .map((option: any) => option.is_correct)
|
|
|
- .join(', ');
|
|
|
-
|
|
|
- }
|
|
|
- return {
|
|
|
+ const record: InterviewRecord = {
|
|
|
question: q.question_text || '未提供问题',
|
|
|
- answer: answerText,
|
|
|
- analysis: q.video_answer?.ai_analysis?.comment || '',
|
|
|
- score: q.video_answer?.ai_score ? `${q.video_answer.ai_score}分` : '',
|
|
|
+ answer: '',
|
|
|
+ analysis: '',
|
|
|
+ score: '',
|
|
|
question_form: q.question_form,
|
|
|
- is_correct:is_correct,
|
|
|
- videoUrl: q.video_answer?.video_url || '',
|
|
|
- question_image_url: q.question_image_url || '',
|
|
|
- options: q.options || [],
|
|
|
- thumbnail: ''
|
|
|
+ options: q.options,
|
|
|
+ answer_data: q.answer_data
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理视频答案
|
|
|
+ if (q.video_answer) {
|
|
|
+ record.answer = q.video_answer.transcript || ''
|
|
|
+ record.analysis = q.video_answer.ai_analysis?.comment || ''
|
|
|
+ record.score = q.video_answer.ai_score ? `${q.video_answer.ai_score}分` : ''
|
|
|
+ record.videoUrl = q.video_answer.video_url || ''
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理选择题答案
|
|
|
+ if (q.answer_data) {
|
|
|
+ record.answer = q.answer_data.text_answer || ''
|
|
|
+ record.is_correct = q.answer_data.selected_option_details?.some((opt: any) => opt.is_correct) || false
|
|
|
}
|
|
|
+
|
|
|
+ // 处理图片题
|
|
|
+ if (q.question_form === 3) {
|
|
|
+ record.question_image_url = q.question_image_url || ''
|
|
|
+ }
|
|
|
+
|
|
|
+ return record
|
|
|
+ })
|
|
|
+ // 按题目类型排序:视频题(0) -> 图片题(3) -> 选择题(1,2,4)
|
|
|
+ .sort((a, b) => {
|
|
|
+ // 定义题型优先级
|
|
|
+ const getPriority = (questionForm: number) => {
|
|
|
+ if (questionForm === 0) return 0 // 视频题最优先
|
|
|
+ if (questionForm === 3) return 1 // 图片题次之
|
|
|
+ return 2 // 其他题型最后
|
|
|
+ }
|
|
|
+
|
|
|
+ return getPriority(a.question_form || 0) - getPriority(b.question_form || 0)
|
|
|
})
|
|
|
}
|
|
|
|
|
@@ -1164,7 +1203,7 @@ const handleTabClick = (tab: any) => {
|
|
|
}; */
|
|
|
|
|
|
// 添加到methods部分或直接在setup中定义
|
|
|
-const setActiveTab = (sectionId) => {
|
|
|
+const setActiveTab = (sectionId: string) => {
|
|
|
// 移除所有标签的active类
|
|
|
document.querySelectorAll('.tab-item').forEach(tab => {
|
|
|
tab.classList.remove('active');
|
|
@@ -1185,7 +1224,7 @@ const setActiveTab = (sectionId) => {
|
|
|
};
|
|
|
|
|
|
// 修改scrollToSection函数
|
|
|
-const scrollToSection = (sectionId) => {
|
|
|
+const scrollToSection = (sectionId: string) => {
|
|
|
console.log('尝试滚动到部分:', sectionId);
|
|
|
const element = document.getElementById(sectionId);
|
|
|
if (element) {
|
|
@@ -1522,8 +1561,77 @@ const getHandPhotos = (hand: 'left' | 'right'): PhotoResult[] => {
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
+ <!-- 选择题布局 -->
|
|
|
+ <div v-if="record.question_form === 1 || record.question_form === 2 || record.question_form === 4" class="mt-4">
|
|
|
+ <div class="bg-white p-4 rounded-lg">
|
|
|
+ <!-- 显示选项 -->
|
|
|
+ <div v-if="record.options && record.options.length > 0" class="space-y-3">
|
|
|
+ <div v-for="(option, optIndex) in record.options" :key="optIndex"
|
|
|
+ :class="[
|
|
|
+ 'p-3 rounded border',
|
|
|
+ record.answer_data?.selected_option_details?.some(
|
|
|
+ (selected: { id: number }) => selected.id === option.id
|
|
|
+ )
|
|
|
+ ? 'border-blue-300 bg-blue-50'
|
|
|
+ : 'border-gray-200'
|
|
|
+ ]">
|
|
|
+ <div class="flex items-center justify-between">
|
|
|
+ <div class="flex-1">
|
|
|
+ <span class="text-gray-700">{{ option.option_text }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="flex items-center space-x-2">
|
|
|
+ <!-- 只在非问卷调查题(question_form !== 4)时显示正确答案和对错状态 -->
|
|
|
+ <template v-if="record.question_form !== 4">
|
|
|
+ <span v-if="option.is_correct" class="text-green-500">✓ 正确答案</span>
|
|
|
+ <span v-if="record.answer_data?.selected_option_details?.some(
|
|
|
+ (selected: { id: number }) => selected.id === option.id
|
|
|
+ )"
|
|
|
+ :class="option.is_correct ? 'text-green-500' : 'text-red-500'">
|
|
|
+ {{ option.is_correct ? '(已选 - 正确)' : '(已选 - 错误)' }}
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ <!-- 问卷调查题只显示是否选中 -->
|
|
|
+ <template v-else>
|
|
|
+ <span v-if="record.answer_data?.selected_option_details?.some(
|
|
|
+ (selected: { id: number }) => selected.id === option.id
|
|
|
+ )"
|
|
|
+ class="text-blue-500">
|
|
|
+ (已选)
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 显示答案状态 -->
|
|
|
+ <div class="mt-4 flex justify-between items-center">
|
|
|
+ <div class="text-gray-600">
|
|
|
+ 候选人: {{ record.answer_data?.selected_option_details?.map(
|
|
|
+ (opt: { option_text: string }) => opt.option_text
|
|
|
+ ).join(', ') || '未作答' }}
|
|
|
+ </div>
|
|
|
+ <!-- 只在非问卷调查题时显示对错状态 -->
|
|
|
+ <div v-if="record.question_form !== 4">
|
|
|
+ <span :class="[
|
|
|
+ 'px-3 py-1 rounded-full text-sm',
|
|
|
+ record.answer_data?.selected_option_details?.every(
|
|
|
+ (opt: { is_correct: boolean }) => opt.is_correct
|
|
|
+ )
|
|
|
+ ? 'bg-green-100 text-green-800'
|
|
|
+ : 'bg-red-100 text-red-800'
|
|
|
+ ]">
|
|
|
+ {{ record.answer_data?.selected_option_details?.every(
|
|
|
+ (opt: { is_correct: boolean }) => opt.is_correct
|
|
|
+ ) ? '正确' : '错误' }}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
<!-- 视频问答题布局 -->
|
|
|
- <div v-if="record.question_form === 0" class="mt-4 flex space-x-4">
|
|
|
+ <div v-else-if="record.question_form === 0" class="mt-4 flex space-x-4">
|
|
|
|
|
|
|
|
|
<!-- 右侧答案和评分 -->
|
|
@@ -1567,83 +1675,75 @@ const getHandPhotos = (hand: 'left' | 'right'): PhotoResult[] => {
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- <!-- 选择题布局 -->
|
|
|
- <div v-else-if="record.question_form === 1 || record.question_form === 2 || record.question_form === 4" class="mt-4">
|
|
|
- <div class="bg-white p-4 rounded-lg">
|
|
|
- <div class="flex items-center justify-between mb-3">
|
|
|
- <div class="flex items-center space-x-2">
|
|
|
- <div class="bg-green-100 text-green-800 px-2 py-1 rounded text-sm">候选人:</div>
|
|
|
- <p class="text-gray-700" style="margin: 0;">{{ record.answer }}</p>
|
|
|
- </div>
|
|
|
- <div>
|
|
|
- <span v-if="record.question_form === 1 || record.question_form === 2" :class="[
|
|
|
- 'px-3 py-1 rounded-full text-sm',
|
|
|
- record.is_correct === true || record.is_correct === 'true'
|
|
|
- ? 'bg-green-100 text-green-800'
|
|
|
- : 'bg-red-100 text-red-800'
|
|
|
- ]">
|
|
|
- {{ record.is_correct === true || record.is_correct === 'true' ? '正确' : '错误' }}
|
|
|
- </span>
|
|
|
+ <!-- 图片题布局 -->
|
|
|
+ <div v-else-if="record.question_form === 3" class="mt-4">
|
|
|
+ <div class="grid grid-cols-2 gap-4">
|
|
|
+ <!-- 左侧图片显示 -->
|
|
|
+ <div class="bg-white p-4 rounded-lg">
|
|
|
+ <div class="aspect-w-16 aspect-h-9 rounded-lg overflow-hidden bg-gray-100">
|
|
|
+ <img
|
|
|
+ :src="record.question_image_url"
|
|
|
+ alt="题目图片"
|
|
|
+ class="w-full h-full object-contain"
|
|
|
+ @error="handleImageError"
|
|
|
+ >
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- <!-- 添加选项渲染 -->
|
|
|
- <div v-if="record.options && record.options.length > 0" class="mt-3 space-y-2">
|
|
|
- <div class="text-sm text-gray-500 mb-1">所有选项:</div>
|
|
|
- <div v-for="(option, optIndex) in record.options" :key="optIndex"
|
|
|
- :class="[
|
|
|
- 'p-2 rounded border',
|
|
|
- record.answer.includes(option.option_text)
|
|
|
- ? 'border-blue-300 bg-blue-50'
|
|
|
- : 'border-gray-200'
|
|
|
- ]">
|
|
|
- <div class="flex items-start">
|
|
|
- <!-- <div class="mr-2 text-gray-500">{{ String.fromCharCode(65 + optIndex) }}.</div> -->
|
|
|
- <div class="flex-1">
|
|
|
- <div class="text-gray-700">{{ option.option_text }}</div>
|
|
|
- <div v-if="option.is_correct" class="text-xs text-green-600 mt-1">✓ 正确答案</div>
|
|
|
+ <!-- 右侧选项和答案 -->
|
|
|
+ <div class="bg-white p-4 rounded-lg">
|
|
|
+ <!-- 显示选项 -->
|
|
|
+ <div v-if="record.options && record.options.length > 0" class="space-y-3">
|
|
|
+ <div v-for="(option, optIndex) in record.options" :key="optIndex"
|
|
|
+ :class="[
|
|
|
+ 'p-3 rounded border',
|
|
|
+ record.answer_data?.selected_option_details?.some(
|
|
|
+ (selected: { id: number }) => selected.id === option.id
|
|
|
+ )
|
|
|
+ ? 'border-blue-300 bg-blue-50'
|
|
|
+ : 'border-gray-200'
|
|
|
+ ]">
|
|
|
+ <div class="flex items-center justify-between">
|
|
|
+ <div class="flex-1">
|
|
|
+ <span class="text-gray-700">{{ option.option_text }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="flex items-center space-x-2">
|
|
|
+ <span v-if="option.is_correct" class="text-green-500">✓ 正确答案</span>
|
|
|
+ <span v-if="record.answer_data?.selected_option_details?.some(
|
|
|
+ (selected: { id: number }) => selected.id === option.id
|
|
|
+ )"
|
|
|
+ :class="option.is_correct ? 'text-green-500' : 'text-red-500'">
|
|
|
+ {{ option.is_correct ? '(已选 - 正确)' : '(已选 - 错误)' }}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 图片题布局 -->
|
|
|
- <div v-else-if="record.question_form === 3" class="mt-4 flex space-x-4">
|
|
|
- <!-- 左侧答案部分 -->
|
|
|
- <div class="w-1/3">
|
|
|
- <div class="bg-white p-4 rounded-lg">
|
|
|
- <div class="flex items-start space-x-2">
|
|
|
- <div class="bg-green-100 text-green-800 px-2 py-1 rounded text-sm">候选人</div>
|
|
|
- <div class="flex-1">
|
|
|
- <p class="text-gray-700" style="margin: 0;">{{ record.answer }}</p>
|
|
|
- <div class="mt-2">
|
|
|
- <span :class="[
|
|
|
- 'px-3 py-1 rounded-full text-sm',
|
|
|
- record.is_correct === true || record.is_correct === 'true'
|
|
|
- ? 'bg-green-100 text-green-800'
|
|
|
- : 'bg-red-100 text-red-800'
|
|
|
- ]">
|
|
|
- {{ record.is_correct === true || record.is_correct === 'true' ? '正确' : '错误' }}
|
|
|
- </span>
|
|
|
- </div>
|
|
|
+
|
|
|
+ <!-- 显示答案状态 -->
|
|
|
+ <div class="mt-4 flex justify-between items-center">
|
|
|
+ <div class="text-gray-600">
|
|
|
+ 答案: {{ record.answer_data?.selected_option_details?.map(
|
|
|
+ (opt: { option_text: string }) => opt.option_text
|
|
|
+ ).join(', ') || '未作答' }}
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <span :class="[
|
|
|
+ 'px-3 py-1 rounded-full text-sm',
|
|
|
+ record.answer_data?.selected_option_details?.every(
|
|
|
+ (opt: { is_correct: boolean }) => opt.is_correct
|
|
|
+ )
|
|
|
+ ? 'bg-green-100 text-green-800'
|
|
|
+ : 'bg-red-100 text-red-800'
|
|
|
+ ]">
|
|
|
+ {{ record.answer_data?.selected_option_details?.every(
|
|
|
+ (opt: { is_correct: boolean }) => opt.is_correct
|
|
|
+ ) ? '正确' : '错误' }}
|
|
|
+ </span>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
-
|
|
|
- <!-- 右侧图片显示 -->
|
|
|
- <div class="w-2/3">
|
|
|
- <div class=" rounded-lg overflow-hidden bg-gray-100">
|
|
|
- <img
|
|
|
- :src="record.question_image_url"
|
|
|
- alt="题目图片"
|
|
|
- class="w-full h-full object-cover rounded-lg"
|
|
|
- @error="handleImageError"
|
|
|
- >
|
|
|
- </div>
|
|
|
- </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|