【OpenHarmony/HarmonyOs 】数学答题结果页设计:成绩统计、错题解析与复盘闭环
【OpenHarmony/HarmonyOs 】数学答题结果页设计:成绩统计、错题解析与复盘闭环
项目类型:OpenHarmony / HarmonyOS ArkTS 数学学习应用
项目名称:数学视界
对应主题:端侧 AI、全新视觉与交互体验、隐私保护方案
关键词:ArkTS、答题结果、错题解析、成绩统计、学习复盘、端侧分析 🎯
一、为什么答题结果页比答题页更重要?
很多学习 App 会把主要精力放在“做题过程”,但真正能帮助用户进步的是“做完之后怎么复盘”。如果结果页只是显示一个分数,用户很快就会离开;如果结果页能展示正确率、用时、错题、解析和再次练习入口,它就会变成学习闭环的一部分。
数学视界项目中的 ChallengeResult.ets 就是围绕这个思路设计的:
- 展示成绩等级;
- 根据分数给出鼓励文案;
- 显示正确数、错误数、用时、正确率;
- 支持全部/错题/正确三种筛选;
- 展示每道题的用户答案、正确答案和解析;
- 支持再来一次和返回首页;
- 将挑战结果写入
AppState,用于后续统计分析。
这篇文章聚焦“答题结果页”,和之前的题库、掌握度文章区分开,重点写复盘体验。
二、结果页如何接收答题数据?
答题完成后,QuizPage 会通过路由参数把结果传给结果页。结果页在 aboutToAppear() 中读取:
aboutToAppear() {
const themeManager = ThemeManager.getInstance()
this.isDarkMode = themeManager.getIsDark()
themeManager.addListener((isDark: boolean) => {
this.isDarkMode = isDark
})
try {
const params = router.getParams() as Record<string, Object>
if (params) {
this.result = params['result'] as ChallengeResultData
if (this.result) {
AppState.recordChallengeResult(this.result)
}
}
} catch {
// ignore
}
}
这里有一个关键动作:
AppState.recordChallengeResult(this.result)
结果页不只是展示页面,它还负责把本次挑战写入全局学习统计。这样“做完题”才能影响学习报告、掌握度、历史最高分、挑战次数等数据。
三、成绩等级:把数字分数转成情绪反馈
分数本身是冷冰冰的,结果页把分数转成等级、颜色、表情和文案:
getScoreGrade(): string {
if (!this.result) return ''
if (this.result.score >= 90) return 'A+'
if (this.result.score >= 80) return 'A'
if (this.result.score >= 70) return 'B'
if (this.result.score >= 60) return 'C'
if (this.result.score >= 40) return 'D'
return 'E'
}
鼓励文案:
getScoreText(): string {
if (!this.result) return ''
if (this.result.score >= 90) return '满分选手!太棒了!'
if (this.result.score >= 80) return '优秀!继续保持!'
if (this.result.score >= 70) return '良好!再接再厉!'
if (this.result.score >= 60) return '及格!还需努力!'
if (this.result.score >= 40) return '继续加油!'
return '不要放弃,多练习!'
}
这类设计很适合学习类产品。用户看到的不只是“60 分”,而是“及格,还需努力”。反馈更接近老师或学习助手。
四、颜色和表情:让成绩可感知
结果页还根据分数切换颜色:
getScoreColor(): string {
if (!this.result) return '#95A5A6'
if (this.result.score >= 90) return '#2ECC71'
if (this.result.score >= 80) return '#3498DB'
if (this.result.score >= 70) return '#F39C12'
if (this.result.score >= 60) return '#E67E22'
return '#E74C3C'
}
表情也会随分数变化:
getScoreEmoji(): string {
if (!this.result) return '📊'
if (this.result.score >= 90) return '🏆'
if (this.result.score >= 80) return '🌟'
if (this.result.score >= 70) return '👍'
if (this.result.score >= 60) return '💪'
return '📚'
}
这就是“全新视觉与交互体验”的一个细节:结果页不是报表,而是学习反馈面板。
五、统计行:正确、错误、用时、正确率
结果页显示四类关键指标:
- 正确题数;
- 错误题数;
- 总用时;
- 正确率。
正确率计算:
getAccuracy(): string {
if (!this.result) return '0%'
return Math.round(
(this.result.correctCount / this.result.totalCount) * 100
) + '%'
}
用时格式化:
formatTime(seconds: number): string {
const mins = Math.floor(seconds / 60)
const secs = seconds % 60
if (mins > 0) {
return `${mins}分${secs}秒`
}
return `${secs}秒`
}
这些数据都来自本地结果对象,不需要上传服务器,也不需要云端分析。
六、Tab 筛选:全部、错题、正确
复盘时,用户最关心的通常是错题。所以结果页提供了三个 Tab:
@State selectedTab: number = 0
Tab UI:
Text('全部')
.fontWeight(this.selectedTab === 0 ? FontWeight.Bold : FontWeight.Normal)
.onClick(() => {
this.pulseAnim('tab0')
this.selectedTab = 0
})
Text('错题')
.fontWeight(this.selectedTab === 1 ? FontWeight.Bold : FontWeight.Normal)
.onClick(() => {
this.pulseAnim('tab1')
this.selectedTab = 1
})
Text('正确')
.fontWeight(this.selectedTab === 2 ? FontWeight.Bold : FontWeight.Normal)
.onClick(() => {
this.pulseAnim('tab2')
this.selectedTab = 2
})
这种筛选让复盘更高效:
- 全部:完整回顾;
- 错题:重点纠错;
- 正确:确认已掌握内容。
七、错题筛选:只看需要改进的部分
错题列表通过过滤 questions 得到:
ForEach(
(this.result?.questions ?? []).filter(
(cq: ChallengeQuestion): boolean => !cq.isCorrect
),
(cq: ChallengeQuestion, i: number) => {
this.buildQuestionItem(cq, i)
}
)
如果没有错题,会展示空状态:
if ((this.result?.questions ?? []).filter(
(cq: ChallengeQuestion): boolean => !cq.isCorrect
).length === 0) {
this.buildEmptyState('🎉', '太棒了!全部答对!')
}
这个设计很重要。用户满分时不应该看到空白页面,而应该得到正向反馈。
八、题目复盘卡片:答案和解析都要给到
每道题的复盘卡片展示:
- 正误图标;
- 第几题;
- 题干;
- 用户答案;
- 正确答案;
- 答案解析。
核心代码:
Text(cq.isCorrect ? '✅' : '❌')
Text('第 ' + (index + 1) + ' 题')
Text(cq.question.title)
Text('你的答案: ' + (cq.userAnswer === '' ? '(未作答)' : cq.userAnswer))
Text('正确答案: ' + cq.question.answer)
Text('📖 解析: ' + cq.question.analysis)
结果页不是为了告诉用户“你错了”,而是帮助用户知道:
- 我错在哪里;
- 正确答案是什么;
- 为什么应该这么做。
这才是复盘闭环。
九、底部操作:再来一次与返回首页
底部提供两个明确操作:
Button('🔄 再来一次')
.onClick(() => {
this.pulseAnim('retry')
router.back()
})
Button('🏠 返回首页')
.onClick(() => {
this.pulseAnim('home')
router.clear()
router.pushUrl({ url: 'pages/Index' })
})
“再来一次”适合立即巩固,“返回首页”适合结束本轮学习。两个按钮让结果页不会成为死胡同。
十、隐私保护:复盘数据留在端侧
结果页展示的内容包括用户答案、错题、正确率、用时。这些都属于学习画像的一部分。
数学视界当前的做法是:
- 本地计算分数;
- 本地保存结果;
- 本地展示解析;
- 本地更新统计;
- 不上传用户答案。
这和“隐私保护方案”主题高度契合。学习分析可以做,但应优先在端侧完成。
十一、总结
这篇文章聚焦数学视界的答题结果页,重点不是挑战流程,而是“复盘闭环”。
核心实现包括:
- 🎯 通过路由参数接收
ChallengeResult; - 📊 根据分数生成等级、颜色、表情和鼓励文案;
- ⏱ 展示正确数、错误数、用时和正确率;
- 🧩 提供全部/错题/正确三种筛选;
- 📖 展示用户答案、正确答案和解析;
- 🔄 提供再来一次和返回首页;
- 🔐 学习结果在端侧处理,避免上传用户答案。
对数学学习 App 来说,答题结果页不是结束,而是下一轮学习的起点。🚀

更多推荐



所有评论(0)