guoyu/_已清理文件备份_周六 22512/md/学习进度判断逻辑说明.md
2025-12-06 20:11:36 +08:00

10 KiB
Raw Blame History

学习进度判断逻辑说明

📊 核心逻辑

学习进度 = (累计学习时长 / 课程总时长) × 100%

🔍 详细判断流程

1. 课件类型分类

系统将课件分为以下类型:

类型 说明 是否参与进度计算 计算方式
video 视频课件 基于学习时长
document 文档课件PDF、Word、Excel等 基于完成状态
image 图片课件 基于完成状态
text 文本课件 -

2. 进度计算步骤(混合计算模式)

系统采用混合计算模式,不同类型课件使用不同的计算方式:

步骤1查询课程的所有课件

// 查询所有类型的课件
SELECT * FROM courseware WHERE course_id = ?

课件分类

  • 视频课件(type = 'video'
  • 图片课件(type = 'image'
  • 文档课件(type = 'document'包括PDF

步骤2分别计算各类型进度

2.1 视频进度计算(基于时长)

// 计算视频总时长
videoTotalDuration = SUM(video.duration)

// 估算视频学习时长(从总学习时长中提取)
videoLearningDuration = totalDuration × 0.7  // 假设视频占70%

// 计算视频进度
videoProgress = (videoLearningDuration / videoTotalDuration) × 100

关键点

  • 视频课件的 duration 字段必须设置(单位:秒)
  • 如果所有视频的 duration 都未设置,视频进度 = 0%

2.2 图片和PDF进度计算基于完成状态

// 统计图片和PDF总数
totalNonVideoCount = imageList.size() + documentList.size()

// 查询学习详情记录,估算已查看的课件数
viewedCount = min(学习详情记录数, totalNonVideoCount)

// 计算非视频进度
nonVideoProgress = (viewedCount / totalNonVideoCount) × 100

关键点

  • 通过查询学习详情记录来判断学生是否查看过课件
  • 每个图片/PDF查看一次默认算30秒学习时长
  • 如果学生有学习记录,认为至少查看过部分课件

步骤3计算权重并综合

// 计算权重
videoWeight = (视频数量 / 总课件数量) × 100
nonVideoWeight = ((图片数量 + PDF数量) / 总课件数量) × 100

// 综合进度
courseProgress = (videoProgress × videoWeight + nonVideoProgress × nonVideoWeight) / 100

计算公式

综合进度 = (视频进度 × 视频权重 + 非视频进度 × 非视频权重) / 100

其中:
- 视频权重 = 视频课件数 / 总课件数 × 100%
- 非视频权重 = (图片数 + PDF数) / 总课件数 × 100%

步骤4限制范围

if (progress > 100) progress = 100
if (progress < 0) progress = 0

进度限制在 0-100% 之间。

📝 代码位置

文件

Study-Vue-redis/ry-study-system/src/main/java/com/ddnai/system/service/impl/study/StudyLearningRecordServiceImpl.java

方法

private BigDecimal calculateCourseProgress(Long studentId, Long courseId, ...)

⚠️ 重要限制

1. 只计算视频课件

当前逻辑

  • 只有 type = 'video' 的课件参与进度计算
  • 图片、PDF、文档等不参与进度计算

影响

  • 如果课程只有图片或PDF没有视频进度会显示 0%
  • 即使学生学习了图片或PDF也不会增加进度

2. 视频时长必须设置

要求

  • 每个视频课件的 duration 字段必须设置(单位:秒)
  • 如果 duration 为 NULL 或 0该视频不计入课程总时长

影响

  • 如果所有视频的 duration 都未设置,课程总时长 = 0 → 进度 = 0%
  • 即使学生学习了很长时间,进度也会显示 0%

3. 学习时长统计

统计方式

  • 学生观看视频时,系统会记录学习时长
  • 每次学习都会累加到 total_duration 字段
  • 图片、PDF 等非视频课件的学习不统计学习时长

📊 实际案例

案例1正常情况

课程配置

  • 视频112分钟720秒
  • 视频210分钟600秒
  • 课程总时长1320秒22分钟

学生学习

  • 累计学习10分钟600秒

进度计算

进度 = (600 / 1320) × 100 = 45.45%

案例2视频时长未设置

课程配置

  • 视频1duration = NULL
  • 视频2duration = NULL
  • 课程总时长0秒

学生学习

  • 累计学习10分钟600秒

进度计算

进度 = (600 / 0) → 返回 0%避免除以0

案例3只有图片和PDF

课程配置

  • 图片1xxx.jpg
  • PDF1xxx.pdf
  • 视频:无
  • 总课件数2个

学生学习

  • 查看了图片和PDF
  • 学习详情记录2条每个课件查看一次
  • 累计学习60秒2个课件 × 30秒/个)

进度计算

视频进度 = 0%(没有视频)
非视频进度 = (2个已查看 / 2个总数) × 100 = 100%
视频权重 = 0 / 2 × 100 = 0%
非视频权重 = 2 / 2 × 100 = 100%
综合进度 = (0 × 0% + 100% × 100%) / 100 = 100%

案例4混合类型视频+图片+PDF

课程配置

  • 视频112分钟720秒
  • 图片1xxx.jpg
  • PDF1xxx.pdf
  • 总课件数3个

学生学习

  • 视频学习6分钟360秒
  • 查看了图片和PDF
  • 累计学习420秒360秒视频 + 60秒图片PDF

进度计算

视频进度 = (360 / 720) × 100 = 50%
非视频进度 = (2个已查看 / 2个总数) × 100 = 100%
视频权重 = 1 / 3 × 100 = 33.33%
非视频权重 = 2 / 3 × 100 = 66.67%
综合进度 = (50% × 33.33% + 100% × 66.67%) / 100 = 83.33%

🔧 如何修复进度问题

问题1进度显示0%,但学生已学习

原因:视频课件的 duration 未设置

解决方案

  1. 在管理端编辑视频课件,设置正确的时长(秒)
  2. 执行SQL重新计算进度
UPDATE learning_record lr
SET progress = (
    SELECT 
        CASE 
            WHEN SUM(cw.duration) IS NULL OR SUM(cw.duration) = 0 THEN 0
            ELSE LEAST(100, ROUND(lr.total_duration * 100.0 / SUM(cw.duration), 2))
        END
    FROM courseware cw
    WHERE cw.course_id = lr.course_id AND cw.type = 'video'
)
WHERE lr.total_duration > 0;

问题2图片和PDF进度计算已解决

当前实现

  • 图片和PDF已参与进度计算
  • 采用基于完成状态的计算方式
  • 通过查询学习详情记录来判断是否查看过

计算逻辑

  1. 统计课程中的图片和PDF数量
  2. 查询学生的学习详情记录
  3. 根据学习记录数量估算已查看的课件数
  4. 计算完成度:已查看数 / 总课件数 × 100%

注意事项

  • 前端需要在学生查看图片/PDF时记录学习详情
  • 每个图片/PDF查看一次默认算30秒学习时长
  • 如果课程只有图片和PDF没有视频进度会基于学习时长计算

📋 数据库字段说明

courseware 表(课件表)

字段 类型 说明 是否必需
id BIGINT 课件ID
course_id BIGINT 课程ID
type VARCHAR 课件类型video/document/image/text
duration INT 视频时长(秒,仅视频类型) ⚠️ 视频必需
title VARCHAR 课件标题
file_path VARCHAR 文件路径

learning_record 表(学习记录表)

字段 类型 说明
id BIGINT 记录ID
student_id BIGINT 学生ID
course_id BIGINT 课程ID
total_duration INT 累计学习时长(秒)
progress DECIMAL 学习进度0-100
learn_count INT 学习次数
last_learn_time DATETIME 最后学习时间

🎯 总结

核心要点

  1. 混合计算模式

    • 视频课件:基于学习时长计算
    • 图片和PDF基于完成状态计算
    • 文本课件:不参与进度计算
  2. 视频时长必须设置duration 字段必须大于0

  3. 计算公式

    综合进度 = (视频进度 × 视频权重 + 非视频进度 × 非视频权重) / 100
    
  4. 进度范围:限制在 0-100% 之间

  5. 图片和PDF完成判断

    • 通过查询学习详情记录来判断
    • 每个图片/PDF查看一次默认算30秒学习时长
    • 如果学生有学习记录,认为至少查看过部分课件

判断流程图

开始
  ↓
查询课程的所有课件
  ↓
分类统计视频、图片、PDF
  ↓
┌─────────────────┬─────────────────┐
│  视频进度计算    │  非视频进度计算   │
│  (基于时长)      │  (基于完成状态)   │
├─────────────────┼─────────────────┤
│ 1. 计算视频总时长│ 1. 统计图片/PDF数│
│ 2. 估算视频学习  │ 2. 查询学习记录  │
│    时长          │ 3. 估算已查看数  │
│ 3. 计算视频进度  │ 4. 计算完成度    │
└─────────────────┴─────────────────┘
  ↓
计算权重:
- 视频权重 = 视频数 / 总课件数
- 非视频权重 = (图片+PDF)数 / 总课件数
  ↓
综合进度 = (视频进度 × 视频权重 + 非视频进度 × 非视频权重) / 100
  ↓
限制在 0-100% 之间
  ↓
返回进度

📚 相关文件

  • 后端代码StudyLearningRecordServiceImpl.java
  • 诊断SQLdatabase_check_learning_progress.sql
  • 修复SQLdatabase_fix_video_duration_and_progress.sql
  • 说明文档学习进度问题修复说明.md

🔍 调试方法

查看后端日志

后端已添加详细日志,重启服务后可以看到:

INFO - 开始计算学习进度 - 学生ID: 109, 课程ID: 3
INFO - 课程 3 包含 2 个视频课件
WARN - 视频课件 8 (亡羊补牢) 的时长未设置或为0
INFO - 课程 3 总时长: 1440秒 (24分钟), 2个视频有时长, 0个视频无时长
INFO - 学生 109 对课程 3 的累计学习时长: 3秒 (0分钟)
INFO - 计算进度: 3 / 1440 * 100 = 0.21%
INFO - 最终进度: 0.21%

执行诊断SQL

-- 查看学习记录和进度
SELECT 
    lr.id,
    lr.course_id,
    c.course_name,
    lr.total_duration as '累计时长(秒)',
    lr.progress as '进度(%)',
    (SELECT SUM(duration) FROM courseware WHERE course_id = lr.course_id AND type = 'video') as '课程总时长(秒)'
FROM learning_record lr
LEFT JOIN course c ON lr.course_id = c.id;