{"id":981368,"student_id":2589,"content":"{\"html\":\"\u003c!DOCTYPE html\u003e\\n\u003chtml lang=\\\"zh-Hant\\\"\u003e\\n\u003chead\u003e\\n \u003cmeta charset=\\\"UTF-8\\\" /\u003e\\n \u003ctitle\u003e綜合練習用單選題系統\u003c/title\u003e\\n \u003cmeta name=\\\"viewport\\\" content=\\\"width=device-width, initial-scale=1.0\\\" /\u003e\\n \u003clink href=\\\"https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/css/bootstrap.min.css\\\" rel=\\\"stylesheet\\\" /\u003e\\n \u003cstyle\u003e\\n *, code {\\n font-family: \\\"Noto Sans Mono\\\", monospace;\\n }\\n body {\\n background-color: #fff;\\n color: #212529;\\n margin: 0;\\n padding-bottom: 100px;\\n }\\n #main {\\n width: 100vw;\\n margin: 0 auto;\\n padding: 2rem 1rem 5rem;\\n }\\n #loadingTool {\\n position: absolute;\\n top: 50%;\\n left: 50%;\\n transform: translate(-50%, -50%);\\n }\\n .code-display-wrapper {\\n background-color: #1e1e1e;\\n color: #fff;\\n padding: 1rem;\\n position: relative;\\n min-height: 150px;\\n overflow: auto;\\n }\\n .code-display-wrapper::after {\\n content: attr(data-label);\\n position: absolute;\\n bottom: 8px;\\n right: 12px;\\n font-size: 0.75rem;\\n color: rgba(255, 255, 255, 0.6);\\n }\\n .code-display-wrapper pre {\\n margin: 0;\\n white-space: pre-wrap;\\n word-wrap: break-word;\\n font-size: 0.9rem;\\n line-height: 1.4;\\n }\\n .option-label {\\n display: block;\\n cursor: pointer;\\n padding: 0;\\n background-color: transparent;\\n border: none;\\n transition: background-color 0.2s ease-in-out, opacity 0.2s ease-in-out;\\n }\\n .option-label:hover:not(.attempted-incorrect):not(.correct-answer-highlight) { /* 避免覆蓋最終狀態的 hover */\\n background-color: #f1f1f1;\\n }\\n .option-label.selected {\\n background-color: #e7f1ff;\\n }\\n /* 錯誤選項樣式 */\\n .option-label.attempted-incorrect {\\n background-color: #e9ecef; /* 淺灰色背景 */\\n opacity: 0.7; /* 降低透明度 */\\n cursor: not-allowed; /* 顯示禁止符號 */\\n pointer-events: none; /* 禁止再次點擊 */\\n }\\n .option-label.attempted-incorrect:hover {\\n background-color: #e9ecef; /* 覆蓋 hover 效果 */\\n }\\n /* (可選) 正確答案高亮樣式 */\\n .option-label.correct-answer-highlight {\\n border: 2px solid #198754; /* 綠色邊框 */\\n /* background-color: #d1e7dd; */ /* 可選的淡綠色背景 */\\n cursor: default; /* 恢復預設鼠標 */\\n pointer-events: none; /* 禁止點擊 */\\n }\\n .form-check-input {\\n display: none;\\n }\\n #answerBox {\\n margin-top: 2rem;\\n padding-top: 1rem;\\n border-top: 1px solid #dee2e6;\\n }\\n .btn-primary {\\n padding: 0.5rem 2rem;\\n font-size: 1rem;\\n }\\n \u003c/style\u003e\\n\u003c/head\u003e\\n\u003cbody\u003e\\n \u003cdiv class=\\\"position-absolute top-50 start-50 translate-middle\\\" id=\\\"loadingTool\\\"\u003e\\n \u003cdiv class=\\\"spinner-border text-secondary\\\" role=\\\"status\\\"\u003e\\n \u003cspan class=\\\"visually-hidden\\\"\u003eLoading...\u003c/span\u003e\\n \u003c/div\u003e\\n \u003c/div\u003e\\n\\n \u003cdiv class=\\\"container visually-hidden\\\" id=\\\"main\\\"\u003e\\n \u003cdiv id=\\\"question\\\" class=\\\"mb-4\\\"\u003e\\n \u003cp class=\\\"fs-5\\\" id=\\\"questionDescription\\\"\u003e\u003c/p\u003e\\n \u003cdiv class=\\\"code-display-wrapper\\\" id=\\\"questionCodeWrapper\\\" data-label=\\\"程式碼\\\"\u003e\\n \u003cpre\u003e\u003ccode id=\\\"questionCodeContent\\\"\u003e\u003c/code\u003e\u003c/pre\u003e\\n \u003c/div\u003e\\n \u003c/div\u003e\\n\\n \u003cdiv class=\\\"row\\\" id=\\\"optionsRow\\\"\u003e\\n \u003c!-- 選項會由 JS 動態產生 --\u003e\\n \u003c/div\u003e\\n\\n \u003cdiv id=\\\"answerBox\\\" class=\\\"visually-hidden\\\"\u003e\\n \u003c!-- *** 以下是被移除的部分 ***\\n \u003cdiv class=\\\"fs-6 mt-3 mb-2\\\"\u003e\\n 答案:\u003cspan id=\\\"answerText\\\" class=\\\"text-success fw-bold\\\"\u003e\u003c/span\u003e\\n \u003c/div\u003e\\n --\u003e\\n \u003cdiv class=\\\"fs-6\\\" id=\\\"answerDescriptionContainer\\\"\u003e\u003cdiv id=\\\"answerDescription\\\" style=\\\"margin-top: 0.5rem;\\\"\u003e\u003c/div\u003e\u003c/div\u003e \u003c!-- 將說明文字放在容器內 --\u003e\\n \u003c/div\u003e\\n \u003c/div\u003e\\n\\n \u003cnav class=\\\"navbar fixed-bottom navbar-light bg-light\\\"\u003e\\n \u003cdiv class=\\\"container-fluid justify-content-end\\\"\u003e\\n \u003cbutton id=\\\"sendBtn\\\" class=\\\"btn btn-primary disabled\\\" data-bs-toggle=\\\"modal\\\" data-bs-target=\\\"#resultModal\\\"\u003e送出\u003c/button\u003e\\n \u003c/div\u003e\\n \u003c/nav\u003e\\n\\n \u003cdiv class=\\\"modal fade\\\" id=\\\"resultModal\\\" tabindex=\\\"-1\\\" aria-labelledby=\\\"resultModalLabel\\\" aria-hidden=\\\"true\\\"\u003e\\n \u003cdiv class=\\\"modal-dialog\\\"\u003e\\n \u003cdiv class=\\\"modal-content\\\"\u003e\\n \u003cdiv class=\\\"modal-header\\\"\u003e\\n \u003ch5 class=\\\"modal-title\\\" id=\\\"resultModalLabel\\\"\u003e測驗結果\u003c/h5\u003e \u003c!-- 修改標題 --\u003e\\n \u003cbutton type=\\\"button\\\" class=\\\"btn-close\\\" data-bs-dismiss=\\\"modal\\\" aria-label=\\\"關閉\\\"\u003e\u003c/button\u003e\\n \u003c/div\u003e\\n \u003cdiv class=\\\"modal-body\\\" id=\\\"modalBodyContent\\\"\u003e\u003c/div\u003e\\n \u003cdiv class=\\\"modal-footer\\\"\u003e\\n \u003cbutton type=\\\"button\\\" class=\\\"btn btn-secondary\\\" data-bs-dismiss=\\\"modal\\\"\u003e關閉\u003c/button\u003e\\n \u003c/div\u003e\\n \u003c/div\u003e\\n \u003c/div\u003e\\n \u003c/div\u003e\\n\\n \u003cscript src=\\\"https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/js/bootstrap.bundle.min.js\\\"\u003e\u003c/script\u003e\\n \u003cscript\u003e\\n // --- DOM Element References ---\\n const loadingTool = document.getElementById('loadingTool');\\n const mainContent = document.getElementById('main');\\n const questionDescription = document.getElementById('questionDescription');\\n const questionCodeContent = document.getElementById('questionCodeContent');\\n const questionCodeWrapper = document.getElementById('questionCodeWrapper');\\n const optionsRow = document.getElementById('optionsRow');\\n const sendBtn = document.getElementById('sendBtn');\\n const answerBox = document.getElementById('answerBox');\\n // const answerText = document.getElementById('answerText'); // 這行可以移除或註解,因為不再使用\\n const answerDescription = document.getElementById('answerDescription'); // 取得說明文字的 div\\n const modalBodyContent = document.getElementById('modalBodyContent');\\n const resultModalElement = document.getElementById('resultModal');\\n const resultModal = new bootstrap.Modal(resultModalElement);\\n\\n // --- Quiz State Variables ---\\n let data = null;\\n let shuffledOptions = [];\\n let correctAnswerKey = '';\\n let selectedKey = null;\\n let answered = false; // 標記是否已回答\\n\\n // --- Utility Functions ---\\n function shuffle(arr) {\\n if (!Array.isArray(arr)) {\\n console.error('shuffle 函數需要一個陣列作為參數', arr);\\n return [];\\n }\\n const copy = [...arr];\\n for (let i = copy.length - 1; i \u003e 0; i--) {\\n const j = Math.floor(Math.random() * (i + 1));\\n [copy[i], copy[j]] = [copy[j], copy[i]];\\n }\\n return copy;\\n }\\n\\n // --- Quiz Initialization ---\\n function initializeQuiz() {\\n if (!data) {\\n console.error('題目資料尚未載入!');\\n return;\\n }\\n\\n // 檢查必要欄位是否存在\\n if (!data.description || data.code === undefined || !data.optionA || !data.optionB || !data.optionC || !data.optionD || !data.answer || data.answerDescription === undefined) {\\n console.error('題目資料欄位不完整:', data);\\n loadingTool.innerHTML = `\u003cdiv class=\\\"text-danger\\\"\u003e題目資料不完整,請檢查資料來源的欄位是否齊全。\u003c/div\u003e`;\\n mainContent.classList.add('visually-hidden'); // 隱藏主內容區\\n return;\\n }\\n\\n\\n const optionsArray = [data.optionA, data.optionB, data.optionC, data.optionD];\\n shuffledOptions = shuffle(optionsArray);\\n\\n questionDescription.textContent = data.description;\\n\\n // 處理程式碼區塊的顯示\\n if (data.code \u0026\u0026 data.code.trim() !== '') {\\n questionCodeContent.textContent = data.code;\\n questionCodeWrapper.style.display = 'block'; // 顯示程式碼區塊\\n } else {\\n questionCodeWrapper.style.display = 'none'; // 隱藏程式碼區塊\\n }\\n\\n\\n const optionKeys = ['A', 'B', 'C', 'D'];\\n optionsRow.innerHTML = '';\\n\\n optionKeys.forEach((key, index) =\u003e {\\n const value = shuffledOptions[index];\\n const col = document.createElement('div');\\n col.className = 'col-md-6'; // 預設為兩欄\\n col.innerHTML = `\\n \u003clabel for=\\\"option${key}\\\" class=\\\"option-label p-3 border rounded mb-3\\\" id=\\\"label${key}\\\"\u003e\\n \u003cdiv class=\\\"d-flex align-items-center mb-2\\\"\u003e\\n \u003cspan class=\\\"option-radio-letter me-2 fw-bold\\\"\u003e${key}\u003c/span\u003e\\n \u003cinput type=\\\"radio\\\" name=\\\"option\\\" id=\\\"option${key}\\\" class=\\\"form-check-input\\\" /\u003e\\n \u003c/div\u003e\\n \u003cdiv class=\\\"code-display-wrapper\\\" data-label=\\\"選項內容\\\"\u003e\\n \u003cpre\u003e\u003ccode\u003e${value}\u003c/code\u003e\u003c/pre\u003e\\n \u003c/div\u003e\\n \u003c/label\u003e\\n `;\\n optionsRow.appendChild(col);\\n\\n const input = col.querySelector('input');\\n const label = col.querySelector('label');\\n\\n input.addEventListener('change', () =\u003e {\\n // 只有在尚未回答時才處理\\n if (answered) return;\\n selectedKey = key;\\n document.querySelectorAll('.option-label').forEach(l =\u003e l.classList.remove('selected'));\\n label.classList.add('selected');\\n sendBtn.classList.remove('disabled');\\n });\\n\\n if (value === data.answer) {\\n correctAnswerKey = key;\\n }\\n });\\n\\n loadingTool.remove();\\n mainContent.classList.remove('visually-hidden');\\n }\\n\\n // --- Event Listeners ---\\n sendBtn.addEventListener('click', () =\u003e {\\n // 如果已經回答過或沒有選擇任何選項,則不執行\\n if (answered || !selectedKey) return;\\n\\n answered = true; // 標記為已回答\\n sendBtn.classList.add('disabled'); // 禁用送出按鈕\\n\\n const selectedValue = shuffledOptions[['A','B','C','D'].indexOf(selectedKey)];\\n const isCorrect = selectedValue === data.answer;\\n\\n // 1. 禁用所有選項的 input\\n document.querySelectorAll('.form-check-input').forEach(input =\u003e input.disabled = true);\\n\\n // 2. 移除所有選項的 selected 樣式\\n document.querySelectorAll('.option-label').forEach(l =\u003e l.classList.remove('selected'));\\n\\n // 3. 標示所有錯誤選項為灰色,並高亮正確答案\\n const optionKeys = ['A', 'B', 'C', 'D'];\\n optionKeys.forEach((key, index) =\u003e {\\n const value = shuffledOptions[index];\\n const label = document.getElementById(`label${key}`);\\n if (label) {\\n if (value !== data.answer) {\\n // 標示錯誤選項\\n label.classList.add('attempted-incorrect');\\n } else {\\n // (可選) 高亮正確答案\\n label.classList.add('correct-answer-highlight');\\n }\\n }\\n });\\n\\n // 4. 顯示答案區塊 (不再設定 answerText)\\n // answerText.textContent = `${correctAnswerKey}`; // \u003c--- 這行已被移除或註解\\n // *** 修改處:處理多行 answerDescription ***\\n if (data.answerDescription) {\\n answerDescription.innerHTML = data.answerDescription.replace(/\\\\n/g, '\u003cbr\u003e');\\n } else {\\n answerDescription.innerHTML = '(無詳細說明)'; // 如果沒有說明,顯示提示\\n }\\n answerBox.classList.remove('visually-hidden');\\n\\n // 5. 準備並顯示 Modal 訊息\\n let modalMessage = '';\\n if (isCorrect) {\\n modalMessage = `恭喜你答對了!正確答案是 ${correctAnswerKey}。`;\\n } else {\\n modalMessage = `您選擇了 ${selectedKey},可惜答錯了,正確答案是 ${correctAnswerKey}。`;\\n }\\n modalBodyContent.textContent = modalMessage;\\n resultModal.show();\\n\\n // 6. 滾動到答案區\\n setTimeout(() =\u003e {\\n answerBox.scrollIntoView({ behavior: 'smooth' });\\n }, 300);\\n\\n }); // --- End of sendBtn click listener ---\\n\\n // --- Accessibility Fix: Focus Management for Modal ---\\n resultModalElement.addEventListener('hide.bs.modal', function (event) {\\n // 當 modal 關閉時,可以考慮將焦點移回某個元素,例如問題描述\\n // if (questionDescription) {\\n // questionDescription.focus();\\n // }\\n });\\n // --- End of Accessibility Fix ---\\n\\n\\n // --- Data Fetching ---\\n const urlParams = new URLSearchParams(window.location.search);\\n const questionId = urlParams.get('id');\\n\\n if (questionId) {\\n // 請替換成你的 Google Apps Script Web App URL\\n const apiUrl = `https://script.google.com/macros/s/AKfycbx37t2v8JktnYYw716AfNY41m2HvnTAfs1-HrKC5EaXBUKdOdVmHYU5RGA0p00NzWUT/exec?id=${questionId}`;\\n\\n fetch(apiUrl)\\n .then(response =\u003e {\\n if (!response.ok) {\\n // 嘗試讀取錯誤回應的文字內容\\n return response.text().then(text =\u003e {\\n let errorMsg = `HTTP 錯誤!狀態碼: ${response.status}`;\\n if (text) {\\n // 嘗試解析 Google Apps Script 可能返回的 HTML 錯誤頁面或 JSON 錯誤訊息\\n try {\\n const errorJson = JSON.parse(text);\\n if (errorJson.error) {\\n errorMsg += `, 訊息: ${errorJson.error}`;\\n } else {\\n errorMsg += `, 回應內容: ${text.substring(0, 200)}...`; // 顯示部分文字\\n }\\n } catch (e) {\\n // 如果不是 JSON,可能是一個 HTML 錯誤頁面\\n const titleMatch = text.match(/\u003ctitle\u003e(.*?)\u003c\\\\/title\u003e/i);\\n if (titleMatch \u0026\u0026 titleMatch[1]) {\\n errorMsg += `, 頁面標題: ${titleMatch[1]}`;\\n } else {\\n errorMsg += `, 回應內容: ${text.substring(0, 200)}...`; // 顯示部分文字\\n }\\n }\\n }\\n throw new Error(errorMsg);\\n });\\n }\\n return response.json();\\n })\\n .then(jsonData =\u003e {\\n // 再次檢查 API 是否返回了結構化的錯誤訊息\\n if (jsonData.error) {\\n throw new Error(`API 返回錯誤: ${jsonData.error}`);\\n }\\n data = jsonData;\\n initializeQuiz(); // 在這裡呼叫初始化\\n })\\n .catch(error =\u003e {\\n console.error('請求或解析 JSON 資料時發生錯誤:', error);\\n loadingTool.innerHTML = `\u003cdiv class=\\\"text-danger\\\"\u003e載入題目失敗:\u003cbr\u003e\u003csmall\u003e${error.message}\u003c/small\u003e\u003c/div\u003e`;\\n mainContent.classList.add('visually-hidden'); // 確保主內容區是隱藏的\\n });\\n } else {\\n console.error('網址中缺少 id 參數!');\\n loadingTool.innerHTML = `\u003cdiv class=\\\"text-danger\\\"\u003e網址參數錯誤,請提供有效的題目 ID。\u003c/div\u003e`;\\n mainContent.classList.add('visually-hidden'); // 確保主內容區是隱藏的\\n }\\n \u003c/script\u003e\\n\u003c/body\u003e\\n\u003c/html\u003e\\n\",\"css\":\"\",\"js\":\"\"}","created_at":"2025-03-29T23:46:59.556+08:00","updated_at":"2025-08-26T20:36:11.434+08:00","name":"綜合練習用單選題系統","language":"web","screenshot":{"url":null},"parent_id":3,"plugin":"","description":null,"note":null,"status":"public","like_student_ids":[73945],"is_featured":false,"views":75,"hashid":"9ygszq4dm","is_content_changed":false,"review_status":"unsubmitted","submitted_at":null,"reviewed_at":null,"advise":null,"is_deleted":false}
[]
橘蘋學習平台
我的作品
檢視專案頁
匯出
複製
匯入
刪除
下載 Android APP (APK)
截圖
前往網站頁面
繁中
简中
English
日本語
1:1:1
1:1
全寬
用手機掃描下方 QRCode 進行安裝
或您也可以
下載 APK
到這台電腦
用手機掃描下方 QRCode 進行安裝
或您也可以
下載 APK
到這台電腦