API-INFO-015 P0 | 写入 LearningRecord 阅读记录 【status:todo】 #131

Closed
opened 2026-06-07 11:22:54 +08:00 by wangdl · 2 comments
Owner

目标

MaterialClosed 后写入 LearningRecord 阅读记录。

触发时机

MaterialClosed 事件处理成功后

规则

recordType = reading
title = 阅读了《资料标题》
durationSeconds = LearningSession.durationSeconds
sessionId = LearningSession.id
同一 userId+clientSessionId 只生成一条 reading record

验收标准

  1. closed 后写入 LearningRecord
  2. 同一 clientSessionId 不重复写入
  3. durationSeconds 正确
  4. title 使用资料标题
## 目标 MaterialClosed 后写入 LearningRecord 阅读记录。 ## 触发时机 MaterialClosed 事件处理成功后 ## 规则 ```text recordType = reading title = 阅读了《资料标题》 durationSeconds = LearningSession.durationSeconds sessionId = LearningSession.id 同一 userId+clientSessionId 只生成一条 reading record ``` ## 验收标准 1. closed 后写入 LearningRecord 2. 同一 clientSessionId 不重复写入 3. durationSeconds 正确 4. title 使用资料标题
wangdl added this to the M8:学习信息收集与基础分析闭环 milestone 2026-06-07 11:22:54 +08:00
wangdl changed title from API-INFO-015 P0 | 写入 LearningRecord 阅读记录 to API-INFO-015 P0 | 写入 LearningRecord 阅读记录 【status:todo】 2026-06-07 19:04:14 +08:00
Author
Owner

审查结论:当前 API 项目学习信息收集体系基本为全新建设。可复用:JWT Guard、LearningSession 基础表/CRUD、DailyLearningActivity 基础表、ActivityController 部分接口、LearningRecord schema。其余 ReadingEvent/TemporaryMaterial/Progress/批量上报/Processor/聚合/查询接口/错误码/去重/权限/测试/文档均不存在或仅部分存在。

本 Issue: 聚合逻辑不存在。blocked-by:processor

标签: audit:reviewed audit:api-info status:todo work:aggregation

## 审查结论:当前 API 项目学习信息收集体系基本为全新建设。可复用:JWT Guard、LearningSession 基础表/CRUD、DailyLearningActivity 基础表、ActivityController 部分接口、LearningRecord schema。其余 ReadingEvent/TemporaryMaterial/Progress/批量上报/Processor/聚合/查询接口/错误码/去重/权限/测试/文档均不存在或仅部分存在。 **本 Issue**: 聚合逻辑不存在。blocked-by:processor **标签**: audit:reviewed audit:api-info status:todo work:aggregation
Author
Owner

完成报告

交付

ProcessorService 事务新增 Step 5d — LearningRecord 写入

// 仅在以下事件写入记录:
//   material_opened  → "Reading started"
//   material_closed  → "Reading ended"
//   marked_as_read   → "Marked as read"

if (["material_opened", "material_closed", "marked_as_read"].includes(eventType)) {
  await this.recordSvc.createReadingRecord({
    userId, sessionId, materialId, readingTargetType,
    knowledgeBaseId, title, totalActiveSeconds, lastPosition, occurredAt
  });
}

metadata 格式 (如 #119 定义):

{
  "materialId": "...",
  "readingTargetType": "knowledge_source",
  "knowledgeBaseId": "...",
  "totalActiveSeconds": 120,
  "lastPosition": { "type": "...", "progress": 0.5 }
}

完整事务流程(5 步聚合在一事务中):

$transaction:
  4.  insert ReadingEvent
  5a. aggregate → LearningSession
  5b. aggregate → MaterialReadingProgress
  5c. aggregate → DailyLearningActivity
  5d. write → LearningRecord (条件)
  6.  mark processed
## 完成报告 ### 交付 **ProcessorService 事务新增 Step 5d — LearningRecord 写入**: ```typescript // 仅在以下事件写入记录: // material_opened → "Reading started" // material_closed → "Reading ended" // marked_as_read → "Marked as read" if (["material_opened", "material_closed", "marked_as_read"].includes(eventType)) { await this.recordSvc.createReadingRecord({ userId, sessionId, materialId, readingTargetType, knowledgeBaseId, title, totalActiveSeconds, lastPosition, occurredAt }); } ``` **metadata 格式** (如 #119 定义): ```json { "materialId": "...", "readingTargetType": "knowledge_source", "knowledgeBaseId": "...", "totalActiveSeconds": 120, "lastPosition": { "type": "...", "progress": 0.5 } } ``` **完整事务流程**(5 步聚合在一事务中): ``` $transaction: 4. insert ReadingEvent 5a. aggregate → LearningSession 5b. aggregate → MaterialReadingProgress 5c. aggregate → DailyLearningActivity 5d. write → LearningRecord (条件) 6. mark processed ```
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: wangdl/api-server#131
No description provided.