|
@@ -1,107 +1,49 @@
|
|
|
"use strict";
|
|
|
const common_vendor = require("../../common/vendor.js");
|
|
|
+const common_config = require("../../common/config.js");
|
|
|
const _sfc_main = {
|
|
|
data() {
|
|
|
return {
|
|
|
+ applicationData: null,
|
|
|
+ // 存储API返回的原始数据
|
|
|
candidateInfo: {
|
|
|
- name: "孙壁涵",
|
|
|
- idNumber: "152201199809150015",
|
|
|
- phoneNumber: "19943770171",
|
|
|
- score: 71,
|
|
|
- availabilityPeriod: "全天任意时间段",
|
|
|
- onboardingTime: "1周内",
|
|
|
+ name: "",
|
|
|
+ idNumber: "",
|
|
|
+ phoneNumber: "",
|
|
|
+ score: 0,
|
|
|
+ availabilityPeriod: "",
|
|
|
+ onboardingTime: "",
|
|
|
dimensions: {
|
|
|
- teamwork: "欠佳",
|
|
|
- learningAbility: "优秀",
|
|
|
- attention: "欠佳",
|
|
|
- workAdaptability: "优秀",
|
|
|
- serviceAwareness: "中等"
|
|
|
+ teamwork: "",
|
|
|
+ learningAbility: "",
|
|
|
+ attention: "",
|
|
|
+ workAdaptability: "",
|
|
|
+ serviceAwareness: ""
|
|
|
},
|
|
|
dimensionDetails: {
|
|
|
- teamwork: "主动交流但缺乏倾听与尊重。",
|
|
|
- learningAbility: "积极向上,具备优秀的学习意愿。",
|
|
|
- attention: "对细节处理不够严谨,需提高标准意识。",
|
|
|
- workAdaptability: "快速适应,表现出强烈的责任心。",
|
|
|
- serviceAwareness: "关注客户需求,但缺乏提升顾客体验的具体措施。"
|
|
|
+ teamwork: "",
|
|
|
+ learningAbility: "",
|
|
|
+ attention: "",
|
|
|
+ workAdaptability: "",
|
|
|
+ serviceAwareness: ""
|
|
|
},
|
|
|
- duvAnalysis: [
|
|
|
- {
|
|
|
- title: "工作经验",
|
|
|
- content: "有相关工作经验,能够胜任岗位要求",
|
|
|
- score: "优秀",
|
|
|
- type: "positive"
|
|
|
- },
|
|
|
- {
|
|
|
- title: "学历背景",
|
|
|
- content: "学历符合岗位要求",
|
|
|
- score: "良好",
|
|
|
- type: "positive"
|
|
|
- }
|
|
|
- ],
|
|
|
- interviewRecord: [
|
|
|
- {
|
|
|
- question: "请问您对餐饮服务工作有什么理解?",
|
|
|
- answer: "餐饮服务工作需要具备良好的服务意识和沟通能力,要以客户满意为目标,及时响应客户需求,保持微笑和耐心。同时要注意个人卫生和仪容仪表,遵守餐饮服务规范。",
|
|
|
- analysis: "答案表现出对岗位的基本理解,但缺乏深入思考",
|
|
|
- score: "中等",
|
|
|
- videoUrl: "https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4",
|
|
|
- thumbnail: "/images/video-placeholder.jpg"
|
|
|
- },
|
|
|
- {
|
|
|
- question: "您如何处理顾客投诉?",
|
|
|
- answer: "首先我会认真倾听顾客的意见,表示理解和歉意。然后了解具体情况,及时向主管报告,并根据公司规定提供合适的解决方案。最后会总结经验,避免类似问题再次发生。",
|
|
|
- analysis: "回答显示了基本的服务意识,但处理方法较为简单",
|
|
|
- score: "良好",
|
|
|
- videoUrl: "https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4",
|
|
|
- thumbnail: "/images/video-placeholder.jpg"
|
|
|
- }
|
|
|
- ],
|
|
|
- videoRecords: [
|
|
|
- {
|
|
|
- category: "服务态度测评",
|
|
|
- videos: [
|
|
|
- {
|
|
|
- url: "https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4",
|
|
|
- thumbnail: "/images/thumbnail1.jpg",
|
|
|
- description: "微笑服务示范"
|
|
|
- },
|
|
|
- {
|
|
|
- url: "https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4",
|
|
|
- thumbnail: "/images/thumbnail2.jpg",
|
|
|
- description: "礼貌用语展示"
|
|
|
- }
|
|
|
- ]
|
|
|
- }
|
|
|
- ],
|
|
|
+ duvAnalysis: [],
|
|
|
+ interviewRecord: [],
|
|
|
+ videoRecords: [],
|
|
|
additionalInfo: {
|
|
|
- idVerification: "通过",
|
|
|
- phoneVerification: "通过",
|
|
|
+ idVerification: "",
|
|
|
+ phoneVerification: "",
|
|
|
leftHandGestures: {
|
|
|
passed: true,
|
|
|
- images: [
|
|
|
- "/images/left-hand-1.jpg",
|
|
|
- "/images/left-hand-2.jpg",
|
|
|
- "/images/left-hand-3.jpg"
|
|
|
- ]
|
|
|
+ images: []
|
|
|
},
|
|
|
rightHandGestures: {
|
|
|
passed: true,
|
|
|
- images: [
|
|
|
- "/images/right-hand-1.jpg",
|
|
|
- "/images/right-hand-2.jpg",
|
|
|
- "/images/right-hand-3.jpg"
|
|
|
- ]
|
|
|
+ images: []
|
|
|
},
|
|
|
faceVerification: {
|
|
|
passed: true,
|
|
|
- images: [
|
|
|
- "/images/face-1.jpg",
|
|
|
- "/images/face-2.jpg",
|
|
|
- "/images/face-3.jpg",
|
|
|
- "/images/face-4.jpg",
|
|
|
- "/images/face-5.jpg",
|
|
|
- "/images/face-6.jpg"
|
|
|
- ]
|
|
|
+ images: []
|
|
|
}
|
|
|
}
|
|
|
},
|
|
@@ -116,7 +58,161 @@ const _sfc_main = {
|
|
|
}
|
|
|
};
|
|
|
},
|
|
|
+ onLoad(options) {
|
|
|
+ const id = options.id || 1;
|
|
|
+ const tenant_id = options.tenant_id || 1;
|
|
|
+ const application_id = options.application_id || 1;
|
|
|
+ this.fetchApplicationDetail(id, tenant_id, application_id);
|
|
|
+ },
|
|
|
methods: {
|
|
|
+ // 获取申请详情数据
|
|
|
+ fetchApplicationDetail(id, tenant_id, application_id) {
|
|
|
+ common_vendor.index.showLoading({
|
|
|
+ title: "加载中..."
|
|
|
+ });
|
|
|
+ common_vendor.index.request({
|
|
|
+ url: `${common_config.apiBaseUrl}/api/job/application_detail?id=${id}&tenant_id=${tenant_id}&application_id=${application_id}`,
|
|
|
+ method: "GET",
|
|
|
+ success: (res) => {
|
|
|
+ if (res.data && res.data.code === 2e3) {
|
|
|
+ this.applicationData = res.data.data;
|
|
|
+ this.processApiData();
|
|
|
+ } else {
|
|
|
+ common_vendor.index.showToast({
|
|
|
+ title: "获取数据失败",
|
|
|
+ icon: "none"
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ fail: () => {
|
|
|
+ common_vendor.index.showToast({
|
|
|
+ title: "网络请求失败",
|
|
|
+ icon: "none"
|
|
|
+ });
|
|
|
+ },
|
|
|
+ complete: () => {
|
|
|
+ common_vendor.index.hideLoading();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 处理API返回的数据,映射到现有数据结构
|
|
|
+ processApiData() {
|
|
|
+ if (!this.applicationData)
|
|
|
+ return;
|
|
|
+ const { application, applicant, position, interview_progress, posture_photos } = this.applicationData;
|
|
|
+ this.candidateInfo.name = applicant.name || "";
|
|
|
+ this.candidateInfo.idNumber = applicant.id || "";
|
|
|
+ this.candidateInfo.phoneNumber = applicant.phone || "";
|
|
|
+ if (application.comprehensive_score) {
|
|
|
+ this.candidateInfo.score = application.comprehensive_score;
|
|
|
+ } else if (application.ai_capability_scores) {
|
|
|
+ const scores = Object.values(application.ai_capability_scores);
|
|
|
+ this.candidateInfo.score = scores.length ? Math.round(scores.reduce((a, b) => a + b, 0) / scores.length) : 0;
|
|
|
+ }
|
|
|
+ if (application.ai_capability_scores) {
|
|
|
+ const scoreMapping = {
|
|
|
+ "专业性": "workAdaptability",
|
|
|
+ "沟通能力": "teamwork",
|
|
|
+ "技术匹配度": "learningAbility",
|
|
|
+ "解决问题能力": "attention"
|
|
|
+ };
|
|
|
+ Object.entries(application.ai_capability_scores).forEach(([key, value]) => {
|
|
|
+ const mappedKey = scoreMapping[key] || "serviceAwareness";
|
|
|
+ let rating = "中等";
|
|
|
+ if (value >= 80)
|
|
|
+ rating = "优秀";
|
|
|
+ else if (value < 65)
|
|
|
+ rating = "欠佳";
|
|
|
+ this.candidateInfo.dimensions[mappedKey] = rating;
|
|
|
+ });
|
|
|
+ }
|
|
|
+ if (application.ai_analysis_details && application.ai_analysis_details.requirements_feedback) {
|
|
|
+ const feedback = application.ai_analysis_details.requirements_feedback;
|
|
|
+ Object.keys(this.candidateInfo.dimensionDetails).forEach((key) => {
|
|
|
+ this.candidateInfo.dimensionDetails[key] = feedback;
|
|
|
+ });
|
|
|
+ }
|
|
|
+ if (application.ai_overall_feedback) {
|
|
|
+ this.candidateInfo.duvAnalysis = [
|
|
|
+ {
|
|
|
+ title: "综合评估",
|
|
|
+ content: application.ai_overall_feedback,
|
|
|
+ score: this.candidateInfo.score >= 70 ? "良好" : "需改进",
|
|
|
+ type: this.candidateInfo.score >= 70 ? "positive" : "negative"
|
|
|
+ }
|
|
|
+ ];
|
|
|
+ if (position) {
|
|
|
+ this.candidateInfo.duvAnalysis.push({
|
|
|
+ title: "职位匹配度",
|
|
|
+ content: `应聘职位: ${position.title}, ${position.department}, ${position.location}`,
|
|
|
+ score: "匹配",
|
|
|
+ type: "positive"
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (interview_progress && interview_progress.length) {
|
|
|
+ this.candidateInfo.interviewRecord = interview_progress.filter((item) => item.question_text).map((item) => {
|
|
|
+ const answer = this.extractAnswerFromNotes(application.note, item.question_text);
|
|
|
+ return {
|
|
|
+ question: item.question_text,
|
|
|
+ answer: answer || "未回答",
|
|
|
+ analysis: "候选人回答简短,需进一步评估",
|
|
|
+ score: "待评估",
|
|
|
+ videoUrl: item.video_answer ? item.video_answer.video_url : null,
|
|
|
+ thumbnail: "/images/video-placeholder.jpg"
|
|
|
+ };
|
|
|
+ });
|
|
|
+ }
|
|
|
+ const videoAnswers = interview_progress.filter((item) => item.video_answer && item.video_answer.video_url);
|
|
|
+ if (videoAnswers.length) {
|
|
|
+ this.candidateInfo.videoRecords = [
|
|
|
+ {
|
|
|
+ category: "面试视频",
|
|
|
+ videos: videoAnswers.map((item) => ({
|
|
|
+ url: item.video_answer.video_url,
|
|
|
+ thumbnail: "/images/thumbnail1.jpg",
|
|
|
+ description: item.question_text
|
|
|
+ }))
|
|
|
+ }
|
|
|
+ ];
|
|
|
+ }
|
|
|
+ if (posture_photos && posture_photos.length) {
|
|
|
+ const leftHandPhotos = posture_photos.filter((p) => p.description.includes("left") && !p.description.includes("face"));
|
|
|
+ const rightHandPhotos = posture_photos.filter((p) => p.description.includes("right") && !p.description.includes("face"));
|
|
|
+ const facePhotos = posture_photos.filter((p) => !p.description.includes("left") && !p.description.includes("right"));
|
|
|
+ this.candidateInfo.additionalInfo.leftHandGestures.images = leftHandPhotos.map((p) => p.photo_url);
|
|
|
+ this.candidateInfo.additionalInfo.rightHandGestures.images = rightHandPhotos.map((p) => p.photo_url);
|
|
|
+ this.candidateInfo.additionalInfo.faceVerification.images = facePhotos.map((p) => p.photo_url);
|
|
|
+ }
|
|
|
+ this.candidateInfo.additionalInfo.idVerification = "通过";
|
|
|
+ this.candidateInfo.additionalInfo.phoneVerification = "通过";
|
|
|
+ },
|
|
|
+ // 从面试记录中提取答案
|
|
|
+ extractAnswerFromNotes(notes, question) {
|
|
|
+ if (!notes)
|
|
|
+ return "";
|
|
|
+ const pattern = new RegExp(`问题 ${question}:\\s*([^\\n]+)`, "i");
|
|
|
+ const match = notes.match(pattern);
|
|
|
+ return match ? match[1].trim() : "";
|
|
|
+ },
|
|
|
+ // 格式化日期
|
|
|
+ formatDate(dateString) {
|
|
|
+ if (!dateString)
|
|
|
+ return "";
|
|
|
+ try {
|
|
|
+ const date = new Date(dateString);
|
|
|
+ return date.toLocaleString("zh-CN", {
|
|
|
+ year: "numeric",
|
|
|
+ month: "2-digit",
|
|
|
+ day: "2-digit",
|
|
|
+ hour: "2-digit",
|
|
|
+ minute: "2-digit",
|
|
|
+ second: "2-digit"
|
|
|
+ });
|
|
|
+ } catch (e) {
|
|
|
+ return dateString;
|
|
|
+ }
|
|
|
+ },
|
|
|
handleSubmit() {
|
|
|
if (this.evaluationScore === 0 || !this.evaluationComments.trim()) {
|
|
|
common_vendor.index.showToast({
|
|
@@ -151,16 +247,18 @@ const _sfc_main = {
|
|
|
}
|
|
|
};
|
|
|
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
+ var _a, _b;
|
|
|
return {
|
|
|
- a: common_vendor.t($data.candidateInfo.idNumber),
|
|
|
- b: $data.candidateInfo.additionalInfo.faceVerification.images[0],
|
|
|
- c: common_vendor.t($data.candidateInfo.name),
|
|
|
- d: common_vendor.t($data.candidateInfo.phoneNumber),
|
|
|
- e: common_vendor.t($data.candidateInfo.score),
|
|
|
- f: common_vendor.t($data.candidateInfo.idNumber),
|
|
|
- g: common_vendor.t($data.candidateInfo.availabilityPeriod),
|
|
|
- h: common_vendor.t($data.candidateInfo.onboardingTime),
|
|
|
- i: common_vendor.f($data.candidateInfo.dimensions, (value, key, i0) => {
|
|
|
+ a: common_vendor.t($data.candidateInfo.idNumber || "未知"),
|
|
|
+ b: common_vendor.t($options.formatDate((_b = (_a = $data.applicationData) == null ? void 0 : _a.application) == null ? void 0 : _b.create_datetime)),
|
|
|
+ c: $data.candidateInfo.additionalInfo.faceVerification.images[0],
|
|
|
+ d: common_vendor.t($data.candidateInfo.name),
|
|
|
+ e: common_vendor.t($data.candidateInfo.phoneNumber),
|
|
|
+ f: common_vendor.t($data.candidateInfo.score),
|
|
|
+ g: common_vendor.t($data.candidateInfo.idNumber),
|
|
|
+ h: common_vendor.t($data.candidateInfo.availabilityPeriod),
|
|
|
+ i: common_vendor.t($data.candidateInfo.onboardingTime),
|
|
|
+ j: common_vendor.f($data.candidateInfo.dimensions, (value, key, i0) => {
|
|
|
return {
|
|
|
a: common_vendor.t($data.dimensionLabels[key]),
|
|
|
b: common_vendor.t(value),
|
|
@@ -171,7 +269,7 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
g: key
|
|
|
};
|
|
|
}),
|
|
|
- j: common_vendor.f($data.candidateInfo.duvAnalysis, (item, index, i0) => {
|
|
|
+ k: common_vendor.f($data.candidateInfo.duvAnalysis, (item, index, i0) => {
|
|
|
return {
|
|
|
a: common_vendor.t(item.title),
|
|
|
b: common_vendor.t(item.score),
|
|
@@ -182,7 +280,7 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
g: index
|
|
|
};
|
|
|
}),
|
|
|
- k: common_vendor.f($data.candidateInfo.interviewRecord, (record, index, i0) => {
|
|
|
+ l: common_vendor.f($data.candidateInfo.interviewRecord, (record, index, i0) => {
|
|
|
return common_vendor.e({
|
|
|
a: common_vendor.t(record.question),
|
|
|
b: common_vendor.t(record.answer),
|
|
@@ -196,7 +294,7 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
h: index
|
|
|
});
|
|
|
}),
|
|
|
- l: common_vendor.f($data.candidateInfo.videoRecords, (category, index, i0) => {
|
|
|
+ m: common_vendor.f($data.candidateInfo.videoRecords, (category, index, i0) => {
|
|
|
return {
|
|
|
a: common_vendor.t(category.category),
|
|
|
b: common_vendor.f(category.videos, (video, vIndex, i1) => {
|
|
@@ -210,21 +308,21 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
c: index
|
|
|
};
|
|
|
}),
|
|
|
- m: common_vendor.t($data.candidateInfo.additionalInfo.idVerification),
|
|
|
- n: common_vendor.t($data.candidateInfo.additionalInfo.phoneVerification),
|
|
|
- o: common_vendor.f($data.candidateInfo.additionalInfo.leftHandGestures.images, (image, index, i0) => {
|
|
|
+ n: common_vendor.t($data.candidateInfo.additionalInfo.idVerification),
|
|
|
+ o: common_vendor.t($data.candidateInfo.additionalInfo.phoneVerification),
|
|
|
+ p: common_vendor.f($data.candidateInfo.additionalInfo.leftHandGestures.images, (image, index, i0) => {
|
|
|
return {
|
|
|
a: image,
|
|
|
b: index
|
|
|
};
|
|
|
}),
|
|
|
- p: common_vendor.f($data.candidateInfo.additionalInfo.rightHandGestures.images, (image, index, i0) => {
|
|
|
+ q: common_vendor.f($data.candidateInfo.additionalInfo.rightHandGestures.images, (image, index, i0) => {
|
|
|
return {
|
|
|
a: image,
|
|
|
b: index
|
|
|
};
|
|
|
}),
|
|
|
- q: common_vendor.f($data.candidateInfo.additionalInfo.faceVerification.images, (image, index, i0) => {
|
|
|
+ r: common_vendor.f($data.candidateInfo.additionalInfo.faceVerification.images, (image, index, i0) => {
|
|
|
return {
|
|
|
a: image,
|
|
|
b: index
|