书写模块 (Write Module)
3 页面 + 4 组件 + 评分算法,TypeScript 实现 | 文件位于
web/src/modules/write/
架构概览
modules/write/
├── pages/
│ ├── character/
│ │ └── character.vue ← 汉字详情页(/character)
│ ├── write/
│ │ └── write.vue ← 书写练习页(/write)
│ └── write-result/
│ └── write-result.vue ← 书写结果页(/write-result)
├── components/
│ ├── CharInfo.vue ← 汉字信息展示
│ ├── HanziWriterCanvas.vue ← HanziWriter 画布封装
│ ├── MiziGrid.vue ← 米字格背景
│ └── WriteLayout.vue ← 书写布局
└── utils/
├── score-calculator.ts ← 书写评分算法
└── score-calculator.test.ts ← 评分测试页面流转
/char-select (汉字浏览)
↓ 点击汉字
/character (汉字详情)
↓ 点击"开始书写"
/write (书写练习)
↓ 完成书写
/write-result (书写结果)
↓ goNext() 根据 from 参数跳转
/char-select | /planet-series | /review-stats书写练习三入口
goNext() 根据 route.query.from 区分处理:
| 入口 | from 值 | 汉字列表 | 掌握判定 | 全部掌握后跳转 |
|---|---|---|---|---|
| 汉字星际 | char-select | 全部汉字 | maxScore ≥ 60 | /char-select |
| 星球地图 | planet-series | 按 subCategory 过滤 | maxScore ≥ 60 | /planet-series |
| 薄弱字 | review-stats | Top 10 薄弱字(动态重算) | 准确率 ≥ 100% | /review-stats |
评分算法
文件: web/src/modules/write/utils/score-calculator.ts | 测试: score-calculator.test.ts
评分公式
score = accuracyScore + completionScore + speedBonus| 维度 | 分值 | 说明 |
|---|---|---|
| accuracyScore | 0-70 | 按尝试笔画数归一化的准确率 |
| completionScore | 0-25 | 完成度(quiz 完成得满分) |
| speedBonus | 0-5 | 速度奖励(仅 quiz 完成时,每笔 4 秒为基准) |
辅助函数
| 函数 | 说明 |
|---|---|
getStarCount(score) | 根据分数计算星级 (95→5, 80→4, 60→3, 40→2, 其余→1) |
getScoreMessage(score) | 根据分数获取鼓励文案 |
HanziWriter 配置
模式切换
| 模式 | 笔画颜色 | 用途 |
|---|---|---|
| 描红模式 | 黑色 #1f2937 | 手写描红练习 |
| 笔顺演示模式 | 蓝色 #3b82f6 | 笔顺动画演示 |
模式切换时保留 writer 实例,通过 setCharacter() 重置状态而非重建。
数据加载
- 笔顺数据通过
resource-service.ts的getHanziWriterData()加载 - 使用
import.meta.glob在构建时解析所有汉字 JSON,运行时 O(1) 查找 - 请求去重:同一汉字并发调用共享同一个 Promise
组件文档
| 组件 | 文档 |
|---|---|
| CharInfo | CharInfo.md |
| HanziWriterCanvas | HanziWriterCanvas.md |
| MiziGrid | MiziGrid.md |
| WriteLayout | WriteLayout.md |
页面文档
| 页面 | 文档 |
|---|---|
| 汉字详情 | character.md |
| 书写练习 | write.md |
| 书写结果 | write-result.md |