|
@@ -69,6 +69,11 @@ interface CandidateInfo {
|
|
|
passed: boolean
|
|
|
images: string[]
|
|
|
}
|
|
|
+ comprehensiveVerification: string
|
|
|
+ handVerification: string
|
|
|
+ handBrightness: string
|
|
|
+ handIntegrity: string
|
|
|
+ handPoseRecognition: string
|
|
|
}
|
|
|
strengths?: string[]
|
|
|
weaknesses?: string[]
|
|
@@ -174,7 +179,12 @@ const candidateInfo = ref<CandidateInfo>({
|
|
|
images: [
|
|
|
|
|
|
]
|
|
|
- }
|
|
|
+ },
|
|
|
+ comprehensiveVerification: '通过',
|
|
|
+ handVerification: '通过',
|
|
|
+ handBrightness: '通过',
|
|
|
+ handIntegrity: '通过',
|
|
|
+ handPoseRecognition: '通过'
|
|
|
},
|
|
|
strengths: [],
|
|
|
weaknesses: [],
|
|
@@ -624,9 +634,11 @@ const handleDownload = async () => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// 添加类型定义
|
|
|
+const originalButtonDisplay: string[] = []
|
|
|
+
|
|
|
+// 修改打印函数
|
|
|
const handlePrint = () => {
|
|
|
- /* ElMessage.success('准备打印报告...') */
|
|
|
-
|
|
|
// 保存当前页面滚动位置
|
|
|
const scrollPosition = window.scrollY
|
|
|
|
|
@@ -639,11 +651,12 @@ const handlePrint = () => {
|
|
|
|
|
|
// 隐藏不需要打印的元素
|
|
|
const buttonsToHide = document.querySelectorAll('.fixed')
|
|
|
- const originalButtonDisplay = []
|
|
|
|
|
|
buttonsToHide.forEach((button, index) => {
|
|
|
- originalButtonDisplay[index] = button.style.display
|
|
|
- button.style.display = 'none'
|
|
|
+ // 添加类型断言
|
|
|
+ const buttonElement = button as HTMLElement
|
|
|
+ originalButtonDisplay[index] = buttonElement.style.display
|
|
|
+ buttonElement.style.display = 'none'
|
|
|
})
|
|
|
|
|
|
// 延迟执行打印,确保样式已应用
|
|
@@ -656,7 +669,9 @@ const handlePrint = () => {
|
|
|
|
|
|
// 恢复隐藏的按钮
|
|
|
buttonsToHide.forEach((button, index) => {
|
|
|
- button.style.display = originalButtonDisplay[index]
|
|
|
+ // 添加类型断言
|
|
|
+ const buttonElement = button as HTMLElement
|
|
|
+ buttonElement.style.display = originalButtonDisplay[index]
|
|
|
})
|
|
|
|
|
|
// 恢复滚动位置
|
|
@@ -765,294 +780,502 @@ const handleVideoError = (event: Event) => {
|
|
|
</script>
|
|
|
|
|
|
<template>
|
|
|
- <div class="max-w-4xl mx-auto p-6 relative overflow-y-auto h-full">
|
|
|
- <!-- 添加顶部锚点 -->
|
|
|
- <div id="report-top" ref="reportTop"></div>
|
|
|
-
|
|
|
- <!-- 加载状态 -->
|
|
|
- <a-spin :spinning="loading" tip="加载中...">
|
|
|
- <!-- 页面标题 -->
|
|
|
- <div class="bg-[#1d1e3a] text-white p-4 rounded-t-lg">
|
|
|
- <div class="flex justify-between items-center">
|
|
|
- <div class="text-sm">No.{{ apiData?.application?.report_id || candidateInfo.idNumber }}</div>
|
|
|
- <div class="text-sm">{{ new Date().toLocaleString() }}</div>
|
|
|
+ <!-- 修改最外层容器的类,添加背景样式 -->
|
|
|
+ <div class="min-h-screen bg-gradient-custom">
|
|
|
+ <div class="max-w-4xl mx-auto p-6 relative overflow-y-auto" style="height: 100vh;">
|
|
|
+ <!-- 添加顶部锚点 -->
|
|
|
+ <div id="report-top" ref="reportTop"></div>
|
|
|
+
|
|
|
+ <!-- 加载状态 -->
|
|
|
+ <a-spin :spinning="loading" tip="加载中...">
|
|
|
+ <!-- 页面标题 -->
|
|
|
+ <div class="bg-[#1d1e3a] text-white p-4 rounded-t-lg">
|
|
|
+ <div class="flex justify-between items-center">
|
|
|
+ <div class="text-sm">No.{{ apiData?.application?.report_id || candidateInfo.idNumber }}</div>
|
|
|
+ <div class="text-sm">{{ new Date().toLocaleString() }}</div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
|
|
|
- <div v-if="error" class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert">
|
|
|
- <strong class="font-bold">错误!</strong>
|
|
|
- <span class="block sm:inline">{{ error }}</span>
|
|
|
- </div>
|
|
|
+ <div v-if="error" class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert">
|
|
|
+ <strong class="font-bold">错误!</strong>
|
|
|
+ <span class="block sm:inline">{{ error }}</span>
|
|
|
+ </div>
|
|
|
|
|
|
- <div v-else class="bg-white rounded-b-lg shadow-lg p-6">
|
|
|
- <!-- 头部信息 -->
|
|
|
- <div class="flex justify-between items-center mb-8 pb-4 border-b">
|
|
|
- <div class="flex items-center space-x-4">
|
|
|
- <div class="w-20 h-20 bg-gray-200 rounded-lg overflow-hidden">
|
|
|
- <img
|
|
|
- :src="candidateInfo.additionalInfo.faceVerification.images[0]"
|
|
|
- alt="头像"
|
|
|
- class="w-full h-full object-cover"
|
|
|
- @error="handleImageError"
|
|
|
- >
|
|
|
- </div>
|
|
|
- <div>
|
|
|
- <h1 class="text-2xl font-bold">{{ candidateInfo.name }}</h1>
|
|
|
- <p class="text-gray-600">{{ candidateInfo.phoneNumber }}</p>
|
|
|
- <p v-if="apiData?.position" class="text-gray-500 text-sm">
|
|
|
- 应聘职位: {{ apiData.position.title }} - {{ apiData.position.department }}
|
|
|
- </p>
|
|
|
+ <div v-else class="bg-white rounded-b-lg shadow-lg p-6">
|
|
|
+ <!-- 头部信息 -->
|
|
|
+ <div class="flex justify-between items-center mb-8 pb-4 border-b">
|
|
|
+ <div class="flex items-center space-x-4">
|
|
|
+ <div class="w-20 h-20 bg-gray-200 rounded-lg overflow-hidden">
|
|
|
+ <img
|
|
|
+ :src="candidateInfo.additionalInfo.faceVerification.images[0]"
|
|
|
+ alt="头像"
|
|
|
+ class="w-full h-full object-cover"
|
|
|
+ @error="handleImageError"
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <h1 class="text-2xl font-bold">{{ candidateInfo.name }}</h1>
|
|
|
+ <p class="text-gray-600">{{ candidateInfo.phoneNumber }}</p>
|
|
|
+ <p v-if="apiData?.position" class="text-gray-500 text-sm">
|
|
|
+ 应聘职位: {{ apiData.position.title }} - {{ apiData.position.department }}
|
|
|
+ </p>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- <div class="text-right">
|
|
|
- <div class="text-4xl font-bold text-yellow-500">{{ candidateInfo.score }}<span class="text-base ml-1">分</span></div>
|
|
|
- <div class="text-sm text-yellow-500">
|
|
|
- {{ candidateInfo.score >= 70 ? '推荐 👍' : candidateInfo.score >= 60 ? '待定 🤔' : '不推荐 👎' }}
|
|
|
+ <div class="text-right">
|
|
|
+ <div class="text-4xl font-bold text-yellow-500">{{ candidateInfo.score }}<span class="text-base ml-1">分</span></div>
|
|
|
+ <div class="text-sm text-yellow-500">
|
|
|
+ {{ candidateInfo.score >= 70 ? '推荐 👍' : candidateInfo.score >= 60 ? '待定 🤔' : '不推荐 👎' }}
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
|
|
|
- <!-- 基本信息 -->
|
|
|
- <div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-8">
|
|
|
- <div>
|
|
|
- <label class="text-gray-600">身份证号</label>
|
|
|
- <div>{{ candidateInfo.idNumber }}</div>
|
|
|
- </div>
|
|
|
- <div>
|
|
|
- <label class="text-gray-600">入职之后,您缺岗的班次时间段是?</label>
|
|
|
- <div>{{ candidateInfo.availabilityPeriod }}</div>
|
|
|
- </div>
|
|
|
- <div>
|
|
|
- <label class="text-gray-600">请问您通过面试之后多久可以入职?</label>
|
|
|
- <div>{{ candidateInfo.onboardingTime }}</div>
|
|
|
- </div>
|
|
|
- <div>
|
|
|
- <label class="text-gray-600">薪资范围</label>
|
|
|
- <div>{{ candidateInfo.salaryRange }}</div>
|
|
|
- </div>
|
|
|
- <div>
|
|
|
- <label class="text-gray-600">建议薪资</label>
|
|
|
- <div class="font-semibold text-blue-600">{{ candidateInfo.suggestedSalary }}</div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 1. 综合评估 -->
|
|
|
- <div class="mb-8">
|
|
|
- <h2 class="text-xl font-bold mb-6">1. 综合评估</h2>
|
|
|
- <div class="space-y-4">
|
|
|
- <div class="border-b pb-4">
|
|
|
- <div class="flex items-center justify-between mb-2">
|
|
|
- <span class="text-gray-600">录用建议</span>
|
|
|
- <span :class="{
|
|
|
- 'text-green-500': candidateInfo.hireRecommendation?.includes('推荐'),
|
|
|
- 'text-red-500': candidateInfo.hireRecommendation?.includes('不推荐'),
|
|
|
- 'text-yellow-500': !candidateInfo.hireRecommendation?.includes('推荐') && !candidateInfo.hireRecommendation?.includes('不推荐')
|
|
|
- }">{{ candidateInfo.hireRecommendation || '无建议' }}</span>
|
|
|
- </div>
|
|
|
- <p class="text-gray-600 text-sm">{{ candidateInfo.hireReason || '无详细说明' }}</p>
|
|
|
+ <!-- 基本信息 -->
|
|
|
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-8">
|
|
|
+ <div>
|
|
|
+ <label class="text-gray-600">身份证号</label>
|
|
|
+ <div>{{ candidateInfo.idNumber }}</div>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <label class="text-gray-600">入职之后,您缺岗的班次时间段是?</label>
|
|
|
+ <div>{{ candidateInfo.availabilityPeriod }}</div>
|
|
|
</div>
|
|
|
-
|
|
|
- <div v-if="candidateInfo.strengths && candidateInfo.strengths.length > 0" class="border-b pb-4">
|
|
|
- <h3 class="font-semibold mb-2">优点</h3>
|
|
|
- <ul class="list-disc pl-5 text-gray-600 text-sm">
|
|
|
- <li v-for="(strength, index) in candidateInfo.strengths" :key="'strength-'+index">
|
|
|
- {{ strength }}
|
|
|
- </li>
|
|
|
- </ul>
|
|
|
+ <div>
|
|
|
+ <label class="text-gray-600">请问您通过面试之后多久可以入职?</label>
|
|
|
+ <div>{{ candidateInfo.onboardingTime }}</div>
|
|
|
</div>
|
|
|
-
|
|
|
- <div v-if="candidateInfo.weaknesses && candidateInfo.weaknesses.length > 0" class="border-b pb-4">
|
|
|
- <h3 class="font-semibold mb-2">需改进的地方</h3>
|
|
|
- <ul class="list-disc pl-5 text-gray-600 text-sm">
|
|
|
- <li v-for="(weakness, index) in candidateInfo.weaknesses" :key="'weakness-'+index">
|
|
|
- {{ weakness }}
|
|
|
- </li>
|
|
|
- </ul>
|
|
|
+ <div>
|
|
|
+ <label class="text-gray-600">薪资范围</label>
|
|
|
+ <div>{{ candidateInfo.salaryRange }}</div>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <label class="text-gray-600">建议薪资</label>
|
|
|
+ <div class="font-semibold text-blue-600">{{ candidateInfo.suggestedSalary }}</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
|
|
|
- <!-- 2. DUV分析评估 -->
|
|
|
- <div class="mb-8">
|
|
|
- <h2 class="text-xl font-bold mb-6">2. 图片分析评估</h2>
|
|
|
- <div class="space-y-4">
|
|
|
- <div v-for="(item, index) in candidateInfo.duvAnalysis" :key="index" class="border-b pb-4">
|
|
|
- <div class="flex items-center justify-between mb-2">
|
|
|
- <span class="text-gray-600">{{ item.title }}</span>
|
|
|
- <span :class="{
|
|
|
- 'text-green-500': item.type === 'positive',
|
|
|
- 'text-red-500': item.type === 'negative',
|
|
|
- 'text-yellow-500': item.type === 'neutral'
|
|
|
- }">{{ item.score }}</span>
|
|
|
+ <!-- 1. 综合评估 -->
|
|
|
+ <div class="mb-8">
|
|
|
+ <h2 class="text-xl font-bold mb-6">1. 综合评估</h2>
|
|
|
+ <div class="space-y-4">
|
|
|
+ <div class="border-b pb-4">
|
|
|
+ <div class="flex items-center justify-between mb-2">
|
|
|
+ <span class="text-gray-600">录用建议</span>
|
|
|
+ <span :class="{
|
|
|
+ 'text-green-500': candidateInfo.hireRecommendation?.includes('推荐'),
|
|
|
+ 'text-red-500': candidateInfo.hireRecommendation?.includes('不推荐'),
|
|
|
+ 'text-yellow-500': !candidateInfo.hireRecommendation?.includes('推荐') && !candidateInfo.hireRecommendation?.includes('不推荐')
|
|
|
+ }">{{ candidateInfo.hireRecommendation || '无建议' }}</span>
|
|
|
+ </div>
|
|
|
+ <p class="text-gray-600 text-sm">{{ candidateInfo.hireReason || '无详细说明' }}</p>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div v-if="candidateInfo.strengths && candidateInfo.strengths.length > 0" class="border-b pb-4">
|
|
|
+ <h3 class="font-semibold mb-2">优点</h3>
|
|
|
+ <ul class="list-disc pl-5 text-gray-600 text-sm">
|
|
|
+ <li v-for="(strength, index) in candidateInfo.strengths" :key="'strength-'+index">
|
|
|
+ {{ strength }}
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div v-if="candidateInfo.weaknesses && candidateInfo.weaknesses.length > 0" class="border-b pb-4">
|
|
|
+ <h3 class="font-semibold mb-2">需改进的地方</h3>
|
|
|
+ <ul class="list-disc pl-5 text-gray-600 text-sm">
|
|
|
+ <li v-for="(weakness, index) in candidateInfo.weaknesses" :key="'weakness-'+index">
|
|
|
+ {{ weakness }}
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
</div>
|
|
|
- <p class="text-gray-600 text-sm">{{ item.content }}</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
|
|
|
- <!-- 3. 面试记录 -->
|
|
|
- <div class="mb-8">
|
|
|
- <h2 class="text-xl font-bold mb-6">3. 面试记录</h2>
|
|
|
- <div class="space-y-6">
|
|
|
- <div v-for="(record, index) in candidateInfo.interviewRecord" :key="index" class="border-b pb-4">
|
|
|
- <div class="mb-2">
|
|
|
- <h3 class="font-semibold">问题:{{ record.question }}</h3>
|
|
|
- <p class="text-gray-600 mt-2">答案:{{ record.answer }}</p>
|
|
|
- <p class="text-gray-500 mt-2 text-sm" v-if="record.question_form === 0">分析:{{ record.analysis }}</p>
|
|
|
- <img v-if="record.question_form === 3" :src="record.question_image_url" alt="图片" class="w-5/12 h-full object-cover m-auto">
|
|
|
- <div v-if="record.videoUrl" class="mt-4">
|
|
|
- <div class="video-container">
|
|
|
- <video
|
|
|
- class="w-full h-full object-cover"
|
|
|
- controls
|
|
|
- :src="record.videoUrl"
|
|
|
- preload="metadata"
|
|
|
- :poster="fallbackImageBase64Ref"
|
|
|
- @loadeddata="handleVideoLoaded"
|
|
|
- @error="handleVideoError"
|
|
|
- >
|
|
|
- 您的浏览器不支持视频播放。
|
|
|
- </video>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="mt-2 flex justify-end">
|
|
|
- <span class="text-blue-500" v-if="record.question_form === 0">得分:{{ record.score }}</span>
|
|
|
- <span class="text-gray-500" v-else>
|
|
|
- <span class="text-green-500" v-if="record.is_correct === true || record.is_correct === 'true'">正确</span>
|
|
|
- <span class="text-red-500" v-else>错误</span>
|
|
|
- </span>
|
|
|
+ <!-- 2. DUV分析评估 -->
|
|
|
+ <div class="mb-8">
|
|
|
+ <h2 class="text-xl font-bold mb-6">2. 图片分析评估</h2>
|
|
|
+ <div class="space-y-4">
|
|
|
+ <div v-for="(item, index) in candidateInfo.duvAnalysis" :key="index" class="border-b pb-4">
|
|
|
+ <div class="flex items-center justify-between mb-2">
|
|
|
+ <span class="text-gray-600">{{ item.title }}</span>
|
|
|
+ <span :class="{
|
|
|
+ 'text-green-500': item.type === 'positive',
|
|
|
+ 'text-red-500': item.type === 'negative',
|
|
|
+ 'text-yellow-500': item.type === 'neutral'
|
|
|
+ }">{{ item.score }}</span>
|
|
|
</div>
|
|
|
+ <p class="text-gray-600 text-sm">{{ item.content }}</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
|
|
|
- <!-- 4. 视频记录 -->
|
|
|
- <div class="mb-8">
|
|
|
- <h2 class="text-xl font-bold mb-6">4. 视频记录</h2>
|
|
|
- <div class="space-y-8">
|
|
|
- <div v-for="(category, index) in candidateInfo.videoRecords" :key="index">
|
|
|
- <h3 class="text-lg font-semibold mb-4">{{ category.category }}</h3>
|
|
|
- <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
|
- <div v-for="(video, vIndex) in category.videos" :key="vIndex" class="bg-gray-50 rounded-lg p-4">
|
|
|
- <div class="video-container">
|
|
|
- <video
|
|
|
- class="w-full h-full object-cover"
|
|
|
- controls
|
|
|
- :src="video.url"
|
|
|
- preload="metadata"
|
|
|
- :poster="fallbackImageBase64Ref"
|
|
|
- @loadeddata="handleVideoLoaded"
|
|
|
- @error="handleVideoError"
|
|
|
- >
|
|
|
- 您的浏览器不支持视频播放。
|
|
|
- </video>
|
|
|
+ <!-- 3. 回答记录 -->
|
|
|
+ <div class="mb-8">
|
|
|
+ <h2 class="text-xl font-bold mb-6">3. 回答记录</h2>
|
|
|
+ <div class="space-y-4">
|
|
|
+ <div v-for="(record, index) in candidateInfo.interviewRecord" :key="index" class="bg-gray-50 rounded-lg p-4">
|
|
|
+ <!-- 题目标题部分 -->
|
|
|
+ <div class="mb-4">
|
|
|
+ <div class="flex items-start space-x-2">
|
|
|
+ <div class="bg-blue-100 text-blue-800 px-2 py-1 rounded text-sm">第{{ index + 1 }}题</div>
|
|
|
+ <div class="flex-1">
|
|
|
+ <h3 class="font-semibold text-gray-800">{{ record.question }}</h3>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 视频问答题布局 -->
|
|
|
+ <div v-if="record.question_form === 0" class="mt-4 flex space-x-4">
|
|
|
+
|
|
|
+
|
|
|
+ <!-- 右侧答案和评分 -->
|
|
|
+ <div class="w-2/3">
|
|
|
+ <div class="bg-white p-4 rounded-lg">
|
|
|
+ <div class="mb-4">
|
|
|
+ <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">{{ record.answer }}</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div>
|
|
|
+ <div class="flex items-start space-x-2">
|
|
|
+ <div class="bg-yellow-100 text-yellow-800 px-2 py-1 rounded text-sm">AI评分</div>
|
|
|
+ <div class="flex-1">
|
|
|
+ <p class="text-gray-600">{{ record.analysis }}</p>
|
|
|
+ <div class="mt-2 text-blue-500">得分:{{ record.score }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- 左侧视频播放器 -->
|
|
|
+ <div class="w-1/3">
|
|
|
+ <div class="video-container">
|
|
|
+ <video
|
|
|
+ class="w-full h-full object-cover rounded-lg"
|
|
|
+ controls
|
|
|
+ :src="record.videoUrl"
|
|
|
+ preload="metadata"
|
|
|
+ :poster="fallbackImageBase64Ref"
|
|
|
+ @loadeddata="handleVideoLoaded"
|
|
|
+ @error="handleVideoError"
|
|
|
+ >
|
|
|
+ 您的浏览器不支持视频播放。
|
|
|
+ </video>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 选择题布局 -->
|
|
|
+ <div v-else-if="record.question_form === 1 || record.question_form === 2" class="mt-4">
|
|
|
+ <div class="bg-white p-4 rounded-lg">
|
|
|
+ <div class="flex items-center justify-between">
|
|
|
+ <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 :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>
|
|
|
+ </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>
|
|
|
+ </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>
|
|
|
- <p class="text-sm text-gray-600 mt-2">{{ video.description }}</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
|
|
|
- <!-- 其他信息 -->
|
|
|
- <div class="mb-8">
|
|
|
- <h2 class="text-xl font-bold mb-6">5. 其他信息</h2>
|
|
|
- <div class="space-y-6">
|
|
|
- <!-- 验证状态 -->
|
|
|
- <div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-4">
|
|
|
- <div class="flex items-center space-x-2">
|
|
|
- <span class="text-gray-600">身份证验证:</span>
|
|
|
- <span class="text-green-500">{{ candidateInfo.additionalInfo.idVerification }}</span>
|
|
|
- </div>
|
|
|
- <div class="flex items-center space-x-2">
|
|
|
- <span class="text-gray-600">手机号验证:</span>
|
|
|
- <span class="text-green-500">{{ candidateInfo.additionalInfo.phoneVerification }}</span>
|
|
|
+ <!-- 4. 视频记录 -->
|
|
|
+ <!-- <div class="mb-8">
|
|
|
+ <h2 class="text-xl font-bold mb-6">4. 视频记录</h2>
|
|
|
+ <div class="space-y-8">
|
|
|
+ <div v-for="(category, index) in candidateInfo.videoRecords" :key="index">
|
|
|
+ <h3 class="text-lg font-semibold mb-4">{{ category.category }}</h3>
|
|
|
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
|
+ <div v-for="(video, vIndex) in category.videos" :key="vIndex" class="bg-gray-50 rounded-lg p-4">
|
|
|
+ <div class="video-container">
|
|
|
+ <video
|
|
|
+ class="w-full h-full object-cover"
|
|
|
+ controls
|
|
|
+ :src="video.url"
|
|
|
+ preload="metadata"
|
|
|
+ :poster="fallbackImageBase64Ref"
|
|
|
+ @loadeddata="handleVideoLoaded"
|
|
|
+ @error="handleVideoError"
|
|
|
+ >
|
|
|
+ 您的浏览器不支持视频播放。
|
|
|
+ </video>
|
|
|
+ </div>
|
|
|
+ <p class="text-sm text-gray-600 mt-2">{{ video.description }}</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
+ </div> -->
|
|
|
|
|
|
- <!-- 手势验证 -->
|
|
|
- <div class="mb-6">
|
|
|
- <h3 class="font-semibold mb-4">手势验证</h3>
|
|
|
- <div class="grid grid-cols-2 gap-8">
|
|
|
- <!-- 左手手势 -->
|
|
|
- <div>
|
|
|
- <h4 class="text-sm font-medium mb-2">左手手势验证</h4>
|
|
|
- <div class="grid grid-cols-3 gap-2">
|
|
|
- <div v-for="(image, index) in candidateInfo.additionalInfo.leftHandGestures.images" :key="index"
|
|
|
- class="aspect-square rounded-lg overflow-hidden bg-gray-100">
|
|
|
- <img :src="image" alt="左手手势" class="w-full h-full object-cover"
|
|
|
- @error="handleImageError">
|
|
|
- </div>
|
|
|
+ <!-- 其他信息 -->
|
|
|
+ <div class="mb-8">
|
|
|
+ <h2 class="text-xl font-bold mb-6">4. 其他信息</h2>
|
|
|
+ <div class="space-y-6">
|
|
|
+ <!-- 验证状态列表 -->
|
|
|
+ <div class="space-y-2">
|
|
|
+ <div class="flex items-center space-x-2">
|
|
|
+ <span class="text-gray-600">身份认证:</span>
|
|
|
+ <span class="text-green-500">{{ candidateInfo.additionalInfo.idVerification }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="flex items-center space-x-2">
|
|
|
+ <span class="text-gray-600">手机号实名认证:</span>
|
|
|
+ <span class="text-green-500">{{ candidateInfo.additionalInfo.phoneVerification }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="flex items-center space-x-2">
|
|
|
+ <span class="text-gray-600">综合A类评估:</span>
|
|
|
+ <span class="text-green-500">{{ candidateInfo.additionalInfo.comprehensiveVerification }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="flex items-center space-x-2">
|
|
|
+ <span class="text-gray-600">综合B类评估:</span>
|
|
|
+ <span class="text-green-500">{{ candidateInfo.additionalInfo.comprehensiveVerification }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 手部综合检测 -->
|
|
|
+ <div class="space-y-4">
|
|
|
+ <div class="flex items-center space-x-2">
|
|
|
+ <span class="text-gray-600">手部综合检测:</span>
|
|
|
+ <span class="text-green-500">{{ candidateInfo.additionalInfo.handVerification }}</span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 手部检测详细信息 -->
|
|
|
+ <div class="pl-4 space-y-2">
|
|
|
+ <div class="flex items-center space-x-2">
|
|
|
+ <span class="text-gray-600">手指灵活度:</span>
|
|
|
+ <span class="text-green-500">{{ candidateInfo.additionalInfo.handBrightness }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="flex items-center space-x-2">
|
|
|
+ <span class="text-gray-600">手指完整度:</span>
|
|
|
+ <span class="text-green-500">{{ candidateInfo.additionalInfo.handIntegrity }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="flex items-center space-x-2">
|
|
|
+ <span class="text-gray-600">手部姿态纹身:</span>
|
|
|
+ <span class="text-green-500">{{ candidateInfo.additionalInfo.handPoseRecognition }}</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <!-- 右手手势 -->
|
|
|
- <div>
|
|
|
- <h4 class="text-sm font-medium mb-2">右手手势验证</h4>
|
|
|
- <div class="grid grid-cols-3 gap-2">
|
|
|
- <div v-for="(image, index) in candidateInfo.additionalInfo.rightHandGestures.images" :key="index"
|
|
|
- class="aspect-square rounded-lg overflow-hidden bg-gray-100">
|
|
|
- <img :src="image" alt="右手手势" class="w-full h-full object-cover"
|
|
|
- @error="handleImageError">
|
|
|
+
|
|
|
+ <!-- 手势验证图片展示 -->
|
|
|
+ <div class="grid grid-cols-2 gap-8 mt-4">
|
|
|
+ <!-- 左手验证结果 -->
|
|
|
+ <div>
|
|
|
+ <div class="mb-2">
|
|
|
+ <h4 class="text-sm font-medium">左手识别结果</h4>
|
|
|
+ <div class="space-y-1">
|
|
|
+ <div class="flex items-center space-x-2">
|
|
|
+ <span>手指灵活度</span>
|
|
|
+ <span class="text-green-500">✓</span>
|
|
|
+ </div>
|
|
|
+ <div class="flex items-center space-x-2">
|
|
|
+ <span>手指完整度</span>
|
|
|
+ <span class="text-green-500">✓</span>
|
|
|
+ </div>
|
|
|
+ <div class="flex items-center space-x-2">
|
|
|
+ <span>手部姿态纹身</span>
|
|
|
+ <span class="text-green-500">✓</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="grid grid-cols-3 gap-2">
|
|
|
+ <div v-for="(image, index) in candidateInfo.additionalInfo.leftHandGestures.images"
|
|
|
+ :key="index"
|
|
|
+ class="aspect-square rounded-lg overflow-hidden bg-gray-100">
|
|
|
+ <img :src="image"
|
|
|
+ alt="左手手势"
|
|
|
+ class="w-full h-full object-cover"
|
|
|
+ @error="handleImageError">
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 右手验证结果 -->
|
|
|
+ <div>
|
|
|
+ <div class="mb-2">
|
|
|
+ <h4 class="text-sm font-medium">右手识别结果</h4>
|
|
|
+ <div class="space-y-1">
|
|
|
+ <div class="flex items-center space-x-2">
|
|
|
+ <span>手指灵活度</span>
|
|
|
+ <span class="text-green-500">✓</span>
|
|
|
+ </div>
|
|
|
+ <div class="flex items-center space-x-2">
|
|
|
+ <span>手指完整度</span>
|
|
|
+ <span class="text-green-500">✓</span>
|
|
|
+ </div>
|
|
|
+ <div class="flex items-center space-x-2">
|
|
|
+ <span>手部姿态纹身</span>
|
|
|
+ <span class="text-green-500">✓</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="grid grid-cols-3 gap-2">
|
|
|
+ <div v-for="(image, index) in candidateInfo.additionalInfo.rightHandGestures.images"
|
|
|
+ :key="index"
|
|
|
+ class="aspect-square rounded-lg overflow-hidden bg-gray-100">
|
|
|
+ <img :src="image"
|
|
|
+ alt="右手手势"
|
|
|
+ class="w-full h-full object-cover"
|
|
|
+ @error="handleImageError">
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
|
|
|
- <!-- 人脸验证 -->
|
|
|
- <div>
|
|
|
- <h3 class="font-semibold mb-4">人脸验证</h3>
|
|
|
- <div class="grid grid-cols-3 md:grid-cols-6 gap-2">
|
|
|
- <div v-for="(image, index) in candidateInfo.additionalInfo.faceVerification.images" :key="index"
|
|
|
- class="aspect-square rounded-lg overflow-hidden bg-gray-100">
|
|
|
- <img :src="image" alt="人脸验证" class="w-full h-full object-cover"
|
|
|
- @error="handleImageError">
|
|
|
+ <!-- 换人检测 -->
|
|
|
+ <div>
|
|
|
+ <h3 class="font-semibold mb-4">换人检测: 通过</h3>
|
|
|
+ <div class="grid grid-cols-3 md:grid-cols-6 gap-2">
|
|
|
+ <div v-for="(image, index) in candidateInfo.additionalInfo.faceVerification.images"
|
|
|
+ :key="index"
|
|
|
+ class="aspect-square rounded-lg overflow-hidden bg-gray-100">
|
|
|
+ <img :src="image"
|
|
|
+ alt="人脸验证"
|
|
|
+ class="w-full h-full object-cover"
|
|
|
+ @error="handleImageError">
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- </a-spin>
|
|
|
+ </a-spin>
|
|
|
|
|
|
- <!-- 悬浮按钮 (Element Plus 版本) -->
|
|
|
- <div class="fixed right-8 bottom-24 flex flex-col space-y-4">
|
|
|
- <el-button
|
|
|
- type="primary"
|
|
|
- style="margin-left: 12px;"
|
|
|
- circle
|
|
|
- @click="handleShare"
|
|
|
- >
|
|
|
- <el-icon><Share /></el-icon>
|
|
|
- </el-button>
|
|
|
- <el-button
|
|
|
- type="primary"
|
|
|
- circle
|
|
|
- @click="handleDownload"
|
|
|
- >
|
|
|
- <el-icon><Download /></el-icon>
|
|
|
- </el-button>
|
|
|
- <el-button
|
|
|
- type="primary"
|
|
|
- circle
|
|
|
- @click="handlePrint"
|
|
|
- >
|
|
|
- <el-icon><Printer /></el-icon>
|
|
|
- </el-button>
|
|
|
- <el-button
|
|
|
- type="primary"
|
|
|
- circle
|
|
|
- @click="scrollToTop"
|
|
|
- >
|
|
|
- <el-icon><ArrowUp /></el-icon>
|
|
|
- </el-button>
|
|
|
+ <!-- 悬浮按钮 (Element Plus 版本) -->
|
|
|
+ <div class="fixed right-8 bottom-24 flex flex-col space-y-4">
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ style="margin-left: 12px;"
|
|
|
+ circle
|
|
|
+ @click="handleShare"
|
|
|
+ >
|
|
|
+ <el-icon><Share /></el-icon>
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ circle
|
|
|
+ @click="handleDownload"
|
|
|
+ >
|
|
|
+ <el-icon><Download /></el-icon>
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ circle
|
|
|
+ @click="handlePrint"
|
|
|
+ >
|
|
|
+ <el-icon><Printer /></el-icon>
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ circle
|
|
|
+ @click="scrollToTop"
|
|
|
+ >
|
|
|
+ <el-icon><ArrowUp /></el-icon>
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<style scoped>
|
|
|
+/* 添加自定义背景渐变样式 */
|
|
|
+.bg-gradient-custom {
|
|
|
+ background: linear-gradient(180deg, #1d1e3a 0%, #2c2d4a 100%);
|
|
|
+ min-height: 100vh;
|
|
|
+ width: 100%;
|
|
|
+ position: relative;
|
|
|
+ overflow-y: auto;
|
|
|
+ scrollbar-width: none; /* Firefox */
|
|
|
+ -ms-overflow-style: none; /* IE and Edge */
|
|
|
+}
|
|
|
+
|
|
|
+.bg-gradient-custom::-webkit-scrollbar {
|
|
|
+ display: none; /* Chrome, Safari and Opera */
|
|
|
+}
|
|
|
+
|
|
|
+/* 修改内容区域的样式 */
|
|
|
+.max-w-4xl {
|
|
|
+ position: relative;
|
|
|
+ overflow-y: visible;
|
|
|
+ min-height: 100%;
|
|
|
+ z-index: 1;
|
|
|
+ scrollbar-width: none;
|
|
|
+ -ms-overflow-style: none;
|
|
|
+}
|
|
|
+
|
|
|
+.max-w-4xl::-webkit-scrollbar {
|
|
|
+ display: none;
|
|
|
+}
|
|
|
+
|
|
|
+/* 添加星星背景效果 */
|
|
|
+.bg-gradient-custom::before {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ bottom: 0;
|
|
|
+ background-image:
|
|
|
+ radial-gradient(2px 2px at 20px 30px, #ffffff15 50%, transparent 100%),
|
|
|
+ radial-gradient(2px 2px at 40px 70px, #ffffff15 50%, transparent 100%),
|
|
|
+ radial-gradient(2px 2px at 50px 160px, #ffffff15 50%, transparent 100%),
|
|
|
+ radial-gradient(2px 2px at 90px 40px, #ffffff15 50%, transparent 100%),
|
|
|
+ radial-gradient(2px 2px at 130px 80px, #ffffff15 50%, transparent 100%),
|
|
|
+ radial-gradient(2px 2px at 160px 120px, #ffffff15 50%, transparent 100%);
|
|
|
+ background-repeat: repeat;
|
|
|
+ background-size: 200px 200px;
|
|
|
+ opacity: 0.5;
|
|
|
+ z-index: 0;
|
|
|
+}
|
|
|
+
|
|
|
.video-container {
|
|
|
position: relative;
|
|
|
width: 100%;
|
|
@@ -1170,5 +1393,21 @@ body {
|
|
|
page-break-before: avoid;
|
|
|
break-before: avoid;
|
|
|
}
|
|
|
+
|
|
|
+ .bg-gradient-custom {
|
|
|
+ background: none !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .bg-gradient-custom::before {
|
|
|
+ display: none !important;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* 确保内容区域可以正常滚动 */
|
|
|
+.max-w-4xl {
|
|
|
+ position: relative;
|
|
|
+ overflow-y: auto;
|
|
|
+ height: 100%;
|
|
|
+ padding-bottom: 100px; /* 为底部按钮留出空间 */
|
|
|
}
|
|
|
</style>
|