【OpenHarmony/HarmonyOs 】化学学习软件成就系统设计实践:让学习 App 更有持续使用动力
【OpenHarmony/HarmonyOs 】成就系统设计实践:让学习 App 更有持续使用动力
学习类 App 很容易遇到一个问题:用户第一次打开觉得内容很多,但过几天就忘了继续用。为了解决这个问题,我在「化学视界」中加入了成就系统,用访问天数、学习行为、收藏、答题等数据给用户持续反馈。🏆
一、为什么学习 App 需要成就系统?
成就系统不是游戏专属。对于学习工具来说,它可以发挥三个作用:
- 给用户正反馈,让学习过程更有成就感。
- 记录长期行为,比如连续学习天数。
- 引导用户探索更多功能,比如查看元素、阅读知识、完成挑战。
在我的项目中,成就不是为了制造焦虑,而是让用户看到自己一点点进步。
二、成就系统的整体结构
项目中成就相关文件主要有:
AchievementData.ts:成就配置数据。Achievement.ts:成就模型。AchievementManager.ts:成就管理器。Achievement.ets:成就展示页面。Statistics.ets:学习统计页面。
我开发时把“成就配置”和“成就进度”分开:
- 配置:成就名称、描述、图标、目标值。
- 进度:当前完成度、是否解锁、解锁时间。
这样以后新增成就时,只需要补充配置,管理逻辑可以复用。
三、用户统计数据设计
成就系统依赖学习行为统计:
function getDefaultStatistics():UserStatistics{return{totalEquationsViewed:0,totalElementsViewed:0,totalKnowledgeRead:0,dailyQuizCorrect:0,dailyQuizStreak:0,totalFavorites:0,totalSearches:0,visitDates:[],currentStreak:0,unlockedAchievements:[]};}这些数据覆盖了 App 的主要学习行为:
- 看过多少方程式。
- 看过多少元素。
- 读过多少知识点。
- 答对多少题。
- 收藏多少内容。
- 连续学习多少天。
我没有把统计写在页面里,而是统一放到管理器中,避免每个页面各算各的。
四、成就管理器:单例统一管理
成就管理器使用单例:
static getInstance(): AchievementManager {if(AchievementManager.instance===null) {AchievementManager.instance =newAchievementManager(); } returnAchievementManager.instance; }这样整个 App 中都能使用同一个成就状态。比如:
- 主入口记录访问。
- 元素详情记录查看。
- 知识详情记录阅读。
- 挑战页记录答题。
- 收藏动作记录收藏数量。
统一管理的好处是数据不会分散,成就判断也不会重复写。
五、记录访问和连续学习
用户每次打开 App 时,会记录当天访问:
recordVisit(): void {constnow = new Date();consttoday =this.formatDate(now);constyesterday =this.formatDate(new Date(now.getTime() -86400000));if(this.statistics.lastVisitDate === today) {return; }if(!this.statistics.visitDates.includes(today)) {this.statistics.visitDates.push(today); }if(this.statistics.lastVisitDate === yesterday) {this.statistics.currentStreak +=1; }else{this.statistics.currentStreak =1; }this.statistics.lastVisitDate = today;this.scheduleSave(); }这段逻辑是成就系统里最基础的一环。连续学习天数可以鼓励用户保持习惯,但同一天重复打开不应该重复计数。
六、行为记录:把学习动作转成成就进度
例如查看方程式:
recordEquationViewed(type?: string): void {this.checkAndUnlock('first_equation',1);this.statistics.totalEquationsViewed +=1;this.checkAndUnlock('equation_5',this.statistics.totalEquationsViewed);this.checkAndUnlock('equation_15',this.statistics.totalEquationsViewed);this.checkAndUnlock('equation_30',this.statistics.totalEquationsViewed);this.scheduleSave(); }这里的思路是:页面只告诉管理器“用户看了一个方程式”,至于是否解锁成就,由管理器判断。
这样页面层非常干净,不需要知道具体成就规则。
七、成就解锁后的弹窗反馈
成就页面订阅解锁事件:
privateonUnlockBound:(achievement: Achievement) =>void=(achievement: Achievement) =>{this.showUnlockAnimation(achievement);this.refreshAchievements();this.unlockedCount=this.manager.getUnlockedCount(); };解锁时展示弹窗动效:
showUnlockAnimation(achievement: Achievement) {this.popupAchievement = achievement;this.showUnlockPopup =true;this.popupScale =0.3;this.popupOpacity =0; animateTo({ duration:400, curve: Curve.EaseOut }, () => {this.popupScale =1;this.popupOpacity =1; }); }这个弹窗是成就系统的情绪反馈。用户完成某个动作后,看到成就解锁,会更愿意继续探索。
八、成就页面展示设计
成就页包含:
- 当前称号。
- 已解锁数量。
- 总进度条。
- 全部/已解锁/未解锁切换。
- 成就卡片列表。
- 解锁弹窗。
顶部进度区域代码片段:
Text(`${this.unlockedCount}`).fontSize(20).fontWeight(FontWeight.Bold).fontColor($r('app.color.secondary_color'))Text(`/${TOTAL_ACHIEVEMENTS}`).fontSize(13).fontColor($r('app.color.text_tertiary'))我希望用户进入页面后第一眼就能知道:我现在处于什么阶段,还差多少成就。
九、称号系统:让成就有长期目标
项目中根据已解锁成就数量计算用户称号:
getTitle(): {level: number;name: string } { const t = getUserTitle(this.statistics.unlockedAchievements.length);return { level: t.level, name: t.name}; }称号比单纯数字更有情绪价值。比如“化学学徒”“化学达人”这种命名,会让学习过程更像成长路线。
十、开发成就系统的思考
我做成就系统时遵循了几个原则:
- 成就来自真实学习行为,不做无意义打卡。
- 页面只记录行为,不判断复杂规则。
- 解锁反馈要及时,但不能打扰学习。
- 成就数据本地保存,保证离线可用。
- 称号系统提供长期目标。
十一、总结
成就系统的价值不在于“炫”,而在于让用户看见自己的学习轨迹。
在「化学视界」里,成就系统把元素查看、方程式阅读、知识学习、答题挑战、收藏行为串了起来:
- 🧪 学得越多,成就越丰富。
- 🔥 坚持越久,连续天数越高。
- ⭐ 收藏越多,复习路径越清晰。
- 🏆 解锁越多,用户称号越高。
如果你也在开发学习类 App,可以考虑把成就系统作为“长期留存”的一部分,而不是最后随便加一个展示页。