Spaces:
Runtime error
Runtime error
File size: 9,027 Bytes
1ec883c |
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 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
// frontend/script.js
// 當 DOM (文件物件模型) 完全載入後才執行裡面的程式碼
document.addEventListener('DOMContentLoaded', () => {
// 取得 HTML 元素:輸入、按鈕、顯示區塊。document.getElementById('對應的html元素id')
const inputTextArea = document.getElementById('predict_info'); // 輸入訊息的文字區域
const inputButton = document.getElementById('detect_button'); // 檢測按鈕
const clearButton = document.getElementById('clear_button'); // 清除按鈕
// 取得圖片上傳欄位與圖片按鈕
const imageInput = document.getElementById('imageInput');
const imageButton = document.getElementById('image_button');
// 取得顯示結果的 HTML 元素
const normalOrScam = document.getElementById('is_scam'); // 顯示正常或詐騙
const confidenceScoreSpan = document.getElementById('confidence_score'); // 顯示模型預測可信度
const suspiciousPhrasesDiv = document.getElementById('suspicious_phrases'); // 顯示可疑詞句列表
/*
後端 FastAPI API 的 URL
在開發階段,通常是 http://127.0.0.1:8000 或 http://localhost:8000
請根據你實際運行 FastAPI 的位址和 Port 進行設定
*/
const API_URL = "http://127.0.0.1:8000/predict";
const API_IMAGE_URL = "http://127.0.0.1:8000/predict-image"
// --- 檢測按鈕點擊事件監聽器 ---
// 當檢測按鈕被點擊時,執行非同步函數
//addEventListener('click', async () => {...})
// click 是一種 DOM 事件,代表使用者點擊按鈕。
// async 是「非同步函數」的關鍵字,允許你在函數中使用 await。它讓你可以像同步一樣撰寫非同步程式(例如網路請求)。
inputButton.addEventListener('click', async () => {
const message = inputTextArea.value.trim(); //.value取得<textarea>的輸入內容。
//.trim()刪掉文字開頭和結尾的空白,避免誤判空訊息。
// 檢查輸入框是否為空
if (message.length === 0) {//alert("輸出內容")是瀏覽器內建的彈出提示。視窗屬於 JavaScript 提供的「視覺提示方法」
alert('請輸入您想檢測的訊息內容。'); // alert彈出提示
return; // 終止函數執行
}
// 顯示載入中的狀態,給使用者視覺回饋
normalOrScam.textContent = '檢測中...'; //.textContent->插入純文字
normalOrScam.style.color = 'gray'; //styly.color改變顏色,style可以想為UI設計
confidenceScoreSpan.textContent = '計算中...';//.innerHTML->插入 HTML 語法
suspiciousPhrasesDiv.innerHTML = '<p>正在分析訊息,請稍候...</p>';//<></>大部分html語法長這樣
try {//try...catch處理程式錯誤。
//fetch(API_URL, {...})。API_URL第17段的變數。method:為html方法,POST送出請求。headers告訴伺服器傳送的資料格式是什麼。
//這段是用 fetch 來呼叫後端 API,送出 POST 請求:
const response = await fetch(API_URL, {
method: 'POST', // 指定 HTTP 方法為 POST
headers: { // 告訴伺服器發送的資料是 JSON 格式。選JSON原因:
//我們使用前端(JavaScript)與後端(Python FastAPI)是兩種不同的語言,而JSON是前後端通訊的「共通語言」,交換最通用、最方便、最安全的格式。
'Content-Type': 'application/json'
},
//把JavaScript物件{text:message}轉換成JSON格式字串,字串作為請求的主體 (body)
body: JSON.stringify({ text: message}),
});
// 檢查 HTTP 回應是否成功 (例如:狀態碼 200 OK)
if (!response.ok) { // 如果回應狀態碼不是 2xx (成功),則拋出錯誤
//建立一個錯誤對象並丟出來,強制跳到catch{}區塊。response.status:HTTP狀態碼(如500)。
throw new Error(`伺服器錯誤: ${response.status} ${response.statusText} `);
}
// 變數data,儲存後端成功回傳的資料。
const data = await response.json();
// 因為後端回傳的欄位名稱status、confidence、suspicious_keywords跟傳進去的參數一致,所以拿的到後端回傳的資料。
updateResults( //呼叫function,分別對應function的
data.status, //isScam,輸出正常或詐騙
data.confidence, //confidence,輸出信心值
data.suspicious_keywords,//suspiciousParts,可疑關鍵字
data.highlighted_text
);
} catch (error) {// 捕獲並處理任何在 fetch 過程中發生的錯誤 (例如網路問題、CORS 錯誤)
console.error('訊息檢測失敗:', error);// 在開發者工具的控制台顯示錯誤
alert(`訊息檢測失敗,請檢查後端服務是否運行或網路連線。\n錯誤詳情: ${error.message}`); // 彈出錯誤提示
resetResults(); // 將介面恢復到初始狀態
}
});
imageButton.addEventListener('click', async()=>{
const file = imageInput.files[0]; //取得上傳相片
if (!file){
alert("請先選擇圖片");
return;
}
// 顯示載入中提示
normalOrScam.textContent = '圖片分析中...';
normalOrScam.style.color = 'gray';
confidenceScoreSpan.textContent = '計算中...';
suspiciousPhrasesDiv.innerHTML = '<p>正在從圖片擷取文字與分析中...</p>';
try{
const formData = new FormData();
formData.append("file", file); // 附加圖片檔案給後端
const response = await fetch(API_IMAGE_URL,{
method : "POST",
body : formData
});
if (!response.ok){
throw new Error(`圖片分析失敗: ${response.status} ${response.statusText}`);
}
const data = await response.json();
updateResults(
data.status,
data.confidence,
data.suspicious_keywords,
data.highlighted_text
)
}catch(error) {
console.error("圖片上傳失敗",error);
alert("圖片分析失敗")
resetResults();
}
});
function escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
/*
function highlightSuspiciousWords(text, suspiciousParts) {
let highlighted = text;
suspiciousParts.forEach(word => {
if (word.length < 2) return; // 避免標記太短詞(如單個字或符號)
const pattern = new RegExp(escapeRegExp(word), 'g');
highlighted = highlighted.replace(pattern, `<span class="highlight">${word}</span>`);
});
return highlighted;
}
*/
// --- 清除按鈕點擊事件監聽器 ---
// 當清除按鈕被點擊時,執行函數
clearButton.addEventListener('click', () => {
inputTextArea.value = '';// 清空輸入框內容
resetResults(); // 重置顯示結果
});
// --- 清除按鈕點擊事件監聽器 ---
// 當清除按鈕被點擊時,執行函數
clearButton.addEventListener('click', () => {
inputTextArea.value = '';// 清空輸入框內容
resetResults(); // 重置顯示結果
});
/**這是 JSDoc 註解格式,給開發者與編輯器看的,不會執行。
* 更新結果顯示的輔助函數
* @param {string} isScam - 是否為詐騙訊息 (從後端獲取)(原始要得"@"param {string} isScam )
* @param {number} confidence - 模型預測可信度 (從後端獲取)
* @param {string[]} suspiciousParts - 可疑詞句陣列 (從後端獲取)
*/
//回傳輸出給index.html顯示
function updateResults(isScam, confidence, suspiciousParts, highlightedText) {
normalOrScam.textContent = isScam;
confidenceScoreSpan.textContent = confidence;
if (confidence < 15) {
suspiciousPhrasesDiv.innerHTML = '<p>此訊息為低風險,未發現可疑詞句。</p>';
} else {
suspiciousPhrasesDiv.innerHTML = highlightedText;
}
}
/**
* 重置所有顯示結果為初始狀態的輔助函數
*/
function resetResults() {
normalOrScam.textContent = '待檢測';
normalOrScam.style.color = 'inherit'; // 恢復預設顏色
confidenceScoreSpan.textContent = '待檢測';
suspiciousPhrasesDiv.innerHTML = '<p>請輸入訊息並點擊「檢測!」按鈕。</p>';
}
}); |