(function() { 'use strict'; var state = { currentId: 1, correctCount: 0, totalCount: 0, selectedOption: null, isLoading: false, answered: false, currentKey: window.INITIAL_KEY || null }; var elements = { questionCard: document.getElementById('questionCard'), navigation: document.getElementById('navigation'), details: document.getElementById('details'), loading: document.getElementById('loading'), correctCount: document.getElementById('correctCount'), totalCount: document.getElementById('totalCount'), feedback: document.getElementById('feedback'), feedbackIcon: document.getElementById('feedbackIcon'), feedbackText: document.getElementById('feedbackText'), overlay: document.getElementById('overlay'), detailAuthor: document.getElementById('detailAuthor'), detailDynasty: document.getElementById('detailDynasty'), detailType: document.getElementById('detailType'), detailGrade: document.getElementById('detailGrade') }; function getUrlParam(name) { var urlParams = new URLSearchParams(window.location.search); return urlParams.get(name); } function setUrlParam(name, value) { var url = new URL(window.location.href); url.searchParams.set(name, value); window.history.replaceState({}, '', url); } function fetchData(url, callback, errorCallback) { if (!state.currentKey) { errorCallback('未初始化 Key'); return; } var separator = url.indexOf('?') !== -1 ? '&' : '?'; var fullUrl = url + separator + 'key=' + encodeURIComponent(state.currentKey); var xhr = new XMLHttpRequest(); xhr.open('GET', fullUrl, true); xhr.setRequestHeader('Accept', 'application/json'); xhr.onreadystatechange = function() { if (xhr.readyState === 4) { if (xhr.status === 200) { try { var response = JSON.parse(xhr.responseText); if (response.new_key) { state.currentKey = response.new_key; } callback(response); } catch (e) { errorCallback('解析响应失败'); } } else if (xhr.status === 429) { errorCallback('请求过于频繁,请稍后再试'); } else { errorCallback('请求失败,状态码: ' + xhr.status); } } }; xhr.onerror = function() { errorCallback('网络错误'); }; xhr.send(); } function fetchQuestion(id) { if (state.isLoading) return; state.isLoading = true; state.answered = false; state.selectedOption = null; showLoading(); fetchData('api.php?id=' + id, function(response) { state.isLoading = false; if (response.success) { renderQuestion(response.data); updateNavigation(id); updateDetails(response.data); } else { showError(response.message || '获取题目失败'); } }, function(error) { state.isLoading = false; showError(error); }); } function submitAnswer(id, answer) { if (state.isLoading || state.answered) return; state.isLoading = true; fetchData('api.php?id=' + id + '&msg=' + answer, function(response) { state.isLoading = false; if (response.success) { state.totalCount++; updateStats(); if (response.type === 'correct') { state.correctCount++; updateStats(); showFeedback('correct', '🎉 ' + response.message); markOption(answer, 'correct'); setTimeout(function() { hideFeedback(); if (response.next_question) { state.currentId++; setUrlParam('id', state.currentId); renderQuestion(response.next_question); updateNavigation(state.currentId); updateDetails(response.next_question); } else { state.currentId++; setUrlParam('id', state.currentId); fetchQuestion(state.currentId); } }, 1500); } else if (response.type === 'wrong') { showFeedback('wrong', '😢 ' + response.message); markOption(answer, 'wrong'); setTimeout(function() { hideFeedback(); clearOptionMark(answer); }, 2000); } else if (response.type === 'hint') { showHintMessage(response.message); } } else { showFeedback('wrong', response.message || '提交失败'); setTimeout(hideFeedback, 2000); } }, function(error) { state.isLoading = false; showFeedback('wrong', error); setTimeout(hideFeedback, 2000); }); } function getHint(id) { if (state.isLoading) return; state.isLoading = true; fetchData('api.php?id=' + id + '&msg=提示', function(response) { state.isLoading = false; if (response.success && response.type === 'hint') { showHintMessage(response.message); } else { showFeedback('wrong', response.message || '获取提示失败'); setTimeout(hideFeedback, 2000); } }, function(error) { state.isLoading = false; showFeedback('wrong', error); setTimeout(hideFeedback, 2000); }); } function showLoading() { elements.questionCard.innerHTML = '
加载中
'; elements.details.style.display = 'none'; } function showError(message) { elements.questionCard.innerHTML = '
' + '

❌ ' + message + '

' + '' + '
'; elements.details.style.display = 'none'; } function renderQuestion(data) { var html = '第 ' + data.id + ' 题'; html += '
' + escapeHtml(data.question) + '
'; html += '
'; data.options.forEach(function(option) { html += ''; }); html += '
'; html += ''; html += '
'; elements.questionCard.innerHTML = html; } function updateNavigation(currentId) { var html = ''; var start = Math.max(1, currentId - 4); var end = currentId + 5; for (var i = start; i <= end; i++) { var activeClass = i === currentId ? ' active' : ''; html += ''; } elements.navigation.innerHTML = html; } function updateDetails(data) { elements.detailAuthor.textContent = data.author || '-'; elements.detailDynasty.textContent = data.dynasty || '-'; elements.detailType.textContent = data.type || '-'; elements.detailGrade.textContent = data.grade || '-'; elements.details.style.display = 'grid'; } function updateStats() { elements.correctCount.textContent = state.correctCount; elements.totalCount.textContent = state.totalCount; } function selectOption(num) { if (state.answered || state.isLoading) return; var buttons = document.querySelectorAll('.option-btn'); buttons.forEach(function(btn) { btn.classList.remove('selected'); }); var selectedBtn = document.querySelector('.option-btn[data-num="' + num + '"]'); if (selectedBtn) { selectedBtn.classList.add('selected'); } state.selectedOption = num; submitAnswer(state.currentId, num); } function markOption(num, type) { var btn = document.querySelector('.option-btn[data-num="' + num + '"]'); if (btn) { btn.classList.add(type); } } function clearOptionMark(num) { var btn = document.querySelector('.option-btn[data-num="' + num + '"]'); if (btn) { btn.classList.remove('wrong', 'selected'); } } function showFeedback(type, message) { elements.feedback.className = 'feedback show ' + type; elements.feedbackIcon.textContent = type === 'correct' ? '🎉' : '😢'; elements.feedbackText.textContent = message.replace(/^[🎉😢]\s*/, ''); elements.overlay.classList.add('show'); } function hideFeedback() { elements.feedback.classList.remove('show'); elements.overlay.classList.remove('show'); } function showHintMessage(message) { var hintEl = document.getElementById('hintMessage'); if (hintEl) { hintEl.textContent = '💡 ' + message; hintEl.classList.add('show'); } } function goToQuestion(id) { if (state.isLoading) return; state.currentId = id; state.answered = false; state.selectedOption = null; setUrlParam('id', id); fetchQuestion(id); } function goToRandomQuestion() { if (state.isLoading) return; var randomId = Math.floor(Math.random() * 500) + 1; goToQuestion(randomId); } function retry() { fetchQuestion(state.currentId); } function escapeHtml(text) { var div = document.createElement('div'); div.textContent = text; return div.innerHTML; } function init() { var idParam = getUrlParam('id'); if (idParam) { state.currentId = parseInt(idParam, 10) || 1; } else { state.currentId = Math.floor(Math.random() * 500) + 1; } fetchQuestion(state.currentId); } window.PoetryQuiz = { selectOption: selectOption, getHint: function() { getHint(state.currentId); }, goToQuestion: goToQuestion, goToRandomQuestion: goToRandomQuestion, retry: retry }; if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();