从零打造中国风古诗背诵小工具——AI素养课ClassRoom实战分享
从零打造中国风古诗背诵小工具——AI素养课ClassRoom实战分享
一个零依赖、单文件、水墨风的中国风古诗背诵 Web 应用,在 AI 素养课 ClassRoom 第二期训练营中从想法到上线只用了不到一杯茶的功夫。本文记录它的设计思路、关键实现与全流程实战经验。
一、项目背景
我正在参加 AI 素养课 ClassRoom 第二期训练营,这是一个面向开发者、以"用 AI 真实交付一个作品"为目标的实战训练项目。训练营地址:
🔗 https://gallery.developer.huaweicloud.com/gallery/001dc3930fc08000
第二期的主题是"从一个想法到一个上线作品",要求学员借助 CodeArts(码道)AI 编码能力,完成需求拆解、代码生成、本地预览、云端托管与作品发布的完整闭环。选题时我定下三个原则:小而完整、有文化温度、能让人愿意打开第二次。
为什么选古诗背诵?一来它功能边界清晰(展示、默写、校验、统计),适合在有限时间内打磨到"可用且好看";二来古诗天然适配中国风视觉,能做出区别于通用模板的辨识度;三来"背诵"是一个有真实复用价值的场景——不是 demo,是工具。于是「古诗背诵·墨韵」就这样诞生了。
二、技术选型与架构设计
为什么是纯前端单页应用
这个工具的核心是"展示 + 交互 + 本地记忆",没有后端逻辑、没有多用户、没有敏感数据。用 HTML + CSS + JavaScript 三件套,把全部代码塞进一个 index.html,是最克制也最合适的选择。
零依赖、零构建工具的优势:
- 无
npm install、无打包配置,任何环境双击即可运行 - 部署即拷贝,一个文件就是整个项目,
python3 -m http.server 8080即刻预览 - 没有 framework 升级负担,三年后打开依然能跑
- 对初学者友好,代码即文档,便于在训练营中讲解
架构分层设计
虽然是单文件,内部依然保持清晰的分层,避免变成一锅"过程式面条代码":
┌─────────────────────────────────────────┐
│ UI 层 DOM 结构 + CSS 视觉样式 │
├─────────────────────────────────────────┤
│ 功能模块 render / recite / answer ... │ ← 事件驱动,操作 state
├─────────────────────────────────────────┤
│ 数据层 POEMS 常量 + localStorage │
└─────────────────────────────────────────┘
- 数据层:
POEMS数组作为内置诗库,progress(一个Set)作为背诵进度,通过localStorage持久化。 - 功能模块:以一个
state对象为单一数据源,render()负责根据 state 重绘视图,enterRecite()/showAnswer()/resetGaps()等函数负责响应交互。 - UI 层:语义化 HTML + CSS 变量主题,视图完全由
render()驱动,不直接操作业务数据。
三、核心功能实现
3.1 古诗数据设计
每首诗是一个扁平对象,字段语义直白,content 保留中文标点,便于后续按标点切句:
const POEMS = [
{title:"静夜思",author:"李白",dynasty:"唐",content:"床前明月光,疑是地上霜。举头望明月,低头思故乡。"},
{title:"春晓",author:"孟浩然",dynasty:"唐",content:"春眠不觉晓,处处闻啼鸟。夜来风雨声,花落知多少。"},
{title:"望庐山瀑布",author:"李白",dynasty:"唐",content:"日照香炉生紫烟,遥看瀑布挂前川。飞流直下三千尺,疑是银河落九天。"},
// ...共 12 首
];
渲染时按 ,。?! 断句,每句包成一个 .line,标点单独包成 .punct,汉字包成 .char。这样做的关键收益是:背诵挖空时可以精确到"字"而非"字符",标点永远保留,默写体验更贴近真实。
3.2 背诵模式——随机挖空算法
背诵模式的核心是"在诗句中随机隐藏一部分字,用输入框替换,实时校验"。
第一步:决定挖多少。 经验值是约 38%——太少没有挑战,太多挫败感强。同时用 Math.min 限制不超过一半,并用 Math.max 保证至少挖 1 个:
function enterRecite(){
const chars = [...$("pBody").querySelectorAll(".char")];
const n = chars.length;
const k = Math.max(1, Math.min(Math.floor(n*0.38), Math.floor(n/2)));
// Fisher-Yates 洗牌,取前 k 个下标作为挖空位
const pool = [...chars.keys()];
for(let i=pool.length-1;i>0;i--){
const j=Math.floor(Math.random()*(i+1));
[pool[i],pool[j]]=[pool[j],pool[i]];
}
const chosen = new Set(pool.slice(0,k));
// 将选中的 .char 替换为 <input class="gap">
chars.forEach((c,i)=>{
if(chosen.has(i)){
const inp=document.createElement("input");
inp.className="gap"; inp.maxLength=1; inp.dataset.ans=c.textContent;
inp.addEventListener("input",onGapInput);
c.textContent=""; c.appendChild(inp);
state.gaps.push({char:c.textContent,el:inp});
}
});
}
这里用 Fisher-Yates 洗牌而不是"逐字按概率决定是否挖空",可以精确控制挖空数量 k,避免出现"一首诗只挖到 1 个字"或"挖了 80%"的极端情况。
第二步:输入校验与颜色反馈。 每次输入即时比对答案,正确加 .ok(绿色高亮)并自动跳到下一个空,错误加 .no(红色 + 抖动动画):
function onGapInput(e){
const inp=e.target, ans=inp.dataset.ans, v=inp.value;
inp.classList.remove("ok","no");
if(v.length===0) return;
if(v===ans){
inp.classList.add("ok");
const next=nextEmpty(inp); if(next) next.focus();
checkAllDone(); // 全部填对则标记已掌握
} else {
inp.classList.add("no"); // 触发 shake 动画
}
}
"自动跳到下一空"是个小但关键体验细节——用户默写时无需手动点下一个框,行云流水地写完整首诗。
3.3 进度持久化
进度用 Set 存已掌握的诗题,序列化成数组写入 localStorage,读取时容错:
function loadProgress(){
try{ return new Set(JSON.parse(localStorage.getItem("poetry_done")||"[]")); }
catch(e){ return new Set(); } // 存储损坏时优雅降级
}
function saveProgress(){
localStorage.setItem("poetry_done", JSON.stringify([...progress]));
}
当所有空填对、或用户点击"查看答案"时,调用 progress.add(title) 并 saveProgress()。进度条宽度 = progress.size / POEMS.length * 100%,底部诗题图例已掌握的变绿,当前诗题描朱红边——进度可视、可点跳转。
四、中国风视觉设计
视觉是这个工具的"灵魂",目标是让人第一眼觉得"这不是个通用模板"。
配色方案
用 CSS 变量定义一套"文房四宝"色板:
:root{
--paper:#f4ecd8; /* 宣纸米黄 */
--ink:#2b2622; /* 浓墨 */
--seal:#b8332a; /* 朱红印泥 */
--gold:#9a6b3f; /* 古铜 */
--jade:#5b7a6a; /* 青绿 */
--green:#3f7d4e; /* 填对 */
}
CSS 渐变模拟宣纸纹理
没有图片素材,纯用两层 repeating-linear-gradient 叠加 mix-blend-mode:multiply 模拟宣纸的细密纤维,再加远山水墨的 radial-gradient 压在底部:
body::before{
content:"";position:fixed;inset:0;pointer-events:none;
background-image:
repeating-linear-gradient(0deg, rgba(120,90,50,.025) 0 1px, transparent 1px 4px),
repeating-linear-gradient(90deg, rgba(120,90,50,.025) 0 1px, transparent 1px 4px);
mix-blend-mode:multiply;
}
Google Fonts 手写体
引入 Ma Shan Zheng(马善政手写体)做诗题与题头,Noto Serif SC 做正文,fallback 到本地的 KaiTi/STKaiti,离线也不至于塌掉:
<link href="https://fonts.googleapis.com/css2?family=Ma+Shan+Zheng&family=Noto+Serif+SC:wght@400;600;700;900&display=swap" rel="stylesheet">
朱红印章装饰
诗题右侧盖一枚"印章"——朱红边框 + 旋转 -6° + 半透明,内容取诗题首字,像极了古籍上的藏书印:
.seal{
width:46px;height:46px;border:2px solid var(--seal);color:var(--seal);
display:flex;align-items:center;justify-content:center;
font-family:"Ma Shan Zheng",serif;
border-radius:4px;transform:rotate(-6deg);opacity:.85;
background:rgba(184,51,42,.04);
}
再配上卷轴卡片上下两道朱红横轴、虚线分隔、古铜色按钮——整体气质统一在"墨韵书香"四个字里。
五、部署方式
本地部署
一个文件,一行命令:
python3 -m http.server 8080 --bind 0.0.0.0
浏览器打开 http://localhost:8080/ 即可。
在线预览
在 CodeArts 沙箱中,本地 8080 端口会自动转发为可访问的预览地址:
https://8080-<容器ID>.workspace.developer.huaweicloud.com/
若要分享给没有 CloudIDE 权限的队友,通过 DevBridge 开发隧道生成公网可访问的分享链接,一行命令把本地服务暴露到公网。
GitCode 仓库托管
代码托管到 GitCode,便于版本管理与协作:
🔗 https://gitcode.com/Eddygit/poetry-recitation-tool.git
华为云开发者作品展览馆发布
训练营作品可发布至华为云开发者作品展览馆(即 ClassRoom 作品 Gallery),供评委与其他学员浏览、点评,形成"开发—托管—发布—交流"的完整闭环。
六、开发实战经验
用 CodeArts(码道)AI 辅助编码
整个 index.html 是我在 CodeArts 码道里用一段自然语言需求一次性生成的:描述清楚功能点(随机展示、背诵挖空、校验反馈、进度持久化)和视觉风格(中国风、水墨、宣纸、印章),码道直接产出了可运行的单文件应用。最让我意外的是它对"中国风"的理解——不是简单套个深色背景,而是给出了宣纸纹理、朱红印章、手写体题字这一整套协调的视觉语言。
通过 skill 体系完成全流程
码道的 skill 体系把"写代码—预览—托管—分享"串成了标准动作:huawei-cloud-codearts-gitcode 负责沙箱路径、项目预览 URL 拼接与 GitCode 建仓推代码;huawei-cloud-codearts-devbridge-tunnel 负责生成公网分享隧道。我几乎不用离开对话窗口就完成了从编码到可分享链接的全流程。
发布至华为云高校运营平台
作品在本地预览验收通过后,推送到 GitCode 仓库,再登记到开发者作品展览馆,即可进入训练营评审通道。整个过程无需自建服务器、无需配置 CI,对学员而言门槛极低。
遇到的挑战与解决方案
| 挑战 | 解决方案 |
|---|---|
| 挖空数量随机波动太大 | 用 Fisher-Yates 洗牌精确取 k 个,而非逐字按概率 |
| 标点被误挖空 | 渲染时把标点单独包成 .punct,挖空只针对 .char |
localStorage 损坏导致崩溃 |
读取时 try/catch,失败返回空 Set 优雅降级 |
| 移动端输入框尺寸错乱 | input.gap 用 em 单位 + vertical-align:baseline,随字号缩放 |
| 离线时手写体丢失 | Google Fonts 后接 KaiTi/STKaiti/serif 多级 fallback |
七、训练营参与指南
AI 素养课 ClassRoom 第二期训练营是一个以"真实交付作品"为导向的开发者实训项目,从需求拆解到云端发布全流程陪跑,适合想在短时间内把"会用 AI"变成"能交付产品"的同学。
- 📚 训练营入口:https://gallery.developer.huaweicloud.com/gallery/001dc3930fc08000
- 🏛️ 作品展览馆:即上方 Gallery 页面,可浏览所有学员作品并互动
- 🛠️ 推荐工具链:CodeArts(码道)AI 编码 + GitCode 托管 + DevBridge 分享
参与建议:先想清楚一个"小而完整"的选题——它不必宏大,但要有真实使用场景和可辨识的审美。然后放手让 AI 生成第一版,再围绕细节(交互手感、视觉气质、边界情况)逐处打磨。你会发现,从想法到上线,距离远比想象中近。
熟读唐诗三百首,不会作诗也会吟。愿这篇分享能帮你也动起手来,做出自己的"墨韵"。
- 点赞
- 收藏
- 关注作者
评论(0)