欢迎加入开源鸿蒙PC社区:
https://harmonypc.csdn.net/

atomgit仓库地址:https://atomgit.com/Math_teacher_fan/jingdiangeci

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

一、项目概述与设计理念

1.1 应用背景

歌词是音乐的灵魂,记忆歌词是很多音乐爱好者的愿望。然而,传统的死记硬背方式效率低下,容易遗忘。本应用旨在通过科学的学习算法和间隔重复技术,帮助用户高效记忆经典歌词。

核心问题

  1. 遗忘规律:根据艾宾浩斯遗忘曲线,不复习就会快速遗忘
  2. 学习效率:传统方式效率低,缺乏针对性练习
  3. 进度追踪:难以量化记忆效果

解决方案

┌─────────────────────────────────────────────────────┐
│                                                     │
│  学习效率提升                                        │
│  ├─ 智能优先级队列:先学难的                       │
│  ├─ 间隔重复:科学复习时间点                      │
│  └─ 即时反馈:立即知道对错                        │
│                                                     │
│  记忆效果量化                                        │
│  ├─ 掌握度统计:每句歌词的掌握程度                │
│  ├─ 进度追踪:整体学习进度                        │
│  └─ 曲线可视化:记忆效果图形化                    │
│                                                     │
└─────────────────────────────────────────────────────┘

1.2 技术架构选型

技术方案 优势 适用场景
鸿蒙Electron 原生性能优秀,系统集成度高 需要与鸿蒙系统深度交互的应用
Web前端技术 开发效率高,跨平台能力强 快速迭代,界面复杂的应用
Canvas 图表绘制能力强 科学数据可视化
LocalStorage 数据持久化简单 单机应用,数据量较小的场景

1.3 功能模块划分

┌─────────────────────────────────────────────────────┐
│                    功能模块架构                      │
├─────────────────────────────────────────────────────┤
│  📖 学习模式  │  ✍️ 测验模式  │  📚 歌词库          │
├─────────────────────────────────────────────────────┤
│  📊 学习进度  │  ❤️ 收藏夹   │                      │
└─────────────────────────────────────────────────────┘

二、核心代码实现详解

2.1 学习队列管理实现

学习队列是应用的核心功能,根据歌词的掌握程度动态调整学习顺序。

const StudyModule = {
    buildStudyQueue() {
        const allLyrics = [...lyricsDatabase, ...DataManager.getLyrics()];
        const progress = DataManager.getProgress();
        studyQueue = [];
        
        // 遍历所有歌词和歌词行
        allLyrics.forEach(lyrics => {
            lyrics.lyrics.forEach((line, index) => {
                const lineProgress = progress[lyrics.id]?.lines[index];
                const wrongCount = lineProgress?.wrong || 0;
                const correctCount = lineProgress?.correct || 0;
                
                // 计算优先级:错误次数越多、正确次数越少,优先级越高
                const priority = wrongCount - correctCount + (correctCount < 3 ? 2 : 0);
                
                studyQueue.push({
                    lyricsId: lyrics.id,
                    song: lyrics.song,
                    artist: lyrics.artist,
                    lineIndex: index,
                    text: line,
                    priority: priority
                });
            });
        });
        
        // 按优先级降序排列
        studyQueue.sort((a, b) => b.priority - a.priority);
    }
};

优先级计算公式

priority = wrongCount - correctCount + (correctCount < 3 ? 2 : 0)

示例分析:
歌词A: wrong=0, correct=1 → priority = 0 - 1 + 2 = 1  (刚开始学习)
歌词B: wrong=3, correct=1 → priority = 3 - 1 + 2 = 4  (需要加强)
歌词C: wrong=1, correct=5 → priority = 1 - 5 + 0 = -4 (已掌握)
歌词D: wrong=0, correct=0 → priority = 0 - 0 + 2 = 2   (从未学习)

2.2 歌词填空算法实现

根据不同难度等级,动态隐藏歌词中的字符。

hideCharacters(text, count) {
    if (count <= 0) return text;
    
    const chars = text.split('');
    const indices = [];
    
    // 选择要隐藏的字符索引
    while (indices.length < count && indices.length < chars.length) {
        const idx = Math.floor(Math.random() * chars.length);
        if (chars[idx] !== ' ' && !indices.includes(idx)) {
            indices.push(idx);
        }
    }
    
    // 按索引排序(保持原有顺序)
    indices.sort((a, b) => a - b);
    
    // 生成显示文本
    let result = '';
    for (let i = 0; i < chars.length; i++) {
        if (indices.includes(i)) {
            result += '<span class="blank">_</span>';
        } else {
            result += chars[i];
        }
    }
    
    return result;
},

getHideCount(difficulty) {
    switch (difficulty) {
        case 'easy': return Math.ceil(text.length * 0.3);      // 隐藏30%
        case 'medium': return Math.ceil(text.length * 0.5);    // 隐藏50%
        case 'hard': return Math.ceil(text.length * 0.7);      // 隐藏70%
        default: return Math.ceil(text.length * 0.5);
    }
}

难度等级效果

原歌词:"天青色等烟雨 而我在等你"
                    ↓
简单模式(30%):"天青色等烟___ 而我___你"  (隐藏3个字符)
中等模式(50%):"天青色___雨 而___等你"    (隐藏5个字符)
困难模式(70%):"天青色__烟___ 而___等__"  (隐藏7个字符)

2.3 进度追踪系统实现

updateProgress(lyricsId, lineIndex, correct) {
    const progress = this.getProgress();
    
    // 初始化歌曲进度
    if (!progress[lyricsId]) {
        progress[lyricsId] = { lines: {}, mastered: 0, total: 0 };
    }
    
    // 初始化歌词行进度
    if (!progress[lyricsId].lines[lineIndex]) {
        progress[lyricsId].lines[lineIndex] = { correct: 0, wrong: 0 };
    }
    
    // 更新正确/错误次数
    if (correct) {
        progress[lyricsId].lines[lineIndex].correct++;
    } else {
        progress[lyricsId].lines[lineIndex].wrong++;
    }
    
    // 计算已掌握的句子
    // 掌握条件:正确次数 >= 3 且 正确次数 > 错误次数
    let mastered = 0;
    const lines = progress[lyricsId].lines;
    for (let key in lines) {
        if (lines[key].correct >= 3 && lines[key].correct > lines[key].wrong) {
            mastered++;
        }
    }
    progress[lyricsId].mastered = mastered;
    
    this.saveProgress(progress);
    return progress;
}

掌握判定条件

掌握 = (正确次数 >= 3) AND (正确次数 > 错误次数)

示例:
歌词行1: correct=3, wrong=0 → mastered ✓
歌词行2: correct=3, wrong=2 → mastered ✓
歌词行3: correct=2, wrong=0 → not mastered (正确次数不足)
歌词行4: correct=1, wrong=2 → not mastered (错误多于正确)
歌词行5: correct=5, wrong=1 → mastered ✓

2.4 记忆曲线绘制实现

使用Canvas绘制艾宾浩斯遗忘曲线。

drawMemoryCurve() {
    const canvas = document.getElementById('memoryCurve');
    const ctx = canvas.getContext('2d');
    
    canvas.width = 600;
    canvas.height = 300;
    
    ctx.clearRect(0, 0, 600, 300);
    
    // 绘制网格线
    ctx.strokeStyle = '#e2e8f0';
    ctx.lineWidth = 1;
    
    for (let i = 0; i <= 5; i++) {
        const y = 30 + i * 50;
        ctx.beginPath();
        ctx.moveTo(50, y);
        ctx.lineTo(550, y);
        ctx.stroke();
    }
    
    // 绘制记忆曲线
    ctx.beginPath();
    ctx.strokeStyle = '#8b5cf6';
    ctx.lineWidth = 3;
    
    const points = [];
    // 艾宾浩斯遗忘曲线公式: y = e^(-t/S)
    // 其中 S=1 (时间常数)
    for (let x = 50; x <= 550; x += 10) {
        const progress = (x - 50) / 500;
        // 归一化到0-1范围,然后映射到y坐标
        const memoryRetention = Math.exp(-3 * progress);
        const y = 250 - 200 * memoryRetention;
        points.push({ x, y });
    }
    
    // 绘制曲线
    ctx.moveTo(points[0].x, points[0].y);
    points.forEach(p => ctx.lineTo(p.x, p.y));
    ctx.stroke();
}

记忆曲线公式

艾宾浩斯遗忘曲线:
R = e^(-t/S)

其中:
R = 记忆保留率 (0-1)
t = 时间
S = 时间常数 (约1天)

曲线特点:
- 20分钟后:记忆保留约58%
- 1小时后:记忆保留约44%
- 1天后:记忆保留约33%
- 6天后:记忆保留约25%

三、歌词数据库设计

3.1 歌词数据模型

const lyricsDatabase = [
    {
        id: 1,
        song: '平凡之路',
        artist: '朴树',
        category: 'folk',
        categoryName: '民谣音乐',
        lyrics: [
            '徘徊着的 在路上的',
            '你要走吗',
            'via via',
            '易碎的 骄傲着',
            '那也曾是我的模样',
            // ... 更多歌词行
        ]
    }
];

3.2 分类管理

const categoryMap = {
    pop: '流行音乐',
    rock: '摇滚音乐',
    folk: '民谣音乐',
    classic: '经典老歌',
    movie: '影视金曲'
};

预置歌词统计

分类 歌曲数量 代表歌曲
民谣音乐 2首 平凡之路、董小姐
流行音乐 2首 青花瓷、演员
摇滚音乐 2首 海阔天空、夜空中最亮的星
经典老歌 1首 后来
影视金曲 1首 匆匆那年

四、测验模式实现

4.1 随机选题算法

startQuiz() {
    // 获取所有歌词
    const allLyrics = [...lyricsDatabase, ...DataManager.getLyrics()];
    
    // 随机选择一首歌曲
    const randomLyrics = allLyrics[Math.floor(Math.random() * allLyrics.length)];
    
    // 随机选择一句歌词
    const randomLineIndex = Math.floor(Math.random() * randomLyrics.lyrics.length);
    
    this.currentQuiz = {
        lyricsId: randomLyrics.id,
        song: randomLyrics.song,
        artist: randomLyrics.artist,
        lineIndex: randomLineIndex,
        text: randomLyrics.lyrics[randomLineIndex],
        context: this.getContext(randomLyrics.lyrics, randomLineIndex)
    };
}

4.2 上下文获取

getContext(lyrics, index) {
    // 获取当前行的前一句和后一句作为上下文
    const before = index > 0 ? lyrics[index - 1] : '';
    const after = index < lyrics.length - 1 ? lyrics[index + 1] : '';
    
    return { before, current: '____________', after };
}

4.3 答案验证

checkAnswer(user, correct) {
    // 标准化处理:去除空格、转小写
    const normalize = (str) => str.replace(/\s+/g, '').toLowerCase();
    
    return normalize(user) === normalize(correct);
}

// 匹配规则说明:
// "天青色等烟雨" 匹配 "天青色等烟雨" ✓
// "天青色 等烟雨" 匹配 "天青色等烟雨" ✓
// "天青色等烟雨 " 匹配 "天青色等烟雨" ✓
// "天青色等烟"   匹配 "天青色等烟雨" ✗

五、数据持久化架构

5.1 LocalStorage数据结构

// 进度数据结构
{
    "lyrics_progress": {
        "1": {  // 歌词ID
            "lines": {
                "0": { "correct": 3, "wrong": 0 },  // 第0行
                "1": { "correct": 2, "wrong": 1 }   // 第1行
            },
            "mastered": 2,  // 已掌握行数
            "total": 15     // 总行数
        }
    },
    
    "lyrics_favorites": [1, 3, 5],  // 收藏的歌词ID数组
    
    "lyrics_custom": [  // 自定义歌词
        {
            "id": 1234567890,
            "song": "自定义歌曲",
            "artist": "歌手名",
            "category": "pop",
            "lyrics": ["歌词1", "歌词2"]
        }
    ]
}

5.2 数据管理接口

const DataManager = {
    // 获取进度
    getProgress() {
        return JSON.parse(localStorage.getItem('lyrics_progress') || '{}');
    },
    
    // 保存进度
    saveProgress(progress) {
        localStorage.setItem('lyrics_progress', JSON.stringify(progress));
    },
    
    // 获取收藏
    getFavorites() {
        return JSON.parse(localStorage.getItem('lyrics_favorites') || '[]');
    },
    
    // 保存收藏
    saveFavorites(favorites) {
        localStorage.setItem('lyrics_favorites', JSON.stringify(favorites));
    },
    
    // 获取自定义歌词
    getLyrics() {
        return JSON.parse(localStorage.getItem('lyrics_custom') || '[]');
    },
    
    // 保存自定义歌词
    saveLyrics(lyrics) {
        localStorage.setItem('lyrics_custom', JSON.stringify(lyrics));
    }
};

六、UI设计与交互体验

6.1 视觉设计风格

色彩方案

颜色 色值 用途
主色调 #8b5cf6 按钮、进度条、高亮
辅助色 #3b82f6 渐变、图标
成功色 #10b981 正确答案
警告色 #f59e0b 提示按钮
错误色 #ef4444 错误答案

布局特点

  • 卡片式设计,信息层次清晰
  • 渐变背景增强视觉效果
  • 响应式布局,适配不同屏幕尺寸

6.2 学习模式UI

<div class="lyrics-display">
    <div class="song-info">
        <span class="song-name">平凡之路</span>
        <span class="artist-name">朴树</span>
    </div>
    <div class="lyrics-content">
        <div class="lyric-line current">
            徘徊着的 <span class="blank">_</span> 上面的
        </div>
    </div>
</div>

6.3 响应式设计

@media (max-width: 768px) {
    .app-header {
        flex-direction: column;
        gap: 15px;
    }
    
    .nav-btn {
        min-width: calc(50% - 5px);
    }
    
    .progress-overview {
        grid-template-columns: 1fr;
    }
}

七、技术亮点与创新

7.1 智能学习算法

学习算法流程图

┌─────────────────────────────────────────────────────┐
│                                                     │
│  1. 构建学习队列                                    │
│     ├─ 遍历所有歌词                                 │
│     ├─ 计算每句优先级                               │
│     └─ 按优先级排序                                 │
│                                                     │
│  2. 学习过程中                                      │
│     ├─ 显示填空歌词                                 │
│     ├─ 用户输入答案                                 │
│     ├─ 判定对错                                     │
│     └─ 更新进度数据                                 │
│                                                     │
│  3. 队列调整                                        │
│     ├─ 答对:移出队列                               │
│     └─ 答错:重新排序(优先级提高)                 │
│                                                     │
└─────────────────────────────────────────────────────┘

7.2 间隔重复原理

复习时间点(基于艾宾浩斯曲线):

第一次学习 → 20分钟后复习
第一次复习 → 1小时后复习
第二次复习 → 1天后复习
第三次复习 → 6天后复习
第四次复习 → 1个月后复习
第五次复习 → 6个月后复习

本应用通过调整优先级实现:
- 错误越多,复习频率越高
- 正确越多,复习频率越低

7.3 数据可视化

// 记忆曲线绘制
const memoryRetention = Math.exp(-3 * timeNormalized);
// 绘制从 100% 到 25% 的衰减曲线

八、总结与展望

8.1 项目成果

功能模块 状态 核心特性
学习模式 填空学习、难度选择、优先级队列
测验模式 随机测验、上下文提示、正确率统计
歌词库 8首预置歌词、分类筛选、自定义添加
学习进度 记忆曲线、掌握统计
收藏夹 收藏管理、快速访问

8.2 未来规划

  1. 发音朗读:加入歌词朗读功能
  2. 歌曲播放:集成音频播放,跟唱学习
  3. 云端同步:支持多设备数据同步
  4. AI推荐:根据学习情况推荐适合的歌词

8.3 技术价值

歌词记忆大师应用展示了如何在鸿蒙PC平台上开发教育类应用,为开发者提供了以下参考:

  • 智能学习算法:优先级队列和间隔重复的实现
  • Canvas可视化:记忆曲线的绘制技术
  • 数据持久化:localStorage的实践应用
  • 模块化架构:功能解耦和代码组织

通过本项目的实践,开发者可以快速掌握教育类应用开发的核心技术,为构建更多优秀应用奠定基础。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐