<!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>第01讲:找规律填数(简单的等差数列雏形)</title>
<style>
/* ================= 基础重置与全局样式 ================= */
:root {
--primary: #a29bfe; /* 薰衣草紫 */
--primary-dark: #6c5ce7;
--accent: #ffeaa7; /* 奶油黄 */
--success: #00b894; /* 薄荷绿 */
--error: #ff7675; /* 珊瑚红 */
--bg-color: #f0f3f5;
--text-main: #2d3436;
--text-sub: #636e72;
--card-shadow: 0 10px 20px rgba(0,0,0,0.05);
}
* { 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(#dfe6e9 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-dark); transform: translateY(-3px); }
.nav-icon { font-size: 24px; margin-bottom: 2px; filter: drop-shadow(0 2px 4px rgba(0,0,0,0.1)); }
.nav-label { font-size: 11px; font-weight: 600; }
/* ================= 顶部 Tab 导航 ================= */
.tab-nav {
display: flex; background: white; margin: 10px 20px 20px;
border-radius: 12px; padding: 5px; box-shadow: var(--card-shadow);
}
.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-dark); }
/* ================= 概念页 ================= */
.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-text {
background: #fff; padding: 25px; border-radius: 20px; text-align: left;
font-size: 16px; line-height: 1.8; color: var(--text-sub);
box-shadow: var(--card-shadow); margin-bottom: 25px;
}
.listen-btn {
background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 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(108, 92, 231, 0.3);
transition: all 0.2s; position: relative; overflow: hidden; display: block; margin: 0 auto;
}
.listen-btn:active { transform: scale(0.95); box-shadow: 0 4px 10px rgba(108, 92, 231, 0.3); }
/* ================= 演示页 ================= */
.demo-page { padding: 0 15px; }
.demo-section { display: none; }
.demo-section.active { display: block; animation: fadeIn 0.5s ease; }
.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), var(--card-shadow);
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(--accent);
border-radius: 0 12px 12px 0; padding: 15px; margin: 15px 0;
min-height: 80px; display: flex; align-items: center; justify-content: center;
box-shadow: var(--card-shadow);
}
.math-formula { font-size: 24px; font-weight: 800; color: var(--text-main); text-align: center; font-family: monospace; }
.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; /* 为底部按钮留空间 */
}
/* 悬浮控制按钮 - 放在动画区域两侧 */
.prev-btn, .next-btn {
position: absolute; top: 50%; transform: translateY(-50%); z-index: 100;
width: 44px; height: 44px; border-radius: 50%;
background: rgba(255, 255, 255, 0.9); color: var(--primary-dark);
border: 1px solid rgba(0,0,0,0.1);
font-size: 18px; cursor: pointer;
box-shadow: 0 4px 10px rgba(0,0,0,0.15);
display: flex; align-items: center; justify-content: center;
transition: all 0.2s;
}
.prev-btn:active, .next-btn:active { transform: translateY(-50%) scale(0.9); }
.prev-btn:disabled, .next-btn:disabled { opacity: 0; pointer-events: none; }
.prev-btn { left: 10px; }
.next-btn { right: 10px; }
/* ================= 讲解页 ================= */
.explain-page { padding: 20px; }
.example-card {
background: white; border-radius: 16px; padding: 20px; margin-bottom: 15px;
box-shadow: var(--card-shadow); transition: transform 0.2s;
border: 1px solid #f1f2f6; overflow: hidden;
}
.example-header { display: flex; justify-content: space-between; align-items: center; cursor: pointer; }
.example-header h4 { margin: 0; color: var(--text-main); font-weight: 700; }
.example-toggle { color: var(--primary-dark); font-size: 20px; font-weight: bold; }
.example-body { display: none; margin-top: 15px; padding-top: 15px; border-top: 1px dashed #eee; }
.example-body.active { display: block; animation: slideDown 0.3s ease; }
@keyframes slideDown { from { opacity: 0; transform: translateY(-5px); } to { opacity: 1; transform: translateY(0); } }
.example-answer {
background: #eafff3; padding: 10px; border-radius: 8px; margin: 10px 0;
color: var(--success); font-weight: bold; border-left: 3px solid var(--success);
}
.example-explanation { font-size: 15px; line-height: 1.6; color: var(--text-sub); }
.concept-list { list-style: none; padding: 0; }
.concept-list li { margin-bottom: 10px; background: #fff; padding: 12px; border-radius: 8px; border-left: 4px solid var(--primary); box-shadow: 0 2px 5px rgba(0,0,0,0.05); }
/* ================= 练习/奥数 ================= */
.practice-page { padding: 20px; }
.question-card { background: white; border-radius: 24px; padding: 30px 20px; box-shadow: var(--card-shadow); }
.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-dark); 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(--accent) 0%, #fab1a0 100%);
color: #d35400; border: none; border-radius: 16px;
font-size: 18px; font-weight: bold; cursor: pointer;
box-shadow: 0 10px 20px rgba(253, 203, 110, 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-3 { background: #ffebee; color: #c62828; }
/* ================= 完成页 ================= */
.completion-page { text-align: center; padding: 80px 20px; }
.completion-emoji { font-size: 100px; margin-bottom: 20px; animation: float 3s infinite; }
.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-scroll { 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">找规律填数</div>
<div class="intro-text">
<p>嗨,小朋友们!今天我们来当小侦探,发现数字里藏起来的秘密!</p>
<p>看,这里有一列数字:<strong>1、2、3、4...</strong></p>
<p>它们是像爬楼梯一样,<strong>一阶一阶</strong>地变大。这就是数字的规律!</p>
<p>只要找到了规律,你就能知道下一个数字是什么,就像预知未来的小魔法师一样!</p>
</div>
<button class="listen-btn" @click="speak('让我们一起学习找规律填数吧!')">🎧 听老师讲解</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">
<button class="prev-btn" @click="prevDirectStep" :disabled="directStep === 0">◀</button>
<button class="next-btn" @click="nextDirectStep" :disabled="directStep === 3">▶</button>
<svg class="svg-container" viewBox="0 0 400 300" preserveAspectRatio="xMidYMid meet">
<rect id="step5-question" x="280" y="200" width="40" height="30" rx="5" fill="#f1f2f6" stroke="#b2bec3" stroke-width="2" visibility="hidden"/>
<text id="step5-question-text" x="300" y="218" text-anchor="middle" font-size="14" fill="#636e72" visibility="hidden">?</text>
<rect id="step4" x="200" y="200" width="40" height="30" rx="5" fill="#a29bfe" stroke="#6c5ce7" stroke-width="2"/>
<text x="220" y="218" text-anchor="middle" font-size="14" fill="white" font-weight="bold">4</text>
<rect id="step3" x="120" y="200" width="40" height="30" rx="5" fill="#74b9ff" stroke="#0984e3" stroke-width="2"/>
<text x="140" y="218" text-anchor="middle" font-size="14" fill="white" font-weight="bold">3</text>
<rect id="step2" x="40" y="200" width="40" height="30" rx="5" fill="#55efc4" stroke="#00b894" stroke-width="2"/>
<text x="60" y="218" text-anchor="middle" font-size="14" fill="white" font-weight="bold">2</text>
<rect id="step1" x="-40" y="200" width="40" height="30" rx="5" fill="#ffeaa7" stroke="#fdcb6e" stroke-width="2"/>
<text x="-20" y="218" text-anchor="middle" font-size="14" fill="#d35400" font-weight="bold">1</text>
<image id="rabbit" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MCA1MCI+PGNpcmNsZSBjeD0iMjUiIGN5PSIyNSIgcj0iMjAiIGZpbGw9IiNmZjZmOWMiLz48cGF0aCBkPSJNMjUgMzUgQTEwIDEwIDAgMCAwIDM1IDI1IiBzdHJva2U9IndoaXRlIiBzdHJva2Utd2lkdGg9IjIiIGZpbGw9Im5vbmUiLz48L3N2Zz4=" x="0" y="140" width="40" height="40" />
<circle id="bubble" cx="60" cy="130" r="0" fill="#6c5ce7"/>
<text id="bubble-text" x="60" y="135" text-anchor="middle" font-size="12" fill="white" visibility="hidden">+1</text>
</svg>
</div>
<div class="math-area">
<div class="math-formula">
<span v-if="directStep === 0">1、2、3、4、?</span>
<span v-if="directStep === 1">2 - 1 = 1</span>
<span v-if="directStep === 2">3 - 2 = 1</span>
<span v-if="directStep === 3">4 - 3 = 1</span>
</div>
</div>
<div class="step-explanation">
<div v-if="directStep === 0">观察数字:1、2、3、4...</div>
<div v-if="directStep === 1">第1步:看看相邻两个数之间差多少:2比1多1。</div>
<div v-if="directStep === 2">第2步:继续看:3比2也多1,规律出现了!</div>
<div v-if="directStep === 3">第3步:每次都加1!下一个数就是4+1=5。</div>
</div>
</div>
<div class="demo-section" :class="{active: demoTab === 'theory'}">
<div class="animation-area">
<button class="prev-btn" @click="prevTheoryStep" :disabled="theoryStep === 0">◀</button>
<button class="next-btn" @click="nextTheoryStep" :disabled="theoryStep === 3">▶</button>
<svg class="svg-container" viewBox="0 0 400 300" preserveAspectRatio="xMidYMid meet">
<rect id="theory-step4-question" x="320" y="200" width="40" height="30" rx="5" fill="#f1f2f6" stroke="#aaa" stroke-width="2" visibility="hidden"/>
<text id="theory-step4-question-text" x="340" y="218" text-anchor="middle" font-size="14" fill="#777" visibility="hidden">?</text>
<rect id="theory-step3" x="240" y="200" width="40" height="30" rx="5" fill="#a29bfe" stroke="#6c5ce7" stroke-width="2"/>
<text x="260" y="218" text-anchor="middle" font-size="14" fill="white" font-weight="bold">7</text>
<rect id="theory-step2" x="160" y="200" width="40" height="30" rx="5" fill="#74b9ff" stroke="#0984e3" stroke-width="2"/>
<text x="180" y="218" text-anchor="middle" font-size="14" fill="white" font-weight="bold">5</text>
<rect id="theory-step1" x="80" y="200" width="40" height="30" rx="5" fill="#55efc4" stroke="#00b894" stroke-width="2"/>
<text x="100" y="218" text-anchor="middle" font-size="14" fill="white" font-weight="bold">3</text>
<rect id="theory-step0" x="0" y="200" width="40" height="30" rx="5" fill="#ffeaa7" stroke="#fdcb6e" stroke-width="2"/>
<text x="20" y="218" text-anchor="middle" font-size="14" fill="#d35400" font-weight="bold">1</text>
<image id="theory-rabbit" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MCA1MCI+PGNpcmNsZSBjeD0iMjUiIGN5PSIyNSIgcj0iMjAiIGZpbGw9IiNmZDc5YTgiLz48cGF0aCBkPSJNMjUgMzUgQTEwIDEwIDAgMCAwIDM1IDI1IiBzdHJva2U9IndoaXRlIiBzdHJva2Utd2lkdGg9IjIiIGZpbGw9Im5vbmUiLz48L3N2Zz4=" x="0" y="140" width="40" height="40" />
<circle id="theory-bubble" cx="60" cy="130" r="0" fill="#fd79a8"/>
<text id="theory-bubble-text" x="60" y="135" text-anchor="middle" font-size="12" fill="white" visibility="hidden">+2</text>
</svg>
</div>
<div class="math-area">
<div class="math-formula">
<span v-if="theoryStep === 0">1、3、5、7、?</span>
<span v-if="theoryStep === 1">3 - 1 = 2</span>
<span v-if="theoryStep === 2">5 - 3 = 2</span>
<span v-if="theoryStep === 3">7 - 5 = 2</span>
</div>
</div>
<div class="step-explanation">
<div v-if="theoryStep === 0">观察数字:1、3、5、7...</div>
<div v-if="theoryStep === 1">第1步:看相邻两数的差:3比1多2。</div>
<div v-if="theoryStep === 2">第2步:规律在延续:5比3也多2。</div>
<div v-if="theoryStep === 3">第3步:每次都加2!下一个数就是7+2=9。</div>
</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 === 'theory'}" @click="explainTab = 'theory'">核心原理</div>
<div class="tab-item" :class="{active: explainTab === 'example'}" @click="explainTab = 'example'">典型例题</div>
</div>
<div v-if="explainTab === 'direct'">
<div class="intro-text">
<p>找规律的关键就是<b>看相邻两个数之间的变化</b>!</p>
<p>用后一个数减去前一个数,看看差是不是一样的。</p>
<p>如果每次都加(或减)同一个数,你就找到了“相同步长”的规律!</p>
</div>
</div>
<div v-if="explainTab === 'theory'">
<ul class="concept-list">
<li><strong>📈 单调变化</strong>:数字像爬楼梯一样越来越大,或者像下楼梯一样越来越小。</li>
<li><strong>📏 相同步长</strong>:每次变化的大小都是一样的,就像每个台阶都一样高。</li>
<li><strong>🔮 规律延续</strong>:找到规律后,就能知道后面的数字是什么。</li>
</ul>
</div>
<div v-if="explainTab === 'example'">
<div class="example-card">
<div class="example-header" @click="toggleExample(0)">
<h4>📝 例题1:基础题</h4>
<span class="example-toggle">{{ exampleVisible[0] ? '−' : '+' }}</span>
</div>
<div class="example-body" :class="{active: exampleVisible[0]}">
<div class="example-answer"><strong>题目:</strong>找规律填数:2、4、6、8、____</div>
<div class="example-answer">答案:10</div>
<div class="example-explanation">
<strong>解析:</strong><br>
1. 看看每两个数之间差多少:4-2=2,6-4=2<br>
2. 发现规律了!每次都加2。<br>
3. 所以下一个数是:8+2=10。
</div>
</div>
</div>
<div class="example-card">
<div class="example-header" @click="toggleExample(1)">
<h4>📈 例题2:进阶题</h4>
<span class="example-toggle">{{ exampleVisible[1] ? '−' : '+' }}</span>
</div>
<div class="example-body" :class="{active: exampleVisible[1]}">
<div class="example-answer"><strong>题目:</strong>找规律填数:15、13、11、9、____</div>
<div class="example-answer">答案:7</div>
<div class="example-explanation">
<strong>解析:</strong><br>
1. 计算每两个数的变化:13-15=-2,11-13=-2<br>
2. 每次都减2(数字越来越小)。<br>
3. 下一个数是:9-2=7。
</div>
</div>
</div>
<div class="example-card">
<div class="example-header" @click="toggleExample(2)">
<h4>⚠️ 例题3:易错题</h4>
<span class="example-toggle">{{ exampleVisible[2] ? '−' : '+' }}</span>
</div>
<div class="example-body" :class="{active: exampleVisible[2]}">
<div class="example-answer"><strong>题目:</strong>找规律填数:1、3、5、____、9</div>
<div class="example-answer">答案:7</div>
<div class="example-explanation">
<strong>解析:</strong><br>
1. 看规律:3-1=2,5-3=2。<br>
2. 每次加2。<br>
3. 5后面应该是5+2=7。<br>
4. 检验:7+2=9✓ 正确!
</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">
<span class="question-number">📝 练习 {{currentQuestion + 1}}/{{practiceQuestions.length}}</span>
<span class="score-display">⭐ {{score}}</span>
</div>
<div class="question-text">{{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,
'shake': answered && selectedOption === index && !option.correct
}"
@click="selectOption(index, option.correct)"
:disabled="answered"
>
{{['A.','B.','C.','D.'][index]}} {{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 fade-in">
<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-top: 5px solid #ff9f43;">
<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>
<span class="score-display">⭐ {{olympiadScore}}</span>
</div>
<div class="question-text">{{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,
'shake': olympiadAnswered && selectedOlympiadOption === index && !option.correct
}"
@click="selectOlympiadOption(index, option.correct)"
:disabled="olympiadAnswered"
>
{{['A.','B.','C.','D.'][index]}} {{option.text}}
</button>
</div>
<div v-if="wrongAttempts > 0 && !olympiadAnswered" class="hint-box fade-in">
<strong>💡 提示:</strong>
{{ wrongAttempts === 1 ? olympiadQuestions[currentOlympiad].hint1 :
(wrongAttempts === 2 ? olympiadQuestions[currentOlympiad].hint2 : olympiadQuestions[currentOlympiad].hint3) }}
</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 fade-in">
<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-scroll">
<div class="secret-card">
<div class="secret-emoji">🔍</div>
<div class="secret-title">两两相减法</div>
<div class="secret-content">把相邻的两个数相减,看看差是不是一样的。这是找规律最直接、最有效的方法!</div>
</div>
<div class="secret-card">
<div class="secret-emoji">🧗</div>
<div class="secret-title">爬楼梯记忆法</div>
<div class="secret-content">把数字想象成楼梯,看是往上爬(越来越大)还是往下走(越来越小),步长就是楼梯的高度。</div>
</div>
<div class="secret-card">
<div class="secret-emoji">✅</div>
<div class="secret-title">检验不忘记</div>
<div class="secret-content">找到规律后,往前再算一个,或者往后多算一步,检查一下对不对,能帮你避开很多陷阱!</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',
exampleVisible: [false, false, false],
directStep: 0,
theoryStep: 0,
// 练习题
currentQuestion: 0,
answered: false,
selectedOption: null,
isCorrect: false,
score: 0,
practiceCompleted: false,
practiceQuestions: [
{ text: '找规律填数:3、6、9、12、____', options: [ {text: 'A.13', correct: false}, {text: 'B.14', correct: false}, {text: 'C.15', correct: true}, {text: 'D.16', correct: false} ], explanation: '12加上3等于15,选C' },
{ text: '找规律填数:10、8、6、4、____', options: [ {text: 'A.3', correct: false}, {text: 'B.2', correct: true}, {text: 'C.1', correct: false}, {text: 'D.0', correct: false} ], explanation: '4-2=2,选B' },
{ text: '找规律填数:1、2、3、4、____', options: [ {text: 'A.4', correct: false}, {text: 'B.5', correct: true}, {text: 'C.6', correct: false}, {text: 'D.7', correct: false} ], explanation: '4+1=5,选B' },
{ text: '找规律填数:20、18、16、14、____', options: [ {text: 'A.10', correct: false}, {text: 'B.11', correct: false}, {text: 'C.12', correct: true}, {text: 'D.13', correct: false} ], explanation: '14-2=12,选C' },
{ text: '找规律填数:5、10、15、____、25', options: [ {text: 'A.17', correct: false}, {text: 'B.18', correct: false}, {text: 'C.20', correct: true}, {text: 'D.22', correct: false} ], explanation: '15+5=20,检查:20+5=25✓,选C' },
{ text: '找规律填数:2、2、2、2、____', options: [ {text: 'A.1', correct: false}, {text: 'B.2', correct: true}, {text: 'C.3', correct: false}, {text: 'D.4', correct: false} ], explanation: '规律是不变,还是2,选B' },
{ text: '找规律填数:1、4、7、10、____', options: [ {text: 'A.11', correct: false}, {text: 'B.12', correct: false}, {text: 'C.13', correct: true}, {text: 'D.14', correct: false} ], explanation: '10+3=13,选C' },
{ text: '找规律填数:9、7、5、____、1', options: [ {text: 'A.2', correct: false}, {text: 'B.3', correct: true}, {text: 'C.4', correct: false}, {text: 'D.5', correct: false} ], explanation: '5-2=3,检查:3-2=1✓,选B' }
],
// 奥数题
currentOlympiad: 0,
olympiadAnswered: false,
selectedOlympiadOption: null,
isOlympiadCorrect: false,
olympiadScore: 0,
olympiadCompleted: false,
wrongAttempts: 0,
olympiadQuestions: [
{ text: '小猴子摘桃子,第一天摘了2个,第二天摘了4个,第三天摘了6个。照这样下去,第五天摘了多少个?', options: [ {text: 'A.8个', correct: false}, {text: 'B.9个', correct: false}, {text: 'C.10个', correct: true}, {text: 'D.12个', correct: false} ], hint1: '每天比前一天多摘几个桃子?', hint2: '每天都多2个,这是一个加2的规律', explanation: '第1天:2个;第2天:4个(加2);第3天:6个(加2);第4天:8个(加2);第5天:10个(加2);答案是10个。', difficulty: 3, difficultyText: '⭐⭐⭐' },
{ text: '花园里的花按照红、红、黄的规律种植。第21朵花是什么颜色?', options: [ {text: 'A.红色', correct: false}, {text: 'B.黄色', correct: true}, {text: 'C.红色或黄色', correct: false}, {text: 'D.不确定', correct: false} ], hint1: '数一数每几朵花为一个循环?', hint2: '红红黄为一组,每3朵循环一次', explanation: '规律:红红黄、红红黄、红红黄...(每3朵为一组);21÷3=7,正好7组;每组的第3朵是黄色;所以第21朵是黄色。', difficulty: 3, difficultyText: '⭐⭐⭐' },
{ text: '小明按照1、2、2、3、3、3、4、4、4、4的规律写数字。他写的第15个数字是几?', options: [ {text: 'A.4', correct: false}, {text: 'B.5', correct: true}, {text: 'C.6', correct: false}, {text: 'D.7', correct: false} ], hint1: '观察规律:1出现几次?2出现几次?', hint2: '数字1出现1次,2出现2次,3出现3次,4出现4次...', explanation: '规律分析:1出现1次(第1个);2出现2次(第2、3个);3出现3次(第4、5、6个);4出现4次(第7、8、9、10个);5出现5次(第11、12、13、14、15个);所以第15个数字是5。', difficulty: 3, difficultyText: '⭐⭐⭐' },
{ text: '按规律填数:1、1、2、2、3、3、____', options: [ {text: 'A.3', correct: false}, {text: 'B.4', correct: true}, {text: 'C.5', correct: false}, {text: 'D.6', correct: false} ], hint1: '看看每个数字出现了几次?', hint2: '每个数都出现了2次', explanation: '规律:每个数字出现两次;1、1、2、2、3、3、4、4...;所以下一个是4。', difficulty: 3, difficultyText: '⭐⭐⭐' },
{ text: '小兔子跳格子:第1次跳1格,第2次跳2格,第3次跳3格。跳4次后,小兔子一共跳了多少格?', options: [ {text: 'A.8格', correct: false}, {text: 'B.9格', correct: false}, {text: 'C.10格', correct: true}, {text: 'D.11格', correct: false} ], hint1: '每次跳的格数和次数一样多', hint2: '要把4次跳的格数全部加起来', explanation: '第1次:1格;第2次:2格;第3次:3格;第4次:4格;一共:1+2+3+4=10格。', difficulty: 3, difficultyText: '⭐⭐⭐' },
{ text: '按规律填数:10、9、9、8、8、8、7、7、7、7、____', options: [ {text: 'A.6', correct: true}, {text: 'B.7', correct: false}, {text: 'C.8', correct: false}, {text: 'D.5', correct: false} ], hint1: '每个数字出现的次数有规律吗?', hint2: '10出现1次,9出现2次,8出现3次,7出现4次', explanation: '规律分析:10出现1次;9出现2次;8出现3次;7出现4次;6应该出现5次;所以下一个是6。', difficulty: 3, difficultyText: '⭐⭐⭐' },
{ text: '排队买票,每3个小朋友中有1个大人陪同。第1个是小朋友,那么第10个人是小朋友还是大人?', options: [ {text: 'A.小朋友', correct: true}, {text: 'B.大人', correct: false}, {text: 'C.可能是小朋友', correct: false}, {text: 'D.可能是大人', correct: false} ], hint1: '排队规律是:3个小朋友、1个大人,循环', hint2: '数一数:1小朋友、2小朋友、3小朋友、4大人、5小朋友...', explanation: '规律:小朋友、小朋友、小朋友、大人、小朋友、小朋友、小朋友、大人...;位置1、2、3:小朋友;位置4:大人;位置5、6、7:小朋友;位置8:大人;位置9、10、11:小朋友;所以第10个是小朋友。', difficulty: 3, difficultyText: '⭐⭐⭐' },
{ text: '数字宝宝排队:2、4、6、8后面应该是几?如果一直排到20,一共有几个数字?', options: [ {text: 'A.10,一共10个', correct: true}, {text: 'B.10,一共9个', correct: false}, {text: 'C.12,一共10个', correct: false}, {text: 'D.10,一共11个', correct: false} ], hint1: '规律是每次加2', hint2: '后面是8+2=10', explanation: '后面是:8+2=10;从2到20:2、4、6、8、10、12、14、16、18、20;数一数:一共10个数字。', difficulty: 3, difficultyText: '⭐⭐⭐' }
]
};
},
mounted() {
this.runDirectAnimation();
},
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.practiceCompleted=false; this.currentQuestion=0; this.score=0; }
if(page === 5 && this.olympiadCompleted) { this.olympiadCompleted=false; this.currentOlympiad=0; this.olympiadScore=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(); }
}
},
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);
}
},
switchDemoTab(tab) {
this.demoTab = tab;
if(tab === 'direct') { this.directStep = 0; this.$nextTick(() => this.runDirectAnimation()); }
else { this.theoryStep = 0; this.$nextTick(() => this.runTheoryAnimation()); }
},
toggleExample(index) {
this.exampleVisible[index] = !this.exampleVisible[index];
},
// 动画逻辑:直接判断 (1, 2, 3, 4, ?)
runDirectAnimation() {
if (typeof gsap === 'undefined') return;
const tl = gsap.timeline();
// Reset
gsap.set(["#step1", "#step2", "#step3", "#step4", "#step5-question"], {opacity: 0, y: 200}); // Initial reset
gsap.set("#step5-question", {visibility: "visible", opacity: 0}); // Fix visibility
gsap.set("#step5-question-text", {visibility: "visible", opacity: 0});
gsap.set("#rabbit", {x: 0, y: 140});
gsap.set("#bubble", {scale: 0});
gsap.set("#bubble-text", {opacity: 0});
// Base state: show numbers sequentially based on step
if(this.directStep >= 0) tl.to("#step1", {opacity:1, y:200, duration:0.5});
if(this.directStep >= 1) tl.to("#step2", {opacity:1, y:200, duration:0.5});
if(this.directStep >= 2) tl.to("#step3", {opacity:1, y:200, duration:0.5});
if(this.directStep >= 3) tl.to("#step4", {opacity:1, y:200, duration:0.5});
// Rabbit Jump Animation for current step
if(this.directStep > 0) {
let prevX = (this.directStep - 1) * 80 - 40; // Approx positions based on visual
let currX = this.directStep * 80 - 40;
if(this.directStep === 1) { prevX = -20; currX = 60; }
if(this.directStep === 2) { prevX = 60; currX = 140; }
if(this.directStep === 3) { prevX = 140; currX = 220; }
tl.fromTo("#rabbit", {x: prevX, y: 140}, {x: currX, y: 140, duration: 0.5, ease: "power1.inOut"});
tl.to("#rabbit", {y: 100, duration: 0.25, yoyo: true, repeat: 1}, "<"); // Jump
// Bubble pop
tl.fromTo("#bubble", {scale:0, cx: currX, cy: 100}, {scale:1.5, duration: 0.3, ease:"elastic.out"});
tl.fromTo("#bubble-text", {opacity:0, x: currX, y: 105}, {opacity:1, duration: 0.1}, "<");
}
if(this.directStep === 3) {
tl.to("#step5-question", {opacity: 1, duration: 0.5});
tl.to("#step5-question-text", {opacity: 1, duration: 0.5}, "<");
}
},
nextDirectStep() { if(this.directStep < 3) { this.directStep++; this.runDirectAnimation(); } },
prevDirectStep() { if(this.directStep > 0) { this.directStep--; this.runDirectAnimation(); } },
// 动画逻辑:位值原理 (1, 3, 5, 7, ?)
runTheoryAnimation() {
if (typeof gsap === 'undefined') return;
const tl = gsap.timeline();
// Reset same logic as direct but with different IDs and +2
gsap.set(["#theory-step0", "#theory-step1", "#theory-step2", "#theory-step3", "#theory-step4-question"], {opacity: 0});
gsap.set("#theory-step4-question", {visibility: "visible", opacity: 0});
gsap.set("#theory-step4-question-text", {visibility: "visible", opacity: 0});
gsap.set("#theory-rabbit", {x: 20, y: 140});
gsap.set("#theory-bubble", {scale: 0});
gsap.set("#theory-bubble-text", {opacity: 0});
if(this.theoryStep >= 0) tl.to("#theory-step0", {opacity:1, duration:0.5});
if(this.theoryStep >= 1) tl.to("#theory-step1", {opacity:1, duration:0.5});
if(this.theoryStep >= 2) tl.to("#theory-step2", {opacity:1, duration:0.5});
if(this.theoryStep >= 3) tl.to("#theory-step3", {opacity:1, duration:0.5});
if(this.theoryStep > 0) {
let prevX = 20 + (this.theoryStep - 1) * 80;
let currX = 20 + this.theoryStep * 80;
tl.fromTo("#theory-rabbit", {x: prevX, y: 140}, {x: currX, y: 140, duration: 0.5, ease: "power1.inOut"});
tl.to("#theory-rabbit", {y: 90, duration: 0.25, yoyo: true, repeat: 1}, "<"); // Higher jump for +2?
tl.fromTo("#theory-bubble", {scale:0, cx: currX, cy: 90}, {scale:1.5, duration: 0.3, ease:"elastic.out"});
tl.fromTo("#theory-bubble-text", {opacity:0, x: currX, y: 95}, {opacity:1, duration: 0.1}, "<");
}
if(this.theoryStep === 3) {
tl.to("#theory-step4-question", {opacity: 1, duration: 0.5});
tl.to("#theory-step4-question-text", {opacity: 1, duration: 0.5}, "<");
}
},
nextTheoryStep() { if(this.theoryStep < 3) { this.theoryStep++; this.runTheoryAnimation(); } },
prevTheoryStep() { if(this.theoryStep > 0) { this.theoryStep--; this.runTheoryAnimation(); } },
// 练习题逻辑
selectOption(index, correct) {
if (this.answered) return;
this.answered = true;
this.selectedOption = index;
this.isCorrect = correct;
if (correct) {
this.score += 20;
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;
confetti({ particleCount: 150, spread: 80, origin: { y: 0.6 } });
} else {
// 震动反馈在CSS类中处理
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 生成。
登录后可复制完整代码