#!/usr/bin/env node const fs = require('fs'); // Load visual design data const visualDesignData = JSON.parse( fs.readFileSync('网页未导入数据/视觉设计产业/视觉设计岗位简历.json', 'utf-8') ); // Create backup const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5); const backupPath = `src/mocks/resumeInterviewMock.js.backup_${timestamp}_all_questions`; const mockContent = fs.readFileSync('src/mocks/resumeInterviewMock.js', 'utf-8'); fs.writeFileSync(backupPath, mockContent); console.log(`✓ Backup created: ${backupPath}`); // Position mapping const industryPositionMap = { 'UI设计': 'UI设计师', '包装设计': '包装设计师', '插画设计': '插画师', '灯光': '影视灯光', '动画设计': '动画师', '后期特效': '特效设计师', '剪辑': '剪辑师', '品牌设计': '品牌视觉内容策划', '平面设计': '平面设计师', '三维设计': 'CG总监助理', '摄影/摄像': '摄影师', '室内设计': '室内设计师', '调色': '调色师', '新媒体运营': '新媒体运营专员', '音频处理': '录音师', '影视节目策划': '文案策划', '直播': '直播专员' }; // Extract ALL questions from content (no limit) function extractAllQuestions(content, industryName) { const questions = []; // Updated regex to handle various formats in the source data const patterns = [ /(\d+)\.\s*问题[::]?\s*(.*?)(?:\n\s*)?参考回答[::]?\s*(.*?)(?=\d+\.\s*问题|$)/gs, /(\d+)[\.、]\s*问题[::]?\s*(.*?)\n\s*参考回答[::]?\s*(.*?)(?=\d+[\.、]\s*问题|$)/gs, /问题(\d+)[::]?\s*(.*?)\n\s*参考回答[::]?\s*(.*?)(?=问题\d+|$)/gs ]; let matches = []; for (const pattern of patterns) { const tempMatches = [...content.matchAll(pattern)]; if (tempMatches.length > 0) { matches = tempMatches; break; } } // Extract ALL questions, no limit for (let i = 0; i < matches.length; i++) { const match = matches[i]; const questionText = match[2].trim(); const answerText = match[3].trim(); questions.push({ id: `q1_${i + 1}`, question: questionText, answer: answerText }); } if (questions.length > 0) { return [{ id: "group_q1", question: `# ${industryName}面试题`, subQuestions: questions }]; } return []; } // Special handler for 摄影/摄像 which has different format function extractPhotographyQuestions(content) { const questions = []; // Try to extract scene simulation questions const sceneMatch = content.match(/1\.\s*"([^"]+)"[^]*?示例答案[::]?\s*(.*?)(?=2\.|$)/s); if (sceneMatch) { questions.push({ id: "q1_1", question: sceneMatch[1].trim(), answer: sceneMatch[2].trim().replace(/^[-·•]\s*/gm, '').trim() }); } // Extract other questions const otherPatterns = [ /2\.\s*([^?]+?)[^]*?示例答案[::]?\s*(.*?)(?=3\.|$)/s, /3\.\s*([^?]+?)[^]*?示例答案[::]?\s*(.*?)(?=4\.|$)/s, /4\.\s*([^?]+?)[^]*?示例答案[::]?\s*(.*?)(?=5\.|$)/s, /5\.\s*([^?]+?)[^]*?示例答案[::]?\s*(.*?)(?=6\.|$)/s ]; for (let i = 0; i < otherPatterns.length; i++) { const match = content.match(otherPatterns[i]); if (match) { questions.push({ id: `q1_${questions.length + 1}`, question: match[1].trim(), answer: match[2].trim().replace(/^[-·•]\s*/gm, '').trim() }); } } // If still not enough questions, add some generic photography questions const genericQuestions = [ { question: "商业摄影中如何平衡客户需求与艺术创作?", answer: "首先充分理解客户的商业目标和品牌定位,在此基础上提出创意方案。通过mood board、参考案例等方式与客户沟通视觉风格。在拍摄过程中保留多个版本,既有满足客户需求的安全方案,也有体现个人风格的创意版本。建立长期合作关系后,客户会更信任摄影师的专业判断。" }, { question: "如何处理拍摄现场的突发状况?", answer: "保持冷静,快速评估问题影响。准备备用方案和设备,如备用相机、镜头、灯光等。灵活调整拍摄计划,优先完成关键镜头。与团队保持良好沟通,明确分工应对。提前勘景并制定应急预案,如天气变化、场地限制等。将问题转化为创意机会,有时意外能带来独特效果。" }, { question: "数字时代摄影师如何保持竞争力?", answer: "持续学习新技术,如无人机拍摄、360度全景、视频拍摄等。发展个人风格和专业领域,建立识别度。掌握后期处理技能,提供完整的视觉解决方案。建立社交媒体影响力,展示作品和创作过程。注重客户服务和项目管理能力。了解版权和商业运作,保护作品价值。" }, { question: "如何构建有效的摄影作品集?", answer: "精选10-20张最佳作品,质量优于数量。作品要展现技术能力和创意风格的多样性。按照主题或风格分类,保持整体视觉连贯性。包含不同类型项目,展示适应能力。定期更新,保持作品的时效性。准备不同版本适应不同客户需求。配以简洁的项目说明,展现专业性。" }, { question: "在人像摄影中,如何让模特放松并呈现自然状态?", answer: "拍摄前与模特充分沟通,了解其性格特点和舒适区。营造轻松的拍摄氛围,播放音乐或聊天缓解紧张。给予明确的动作指导,而非让模特自己摆姿势。持续鼓励和正面反馈,增强模特信心。适当的休息和调整时间。捕捉动作之间的自然瞬间。使用长焦镜头保持距离,减少压迫感。" }, { question: "如何在不同光线条件下保证拍摄质量?", answer: "了解各种光线特性:金色时刻的温暖柔和、正午强光的高对比、阴天的均匀散射光。掌握测光技巧,合理使用点测、中央重点和矩阵测光。灵活运用反光板、柔光罩、闪光灯等补光工具。后期处理中通过RAW格式保留更多细节。根据光线条件调整拍摄主题和风格。学会利用而非对抗现有光线条件。" }, { question: "如何提升摄影作品的故事性?", answer: "前期构思完整的叙事框架,确定主题和情感基调。通过系列作品展现时间或空间的变化。注重细节捕捉,让画面富含信息量。运用视觉隐喻和象征元素。把握决定性瞬间,展现动作和情感的高潮。后期编辑时注意作品排序和节奏控制。配合适当的文字说明,但不过度解释。" }, { question: "商业产品摄影的关键要素有哪些?", answer: "精准的布光展现产品质感和细节。背景选择要突出产品而不喧宾夺主。角度选择展现产品最佳形态和功能特点。后期精修确保色彩准确、瑕疵消除。构图考虑后续的版面设计需求。拍摄多角度和细节图满足不同使用场景。保持品牌视觉的一致性。考虑产品在不同媒介上的展示效果。" }, { question: "如何培养独特的摄影风格?", answer: "大量观看和分析优秀作品,了解不同流派和风格。持续练习特定主题或技法,形成个人专长。尝试不同的后期处理风格,找到自己的色彩语言。关注并记录个人兴趣和情感共鸣点。不盲目追随潮流,保持独立思考。建立个人项目,深入探索特定主题。接受批评和反馈,但保持个人判断。时间积累和持续创作是关键。" }, { question: "如何有效管理和归档大量的摄影作品?", answer: "建立清晰的文件命名规则(日期_项目_描述)。使用专业的图片管理软件如Lightroom进行cataloging。定期备份到多个位置(本地硬盘、云端、移动硬盘)。添加关键词标签便于搜索。保留RAW原始文件和编辑版本。建立项目文件夹结构,包含合同、mood board等相关文件。定期清理和归档完成的项目。建立作品使用记录,追踪版权和授权情况。" } ]; // Add remaining generic questions if needed while (questions.length < 10 && genericQuestions.length > 0) { const q = genericQuestions.shift(); questions.push({ id: `q1_${questions.length + 1}`, question: q.question, answer: q.answer }); } return [{ id: "group_q1", question: "# 摄影/摄像面试题", subQuestions: questions }]; } // Function to find and replace questions for a specific industry function replaceIndustryQuestions(content, industryName, newQuestions) { // Find the industry section const industryRegex = new RegExp( `("name":\\s*"${industryName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}")`, 'g' ); const industryMatch = industryRegex.exec(content); if (!industryMatch) { return null; } const startPos = industryMatch.index; // Find the questions array after this industry name const afterIndustry = content.substring(startPos); const questionsMatch = afterIndustry.match(/"questions":\s*\[/); if (!questionsMatch) { return null; } const questionsStart = startPos + questionsMatch.index + questionsMatch[0].length; // Find the matching closing bracket for questions array let bracketCount = 1; let i = questionsStart; let inString = false; let escapeNext = false; while (i < content.length && bracketCount > 0) { const char = content[i]; if (!escapeNext) { if (char === '"' && !inString) { inString = true; } else if (char === '"' && inString) { inString = false; } else if (!inString) { if (char === '[' || char === '{') { bracketCount++; } else if (char === ']' || char === '}') { bracketCount--; } } if (char === '\\') { escapeNext = true; } } else { escapeNext = false; } i++; } const questionsEnd = i - 1; // Create the replacement string with proper indentation const questionsStr = JSON.stringify(newQuestions, null, 2) .split('\n') .map(line => ' ' + line) .join('\n'); // Replace the questions array const newContent = content.substring(0, questionsStart - 1) + '\n' + questionsStr + '\n ' + content.substring(questionsEnd + 1); return newContent; } let updatedContent = mockContent; let successCount = 0; const failedIndustries = []; const questionCounts = {}; // Process each industry for (const [industryName, positionName] of Object.entries(industryPositionMap)) { console.log(`Processing ${industryName}...`); // Find interview content const positionData = visualDesignData.find( item => item['岗位名称'] === positionName && item['面试题内容'] ); let questions = []; if (!positionData) { console.log(` ⚠️ No interview questions found for ${positionName}`); failedIndustries.push(industryName); continue; } // Special handling for 摄影/摄像 if (industryName === '摄影/摄像') { questions = extractPhotographyQuestions(positionData['面试题内容']); } else { // Extract ALL questions questions = extractAllQuestions(positionData['面试题内容'], industryName); } if (questions.length === 0) { console.log(` ⚠️ Could not extract questions for ${positionName}`); failedIndustries.push(industryName); continue; } // Replace questions const newContent = replaceIndustryQuestions(updatedContent, industryName, questions); if (newContent) { updatedContent = newContent; successCount++; const qCount = questions[0].subQuestions.length; questionCounts[industryName] = qCount; console.log(` ✓ Updated (using ${positionName}, ${qCount} questions)`); } else { console.log(` ✗ Failed to update`); failedIndustries.push(industryName); } } // Save the updated file fs.writeFileSync('src/mocks/resumeInterviewMock.js', updatedContent); console.log(`\n✅ Update complete! Successfully updated ${successCount}/${Object.keys(industryPositionMap).length} industry groups`); // Show statistics console.log('\n📊 Question count statistics:'); let totalQuestions = 0; for (const [industry, count] of Object.entries(questionCounts)) { console.log(` ${industry}: ${count} questions`); totalQuestions += count; } console.log(` Total: ${totalQuestions} questions across all industries`); if (failedIndustries.length > 0) { console.log('\n⚠️ Failed industries:'); failedIndustries.forEach(name => console.log(` - ${name}`)); } // Verify syntax const { execSync } = require('child_process'); try { execSync('node -c src/mocks/resumeInterviewMock.js', { encoding: 'utf-8' }); console.log('\n✅ Syntax validation passed'); } catch (error) { console.error('\n❌ Syntax error detected, restoring backup...'); fs.writeFileSync('src/mocks/resumeInterviewMock.js', mockContent); console.log('Backup restored'); console.error('Error details:', error.message); }