<!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>第06讲: 简单的周期问题(周期找余数)</title>
<style>
/* ================= 基础重置与全局样式 ================= */
* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; outline: none; }
html, body {
margin: 0; padding: 0;
overflow: hidden; height: 100vh;
font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", sans-serif;
/* 全局柔和渐变背景 */
background: linear-gradient(180deg, #fdfbfb 0%, #ebedee 100%);
color: #333;
}
/* 隐藏滚动条但保留功能 */
::-webkit-scrollbar { display: none; width: 0 !important; height: 0 !important; }
* { -ms-overflow-style: none; scrollbar-width: none; }
/* 主容器 */
#app {
height: 100vh; max-width: 480px; margin: 0 auto;
display: flex; flex-direction: column;
position: relative;
background-color: rgba(255,255,255,0.5); /* 玻璃质感底色 */
backdrop-filter: blur(10px);
}
.content-area { flex: 1; overflow-y: auto; padding-bottom: 90px; scroll-behavior: smooth; }
/* ================= UI 组件库 (圆润、微投影、渐变) ================= */
/* 通用圆角卡片 - 微投影风格 */
.card-base {
background: #fff;
border-radius: 24px;
padding: 24px;
margin-bottom: 20px;
border: 1px solid rgba(255,255,255,0.8);
/* SVG 风格的高级阴影: 两层阴影模拟环境光和直射光 */
box-shadow:
0 10px 30px -10px rgba(50, 50, 93, 0.1),
0 6px 15px -8px rgba(0, 0, 0, 0.07);
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
/* 标题样式 */
.page-title {
text-align: center; font-size: 24px;
background: linear-gradient(45deg, #333 0%, #666 100%);
-webkit-background-clip: text; -webkit-text-fill-color: transparent;
margin: 25px 0 5px; font-weight: 800; letter-spacing: 1px;
}
.page-subtitle {
text-align: center; color: #667eea;
margin-bottom: 30px; font-size: 14px; opacity: 0.8; font-weight: 500;
}
/* 按钮通用样式 */
.btn-gradient {
display: block; width: 100%; border: none;
padding: 16px; border-radius: 20px;
font-size: 18px; font-weight: bold; cursor: pointer; color: white;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
box-shadow: 0 10px 20px -5px rgba(118, 75, 162, 0.4);
transition: all 0.2s;
position: relative; overflow: hidden;
}
.btn-gradient:active { transform: scale(0.96); box-shadow: 0 5px 10px -5px rgba(118, 75, 162, 0.4); }
/* ================= 页面特定样式 ================= */
/* --- Page 1: 概念引入 --- */
.intro-page { padding: 20px; }
.story-box {
/* 更加鲜艳的渐变背景 */
background: linear-gradient(120deg, #f6d365 0%, #fda085 100%);
color: #fff;
border-radius: 24px;
padding: 28px;
margin: 20px 0;
box-shadow: 0 15px 30px -5px rgba(253, 160, 133, 0.4);
line-height: 1.7; font-size: 16px; font-weight: 500;
text-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.concept-card {
background: rgba(255, 255, 255, 0.9);
border-left: none; /* 移除旧样式 */
position: relative;
}
.concept-card::before {
content: ''; position: absolute; left: 0; top: 20px; bottom: 20px; width: 6px;
background: #667eea; border-radius: 0 6px 6px 0;
}
.listen-btn {
background: linear-gradient(135deg, #84fab0 0%, #8fd3f4 100%);
color: #005c97;
box-shadow: 0 10px 25px -8px rgba(132, 250, 176, 0.5);
margin-top: 40px; border-radius: 50px; width: auto; padding: 15px 50px;
}
/* --- Page 2: 演示动画 --- */
.demo-page { padding: 0 20px; }
.tab-nav {
display: flex; margin: 10px 0 20px;
background: #f1f3f5; border-radius: 16px; padding: 4px; border: none;
}
.tab-item {
flex: 1; padding: 10px; text-align: center; cursor: pointer;
border-radius: 12px; font-size: 14px; font-weight: 600; color: #888;
transition: all 0.3s; border: none;
}
.tab-item.active {
background: #fff; color: #667eea;
box-shadow: 0 4px 10px rgba(0,0,0,0.05); transform: scale(1.02);
}
.animation-area {
background: #fff; border-radius: 24px; padding: 10px; height: 360px;
position: relative; overflow: hidden;
box-shadow: inset 0 0 20px rgba(0,0,0,0.02);
border: 1px solid #f0f0f0;
}
.math-area {
background: #fff; border: 2px solid #e0e7ff;
border-radius: 20px; margin: 20px 0; min-height: 80px;
box-shadow: 0 8px 20px rgba(102, 126, 234, 0.08);
}
.step-explanation {
background: #eef2ff; border-radius: 16px; border: none;
color: #4338ca; padding: 18px; font-weight: 500;
}
/* --- Page 3: 讲解页 --- */
.explain-page { padding: 0 20px; }
.example-card {
border-radius: 18px; border: none; margin-bottom: 16px;
box-shadow: 0 4px 12px rgba(0,0,0,0.03); overflow: hidden;
background: #fff;
}
.example-header {
background: #fff; padding: 18px 20px;
font-weight: 600; color: #444; border-bottom: 1px solid #f5f5f5;
}
.example-header.expanded { background: #f8fafc; color: #667eea; }
/* --- Page 4 & 5: 练习 & 奥数 --- */
.practice-page { padding: 20px; }
.question-card {
background: #fff; border-radius: 28px; padding: 30px 25px;
box-shadow: 0 15px 35px -5px rgba(0,0,0,0.08);
position: relative; z-index: 1;
}
.question-header { border-bottom: 2px dashed #f0f0f0; margin-bottom: 25px; }
.question-text { font-size: 19px; color: #2d3748; margin-bottom: 30px; }
.option-btn {
background: #f7fafc; border: 1px solid #edf2f7; border-radius: 16px;
padding: 18px 20px; margin-bottom: 15px; font-weight: 500; color: #4a5568;
box-shadow: 0 2px 5px rgba(0,0,0,0.02);
}
.option-btn:hover:not(:disabled) { background: #ebf8ff; color: #3182ce; border-color: #bee3f8; }
.option-btn.correct {
background: linear-gradient(90deg, #d4edda 0%, #c3e6cb 100%);
color: #155724; border: none; box-shadow: 0 4px 10px rgba(40, 167, 69, 0.2);
}
.option-btn.wrong {
background: linear-gradient(90deg, #f8d7da 0%, #f5c6cb 100%);
color: #721c24; border: none; box-shadow: 0 4px 10px rgba(220, 53, 69, 0.2);
}
.difficulty-badge { padding: 5px 12px; border-radius: 12px; font-size: 11px; vertical-align: middle; }
.hint-box { background: #fff8e1; border: none; color: #b7791f; border-radius: 12px; }
/* ================= Page 6: 秘籍 (重构重点) ================= */
.secrets-container {
width: 100%;
height: calc(100vh - 90px); /* 减去底部导航高度 */
display: flex; /* Flex布局 */
flex-wrap: nowrap; /* 不换行 */
overflow-x: auto; /* 允许横向滚动 */
scroll-snap-type: x mandatory; /* 强制滚动捕捉 */
-webkit-overflow-scrolling: touch; /* iOS顺滑滚动 */
padding: 20px 0; /* 上下内边距 */
gap: 20px; /* 卡片间距 */
align-items: center; /* 垂直居中 */
}
/* 隐藏横向滚动条 */
.secrets-container::-webkit-scrollbar { display: none; }
/* 占位元素,用于让第一张和最后一张卡片能居中 */
.secrets-spacer {
flex: 0 0 10px;
}
.secret-card {
flex: 0 0 85%; /* 这里的宽度决定了卡片在屏幕上的占比,留出一点边距可以看到下一张 */
width: 85%;
height: 80%; /* 高度占容器的80% */
min-height: 400px; /* 最小高度 */
scroll-snap-align: center; /* 滚动停止时居中 */
border-radius: 30px;
padding: 40px 30px;
display: flex; flex-direction: column; justify-content: center; align-items: center; text-align: center;
color: white;
position: relative;
/* 3D 阴影效果 */
box-shadow:
0 20px 50px -10px rgba(0,0,0,0.3), /* 远阴影 */
0 10px 20px -10px rgba(0,0,0,0.1); /* 近阴影 */
transition: transform 0.3s ease;
}
/* 秘籍卡片配色 */
.secret-1 { background: linear-gradient(135deg, #a18cd1 0%, #fbc2eb 100%); }
.secret-2 { background: linear-gradient(135deg, #84fab0 0%, #8fd3f4 100%); }
.secret-3 { background: linear-gradient(135deg, #fccb90 0%, #d57eeb 100%); }
.secret-icon { font-size: 80px; margin-bottom: 30px; filter: drop-shadow(0 5px 15px rgba(0,0,0,0.15)); }
.secret-title { font-size: 32px; font-weight: 800; margin-bottom: 20px; text-shadow: 0 2px 10px rgba(0,0,0,0.1); }
.secret-text { font-size: 20px; line-height: 1.6; font-weight: 500; opacity: 0.95; }
/* 滑动提示动画 */
.swipe-hint {
position: absolute; bottom: 100px; width: 100%; text-align: center;
color: #999; font-size: 12px; pointer-events: none;
animation: fadeInOut 2s infinite;
}
@keyframes fadeInOut { 0%,100% { opacity: 0.3; } 50% { opacity: 1; } }
/* ================= 底部导航 (毛玻璃) ================= */
.bottom-nav {
position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%);
width: 90%; max-width: 440px; height: 65px;
background: rgba(255, 255, 255, 0.85); /* 半透明 */
backdrop-filter: blur(15px); /* 毛玻璃 */
border-radius: 35px; /* 圆润胶囊 */
box-shadow: 0 10px 30px rgba(0,0,0,0.1); /* 悬浮感 */
display: flex; justify-content: space-around; align-items: center; z-index: 9999;
padding: 0 10px;
border: 1px solid rgba(255,255,255,0.5);
}
.nav-item { flex: 1; display: flex; flex-direction: column; align-items: center; cursor: pointer; opacity: 0.5; transition: all 0.3s; }
.nav-item.active { opacity: 1; transform: translateY(-5px); }
.nav-item.active .nav-icon { transform: scale(1.2); }
.nav-icon { font-size: 22px; margin-bottom: 2px; transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); }
.nav-label { font-size: 10px; font-weight: bold; }
</style>
</head>
<body>
<div id="app">
<div class="content-area">
<div v-show="currentPage === 1" class="intro-page">
<div class="page-title">简单的周期问题</div>
<div class="page-subtitle">周期找余数</div>
<div class="story-box">
📅 今天是星期一。小明想知道,再过30天是星期几?<br><br>
难道要从星期二、星期三……一个一个数到第30天吗?<br><br>
太麻烦啦!其实,掌握“周期找余数”,一算就知道答案!
</div>
<div class="card-base concept-card">
<h3 style="margin-top:0; color:#333;">🎯 知识小卡片</h3>
<ul style="padding-left: 20px; color:#555; line-height: 1.8;">
<li><strong>周期</strong>:不断重复出现的一组事物。</li>
<li><strong>余数</strong>:除法分不完剩下的数。</li>
<li><strong>找规律</strong>:找出谁在重复,一组有几个。</li>
</ul>
</div>
<button class="listen-btn btn-gradient" @click="speak('周期就是不断重复出现的一组事物,像春夏秋冬,星期一到星期日。余数是除法分不完剩下的数,它能告诉我们周期的秘密。找规律就是要先找到谁在重复,数数一组有几个')">
🎧 听老师讲解
</button>
</div>
<div v-show="currentPage === 2" class="demo-page">
<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">
<svg class="svg-container" viewBox="0 0 400 340" xmlns="http://www.w3.org/2000/svg" style="width:100%; height:100%;">
<rect x="20" y="270" width="360" height="5" fill="#e2e8f0" rx="2"/>
<rect x="20" y="275" width="360" height="10" fill="#cbd5e0" rx="5"/>
<g id="shapeGroup">
<circle id="shape-1" cx="50" cy="240" r="25" fill="#4ade80" stroke="#22c55e" stroke-width="2"/>
<text id="text-1" x="50" y="245" text-anchor="middle" fill="white" font-size="20" font-weight="bold">△</text>
<circle id="shape-2" cx="150" cy="240" r="25" fill="#fbbf24" stroke="#f59e0b" stroke-width="2"/>
<text id="text-2" x="150" y="245" text-anchor="middle" fill="white" font-size="20" font-weight="bold">○</text>
<circle id="shape-3" cx="250" cy="240" r="25" fill="#60a5fa" stroke="#3b82f6" stroke-width="2"/>
<text id="text-3" x="250" y="245" text-anchor="middle" fill="white" font-size="20" font-weight="bold">□</text>
</g>
<use id="shape-4" href="#shape-1" x="100" opacity="0"/>
<use id="shape-5" href="#shape-2" x="100" opacity="0"/>
<use id="shape-6" href="#shape-3" x="100" opacity="0"/>
<use id="shape-7" href="#shape-1" x="200" opacity="0"/>
<use id="shape-8" href="#shape-2" x="200" opacity="0"/>
<use id="shape-9" href="#shape-3" x="200" opacity="0"/>
<use id="shape-10" href="#shape-1" x="300" opacity="0"/>
<rect x="150" y="30" width="100" height="50" rx="15" fill="#667eea" stroke="#5a67d8" stroke-width="0" style="filter: drop-shadow(0 4px 6px rgba(102,126,234,0.4));"/>
<text id="counterText" x="200" y="65" text-anchor="middle" fill="white" font-size="28" font-weight="bold">1</text>
<text x="200" y="100" text-anchor="middle" fill="#718096" font-size="14" font-weight="bold">当前是第几个?</text>
<rect id="group1" x="35" y="190" width="110" height="70" rx="12" stroke="#ff6b6b" stroke-width="3" fill="none" stroke-dasharray="8,5" opacity="0"/>
<rect id="group2" x="135" y="190" width="110" height="70" rx="12" stroke="#4d96ff" stroke-width="3" fill="none" stroke-dasharray="8,5" opacity="0"/>
<rect id="group3" x="235" y="190" width="110" height="70" rx="12" stroke="#6bc77b" stroke-width="3" fill="none" stroke-dasharray="8,5" opacity="0"/>
<rect id="remainBox" x="335" y="190" width="70" height="70" rx="12" stroke="#ffb347" stroke-width="3" fill="rgba(255, 179, 71, 0.2)" opacity="0"/>
<text x="200" y="170" text-anchor="middle" fill="#666" font-size="14" opacity="0" id="groupText" font-weight="bold">分成3组,每组3个</text>
</svg>
<button class="step-btn prev-step" @click="prevDirectStep" :disabled="directStep === 0" style="position:absolute; left:10px; top:50%; width:44px; height:44px; border-radius:50%; border:none; background:white; color:#667eea; font-weight:bold; box-shadow:0 4px 10px rgba(0,0,0,0.1); font-size:20px; cursor:pointer; z-index:10;">◀</button>
<button class="step-btn next-step" @click="nextDirectStep" :disabled="directStep === 3" style="position:absolute; right:10px; top:50%; width:44px; height:44px; border-radius:50%; border:none; background:#667eea; color:white; font-weight:bold; box-shadow:0 4px 10px rgba(102,126,234,0.4); font-size:20px; cursor:pointer; z-index:10;">▶</button>
</div>
<div class="math-area">
<div class="math-formula" id="mathFormula" style="font-size: 20px; font-weight: 800; color: #4a5568;">找规律:△ ○ □ △ ○ □ ...</div>
</div>
<div class="step-explanation" id="stepExplanation">小朋友们,看看红绿灯,总是绿、黄、红、绿、黄、红……这样不停地变。这就是<strong>周期</strong>!</div>
</div>
</div>
<div v-show="currentPage === 3" class="explain-page">
<div class="tab-nav">
<div class="tab-item" :class="{active: explainTab === 'formula'}" @click="explainTab='formula'">核心口诀</div>
<div class="tab-item" :class="{active: explainTab === 'steps'}" @click="explainTab='steps'">解题步骤</div>
<div class="tab-item" :class="{active: explainTab === 'example'}" @click="explainTab='example'">典型例题</div>
</div>
<div class="explain-section" v-show="explainTab === 'formula'">
<div class="card-base">
<h3 style="color:#667eea; text-align:center;">📐 核心公式</h3>
<div style="background:#f7fafc; padding:15px; border-radius:12px; margin:15px 0; text-align:center; font-weight:bold; color:#2d3748; border:1px dashed #cbd5e0;">
总数 ÷ 周期数 = 组数 …… 余数
</div>
<p>👉 余数是几,就是每组里的第几个!</p>
</div>
</div>
<div class="explain-section" v-show="explainTab === 'steps'">
<div class="card-base">
<h3 style="color:#667eea; text-align:center;">🚀 解题三步走</h3>
<ol style="padding-left:20px; line-height:2;">
<li><span style="background:#e6fffa; color:#2c7a7b; padding:2px 8px; border-radius:4px; font-size:12px; font-weight:bold; margin-right:5px;">STEP 1</span> <strong>圈一圈</strong>:找出重复的周期。</li>
<li><span style="background:#ebf8ff; color:#2b6cb0; padding:2px 8px; border-radius:4px; font-size:12px; font-weight:bold; margin-right:5px;">STEP 2</span> <strong>数一数</strong>:一个周期有几个?</li>
<li><span style="background:#fff5f5; color:#c53030; padding:2px 8px; border-radius:4px; font-size:12px; font-weight:bold; margin-right:5px;">STEP 3</span> <strong>算一算</strong>:除法找余数。</li>
</ol>
</div>
</div>
<div class="explain-section" v-show="explainTab === 'example'">
<div class="example-card">
<div class="example-header" :class="{expanded: expandedExample === 1}" @click="toggleExample(1)">
<span>🚩 例题1:基础题</span>
<span style="color:#cbd5e0;">{{ expandedExample === 1 ? '▲' : '▼' }}</span>
</div>
<div class="example-content" :class="{expanded: expandedExample === 1}" v-show="expandedExample === 1" style="padding:20px;">
<div class="example-q">题目:彩旗按“红、黄、蓝、红、黄、蓝……”排列,第 8 面是什么颜色?</div>
<div class="example-a">答案:黄色</div>
<div class="example-exp">解析:周期是3(红黄蓝)。8 ÷ 3 = 2......2。余数是2,对应第2个颜色,是黄色。</div>
</div>
</div>
<div class="example-card">
<div class="example-header" :class="{expanded: expandedExample === 2}" @click="toggleExample(2)">
<span>📅 例题2:进阶题</span>
<span style="color:#cbd5e0;">{{ expandedExample === 2 ? '▲' : '▼' }}</span>
</div>
<div class="example-content" :class="{expanded: expandedExample === 2}" v-show="expandedExample === 2" style="padding:20px;">
<div class="example-q">题目:今天是星期一,再过 3 天是星期几?</div>
<div class="example-a">答案:星期四</div>
<div class="example-exp">解析:这是简单的推算,直接数:二、三、四。</div>
</div>
</div>
</div>
</div>
<div v-show="currentPage === 4" class="practice-page">
<div v-if="!practiceCompleted">
<div class="question-card">
<div class="question-header">
<div class="question-number" style="color:#667eea; font-weight:800;">Question {{currentQuestion + 1}}</div>
<div class="score-display" style="background:#fffaf0; color:#ed8936; padding:5px 15px; border-radius:20px; font-size:14px;">⭐ {{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; background:#f7fafc; margin-bottom:20px;">
<div v-if="isCorrect" style="color:#38a169;"><strong>🎉 太棒了!</strong> {{practiceQuestions[currentQuestion].explanation}}</div>
<div v-else style="color:#e53e3e;"><strong>💡 分析:</strong> {{practiceQuestions[currentQuestion].explanation}}</div>
</div>
<button v-if="answered" class="next-btn btn-gradient" @click="nextQuestion">
{{currentQuestion < practiceQuestions.length - 1 ? '下一题 →' : '完成练习 ✓'}}
</button>
</div>
</div>
<div v-else class="completion-page" style="text-align:center; padding-top:50px;">
<div class="completion-emoji" style="font-size:80px; margin-bottom:20px;">🎊</div>
<div class="completion-title" style="font-size:24px; font-weight:bold; margin-bottom:20px;">练习完成!</div>
<div class="final-score" style="font-size:60px; font-weight:800; color:#ecc94b; margin:20px 0;">{{score}}</div>
<button class="restart-btn btn-gradient" @click="switchPage(5)">挑战奥数题 →</button>
</div>
</div>
<div v-show="currentPage === 5" class="practice-page">
<div v-if="!olympiadCompleted">
<div class="question-card">
<div class="question-header">
<div>
<span class="question-number" style="color:#d53f8c; font-weight:800;">Challenge {{currentOlympiad + 1}}</span>
<span class="difficulty-badge" :class="'difficulty-' + olympiadQuestions[currentOlympiad].difficulty" style="margin-left:10px; background:#f7fafc; border:1px solid #e2e8f0;">{{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" class="hint-box" style="padding:15px; margin-bottom:15px;">
<strong v-if="wrongAttempts === 1">💡 提示1:</strong>
<strong v-if="wrongAttempts === 2">💡 提示2:</strong>
{{ wrongAttempts === 1 ? olympiadQuestions[currentOlympiad].hint1 : olympiadQuestions[currentOlympiad].hint2 }}
</div>
<button v-if="olympiadAnswered || wrongAttempts >= 3" class="next-btn btn-gradient" @click="nextOlympiad">
{{currentOlympiad < olympiadQuestions.length - 1 ? '下一题 →' : '完成挑战 ✓'}}
</button>
</div>
</div>
<div v-else class="completion-page" style="text-align:center; padding-top:50px;">
<div class="completion-emoji" style="font-size:80px; margin-bottom:20px;">🏆</div>
<div class="completion-title" style="font-size:24px; font-weight:bold; margin-bottom:20px;">挑战成功!</div>
<div class="final-score" style="font-size:60px; font-weight:800; color:#ecc94b; margin:20px 0;">{{olympiadScore}}</div>
<button class="restart-btn btn-gradient" @click="switchPage(6)">查看通关秘籍 →</button>
</div>
</div>
<div v-show="currentPage === 6">
<div v-if="currentPage === 6" class="swipe-hint">← 左右滑动查看更多 →</div>
<div class="secrets-container">
<div class="secrets-spacer"></div>
<div class="secret-card secret-1">
<div class="secret-icon">🔍</div>
<div class="secret-title">秘籍一</div>
<div class="secret-text">
<strong>圈一圈</strong><br><br>
把重复的那一部分圈起来<br>
数数有几个<br>
这就是周期 T
</div>
</div>
<div class="secret-card secret-2">
<div class="secret-icon">🧮</div>
<div class="secret-title">秘籍二</div>
<div class="secret-text">
<strong>找余数</strong><br><br>
用总数除以周期<br>
余数是几<br>
就看这一组的第几个
</div>
</div>
<div class="secret-card secret-3">
<div class="secret-icon">✨</div>
<div class="secret-title">秘籍三</div>
<div class="secret-text">
<strong>整除看最后</strong><br><br>
如果余数是 0<br>
(正好分完)<br>
那就是这一组的最后一个
</div>
</div>
<div class="secrets-spacer"></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: 'formula',
directStep: 0,
steps: [
'小朋友们,看看红绿灯,总是绿、黄、红、绿、黄、红……这样不停地变。这就是周期!',
'看,传送带上运来图形:△ ○ □,它们一直在重复。找规律:△ ○ □ △ ○ □ ...',
'我们想知道第10个是什么。先把前9个分一分,3个一组,正好分3组。算式是:10 ÷ 3 = 3......1。',
'分完3组后,还剩1个。余数是1,就找周期里的第1个!看,是△。所以第10个图形是△。'
],
expandedExample: 1,
// 课内练习
practiceQuestions: [
{ text: "有一串珠子按 ●○○ ●○○ ... 排列,第 10 颗是什么?", options: [{text: "A. ●", correct: true}, {text: "B. ○", correct: false}, {text: "C. 不确定", correct: false}, {text: "D. 红色", correct: false}], explanation: "余数1,看每组第1个。" },
{ text: "数字按 1, 2, 3, 4, 1, 2, 3, 4... 排列,第 15 个数字是?", options: [{text: "A. 1", correct: false}, {text: "B. 2", correct: false}, {text: "C. 3", correct: true}, {text: "D. 4", correct: false}], explanation: "余数3,对应数字3。" },
{ text: "今天是星期二,7 天后是星期几?", options: [{text: "A. 星期二", correct: true}, {text: "B. 星期一", correct: false}, {text: "C. 星期三", correct: false}, {text: "D. 星期日", correct: false}], explanation: "7天后正好过了一周,还是星期二。" },
{ text: "图形规律:△△□○ △△□○... 第 12 个图形是?", options: [{text: "A. △", correct: false}, {text: "B. □", correct: false}, {text: "C. ○", correct: true}, {text: "D. 不确定", correct: false}], explanation: "没有余数就是最后一个,○。" },
{ text: "小狗在跑道上按“前、后、左、右”的顺序跳,第 13 次跳向哪里?", options: [{text: "A. 前", correct: true}, {text: "B. 后", correct: false}, {text: "C. 左", correct: false}, {text: "D. 右", correct: false}], explanation: "余1,方向是前。" },
{ text: "20 个小朋友报数,1, 2, 1, 2... 循环报,第 19 个小朋友报几?", options: [{text: "A. 1", correct: true}, {text: "B. 2", correct: false}, {text: "C. 3", correct: false}, {text: "D. 0", correct: false}], explanation: "奇数位置报1,偶数位置报2。" },
{ text: "一串灯笼:红黄蓝绿紫,第 23 个灯笼颜色?", options: [{text: "A. 红", correct: false}, {text: "B. 黄", correct: false}, {text: "C. 蓝", correct: true}, {text: "D. 绿", correct: false}], explanation: "余3,第三个是蓝。" },
{ text: "今天是 1 号星期三,8 号是星期几?", options: [{text: "A. 星期二", correct: false}, {text: "B. 星期三", correct: true}, {text: "C. 星期四", correct: false}, {text: "D. 星期五", correct: false}], explanation: "8 - 1 = 7,过了7天正好一个周期,回到星期三。" }
],
currentQuestion: 0, answered: false, selectedOption: null, isCorrect: false, score: 0, practiceCompleted: false,
// 奥数挑战
olympiadQuestions: [
{ text: "有一列数 1, 4, 2, 8, 5, 7, 1, 4, 2, 8, 5, 7... 第 50 个数是多少?", options: [{text: "A. 4", correct: true}, {text: "B. 2", correct: false}, {text: "C. 8", correct: false}, {text: "D. 5", correct: false}], hint1: "数数几个数循环?6个。", hint2: "50 ÷ 6 = 8......2。", hint3: "余数2,看第2个数。", explanation: "大数字找周期。周期是6。50 ÷ 6 = 8......2。余数是2,对应周期(1,4,2,8,5,7)里的第2个,是4。", difficulty: 2, difficultyText: "⭐⭐" },
{ text: "2015 年的 5 月 1 日是星期五,5 月 31 日是星期几?", options: [{text: "A. 星期五", correct: false}, {text: "B. 星期六", correct: false}, {text: "C. 星期日", correct: true}, {text: "D. 星期一", correct: false}], hint1: "31 - 1 = 30 天。", hint2: "30 ÷ 7 = 4......2。", hint3: "星期五往后数2天,六、日。", explanation: "日期差计算。从1日到31日,过了30天。30 ÷ 7 = 4周......2天。星期五往后推2天:星期六、星期日。", difficulty: 2, difficultyText: "⭐⭐" },
{ text: "把 1/7 化成小数,小数点后第 20 位数字是多少?(1÷7=0.142857142857...)", options: [{text: "A. 4", correct: true}, {text: "B. 2", correct: false}, {text: "C. 8", correct: false}, {text: "D. 5", correct: false}], hint1: "循环节是 142857,6个数字。", hint2: "20 ÷ 6 = 3......2。", hint3: "第2个数字是4。", explanation: "小数循环节。1÷7=0.142857142857...循环节是6位的142857。20 ÷ 6 = 3......2。余数是2,取循环节第2位,是4。", difficulty: 3, difficultyText: "⭐⭐⭐" },
{ text: "流水线上装产品,按“红、黄、蓝、绿、白”的顺序装箱。第 100 个产品是什么颜色?", options: [{text: "A. 白", correct: true}, {text: "B. 绿", correct: false}, {text: "C. 蓝", correct: false}, {text: "D. 黄", correct: false}], hint1: "周期是5。", hint2: "100 ÷ 5 = 20(整除)。", hint3: "整除就是最后一个颜色,白色。", explanation: "整除情况。周期是5。100 ÷ 5 = 20,正好整除,没有余数,所以是周期里的最后一个颜色:白色。", difficulty: 1, difficultyText: "⭐" },
{ text: "小明按照 1个红球、2个黄球、3个白球的顺序穿珠子,第 50 个珠子是什么颜色?", options: [{text: "A. 红", correct: false}, {text: "B. 黄", correct: true}, {text: "C. 白", correct: false}, {text: "D. 黑", correct: false}], hint1: "一组是 1+2+3=6 个。", hint2: "50 ÷ 6 = 8......2。", hint3: "第2个在黄球范围内吗?不对!第一组:红(1), 黄(2,3), 白(4,5,6)。余数2是黄球!", explanation: "不均匀周期。一个周期有1+2+3=6个珠子。50 ÷ 6 = 8组......2个。余数2表示第9组里的第2个。在第一组里找:第1个是红,第2个是黄。所以是黄球。", difficulty: 3, difficultyText: "⭐⭐⭐" },
{ text: "有一列图形:□□△○□□△○... 前 22 个图形中,有几个 □?", options: [{text: "A. 10", correct: false}, {text: "B. 11", correct: false}, {text: "C. 12", correct: true}, {text: "D. 8", correct: false}], hint1: "周期是4,每组有2个□。", hint2: "22 ÷ 4 = 5组......2个。", hint3: "5组有 5×2=10个,余下的2个里有2个□。共12个。", explanation: "周期内的数量统计。周期(□,□,△,○)共4个图形,其中□有2个。22 ÷ 4 = 5组......2个。5组共有5×2=10个□。余下的2个是□□,所以再加2个。总共10+2=12个□。", difficulty: 2, difficultyText: "⭐⭐" },
{ text: "河岸边插彩旗,按“红黄蓝绿”顺序。第 1 面是红旗,第 30 面是什么旗?", options: [{text: "A. 红", correct: false}, {text: "B. 黄", correct: true}, {text: "C. 蓝", correct: false}, {text: "D. 绿", correct: false}], hint1: "30 ÷ 4 = 7......2。", hint2: "余2。", hint3: "黄色。", explanation: "标准周期。周期是4。30 ÷ 4 = 7......2。余数是2,对应周期(红、黄、蓝、绿)里的第2个:黄色。", difficulty: 1, difficultyText: "⭐" },
{ text: "今天是星期六,从今天算起,第 100 天是星期几?", options: [{text: "A. 星期六", correct: false}, {text: "B. 星期日", correct: true}, {text: "C. 星期一", correct: false}, {text: "D. 星期二", correct: false}], hint1: "这题有歧义。通常“第1天”是今天。100 ÷ 7 = 14......2。", hint2: "把星期六当做1,余数2就是星期日。", hint3: "如果是“过100天”,就是100÷7余2,六+2=一。题目是“第100天”,选B。", explanation: "包含今天的推算。把星期六当做第1天。100 ÷ 7 = 14周......2天。余数2,表示第100天是周期(六、日、一、二、三、四、五)里的第2个:星期日。", difficulty: 2, difficultyText: "⭐⭐" }
],
currentOlympiad: 0, olympiadAnswered: false, selectedOlympiadOption: null, isOlympiadCorrect: false, olympiadScore: 0, olympiadCompleted: false, wrongAttempts: 0
};
},
mounted() {
if (this.currentPage === 2) { this.runDirectAnimation(); }
},
methods: {
switchPage(page) {
this.stopSpeak();
this.currentPage = page;
if (page === 2) { this.directStep = 0; setTimeout(() => { this.runDirectAnimation(); }, 50); }
if (page === 4 && this.practiceCompleted) { this.currentQuestion = 0; this.practiceCompleted = false; this.score = 0; }
if (page === 5 && this.olympiadCompleted) { this.currentOlympiad = 0; this.olympiadCompleted = false; 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) {
this.stopSpeak();
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.stopSpeak(); this.demoTab = tab; },
runDirectAnimation() {
if (typeof gsap === 'undefined') return;
const tl = gsap.timeline();
gsap.set(['#shape-4', '#shape-5', '#shape-6', '#shape-7', '#shape-8', '#shape-9', '#shape-10', '#group1', '#group2', '#group3', '#remainBox', '#groupText'], { opacity: 0 });
gsap.set(['#shape-1', '#shape-2', '#shape-3'], { x: 0 });
gsap.set('#counterText', { text: '1' });
if (this.directStep === 0) {
tl.to('#shape-1', { x: 0, duration: 0.5, ease: "bounce.out" }).to('#counterText', { text: '1', duration: 0.5, ease: "none" }, '<');
} else if (this.directStep === 1) {
tl.to('#shape-1', { x: 0, duration: 0.5, ease: "bounce.out" }).to('#shape-2', { x: 0, duration: 0.5, ease: "bounce.out" }, '+=0.2').to('#shape-3', { x: 0, duration: 0.5, ease: "bounce.out" }, '+=0.2').to('#counterText', { text: '3', duration: 0.5, ease: "none" }, '<');
} else if (this.directStep === 2) {
tl.to('#shape-1', { x: -100, duration: 0.5 }).to('#shape-2', { x: 0, duration: 0.5 }, '<').to('#shape-3', { x: 100, duration: 0.5 }, '<').to('#shape-4', { opacity: 1, x: -100, duration: 0.5, ease: "bounce.out" }, '+=0.3').to('#shape-5', { opacity: 1, x: 0, duration: 0.5, ease: "bounce.out" }, '+=0.2').to('#shape-6', { opacity: 1, x: 100, duration: 0.5, ease: "bounce.out" }, '+=0.2').to('#shape-7', { opacity: 1, x: -100, duration: 0.5, ease: "bounce.out" }, '+=0.3').to('#shape-8', { opacity: 1, x: 0, duration: 0.5, ease: "bounce.out" }, '+=0.2').to('#shape-9', { opacity: 1, x: 100, duration: 0.5, ease: "bounce.out" }, '+=0.2').to('#counterText', { text: '9', duration: 0.5, ease: "none" }, '<').to('#groupText', { opacity: 1, duration: 0.5 }, '+=0.5').to(['#group1', '#group2', '#group3'], { opacity: 1, duration: 0.5, stagger: 0.1 }, '<');
} else if (this.directStep === 3) {
this.runDirectAnimation();
tl.to('#shape-10', { opacity: 1, x: 300, duration: 0.8, ease: "bounce.out" }, '+=0.5').to('#counterText', { text: '10', duration: 0.5, ease: "none" }, '<').to('#remainBox', { opacity: 1, duration: 0.5 }, '<');
}
},
nextDirectStep() {
if (this.directStep < 3) {
this.directStep++;
this.runDirectAnimation();
const formulaText = ['找规律:△ ○ □ △ ○ □ ...', '找规律:△ ○ □ △ ○ □ ...', '算式:10 ÷ 3 = 3......1', '余1,是△!第10个图形是△。'];
document.getElementById('mathFormula').innerText = formulaText[this.directStep];
document.getElementById('stepExplanation').innerHTML = this.steps[this.directStep];
}
},
prevDirectStep() {
if (this.directStep > 0) {
this.directStep--;
this.runDirectAnimation();
const formulaText = ['找规律:△ ○ □ △ ○ □ ...', '找规律:△ ○ □ △ ○ □ ...', '算式:10 ÷ 3 = 3......1', '余1,是△!第10个图形是△。'];
document.getElementById('mathFormula').innerText = formulaText[this.directStep];
document.getElementById('stepExplanation').innerHTML = this.steps[this.directStep];
}
},
toggleExample(num) { this.expandedExample = this.expandedExample === num ? null : num; },
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; this.isOlympiadCorrect = correct;
if (correct) { this.olympiadAnswered = true; this.olympiadScore += 30; this.wrongAttempts = 0; if (typeof confetti !== 'undefined') { confetti({ particleCount: 150, spread: 100, origin: { y: 0.6 } }); } } else { this.wrongAttempts++; if (navigator.vibrate) navigator.vibrate(200); if (this.wrongAttempts >= 3) { this.olympiadAnswered = true; } }
},
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 生成。
登录后可复制完整代码