File size: 4,584 Bytes
f3dfb38
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/// 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>';
    }
});