API-INFO-004 P0 | 新增 MaterialReadingProgress 表 【status:todo】 #108

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

目标

用户-阅读对象维度的最新进度表。

关键字段

userId, readingTargetType, materialId, knowledgeBaseId?,
lastClientSessionId?, lastPosition (JSON),
lastProgress (0~1), totalActiveSeconds,
firstOpenedAt, lastOpenedAt, lastReadAt,
isMarkedRead, markedReadAt,
status (not_started|reading|read|abandoned|source_deleted|expired)

聚合规则

  • MaterialClosed 无 position 时不覆盖已有 lastPosition
  • 非法 position 不崩溃,事件仍保存

详见设计文档 API-INFO-000。

## 目标 用户-阅读对象维度的最新进度表。 ### 关键字段 ```text userId, readingTargetType, materialId, knowledgeBaseId?, lastClientSessionId?, lastPosition (JSON), lastProgress (0~1), totalActiveSeconds, firstOpenedAt, lastOpenedAt, lastReadAt, isMarkedRead, markedReadAt, status (not_started|reading|read|abandoned|source_deleted|expired) ``` ### 聚合规则 - MaterialClosed 无 position 时不覆盖已有 lastPosition - 非法 position 不崩溃,事件仍保存 详见设计文档 API-INFO-000。
wangdl added this to the M8:学习信息收集与基础分析闭环 milestone 2026-06-07 11:03:38 +08:00
wangdl changed title from API-INFO-003 P0 | 新增 MaterialReadingProgress 数据表 to API-INFO-004 P0 | 新增 MaterialReadingProgress 表 2026-06-07 11:22:14 +08:00
wangdl changed title from API-INFO-004 P0 | 新增 MaterialReadingProgress 表 to API-INFO-004 P0 | 新增 MaterialReadingProgress 表 【status:todo】 2026-06-07 19:04:10 +08:00
Author
Owner

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

本 Issue: 表不存在。全新建设。

标签: audit:reviewed audit:api-info status:todo work:new-table

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

完成报告

交付

1. Prisma Schemaprisma/schema.prisma 新增 MaterialReadingProgress 模型:

model MaterialReadingProgress {
  id                  String    @id @default(cuid())
  userId              String
  readingTargetType   String    @db.VarChar(32)
  materialId          String
  knowledgeBaseId     String?
  lastClientSessionId String?
  lastPosition        Json?
  lastProgress        Float?       // 0~1 归一化
  totalActiveSeconds  Int       @default(0)
  sessionCount        Int       @default(0)
  status              String    @default("not_started") @db.VarChar(32)
  firstOpenedAt       DateTime?
  lastOpenedAt        DateTime?
  lastReadAt          DateTime?
  isMarkedRead        Boolean   @default(false)
  markedReadAt        DateTime?

  @@unique([userId, materialId])
  @@index([knowledgeBaseId])
  @@index([status])
}

聚合规则(在 Service 中实现)

  • totalActiveSeconds 使用 { increment: delta } 原子累加
  • MaterialClosed 无 position 时不覆盖 lastPosition(update 中条件判断)
  • firstOpenedAt 仅首次设置,lastOpenedAt 每次更新
  • sessionCount 新 session 时 increment
  • status 枚举:not_started / reading / read / abandoned / source_deleted / expired

2. NestJS Modulesrc/modules/material-reading-progress/:

MaterialReadingProgressService.upsertProgress({
  userId, materialId, readingTargetType, knowledgeBaseId?,
  lastPosition?, lastProgress?, activeSecondsDelta, status?
})
MaterialReadingProgressService.getProgress(userId, materialId)
## 完成报告 ### 交付 **1. Prisma Schema** — `prisma/schema.prisma` 新增 `MaterialReadingProgress` 模型: ```prisma model MaterialReadingProgress { id String @id @default(cuid()) userId String readingTargetType String @db.VarChar(32) materialId String knowledgeBaseId String? lastClientSessionId String? lastPosition Json? lastProgress Float? // 0~1 归一化 totalActiveSeconds Int @default(0) sessionCount Int @default(0) status String @default("not_started") @db.VarChar(32) firstOpenedAt DateTime? lastOpenedAt DateTime? lastReadAt DateTime? isMarkedRead Boolean @default(false) markedReadAt DateTime? @@unique([userId, materialId]) @@index([knowledgeBaseId]) @@index([status]) } ``` **聚合规则(在 Service 中实现)**: - `totalActiveSeconds` 使用 `{ increment: delta }` 原子累加 - MaterialClosed 无 position 时不覆盖 `lastPosition`(update 中条件判断) - `firstOpenedAt` 仅首次设置,`lastOpenedAt` 每次更新 - `sessionCount` 新 session 时 increment - `status` 枚举:not_started / reading / read / abandoned / source_deleted / expired **2. NestJS Module** — `src/modules/material-reading-progress/`: ```typescript MaterialReadingProgressService.upsertProgress({ userId, materialId, readingTargetType, knowledgeBaseId?, lastPosition?, lastProgress?, activeSecondsDelta, status? }) MaterialReadingProgressService.getProgress(userId, materialId) ```
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#108
No description provided.