LPC/static/js/main.js

403 lines
11 KiB
JavaScript
Raw Normal View History

let currentFeature = null;
let 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 === 'interview' || feature === 'feedback') {
resetInterview();
} else 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 '<p>未能生成优化建议,请重试。</p>';
let html = text
.replace(/\n\n/g, '</p><p>')
.replace(/\n/g, '<br>');
return '<p>' + html + '</p>';
}
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;
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) {
showFinalFeedback(data.conversation_history);
} 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');
}
} 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) {
alert('获取反馈失败:' + error.message);
} 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') {
feedbackContent.innerHTML = formatSuggestions(feedbackData);
} else {
let html = '<h4>面试综合评估</h4>';
feedbackData.forEach(msg => {
html += `<p><strong>${msg.role === 'assistant' ? '面试官' : '你'}</strong>${msg.content}</p>`;
});
feedbackContent.innerHTML = html;
}
}
function resetInterview() {
interviewId = null;
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();
}
});
});