<!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>第02讲:乘法口诀与图形应用</title>
<style>
/* =========================================
基础重置 & 全局样式优化
========================================= */
* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
::-webkit-scrollbar { display: none; width: 0 !important; height: 0 !important; }
* { -ms-overflow-style: none; scrollbar-width: none; }
html, body {
margin: 0; padding: 0;
/* 升级:柔和的全局渐变背景 */
background: linear-gradient(180deg, #fdfbfb 0%, #ebedee 100%);
overflow: hidden;
height: 100vh;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}
/* 主容器 */
#app {
height: 100vh;
max-width: 480px;
margin: 0 auto;
background: transparent; /* 透明以显示body渐变 */
display: flex;
flex-direction: column;
position: relative;
}
.content-area {
flex: 1;
overflow-y: auto;
padding-bottom: 90px; /* 给底部导航留更多空间 */
scroll-behavior: smooth;
}
/* 装饰背景:保留点阵但减淡 */
.dot-pattern-bg {
background-image: radial-gradient(#cbd5e1 1.5px, transparent 1.5px);
background-size: 24px 24px;
}
/* =========================================
UI 组件升级:圆润、微投影
========================================= */
/* 通用卡片样式 - 微投影风格 */
.card-base {
background: white;
border-radius: 24px; /* 更圆润 */
/* SVG风格阴影:多层阴影叠加实现柔和立体感 */
box-shadow:
0 4px 6px -1px rgba(0, 0, 0, 0.05),
0 10px 15px -3px rgba(0, 0, 0, 0.05),
0 0 0 1px rgba(0,0,0,0.02);
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
/* 底部导航 - 悬浮胶囊风格 */
.bottom-nav {
position: fixed;
bottom: 20px; /* 悬浮起来 */
left: 50%;
transform: translateX(-50%);
width: 90%; /* 不占满全宽 */
max-width: 440px;
height: 65px;
background: rgba(255, 255, 255, 0.95); /* 毛玻璃感 */
backdrop-filter: blur(10px);
border-radius: 35px; /* 胶囊形状 */
display: flex;
justify-content: space-around;
align-items: center;
z-index: 9999;
box-shadow: 0 10px 25px rgba(0,0,0,0.08);
border: 1px solid rgba(255,255,255,0.5);
}
.nav-item { flex: 1; display: flex; flex-direction: column; align-items: center; cursor: pointer; transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1); color: #94a3b8; }
.nav-item.active { color: #667eea; transform: translateY(-4px); } /* 选中上浮 */
.nav-icon { font-size: 20px; margin-bottom: 2px; }
.nav-label { font-size: 10px; font-weight: 500; }
/* 页面容器 */
.page-container { padding: 24px 20px; }
.page-title { font-size: 24px; font-weight: 800; color: #1e293b; margin-bottom: 20px; text-align: center; letter-spacing: -0.5px; }
/* 概念页组件 */
.emoji-intro { font-size: 72px; text-align: center; margin: 30px 0; filter: drop-shadow(0 4px 6px rgba(0,0,0,0.1)); }
.story-box {
background: #fff;
padding: 20px;
border-radius: 20px;
margin-bottom: 25px;
line-height: 1.8;
color: #475569;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05);
border: 1px solid rgba(0,0,0,0.03);
}
.concept-card {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 25px;
border-radius: 24px;
margin-bottom: 20px;
box-shadow: 0 10px 25px rgba(118, 75, 162, 0.3); /* 彩色投影 */
position: relative;
overflow: hidden;
}
/* 增加纹理 */
.concept-card::before {
content: ''; position: absolute; top: -50%; left: -50%; width: 200%; height: 200%;
background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 60%);
transform: rotate(30deg);
}
.listen-btn {
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
color: white; border: none; padding: 14px 45px; border-radius: 50px;
font-size: 16px; font-weight: bold; cursor: pointer; display: block; margin: 30px auto 0;
transition: transform 0.2s;
box-shadow: 0 8px 20px rgba(245, 87, 108, 0.35);
}
.listen-btn:active { transform: scale(0.95); }
/* Tab 导航 */
.tab-nav { display: flex; background: #f1f5f9; border-radius: 16px; padding: 4px; margin-bottom: 25px; border: none; }
.tab-item {
flex: 1; padding: 10px; text-align: center; cursor: pointer;
border-radius: 12px; font-weight: 600; color: #64748b; transition: all 0.3s ease;
border: none;
}
.tab-item.active {
background: white; color: #667eea;
box-shadow: 0 4px 6px rgba(0,0,0,0.05);
}
/* 动画区域 */
.animation-area {
background: white;
border-radius: 24px;
padding: 20px; height: 360px;
position: relative;
display: flex; align-items: center; justify-content: center;
margin-bottom: 20px; overflow: hidden;
box-shadow: inset 0 2px 6px rgba(0,0,0,0.03); /* 内阴影增加深度 */
border: 1px solid #f1f5f9;
}
.svg-container { width: 100%; height: 100%; }
/* 公式和控制栏 */
.math-area {
background: white;
border: none;
/* 渐变边框效果 */
background-image: linear-gradient(white, white), linear-gradient(135deg, #667eea, #764ba2);
background-origin: border-box;
background-clip: content-box, border-box;
border: 2px solid transparent;
border-radius: 20px;
padding: 15px; margin-bottom: 15px;
min-height: 90px;
display: flex; align-items: center; justify-content: center;
box-shadow: 0 8px 20px rgba(102, 126, 234, 0.15);
}
.math-formula { font-size: 24px; font-weight: 800; color: #333; text-align: center; }
.step-explanation {
background: #f8fafc; padding: 18px; border-radius: 16px;
color: #475569; font-size: 15px; text-align: center; margin-bottom: 20px; line-height: 1.6;
border: 1px solid #e2e8f0;
}
.step-btn {
position: absolute; top: 50%; transform: translateY(-50%); z-index: 100;
background: rgba(255, 255, 255, 0.9);
color: #667eea; border: 1px solid #e2e8f0;
width: 44px; height: 44px; border-radius: 50%;
font-size: 18px; cursor: pointer;
box-shadow: 0 4px 10px rgba(0,0,0,0.1);
display: flex; align-items: center; justify-content: center;
}
.step-btn:hover { background: white; transform: translateY(-50%) scale(1.1); }
.step-btn-prev { left: 15px; }
.step-btn-next { right: 15px; }
/* 讲解 & 练习卡片 */
.example-card, .question-card {
background: white; border-radius: 24px; padding: 25px; margin-bottom: 20px;
box-shadow: 0 10px 20px rgba(0,0,0,0.03), 0 2px 6px rgba(0,0,0,0.02);
border: 1px solid rgba(0,0,0,0.02);
}
.example-header { display: flex; justify-content: space-between; align-items: center; cursor: pointer; padding-bottom: 5px;}
.example-title { font-weight: 700; color: #3b82f6; font-size: 17px; }
.question-text { font-size: 19px; margin-bottom: 25px; line-height: 1.6; color: #1e293b; font-weight: 600;}
/* 选项按钮 */
.options-container { display: flex; flex-direction: column; gap: 15px; margin-bottom: 20px; }
.option-btn {
padding: 18px 20px;
border: 2px solid #f1f5f9;
border-radius: 16px;
background: #fff;
font-size: 16px;
color: #475569;
text-align: left;
cursor: pointer;
transition: all 0.2s cubic-bezier(0.25, 0.8, 0.25, 1);
position: relative;
overflow: hidden;
}
.option-btn:active { transform: scale(0.98); background: #f8fafc; }
.option-btn.correct { background-color: #ecfdf5; border-color: #10b981; color: #047857; font-weight: bold; }
.option-btn.wrong { background-color: #fef2f2; border-color: #ef4444; color: #b91c1c; }
.next-btn {
display: block; width: 100%; padding: 18px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white; border: none; border-radius: 18px;
font-size: 17px; font-weight: bold;
cursor: pointer; margin-top: 25px;
box-shadow: 0 8px 20px rgba(102, 126, 234, 0.3);
transition: transform 0.2s;
}
/* 难度徽章 */
.difficulty-badge { padding: 4px 10px; border-radius: 12px; font-weight: bold; }
/* =========================================
新版秘籍卡片 (左右滑动) - 核心修改区域
========================================= */
/* 1. 滑动容器 */
.secrets-scroll-container {
display: flex;
overflow-x: auto; /* 允许横向滚动 */
scroll-snap-type: x mandatory; /* 强制吸附 */
scroll-behavior: smooth;
gap: 20px; /* 卡片间距 */
padding: 20px 20px 40px 20px; /* 底部留空间给投影 */
height: calc(100vh - 150px); /* 占据大部分高度 */
align-items: center; /* 垂直居中 */
}
/* 2. 秘籍卡片本体 */
.secret-card {
flex: 0 0 100%; /* 关键:强制宽度为容器的100% */
width: 100%;
min-height: 500px; /* 按照要求 */
/* 按照要求:渐变背景 */
background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);
border-radius: 30px; /* 更大的圆角 */
padding: 40px 30px;
/* 按照要求:SVG阴影/微投影 */
/* 这里使用多层box-shadow模拟高质量SVG阴影效果 */
box-shadow:
0 20px 40px -10px rgba(0,0,0,0.15),
0 0 0 1px rgba(255,255,255,0.4) inset;
scroll-snap-align: center; /* 滚动吸附点 */
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
position: relative;
transform-style: preserve-3d;
}
/* 秘籍内容样式 */
.secret-icon {
font-size: 100px; margin-bottom: 30px;
filter: drop-shadow(0 10px 10px rgba(0,0,0,0.1));
transform: translateZ(20px); /* 视差效果 */
}
.secret-card h3 {
font-size: 28px; color: #fff; margin: 0 0 20px 0;
text-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.secret-card p {
font-size: 20px; line-height: 1.8; color: rgba(255,255,255,0.95);
font-weight: 500; margin: 0;
}
/* 滑动提示 */
.swipe-hint {
text-align: center; color: #94a3b8; font-size: 12px; margin-top: -10px; opacity: 0.8;
}
@keyframes shake {
0%, 100% { transform: translateX(0); }
10%, 30%, 50%, 70%, 90% { transform: translateX(-5px); }
20%, 40%, 60%, 80% { transform: translateX(5px); }
}
</style>
</head>
<body>
<div id="app">
<div class="content-area">
<div v-show="currentPage === 1" class="intro-page page-container dot-pattern-bg">
<div class="page-title">乘法口诀与图形应用</div>
<div class="emoji-intro">📦</div>
<div class="story-box">
<p>小朋友,老师有一大盒糖果,想平均分给班上的小朋友。如果横着数一排有5颗糖,竖着数一共有3排。我可以用加法:5+5+5=15颗。但如果有很多很多排,这样加就太慢啦!</p>
<p>这时候就需要“乘法”这个魔法来帮忙!只要用乘法口诀“三五十五”,一下子就知道是15颗糖啦!</p>
</div>
<div class="concept-card">
<h3>📚 核心概念</h3>
<p><strong>乘法</strong>:就是好多个相同的数加在一起的简便写法。</p>
<p style="margin-top:8px;"><strong>方阵</strong>:排得整整齐齐的队伍,横着看是行,竖着看是列。</p>
<p style="margin-top:8px;"><strong>乘法口诀</strong>:帮助我们快速算出乘法结果的神奇咒语。</p>
</div>
<button class="listen-btn" @click="speak('乘法就是好多个相同的数加在一起的简便写法。\n方阵是排得整整齐齐的队伍。\n乘法口诀是帮助我们快速算出乘法结果的神奇咒语。')">🔊 听老师讲解</button>
</div>
<div v-show="currentPage === 2" class="demo-page page-container">
<div class="tab-nav">
<div class="tab-item" :class="{active: demoTab === 'direct'}" @click="switchDemoTab('direct')">星星方阵演示</div>
</div>
<div class="demo-section" :class="{active: demoTab === 'direct'}">
<div class="animation-area">
<button class="step-btn step-btn-prev" @click="prevDirectStep" :disabled="directStep === 0">◀</button>
<button class="step-btn step-btn-next" @click="nextDirectStep" :disabled="directStep === 3">▶</button>
<svg class="svg-container" viewBox="0 0 400 330">
<rect x="50" y="50" width="300" height="180" fill="none" stroke="#cbd5e1" stroke-width="2" stroke-dasharray="5,5" />
<g id="star-grid">
<g v-for="i in 4">
<use v-for="j in 3" :href="'#star' + ((i-1)*3 + j)" :x="50 + (i-1)*75" :y="50 + (j-1)*60" />
</g>
</g>
<defs>
<symbol id="starSymbol" viewBox="0 0 40 40">
<path d="M20 3 L26 15 L39 17 L29 27 L31 40 L20 33 L9 40 L11 27 L1 17 L14 15 Z" fill="#fbbf24" stroke="#f59e0b" stroke-width="2" />
</symbol>
</defs>
<use id="star1" xlink:href="#starSymbol" x="65" y="65" opacity="0" />
<use id="star2" xlink:href="#starSymbol" x="65" y="125" opacity="0" />
<use id="star3" xlink:href="#starSymbol" x="65" y="185" opacity="0" />
<use id="star4" xlink:href="#starSymbol" x="140" y="65" opacity="0" />
<use id="star5" xlink:href="#starSymbol" x="140" y="125" opacity="0" />
<use id="star6" xlink:href="#starSymbol" x="140" y="185" opacity="0" />
<use id="star7" xlink:href="#starSymbol" x="215" y="65" opacity="0" />
<use id="star8" xlink:href="#starSymbol" x="215" y="125" opacity="0" />
<use id="star9" xlink:href="#starSymbol" x="215" y="185" opacity="0" />
<use id="star10" xlink:href="#starSymbol" x="290" y="65" opacity="0" />
<use id="star11" xlink:href="#starSymbol" x="290" y="125" opacity="0" />
<use id="star12" xlink:href="#starSymbol" x="290" y="185" opacity="0" />
<text id="formulaText" x="200" y="270" text-anchor="middle" font-size="24" fill="#333" font-weight="bold" opacity="0"></text>
<text id="formulaText2" x="200" y="300" text-anchor="middle" font-size="20" fill="#764ba2" opacity="0"></text>
</svg>
</div>
<div class="math-area">
<div class="math-formula">{{ directStepFormulas[directStep] }}</div>
</div>
<div class="step-explanation">{{ directStepExplanations[directStep] }}</div>
</div>
</div>
<div v-show="currentPage === 3" class="explain-page page-container">
<div class="tab-nav">
<div class="tab-item" :class="{active: explainTab === 'basic'}" @click="explainTab='basic'">基础题</div>
<div class="tab-item" :class="{active: explainTab === 'advance'}" @click="explainTab='advance'">进阶题</div>
<div class="tab-item" :class="{active: explainTab === 'tricky'}" @click="explainTab='tricky'">易错题</div>
</div>
<div v-show="explainTab === 'basic'">
<div class="example-card">
<div class="example-header" @click="toggleExample('basic')">
<div class="example-title">例题1:基础题</div>
<div class="toggle-btn">{{ exampleOpen.basic ? '▲ 收起' : '▼ 展开' }}</div>
</div>
<div class="example-content" v-show="exampleOpen.basic">
<div class="question" style="margin-top:10px;"><strong>题目</strong>:把 4 + 4 + 4 + 4 + 4 改写成乘法算式。</div>
<div class="answer"><strong>答案</strong>:4 × 5 = 20</div>
<div class="explanation"><strong>解析</strong>:这里有 5 个 4 相加,所以是 4 乘以 5。</div>
</div>
</div>
</div>
<div v-show="explainTab === 'advance'">
<div class="example-card">
<div class="example-header" @click="toggleExample('advance')">
<div class="example-title">例题2:进阶题</div>
<div class="toggle-btn">{{ exampleOpen.advance ? '▲ 收起' : '▼ 展开' }}</div>
</div>
<div class="example-content" v-show="exampleOpen.advance">
<div class="question" style="margin-top:10px;"><strong>题目</strong>:看图列式:★★★ ★★★ ★★★ ★★</div>
<div class="answer"><strong>答案</strong>:3 × 3 + 2 = 11 或 3 × 4 - 1 = 11</div>
<div class="explanation"><strong>解析</strong>:可以看作 3 组 3 颗星再加上 2 颗,或者 4 组 3 颗星减去 1 颗。</div>
</div>
</div>
</div>
<div v-show="explainTab === 'tricky'">
<div class="example-card">
<div class="example-header" @click="toggleExample('tricky')">
<div class="example-title">例题3:易错题</div>
<div class="toggle-btn">{{ exampleOpen.tricky ? '▲ 收起' : '▼ 展开' }}</div>
</div>
<div class="example-content" v-show="exampleOpen.tricky">
<div class="question" style="margin-top:10px;"><strong>题目</strong>:6 × 3 读作什么?</div>
<div class="answer"><strong>答案</strong>:6 乘 3</div>
<div class="explanation"><strong>解析</strong>:【易错点】不能读作“6 乘以 3”(现在的数学规范统称“乘”),也不能读作“3 乘 6”(虽然结果一样,但顺序不同)。</div>
</div>
</div>
</div>
</div>
<div v-show="currentPage === 4" class="practice-page page-container">
<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
}"
@click="selectOption(index, option.correct)"
:disabled="answered"
>
{{option.text}}
</button>
</div>
<div v-if="answered" class="feedback-area" :class="isCorrect ? 'feedback-correct' : 'feedback-wrong'" style="padding:15px; border-radius:12px; margin-top:15px; background:#f0fdf4;">
<div v-if="isCorrect" style="color:#15803d;">
<strong>🎉 太棒了!</strong><br>
{{practiceQuestions[currentQuestion].explanation}}
</div>
<div v-else style="color:#b91c1c;">
<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" style="text-align:center; padding:50px 20px;">
<div class="completion-emoji" style="font-size:80px; margin-bottom:20px;">🎊</div>
<div class="completion-title">课内练习完成!</div>
<div class="final-score" style="font-size:48px; font-weight:bold; color:#667eea; margin:20px 0;">{{score}}分</div>
<button class="restart-btn" @click="switchPage(5)" style="background:linear-gradient(135deg, #667eea, #764ba2); color:white; border:none; padding:15px 40px; border-radius:30px; font-size:18px;">挑战奥数题 →</button>
</div>
</div>
<div v-show="currentPage === 5" class="practice-page page-container">
<div v-if="!olympiadCompleted">
<div class="question-card">
<div class="question-header">
<div>
<span class="question-number">第 {{currentOlympiad + 1}}/{{olympiadQuestions.length}} 题</span>
<span class="difficulty-badge" :class="'difficulty-' + olympiadQuestions[currentOlympiad].difficulty" :style="{backgroundColor: olympiadQuestions[currentOlympiad].difficulty===1?'#d1fae5':(olympiadQuestions[currentOlympiad].difficulty===2?'#fef3c7':'#fee2e2'), color: olympiadQuestions[currentOlympiad].difficulty===1?'#065f46':(olympiadQuestions[currentOlympiad].difficulty===2?'#92400e':'#991b1b')}">
{{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
}"
@click="selectOlympiadOption(index, option.correct)"
:disabled="olympiadAnswered"
>
{{option.text}}
</button>
</div>
<div v-if="wrongAttempts > 0 && !olympiadAnswered">
<div class="hint-box" v-if="wrongAttempts === 1" style="background:#fef3c7; padding:12px; border-radius:8px; color:#92400e; margin-top:10px;">
<strong>💡 提示1:</strong> {{olympiadQuestions[currentOlympiad].hint1}}
</div>
<div class="hint-box" v-if="wrongAttempts === 2" style="background:#fef3c7; padding:12px; border-radius:8px; color:#92400e; margin-top:10px;">
<strong>💡 提示2:</strong> {{olympiadQuestions[currentOlympiad].hint2}}
</div>
</div>
<div v-if="olympiadAnswered" class="feedback-area" style="padding:15px; border-radius:12px; margin-top:15px;" :style="{backgroundColor: isOlympiadCorrect?'#ecfdf5':'#fef2f2', color: isOlympiadCorrect?'#047857':'#b91c1c'}">
<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" style="text-align:center; padding:50px 20px;">
<div class="completion-emoji" style="font-size:80px; margin-bottom:20px;">🏆</div>
<div class="completion-title">奥数挑战完成!</div>
<div class="final-score" style="font-size:48px; font-weight:bold; color:#667eea; margin:20px 0;">{{olympiadScore}}分</div>
<button class="restart-btn" @click="switchPage(6)" style="background:linear-gradient(135deg, #f093fb, #f5576c); color:white; border:none; padding:15px 40px; border-radius:30px; font-size:18px;">查看通关秘籍 →</button>
</div>
</div>
<div v-show="currentPage === 6">
<div class="secrets-scroll-container">
<div class="secret-card">
<div class="secret-icon">⏩</div>
<h3>秘籍1:乘法是加法的快进键</h3>
<p>求几个相同加数的和,用乘法算最快。<br>比如 5+5+5+5 直接写成 5×4。</p>
</div>
<div class="secret-card" style="background: linear-gradient(135deg, #fbc2eb 0%, #a6c1ee 100%);">
<div class="secret-icon">🧠</div>
<h3>秘籍2:口诀要记牢</h3>
<p>熟背乘法口诀,看见算式就能报出答案。<br>它是计算速度变快的秘密武器!</p>
</div>
<div class="secret-card" style="background: linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%);">
<div class="secret-icon">🎯</div>
<h3>秘籍3:方阵问题有窍门</h3>
<p>遇到方阵不要慌:<br>正方形方阵四周人数 = (边长-1)×4。<br>实心方阵总人数 = 边长×边长。</p>
</div>
</div>
<div class="swipe-hint">← 左右滑动查看更多秘籍 →</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: 'basic',
directStep: 0,
theoryStep: 0,
exampleOpen: { basic: true, advance: false, tricky: false },
// 演示步骤公式和说明
directStepFormulas: [
'让我们来看看这个星星方阵!',
'横着看,一行有 4 颗星',
'竖着看,一共有 3 行',
'4 × 3 = 12(口诀:三四十二)'
],
directStepExplanations: [
'屏幕上出现了一个 3 行 4 列的星星方阵,让我们一起来数一数。',
'我们先数第一行,1、2、3、4,一行有 4 颗星。记作一个4。',
'像这样的行数一共有 3 行,那就是 4+4+4。',
'所以用乘法表示就是 4 × 3 = 12,口诀就是:三四十二!'
],
// 练习题数据 (完全保留原数据)
practiceQuestions: [
{ text: "5 个 3 相加是多少?", options: [{text: "A. 8", correct: false}, {text: "B. 15", correct: true}, {text: "C. 12", correct: false}, {text: "D. 10", correct: false}], explanation: "三五十五。" },
{ text: "4 × 6 表示什么?", options: [{text: "A. 4 个 6 相加", correct: true}, {text: "B. 4 加 6", correct: false}, {text: "C. 6 个 6 相加", correct: false}, {text: "D. 4 个 4 相加", correct: false}], explanation: "可以是4个6,也可以是6个4,选项中只有A符合。" },
{ text: "下面的图形中,哪一个可以用 3 × 4 表示?<br> A. ▲▲▲ ▲▲▲ <br> B. ▲▲▲ ▲▲▲ ▲▲▲ ▲▲▲ <br> C. ▲▲ ▲▲ ▲▲ <br> D. ▲▲▲ ▲▲", options: [{text: "A", correct: false}, {text: "B", correct: true}, {text: "C", correct: false}, {text: "D", correct: false}], explanation: "B选项是4组,每组3个。" },
{ text: "补全口诀:四( )三十六", options: [{text: "A. 八", correct: false}, {text: "B. 九", correct: true}, {text: "C. 七", correct: false}, {text: "D. 六", correct: false}], explanation: "四九三十六。" },
{ text: "一个正方形有 4 个角,5 个正方形有几个角?", options: [{text: "A. 9", correct: false}, {text: "B. 16", correct: false}, {text: "C. 20", correct: true}, {text: "D. 25", correct: false}], explanation: "四五二十。" },
{ text: "计算 2 × 5 + 5", options: [{text: "A. 10", correct: false}, {text: "B. 12", correct: false}, {text: "C. 15", correct: true}, {text: "D. 20", correct: false}], explanation: "3 × 5 = 15。" },
{ text: "7 + 7 + 7 + 7 + 6 可以写成?", options: [{text: "A. 7 × 5", correct: false}, {text: "B. 7 × 4 + 6", correct: true}, {text: "C. 7 × 5 + 1", correct: false}, {text: "D. 7 × 6", correct: false}], explanation: "所以是 4 个 7 加上一个 6。" },
{ text: "() × 5 < 24,括号里最大能填几?", options: [{text: "A. 3", correct: false}, {text: "B. 4", correct: true}, {text: "C. 5", correct: false}, {text: "D. 6", correct: false}], explanation: "25 比 24 大了,所以只能填 4。" }
],
currentQuestion: 0,
answered: false,
selectedOption: null,
isCorrect: false,
score: 0,
practiceCompleted: false,
// 奥数题数据 (完全保留原数据)
olympiadQuestions: [
{ text: "把一根绳子对折再对折,剪一刀,绳子变成了几段?(不剪断两头)", options: [{text: "A. 3", correct: false}, {text: "B. 4", correct: false}, {text: "C. 5", correct: true}, {text: "D. 9", correct: false}], hint1: "对折再对折是4层。", hint2: "中间剪一刀,每一层都断了。", hint3: "画图看看,中间有3小段,两头各1段,共5段。", explanation: "完整解析:对折两次后变成4层,中间剪一刀,每一层都被剪成两段,但最外面的两层各有一段是连在一起的(不剪断两头),所以得到5段。", difficulty: 2, difficultyText: "⭐⭐" },
{ text: "同学们排方阵做操,最外层一共有 20 人,这个方阵一共有多少人?(实心方阵)", options: [{text: "A. 25", correct: false}, {text: "B. 36", correct: true}, {text: "C. 49", correct: false}, {text: "D. 64", correct: false}], hint1: "(20 + 4) ÷ 4 = 6,每边有6人。", hint2: "方阵总人数 = 边长 × 边长。", hint3: "6 × 6 = 36。", explanation: "完整解析:最外层人数 = (每边人数 - 1) × 4。所以每边人数 = (20 ÷ 4) + 1 = 6。总人数 = 6 × 6 = 36。", difficulty: 3, difficultyText: "⭐⭐⭐" },
{ text: "一条毛毛虫长到成虫,每天长一倍,4天长到 20 厘米,问长到 5 厘米时是第几天?", options: [{text: "A. 1", correct: false}, {text: "B. 2", correct: true}, {text: "C. 3", correct: false}, {text: "D. 4", correct: false}], hint1: "第4天 20cm,第3天是它的一半 10cm。", hint2: "第2天是 10cm 的一半。", hint3: "第2天是 5cm。", explanation: "完整解析:倒推法。第4天:20cm。第3天:20 ÷ 2 = 10cm。第2天:10 ÷ 2 = 5cm。所以是第2天。", difficulty: 3, difficultyText: "⭐⭐⭐" },
{ text: "○ + ○ + △ = 18,△ = ○ + ○ + ○ + ○,求 △ = ?", options: [{text: "A. 3", correct: false}, {text: "B. 6", correct: false}, {text: "C. 12", correct: true}, {text: "D. 9", correct: false}], hint1: "把第一个算式里的△换成4个○。", hint2: "○ + ○ + (○+○+○+○) = 18,6个○是18,○=3。", hint3: "△ = 4 × 3 = 12。", explanation: "完整解析:由△=4○代入第一个算式:○+○+4○=18 → 6○=18 → ○=3。所以△=4×3=12。", difficulty: 2, difficultyText: "⭐⭐" },
{ text: "锯一根木头,锯成 4 段需要 12 分钟,如果锯成 6 段需要几分钟?", options: [{text: "A. 18", correct: false}, {text: "B. 20", correct: true}, {text: "C. 24", correct: false}, {text: "D. 15", correct: false}], hint1: "锯成4段需要锯3次,每次 12÷3=4 分钟。", hint2: "锯成6段需要锯5次。", hint3: "5 × 4 = 20 分钟。", explanation: "完整解析:锯成4段只需锯3次,每次用时12÷3=4分钟。锯成6段需要锯5次,总时间5×4=20分钟。", difficulty: 2, difficultyText: "⭐⭐" },
{ text: "2 × 3 × 4 × 5 × 0 + 1 等于多少?", options: [{text: "A. 120", correct: false}, {text: "B. 121", correct: false}, {text: "C. 1", correct: true}, {text: "D. 0", correct: false}], hint1: "任何数乘以0都得0。", hint2: "前面一大串乘起来最后是0。", hint3: "0 + 1 = 1。", explanation: "完整解析:在连乘中,只要有一个乘数是0,结果就是0。所以2×3×4×5×0=0,然后0+1=1。", difficulty: 1, difficultyText: "⭐" },
{ text: "在正方形池塘四周种树,四个角都要种,每边种 5 棵,一共需要种多少棵?", options: [{text: "A. 20", correct: false}, {text: "B. 16", correct: true}, {text: "C. 15", correct: false}, {text: "D. 25", correct: false}], hint1: "四个角是共用的。", hint2: "(5 - 1) × 4。", hint3: "4 × 4 = 16棵。", explanation: "完整解析:封闭路线植树问题。每边5棵,但角上的树被两边共用。实际每边只需种5-1=4棵新树(因为角已固定)。总棵数:4×4=16棵。", difficulty: 2, difficultyText: "⭐⭐" },
{ text: "找规律填数:1, 4, 9, 16, ( )", options: [{text: "A. 20", correct: false}, {text: "B. 24", correct: false}, {text: "C. 25", correct: true}, {text: "D. 30", correct: false}], hint1: "1×1, 2×2, 3×3...", hint2: "16是4×4。", hint3: "下一个是5×5=25。", explanation: "完整解析:这是一个平方数数列。1=1×1,4=2×2,9=3×3,16=4×4,所以下一个是5×5=25。", difficulty: 1, difficultyText: "⭐" }
],
currentOlympiad: 0,
olympiadAnswered: false,
selectedOlympiadOption: null,
isOlympiadCorrect: false,
olympiadScore: 0,
olympiadCompleted: false,
wrongAttempts: 0
};
},
methods: {
switchPage(page) {
this.stopSpeak();
this.currentPage = page;
if (page === 2) {
this.directStep = 0;
this.theoryStep = 0;
this.runDirectAnimation();
}
if (page === 4) {
this.currentQuestion = 0;
this.answered = false;
this.selectedOption = null;
this.isCorrect = false;
this.score = 0;
this.practiceCompleted = false;
}
if (page === 5) {
this.currentOlympiad = 0;
this.olympiadAnswered = false;
this.selectedOlympiadOption = null;
this.isOlympiadCorrect = 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.stopSpeak();
this.demoTab = tab;
},
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);
}
},
runDirectAnimation() {
if (typeof gsap === 'undefined') return;
gsap.killTweensOf("#star1, #star2, #star3, #star4, #star5, #star6, #star7, #star8, #star9, #star10, #star11, #star12, #formulaText, #formulaText2");
const tl = gsap.timeline();
if (this.directStep === 0) {
tl.set("#star1, #star2, #star3, #star4, #star5, #star6, #star7, #star8, #star9, #star10, #star11, #star12", { opacity: 0 });
tl.set("#formulaText, #formulaText2", { opacity: 0 });
document.getElementById('formulaText').textContent = '';
document.getElementById('formulaText2').textContent = '';
} else if (this.directStep === 1) {
tl.to("#star1", { opacity: 1, duration: 0.3, ease: "power2.in" });
tl.to("#star2", { opacity: 1, duration: 0.3, ease: "power2.in" }, "+=0.1");
tl.to("#star3", { opacity: 1, duration: 0.3, ease: "power2.in" }, "+=0.1");
tl.to("#star4", { opacity: 1, duration: 0.3, ease: "power2.in" }, "+=0.1");
tl.to("#star1, #star2, #star3, #star4", { scale: 1.2, duration: 0.2, repeat: 1, yoyo: true });
tl.set("#formulaText", { textContent: '一行有 4 颗星', opacity: 0 });
tl.to("#formulaText", { opacity: 1, duration: 0.5, ease: "power2.out" });
} else if (this.directStep === 2) {
tl.to("#star1, #star2, #star3, #star4", { opacity: 1, duration: 0.3, ease: "power2.in" });
tl.to("#star1, #star2, #star3, #star4", { scale: 1.2, duration: 0.2, repeat: 1, yoyo: true });
tl.to("#formulaText", { textContent: '4', opacity: 1, duration: 0.3 });
tl.to("#star5, #star6, #star7, #star8", { opacity: 1, duration: 0.3, ease: "power2.in" }, "+=0.3");
tl.to("#star5, #star6, #star7, #star8", { scale: 1.2, duration: 0.2, repeat: 1, yoyo: true });
tl.to("#formulaText", { textContent: '4 + 4', duration: 0.3 }, "<");
tl.to("#star9, #star10, #star11, #star12", { opacity: 1, duration: 0.3, ease: "power2.in" }, "+=0.3");
tl.to("#star9, #star10, #star11, #star12", { scale: 1.2, duration: 0.2, repeat: 1, yoyo: true });
tl.to("#formulaText", { textContent: '4 + 4 + 4', duration: 0.3 }, "<");
} else if (this.directStep === 3) {
tl.set("#star1, #star2, #star3, #star4, #star5, #star6, #star7, #star8, #star9, #star10, #star11, #star12", { opacity: 1 });
tl.set("#formulaText", { opacity: 0 });
tl.set("#formulaText2", { opacity: 0 });
tl.set("#formulaText", { textContent: '4 × 3 = 12' });
tl.to("#formulaText", { opacity: 1, duration: 0.5, ease: "bounce.out" });
tl.set("#formulaText2", { textContent: '口诀:三四十二' });
tl.to("#formulaText2", { opacity: 1, duration: 0.5, ease: "power2.out" }, "+=0.3");
}
},
nextDirectStep() {
if (this.directStep < 3) {
this.directStep++;
this.runDirectAnimation();
}
},
prevDirectStep() {
if (this.directStep > 0) {
this.directStep--;
this.runDirectAnimation();
}
},
toggleExample(key) {
this.exampleOpen[key] = !this.exampleOpen[key];
},
selectOption(index, correct) {
if (this.answered) return;
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;
this.selectedOlympiadOption = index;
if (correct) {
this.olympiadAnswered = true;
this.isOlympiadCorrect = true;
this.olympiadScore += 30;
this.wrongAttempts = 0;
if (typeof confetti !== 'undefined') {
confetti({ particleCount: 150, spread: 80, origin: { y: 0.6 } });
}
} else {
this.wrongAttempts++;
if (navigator.vibrate) navigator.vibrate(200);
if (this.wrongAttempts >= 3) {
this.olympiadAnswered = true;
this.isOlympiadCorrect = false;
}
}
},
nextOlympiad() {
if (this.currentOlympiad < this.olympiadQuestions.length - 1) {
this.currentOlympiad++;
this.olympiadAnswered = false;
this.selectedOlympiadOption = null;
this.isOlympiadCorrect = false;
this.wrongAttempts = 0;
} else {
this.olympiadCompleted = true;
}
}
}
}).mount('#app');
</script>
</body>
</html>
💡 这段代码完全由 AI 生成。
登录后可复制完整代码