2026/7/26 2:51:00

HarmonyOS 应用开发《掌上英语》第48篇:学习进度追踪——从数据记录到可视化展示

HarmonyOS 应用开发《掌上英语》第48篇:学习进度追踪——从数据记录到可视化展示 学习进度追踪——从数据记录到可视化展示一、进度追踪的整体架构学习进度追踪是英语学习 App 的核心功能之一。用户需要知道今天学了多少、“总共学了多少”、“目标完成得怎么样”。本项目通过 LearningPlanManager 管理目标数据通过 CourseHomePage 和首页的 Progress 组件进行可视化展示。数据流如下用户答题 → recordWordStudy(count) ↓ LearningPlanManager ├── todayWordCount → 今日已学 ├── totalWordCount → 累计已学 ├── continuousDays → 连续天数 └── getTodayProgress() → 百分比 ↓ CourseHomePage / MainPage └── Progress 组件 → 可视化展示二、学习计划的定义2.1 LearningPlan 模型exportinterfaceLearningPlan{dailyWordGoal:number// 每日单词目标dailyListeningGoal:number// 每日听力目标分钟dailyReadingGoal:number// 每日阅读目标分钟continuousDays:number// 连续学习天数lastStudyDate:number// 最后学习日期时间戳todayWordCount:number// 今日已学单词todayListeningDuration:number// 今日已听时长todayReadingDuration:number// 今日已读时长totalWordCount:number// 总学习单词数totalStudyDuration:number// 总学习时长badges:string[]// 成就徽章// ... 提醒相关字段}默认计划DEFAULT_LEARNING_PLAN为每日 20 个单词、15 分钟听力、10 分钟阅读。2.2 数据记录入口在 AnswerQuestionsPage 完成答题后通过recordStudyData方法记录学习数据recordStudyData(){try{lettopicItemTypeListthis.toTopicItemTypeList(this.ques);// 1. 记录统计StatisticsManager.getInstance().calculateStatistics(topicItemTypeList,this.practiceDuration);// 2. 更新学习计划letplanManagerLearningPlanManager.getInstance();letansweredCountthis.ques.filter(itemitem.isAnswer).length;planManager.recordWordStudy(answeredCount);}catch(e){Logger.error(AnswerQuestionsPage,记录学习数据失败:${JSON.stringify(e)});}}recordWordStudy方法执行三个操作累加todayWordCount和totalWordCount调用checkAndUpdateContinuousDays更新连续天数调用checkAndUnlockBadges检查是否满足徽章解锁条件三、今日进度计算3.1 百分比计算publicgetTodayProgress():TodayProgress{try{letplanthis.getLearningPlan();letresult:TodayProgress{wordProgress:plan.dailyWordGoal0?Math.min(100,Math.floor(plan.todayWordCount/plan.dailyWordGoal*100)):0,listeningProgress:plan.dailyListeningGoal0?Math.min(100,Math.floor(plan.todayListeningDuration/plan.dailyListeningGoal*100)):0,readingProgress:plan.dailyReadingGoal0?Math.min(100,Math.floor(plan.todayReadingDuration/plan.dailyReadingGoal*100)):0};returnresult;}catch(e){Logger.error(LearningPlanManager,获取今日进度失败:${JSON.stringify(e)});return{wordProgress:0,listeningProgress:0,readingProgress:0};}}关键点Math.min(100, ...)防止进度超过 100%目标为 0 时返回 0%避免除零错误每个维度独立计算单词、听力、阅读3.2 首页进度卡展示在 CourseHomePage 中进度通过 Progress 组件展示Row(){Column(){Text(${this.learnedCount}/${this.totalCount}).fontSize(22).fontWeight(FontWeight.Bold).fontColor(#165DFF);Text(已学 / 总数).fontSize(11).fontColor($r(sys.color.font_secondary));}.layoutWeight(1);Column(){Text(今日需学 30 词).fontSize(13);Text(已完成${this.learnedCount}词).fontSize(11);}}Progress({value:this.getTodayProgress(),total:30,type:ProgressType.Linear}).width(100%).height(6).color(#165DFF).backgroundColor(#E8EEF8);这里使用了ProgressType.Linear线性进度条以30为每日目标总数value是当前已学数量。四、总进度统计4.1 学习统计摘要publicgetStudySummary():StudySummary{try{letplanthis.getLearningPlan();letresult:StudySummary{totalDays:plan.continuousDays,totalWords:plan.totalWordCount,totalDuration:plan.totalStudyDuration,badgeCount:plan.badges.length};returnresult;}catch(e){Logger.error(LearningPlanManager,获取学习统计摘要失败:${JSON.stringify(e)});return{totalDays:0,totalWords:0,totalDuration:0,badgeCount:0};}}这个摘要方法返回四个关键指标可以在学习报告页面统一呈现。4.2 学习报告中的 Dashboard 集成DashboardManager 也整合了进度数据publicrefreshData():void{letplanManagerLearningPlanManager.getInstance();letstatsManagerStatisticsManager.getInstance();letplanplanManager.getLearningPlan();letprogressplanManager.getTodayProgress();letsummarystatsManager.getHistoryStatistics();this.todayWordProgressprogress.wordProgress;this.todayListeningProgressprogress.listeningProgress;this.todayReadingProgressprogress.readingProgress;this.overallProgressMath.floor((this.todayWordProgressthis.todayListeningProgressthis.todayReadingProgress)/3);this.continuousDaysplan.continuousDays;this.weeklyDatathis.buildWeeklyData(plan);// ...}overallProgress是三个进度维度的平均值用于展示总体完成度。五、Progress 组件的两种形态5.1 线性进度条ProgressType.LinearProgress({value:13,total:30,type:ProgressType.Linear}).width(100).height(6).color(#165DFF).backgroundColor(#E8EEF8);适用场景展示单词学习进度、阅读进度。形态简洁适合嵌入卡片中。5.2 环形进度条ProgressType.RingProgress({value:65,total:100,type:ProgressType.Ring}).width(50).height(50).color(#165DFF).style({strokeWidth:4});适用场景首页今日学习卡中的总体进度。圆形视觉更醒目适合作为模块的视觉锚点。5.3 柱状图自定义实现DashboardManager 中的 WeeklyBarChart 不使用系统的 Progress 组件而是用 Row 组件模拟柱状图Column(){if(item.readingMin0){Row().width(20).height(this.barHeight(item.readingMin)).backgroundColor(#FF9800);}if(item.listeningMin0){Row().width(20).height(this.barHeight(item.listeningMin)).backgroundColor(#4CAF50);}if(item.wordCount0){Row().width(20).height(this.barHeight(item.wordCount)).backgroundColor(#2196F3);}}.height(120).justifyContent(FlexAlign.End);堆叠柱状条每种颜色代表一个维度的数据高度通过barHeight方法按比例计算。六、每日数据重置新的一天开始时需要重置今日学习数据publicresetDailyData():LearningPlan{try{letplanthis.getLearningPlan();plan.todayWordCount0;plan.todayListeningDuration0;plan.todayReadingDuration0;this.saveLearningPlan(plan);returnplan;}catch(e){Logger.error(LearningPlanManager,重置每日数据失败:${JSON.stringify(e)});returnthis.getLearningPlan();}}实际调用时机在checkAndUpdateContinuousDays中隐式完成——当检测到「最后学习日期不是今天」时新的记录会自然产生新的今日数据旧数据不再被引用。七、总结从 LearningPlanManager 的数据记录到 Progress 组件的可视化呈现学习进度追踪形成了一条完整的数据链路。三个维度的目标单词、听力、阅读、两种进度形态线性条、环形、以及柱状图等自定义图表共同构成了用户学习旅程的仪表盘让进步看得见。