${COURSE_DATA.meta.subtitle} · ${COURSE_DATA.meta.version}
有趣 · 好懂 · 全面覆盖每个章节、实验和测试
${exp.objective}
${block.text}
${block.text}
`; } } // ============================================================ // 测试逻辑 // ============================================================ function selectAnswer(chId, qi, oi) { // 如果已经提交了,不允许再选 const result = document.getElementById(`result-${chId}`); if (result && result.classList.contains('show')) return; quizAnswers[chId] = quizAnswers[chId] || {}; quizAnswers[chId][qi] = oi; // 更新UI const question = document.getElementById(`q-${chId}-${qi}`); question.querySelectorAll('.quiz-option').forEach(opt => opt.classList.remove('selected')); question.querySelector(`[data-q="${qi}"][data-o="${oi}"]`).classList.add('selected'); } function submitQuiz(chId) { const ch = [...COURSE_DATA.book1.chapters, ...COURSE_DATA.book2.chapters].find(c => c.id === chId); const questions = ch.quiz.questions; let correct = 0; const answers = quizAnswers[chId] || {}; questions.forEach((q, qi) => { const userAns = answers[qi]; const questionEl = document.getElementById(`q-${chId}-${qi}`); questionEl.querySelectorAll('.quiz-option').forEach(opt => { opt.classList.remove('selected', 'correct', 'wrong'); const oi = parseInt(opt.dataset.o); if (oi === q.answer) opt.classList.add('correct'); else if (oi === userAns) opt.classList.add('wrong'); }); if (userAns === q.answer) correct++; document.getElementById(`explain-${chId}-${qi}`).classList.add('show'); }); const score = Math.round(correct / questions.length * 100); const result = document.getElementById(`result-${chId}`); const scoreEl = document.getElementById(`score-${chId}`); const msgEl = document.getElementById(`score-msg-${chId}`); scoreEl.textContent = score; result.classList.add('show'); let msg = ''; if (score === 100) msg = '🎉 满分!太棒了!'; else if (score >= 80) msg = '👍 不错!再接再厉!'; else if (score >= 60) msg = '💪 及格了,还有提升空间!'; else msg = '📚 别灰心,复习一下再试试!'; msgEl.textContent = msg; // 标记测试完成 if (score >= 60) { markQuizDone(chId); } result.scrollIntoView({ behavior: 'smooth', block: 'center' }); } function resetQuiz(chId) { quizAnswers[chId] = {}; const ch = [...COURSE_DATA.book1.chapters, ...COURSE_DATA.book2.chapters].find(c => c.id === chId); ch.quiz.questions.forEach((q, qi) => { const questionEl = document.getElementById(`q-${chId}-${qi}`); if (questionEl) { questionEl.querySelectorAll('.quiz-option').forEach(opt => { opt.classList.remove('selected', 'correct', 'wrong'); }); document.getElementById(`explain-${chId}-${qi}`).classList.remove('show'); } }); const result = document.getElementById(`result-${chId}`); if (result) result.classList.remove('show'); } // ============================================================ // 学习进度管理 // ============================================================ function getProgress() { try { return JSON.parse(localStorage.getItem('physics_progress') || '{}'); } catch(e) { return {}; } } function saveProgress(data) { try { localStorage.setItem('physics_progress', JSON.stringify(data)); } catch(e) {} } function isSectionDone(chId, secId) { const p = getProgress(); return p.sections && p.sections.includes(`${chId}_${secId}`); } function markSectionDone(chId, secId, idx) { const p = getProgress(); if (!p.sections) p.sections = []; const key = `${chId}_${secId}`; if (!p.sections.includes(key)) { p.sections.push(key); saveProgress(p); } const btn = document.getElementById(`done-btn-${secId}`); if (btn) btn.textContent = '✅ 已学完'; // 更新进度条 if (currentView === 'chapter' && currentChapter) { const progress = getChapterProgress(currentChapter.id); const fill = document.querySelector('.progress-fill'); const text = document.querySelector('.progress-text'); if (fill) fill.style.width = progress.percent + '%'; if (text) text.textContent = `学习进度:${progress.done}/${progress.total} 节(${progress.percent}%)`; } } function markQuizDone(chId) { const p = getProgress(); if (!p.quizzes) p.quizzes = []; if (!p.quizzes.includes(chId)) { p.quizzes.push(chId); saveProgress(p); } } function getChapterProgress(chId) { const ch = [...COURSE_DATA.book1.chapters, ...COURSE_DATA.book2.chapters].find(c => c.id === chId); const p = getProgress(); const total = ch.sections.length; let done = 0; ch.sections.forEach(sec => { if (p.sections && p.sections.includes(`${chId}_${sec.id}`)) done++; }); return { done, total, percent: Math.round(done/total*100) }; } // ============================================================ // 渲染:重点总结 // ============================================================ function renderHighlights() { const hl = COURSE_DATA.highlights; const html = `${hl.subtitle}