间隔重复记忆卡片:翻卡自评掌握度,SM-2 算法自动排下一次复习
背单词、记知识点最怕的不是不会,而是想不起来该哪天复习。这个单文件网页把「艾宾浩斯式间隔重复」做成一张张可以翻面的卡片:先看问题、再翻答案,按「不会 / 困难 / 良好 / 简单」自评一下,它就自动帮你算出下一次复习时间,数据全部存在本地。
先看成品效果,再讲这次怎么用华为云 CodeArts 码道 WebUI 一段话把它做出来、部署并公开分享。
这个工具做什么
它把「背卡片」这件小事做到顺手:
- 卡片组管理:可以新建、删除卡片组,首页仪表盘直接展示每个组还剩多少张待复习。
- 问题 + 答案卡片:每个组里自由添加、编辑、删除卡片,复习时先看问题,点击翻面看答案。
- 四档自评:复习一张卡后点「不会 / 困难 / 良好 / 简单」,系统据此安排下次复习。
- SM-2 间隔重复算法:内置易度因子 EF 与复习间隔计算,按钮上会实时预览下一次复习时间。
- 学习进度统计:总卡片、待复习、已掌握百分比、连续学习天数,还有近 7 天复习量柱状图。
- 本地保存:全部数据写进
localStorage,刷新不丢失,还支持 JSON 导出 / 导入 / 一键重置。 - 手机电脑都能用:响应式布局,复习时按空格翻卡、按 1–4 键快速评分。

码道开通(免费体验版)
开始之前,先免费开通码道体验版。不需要装任何软件,浏览器就能用:
https://developer.huaweicloud.com/codeartsco.html?source=dmzntgwsf&sourcead=dmzntgwwbwz
开通后有三种使用方式:WebUI(浏览器对话)、TUI(终端命令行)和桌面 IDE(IDE 插件)。本文用 WebUI 版演示。
进入 AI 开发者空间
- 浏览器打开 https://devstation.developer.huaweicloud.com/aidevspace?utm_source=opcsfsq&utm_medium=wbwz
- 弹窗「请选择要进入的版本」→ 点击 体验版
- 首次使用会跳到华为云登录页,扫码登录一次,后续浏览器会话复用
- 弹窗「临时凭据自动配置」→ 点击 同意,沙箱自动创建
进入 AI 开发者空间主界面后,先等左侧菜单加载出来,再找到 CodeArts,点击它右侧的浏览器图标,打开码道 WebUI 对话窗口:

打开后码道 WebUI 的底部输入框提示「尽管吩咐,我来帮你搞定」:

小贴士:体验版沙箱 3 小时后自动重置,生成完记得把
index.html下载保存。
任务描述
在码道 WebUI 输入框粘贴以下需求,回车发送(模型默认 glm-5.2,可直接用):
开发一个「间隔重复记忆卡片」单文件网页应用:可以新建卡片组、添加问题和答案卡片,复习时翻卡自评掌握程度,根据间隔重复算法自动安排下次复习时间,带学习进度统计和本地保存(localStorage),界面简洁清晰,手机和电脑都能用,所有代码写在一个 index.html 里。完成后用部署功能部署成可访问的网页应用,生成一个公网可访问的分享链接,并告诉我访问地址。

这轮码道具体做了什么
不是把通用 AI 能力复述一遍,而是它在这篇项目里的实际动作:
- 在沙箱里创建
/workspace/spaced-repetition-cards,先把数据结构和页面骨架搭好,再写入单文件index.html。 - 写文件过程中发现末尾乱码,主动重写整个文件,最终生成约 35KB 的完整 HTML + CSS + JS。
- 抽出
<script>内容做node --check语法校验,确认 JS 语法通过后再继续。 - 检测到 3000 端口空闲,写了一个 33 行的
server.js静态服务器监听0.0.0.0:3000,并curl验证返回 HTTP 200。 - 随后拉起 DevBridge 隧道,把 3000 端口发布成 8 小时有效的公网 HTTPS 链接,并逐段检查公网 URL 是不是正确返回了这个应用。
这次实际生成的临时公网地址(8 小时有效):
https://nrimgx4z-3000.cn-north-4-bridge.myhuaweicloud.com/这个地址是 DevBridge 生成的临时部署入口,适合演示和验收,不适合作为长期访问地址;到期后读者可以按后面的「直接下载试玩」把
index.html下载到本地打开。
代码亮点
以下是 index.html 里值得关注的设计思路和实现细节。
1. 四档评分驱动复习调度,SM-2 公式一目了然
schedule(card, grade) 把「不会 / 困难 / 良好 / 简单」映射成间隔调整:评分太低就把复习进度清零,评分高则按易度因子拉起下一次间隔:
function schedule(card, grade){
let ef = card.ef, interval = card.interval, reps = card.reps;
if(grade < 3){
reps = 0; interval = 0;
} else {
reps = reps + 1;
if(reps===1) interval = 1;
else if(reps===2) interval = 6;
else interval = Math.round(interval * ef);
if(grade===5) interval = Math.round(interval * 1.15);
if(grade===3) interval = Math.max(1, Math.round(interval * 0.8));
}
ef = ef + (0.1 - (5-grade)*(0.08 + (5-grade)*0.02));
if(ef < 1.3) ef = 1.3;
if(ef > 2.8) ef = 2.8;
card.ef = Math.round(ef*100)/100;
card.interval = interval;
card.reps = reps;
card.lastReviewed = now();
card.due = interval === 0 ? now() + 600000 : now() + interval * DAY;
}
2. 翻卡动画 + 键盘快捷键,复习更顺手
复习页支持点击翻面,也可以直接用键盘:空格翻卡,1–4 键分别对应四档评分,减少鼠标来回点:
document.addEventListener('keydown', e=>{
if(document.getElementById('view-review').classList.contains('active')){
const flip = document.getElementById('flip-card');
if(flip.style.display==='none') return;
if(e.code==='Space' || e.code==='Enter'){ e.preventDefault(); flipCard(); }
else if(flip.classList.contains('flipped')){
if(e.key==='1') gradeCard(1);
else if(e.key==='2') gradeCard(3);
else if(e.key==='3') gradeCard(4);
else if(e.key==='4') gradeCard(5);
}
}
if(e.key==='Escape') hideModal();
});
3. 本地存储 + 导入导出,数据不怕丢
save() 每次变更都写入 localStorage,exportData() 和 importData(file) 则把整份数据序列化成 JSON 下载或读回,方便换设备时迁移:
function save(){ localStorage.setItem(STORE_KEY, JSON.stringify(state)); }
function exportData(){
const blob = new Blob([JSON.stringify(state, null, 2)], { type:'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url; a.download = 'memory-cards-'+new Date().toISOString().slice(0,10)+'.json';
a.click(); URL.revokeObjectURL(url); toast('已导出');
}
4. 状态由单一对象管理,渲染与数据分离
所有卡片组、卡片和学习记录都放在一个 state 对象里,增删改查统一走 save() 再调用对应 render*(),页面和状态不会互相打架:
let state = { decks: [], history: [] };
function newDeck(name){ const d={ id:uid(), name:name||'新卡片组', createdAt:now(), cards:[] }; state.decks.push(d); save(); return d; }
function newCard(deckId, question, answer){
const d=getDeck(deckId); if(!d) return;
d.cards.push({ id:uid(), question, answer, ef:2.5, interval:0, reps:0, due:now(), createdAt:now(), lastReviewed:0 });
save();
}
直接下载试玩
本次生成的项目就是单文件 index.html,没有第三方依赖,把文件保存到本地后双击用浏览器打开即可运行。后续进入发布流程时,会把源码同步到公开 Demo Park 仓库,方便直接复制:
- Demo Park 仓库:https://atomgit.com/deli007/demo_park
- 本案例目录:https://atomgit.com/deli007/demo_park/tree/main/codearts-memory-cards
总结
间隔重复记忆卡片的核心价值不在「有卡片界面」,而在「什么时候让你再看一次」。它把 SM-2 算法、翻卡自评和本地统计串成一个闭环,复习节奏由数据决定而不是凭感觉。技术上主要练习了间隔重复调度、localStorage 持久化、JSON 导入导出和键盘交互几处,后续还可以加上图片卡片、云端同步或多套复习题库。
如果还没用过码道,可以免费开通体验版:https://developer.huaweicloud.com/codeartsco.html?source=dmzntgwsf&sourcead=dmzntgwwbwz
浙公网安备 33010602011771号