【听见课堂 HarmonyOS NEXT 实战系列 04】用领域模型串起课堂证据:Course、Transcript、Scan、Task 建模
2026/8/31 19:16:29 网站建设 项目流程

【听见课堂 HarmonyOS NEXT 实战系列 04】用领域模型串起课堂证据:Course、Transcript、Scan、Task 建模

课堂助手的数据模型如果只围绕页面设计,很容易变成“首页卡片一个类型、复习页卡片一个类型、历史页再复制一个类型”。同一段字幕被反复转换,来源时间和确认状态也可能在转换过程中丢失。

听见课堂选择从领域事实出发:课程是上下文,字幕和扫描是课堂证据,任务是经过确认后形成的行动项。页面需要的统计与分组,再由这些 canonical data 计算出来。

一、先区分事实数据与页面快照

事实数据描述“发生了什么”,页面快照描述“当前要怎么展示”。这两类模型不应该混在一起。

听见课堂的核心事实模型包括:

exportclassCourseSummary{id:string;title:string;teacher:string;room:string;startTime:string;progress:number;colorToken:string;}exportclassTranscriptSegment{id:string;timestamp:string;speaker:string;text:string;isKeyPoint:boolean;}

CourseSummary提供当前课堂上下文,TranscriptSegmenttimestamp定位片段。speaker允许界面区分教师、同学或未知说话人,isKeyPoint则体现用户是否把它标为重点。

这里也能看到当前模型的真实边界:项目目前围绕“今日课程”运行,字幕没有单独保存courseId。如果未来支持多课程长期归档,就需要在数据库迁移中补充稳定外键,而不能只在页面里临时拼接课程标题。

二、Scan 不应该只保存 OCR 文本

扫描记录不仅要有 OCR 文本,还要说明内容标题、识别置信度和证据来源。当前项目模型如下:

exportclassScanNote{id:string;title:string;text:string;confidence:number;source:string;}

其中text是可编辑的识别结果,confidence支持页面提示识别可信程度,source保存“板书/讲义 + 证据时间”等来源信息。原始拍摄图片由扫描服务流程管理,并没有直接塞进这个轻量领域对象。

实践中还要考虑:

  • 图像文件不存在时显示占位与说明;
  • OCR 失败时仍允许保存原图并稍后重试;
  • 删除扫描记录时同步处理文件引用,避免产生孤儿文件;
  • 导出时明确是否包含原始图片,而不是只导出文本。

三、Task 是行动项,也要保留课堂上下文

任务模型描述标题、截止时间、确认状态、完成状态和来源文案:

exportclassTaskItem{id:string;title:string;dueText:string;source:string;confirmed:boolean;completed:boolean;dueAtMillis:number;}

source让任务卡片可以显示它来自课堂字幕还是板书证据,confirmed则把候选任务与正式任务分开。dueText负责保留用户看到的自然语言,dueAtMillis用于排序、逾期判断和日历分组。

当前source仍是字符串,不是结构化外键。它适合现阶段本地单课程原型,但还不能可靠地级联检查来源证据是否被删除。后续若需要完整追溯,应增加sourceTypesourceIdcourseId,并同步修改表结构与迁移脚本。

四、时间统一用可计算值,展示交给页面

领域模型使用Millis数值,而不是直接保存“今天 18:00”“周三提交”这类展示文本。原因是:

  • 排序和区间筛选需要统一的时间基准;
  • “今天”“明天”“已逾期”会随当前时间变化;
  • 手机、平板以及不同语言环境可能采用不同展示格式;
  • 夏令时和时区转换不应由页面文案反向解析。

Service 可以基于dueAtMillis计算任务分组,页面再使用本地化格式显示。测试时应把当前时间作为可注入参数,避免依赖真实系统时钟导致用例在午夜前后随机失败。

五、Snapshot 是为页面服务的只读聚合

事实模型稳定之后,可以为具体页面定义快照,例如复习页快照和任务中心快照:

exportclassReviewSnapshot{completionPercent:number;masteryPercent:number;keyPointCount:number;scanCount:number;pendingCount:number;items:Array<ReviewTimelineItem>;}exportclassTaskCenterSnapshot{totalCount:number;pendingCount:number;completedCount:number;overdueCount:number;items:Array<TaskCenterItem>;calendarDays:Array<TaskCalendarDay>;}

Snapshot 可以随着页面需求调整,但不应该反过来污染数据库表。例如任务卡片的按钮文字、背景色和展开状态不属于TaskItem,它们应由页面根据状态和 theme token 决定。

六、导出模型要显式表达隐私边界

课堂数据可能包含敏感对话、师生姓名和拍摄图片。听见课堂的导出模型应明确包含哪些内容,并对原始音频保持显式开关:

exportclassClassroomDataExport{schemaVersion:number;exportedAt:string;storageMode:string;course:CourseSummary;transcript:Array<TranscriptSegment>;scans:Array<ScanNote>;tasks:Array<TaskItem>;rawAudioIncluded:boolean;}

如果当前版本没有保存原始音频,rawAudioIncluded就必须为false。不能因为产品展示了实时字幕,就在文案中暗示后台保存了完整录音。

同样,导出流程要由用户主动触发,并在导出前说明范围、目标位置和失败结果。日志中不应打印完整字幕、图片路径或个人信息。

七、模型演进要和数据库迁移同步

当后续增加“证据置信度”“用户修订历史”“跨课程任务”等字段时,不能只修改 ArkTS 接口。至少要同步处理:

  1. RelationalStore schema 版本;
  2. 旧数据默认值与迁移语句;
  3. Repository 的行映射;
  4. Service 的聚合规则;
  5. 导出格式兼容性;
  6. 空数据、脏数据和回滚策略。

如果后续把source拆成结构化来源类型,也要为未知旧值保留安全降级,避免升级后读取历史任务直接崩溃。

八、验证模型不能只看“能编译”

领域模型的验证应覆盖:

场景需要确认的结果
空课程页面进入空态,不构造虚假统计
未确认任务只进入候选区,不直接进入正式任务中心
OCR 失败原图仍可保存,识别文本可为空
截止时间跨日今日、逾期、未来分组稳定
删除来源证据当前字符串来源的限制被明确提示;结构化关联后再验证级联策略
旧版本升级缺失字段有默认值,历史数据可读取
数据导出导出范围与隐私说明一致

这些用例适合在 Service 与 Repository 层测试,再通过真机验证文件、数据库与生命周期行为。页面截图无法证明数据关联一定正确。

总结

好的领域模型不会追着页面布局变化,而是稳定表达业务事实。听见课堂用Course提供上下文,用TranscriptScan记录证据,用Task承接行动,再用 Snapshot 为不同页面聚合视图。

下一篇将回到 UI 外壳,拆解 12 个页面如何通过集中式RouteId、手机底部导航和平板侧栏保持一致的导航语义。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询