小学英语单词魔法学园HTML5实现

小学英语单词魔法学园HTML5实现

这是一个有趣的小学英语学习的互动式单词学习工具,这个工具把一个枯燥的单词学习,变成了一个能听、能玩、能跟读、能自定义的动态学习环境,而且无需安装,降低了有趣且高效的英语启蒙的门槛。

" 小学单词魔法学园 "功能全景和实现原理

这个互动式单词学习工具是一个集单词卡片展示、听音选词游戏、自动领读于一体、可直接在浏览器中运行的 HTML 单文件应用。

是一个纯前端、零依赖、开箱即用的英文单词学习工具,所有数据均在本地处理,无需联网(但因需要用Edge 浏览器语音优质语音需要联网------断网可能导致TTS声音降级,联网朗读效果最佳)。使用Edge 浏览器音质效果最佳:

右键 本工具→ "打开方式" → Edge 浏览器,享受最佳语音体验。

内置发音修正表目前仅覆盖少量缩写,若词库中含有其他特殊缩写,需手动扩充 pronunciationFix。

pronunciationFix 对象用于覆盖 TTS 引擎可能读错的单词:

const pronunciationFix = {

"Ms": "mizz", // 强制读成 /mɪz/

"o'clock": "o clock", // 避免特殊字符干扰

"won't": "will not" // 防止缩略词读法生硬

};

在 speakWordSingle 和领读模式中,实际发音的文本会先经过此表转换,再送入 TTS 引擎。

内置小学常用完整词库

基本够用。

还支持导入自定义 .txt 文件。词库文本格式:

格式: 单词 # 释义 # 音标 # emoji (后两项可选)。

如:

html 复制代码
三年级:
apple # 苹果 # /ˈæpl/ # 🍎
banana # 香蕉 # /bəˈnɑːnə/ # 🍌

四年级:
classroom # 教室 # /ˈklɑːsruːm/ # 🏫

导入后自动替换内置词库,并刷新所有模式。

数据流与交互示意

用户导入 .txt 文件

解析为 currentWords 数组

渲染词汇卡片

切换模式 ────┬── 听力挑战 (随机选词、生成干扰项)

├── 领读模式 (状态机驱动循环朗读)

└── 返回卡片 (界面同步)

整体功能概览

|--------------------|------------------------------------------|
| 模块 | 功能 |
| 魔法图鉴(学习模式) | 按年级展示单词卡片,含 emoji、音标、释义;点击卡片可播放单词发音 |
| 咒语对决(游戏模式) | 听发音,从三个选项中选出正确单词,得分击败怪兽 |
| 领读模式 | 按设定次数和间隔,自动逐词朗读整个词库,支持暂停/继续/停止 |
| 词库管理 | 内置完整词库;支持导入自定义 .txt 文件,自动解析并按年级分类 |
| 发音优化 | 使用 Web Speech API,优选 Edge 神经网络语音,内置发音修正表 |

· 魔法图鉴(学习模式)

根据当前选中的年级动态生成卡片,单机卡片读音。

· 咒语对决(游戏模式)

每次从当前词库随机抽取一题,再随机选两个不同单词作为干扰项,组成三个选项并随机排序。

正确:加分,显示胜利反馈,怪兽爆炸动画 → 短暂延迟后进入下一题。

错误:显示失败反馈,重新朗读正确答案,短暂延迟后恢复按钮可用。

· 领读模式

播放当前单词。

暂停/继续/停止通过修改状态变量并清理定时器、取消语音来实现。

量并清理定时器、取消语音来实现。

运行截图和源码

运行截图:

源码如下:

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>🔮 小学单词魔法学园 · 终极稳定版</title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body {
            background: radial-gradient(circle at 10% 20%, #1a0a2e, #0d0d2b);
            font-family: 'Segoe UI', 'Comic Sans MS', cursive, sans-serif;
            min-height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            color: white;
            padding: 20px;
        }
        .magic-book {
            background: rgba(255,255,255,0.08);
            backdrop-filter: blur(25px);
            border-radius: 50px;
            padding: 30px;
            max-width: 950px;
            width: 100%;
            text-align: center;
            box-shadow: 0 20px 60px rgba(0,0,0,0.7), inset 0 0 30px rgba(255,215,0,0.2);
            border: 2px solid rgba(255,215,0,0.3);
            position: relative;
            z-index: 1;
        }
        h1 { font-size: 2.5em; margin-bottom: 5px; text-shadow: 0 0 15px gold; }
        .subtitle { opacity: 0.8; margin-bottom: 20px; }

        .help-btn {
            position: absolute;
            top: 20px;
            right: 20px;
            background: rgba(255,255,255,0.2);
            border: 2px solid gold;
            color: gold;
            width: 45px;
            height: 45px;
            border-radius: 50%;
            font-size: 1.6em;
            cursor: pointer;
            transition: 0.3s;
            display: flex;
            align-items: center;
            justify-content: center;
            z-index: 10;
        }
        .help-btn:hover { background: rgba(255,215,0,0.3); box-shadow: 0 0 15px gold; }

        .help-modal {
            display: none;
            position: fixed;
            top: 0; left: 0; right: 0; bottom: 0;
            background: rgba(0,0,0,0.75);
            backdrop-filter: blur(5px);
            z-index: 1000;
            justify-content: center;
            align-items: center;
        }
        .help-modal.show { display: flex; }
        .help-content {
            background: linear-gradient(145deg, #2a1a4a, #1e1236);
            border: 2px solid #e94560;
            border-radius: 30px;
            padding: 30px;
            max-width: 600px;
            width: 90%;
            text-align: left;
            color: white;
            max-height: 80vh;
            overflow-y: auto;
            box-shadow: 0 20px 50px rgba(0,0,0,0.9);
            position: relative;
        }
        .help-content h2 { text-align: center; margin-bottom: 20px; color: gold; font-size: 2em; }
        .help-content h3 { color: #ff6ec7; margin-top: 20px; margin-bottom: 5px; }
        .help-content p, .help-content li { margin: 8px 0; line-height: 1.5; }
        .help-content ul { padding-left: 20px; }
        .help-content code {
            background: rgba(255,255,255,0.15);
            padding: 2px 6px;
            border-radius: 5px;
            font-size: 0.9em;
        }
        .close-help {
            position: absolute; top: 15px; right: 20px;
            background: none; border: none; color: white;
            font-size: 2em; cursor: pointer; transition: 0.2s;
        }
        .close-help:hover { color: #e94560; transform: scale(1.2); }

        .import-area {
            display: flex;
            flex-wrap: wrap;
            justify-content: center;
            gap: 12px;
            margin-bottom: 20px;
            background: rgba(255,255,255,0.05);
            padding: 10px 16px;
            border-radius: 40px;
            border: 1px dashed rgba(255,215,0,0.3);
        }
        .import-area .file-label {
            background: #2c5364;
            color: white;
            padding: 6px 18px;
            border-radius: 30px;
            cursor: pointer;
            font-size: 0.9em;
            transition: 0.2s;
            border: none;
        }
        .import-area .file-label:hover { background: #3a6b7a; }
        #fileInput { display: none; }
        .import-area .file-status {
            font-size: 0.9em;
            opacity: 0.7;
            display: flex;
            align-items: center;
            gap: 6px;
        }
        .import-area .file-status .fname {
            color: #ffd966;
            max-width: 120px;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }

        .grade-selector { display: flex; justify-content: center; flex-wrap: wrap; gap: 8px; margin-bottom: 25px; }
        .grade-btn {
            background: rgba(255,255,255,0.1); border: 2px solid transparent;
            color: white; padding: 8px 18px; border-radius: 25px;
            cursor: pointer; font-size: 1em; transition: 0.3s; font-weight: bold;
        }
        .grade-btn.active { background: #e94560; border-color: gold; box-shadow: 0 0 12px #e94560; }

        .tabs { display: flex; justify-content: center; gap: 15px; margin-bottom: 25px; flex-wrap: wrap; }
        .tab {
            background: rgba(255,255,255,0.1); border: none; color: white;
            padding: 10px 25px; border-radius: 30px; cursor: pointer;
            font-size: 1.1em; transition: 0.3s; font-weight: bold;
        }
        .tab.active { background: #e94560; box-shadow: 0 0 15px #e94560; }

        .card-grid { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; max-height: 420px; overflow-y: auto; padding: 5px; }
        .word-card {
            background: linear-gradient(145deg, #2a1a4a, #1e1236);
            border: 2px solid #7b68ee; border-radius: 20px;
            padding: 12px 14px; cursor: pointer; transition: transform 0.3s, box-shadow 0.3s;
            min-width: 110px; text-align: center;
        }
        .word-card:hover { transform: translateY(-5px); box-shadow: 0 10px 25px rgba(123,104,238,0.6); }
        .card-emoji { font-size: 2.2em; display: block; transition: transform 0.5s; min-height: 1.2em; }
        .word-card:hover .card-emoji { animation: bounce 0.6s ease infinite; }
        @keyframes bounce { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-12px); } }
        .word { font-size: 1.4em; font-weight: bold; margin: 5px 0 2px; }
        .phonetic { font-size: 0.9em; color: #ffd966; font-style: italic; letter-spacing: 0.5px; margin-bottom: 4px; }
        .meaning { font-size: 0.85em; opacity: 0.8; }

        .game-area { margin-top: 20px; }
        .monster-box { display: flex; justify-content: center; align-items: center; gap: 15px; margin-bottom: 20px; flex-wrap: wrap; }
        .monster { font-size: 3.5em; animation: float 3s ease-in-out infinite; }
        @keyframes float { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-10px); } }
        .options { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; }
        .option-btn {
            background: #2a1a4a; border: 2px solid #7b68ee; color: white;
            padding: 10px 22px; border-radius: 30px; font-size: 1.2em; cursor: pointer; transition: 0.2s;
        }
        .option-btn:hover { background: #7b68ee; }
        .option-btn:disabled { opacity: 0.5; cursor: not-allowed; }
        .score { font-size: 1.2em; margin-top: 15px; }
        .feedback { font-size: 1.4em; margin-top: 10px; min-height: 35px; }
        button:active { transform: scale(0.95); }

        .read-settings {
            display: flex;
            flex-wrap: wrap;
            justify-content: center;
            gap: 20px;
            margin: 10px 0 15px;
            background: rgba(255,255,255,0.05);
            padding: 12px 20px;
            border-radius: 30px;
        }
        .read-settings label {
            display: flex;
            align-items: center;
            gap: 8px;
            font-size: 0.95em;
            opacity: 0.8;
        }
        .read-settings input[type="number"] {
            background: rgba(255,255,255,0.1);
            border: 1px solid rgba(255,255,255,0.2);
            border-radius: 20px;
            padding: 4px 10px;
            width: 60px;
            color: white;
            font-size: 1em;
            text-align: center;
        }
        .read-settings input[type="number"]:focus {
            outline: none;
            border-color: #00b4d8;
        }
        .read-display {
            background: rgba(0,0,0,0.3);
            border-radius: 30px;
            padding: 30px 20px;
            margin: 10px 0 20px;
            border: 1px solid rgba(255,215,0,0.2);
        }
        .read-word {
            font-size: 3em;
            font-weight: 600;
            color: #fff;
            margin-bottom: 5px;
            text-shadow: 0 0 20px gold;
        }
        .read-phonetic {
            font-size: 1.2em;
            color: #ffd966;
            font-style: italic;
        }
        .read-meaning {
            font-size: 1.1em;
            opacity: 0.85;
            margin-top: 8px;
        }
        .read-progress {
            font-size: 0.95em;
            opacity: 0.7;
            margin-top: 10px;
        }
        .read-controls {
            display: flex;
            flex-wrap: wrap;
            justify-content: center;
            gap: 12px;
            margin: 15px 0;
        }
        .read-controls button {
            background: rgba(255,255,255,0.1);
            border: 1px solid rgba(255,255,255,0.25);
            color: white;
            padding: 10px 24px;
            border-radius: 30px;
            font-size: 1em;
            cursor: pointer;
            transition: 0.2s;
        }
        .read-controls button:hover { background: rgba(0,180,216,0.3); border-color: #00b4d8; }
        .read-controls button.primary { background: #e94560; border-color: gold; }
        .read-controls button.primary:hover { background: #ff6ec7; }

        .card-grid::-webkit-scrollbar, .help-content::-webkit-scrollbar { width: 6px; }
        .card-grid::-webkit-scrollbar-track, .help-content::-webkit-scrollbar-track { background: transparent; }
        .card-grid::-webkit-scrollbar-thumb, .help-content::-webkit-scrollbar-thumb { background: #7b68ee; border-radius: 10px; }
    </style>
</head>
<body>
    <div class="magic-book">
        <button class="help-btn" onclick="openHelp()" title="使用帮助">❓</button>
        <h1>🔮 小学单词魔法学园</h1>
        <p class="subtitle">  听发音 · 学音标 · 击败单词怪兽 ·  💻设计:Wang Kejun</p>

        <div class="import-area">
            <label class="file-label" for="fileInput">📂 导入词库</label>
            <input type="file" id="fileInput" accept=".txt">
            <span class="file-status">
                <span>📄</span>
                <span class="fname" id="fileName">未选择文件</span>
            </span>
            <span style="opacity:0.5; font-size:0.85em;">格式:单词 # 释义 # 音标 # emoji</span>
        </div>

        <div class="grade-selector" id="gradeSelector">
            <button class="grade-btn active" data-grade="all">🌟 全部</button>
            <button class="grade-btn" data-grade="3">三年级</button>
            <button class="grade-btn" data-grade="4">四年级</button>
            <button class="grade-btn" data-grade="5">五年级</button>
            <button class="grade-btn" data-grade="6">六年级</button>
        </div>

        <div class="tabs">
            <button class="tab active" id="learnTab" onclick="switchMode('learn')">📖 魔法图鉴</button>
            <button class="tab" id="playTab" onclick="switchMode('play')">⚔️ 咒语对决</button>
            <button class="tab" id="readTab" onclick="switchMode('read')">🔊 领读模式</button>
        </div>

        <div id="learnMode"><div class="card-grid" id="cardContainer"></div></div>

        <div id="playMode" style="display: none;">
            <div class="game-area">
                <div class="monster-box">
                    <span class="monster" id="monsterEmoji">👾</span>
                    <span style="font-size:1.1em;">听发音,选对单词击败它!</span>
                </div>
                <div class="options" id="optionsContainer"></div>
                <div class="feedback" id="feedback"></div>
                <div class="score">🏆 得分: <span id="score">0</span></div>
                <button class="option-btn" onclick="nextRound()" style="margin-top:15px; background:#e94560;">跳过 / 下一题 ➡️</button>
            </div>
        </div>

        <div id="readMode" style="display: none;">
            <div class="read-settings">
                <label>🔁 朗读次数
                    <input type="number" id="repeatCountInput" value="1" min="1" max="3" step="1">
                </label>
                <label>⏱️ 单词间隔 (秒)
                    <input type="number" id="intervalInput" value="2" min="1" max="5" step="0.5">
                </label>
            </div>
            <div class="read-display">
                <div class="read-word" id="readWord">---</div>
                <div class="read-phonetic" id="readPhonetic"></div>
                <div class="read-meaning" id="readMeaning"></div>
                <div class="read-progress" id="readProgress">0 / 0</div>
            </div>
            <div class="read-controls">
                <button class="primary" id="readStartBtn" onclick="startReading()">▶ 开始领读</button>
                <button id="readPauseBtn" onclick="pauseReading()" style="display:none;">⏸️ 暂停</button>
                <button id="readResumeBtn" onclick="resumeReading()" style="display:none;">▶️ 继续</button>
                <button onclick="stopReading()">⏹️ 停止</button>
            </div>
        </div>
    </div>

    <div class="help-modal" id="helpModal">
        <div class="help-content">
            <button class="close-help" onclick="closeHelp()">✖</button>
            <h2>📖 使用帮助</h2>
            <h3>🗂️ 默认内置词库</h3>
            <p>默认小学常用单词 </p>
            <h3>📂 词库导入</h3>
            <p>支持上传 <code>.txt</code> 文件,每行一个单词,字段之间用 <code> # </code> 分隔。<br>
            <strong>格式:</strong> <code>单词 # 释义 # 音标 # emoji</code> (后两项可选)。</p>
            <p><strong>示例(不分年级):</strong></p>
            <pre style="background:rgba(0,0,0,0.3); padding:10px; border-radius:10px; overflow-x:auto;">
apple # 苹果 # /ˈæpl/ # 🍎
banana # 香蕉 # /bəˈnɑːnə/ # 🍌
cat # 猫 # /kæt/ # 🐱</pre>
            <p><strong>如果要分年级显示,</strong>请在单词前添加年级标头行,如 <code>三年级:</code> 或 <code>3年级:</code> 均可。</p>
            <pre style="background:rgba(0,0,0,0.3); padding:10px; border-radius:10px; overflow-x:auto;">
三年级:
pen # 钢笔 # /pen/ # 🖊️
pencil # 铅笔 # /ˈpensl/ # ✏️

四年级:
classroom # 教室 # /ˈklɑːsruːm/ # 🏫
window # 窗户 # /ˈwɪndəʊ/ # 🪟</pre>
            <p><strong>注意事项:</strong></p>
            <ul>
                <li>文件请保存为 <strong>UTF-8 编码</strong>。</li>
                <li>年级标头中的冒号为英文冒号(<code>:</code>)。</li>
                <li>没有年级标头时所有单词自动归入"全部"类别。</li>
                <li>导入后自动替换内置词库,并刷新所有模式。</li>
            </ul>
            <h3>📖 魔法图鉴</h3>
            <ul><li>浏览单词卡片,点击听发音。</li></ul>
            <h3>⚔️ 咒语对决</h3>
            <ul><li>听发音选单词,得分击败怪兽。</li></ul>
            <h3>🔊 领读模式</h3>
            <ul><li>自动朗读,可设重复次数和间隔。</li></ul>
            <h3>🔊 推荐使用 Microsoft Edge浏览器</h3>
            <ul><li>针对 Edge 浏览器的 Neural 神经网络语音进行了最深层的算法适配。提示:断网可能导致TTS声音降级,联网朗读效果最佳。</li></ul>
            <ul><li>内置发音修正表pronunciationFix可调整个别单词的发音。</li></ul>
            <p style="text-align:center; margin-top:25px; opacity:0.8;">祝学习愉快!✨</p>
        </div>
    </div>

    <script>
        // ============================================================
        //  1. 内置词库(文本格式)
        // ============================================================
        const builtInWordsText = `
三年级:
I # 我 # /aɪ/ # 
am # 是 # /æm/ # 
I'm # 我是 # /aɪm/ # 
hello # 你好 # /həˈləʊ/ # 👋
hi # 嗨 # /haɪ/ # 🙌
goodbye # 再见 # /ˌɡʊdˈbaɪ/ # 👋
bye-bye # 拜拜 # /baɪ baɪ/ # 👋
are # 是 # /ɑː(r)/ # 
good # 好的 # /ɡʊd/ # 👍
morning # 早晨,上午 # /ˈmɔːnɪŋ/ # 🌅
fine # 健康的 # /faɪn/ # 😊
thank # 谢谢 # /θæŋk/ # 🙏
you # 你,你们 # /juː/ # 
how are you # 你好吗 # /haʊ ɑː juː/ # 
Ms # 女士 # /mɪz/ # 👩
boy # 男孩 # /bɔɪ/ # 👦
girl # 女孩 # /ɡɜːl/ # 👧
and # 和;那么 # /ənd/ # 
too # 也 # /tuː/ # 
what # 什么 # /wɒt/ # 
what's # 是什么 # /wɒts/ # 
is # 是 # /ɪz/ # 
your # 你的 # /jɔː(r)/ # 
name # 名字 # /neɪm/ # 📛
please # 请 # /pliːz/ # 🙇
afternoon # 下午 # /ˌɑːftəˈnuːn/ # 🌤️
Mr # 先生 # /ˈmɪstə(r)/ # 👨
ha ha # 哈哈 # /hɑː hɑː/ # 
whoops # 哎哟 # /wuːps/ # 
point # 指 # /pɔɪnt/ # 👉
to # 向;朝 # /tuː/ # 
the # 这/那;这些/那些 # /ðə/ # 
door # 门 # /dɔː(r)/ # 🚪
sit # 坐 # /sɪt/ # 🪑
down # 向下 # /daʊn/ # ⬇️
sit down # 坐下 # /sɪt daʊn/ # 🪑
stand # 站 # /stænd/ # 🧍
up # 向上 # /ʌp/ # ⬆️
stand up # 起立 # /stænd ʌp/ # 🧍
window # 窗户 # /ˈwɪndəʊ/ # 🪟
blackboard # 黑板 # /ˈblækbɔːd/ # ⬛·
bird # 鸟 # /bɜːd/ # 🐦
tweet # 啾啾(鸟叫) # /twiːt/ # 
desk # 书桌 # /desk/ # 📑
chair # 椅子 # /tʃeə(r)/ # 🪑
it # 它 # /ɪt/ # 
it's # 它是 # /ɪts/ # 
red # 红色的 # /red/ # 🔴
look # 看 # /lʊk/ # 👀
wow # 哇 # /waʊ/ # 
yellow # 黄色的 # /ˈjeləʊ/ # 🟡
blue # 蓝色的 # /bluː/ # 🔵
a # 一个 # /ə/ # 
an # 一个 # /æn/ # 
chameleon # 变色龙 # /kəˈmiːliən/ # 🦎
my # 我的 # /maɪ/ # 
panda # 熊猫 # /ˈpændə/ # 🐼
now # 现在 # /naʊ/ # 
green # 绿色的 # /ɡriːn/ # 🟢
black # 黑色的 # /blæk/ # ⚫
dog # 狗 # /dɒɡ/ # 🐶
cat # 猫 # /kæt/ # 🐱
cap # 帽子 # /kæp/ # 🧢
many # 许多 # /ˈmeni/ # 
how many # 多少 # /haʊ ˈmeni/ # 
one # 一 # /wʌn/ # 1️⃣
two # 二 # /tuː/ # 2️⃣
three # 三 # /θriː/ # 3️⃣
four # 四 # /fɔː(r)/ # 4️⃣
five # 五 # /faɪv/ # 5️⃣
six # 六 # /sɪks/ # 6️⃣
seven # 七 # /ˈsevn/ # 7️⃣
eight # 八 # /eɪt/ # 8️⃣
nine # 九 # /naɪn/ # 9️⃣
oh # 哦 # /əʊ/ # 
ten # 十 # /ten/ # 🔟
eleven # 十一 # /ɪˈlevn/ # 11️⃣
twelve # 十二 # /twelv/ # 12️⃣
happy # 快乐的 # /ˈhæpi/ # 😄
birthday # 生日 # /ˈbɜːθdeɪ/ # 🎂
here # 这里 # /hɪə(r)/ # 📍
here's # 这是 # /hɪəz/ # 
present # 礼物 # /ˈpreznt/ # 🎁
this # 这个 # /ðɪs/ # 👉
pencil # 铅笔 # /ˈpensl/ # ✏️
pen # 钢笔 # /pen/ # 🖊️
cake # 蛋糕 # /keɪk/ # 🍰
old # 年岁的;老的 # /əʊld/ # 👴
yes # 是的 # /jes/ # ✅
no # 不 # /nəʊ/ # ❌
teacher # 教师 # /ˈtiːtʃə(r)/ # 👩‍🏫
pupil # 小学生 # /ˈpjuːpl/ # 🎒
school # 学校 # /skuːl/ # 🏫
classroom # 教室 # /ˈklɑːsruːm/ # 🏡
English # 英语 # /ˈɪŋɡlɪʃ/ # 📖
that # 那个 # /ðæt/ # 👈
say # 说 # /seɪ/ # 🗣️
again # 再一次 # /əˈɡeɪn/ # 🔁
schoolbag # 书包 # /ˈskuːlbæɡ/ # 🎒
bag # 包 # /bæɡ/ # 👜
ball # 球 # /bɔːl/ # ⚽
book # 书 # /bʊk/ # 📕
monster # 怪物 # /ˈmɒnstə(r)/ # 👾
kite # 风筝 # /kaɪt/ # 🪁
new # 新的 # /njuː/ # 🆕
or # 或者 # /ɔː(r)/ # 
know # 知道 # /nəʊ/ # 💡
help # 救命;帮助 # /help/ # 🆘
in # 在......里面 # /ɪn/ # 
father # 爸爸,父亲 # /ˈfɑːðə(r)/ # 👨
dad # 爸爸 # /dæd/ # 👨
mother # 妈妈,母亲 # /ˈmʌðə(r)/ # 👩
mum # 妈妈 # /mʌm/ # 👩
sister # 姐妹 # /ˈsɪstə(r)/ # 👧
brother # 兄弟 # /ˈbrʌðə(r)/ # 👦
grandma # 奶奶,外婆 # /ˈɡrænmɑː/ # 👵
grandpa # 爷爷,外公 # /ˈɡrænpɑː/ # 👴
family # 家庭,家人 # /ˈfæməli/ # 👨‍👩‍👧‍👦
doctor # 医生 # /ˈdɒktə(r)/ # 👨‍⚕️
nurse # 护士 # /nɜːs/ # 👩‍⚕️
driver # 司机 # /ˈdraɪvə(r)/ # 🚗
farmer # 农民 # /ˈfɑːmə(r)/ # 🌾
body # 身体 # /ˈbɒdi/ # 🧍
head # 头 # /hed/ # 👤
hand # 手 # /hænd/ # ✋
arm # 胳膊 # /ɑːm/ # 💪
leg # 腿 # /leɡ/ # 🦵
foot # 脚 # /fʊt/ # 🦶
feet # 脚(复数) # /fiːt/ # 🦶
eye # 眼睛 # /aɪ/ # 👁️
ear # 耳朵 # /ɪə(r)/ # 👂
mouth # 嘴巴 # /maʊθ/ # 👄
nose # 鼻子 # /nəʊz/ # 👃
ruler # 尺子 # /ˈruːlə(r)/ # 📏
eraser # 橡皮 # /ɪˈreɪzə(r)/ # 🧽
orange # 橙色;橙子 # /ˈɒrɪndʒ/ # 🍊
tiger # 老虎 # /ˈtaɪɡə(r)/ # 🐅
lion # 狮子 # /ˈlaɪən/ # 🦁
elephant # 大象 # /ˈelɪfənt/ # 🐘
monkey # 猴子 # /ˈmʌŋki/ # 🐒
panda # 熊猫 # /ˈpændə/ # 🐼
bear # 熊 # /beə(r)/ # 🐻
short # 矮的;短的 # /ʃɔːt/ # 📏
tall # 高的 # /tɔːl/ # 📐
fat # 胖的 # /fæt/ # 🐷
thin # 瘦的 # /θɪn/ # 📉
big # 大的 # /bɪɡ/ # 🔵
small # 小的 # /smɔːl/ # ⚪
they # 他们;她们;它们 # /ðeɪ/ # 
they're # 他们是 # /ðeə(r)/ # 
fruit # 水果 # /fruːt/ # 🍓
apple # 苹果 # /ˈæpl/ # 🍎
banana # 香蕉 # /bəˈnɑːnə/ # 🍌
pear # 梨 # /peə(r)/ # 🍐
milk # 牛奶 # /mɪlk/ # 🥛
here you are # 给你 # /hɪə(r) juː ɑː(r)/ # 🤲
thank you # 谢谢你 # /θæŋk juː/ # 🙏
like # 喜欢 # /laɪk/ # ❤️
football # 足球 # /ˈfʊtbɔːl/ # ⚽
basketball # 篮球 # /ˈbɑːskɪtbɔːl/ # 🏀
table tennis # 乒乓球 # /ˈteɪbl tenɪs/ # 🏓
swim # 游泳 # /swɪm/ # 🏊
ride # 骑 # /raɪd/ # 🚲
bike # 自行车 # /baɪk/ # 🚴
skip # 跳绳 # /skɪp/ # 🪀
skip rope # 跳绳 # /skɪp rəʊp/ # 🪀
meat # 肉 # /miːt/ # 🥩
rice # 米饭 # /raɪs/ # 🍚
noodles # 面条 # /ˈnuːdlz/ # 🍜
fish # 鱼;鱼肉 # /fɪʃ/ # 🐟
egg # 鸡蛋 # /eɡ/ # 🥚
get up # 起床 # /ɡet ʌp/ # ⏰
go to school # 去上学 # /ɡəʊ tuː skuːl/ # 🏫
have lunch # 吃午餐 # /hæv lʌntʃ/ # 🍱
go home # 回家 # /ɡəʊ həʊm/ # 🏠
go to bed # 上床睡觉 # /ɡəʊ tuː bed/ # 🛏️
morning # 早上 # /ˈmɔːnɪŋ/ # 🌅
afternoon # 下午 # /ˌɑːftəˈnuːn/ # 🌤️
evening # 晚上 # /ˈiːvnɪŋ/ # 🌙
what # 什么 # /wɒt/ # 
time # 时间 # /taɪm/ # ⏱️
o'clock # ......点钟 # /əˈklɒk/ # 🕐
hour # 小时 # /ˈaʊə(r)/ # ⌛
half # 半 # /hɑːf/ # 
past # 过(几点) # /pɑːst/ # 
late # 迟的,晚的 # /leɪt/ # 🚨
park # 公园 # /pɑːk/ # 🌳
lake # 湖 # /leɪk/ # 🏞️
tree # 树 # /triː/ # 🌲
boat # 小船 # /bəʊt/ # 🚣
read # 读,阅读 # /riːd/ # 📖
listen # 听 # /ˈlɪsn/ # 👂
listen to # 听...... # /ˈlɪsn tuː/ # 🎧
talk # 交谈 # /tɔːk/ # 🗣️
spring # 春天 # /sprɪŋ/ # 🌱
summer # 夏天 # /ˈsʌmə(r)/ # ☀️
autumn # 秋天 # /ˈɔːtəm/ # 🍂
winter # 冬天 # /ˈwɪntə(r)/ # ❄️
warm # 温暖的 # /wɔːm/ # 🔥
hot # 热的 # /hɒt/ # 🌡️
cool # 凉爽的 # /kuːl/ # 🍃
cold # 寒冷的 # /kəʊld/ # 🧊
clothes # 衣服 # /kləʊðz/ # 👕
coat # 外套 # /kəʊt/ # 🧥
dress # 连衣裙 # /dres/ # 👗
shirt # 衬衫 # /ʃɜːt/ # 👔
shoe # 鞋子 # /ʃuː/ # 👟
shoes # 鞋子(复数) # /ʃuːz/ # 👟
sock # 袜子 # /sɒk/ # 🧦
socks # 袜子(复数) # /sɒks/ # 🧦
cap # 鸭舌帽 # /kæp/ # 🧢
hat # 礼帽 # /hæt/ # 🎩
toy # 玩具 # /tɔɪ/ # 🧸
car # 小汽车 # /kɑː(r)/ # 🚗
train # 玩具火车 # /treɪn/ # 🚂
doll # 布娃娃 # /dɒl/ # 🪆
ship # 轮船 # /ʃɪp/ # 🚢
plane # 飞机玩具 # /pleɪn/ # ✈️
water # 水 # /ˈwɔːtə(r)/ # 💧
food # 食物 # /fuːd/ # 🍱
orange juice # 橙汁 # /ˈɒrɪndʒ dʒuːs/ # 🧃

四年级:
nice # 友好的,讨人喜欢的 # /naɪs/ # 😊
clever # 聪明的 # /ˈklevə(r)/ # 🧠
naughty # 淘气的 # /ˈnɔːti/ # 🙈
a bit # 有一点 # /ə bɪt/ # 📏
shy # 害羞的 # /ʃaɪ/ # 🙊
answer # 回答 # /ˈɑːnsə(r)/ # 💬
call # 打电话;称呼 # /kɔːl/ # 📞
bad # 不好的,坏的 # /bæd/ # 👎
cool # 酷的 # /kuːl/ # 😎
city # 城市 # /ˈsɪti/ # 🏙️
ship # 轮船 # /ʃɪp/ # 🚢
beautiful # 美丽的 # /ˈbjuːtɪfl/ # 🌸
whose # 谁的 # /huːz/ # 
close # 近的,靠近的 # /kləʊz/ # 🤏
old # 古老的;旧的 # /əʊld/ # 🏯
famous # 著名的 # /ˈfeɪməs/ # ⭐
robot # 机器人 # /ˈrəʊbɒt/ # 🤖
will # 将,将会 # /wɪl/ # 
won't # 将不会 # /wəʊnt/ # 
everything # 所有事情 # /ˈevriθɪŋ/ # 📦
housework # 家务 # /ˈhaʊswɜːk/ # 🧹
learn # 学习 # /lɜːn/ # 📚
our # 我们的 # /ˈaʊə(r)/ # 
homework # 家庭作业 # /ˈhəʊmwɜːk/ # 📝
Tuesday # 星期二 # /ˈtjuːzdeɪ/ # 2️⃣
Wednesday # 星期三 # /ˈwenzdeɪ/ # 3️⃣
Thursday # 星期四 # /ˈθɜːzdeɪ/ # 4️⃣
Friday # 星期五 # /ˈfraɪdeɪ/ # 5️⃣
take # 搭乘;乘坐 # /teɪk/ # 🚌
train # 火车 # /treɪn/ # 🚞
plane # 飞机 # /pleɪn/ # ✈️
bus # 公共汽车 # /bʌs/ # 🚌
beside # 在......旁边 # /bɪˈsaɪd/ # 📍
hospital # 医院 # /ˈhɒspɪtl/ # 🏥
station # 车站 # /ˈsteɪʃn/ # 🚉
supermarket # 超市 # /ˈsuːpəmɑːkɪt/ # 🛒
cinema # 电影院 # /ˈsɪnəmə/ # 🎬
park # 公园 # /pɑːk/ # 🌳
weather # 天气 # /ˈweðə(r)/ # 🌤️
like # 像......那样 # /laɪk/ # 
rain # 下雨;雨水 # /reɪn/ # 🌧️
sun # 太阳 # /sʌn/ # ☀️
snow # 下雪;雪 # /snəʊ/ # ❄️
wind # 风 # /wɪnd/ # 💨
cloud # 云 # /klaʊd/ # ☁️
rainy # 下雨的 # /ˈreɪni/ # 🌧️
sunny # 晴朗的 # /ˈsʌni/ # ☀️
windy # 刮风的 # /ˈwɪndi/ # 💨
cloudy # 多云的 # /ˈklaʊdi/ # ☁️
grandma # 祖母,奶奶,外婆 # /ˈɡrænmɑː/ # 👵
grandpa # 祖父,爷爷,外公 # /ˈɡrænpɑː/ # 👴
then # 当时,那时 # /ðen/ # 
hair # 头发 # /heə(r)/ # 💇
so # 如此,这么 # /səʊ/ # 
short # 短的 # /ʃɔːt/ # 📏
long # 长的 # /lɒŋ/ # 📐
was # (is/am 的过去式)是 # /wɒz/ # 
were # (are 的过去式)是 # /wɜː(r)/ # 
hometown # 家乡 # /ˈhəʊmtaʊn/ # 🏡
young # 年轻的 # /jʌŋ/ # 🧑
old # 年老的 # /əʊld/ # 👴
beautiful # 美丽的 # /ˈbjuːtɪfl/ # 🌷
dirty # 脏的 # /ˈdɜːti/ # 🤢
clean # 干净的 # /kliːn/ # 🧼
Saturday # 星期六 # /ˈsætədeɪ/ # 6️⃣
Sunday # 星期日 # /ˈsʌndeɪ/ # 7️⃣
paint # 绘画;颜料 # /peɪnt/ # 🎨
picture # 图画,照片 # /ˈpɪktʃə(r)/ # 🖼️
quiet # 安静的 # /ˈkwaɪət/ # 🤫
hard # 努力地;困难的 # /hɑːd/ # 💪
sport # 体育运动 # /spɔːt/ # ⚽
play football # 踢足球 # /pleɪ ˈfʊtbɔːl/ # ⚽
play basketball # 打篮球 # /pleɪ ˈbɑːskɪtbɔːl/ # 🏀
run fast # 跑得快 # /rʌn fɑːst/ # 🏃💨
jump high # 跳得高 # /dʒʌmp haɪ/ # 🦘
star # 明星 # /stɑː(r)/ # ⭐
horse # 马 # /hɔːs/ # 🐎
cow # 奶牛 # /kaʊ/ # 🐄
pig # 猪 # /pɪɡ/ # 🐖
sheep # 绵羊 # /ʃiːp/ # 🐑
farm # 农场 # /fɑːm/ # 🌾
farmer # 农民 # /ˈfɑːmə(r)/ # 👨🌾
close # 关上 # /kləʊz/ # 🚪
window # 窗户 # /ˈwɪndəʊ/ # 🪟
door # 门 # /dɔː(r)/ # 🚪
light # 灯 # /laɪt/ # 💡
fan # 风扇 # /fæn/ # 🪭
TV # 电视机 # /ˌtiː ˈviː/ # 📺
help # 帮助 # /help/ # 🤝
minute # 分钟 # /ˈmɪnɪt/ # ⏱️
house # 房子 # /haʊs/ # 🏠
room # 房间 # /ruːm/ # 🛋️
bedroom # 卧室 # /ˈbedruːm/ # 🛏️
living room # 客厅 # /ˈlɪvɪŋ ruːm/ # 📺
dining room # 餐厅 # /ˈdaɪnɪŋ ruːm/ # 🍽️
kitchen # 厨房 # /ˈkɪtʃɪn/ # 🍳
bathroom # 卫生间 # /ˈbɑːθruːm/ # 🚿
really # 真的 # /ˈriːəli/ # ❗
watch # 观看 # /wɒtʃ/ # 👀
football game # 足球比赛 # /ˈfʊtbɔːl ɡeɪm/ # ⚽
play # 玩;演奏 # /pleɪ/ # 🎮
basketball # 篮球 # /ˈbɑːskɪtbɔːl/ # 🏀
table tennis # 乒乓球 # /ˈteɪbl tenɪs/ # 🏓
jump # 跳 # /dʒʌmp/ # 🦘
dance # 跳舞 # /dɑːns/ # 💃
sing # 唱歌 # /sɪŋ/ # 🎤
week # 星期,周 # /wiːk/ # 📅
Monday # 星期一 # /ˈmʌndeɪ/ # 1️⃣
Tuesday # 星期二 # /ˈtjuːzdeɪ/ # 2️⃣
Wednesday # 星期三 # /ˈwenzdeɪ/ # 3️⃣
Thursday # 星期四 # /ˈθɜːzdeɪ/ # 4️⃣
Friday # 星期五 # /ˈfraɪdeɪ/ # 5️⃣
Saturday # 星期六 # /ˈsætədeɪ/ # 6️⃣
Sunday # 星期日 # /ˈsʌndeɪ/ # 7️⃣
weather # 天气 # /ˈweðə(r)/ # 🌤️
warm # 温暖的 # /wɔːm/ # ☀️
cold # 寒冷的 # /kəʊld/ # ❄️
hot # 炎热的 # /hɒt/ # 🔥
cool # 凉爽的 # /kuːl/ # 🍃
windy # 刮风的 # /ˈwɪndi/ # 💨
rainy # 下雨的 # /ˈreɪni/ # 🌧️
sunny # 晴朗的 # /ˈsʌni/ # ☀️
father # 父亲,爸爸 # /ˈfɑːðə(r)/ # 👨
mother # 母亲,妈妈 # /ˈmʌðə(r)/ # 👩
parent # 父母之一 # /ˈpeərənt/ # 👫
grandparent # (外)祖父(母) # /ˈɡrænpeərənt/ # 👴👵
brother # 兄弟 # /ˈbrʌðə(r)/ # 👦
sister # 姐妹 # /ˈsɪstə(r)/ # 👧
me # 我(宾格) # /miː/ # 
him # 他(宾格) # /hɪm/ # 
her # 她(宾格) # /hɜː(r)/ # 
city # 城市 # /ˈsɪti/ # 🏙️
village # 村庄 # /ˈvɪlɪdʒ/ # 🏘️
small # 小的 # /smɔːl/ # 🔘
big # 大的 # /bɪɡ/ # 🔵
tall # 高的 # /tɔːl/ # 🏢
short # 矮的 # /ʃɔːt/ # 🪑
beautiful # 美丽的 # /ˈbjuːtɪfl/ # 🌸
cake # 蛋糕 # /keɪk/ # 🎂
candy # 糖果 # /ˈkændi/ # 🍬
fruit # 水果 # /fruːt/ # 🍓
drink # 饮料;喝 # /drɪŋk/ # 🥤
water # 水 # /ˈwɔːtə(r)/ # 💧
milk # 牛奶 # /mɪlk/ # 🥛
juice # 果汁 # /dʒuːs/ # 🧃
animal # 动物 # /ˈænɪml/ # 🐾
snake # 蛇 # /sneɪk/ # 🐍
bird # 小鸟 # /bɜːd/ # 🐦
love # 喜爱 # /lʌv/ # ❤️
pet # 宠物 # /pet/ # 🐹
festival # 节日 # /ˈfestɪvl/ # 🎉
Spring Festival # 春节 # /sprɪŋ ˈfestɪvl/ # 🧨
dragon # 龙 # /ˈdræɡən/ # 🐉
firecracker # 鞭炮 # /ˈfaɪəkrækə(r)/ # 🧨
year # 年 # /jɪə(r)/ # 📅

五年级:
list # 清单 # /lɪst/ # 📋
er # 哦,嗯(语气词) # /ɜː(r)/ # 
need # 需要 # /niːd/ # 🛒
first # 首先;第一 # /fɜːst/ # 
can # 可以;能 # /kæn/ # 
can't # 不能;不可以 # /kænt/ # 
lost # 丢失的 # /lɒst/ # 🔍
how much # 多少(钱) # /haʊ mʌtʃ/ # 💰
cheese # 奶酪 # /tʃiːz/ # 🧀
any # 一些;任何 # /ˈeni/ # 
over there # 在那边 # /ˈəʊvə ðeə(r)/ # 👉
bag # 包 # /bæɡ/ # 👜
back # 回来,返回 # /bæk/ # ↩️
last # 最近过去的;上一个 # /lɑːst/ # 
weekend # 周末 # /ˌwiːkˈend/ # 📅
place # 地方 # /pleɪs/ # 📍
British # 英国的;英国人 # /ˈbrɪtɪʃ/ # 🇬🇧
museum # 博物馆 # /mjuˈziːəm/ # 🏛️
how # 如何,怎样 # /haʊ/ # 
best # 最 # /best/ # 
took # 搭乘;拍照(take过去式) # /tʊk/ # 📸
trip # 旅行 # /trɪp/ # 🚞
along # 沿着 # /əˈlɒŋ/ # 
river # 河,江 # /ˈrɪvə(r)/ # 🌊
hour # 小时 # /ˈaʊə(r)/ # ⌛
twenty # 二十 # /ˈtwenti/ # 2️⃣0️⃣
minute # 分钟 # /ˈmɪnɪt/ # ⏱️
week # 星期,周 # /wiːk/ # 🗓️
policeman # 警察(单数) # /pəˈliːsmən/ # 👮
policemen # 警察(复数) # /pəˈliːsmən/ # 👮‍♂️👮‍♂️
child # 小孩(单数) # /tʃaɪld/ # 👶
children # 孩子们(复数) # /ˈtʃɪldrən/ # 👧👦
wear # 穿,戴 # /weə(r)/ # 🧥
hat # 宽檐礼帽 # /hæt/ # 🎩
funny # 滑稽的,好笑的 # /ˈfʌni/ # 🤪
copy # 复印件;模仿 # /ˈkɒpi/ # 📄
orange # 橙色的;橙子 # /ˈɒrɪndʒ/ # 🍊
pair # 一套,一双,一副 # /peə(r)/ # 🧦
shorts # 短裤 # /ʃɔːts/ # 🩳
argue # 争吵,争论 # /ˈɑːɡjuː/ # 💢
matter # 问题,麻烦事 # /ˈmætə(r)/ # ❓
wear # 穿 # /weə(r)/ # 👕
sports # 体育运动 # /spɔːts/ # ⚽
coat # 外套,大衣 # /kəʊt/ # 🧥
angry # 生气的 # /ˈæŋɡri/ # 😡
cap # 有檐鸭舌帽 # /kæp/ # 🧢
nineteen # 十九 # /ˌnaɪnˈtiːn/ # 1️⃣9️⃣
crayon # 蜡笔 # /ˈkreɪɒn/ # 🖍️
fifteen # 十五 # /ˌfɪfˈtiːn/ # 1️⃣5️⃣
begin # 开始 # /bɪˈɡɪn/ # ▶️
floor # 地面,地板 # /flɔː(r)/ # 🪵
all # 全部,所有 # /ɔːl/ # 
best # 最 # /best/ # 
basketball # 篮球 # /ˈbɑːskɪtbɔːl/ # 🏀
football # 足球 # /ˈfʊtbɔːl/ # ⚽
table tennis # 乒乓球 # /ˈteɪbl tenɪs/ # 🏓
swimming # 游泳 # /ˈswɪmɪŋ/ # 🏊
team # 运动队,球队 # /tiːm/ # 🤝
really # 真正地 # /ˈriːəli/ # ❗
want # 想要 # /wɒnt/ # 💖
airport # 机场 # /ˈeəpɔːt/ # ✈️
sea # 大海 # /siː/ # 🌊
visit # 参观,拜访 # /ˈvɪzɪt/ # 👋
holiday # 假期 # /ˈhɒlədeɪ/ # 🏖️
make # 制作 # /meɪk/ # 🛠️
paper # 纸 # /ˈpeɪpə(r)/ # 📃
boat # 小船 # /bəʊt/ # 🚣
laugh # 笑 # /lɑːf/ # 😂
cup # 杯子 # /kʌp/ # 🥤
plan # 计划 # /plæn/ # 📝
baseball # 棒球 # /ˈbeɪsbɔːl/ # ⚾
more # 更多的 # /mɔː(r)/ # 
mistake # 错误 # /mɪˈsteɪk/ # ❌
word # 单词,字 # /wɜːd/ # 🔤
backpack # 双肩背包 # /ˈbækpæk/ # 🎒
heavy # 重的 # /ˈhevi/ # ⚖️
light # 轻的 # /laɪt/ # 🪶
hard # 硬的 # /hɑːd/ # 
soft # 柔软的 # /sɒft/ # ☁️
bored # 无聊的 # /bɔːd/ # 😔
sad # 伤心的 # /sæd/ # 😢
thirsty # 口渴的 # /ˈθɜːsti/ # 🥤
tired # 疲惫的 # /ˈtaɪəd/ # 😫
shop # 商店 # /ʃɒp/ # 🏪
cost # 花费 # /kɒst/ # 💰
cheap # 便宜的 # /tʃiːp/ # 💸
expensive # 昂贵的 # /ɪkˈspensɪv/ # 💎
hundred # 百 # /ˈhʌndrəd/ # 💯
life # 生活 # /laɪf/ # 🌿
different # 不同的 # /ˈdɪfrənt/ # 
ago # 以前 # /əˈɡəʊ/ # 
house # 房子 # /haʊs/ # 🏠
enough # 足够的 # /ɪˈnʌf/ # 
food # 食物 # /fuːd/ # 🍱
television # 电视机 # /ˈtelɪvɪʒn/ # 📺
watch # 观看 # /wɒtʃ/ # 👀
grandchildren # (外)孙子孙女们 # /ˈɡræntʃɪldrən/ # 👧👦
change # 改变 # /tʃeɪndʒ/ # 🔄
learn # 学习 # /lɜːn/ # 📖
dance # 跳舞;舞蹈 # /dɑːns/ # 💃
foreign # 外国的 # /ˈfɒrən/ # 🌍
language # 语言 # /ˈlæŋɡwɪdʒ/ # 🗣️
wrote # 写(write过去式) # /rəʊt/ # ✍️
hard # 努力地 # /hɑːd/ # 💪
card # 卡片 # /kɑːd/ # 💳
hamburger # 汉堡包 # /ˈhæmbɜːɡə(r)/ # 🍔
English # 英国的;英语 # /ˈɪŋɡlɪʃ/ # 🇬🇧
sun # 太阳 # /sʌn/ # ☀️
moon # 月亮 # /muːn/ # 🌙
star # 星星 # /stɑː(r)/ # ⭐
astronaut # 宇航员 # /ˈæstrənɔːt/ # 👨‍🚀
space # 太空 # /speɪs/ # 🌌
travel # 旅行 # /ˈtrævl/ # 🚀
interested # 感兴趣的 # /ˈɪntrəstɪd/ # 🧐
model # 模型 # /ˈmɒdl/ # 🛠️
national # 国家的 # /ˈnæʃnəl/ # 🇨🇳
weekend # 周末 # /ˌwiːkˈend/ # 🗓️
read # 阅读 # /riːd/ # 📚
play # 玩;演奏 # /pleɪ/ # 🎮
paint # 绘画 # /peɪnt/ # 🎨
computer # 电脑 # /kəmˈpjuːtə(r)/ # 💻
game # 游戏 # /ɡeɪm/ # 🎲
listen # 听 # /ˈlɪsn/ # 👂
music # 音乐 # /ˈmjuːzɪk/ # 🎵
time # 时间 # /taɪm/ # ⏰
clock # 钟表 # /klɒk/ # 🕰️
half # 一半 # /hɑːf/ # 
past # 过(几点) # /pɑːst/ # 
late # 迟的 # /leɪt/ # 🚨
start # 开始 # /stɑːt/ # ▶️
skip # 跳绳 # /skɪp/ # 🪀
coffee # 咖啡 # /ˈkɒfi/ # ☕
earth # 地球 # /ɜːθ/ # 🌍
space # 太空 # /speɪs/ # 🌌
land # 陆地;登陆 # /lænd/ # 🏞️
sea # 大海 # /siː/ # 🌊
river # 河流 # /ˈrɪvə(r)/ # 🌊
mountain # 大山 # /ˈmaʊntən/ # ⛰️
forest # 森林 # /ˈfɒrɪst/ # 🌳
flying # 飞 # /ˈflaɪɪŋ/ # 🦅
kite # 风筝 # /kaɪt/ # 🪁
bike # 自行车 # /baɪk/ # 🚲
horse # 马 # /hɔːs/ # 🐎
run # 跑 # /rʌn/ # 🏃
fast # 快的 # /fɑːst/ # 💨
slow # 慢的 # /sləʊ/ # 🐢
team # 队伍 # /tiːm/ # 🤝
win # 赢 # /wɪn/ # 🏆
basket # 篮子 # /ˈbɑːskɪt/ # 🧺
football # 足球 # /ˈfʊtbɔːl/ # ⚽
fan # 粉丝;风扇 # /fæn/ # 🙋
well # 好,出色地 # /wel/ # 👍
letter # 信 # /ˈletə(r)/ # ✉️
story # 故事 # /ˈstɔːri/ # 📖
picture # 图画 # /ˈpɪktʃə(r)/ # 🖼️
write # 写 # /raɪt/ # ✍️
pen pal # 笔友 # /pen pæl/ # ✍️
hobby # 爱好 # /ˈhɒbi/ # 🎨
collect # 收集 # /kəˈlekt/ # 📦
stamp # 邮票 # /stæmp/ # 🪙
coconut # 椰子 # /ˈkəʊkənʌt/ # 🥥

六年级:
more # 更多的 # /mɔː(r)/ # 
hobby # 爱好 # /ˈhɒbi/ # 🎨
collect # 收集 # /kəˈlekt/ # 📦
stamp # 邮票 # /stæmp/ # 🪙
doll # 玩偶 # /dɒl/ # 🪆
bicycle # 自行车 # /ˈbaɪsɪkl/ # 🚲
photo # 照片 # /ˈfəʊtəʊ/ # 📷
ride # 骑 # /raɪd/ # 🚴
pen friend # 笔友 # /pen frend/ # ✉️
address # 地址 # /əˈdres/ # 📍
French # 法语;法国的 # /frentʃ/ # 🇫🇷
English # 英语;英国的 # /ˈɪŋɡlɪʃ/ # 🇬🇧
Japanese # 日语;日本的 # /ˌdʒæpəˈniːz/ # 🇯🇵
Chinese # 汉语;中国的 # /ˌtʃaɪˈniːz/ # 🇨🇳
age # 年龄 # /eɪdʒ/ # 🎂
story # 故事 # /ˈstɔːri/ # 📖
thanksgiving # 感恩节 # /ˌθæŋksˈɡɪvɪŋ/ # 🦃
flag # 旗帜 # /flæɡ/ # 🚩
special # 特殊的,特别的 # /ˈspeʃl/ # ⭐
meal # 一餐饭 # /miːl/ # 🍽️
football game # 足球比赛 # /ˈfʊtbɔːl ɡeɪm/ # ⚽
moon cake # 月饼 # /muːn keɪk/ # 🥮
lantern # 灯笼 # /ˈlæntən/ # 🏮
library # 图书馆 # /ˈlaɪbrəri/ # 📚
card # 卡片 # /kɑːd/ # 🪪
line # 排队;线 # /laɪn/ # 🧵
talk # 交谈 # /tɔːk/ # 🗣️
quiet # 安静的 # /ˈkwaɪət/ # 🤫
rule # 规则 # /ruːl/ # 📜
happy # 开心的 # /ˈhæpi/ # 😊
country # 国家 # /ˈkʌntri/ # 🌏
city # 城市 # /ˈsɪti/ # 🏙️
north # 北方;北部 # /nɔːθ/ # ⬆️
south # 南方;南部 # /saʊθ/ # ⬇️
east # 东方;东部 # /iːst/ # ➡️
west # 西方;西部 # /west/ # ⬅️
map # 地图 # /mæp/ # 🗺️
postcard # 明信片 # /ˈpəʊstkɑːd/ # 💌
grandparent # (外) 祖父母 # /ˈɡrænpeərənt/ # 👴👵
visit # 参观,拜访 # /ˈvɪzɪt/ # 👋
restaurant # 餐馆 # /ˈrestərɒnt/ # 🍲
opera # 戏曲 # /ˈɒpərə/ # 🎭
chopsticks # 筷子 # /ˈtʃɒpstɪks/ # 🥢
airport # 机场 # /ˈeəpɔːt/ # ✈️
ticket # 票 # /ˈtɪkɪt/ # 🎫
passport # 护照 # /ˈpɑːspɔːt/ # 📇
safe # 安全的 # /seɪf/ # 🛡️
dangerous # 危险的 # /ˈdeɪndʒərəs/ # ⚠️
trip # 旅行 # /trɪp/ # 🚞
stage # 舞台 # /steɪdʒ/ # 🎤
actor # 演员 # /ˈæktə(r)/ # 🧑‍🎤
interview # 采访 # /ˈɪntəvjuː/ # 🎙️
question # 问题 # /ˈkwestʃən/ # ❓
answer # 回答 # /ˈɑːnsə(r)/ # 💬
hard # 努力的 # /hɑːd/ # 💪
plan # 计划 # /plæn/ # 📝
summer holiday # 暑假 # /ˈsʌmə ˈhɒlədeɪ/ # 🏖️
stay # 停留 # /steɪ/ # 🏡
sea # 大海 # /siː/ # 🌊
swim # 游泳 # /swɪm/ # 🏊
middle school # 中学 # /ˈmɪdl skuːl/ # 🏫
secondary # 中等教育的 # /ˈsekəndri/ # 
subject # 科目 # /ˈsʌbdʒɪkt/ # 📚
geography # 地理 # /dʒiˈɒɡrəfi/ # 🗺️
hot dog # 热狗 # /hɒt dɒɡ/ # 🌭
cashier # 收银员 # /kæˈʃɪə(r)/ # 💁
cola # 可乐 # /ˈkəʊlə/ # 🥤
dollar # 美元 # /ˈdɒlə(r)/ # 💵
cent # 美分 # /sent/ # 🪙
enjoy # 享用;享受 # /ɪnˈdʒɔɪ/ # 😋
later # 后来,以后 # /ˈleɪtə(r)/ # 
duck # 鸭子 # /dʌk/ # 🦆
pond # 池塘 # /pɒnd/ # 💧
cloud # 云 # /klaʊd/ # ☁️
wind # 风 # /wɪnd/ # 💨
rain # 下雨;雨水 # /reɪn/ # 🌧️
snow # 下雪;雪 # /snəʊ/ # ❄️
cup # 杯子 # /kʌp/ # 🥤
baseball # 棒球 # /ˈbeɪsbɔːl/ # ⚾
more # 更多 # /mɔː(r)/ # 
mistake # 错误 # /mɪˈsteɪk/ # ❌
word # 单词 # /wɜːd/ # 🔤
said # 说(say 过去式) # /sed/ # 🗣️
bottle # 瓶子 # /ˈbɒtl/ # 🍶
can # 金属罐 # /kæn/ # 🥫
rubbish # 垃圾 # /ˈrʌbɪʃ/ # 🗑️
truck # 卡车 # /trʌk/ # 🚛
cycle # 循环 # /ˈsaɪkl/ # ♻️
reuse # 再使用 # /ˌriːˈjuːz/ # 🔁
space # 太空 # /speɪs/ # 🌌
travel # 旅行 # /ˈtrævl/ # 🚀
interested # 感兴趣的 # /ˈɪntrəstɪd/ # 🧐
spaceship # 宇宙飞船 # /ˈspeɪsʃɪp/ # 🛸
surprise # 惊喜 # /səˈpraɪz/ # 🎁
model # 模型 # /ˈmɒdl/ # 🛠️
middle # 中间的 # /ˈmɪdl/ # 🎯
middle school # 中学 # /ˈmɪdl skuːl/ # 🏫
speech # 演讲 # /spiːtʃ/ # 🎤
September # 九月 # /sepˈtembə(r)/ # 9️⃣
excited # 激动的 # /ɪkˈsaɪtɪd/ # 🤩
geography # 地理 # /dʒiˈɒɡrəfi/ # 🗺️
primary # 初等的;小学的 # /ˈpraɪməri/ # 📖
primary school # 小学 # /ˈpraɪməri skuːl/ # 🏫
keep # 保持;保留 # /kiːp/ # 📦
forever # 永远 # /fəˈrevə(r)/ # 
fun # 乐趣 # /fʌn/ # 😄
future # 将来,未来 # /ˈfjuːtʃə(r)/ # ⏭️
tea # 茶 # /tiː/ # 🍵
cup # 茶杯 # /kʌp/ # ☕
plan # 计划 # /plæn/ # 📝
basketball # 篮球 # /ˈbɑːskɪtbɔːl/ # 🏀
football # 足球 # /ˈfʊtbɔːl/ # ⚽
friend # 朋友 # /frend/ # 👫
wish # 愿望;祝愿 # /wɪʃ/ # 🙏
happiness # 幸福,快乐 # /ˈhæpinəs/ # 😊
best wishes # 最美好的祝愿 # /best ˈwɪʃɪz/ # 💌
luck # 运气 # /lʌk/ # 🍀
primary # 小学的 # /ˈpraɪməri/ # 🏫
new friend # 新朋友 # /njuː frend/ # 🤝
study # 学习 # /ˈstʌdi/ # 📖
subject # 学科 # /ˈsʌbdʒɪkt/ # 📚
`;

        function parseWordBank(text) {
            const chnNumMap = { '三': '3', '四': '4', '五': '5', '六': '6' };
            const lines = text.split(/\r?\n/)
                              .map(line => line.trim())
                              .filter(line => line !== '')
                              .map(line => {
                                  return line.replace(/^([三四五六])年级/, (match, chn) => {
                                      return (chnNumMap[chn] || chn) + '年级';
                                  });
                              });

            const parsed = {};
            let allWords = [];
            let currentGradeKey = null;

            lines.forEach(line => {
                if (/^\d年级/.test(line)) {
                    const match = line.match(/^(\d)年级/);
                    if (match) {
                        currentGradeKey = parseInt(match[1], 10);
                        if (!parsed[currentGradeKey]) parsed[currentGradeKey] = [];
                    }
                    return;
                }

                const parts = line.split('#').map(s => s.trim());
                if (parts.length < 2) return;
                const word = parts[0];
                const meaning = parts[1] || '';
                const phonetic = parts[2] || '';
                const emoji = parts[3] || '✦';
                if (word) {
                    const entry = { word, meaning, phonetic, emoji };
                    if (currentGradeKey !== null && parsed[currentGradeKey]) {
                        parsed[currentGradeKey].push(entry);
                    } else {
                        allWords.push(entry);
                    }
                }
            });

            if (Object.keys(parsed).length === 0 && allWords.length > 0) {
                parsed.all = allWords;
            }
            return parsed;
        }

        const builtInWords = parseWordBank(builtInWordsText);

        // ============================================================
        //  2. 全局变量与状态
        // ============================================================
        let currentGrade = 'all';
        let currentWords = [];
        let customWords = null;
        
        // 内置发音修正表:pronunciationFix表,其中冒号是标准的英文冒号(:),前面是属性名(Key),后面是属性值(Value)
        const pronunciationFix = {
            "Ms": "mizz",
            "o'clock": "o clock",
            "won't": "will not",
            "WHO": "W H O",          // 世界卫生组织
        };

        // 用于强力防止垃圾回收断音、哑音的宿主引用映射组件
        if (!window.activeSpeechUtterances) window.activeSpeechUtterances = [];
        let activeUtterance = null; // 用于精确终止幽灵端回调

        let cachedBestVoice = null;
        let readingActive = false;
        let readingPaused = false;
        let currentReadIndex = 0;
        let currentRepeatIndex = 0;
        let readDelayTimer = null;
        let gameTimer = null;

        const fileInput = document.getElementById('fileInput');
        const fileNameSpan = document.getElementById('fileName');
        const cardContainer = document.getElementById('cardContainer');
        const optionsContainer = document.getElementById('optionsContainer');
        const feedback = document.getElementById('feedback');
        const scoreSpan = document.getElementById('score');
        const monsterEmoji = document.getElementById('monsterEmoji');
        const gradeSelector = document.getElementById('gradeSelector');

        const readWordEl = document.getElementById('readWord');
        const readPhoneticEl = document.getElementById('readPhonetic');
        const readMeaningEl = document.getElementById('readMeaning');
        const readProgressEl = document.getElementById('readProgress');
        const readStartBtn = document.getElementById('readStartBtn');
        const readPauseBtn = document.getElementById('readPauseBtn');
        const readResumeBtn = document.getElementById('readResumeBtn');
        const repeatCountInput = document.getElementById('repeatCountInput');
        const intervalInput = document.getElementById('intervalInput');

        // ============================================================
        //  3. 发音前的清洗与纠音适配机制
        // ============================================================
        function cleanWordForSpeech(rawWord) {
            if (!rawWord) return "";
            // 规则 A: 移除任何括号及括号内的文本,比如 "pen (blue)" 净化为 "pen"
            let cleaned = rawWord.replace(/\([^)]*\)/g, "");
            cleaned = cleaned.replace(/\[[^\]]*\]/g, "");
            // 规则 B: 剔除斜杠、特定非常规语法字符,避免发音人读出 "slash"
            cleaned = cleaned.replace(/[\/\\]/g, " ");
            cleaned = cleaned.trim();
            // 规则 C: 优先映射拼写纠正表
            return pronunciationFix[cleaned] || cleaned;
        }

        function getBestEnglishVoice() {
            if (cachedBestVoice) return cachedBestVoice;
            if (!window.speechSynthesis) return null;
            const voices = window.speechSynthesis.getVoices();
            if (voices.length === 0) return null;

            let best = null;
            // 专为 Edge 浏览器锁定的 Neural 在线精品人
            best = voices.find(v => {
                const name = v.name.toLowerCase();
                const lang = v.lang.toLowerCase();
                return lang.startsWith('en') && name.includes('natural') && (name.includes('aria') || name.includes('jenny'));
            });
            if (!best) {
                best = voices.find(v => {
                    const name = v.name.toLowerCase();
                    const lang = v.lang.toLowerCase();
                    return lang.startsWith('en') && name.includes('natural');
                });
            }
            if (!best) {
                best = voices.find(v => {
                    const name = v.name.toLowerCase();
                    const lang = v.lang.toLowerCase();
                    return lang.startsWith('en') && (name.includes('zira') || name.includes('david'));
                });
            }
            if (best) cachedBestVoice = best;
            return best;
        }

        if (window.speechSynthesis) {
            window.speechSynthesis.onvoiceschanged = () => {
                cachedBestVoice = null;
                getBestEnglishVoice();
            };
        }

        // ============================================================
        //  4. 终极发音防卡死/防重音执行器
        // ============================================================
        function speakWord(word) {
            // 🎯 第一步:彻底清空、解除当前活跃 utterance 的一切幽灵回调绑定
            if (activeUtterance) {
                activeUtterance.onend = null;
                activeUtterance.onerror = null;
            }
            window.speechSynthesis.cancel();

            const textToSpeak = cleanWordForSpeech(word);
            if (!textToSpeak) return;

            const utterance = new SpeechSynthesisUtterance(textToSpeak);
            utterance.lang = 'en-US';
            utterance.rate = 0.85;
            
            const voice = getBestEnglishVoice();
            if (voice) utterance.voice = voice;

            // 存入防 GC 销毁集
            window.activeSpeechUtterances.push(utterance);
            if (window.activeSpeechUtterances.length > 50) window.activeSpeechUtterances.shift();

            activeUtterance = utterance;

            window.speechSynthesis.speak(utterance);
            if (window.speechSynthesis.paused) window.speechSynthesis.resume();
        }

        // ============================================================
        //  5. 词词列表管理
        // ============================================================
        function getGradeWords(grade) {
            const source = customWords || builtInWords;
            if (grade === 'all') {
                return Object.values(source).flat();
            } else {
                const numGrade = parseInt(grade, 10);
                return source[numGrade] || [];
            }
        }

        function updateWordList(grade) {
            currentGrade = grade;
            currentWords = getGradeWords(grade);
        }

        fileInput.addEventListener('change', function(e) {
            const file = e.target.files[0];
            if (!file) return;
            fileNameSpan.textContent = file.name;
            const reader = new FileReader();
            reader.onload = function(ev) {
                const text = ev.target.result;
                const parsed = parseWordBank(text);
                if (Object.keys(parsed).length === 0) {
                    alert('未能解析出有效词条,请检查格式。');
                    return;
                }
                customWords = parsed;
                if (parsed.all && !parsed[3] && !parsed[4] && !parsed[5] && !parsed[6] && currentGrade !== 'all') {
                    const allBtn = document.querySelector('[data-grade="all"]');
                    if (allBtn) allBtn.click();
                }
                updateWordList(currentGrade);
                renderCards();
                resetGameState();
                if (document.getElementById('playMode').style.display !== 'none') {
                    if (currentWords.length >= 3) nextRound();
                    else feedback.textContent = '⚠️ 词库不足3个,无法游戏';
                }
                updateReadDisplay();
            };
            reader.onerror = function() { alert('读取文件失败,请重试'); };
            reader.readAsText(file, 'UTF-8');
            fileInput.value = '';
        });

        // ============================================================
        //  6. 渲染卡片
        // ============================================================
        function renderCards() {
            cardContainer.innerHTML = '';
            if (currentWords.length === 0) {
                cardContainer.innerHTML = '<p style="opacity:0.7;">该年级暂无单词,请选择其他年级或导入词库</p>';
                return;
            }
            currentWords.forEach(item => {
                const card = document.createElement('div');
                card.className = 'word-card';
                const displayEmoji = (item.emoji && item.emoji.trim()) ? item.emoji : '✦';
                card.innerHTML = `
                    <span class="card-emoji">${displayEmoji}</span>
                    <div class="word">${item.word}</div>
                    <div class="phonetic">${item.phonetic || ''}</div>
                    <div class="meaning">${item.meaning}</div>
                `;
                card.addEventListener('click', () => speakWord(item.word));
                cardContainer.appendChild(card);
            });
        }

        // ============================================================
        //  7. 游戏模式
        // ============================================================
        let gameScore = 0;
        let currentQuestion = null;
        let gameLock = false;

        function resetGameState() {
            clearTimeout(gameTimer);
            gameTimer = null;
            gameLock = false;
            currentQuestion = null;
            optionsContainer.innerHTML = '';
            feedback.textContent = '';
            gameScore = 0;
            scoreSpan.textContent = '0';
            monsterEmoji.textContent = '👾';
        }

        function getRandomWord() {
            return currentWords[Math.floor(Math.random() * currentWords.length)];
        }

        function shuffleArray(arr) {
            return arr.sort(() => Math.random() - 0.5);
        }

        function nextRound() {
            clearTimeout(gameTimer); 
            if (gameLock) return;
            if (currentWords.length < 3) {
                feedback.textContent = '⚠️ 单词不够,请选择更多单词的年级或导入词库';
                optionsContainer.innerHTML = '';
                return;
            }
            currentQuestion = getRandomWord();
            let others = currentWords.filter(w => w.word !== currentQuestion.word);
            others = shuffleArray(others).slice(0, 2);
            const options = shuffleArray([currentQuestion, ...others]);

            optionsContainer.innerHTML = '';
            options.forEach(opt => {
                const btn = document.createElement('button');
                btn.className = 'option-btn';
                btn.textContent = opt.word;
                btn.dataset.word = opt.word;
                btn.addEventListener('click', () => checkAnswer(btn));
                optionsContainer.appendChild(btn);
            });

            monsterEmoji.textContent = ['👾','🐲','👻','🤖','🧟','🐉'][Math.floor(Math.random()*6)];
            feedback.textContent = '';
            gameLock = false;

            // 彻底防止多余后台朗读延时器重叠
            gameTimer = setTimeout(() => speakWord(currentQuestion.word), 300);
        }

        function checkAnswer(btn) {
            if (gameLock) return;
            gameLock = true;
            clearTimeout(gameTimer); // 强制斩断正在排队的TTS任务

            const selectedWord = btn.dataset.word;
            const allBtns = optionsContainer.querySelectorAll('.option-btn');
            allBtns.forEach(b => b.disabled = true);

            if (selectedWord === currentQuestion.word) {
                gameScore += 10;
                scoreSpan.textContent = gameScore;
                feedback.textContent = '🎉 咒语生效!击败怪兽!';
                monsterEmoji.textContent = '💥';
                gameTimer = setTimeout(() => {
                    monsterEmoji.textContent = '✨';
                    gameTimer = setTimeout(() => {
                        allBtns.forEach(b => b.disabled = false);
                        gameLock = false;
                        nextRound();
                    }, 500);
                }, 600);
            } else {
                feedback.textContent = '❌ 咒语反噬!再试一次!';
                speakWord(currentQuestion.word);
                gameTimer = setTimeout(() => {
                    allBtns.forEach(b => b.disabled = false);
                    gameLock = false;
                }, 800);
            }
        }

        // ============================================================
        //  8. 领读模式状态机 (事件解绑完全体)
        // ============================================================
        function updateReadDisplay() {
            if (currentWords.length === 0) {
                readWordEl.textContent = '---';
                readPhoneticEl.textContent = '';
                readMeaningEl.textContent = '';
                readProgressEl.textContent = '0 / 0';
                return;
            }
            const idx = Math.min(currentReadIndex, currentWords.length - 1);
            const item = currentWords[idx];
            readWordEl.textContent = item.word;
            readPhoneticEl.textContent = item.phonetic || '';
            readMeaningEl.textContent = item.meaning;
            readProgressEl.textContent = `${idx + 1} / ${currentWords.length}`;
        }

        function speakCurrentWordInLoop() {
            clearTimeout(readDelayTimer);
            
            // 🎯 首要核心:切断老一轮在运行的声音的所有事件触达,防止并发幽灵重写
            if (activeUtterance) {
                activeUtterance.onend = null;
                activeUtterance.onerror = null;
            }
            window.speechSynthesis.cancel();

            if (!readingActive || readingPaused) return;
            if (currentReadIndex >= currentWords.length) {
                finishReading();
                return;
            }

            updateReadDisplay();
            const item = currentWords[currentReadIndex];
            const repeatLimit = parseInt(repeatCountInput.value) || 1;

            const textToSpeak = cleanWordForSpeech(item.word);
            if (!textToSpeak) {
                // 如果空,跳过到下一个
                currentReadIndex++;
                speakCurrentWordInLoop();
                return;
            }

            const utterance = new SpeechSynthesisUtterance(textToSpeak);
            utterance.lang = 'en-US';
            utterance.rate = 0.85;
            
            const voice = getBestEnglishVoice();
            if (voice) utterance.voice = voice;

            // 阻截垃圾回收生存屏障
            window.activeSpeechUtterances.push(utterance);
            if (window.activeSpeechUtterances.length > 50) window.activeSpeechUtterances.shift();

            activeUtterance = utterance;

            utterance.onend = () => {
                if (!readingActive || readingPaused) return;
                currentRepeatIndex++;
                if (currentRepeatIndex < repeatLimit) {
                    readDelayTimer = setTimeout(speakCurrentWordInLoop, 400);
                } else {
                    currentRepeatIndex = 0;
                    if (currentReadIndex < currentWords.length - 1) {
                        const interval = (parseFloat(intervalInput.value) || 2) * 1000;
                        readDelayTimer = setTimeout(() => {
                            currentReadIndex++;
                            speakCurrentWordInLoop();
                        }, interval);
                    } else {
                        currentReadIndex++;
                        readDelayTimer = setTimeout(speakCurrentWordInLoop, 400);
                    }
                }
            };

            utterance.onerror = (e) => {
                if (e.error === 'interrupted') return; // 用户手动干预 cancel 的不触发延时流程
                if (readingActive && !readingPaused) {
                    readDelayTimer = setTimeout(() => {
                        currentReadIndex++;
                        currentRepeatIndex = 0;
                        speakCurrentWordInLoop();
                    }, 1000);
                }
            };

            window.speechSynthesis.speak(utterance);
            if (window.speechSynthesis.paused) window.speechSynthesis.resume();
        }

        function finishReading() {
            readingActive = false;
            readingPaused = false;
            readWordEl.textContent = '🎉 全部完成!';
            readPhoneticEl.textContent = '';
            readMeaningEl.textContent = '';
            readProgressEl.textContent = `${currentWords.length} / ${currentWords.length}`;
            updateReadButtons();
        }

        function startReading() {
            if (currentWords.length === 0) {
                alert('请先选择或导入词库!');
                return;
            }
            clearTimeout(readDelayTimer);
            
            if (activeUtterance) {
                activeUtterance.onend = null;
                activeUtterance.onerror = null;
            }
            window.speechSynthesis.cancel();
            window.speechSynthesis.resume();

            readingActive = true;
            readingPaused = false;
            if (currentReadIndex >= currentWords.length) currentReadIndex = 0;
            currentRepeatIndex = 0;
            updateReadButtons();
            speakCurrentWordInLoop();
        }

        function pauseReading() {
            if (!readingActive || readingPaused) return;
            readingPaused = true;
            clearTimeout(readDelayTimer);
            if (activeUtterance) {
                activeUtterance.onend = null;
                activeUtterance.onerror = null;
            }
            window.speechSynthesis.cancel();
            updateReadButtons();
        }

        function resumeReading() {
            if (!readingActive || !readingPaused) return;
            readingPaused = false;
            updateReadButtons();
            speakCurrentWordInLoop();
        }

        function stopReading() {
            readingActive = false;
            readingPaused = false;
            clearTimeout(readDelayTimer);
            if (activeUtterance) {
                activeUtterance.onend = null;
                activeUtterance.onerror = null;
            }
            window.speechSynthesis.cancel();
            currentReadIndex = 0;
            currentRepeatIndex = 0;
            updateReadButtons();
            if (currentWords.length > 0) updateReadDisplay();
            else {
                readWordEl.textContent = '已停止';
                readPhoneticEl.textContent = '';
                readMeaningEl.textContent = '';
                readProgressEl.textContent = '0 / 0';
            }
        }

        function updateReadButtons() {
            if (readingActive && !readingPaused) {
                readStartBtn.style.display = 'none';
                readPauseBtn.style.display = 'inline-block';
                readResumeBtn.style.display = 'none';
            } else if (readingActive && readingPaused) {
                readStartBtn.style.display = 'none';
                readPauseBtn.style.display = 'none';
                readResumeBtn.style.display = 'inline-block';
            } else {
                readStartBtn.style.display = 'inline-block';
                readPauseBtn.style.display = 'none';
                readResumeBtn.style.display = 'none';
            }
        }

        // ============================================================
        //  9. 模式切换与年级选择
        // ============================================================
        function switchMode(mode) {
            stopReading();
            resetGameState();

            document.getElementById('learnMode').style.display = mode === 'learn' ? 'block' : 'none';
            document.getElementById('playMode').style.display = mode === 'play' ? 'block' : 'none';
            document.getElementById('readMode').style.display = mode === 'read' ? 'block' : 'none';
            document.getElementById('learnTab').classList.toggle('active', mode === 'learn');
            document.getElementById('playTab').classList.toggle('active', mode === 'play');
            document.getElementById('readTab').classList.toggle('active', mode === 'read');

            if (mode === 'play') {
                if (currentWords.length >= 3) nextRound();
                else feedback.textContent = '⚠️ 词库不足3个,无法游戏';
            }
            if (mode === 'read') {
                updateReadDisplay();
            }
        }

        gradeSelector.addEventListener('click', (e) => {
            if (e.target.classList.contains('grade-btn')) {
                document.querySelectorAll('.grade-btn').forEach(b => b.classList.remove('active'));
                e.target.classList.add('active');
                const grade = e.target.dataset.grade;
                updateWordList(grade);
                renderCards();
                resetGameState();
                if (document.getElementById('playMode').style.display !== 'none') {
                    if (currentWords.length >= 3) nextRound();
                    else feedback.textContent = '该年级单词不足,无法游戏';
                }
                if (document.getElementById('readMode').style.display !== 'none') {
                    stopReading();
                    updateReadDisplay();
                }
            }
        });

        // ============================================================
        //  10. 帮助弹窗
        // ============================================================
        function openHelp() {
            document.getElementById('helpModal').classList.add('show');
        }
        function closeHelp() {
            document.getElementById('helpModal').classList.remove('show');
        }
        document.getElementById('helpModal').addEventListener('click', function(e) {
            if (e.target === this) closeHelp();
        });

        // ============================================================
        //  11. 初始化
        // ============================================================
        window.onload = function() {
            updateWordList('all');
            renderCards();
            resetGameState();
            updateReadDisplay();
            updateReadButtons();
            
            // 安全限制约束
            repeatCountInput.value = 1;
            intervalInput.value = 2;
            fileNameSpan.textContent = '未选择文件';
            
            repeatCountInput.addEventListener('change', () => {
                let val = parseInt(repeatCountInput.value);
                if (isNaN(val) || val < 1) repeatCountInput.value = 1;
                if (val > 3) repeatCountInput.value = 3;
            });
            intervalInput.addEventListener('change', () => {
                let val = parseFloat(intervalInput.value);
                if (isNaN(val) || val < 1) intervalInput.value = 1;
                if (val > 5) intervalInput.value = 5;
            });

            setTimeout(() => getBestEnglishVoice(), 500);
        };
    </script>
</body>
</html>
相关推荐
勉灬之2 小时前
Next.js + Prisma 跨平台部署踩坑记
开发语言·javascript·ecmascript
糖果店的幽灵2 小时前
langgraph分支之 - 动态分支(Dynamic Branch)
java·前端·javascript·人工智能·langgraph
这是个栗子3 小时前
前端开发中的常用工具函数(九)
开发语言·javascript·ecmascript·at
Revolution614 小时前
一段 JavaScript 代码执行时,到底发生了什么
前端·javascript
To_OC13 小时前
LC 131 分割回文串:刚学回溯时,我连怎么切字符串都想不明白
javascript·算法·leetcode
To_OC15 小时前
LC 42 接雨水:暴力超时卡半天?前后缀数组一用就通了
javascript·算法·leetcode
小林ixn15 小时前
从 ??= 到 onKeyDown:一个 React 组件的“自我修养”
前端·javascript·react.js
এ慕ོ冬℘゜16 小时前
前端实战:jQuery 多条件联合搜索(标题模糊查询 + 日历时间段筛选)
前端·javascript·jquery
随心点儿17 小时前
js postMessage 实现跨域发送消息-应用示例
javascript·ecmascript·postmessage