scam-detector / script.js
jerrynnms's picture
Upload 12 files
f3dfb38 verified
/// script.js
document.addEventListener('DOMContentLoaded', () => {
const inputTextArea = document.getElementById('predict_info');
const inputButton = document.getElementById('detect_button');
const clearButton = document.getElementById('clear_button');
const normalOrScam = document.getElementById('is_scam');
const confidenceScoreSpan = document.getElementById('confidence_score');
const suspiciousPhrasesDiv = document.getElementById('suspicious_phrases');
const feedbackArea = document.getElementById('feedback_area');
const feedbackCorrectBtn = document.getElementById('feedback_correct');
const feedbackWrongBtn = document.getElementById('feedback_wrong');
const feedbackStatus = document.getElementById('feedback_status');
let lastPrediction = null;
// 使用相對路徑,Vercel 會自動解析
const API_URL = '/predict';
const FEEDBACK_API = '/feedback';
inputButton.addEventListener('click', async () => {
const message = inputTextArea.value.trim();
if (!message) {
alert('請輸入您想檢測的訊息內容。');
return;
}
normalOrScam.textContent = '檢測中...';
normalOrScam.style.color = 'gray';
confidenceScoreSpan.textContent = '計算中...';
suspiciousPhrasesDiv.innerHTML = '<p>正在分析訊息,請稍候...</p>';
feedbackArea.style.display = 'none';
feedbackStatus.textContent = '';
feedbackCorrectBtn.style.display = 'inline-block';
feedbackWrongBtn.style.display = 'inline-block';
try {
const response = await fetch(API_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text: message }),
});
if (!response.ok) throw new Error(`伺服器錯誤: ${response.status} ${response.statusText}`);
const data = await response.json();
updateResults(data.status, data.confidence, data.suspicious_keywords);
feedbackArea.style.display = 'block';
lastPrediction = { text: message, model_status: data.status };
} catch (error) {
console.error('訊息檢測失敗:', error);
alert(`訊息檢測失敗,請檢查後端服務。\n錯誤詳情: ${error.message}`);
resetResults();
}
});
clearButton.addEventListener('click', () => {
inputTextArea.value = '';
resetResults();
feedbackArea.style.display = 'none';
feedbackStatus.textContent = '';
});
feedbackCorrectBtn.addEventListener('click', () => submitFeedback('正確'));
feedbackWrongBtn.addEventListener('click', () => submitFeedback('錯誤'));
async function submitFeedback(user_feedback) {
if (!lastPrediction) return;
const payload = { ...lastPrediction, user_feedback };
try {
const res = await fetch(FEEDBACK_API, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
});
const msg = await res.json();
feedbackStatus.textContent = '✅ 感謝你的回饋!';
feedbackCorrectBtn.style.display = 'none';
feedbackWrongBtn.style.display = 'none';
} catch (e) {
feedbackStatus.textContent = '❌ 回饋提交失敗';
}
}
function updateResults(isScam, confidence, suspiciousParts) {
normalOrScam.textContent = isScam;
confidenceScoreSpan.textContent = confidence;
suspiciousPhrasesDiv.innerHTML = '';
if (suspiciousParts && suspiciousParts.length > 0) {
const ul = document.createElement('ul');
suspiciousParts.forEach(phrase => {
const li = document.createElement('li');
li.textContent = phrase;
ul.appendChild(li);
});
suspiciousPhrasesDiv.appendChild(ul);
} else {
suspiciousPhrasesDiv.innerHTML = '<p>沒有偵測到特別可疑的詞句。</p>';
}
}
function resetResults() {
normalOrScam.textContent = '待檢測';
normalOrScam.style.color = 'inherit';
confidenceScoreSpan.textContent = '待檢測';
suspiciousPhrasesDiv.innerHTML = '<p>請輸入訊息並點擊「檢測!」按鈕。</p>';
}
});