fix: 修复简历面试页面14个岗位数据显示问题

- 修复resumeInterviewMock.js文件结构错误
- 解决"宠物店经营"数组未正确关闭导致的语法错误
- 修复14个岗位(民宿管家、露营地运营专员等)的数据无法显示问题
- 优化ResumeInterviewPage和ResumeInfoModal组件对content.original结构的处理
- 清理多余的compound_skills数组和重复数据

影响岗位:民宿管家、民宿客房管家、民宿运营专员、露营地运营专员、
新媒体运营专员、文创产品设计师、文创产品策划师、文创产品设计师助理、
品牌策划运营专员、品牌公关、品牌推广专员、ip运营、IP运营总监助理、品牌公关管培生

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
KQL
2025-09-12 14:26:33 +08:00
parent 883f102962
commit d2f289e59a
3 changed files with 113 additions and 25 deletions

View File

@@ -3967,8 +3967,13 @@ const resumeTemplates = {
"熟悉店铺开闭店流程及环境卫生与设备维护,保障门店符合运营与安全标准;", "熟悉店铺开闭店流程及环境卫生与设备维护,保障门店符合运营与安全标准;",
"具备宠物基础饲养与产品推荐能力,可为客户提供专业服务建议;", "具备宠物基础饲养与产品推荐能力,可为客户提供专业服务建议;",
"能协助促销执行与商品陈列优化,提高销售表现;", "能协助促销执行与商品陈列优化,提高销售表现;",
"具备团队排班与任务协助能力,支持店员培训与协作氛围建设。", "具备团队排班与任务协助能力,支持店员培训与协作氛围建设。"
], ],
compound_skills: [],
personal_summary: ""
}
}
],
"露营地运营": [ "露营地运营": [
{ {
position: "露营地运营专员", position: "露营地运营专员",
@@ -4013,21 +4018,6 @@ const resumeTemplates = {
personal_summary: "我是一名刚完成实习的大专毕业生,在露营地运营项目中担任助理角色,接触了从活动前期策划到现场执行、再到后期传播的全流程,对文旅活动的实际运作有了较为清晰的认识。在项目中,我能够主动承担任务、及时响应需求、配合团队完成细节工作。虽然经验尚浅,但我有较强的责任感与适应能力,愿意从基层做起,逐步积累经验,努力成长为一名综合型的运营人才。" personal_summary: "我是一名刚完成实习的大专毕业生,在露营地运营项目中担任助理角色,接触了从活动前期策划到现场执行、再到后期传播的全流程,对文旅活动的实际运作有了较为清晰的认识。在项目中,我能够主动承担任务、及时响应需求、配合团队完成细节工作。虽然经验尚浅,但我有较强的责任感与适应能力,愿意从基层做起,逐步积累经验,努力成长为一名综合型的运营人才。"
} }
} }
],
compound_skills: [
"产品营销基础:具备基本营销思维与客户画像构建能力,能够理解产品定位、传播路径与沟通逻辑,支持策划与执行文旅项目的推广策略。",
"服务体验优化和资源协同能力理解文旅服务的形象表达与情境化设计原则掌握文旅项目中各类资源如住宿、交通、商品的调度逻辑与协同机制具备在多元文化与B2B/B2C场景下开展基础服务支持与供应协作的能力。",
"活动执行与现场管理能力:了解活动从前期策划、主题创意、文案撰写、宣传推广,到流程设计、现场布置、预算管理、应急预案及数据复盘的完整流程,具备基础的统筹与执行配合能力。",
"新媒体平台运营能力:具备新媒体平台账号经营、内容赛道规划与短视频制作的基础能力,能够参与直播搭建、私域维护与跨平台内容策划等简单的工作内容,辅助文旅项目的数字传播落地。",
"商业视觉表达与工具应用能力了解平面设计、色彩搭配、字体表现与视觉规范的基础知识能使用Canva、Figma、Photoshop、剪映等工具进行简单的视觉表达与内容制作。",
"文化IP策划与品牌传播能力理解本地文化IP的挖掘逻辑与数字化表达方式具备参与品牌定位、跨界联动与差异化推广的初步经验。",
"文旅行业理解能力:具备现代文旅产业结构与政策环境的整体认知,了解旅游资源分类、游客行为特征与行业合规要点,初步建立了岗位适应能力。",
"智慧文旅应用能力了解OTA平台、票务分销、导览系统、智能设备及智慧酒店等新型文旅科技应用具备智慧场景运营的基础认知与设备使用能力。",
"AIGC工具使用能力了解AIGC内容生成逻辑能够使用ChatGPT、Stable Diffusion、Suno等AI工具完成图像生成、文案创作与音视频剪辑等初级创作任务。",
],
personal_summary: "我是一名主修宠物医疗技术的大专毕业生,热爱动物护理和宠物行业运营。在\"宠物生活馆经营改善项目\"中我从数据分析到实际运营改进全流程参与包括SKU组合、布局优化、SOP机制与私域体系建设。实习期间我注重服务体验、运营数据与团队协作推动业绩提升与客户满意度增长。未来希望在宠物零售与服务行业继续深耕成为兼具专业知识与运营能力的店长型人才。"
}
}
], ],
"新媒体运营": [ "新媒体运营": [
{ {
@@ -6528,7 +6518,7 @@ const resumeTemplates = {
} }
} }
] ]
}; };
// 我的简历数据 // 我的简历数据
const myResume = { const myResume = {

View File

@@ -11,6 +11,29 @@ export default ({ visible, onClose, data, initialVersion = "2" }) => {
const [editableData, setEditableData] = useState(null); const [editableData, setEditableData] = useState(null);
const [customVersions, setCustomVersions] = useState([]); const [customVersions, setCustomVersions] = useState([]);
// 调试:检查接收到的数据
useEffect(() => {
if (visible && data) {
console.log('ResumeInfoModal接收到的数据:', {
title: data.title,
hasContent: !!data.content,
contentType: typeof data.content,
contentKeys: data.content ? Object.keys(data.content) : null,
hasSelectedTemplate: !!data.selectedTemplate,
selectedTemplateKeys: data.selectedTemplate ? Object.keys(data.selectedTemplate) : null
});
if (data.content) {
console.log('content详情:', {
hasOriginal: !!data.content.original,
hasModified: !!data.content.modified,
originalType: typeof data.content.original,
originalLength: data.content.original ? data.content.original.length : 0
});
}
}
}, [visible, data]);
// 响应initialVersion变化 // 响应initialVersion变化
useEffect(() => { useEffect(() => {
setVersion(initialVersion); setVersion(initialVersion);
@@ -243,6 +266,9 @@ export default ({ visible, onClose, data, initialVersion = "2" }) => {
// 获取简历数据 - 支持新的数据结构 // 获取简历数据 - 支持新的数据结构
let resumeContent = {}; let resumeContent = {};
console.log('开始处理简历内容,当前版本:', version);
console.log('data?.content存在:', !!data?.content);
// 处理自定义版本 // 处理自定义版本
if (version.startsWith('custom_')) { if (version.startsWith('custom_')) {
const customVersion = resumeManager.getVersionById(version.replace('custom_', '')); const customVersion = resumeManager.getVersionById(version.replace('custom_', ''));
@@ -250,11 +276,18 @@ export default ({ visible, onClose, data, initialVersion = "2" }) => {
resumeContent = parseResumeMarkdown(customVersion.content) || {}; resumeContent = parseResumeMarkdown(customVersion.content) || {};
} }
} else if (data?.content) { } else if (data?.content) {
console.log('处理data.content结构:', {
hasOriginal: !!data.content.original,
hasModified: !!data.content.modified,
originalType: typeof data.content.original
});
// 新的数据结构 - 来自resume-interview页面 // 新的数据结构 - 来自resume-interview页面
if (data.content.original) { if (data.content.original) {
// 有original字段可能有或没有modified字段 // 有original字段可能有或没有modified字段
const hasModified = !!data.content.modified; const hasModified = !!data.content.modified;
const selectedContent = (!hasModified || version === "1") ? data.content.original : data.content.modified; const selectedContent = (!hasModified || version === "1") ? data.content.original : data.content.modified;
console.log('选择的内容长度:', selectedContent ? selectedContent.length : 0);
// 如果是markdown格式的字符串使用解析器 // 如果是markdown格式的字符串使用解析器
if (typeof selectedContent === 'string') { if (typeof selectedContent === 'string') {
@@ -271,14 +304,27 @@ export default ({ visible, onClose, data, initialVersion = "2" }) => {
resumeContent = parseResumeMarkdown(data.content); resumeContent = parseResumeMarkdown(data.content);
} }
} else { } else {
console.log('进入else分支检查selectedTemplate');
// 旧的数据结构 - 兼容现有的company jobs页面 // 旧的数据结构 - 兼容现有的company jobs页面
const currentTemplate = data?.selectedTemplate; const currentTemplate = data?.selectedTemplate;
const studentInfo = currentTemplate?.studentInfo; const studentInfo = currentTemplate?.studentInfo;
// 检查是否是来自resume-interview页面的数据 (有content和personal_summary字段) console.log('currentTemplate信息:', {
if (currentTemplate && currentTemplate.content && currentTemplate.position) { hasCurrentTemplate: !!currentTemplate,
// 来自resume-interview页面的新数据结构 hasContent: !!currentTemplate?.content,
const parsedContent = parseResumeMarkdown(currentTemplate.content); hasContentOriginal: !!currentTemplate?.content?.original,
hasPosition: !!currentTemplate?.position,
contentKeys: currentTemplate?.content ? Object.keys(currentTemplate.content) : null
});
// 检查是否是来自resume-interview页面的数据 (有content.original字段)
if (currentTemplate && currentTemplate.content && currentTemplate.content.original) {
console.log('处理content.original结构');
// 处理有content.original的数据结构
const hasModified = !!currentTemplate.content.modified;
const selectedContent = (!hasModified || version === "1") ? currentTemplate.content.original : currentTemplate.content.modified;
const parsedContent = parseResumeMarkdown(selectedContent);
if (parsedContent) { if (parsedContent) {
resumeContent = parsedContent; resumeContent = parsedContent;
// 添加个人总结 - 检查多个可能的位置 // 添加个人总结 - 检查多个可能的位置
@@ -354,12 +400,22 @@ export default ({ visible, onClose, data, initialVersion = "2" }) => {
// 数据校验:确保必要字段存在 // 数据校验:确保必要字段存在
const isValidData = resumeContent && Object.keys(resumeContent).length > 0 && resumeContent.personalInfo; const isValidData = resumeContent && Object.keys(resumeContent).length > 0 && resumeContent.personalInfo;
// 调试日志 (可以移除) console.log('最终resumeContent:', {
// console.log('ResumeInfoModal Debug:', { data, resumeContent }); hasResumeContent: !!resumeContent,
keys: resumeContent ? Object.keys(resumeContent) : [],
hasPersonalInfo: !!resumeContent?.personalInfo,
isValidData
});
// 如果数据无效,提供默认值防止渲染异常 // 如果数据无效,提供默认值防止渲染异常
if (!isValidData) { if (!isValidData) {
console.warn('ResumeInfoModal: Invalid resume data received', { data, resumeContent }); console.warn('ResumeInfoModal: Invalid resume data received', {
data,
resumeContent,
dataKeys: data ? Object.keys(data) : null,
hasContent: !!data?.content,
hasSelectedTemplate: !!data?.selectedTemplate
});
resumeContent = { resumeContent = {
personalInfo: { name: '数据加载中...' }, personalInfo: { name: '数据加载中...' },
education: [], education: [],

View File

@@ -108,6 +108,15 @@ const ResumeInterviewPage = () => {
const handlePositionClick = (position, industry) => { const handlePositionClick = (position, industry) => {
// Find resume templates for this industry // Find resume templates for this industry
const templates = pageData.resumeTemplates[industry.name] || []; const templates = pageData.resumeTemplates[industry.name] || [];
// 调试日志
console.log('查找简历模板:', {
industryName: industry.name,
positionTitle: position.title,
templatesCount: templates.length,
templatePositions: templates.map(t => t.position)
});
// 首先根据岗位名称精确匹配 // 首先根据岗位名称精确匹配
const selectedTemplate = const selectedTemplate =
templates.find((t) => t.position === position.title) || templates.find((t) => t.position === position.title) ||
@@ -115,13 +124,46 @@ const ResumeInterviewPage = () => {
templates[0]; templates[0];
// 构造符合ResumeInfoModal期望的数据格式 // 构造符合ResumeInfoModal期望的数据格式
// 处理不同的数据结构有些模板有content.original有些有content有些有oldContent
let templateContent = null;
if (selectedTemplate) {
console.log('找到的模板:', {
position: selectedTemplate.position,
hasContent: !!selectedTemplate.content,
hasContentOriginal: !!selectedTemplate.content?.original,
hasOldContent: !!selectedTemplate.oldContent,
contentKeys: selectedTemplate.content ? Object.keys(selectedTemplate.content) : []
});
if (selectedTemplate.content) {
// 检查是否有嵌套的original字段
if (selectedTemplate.content.original) {
templateContent = selectedTemplate.content;
} else {
templateContent = selectedTemplate.content;
}
} else if (selectedTemplate.oldContent) {
templateContent = selectedTemplate.oldContent;
}
} else {
console.log('未找到匹配的模板');
}
const resumeData = { const resumeData = {
title: position.title, title: position.title,
content: selectedTemplate?.content || selectedTemplate?.oldContent || null, content: templateContent,
studentResume: pageData.myResume, studentResume: pageData.myResume,
selectedTemplate: selectedTemplate, // 添加整个模板数据包括studentInfo selectedTemplate: selectedTemplate, // 添加整个模板数据包括studentInfo
}; };
console.log('最终传递给Modal的数据:', {
title: resumeData.title,
hasContent: !!resumeData.content,
contentType: typeof resumeData.content,
contentKeys: resumeData.content ? Object.keys(resumeData.content) : null,
hasSelectedTemplate: !!resumeData.selectedTemplate
});
setResumeModalData(resumeData); setResumeModalData(resumeData);
setResumeModalVisible(true); setResumeModalVisible(true);
}; };