【听见课堂 HarmonyOS NEXT 实战系列 04】用领域模型串起课堂证据:Course、Transcript、Scan、Task 建模 📅 发布时间:2026/8/31 19:16:55 👁 浏览次数: 【听见课堂 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提供当前课堂上下文TranscriptSegment用timestamp定位片段。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仍是字符串不是结构化外键。它适合现阶段本地单课程原型但还不能可靠地级联检查来源证据是否被删除。后续若需要完整追溯应增加sourceType、sourceId和courseId并同步修改表结构与迁移脚本。四、时间统一用可计算值展示交给页面领域模型使用Millis数值而不是直接保存“今天 18:00”“周三提交”这类展示文本。原因是排序和区间筛选需要统一的时间基准“今天”“明天”“已逾期”会随当前时间变化手机、平板以及不同语言环境可能采用不同展示格式夏令时和时区转换不应由页面文案反向解析。Service 可以基于dueAtMillis计算任务分组页面再使用本地化格式显示。测试时应把当前时间作为可注入参数避免依赖真实系统时钟导致用例在午夜前后随机失败。五、Snapshot 是为页面服务的只读聚合事实模型稳定之后可以为具体页面定义快照例如复习页快照和任务中心快照exportclassReviewSnapshot{completionPercent:number;masteryPercent:number;keyPointCount:number;scanCount:number;pendingCount:number;items:ArrayReviewTimelineItem;}exportclassTaskCenterSnapshot{totalCount:number;pendingCount:number;completedCount:number;overdueCount:number;items:ArrayTaskCenterItem;calendarDays:ArrayTaskCalendarDay;}Snapshot 可以随着页面需求调整但不应该反过来污染数据库表。例如任务卡片的按钮文字、背景色和展开状态不属于TaskItem它们应由页面根据状态和 theme token 决定。六、导出模型要显式表达隐私边界课堂数据可能包含敏感对话、师生姓名和拍摄图片。听见课堂的导出模型应明确包含哪些内容并对原始音频保持显式开关exportclassClassroomDataExport{schemaVersion:number;exportedAt:string;storageMode:string;course:CourseSummary;transcript:ArrayTranscriptSegment;scans:ArrayScanNote;tasks:ArrayTaskItem;rawAudioIncluded:boolean;}如果当前版本没有保存原始音频rawAudioIncluded就必须为false。不能因为产品展示了实时字幕就在文案中暗示后台保存了完整录音。同样导出流程要由用户主动触发并在导出前说明范围、目标位置和失败结果。日志中不应打印完整字幕、图片路径或个人信息。七、模型演进要和数据库迁移同步当后续增加“证据置信度”“用户修订历史”“跨课程任务”等字段时不能只修改 ArkTS 接口。至少要同步处理RelationalStore schema 版本旧数据默认值与迁移语句Repository 的行映射Service 的聚合规则导出格式兼容性空数据、脏数据和回滚策略。如果后续把source拆成结构化来源类型也要为未知旧值保留安全降级避免升级后读取历史任务直接崩溃。八、验证模型不能只看“能编译”领域模型的验证应覆盖场景需要确认的结果空课程页面进入空态不构造虚假统计未确认任务只进入候选区不直接进入正式任务中心OCR 失败原图仍可保存识别文本可为空截止时间跨日今日、逾期、未来分组稳定删除来源证据当前字符串来源的限制被明确提示结构化关联后再验证级联策略旧版本升级缺失字段有默认值历史数据可读取数据导出导出范围与隐私说明一致这些用例适合在 Service 与 Repository 层测试再通过真机验证文件、数据库与生命周期行为。页面截图无法证明数据关联一定正确。总结好的领域模型不会追着页面布局变化而是稳定表达业务事实。听见课堂用Course提供上下文用Transcript和Scan记录证据用Task承接行动再用 Snapshot 为不同页面聚合视图。下一篇将回到 UI 外壳拆解 12 个页面如何通过集中式RouteId、手机底部导航和平板侧栏保持一致的导航语义。