【OpenHarmony/HarmonyOs 】数学题库结构设计:12 个年级、知识点标签与本地题库索引

项目类型:OpenHarmony / HarmonyOS ArkTS 数学学习应用
项目名称:数学视界
对应主题:端侧 AI、元服务能力集成、隐私保护方案
关键词:ArkTS、本地题库、年级体系、知识点标签、题库索引、智能组卷 📚

一、为什么题库结构值得单独写?

前面已经写过知识点掌握度评估,但掌握度分析的基础是题库结构。如果题库只是一个普通数组,后续很难做筛选、组卷、统计和推荐。

数学视界项目中的题库设计有几个特点:

  • 12 个年级;
  • 30+ 个知识点;
  • 选择题、填空题、判断题、计算题多题型;
  • 每道题绑定年级和知识点;
  • 每道题有难度、答案、解析、标签;
  • 本地题库可直接筛选;
  • 后续可用于智能组卷和元服务“今日一题”。

这篇文章就聚焦题库建模,不再写挑战页 UI。

二、年级模型:从小学到高中

项目中定义了 Grade

export interface Grade {
  id: string
  name: string
  shortName: string
  level: number
  color: string
  bgColor: string
  icon: string
  description: string
  sortOrder: number
}

年级数据示例:

export const GRADES: Grade[] = [
  {
    id: 'g1',
    name: '一年级',
    shortName: '小一',
    level: 1,
    description: '加减法、认识图形',
    sortOrder: 1
  },
  {
    id: 'g12',
    name: '高三',
    shortName: '高三',
    level: 12,
    description: '综合复习、冲刺高考',
    sortOrder: 12
  },
]

年级模型不只是显示名称,它还能用于:

  • 按学习阶段筛题;
  • 控制知识点范围;
  • 生成年级挑战;
  • 统计年级掌握度。

三、知识点模型:题库分析的关键维度

知识点结构如下:

export interface KnowledgePoint {
  id: string
  name: string
  shortName: string
  category: string
  icon: string
  color: string
  bgColor: string
  description: string
  grades: string[]
  difficulty: number
  questionCount: number
  sortOrder: number
}

一个知识点示例:

{
  id: 'kp_quadratic_func',
  name: '二次函数',
  shortName: '二次',
  category: '函数',
  icon: '📈',
  description: '二次函数的图像、开口、顶点',
  grades: ['g9', 'g10', 'g11'],
  difficulty: 4,
  questionCount: 0,
  sortOrder: 17
}

知识点比年级更细,它可以用于:

  • 专项练习;
  • 薄弱点复习;
  • 正确率统计;
  • 题库数量展示;
  • 智能组卷权重。

四、题目模型:每道题都要可分析

项目中的 Question 定义如下:

export interface Question {
  id: string
  type: QuestionType
  gradeId: string
  knowledgeIds: string[]
  difficulty: number
  title: string
  options?: QuestionOption[]
  answer: string
  analysis: string
  tags?: string[]
  createdAt: number
  usageCount: number
  correctRate: number
}

这个结构很完整:

  • type:题型;
  • gradeId:年级;
  • knowledgeIds:关联知识点;
  • difficulty:难度;
  • title:题干;
  • options:选择题选项;
  • answer:标准答案;
  • analysis:答案解析;
  • tags:题目标签;
  • usageCountcorrectRate:为后续统计预留。

题库越结构化,后续越容易做智能推荐。

五、题型设计:选择、填空、判断、计算

项目中题型是联合类型:

export type QuestionType = 'choice' | 'fill' | 'judge' | 'calc'

选项结构:

export interface QuestionOption {
  label: string
  value: string
}

这让题库能覆盖不同学习场景:

  • choice:适合快速练习;
  • fill:适合公式和概念;
  • judge:适合判断性质;
  • calc:适合计算题。

后续如果要扩展,还可以增加:

  • 多选题;
  • 连线题;
  • 排序题;
  • 图形题。

六、题库生成函数:统一创建题目

项目通过 makeQuestion() 创建题目:

function makeQuestion(
  id: string,
  type: QuestionType,
  gradeId: string,
  knowledgeIds: string[],
  diff: number,
  title: string,
  options: QuestionOption[] | undefined,
  answer: string,
  analysis: string,
  tags?: string[]
): Question {
  return {
    id,
    type,
    gradeId,
    knowledgeIds,
    difficulty: diff,
    title,
    options,
    answer,
    analysis,
    tags: tags ?? [],
    createdAt: Date.now(),
    usageCount: 0,
    correctRate: 0,
  }
}

统一工厂函数的好处是:

  • 字段不会漏;
  • 默认值统一;
  • 后续新增字段更容易维护;
  • 题库数据更规范。

七、题目示例:一道题的完整信息

题库中的题目示例:

makeQuestion(
  'q_g1_as_001',
  'choice',
  'g1',
  ['kp_addsub'],
  1,
  '3 + 5 = ?',
  [
    { label: 'A', value: '6' },
    { label: 'B', value: '7' },
    { label: 'C', value: '8' },
    { label: 'D', value: '9' }
  ],
  'C',
  '3+5=8,想想3个苹果加上5个苹果,一共8个苹果。',
  ['口算', '基础']
)

这道题绑定了:

  • 一年级;
  • 加减运算知识点;
  • 选择题;
  • 难度 1;
  • 答案和解析;
  • 口算、基础标签。

这样才能在答题后做知识点统计。

八、本地索引:按年级和知识点筛题

项目提供了题库筛选函数:

export function getQuestionsByGradeAndKnowledge(
  gradeId: string,
  knowledgeIds: string[]
): Question[] {
  if (knowledgeIds.length === 0) {
    return getQuestionsByGrade(gradeId)
  }

  return QUESTION_BANK.filter((q: Question): boolean =>
    q.gradeId === gradeId &&
    knowledgeIds.some((kid: string): boolean =>
      q.knowledgeIds.indexOf(kid) >= 0
    )
  )
}

这个函数是本地题库索引的核心。它支持:

  • 年级挑战;
  • 知识点专项练习;
  • 分类入口;
  • 智能组卷。

九、题库数量统计:知识点可以显示题量

项目还提供了更新题量的方法:

export function updateQuestionBankCounts(): void {
  for (let i: number = 0; i < KNOWLEDGE_POINTS.length; i++) {
    const kp: KnowledgePoint = KNOWLEDGE_POINTS[i]
    let count: number = 0
    for (let j: number = 0; j < QUESTION_BANK.length; j++) {
      if (QUESTION_BANK[j].knowledgeIds.indexOf(kp.id) >= 0) {
        count++
      }
    }
    KNOWLEDGE_POINTS[i].questionCount = count
  }
}

这样知识点列表可以显示“这个知识点有多少题”,用户选择练习时更有预期。

十、端侧 AI:智能组卷从结构化题库开始

有了这些字段,就可以继续做端侧智能组卷:

function calcQuestionWeight(q: Question, weakKnowledgeIds: string[]): number {
  let weight = 1
  if (weakKnowledgeIds.some((kid: string) =>
    q.knowledgeIds.indexOf(kid) >= 0
  )) {
    weight += 2
  }
  if (q.correctRate < 0.6) {
    weight += 1
  }
  return weight
}

这里的智能不是云端大模型,而是本地规则:

  • 薄弱知识点权重更高;
  • 正确率低的题更容易出现;
  • 难度可以按阶段递进;
  • 最近做过的题可以降低权重。

十一、元服务扩展:今日一题

结构化题库也很适合做元服务:

  • 今日一题;
  • 薄弱点一题;
  • 年级速练;
  • 错题复习;
  • 公式相关题。

元服务只需要从 QUESTION_BANK 中取一题,再用 Question 结构渲染即可,不需要重新建数据模型。

十二、隐私保护:本地题库不上传学习内容

本地题库还有一个隐私优势:

  • 不需要拍照识题;
  • 不需要上传题目;
  • 不需要网络请求;
  • 不需要云端返回解析。

用户做题、看解析、生成结果都可以在端侧完成。

十三、总结

这篇文章聚焦数学视界的题库建模,和之前“知识点掌握度评估”文章区分开:本篇讲数据结构,前篇讲统计分析。

核心实现包括:

  • 🎓 用 Grade 建立 12 个年级体系;
  • 🧩 用 KnowledgePoint 建立知识点标签系统;
  • 📚 用 Question 表达题目、答案、解析、难度和标签;
  • 🏗 用 makeQuestion() 统一创建题目;
  • 🔍 用 getQuestionsByGradeAndKnowledge() 构建本地索引;
  • 📊 用 updateQuestionBankCounts() 统计知识点题量;
  • 🧠 为端侧智能组卷和元服务“今日一题”打基础;
  • 🔐 题库和解析都在本地,避免 AI 识图和云端上传。

结构化题库是学习 App 的地基。地基打好了,后续才能稳稳扩展挑战、复盘、推荐、报告和元服务。🚀

img

img

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐