File size: 5,742 Bytes
6ce4b4c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
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');
    const imageUpload = document.getElementById('image_upload');
    const ocrResult = document.getElementById('ocr_result');

    let lastPrediction = null;

    const API_URL = '/predict';
    const FEEDBACK_API = '/feedback';
    const IMAGE_API = '/analyze-image';

    // ✅ 文字檢測
    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>';
    }

    // ✅ 圖片上傳 + OCR 分析
    window.analyzeImage = async function () {
        if (!imageUpload.files.length) {
            alert('請選擇圖片');
            return;
        }

        const formData = new FormData();
        formData.append('file', imageUpload.files[0]);

        ocrResult.innerHTML = '<p>⏳ 處理中...</p>';

        try {
            const response = await fetch(IMAGE_API, {
                method: 'POST',
                body: formData
            });

            const data = await response.json();

            ocrResult.innerHTML = `
                <p><strong>📄 擷取文字:</strong> ${data.extracted_text}</p>
                <p><strong>是否為詐騙訊息:</strong> ${data.analysis_result.status}</p>
                <p><strong>模型預測可疑度:</strong> ${data.analysis_result.confidence}%</p>
                <p><strong>可疑詞句分析:</strong> ${data.analysis_result.suspicious_keywords.join("、")}</p>
            `;
        } catch (error) {
            ocrResult.innerHTML = `<p style="color:red;">❌ 分析失敗:${error.message}</p>`;
        }
    };
});