<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>第04讲: 巧算与速算(凑十法、分组法)</title>
<style>
/* ================= 基础重置与全局样式 ================= */
:root {
--primary: #667eea;
--primary-dark: #5a67d8;
--accent: #ff9f43;
--success: #2ecc71;
--error: #ff6b6b;
--bg-color: #f4f7f6;
--card-bg: #ffffff;
--text-main: #2d3436;
--text-sub: #636e72;
}
* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; }
::-webkit-scrollbar { display: none; }
html, body { margin: 0; padding: 0; background: var(--bg-color); overflow: hidden; height: 100vh; }
/* 动态背景图案 */
body {
background-image: radial-gradient(#e0e0e0 1px, transparent 1px);
background-size: 20px 20px;
}
#app { height: 100vh; max-width: 480px; margin: 0 auto; background: rgba(255,255,255,0.95); display: flex; flex-direction: column; position: relative; box-shadow: 0 0 30px rgba(0,0,0,0.05); }
.content-area { flex: 1; overflow-y: auto; padding-bottom: 90px; scroll-behavior: smooth; padding-top: 10px; }
/* 通用动画类 */
.fade-in { animation: fadeIn 0.4s ease-out; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
.shake { animation: shake 0.5s cubic-bezier(.36,.07,.19,.97) both; }
@keyframes shake { 10%, 90% { transform: translate3d(-1px, 0, 0); } 20%, 80% { transform: translate3d(2px, 0, 0); } 30%, 50%, 70% { transform: translate3d(-4px, 0, 0); } 40%, 60% { transform: translate3d(4px, 0, 0); } }
/* ================= 底部导航 (App Bar) ================= */
.bottom-nav {
position: fixed; bottom: 0; left: 50%; transform: translateX(-50%);
width: 100%; max-width: 480px; height: 75px;
background: rgba(255, 255, 255, 0.98);
border-top: 1px solid rgba(0,0,0,0.05);
display: flex; justify-content: space-around; align-items: center;
z-index: 9999; box-shadow: 0 -5px 20px rgba(0,0,0,0.03);
backdrop-filter: blur(10px);
padding-bottom: 10px; /* 适配全面屏手势区 */
}
.nav-item { flex: 1; display: flex; flex-direction: column; align-items: center; cursor: pointer; padding: 5px; color: #b2bec3; transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); }
.nav-item.active { color: var(--primary); transform: translateY(-5px); }
.nav-icon { font-size: 22px; margin-bottom: 2px; filter: drop-shadow(0 2px 4px rgba(0,0,0,0.1)); } /* 假设有图标,这里用文字模拟布局 */
.nav-label { font-size: 12px; font-weight: 600; }
/* ================= 顶部 Tab 导航 ================= */
.tab-nav {
display: flex; background: white; margin: 10px 20px 20px;
border-radius: 12px; padding: 5px; box-shadow: 0 4px 12px rgba(0,0,0,0.05);
}
.tab-item {
flex: 1; padding: 10px; text-align: center; cursor: pointer;
font-weight: 600; color: var(--text-sub); border-radius: 8px;
transition: all 0.3s; font-size: 14px;
}
.tab-item.active { background: #e0e7ff; color: var(--primary); }
/* ================= 概念页 ================= */
.intro-page { padding: 30px 20px; text-align: center; }
.intro-emoji { font-size: 80px; margin-bottom: 20px; animation: float 3s ease-in-out infinite; }
@keyframes float { 0% { transform: translateY(0px); } 50% { transform: translateY(-10px); } 100% { transform: translateY(0px); } }
.intro-title { font-size: 28px; font-weight: 800; color: var(--text-main); margin-bottom: 20px; letter-spacing: 1px; }
.intro-content {
background: #fff; padding: 25px; border-radius: 20px; text-align: left;
font-size: 16px; line-height: 1.8; color: var(--text-sub);
box-shadow: 0 10px 25px rgba(0,0,0,0.05); margin-bottom: 25px;
}
.intro-button {
background: linear-gradient(135deg, var(--primary) 0%, #a29bfe 100%);
color: white; border: none; padding: 16px 45px; border-radius: 50px;
font-size: 18px; font-weight: bold; cursor: pointer;
box-shadow: 0 8px 20px rgba(102, 126, 234, 0.4);
transition: all 0.2s; position: relative; overflow: hidden; display: block; margin: 15px auto; width: 80%;
}
.intro-button:active { transform: scale(0.95); box-shadow: 0 4px 10px rgba(102, 126, 234, 0.3); }
/* ================= 演示页 ================= */
.demo-page { padding: 0 15px; }
.demo-section { display: none; }
.demo-section.active { display: block; animation: fadeIn 0.5s ease; }
.animation-area, .theory-animation-area {
background: #ffffff;
border-radius: 20px; padding: 10px; min-height: 320px;
position: relative; overflow: hidden;
box-shadow: inset 0 0 20px rgba(0,0,0,0.03), 0 10px 20px rgba(0,0,0,0.05);
border: 1px solid rgba(0,0,0,0.05); margin-bottom: 20px;
}
.svg-container { width: 100%; height: 100%; min-height: 280px; }
/* 公式与控制栏 */
.math-area {
background: #fff; border-left: 4px solid var(--primary);
border-radius: 0 12px 12px 0; padding: 15px; margin: 15px 0;
min-height: 80px; display: flex; align-items: center; justify-content: center;
box-shadow: 0 4px 15px rgba(0,0,0,0.05);
}
.math-formula { font-size: 22px; font-weight: 800; color: var(--text-main); text-align: center; }
.step-explanation {
background: #eef2ff; padding: 15px; border-radius: 12px;
color: var(--primary-dark); font-size: 15px; text-align: center;
line-height: 1.6; font-weight: 500; margin-bottom: 80px; /* 为底部按钮留空间 */
}
.control-bar {
position: fixed; bottom: 80px; left: 50%; transform: translateX(-50%);
width: 92%; max-width: 460px; z-index: 1000;
background: rgba(255, 255, 255, 0.9); backdrop-filter: blur(5px);
padding: 10px; border-radius: 20px;
box-shadow: 0 5px 20px rgba(0,0,0,0.1);
display: flex; justify-content: space-between; border: 1px solid rgba(0,0,0,0.05);
}
.step-btn {
background: var(--primary); color: white; border: none;
padding: 12px 30px; border-radius: 16px; font-size: 16px; font-weight: bold;
cursor: pointer; transition: transform 0.2s; box-shadow: 0 4px 10px rgba(102, 126, 234, 0.3);
}
.step-btn:disabled { background: #dcdde1; color: #a4b0be; box-shadow: none; cursor: not-allowed; }
.step-btn:active:not(:disabled) { transform: scale(0.95); }
/* 理论动画特有 */
.theory-animation-area { display: flex; align-items: center; justify-content: center; flex-direction: column; }
.theory-formula { font-size: 32px; font-weight: bold; color: var(--primary); margin-bottom: 15px; }
.theory-step { font-size: 20px; color: var(--text-sub); }
/* ================= 讲解页 ================= */
.explain-page { padding: 20px; }
.concept-box { background: #f0f7ff; border-left: 5px solid var(--primary); padding: 20px; border-radius: 12px; margin: 15px 0; box-shadow: 0 4px 12px rgba(0,0,0,0.03); }
.concept-box h3 { color: var(--primary); margin-top: 0; }
.principle-card {
background: white; border: 1px solid #e0e0e0; border-radius: 16px;
padding: 20px; margin: 15px 0; box-shadow: 0 4px 15px rgba(0,0,0,0.04);
border-top: 4px solid var(--accent);
}
.principle-title { color: var(--text-main); font-weight: bold; font-size: 18px; margin-bottom: 10px; }
.example-card {
background: white; border-radius: 16px; padding: 20px; margin-bottom: 15px;
box-shadow: 0 4px 15px rgba(0,0,0,0.04); transition: transform 0.2s;
}
.example-header { display: flex; justify-content: space-between; align-items: center; cursor: pointer; }
.example-type { background: #e0e7ff; color: var(--primary); padding: 4px 10px; border-radius: 20px; font-size: 12px; font-weight: 700; }
.example-title { font-weight: bold; flex: 1; margin-left: 10px; color: var(--text-main); }
.toggle-icon { color: var(--primary); font-size: 12px; }
.example-answer { font-weight: bold; color: var(--success); margin: 10px 0; background: #f6ffed; padding: 5px 10px; border-radius: 8px; display: inline-block; }
/* ================= 练习页 ================= */
.practice-page { padding: 20px; }
.question-card { background: white; border-radius: 24px; padding: 30px 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.08); }
.question-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 25px; border-bottom: 2px solid #f0f2f5; padding-bottom: 15px; }
.question-number { color: var(--primary); font-weight: 800; }
.score-display { background: #fff3e0; color: #ff9800; padding: 5px 15px; border-radius: 20px; font-weight: 800; font-size: 14px; }
.question-text { font-size: 19px; line-height: 1.6; color: var(--text-main); margin-bottom: 30px; font-weight: 600; }
.option-btn {
display: block; width: 100%; padding: 18px; margin-bottom: 15px;
text-align: left; border: 2px solid #f0f2f5; border-radius: 16px;
background: white; font-size: 17px; cursor: pointer; color: var(--text-sub);
transition: all 0.2s; position: relative; overflow: hidden;
}
.option-btn:active:not(:disabled) { transform: scale(0.98); background: #fafafa; }
.option-btn.correct { background: #eafff3; border-color: #2ecc71; color: #2ecc71; font-weight: 600; }
.option-btn.wrong { background: #fff5f5; border-color: #ff6b6b; color: #ff6b6b; }
.option-btn.shaking { animation: shake 0.5s; }
.feedback-area { padding: 20px; border-radius: 16px; margin: 25px 0; font-size: 15px; line-height: 1.6; animation: fadeIn 0.3s ease; }
.feedback-correct { background: #eafff3; color: #27ae60; border: 1px solid #b8e9ca; }
.feedback-wrong { background: #fff5f5; color: #c0392b; border: 1px solid #ffcccc; }
.next-btn {
width: 100%; padding: 18px;
background: linear-gradient(135deg, var(--primary) 0%, #764ba2 100%);
color: white; border: none; border-radius: 16px;
font-size: 18px; font-weight: bold; cursor: pointer;
box-shadow: 0 10px 20px rgba(102, 126, 234, 0.3);
transition: transform 0.2s;
}
.next-btn:active { transform: scale(0.97); }
.hint-box { background: #fff8e1; border-left: 5px solid #ffca28; padding: 15px; border-radius: 8px; margin: 15px 0; font-size: 14px; color: #f57c00; font-weight: 500; }
.difficulty-badge { padding: 3px 10px; border-radius: 12px; font-size: 12px; font-weight: 700; margin-left: 8px; vertical-align: middle; }
.difficulty-1 { background: #e8f5e9; color: #2e7d32; }
.difficulty-2 { background: #fff3e0; color: #ef6c00; }
.difficulty-3 { background: #ffebee; color: #c62828; }
/* 完成页 */
.completion-page { text-align: center; padding: 80px 20px; }
.completion-emoji { font-size: 100px; margin-bottom: 20px; }
.final-score { font-size: 72px; font-weight: 800; color: var(--accent); margin-bottom: 40px; text-shadow: 4px 4px 0px rgba(0,0,0,0.1); }
.restart-btn {
background: linear-gradient(135deg, #00b894 0%, #00cec9 100%);
color: white; border: none; padding: 18px 50px; border-radius: 50px;
font-size: 18px; font-weight: bold; cursor: pointer; box-shadow: 0 10px 20px rgba(0,184,148,0.3);
}
/* 秘籍页 */
.secrets-container { padding: 30px 20px; overflow-x: auto; padding-bottom: 50px; }
.secrets-slider { display: flex; gap: 20px; }
.secret-card {
flex: 0 0 280px; height: 320px;
background: white; border-radius: 30px; padding: 30px;
display: flex; flex-direction: column; justify-content: center; align-items: center;
box-shadow: 0 15px 35px rgba(0,0,0,0.15); transition: transform 0.3s;
}
.secret-card:nth-child(1) { border-top: 6px solid #ff9f43; }
.secret-card:nth-child(2) { border-top: 6px solid #54a0ff; }
.secret-card:nth-child(3) { border-top: 6px solid #5f27cd; }
.secret-emoji { font-size: 60px; margin-bottom: 20px; }
.secret-title { font-size: 22px; font-weight: 800; color: var(--text-main); margin-bottom: 15px; text-align: center; }
.secret-content { color: var(--text-sub); line-height: 1.6; text-align: center; font-size: 15px; }
</style>
</head>
<body>
<div id="app">
<div class="content-area">
<div v-show="currentPage === 1" class="intro-page fade-in">
<div class="intro-emoji">🪄</div>
<div class="intro-title">第04讲: 巧算与速算</div>
<div class="intro-content">
小朋友们,你们数过自己的10根手指吗?10是个神奇的数字,凑够10就能算得又快又准!<br><br>
✨ <strong>凑十法</strong>:把数字凑成10<br>
📦 <strong>分组法</strong>:把数字分组算<br>
🔄 <strong>交换律</strong>:加法可以换位置
</div>
<button class="intro-button" @click="switchPage(2)">🎬 开始学习</button>
<button class="intro-button" @click="speak('小朋友们,你们数过自己的10根手指吗?10是个神奇的数字,凑够10就能算得又快又准!凑十法是把数字凑成10,因为10是我们最熟悉的数,算起来最快。分组法是把很多数字分成几组,每组单独算,最后再合起来。交换律是加法时可以调换位置,就像排队谁站前谁站后,总数不变')">🔊 听老师讲解</button>
</div>
<div v-show="currentPage === 2" class="demo-page fade-in">
<div class="tab-nav">
<div class="tab-item" :class="{active: demoTab === 'direct'}" @click="switchDemoTab('direct')">凑十法演示</div>
<div class="tab-item" :class="{active: demoTab === 'theory'}" @click="switchDemoTab('theory')">分组法原理</div>
</div>
<div class="demo-section" :class="{active: demoTab === 'direct'}">
<div class="animation-area">
<svg class="svg-container" viewBox="0 0 400 330" id="direct-svg">
<rect x="50" y="50" width="300" height="60" rx="8" ry="8" fill="none" stroke="#ccc" stroke-width="2"/>
<rect x="50" y="120" width="300" height="60" rx="8" ry="8" fill="none" stroke="#ccc" stroke-width="2"/>
<rect x="53" y="53" width="54" height="54" rx="4" ry="4" fill="#fff" stroke="#e0e0e0" stroke-width="1" id="grid-1"/>
<rect x="113" y="53" width="54" height="54" rx="4" ry="4" fill="#fff" stroke="#e0e0e0" stroke-width="1" id="grid-2"/>
<rect x="173" y="53" width="54" height="54" rx="4" ry="4" fill="#fff" stroke="#e0e0e0" stroke-width="1" id="grid-3"/>
<rect x="233" y="53" width="54" height="54" rx="4" ry="4" fill="#fff" stroke="#e0e0e0" stroke-width="1" id="grid-4"/>
<rect x="293" y="53" width="54" height="54" rx="4" ry="4" fill="#fff" stroke="#e0e0e0" stroke-width="1" id="grid-5"/>
<rect x="53" y="123" width="54" height="54" rx="4" ry="4" fill="#fff" stroke="#e0e0e0" stroke-width="1" id="grid-6"/>
<rect x="113" y="123" width="54" height="54" rx="4" ry="4" fill="#fff" stroke="#e0e0e0" stroke-width="1" id="grid-7"/>
<rect x="173" y="123" width="54" height="54" rx="4" ry="4" fill="#fff" stroke="#e0e0e0" stroke-width="1" id="grid-8"/>
<rect x="233" y="123" width="54" height="54" rx="4" ry="4" fill="#fff" stroke="#e0e0e0" stroke-width="1" id="grid-9"/>
<rect x="293" y="123" width="54" height="54" rx="4" ry="4" fill="#fff" stroke="#e0e0e0" stroke-width="1" id="grid-10"/>
<circle cx="200" cy="-20" r="20" fill="#ff6b6b" id="red-ball-1"/>
<circle cx="170" cy="-20" r="20" fill="#ff6b6b" id="red-ball-2"/>
<circle cx="140" cy="-20" r="20" fill="#ff6b6b" id="red-ball-3"/>
<circle cx="230" cy="-20" r="20" fill="#ff6b6b" id="red-ball-4"/>
<circle cx="260" cy="-20" r="20" fill="#ff6b6b" id="red-ball-5"/>
<circle cx="110" cy="-20" r="20" fill="#ff6b6b" id="red-ball-6"/>
<circle cx="290" cy="-20" r="20" fill="#ff6b6b" id="red-ball-7"/>
<circle cx="-30" cy="80" r="20" fill="#4dabf7" id="blue-ball-1"/>
<circle cx="-30" cy="120" r="20" fill="#4dabf7" id="blue-ball-2"/>
<circle cx="-30" cy="160" r="20" fill="#4dabf7" id="blue-ball-3"/>
<circle cx="430" cy="80" r="20" fill="#51cf66" id="green-ball-1"/>
<circle cx="430" cy="120" r="20" fill="#51cf66" id="green-ball-2"/>
<text x="200" y="250" text-anchor="middle" font-size="24" fill="#333" id="formula-text" font-weight="bold">7 + ? + ? = ?</text>
</svg>
</div>
<div class="math-area">
<div class="math-formula" id="math-formula-display">7 + ? = ?</div>
</div>
<div class="step-explanation" id="step-explanation-display">小朋友们,我们一起来看凑十法的神奇过程吧!</div>
<div class="control-bar">
<button class="step-btn" @click="prevDirectStep" :disabled="directStep === 0">◀ 上一步</button>
<button class="step-btn" @click="nextDirectStep" :disabled="directStep === 3">下一步 ▶</button>
</div>
</div>
<div class="demo-section" :class="{active: demoTab === 'theory'}">
<div class="theory-animation-area">
<div>
<div class="theory-formula">{{ theorySteps[theoryStep].formula }}</div>
<div class="theory-step">{{ theorySteps[theoryStep].text }}</div>
</div>
</div>
<div class="math-area">
<div class="math-formula">分组法原理</div>
</div>
<div class="step-explanation">
{{ theorySteps[theoryStep].explanation }}
</div>
<div class="control-bar">
<button class="step-btn" @click="prevTheoryStep" :disabled="theoryStep === 0">◀ 上一步</button>
<button class="step-btn" @click="nextTheoryStep" :disabled="theoryStep === 2">下一步 ▶</button>
</div>
</div>
</div>
<div v-show="currentPage === 3" class="explain-page fade-in">
<div class="tab-nav">
<div class="tab-item" :class="{active: explainTab === 'direct'}" @click="explainTab = 'direct'">凑十法</div>
<div class="tab-item" :class="{active: explainTab === 'principle'}" @click="explainTab = 'principle'">核心原理</div>
<div class="tab-item" :class="{active: explainTab === 'examples'}" @click="explainTab = 'examples'">典型例题</div>
</div>
<div v-show="explainTab === 'direct'" class="demo-section active">
<div class="concept-box">
<h3>🧐 什么是凑十法?</h3>
<p>把两个数加起来等于10,然后再和其他的数相加。因为10是我们最熟悉的数,算起来最快!</p>
<div style="background:white; padding:10px; border-radius:8px; margin-top:10px;">
<p><strong>🍬 例子1(凑十买东西)</strong><br>买糖3元+买笔7元=10元,正好一张10元!不用找零,真方便!</p>
</div>
<div style="background:white; padding:10px; border-radius:8px; margin-top:10px;">
<p><strong>🔄 例子2(调换位置)</strong><br>2+8+5,可以先算2+8=10,再加5,得15。比2+5+8要快!</p>
</div>
</div>
</div>
<div v-show="explainTab === 'principle'" class="demo-section active">
<div class="principle-card">
<div class="principle-title">🔑 凑十法口诀</div>
<div class="principle-content">见到9就找1,见到8就找2<br>见到7就找3,见到6就找4<br>见到5就找5。</div>
</div>
<div class="principle-card">
<div class="principle-title">📦 分组法原理</div>
<div class="principle-content">把很多数字分成几组,每组单独算,最后再合起来。</div>
</div>
<div class="principle-card">
<div class="principle-title">🔄 加法交换律</div>
<div class="principle-content">加法时可以调换位置,就像排队谁站前谁站后,总数不变。<br>例如:a + b + c = a + c + b。</div>
</div>
</div>
<div v-show="explainTab === 'examples'" class="demo-section active">
<div class="example-card" v-for="(example, index) in typicalExamples" :key="index">
<div class="example-header" @click="toggleExample(index)">
<span class="example-type">{{ example.type }}</span>
<span class="example-title">{{ example.title }}</span>
<span class="toggle-icon">{{ expandedExample === index ? '▼' : '▶' }}</span>
</div>
<div v-show="expandedExample === index">
<div class="example-answer">答案:{{ example.answer }}</div>
<div class="example-explanation" v-html="example.explanation"></div>
</div>
</div>
</div>
</div>
<div v-show="currentPage === 4" class="practice-page fade-in">
<div v-if="!practiceCompleted">
<div class="question-card">
<div class="question-header">
<div class="question-number">第 {{currentQuestion + 1}}/{{practiceQuestions.length}} 题</div>
<div class="score-display">⭐ {{score}}分</div>
</div>
<div class="question-text" v-html="practiceQuestions[currentQuestion].text"></div>
<div class="options-container">
<button
v-for="(option, index) in practiceQuestions[currentQuestion].options"
:key="'opt'+index"
class="option-btn"
:class="{
'correct': answered && option.correct,
'wrong': answered && selectedOption === index && !option.correct,
'shaking': answered && selectedOption === index && !option.correct && shakingIndex === index
}"
@click="selectOption(index, option.correct)"
:disabled="answered"
>
<span v-if="answered && option.correct">✅ </span>
<span v-if="answered && selectedOption === index && !option.correct">❌ </span>
{{option.text}}
</button>
</div>
<div v-if="answered" class="feedback-area" :class="isCorrect ? 'feedback-correct' : 'feedback-wrong'">
<div v-if="isCorrect">
<strong>🎉 太棒了!</strong><br>
{{practiceQuestions[currentQuestion].explanation}}
</div>
<div v-else>
<strong>💡 让我们一起分析:</strong><br>
{{practiceQuestions[currentQuestion].explanation}}
</div>
</div>
<button v-if="answered" class="next-btn" @click="nextQuestion">
{{currentQuestion < practiceQuestions.length - 1 ? '下一题 →' : '完成练习 ✓'}}
</button>
</div>
</div>
<div v-else class="completion-page">
<div class="completion-emoji">🎊</div>
<div class="completion-title">课内练习完成!</div>
<div class="final-score">{{score}}分</div>
<button class="restart-btn" @click="switchPage(5)">挑战奥数题 →</button>
</div>
</div>
<div v-show="currentPage === 5" class="practice-page fade-in">
<div v-if="!olympiadCompleted">
<div class="question-card" style="border: 2px solid #ffd700;">
<div class="question-header">
<div>
<span class="question-number">第 {{currentOlympiad + 1}}/{{olympiadQuestions.length}} 题</span>
<span class="difficulty-badge" :class="'difficulty-' + olympiadQuestions[currentOlympiad].difficulty">
{{olympiadQuestions[currentOlympiad].difficultyText}}
</span>
</div>
<div class="score-display">⭐ {{olympiadScore}}分</div>
</div>
<div class="question-text" v-html="olympiadQuestions[currentOlympiad].text"></div>
<div class="options-container">
<button
v-for="(option, index) in olympiadQuestions[currentOlympiad].options"
:key="'olopt'+index"
class="option-btn"
:class="{
'correct': olympiadAnswered && option.correct,
'wrong': olympiadAnswered && selectedOlympiadOption === index && !option.correct,
'shaking': olympiadAnswered && selectedOlympiadOption === index && !option.correct && shakingIndex === index
}"
@click="selectOlympiadOption(index, option.correct)"
:disabled="olympiadAnswered"
>
<span v-if="olympiadAnswered && option.correct">✅ </span>
{{option.text}}
</button>
</div>
<div v-if="wrongAttempts > 0 && !olympiadAnswered">
<div class="hint-box" v-if="wrongAttempts === 1">
<strong>💡 提示1:</strong> {{olympiadQuestions[currentOlympiad].hint1}}
</div>
<div class="hint-box" v-if="wrongAttempts === 2">
<strong>💡 提示2:</strong> {{olympiadQuestions[currentOlympiad].hint2}}
</div>
</div>
<div v-if="olympiadAnswered" class="feedback-area" :class="isOlympiadCorrect ? 'feedback-correct' : 'feedback-wrong'">
<div v-if="isOlympiadCorrect">
<strong>🏆 厉害!</strong><br>
{{olympiadQuestions[currentOlympiad].explanation}}
</div>
<div v-else>
<strong>📖 详细解析:</strong><br>
{{olympiadQuestions[currentOlympiad].explanation}}
</div>
</div>
<button v-if="olympiadAnswered || wrongAttempts >= 3" class="next-btn" @click="nextOlympiad">
{{currentOlympiad < olympiadQuestions.length - 1 ? '下一题 →' : '完成挑战 ✓'}}
</button>
</div>
</div>
<div v-else class="completion-page">
<div class="completion-emoji">🏆</div>
<div class="completion-title">奥数挑战完成!</div>
<div class="final-score">{{olympiadScore}}分</div>
<button class="restart-btn" @click="switchPage(6)">查看通关秘籍 →</button>
</div>
</div>
<div v-show="currentPage === 6" class="secrets-container fade-in">
<div class="secrets-slider">
<div class="secret-card">
<div class="secret-emoji">🔟</div>
<div class="secret-title">秘籍1: 见到9就凑10</div>
<div class="secret-content">看到9就找1,看到8就找2,看到7就找3,看到6就找4,看到5就找5。</div>
</div>
<div class="secret-card">
<div class="secret-emoji">👯♀️</div>
<div class="secret-title">秘籍2: 相同数字配对</div>
<div class="secret-content">两个5凑10,两个6凑12,找相同的数字更快。</div>
</div>
<div class="secret-card">
<div class="secret-emoji">🚀</div>
<div class="secret-title">秘籍3: 先凑十再算</div>
<div class="secret-content">有10在手,其他数字往上加就简单了。</div>
</div>
</div>
</div>
</div>
<div class="bottom-nav">
<div class="nav-item" :class="{active: currentPage === 1}" @click="switchPage(1)">
<div class="nav-icon">💡</div>
<div class="nav-label">概念</div>
</div>
<div class="nav-item" :class="{active: currentPage === 2}" @click="switchPage(2)">
<div class="nav-icon">🎬</div>
<div class="nav-label">演示</div>
</div>
<div class="nav-item" :class="{active: currentPage === 3}" @click="switchPage(3)">
<div class="nav-icon">📝</div>
<div class="nav-label">讲解</div>
</div>
<div class="nav-item" :class="{active: currentPage === 4}" @click="switchPage(4)">
<div class="nav-icon">✏️</div>
<div class="nav-label">练习</div>
</div>
<div class="nav-item" :class="{active: currentPage === 5}" @click="switchPage(5)">
<div class="nav-icon">🏆</div>
<div class="nav-label">奥数</div>
</div>
<div class="nav-item" :class="{active: currentPage === 6}" @click="switchPage(6)">
<div class="nav-icon">🎁</div>
<div class="nav-label">秘籍</div>
</div>
</div>
</div>
<script src="https://www.xinghuo.tv/wp-content/themes/xinghuo-tv/assets/js/vue.global.prod.js"></script>
<script src="https://www.xinghuo.tv/wp-content/themes/xinghuo-tv/assets/js/gsap.min.js"></script>
<script src="https://www.xinghuo.tv/wp-content/themes/xinghuo-tv/assets/js/confetti.browser.min.js"></script>
<script>
const { createApp } = Vue;
createApp({
data() {
return {
currentPage: 1,
demoTab: 'direct',
explainTab: 'direct',
directStep: 0,
theoryStep: 0,
expandedExample: null,
shakingIndex: null, // 控制震动的索引
// 练习题数据
currentQuestion: 0,
answered: false,
selectedOption: null,
isCorrect: false,
score: 0,
practiceCompleted: false,
practiceQuestions: [
{
text: "用凑十法计算:9+1+3=____",
options: [
{text: "A.12", correct: false},
{text: "B.13", correct: true},
{text: "C.14", correct: false},
{text: "D.15", correct: false}
],
explanation: "10+3=13"
},
{
text: "计算:5+8+5=____",
options: [
{text: "A.16", correct: false},
{text: "B.17", correct: false},
{text: "C.18", correct: true},
{text: "D.19", correct: false}
],
explanation: "10+8=18"
},
{
text: "用凑十法:3+6+4=____",
options: [
{text: "A.11", correct: false},
{text: "B.12", correct: false},
{text: "C.13", correct: true},
{text: "D.14", correct: false}
],
explanation: "3+10=13"
},
{
text: "计算:7+2+8=____",
options: [
{text: "A.15", correct: false},
{text: "B.16", correct: false},
{text: "C.17", correct: true},
{text: "D.18", correct: false}
],
explanation: "7+10=17"
},
{
text: "用分组法:10+20+30=____",
options: [
{text: "A.50", correct: false},
{text: "B.60", correct: true},
{text: "C.70", correct: false},
{text: "D.80", correct: false}
],
explanation: "1个十+2个十+3个十=6个十,6个十就是60"
},
{
text: "巧算:6+3+4+7=____",
options: [
{text: "A.18", correct: false},
{text: "B.19", correct: false},
{text: "C.20", correct: true},
{text: "D.21", correct: false}
],
explanation: "10+10=20"
},
{
text: "计算:8+5+2+5=____",
options: [
{text: "A.18", correct: false},
{text: "B.19", correct: false},
{text: "C.20", correct: true},
{text: "D.21", correct: false}
],
explanation: "10+10=20"
},
{
text: "巧算:1+9+1+9=____",
options: [
{text: "A.18", correct: false},
{text: "B.19", correct: false},
{text: "C.20", correct: true},
{text: "D.21", correct: false}
],
explanation: "(1+9)+(1+9)=10+10=20"
}
],
// 奥数挑战数据
currentOlympiad: 0,
olympiadAnswered: false,
selectedOlympiadOption: null,
isOlympiadCorrect: false,
olympiadScore: 0,
olympiadCompleted: false,
wrongAttempts: 0,
olympiadQuestions: [
{
text: "小明有7颗糖,小红给他3颗,小刚又给他2颗,小明现在有多少颗糖?用凑十法算一算。",
options: [
{text: "A.10颗", correct: false},
{text: "B.11颗", correct: false},
{text: "C.12颗", correct: true},
{text: "D.13颗", correct: false}
],
hint1: "写出算式:7+3+2",
hint2: "哪两个数能凑成10?",
hint3: "7+3=10,然后再加2",
explanation: "原有:7颗<br>小红给:3颗<br>小刚给:2颗<br>算式:7+3+2<br>凑十法:7+3=10,10+2=12<br>答案:12颗",
difficulty: 1,
difficultyText: "⭐"
},
{
text: "小猴子摘桃:第一天摘8个,第二天摘9个,第三天摘2个,第四天摘1个。一共摘了多少个?",
options: [
{text: "A.18个", correct: false},
{text: "B.19个", correct: false},
{text: "C.20个", correct: true},
{text: "D.21个", correct: false}
],
hint1: "写出算式,找能凑10的数",
hint2: "8和2凑10,9和1凑10",
hint3: "10+10=20",
explanation: "算式:8+9+2+1<br>巧算方法:<br>8+2=10(凑十)<br>9+1=10(凑十)<br>10+10=20<br>答案:20个",
difficulty: 2,
difficultyText: "⭐⭐"
},
{
text: "公交车上原有5人,第一站上车7人,第二站上车3人,现在车上有几人?",
options: [
{text: "A.13人", correct: false},
{text: "B.14人", correct: false},
{text: "C.15人", correct: true},
{text: "D.16人", correct: false}
],
hint1: "把三个数加起来",
hint2: "找能凑10的数:7和3",
hint3: "5+(7+3)=5+10=15",
explanation: "原有:5人<br>第一站:上7人<br>第二站:上3人<br>算式:5+7+3<br>巧算:7+3=10,5+10=15<br>答案:15人",
difficulty: 1,
difficultyText: "⭐"
},
{
text: "小朋友排队做操,第一排4人,第二排6人,第三排4人,第四排6人。一共多少人?",
options: [
{text: "A.18人", correct: false},
{text: "B.19人", correct: false},
{text: "C.20人", correct: true},
{text: "D.21人", correct: false}
],
hint1: "观察数字规律:两个4,两个6",
hint2: "4+6=10",
hint3: "10+10=20",
explanation: "算式:4+6+4+6<br>分组巧算:<br>(4+6)+(4+6)<br>=10+10<br>=20人",
difficulty: 2,
difficultyText: "⭐⭐"
},
{
text: "小红买文具:铅笔3元,橡皮2元,尺子5元,笔记本8元。一共多少元?",
options: [
{text: "A.16元", correct: false},
{text: "B.17元", correct: false},
{text: "C.18元", correct: true},
{text: "D.19元", correct: false}
],
hint1: "找能凑成10的两个数",
hint2: "2和8能凑成10",
hint3: "剩下3+5=8,10+8=18",
explanation: "算式:3+2+5+8<br>巧算方法:<br>2+8=10(凑十)<br>3+5=8<br>10+8=18元",
difficulty: 2,
difficultyText: "⭐⭐"
},
{
text: "算式填空:6+____+4=16",
options: [
{text: "A.4", correct: false},
{text: "B.5", correct: false},
{text: "C.6", correct: true},
{text: "D.7", correct: false}
],
hint1: "先算6+4等于多少",
hint2: "6+4=10,还差几到16?",
hint3: "16-10=6",
explanation: "方法1:16-6-4=6<br>方法2:6+4=10,16-10=6<br>巧算提示:先凑十,再看差几",
difficulty: 3,
difficultyText: "⭐⭐⭐"
},
{
text: "小明的计算:7+3=10,10+5=15,10+5+2=____",
options: [
{text: "A.15", correct: false},
{text: "B.16", correct: false},
{text: "C.17", correct: true},
{text: "D.18", correct: false}
],
hint1: "前面已经算出15",
hint2: "现在要加2",
hint3: "15+2=17",
explanation: "前面已经算出7+3+5=15<br>现在要加上2<br>15+2=17",
difficulty: 1,
difficultyText: "⭐"
},
{
text: "买水果:苹果8元,香蕉2元,橙子4元,葡萄6元。如果只买两种水果,选哪两种凑成10元?",
options: [
{text: "A.苹果+香蕉", correct: false},
{text: "B.香蕉+橙子", correct: false},
{text: "C.橙子+葡萄", correct: true},
{text: "D.香蕉+葡萄", correct: false}
],
hint1: "找两个数相加等于10",
hint2: "试试不同的组合",
hint3: "4+6=10,选C",
explanation: "找两个数相加等于10:<br>8+2=10(苹果+香蕉)<br>4+6=10(橙子+葡萄)<br>2+8=10(香蕉+苹果,同A)<br>答案有两组,题目问凑成10元的,橙子+葡萄也对",
difficulty: 2,
difficultyText: "⭐⭐"
}
],
// 典型例题数据
typicalExamples: [
{
type: "基础题",
title: "用凑十法计算:7+3+4",
answer: "14",
explanation: "第1步:找一找哪两个数能凑成10<br>第2步:7+3=10(凑成10了!)<br>第3步:10+4=14<br>很简单吧!"
},
{
type: "进阶题",
title: "用凑十法计算:8+5+2",
answer: "15",
explanation: "第1步:8和2能凑成10<br>第2步:但8在前面,2在后面,怎么办?<br>第3步:记住可以调换顺序!8+2+5<br>第4步:8+2=10,10+5=15"
},
{
type: "易错题",
title: "计算:6+7+4",
answer: "17",
explanation: "【易错点】:有的小朋友从左往右算:6+7=13,13+4=17。虽然对了,但比较慢<br>【巧算方法】:<br>第1步:6和4能凑成10<br>第2步:调换顺序:6+4+7<br>第3步:6+4=10,10+7=17<br>第4步:快多了!"
}
],
// 理论演示步骤
theorySteps: [
{
formula: "10 + 6 = 16",
text: "第1步:先数一堆10个",
explanation: "有16个积木,分成10个一堆和6个一堆,更容易数"
},
{
formula: "(10 + 6) = 16",
text: "第2步:再数另一堆6个",
explanation: "把很多数字分成几组,每组单独算"
},
{
formula: "10 + 6 = 16",
text: "第3步:合起来就是总数",
explanation: "最后再把每组的结果合起来,这就是分组法的妙用!"
}
],
// 动画步骤的文字
directSteps: [
"小朋友们,我们一起来看凑十法的神奇过程吧!",
"先掉下来7个红球,看!还有3个空位才能填满10格。",
"3个蓝球掉下来啦!7+3=10,正好凑成10!方格发光了!",
"最后掉下来2个绿球,10+2=12,总数就是12个球啦!"
],
directFormulas: [
"7 + ? = ?",
"7 + 3 = 10",
"7 + 3 = 10",
"10 + 2 = 12"
]
};
},
methods: {
switchPage(page) {
this.stopSpeak();
this.currentPage = page;
window.scrollTo(0, 0); // 切换页面时滚回顶部
if (page === 2) {
this.directStep = 0;
this.theoryStep = 0;
this.$nextTick(() => {
this.runDirectAnimation();
});
}
if (page === 4 && this.practiceCompleted) {
this.currentQuestion = 0;
this.answered = false;
this.score = 0;
this.practiceCompleted = false;
}
if (page === 5 && this.olympiadCompleted) {
this.currentOlympiad = 0;
this.olympiadAnswered = false;
this.olympiadScore = 0;
this.olympiadCompleted = false;
this.wrongAttempts = 0;
}
},
// 停止语音 (逻辑保持不变)
stopSpeak() {
const isWeChat = /MicroMessenger/i.test(navigator.userAgent);
if (isWeChat) {
const audio = document.getElementById('tts-audio');
if (audio) {
audio.pause();
audio.currentTime = 0;
}
} else {
if (window.speechSynthesis) {
window.speechSynthesis.cancel();
}
}
},
switchDemoTab(tab) {
this.demoTab = tab;
if (tab === 'direct') {
this.directStep = 0;
this.$nextTick(() => {
this.runDirectAnimation();
});
}
},
// 语音合成 (逻辑保持不变)
speak(text) {
const isWeChat = /MicroMessenger/i.test(navigator.userAgent);
if (isWeChat) {
let audio = document.getElementById('tts-audio');
if (!audio) {
audio = document.createElement('audio');
audio.id = 'tts-audio';
audio.style.display = 'none';
document.body.appendChild(audio);
}
const url = `https://www.xinghuo.tv/wp-content/themes/xinghuo-tv/tts.php?text=${encodeURIComponent(text)}&t=${Date.now()}`;
audio.src = url;
audio.play().catch(err => { console.log('语音播放失败:', err); });
} else {
const utterance = new SpeechSynthesisUtterance(text);
utterance.lang = 'zh-CN';
utterance.rate = 0.9;
window.speechSynthesis.speak(utterance);
}
},
// GSAP 动画逻辑 - 凑十法演示 (优化版)
runDirectAnimation() {
if (typeof gsap === 'undefined') return;
const tl = gsap.timeline();
// 重置所有球到初始位置
gsap.set(['#red-ball-1', '#red-ball-2', '#red-ball-3', '#red-ball-4', '#red-ball-5', '#red-ball-6', '#red-ball-7'], {y: -20, opacity: 1});
gsap.set(['#blue-ball-1', '#blue-ball-2', '#blue-ball-3'], {x: -30, opacity: 1});
gsap.set(['#green-ball-1', '#green-ball-2'], {x: 430, opacity: 1});
gsap.set(['#grid-1', '#grid-2', '#grid-3', '#grid-4', '#grid-5', '#grid-6', '#grid-7', '#grid-8', '#grid-9', '#grid-10'], {fill: '#fff', scale: 1});
gsap.set('#formula-text', {text: '7 + ? + ? = ?', scale: 1});
if (this.directStep === 0) {
// 初始状态
tl.set('#math-formula-display', {innerHTML: this.directFormulas[0]})
.set('#step-explanation-display', {innerHTML: this.directSteps[0]});
}
if (this.directStep === 1) {
// 掉下7个红球,增加弹性效果
tl.to(['#red-ball-1', '#red-ball-2', '#red-ball-3', '#red-ball-4', '#red-ball-5', '#red-ball-6', '#red-ball-7'], {
y: '+=140', duration: 0.8, stagger: 0.05, ease: 'bounce.out'
})
.to(['#grid-1', '#grid-2', '#grid-3', '#grid-4', '#grid-5', '#grid-6', '#grid-7'], {
fill: '#ffebee', duration: 0.3
}, '-=0.6')
.set('#math-formula-display', {innerHTML: this.directFormulas[1]})
.set('#step-explanation-display', {innerHTML: this.directSteps[1]});
}
if (this.directStep === 2) {
// 掉下3个蓝球,凑成10,增加发光和放大效果
tl.to(['#blue-ball-1', '#blue-ball-2', '#blue-ball-3'], {
x: '+=430', duration: 0.8, stagger: 0.1, ease: 'back.out(1.7)'
})
.to(['#grid-8', '#grid-9', '#grid-10'], {
fill: '#e3f2fd', duration: 0.3
}, '-=0.5')
.to(['#grid-1', '#grid-2', '#grid-3', '#grid-4', '#grid-5', '#grid-6', '#grid-7', '#grid-8', '#grid-9', '#grid-10'], {
scale: 1.1, duration: 0.2, yoyo: true, repeat: 1, ease: 'power1.inOut'
})
.set('#formula-text', {text: '7 + 3 = 10'})
.fromTo('#formula-text', {scale: 1.5, color: '#2ecc71'}, {scale: 1, color: '#333', duration: 0.5})
.set('#math-formula-display', {innerHTML: this.directFormulas[2]})
.set('#step-explanation-display', {innerHTML: this.directSteps[2]});
}
if (this.directStep === 3) {
// 掉下2个绿球,得到总数12
tl.to(['#green-ball-1', '#green-ball-2'], {
x: '-=430', duration: 0.8, stagger: 0.1, ease: 'back.out(1.7)'
})
.set('#formula-text', {text: '7 + 3 + 2 = 12'})
.set('#math-formula-display', {innerHTML: this.directFormulas[3]})
.set('#step-explanation-display', {innerHTML: this.directSteps[3]});
}
},
// 步骤导航
nextDirectStep() {
if (this.directStep < 3) {
this.directStep++;
this.runDirectAnimation();
}
},
prevDirectStep() {
if (this.directStep > 0) {
this.directStep--;
this.runDirectAnimation();
}
},
// 理论步骤导航
nextTheoryStep() {
if (this.theoryStep < 2) {
this.theoryStep++;
}
},
prevTheoryStep() {
if (this.theoryStep > 0) {
this.theoryStep--;
}
},
// 典型例题折叠
toggleExample(index) {
this.expandedExample = this.expandedExample === index ? null : index;
},
// 练习题逻辑
selectOption(index, correct) {
if (this.answered) return;
if (!correct) {
// 错题震动效果
this.shakingIndex = index;
setTimeout(() => {
this.shakingIndex = null;
}, 500);
}
this.answered = true;
this.selectedOption = index;
this.isCorrect = correct;
if (correct) {
this.score += 20;
if (typeof confetti !== 'undefined') {
confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } });
}
}
},
nextQuestion() {
if (this.currentQuestion < this.practiceQuestions.length - 1) {
this.currentQuestion++;
this.answered = false;
this.selectedOption = null;
} else {
this.practiceCompleted = true;
}
},
// 奥数题逻辑
selectOlympiadOption(index, correct) {
if (this.olympiadAnswered) return;
if (correct) {
this.olympiadAnswered = true;
this.selectedOlympiadOption = index;
this.isOlympiadCorrect = true;
this.olympiadScore += 25;
this.wrongAttempts = 0;
if (typeof confetti !== 'undefined') {
confetti({ particleCount: 150, spread: 80, origin: { y: 0.6 } });
}
} else {
// 错题震动
this.shakingIndex = index;
setTimeout(() => { this.shakingIndex = null; }, 500);
this.wrongAttempts++;
if (this.wrongAttempts >= 3) {
this.olympiadAnswered = true;
this.selectedOlympiadOption = index;
this.isOlympiadCorrect = false;
}
}
},
nextOlympiad() {
if (this.currentOlympiad < this.olympiadQuestions.length - 1) {
this.currentOlympiad++;
this.olympiadAnswered = false;
this.selectedOlympiadOption = null;
this.wrongAttempts = 0;
} else {
this.olympiadCompleted = true;
}
}
}
}).mount('#app');
</script>
</body>
</html>
💡 这段代码完全由 AI 生成。
登录后可复制完整代码