let currentFeature = null; let interviewId = localStorage.getItem('interviewId') || null; let conversationKey = 'default'; function showFeature(feature) { document.querySelectorAll('.tool-section').forEach(section => { section.style.display = 'none'; }); document.querySelectorAll('.feature-card').forEach(card => { card.style.transform = ''; card.style.boxShadow = ''; }); if (feature === null) { currentFeature = null; return; } const featureCard = document.querySelector(`.feature-card[onclick="showFeature('${feature}')"]`); if (featureCard) { featureCard.style.transform = 'translateY(-5px)'; featureCard.style.boxShadow = '0 10px 30px rgba(102, 126, 234, 0.3)'; } currentFeature = feature; const sectionMap = { 'resume': 'resume-section', 'interview': 'interview-section', 'feedback': 'interview-section' }; const targetSection = sectionMap[feature]; if (targetSection) { document.getElementById(targetSection).style.display = 'block'; if (feature === 'resume') { document.getElementById('resume-result').style.display = 'none'; } } } function showLoading(show) { document.getElementById('loading-overlay').style.display = show ? 'flex' : 'none'; } async function optimizeResume() { const targetPosition = document.getElementById('target-position').value.trim(); const resumeContent = document.getElementById('resume-content').value.trim(); if (!resumeContent) { alert('请输入简历内容'); return; } showLoading(true); try { const response = await fetch('/api/resume/optimize', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ resume_content: resumeContent, target_position: targetPosition }) }); const data = await response.json(); if (data.error) { alert(data.error); return; } const suggestionsDiv = document.getElementById('resume-suggestions'); suggestionsDiv.innerHTML = formatSuggestions(data.suggestions); document.getElementById('resume-result').style.display = 'block'; } catch (error) { alert('优化失败:' + error.message); } finally { showLoading(false); } } function formatSuggestions(text) { if (!text) return '
未能生成优化建议,请重试。
'; let html = text .replace(/\n\n/g, '')
.replace(/\n/g, '
');
return '
' + html + '
'; } async function startInterview() { const jobPosition = document.getElementById('job-position').value.trim(); if (!jobPosition) { alert('请输入目标岗位'); return; } const difficulty = document.querySelector('input[name="difficulty"]:checked').value; showLoading(true); try { const response = await fetch('/api/interview/start', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ job_position: jobPosition, difficulty: difficulty }) }); const data = await response.json(); if (data.error) { alert(data.error); return; } interviewId = data.interview_id; localStorage.setItem('interviewId', interviewId); document.getElementById('interview-setup').style.display = 'none'; document.getElementById('interview-active').style.display = 'flex'; document.getElementById('current-position').textContent = '目标岗位:' + data.job_position; updatePhaseBadge(data.phase); const messagesContainer = document.getElementById('interview-messages'); messagesContainer.innerHTML = ''; addInterviewMessage(data.question, 'interviewer'); } catch (error) { alert('开始面试失败:' + error.message); } finally { showLoading(false); } } function updatePhaseBadge(phase) { const phaseMap = { 'intro': '自我介绍', 'professional': '专业能力', 'scenario': '情景假设', 'career': '职业规划', 'closing': '面试结束' }; document.getElementById('current-phase').textContent = phaseMap[phase] || phase; } function addInterviewMessage(content, type) { if (!content) return; const messagesContainer = document.getElementById('interview-messages'); const messageDiv = document.createElement('div'); messageDiv.className = 'message ' + type; messageDiv.textContent = content; messagesContainer.appendChild(messageDiv); messagesContainer.scrollTop = messagesContainer.scrollHeight; } async function submitAnswer() { const answerInput = document.getElementById('answer-input'); const answer = answerInput.value.trim(); if (!answer) { alert('请输入你的回答'); return; } addInterviewMessage(answer, 'candidate'); answerInput.value = ''; showLoading(true); try { const response = await fetch('/api/interview/answer', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ interview_id: interviewId, answer: answer, request_feedback: false }) }); const data = await response.json(); if (data.error) { alert(data.error); return; } if (data.ended) { // 面试结束,调用endInterview获取生成的面试反馈 endInterview(); } else if (data.question) { addInterviewMessage(data.question, 'interviewer'); updatePhaseBadge(data.phase); } } catch (error) { alert('提交回答失败:' + error.message); } finally { showLoading(false); } } async function requestFeedback() { const answerInput = document.getElementById('answer-input'); const answer = answerInput.value.trim(); if (!answer) { alert('请先输入你的回答'); return; } addInterviewMessage(answer, 'candidate'); answerInput.value = ''; showLoading(true); try { const response = await fetch('/api/interview/answer', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ interview_id: interviewId, answer: answer, request_feedback: true }) }); const data = await response.json(); if (data.error) { alert(data.error); return; } if (data.feedback) { addInterviewMessage(data.feedback, 'feedback'); // 添加返回面试的按钮 const messagesContainer = document.getElementById('interview-messages'); const returnButton = document.createElement('button'); returnButton.className = 'return-interview-btn'; returnButton.textContent = '返回面试'; returnButton.onclick = function() { // 移除按钮 this.remove(); // 可以在这里添加额外的逻辑,比如重新启用输入框等 }; const buttonContainer = document.createElement('div'); buttonContainer.className = 'return-button-container'; buttonContainer.appendChild(returnButton); messagesContainer.appendChild(buttonContainer); messagesContainer.scrollTop = messagesContainer.scrollHeight; } } catch (error) { alert('获取反馈失败:' + error.message); } finally { showLoading(false); } } async function endInterview() { const messages = []; document.querySelectorAll('.interview-messages .message').forEach(msg => { messages.push({ role: msg.classList.contains('interviewer') ? 'assistant' : 'user', content: msg.textContent }); }); showLoading(true); try { const response = await fetch('/api/interview/feedback', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ interview_id: interviewId, conversation_history: messages }) }); const data = await response.json(); if (data.error) { alert(data.error); return; } showFinalFeedback(data.feedback); } catch (error) { console.error('获取反馈失败:', error); alert('获取反馈失败,请稍后重试'); } finally { showLoading(false); } } function showFinalFeedback(feedbackData) { document.getElementById('interview-active').style.display = 'none'; document.getElementById('interview-feedback').style.display = 'block'; const feedbackContent = document.getElementById('feedback-content'); if (typeof feedbackData === 'string') { // 将Markdown风格的列表和标题转换为HTML let formattedFeedback = feedbackData // 转换标题 .replace(/^###\s+(.*)$/gm, '')
.replace(/\n/g, '
');
feedbackContent.innerHTML = `
${msg.role === 'assistant' ? '面试官' : '你'}:${msg.content}
`; }); feedbackContent.innerHTML = html; } } function resetInterview() { interviewId = null; localStorage.removeItem('interviewId'); document.getElementById('interview-setup').style.display = 'block'; document.getElementById('interview-active').style.display = 'none'; document.getElementById('interview-feedback').style.display = 'none'; document.getElementById('interview-messages').innerHTML = ''; document.getElementById('answer-input').value = ''; document.getElementById('job-position').value = ''; } async function sendChatMessage() { const chatInput = document.getElementById('chat-input'); const message = chatInput.value.trim(); if (!message) { return; } const messagesContainer = document.getElementById('chat-messages'); const userMessageDiv = document.createElement('div'); userMessageDiv.className = 'chat-message user'; userMessageDiv.textContent = message; messagesContainer.appendChild(userMessageDiv); chatInput.value = ''; messagesContainer.scrollTop = messagesContainer.scrollHeight; showLoading(true); try { const response = await fetch('/api/chat', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ message: message, system_type: 'general_assistant', conversation_key: conversationKey }) }); const data = await response.json(); if (data.error) { alert(data.error); return; } const assistantMessageDiv = document.createElement('div'); assistantMessageDiv.className = 'chat-message assistant'; assistantMessageDiv.textContent = data.response; messagesContainer.appendChild(assistantMessageDiv); messagesContainer.scrollTop = messagesContainer.scrollHeight; } catch (error) { alert('发送消息失败:' + error.message); } finally { showLoading(false); } } document.addEventListener('DOMContentLoaded', function() { document.getElementById('chat-input').addEventListener('keypress', function(e) { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); sendChatMessage(); } }); document.getElementById('answer-input').addEventListener('keypress', function(e) { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); submitAnswer(); } }); });