熟悉度系统设计
概述
使用 0-100 的熟悉度(familiarity)替代简单的 status 枚举,提供更灵活的学习进度跟踪。
数据库设计
UserStudyItem 表新增字段
familiarity INT NOT NULL DEFAULT 0 -- 熟悉度:0-100
熟悉度等级划分
| 熟悉度范围 | 等级描述 | 对应旧 status |
|---|---|---|
| 0-20 | 完全陌生 | 0 (待学习), 1 (陌生) |
| 21-40 | 有印象但不熟 | 2 (模糊) |
| 41-60 | 基本认识 | 3 (认识) |
| 61-80 | 比较熟悉 | 4 (熟识) |
| 81-100 | 非常熟悉 | - |
熟悉度更新策略
标记单词时的规则
首次标记"认识":
create: familiarity = 60- 表示用户对这个单词有基本认识
重复标记"认识":
update: familiarity += 10- 最大值:100
- 每次标记增加熟悉度
标记"不认识":
create: familiarity = 20update: familiarity -= 5- 最小值:0
- 降低熟悉度,表示需要加强
单词展示策略
排序规则
在课程详情页面,单词按熟悉度从低到高排序:
words.sort((a, b) => a.familiarity - b.familiarity)
这样确保:
- 熟悉度低的单词(需要学习的)优先显示
- 熟悉度高的单词(已掌握的)排在后面
视觉反馈
- 熟悉度 < 60:标记为"需练习",卡片背景为 muted
- 熟悉度 >= 60:标记为"已掌握",卡片背景为 primary/5
- 在单词详情对话框中显示熟悉度进度条
自动提交机制
用户交互优化
点击"认识/不认识"按钮:
- 立即更新本地 UI 状态
- 自动发送 API 请求保存到后端
- 无需单独的"提交"按钮
失败处理:
- API 失败时自动回滚本地状态
- 保证数据一致性
成功处理:
- 刷新页面数据(router.refresh)
- 更新排序和统计
API 接口
POST /api/courses/[courseId]/mark-words
{
marks: [
{
courseItemId: string;
known: boolean; // true=认识, false=不认识
}
]
}
处理逻辑:
- known = true:
- 首次:familiarity = 60, status = 3
- 重复:familiarity += 10
- known = false:
- 首次:familiarity = 20, status = 0
- 重复:familiarity -= 5
迁移计划
步骤 1: 添加 familiarity 字段
pnpm db:push
步骤 2: 迁移现有数据
-- 一次性转换 status 到 familiarity
UPDATE study_item
SET familiarity = CASE
WHEN status = 0 THEN 0
WHEN status = 1 THEN 20
WHEN status = 2 THEN 40
WHEN status = 3 THEN 60
WHEN status = 4 THEN 80
ELSE 0
END
WHERE familiarity = 0;
步骤 3: 向后兼容
- 保留
status字段用于向后兼容 - 新逻辑优先使用
familiarity - 旧逻辑仍可读取
status
未来扩展
基于熟悉度的学习策略
智能推荐:
- 优先练习熟悉度低的单词
- 定期复习熟悉度中等的单词
- 偶尔测试熟悉度高的单词
动态调整:
- 根据错误率调整熟悉度
- 长时间未复习自动降低熟悉度
- 连续答对快速提升熟悉度
个性化学习:
- 根据用户习惯调整熟悉度变化速率
- 不同难度单词使用不同的熟悉度阈值
- 支持用户手动调整熟悉度
统计分析
学习进度可视化:
- 熟悉度分布直方图
- 熟悉度变化趋势图
- 学习效率分析
学习建议:
- 根据熟悉度分布推荐学习计划
- 识别需要重点关注的单词
- 预测掌握时间
优势对比
旧系统 (status)
- 优点:简单直观
- 缺点:
- 只有 5 个等级,粒度粗
- 难以体现细微进步
- 不支持动态调整策略
新系统 (familiarity)
优点:
- 0-100 精细度,可量化进步
- 支持复杂的学习策略
- 灵活调整和扩展
- 更好的用户反馈
缺点:
- 实现稍复杂
- 需要设计合理的更新策略
- 需要迁移现有数据