Commit 91792091 authored by wangzhengwen's avatar wangzhengwen

学习进度优化

parent f3000da9
<?php
namespace app\api\controller;
use OSS\OssClient;
class Test
{
public function concurrentUpload($object, $filePath) {
$ossClient = new OssClient(/* 配置 */);
$uploadId = $ossClient->initiateMultipartUpload(config('oss.bucket'), $object);
$partSize = 10 * 1024 * 1024;
$fileSize = filesize($filePath);
$partNum = ceil($fileSize / $partSize);
$parts = [];
$promises = [];
// 使用Guzzle或其他HTTP客户端并发请求
$client = new \GuzzleHttp\Client();
for ($i = 1; $i <= $partNum; $i++) {
$from = ($i - 1) * $partSize;
$to = min($i * $partSize, $fileSize);
$promises[] = $client->postAsync('您的上传处理接口', [
'multipart' => [
[
'name' => 'part_index',
'contents' => $i
],
[
'name' => 'file',
'contents' => fopen($filePath, 'r'),
'headers' => [
'Content-Range' => 'bytes '.$from.'-'.$to.'/'.$fileSize
]
]
]
])->then(function($response) use (&$parts, $i) {
$parts[$i] = [
'PartNumber' => $i,
'ETag' => $response->getHeader('ETag')[0]
];
});
}
// 等待所有分片上传完成
\GuzzleHttp\Promise\Utils::all($promises)->wait();
// 按分片顺序排序
ksort($parts);
// 完成上传
$ossClient->completeMultipartUpload(config('oss.bucket'), $object, $uploadId, $parts);
}
}
\ No newline at end of file
......@@ -7,12 +7,13 @@ use app\model\CourseProgress;
use app\model\CourseUserWork;
use app\model\CourseWork;
use app\model\Payment;
use think\Exception;
class CourseProgressService
{
// 常量定义
const MIN_CONSIDERED_FINISHED_SECONDS = 10; // 视为完成的最小观看秒数
const MIN_CONSIDERED_FINISHED_SECONDS = 0; // 视为完成的最小观看秒数
const FINISHED_THRESHOLD_PERCENT = 95; // 视为完成的进度百分比阈值
/**
......@@ -190,12 +191,15 @@ class CourseProgressService
];
}
// /**
// * 获取用户课程进度统计
// * @param int $userId 用户ID
// * @param int $courseId 课程ID
// * @return array
// */
/**获取课程学习进度 7.3 老版本 记录5s 单课时
* @param $userId
* @param $courseId
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
// public static function getCourseProgress($userId, $courseId)
// {
// // 获取所有课时进度
......@@ -203,98 +207,150 @@ class CourseProgressService
// ->where('user_id', $userId)
// ->where('course_id', $courseId)
// ->select();
//
// // 统计计算
// $finishedCount = 0;
// $totalDuration = 0;
// $learnedDuration = 0;
// $totalDuration = 0; // 课程总时长(所有课时的 tvtime 之和)
// $learnedDuration = 0; // 有效学习时长(用于计算进度)
// $totalLearnedDuration = 0; // 总观看时长(实际观看时间,不经过优化逻辑)
//
// $classProgress = [];
// foreach ($progressList as $item) {
// if ($item->is_wc_look) {
// // 计算当前课时的观看比例
// $currentProgress = ($item->tvtime > 0) ? ($item->look_tvtime / $item->tvtime) : 0;
//
// // 判断是否满足"视为完成"的条件(观看时间<10s 或 进度>95%)
// $isConsideredFinished = ($item->look_tvtime < self::MIN_CONSIDERED_FINISHED_SECONDS) || ($currentProgress > self::FINISHED_THRESHOLD_PERCENT);
//
// // 计算有效学习时长(用于进度计算)
// if ($item->is_wc_look || $isConsideredFinished) {
// $finishedCount++;
// $learnedDuration += $item->tvtime; // 视为完成则计入全部时长
// } else {
// $learnedDuration += min($item->look_tvtime, $item->tvtime);
// }
//
// // 总观看时长(直接累加 look_tvtime,不经过优化逻辑)
// $totalLearnedDuration += $item->look_tvtime;
//
// // 课程总时长(所有课时的 tvtime 之和)
// $totalDuration += $item->tvtime;
// $learnedDuration += min($item->look_tvtime, $item->tvtime);
//
// $classProgress[$item->class_id] = [
// 'progress' => $item->look_tvtime,
// 'duration' => $item->tvtime,
// 'is_finished' => $item->is_wc_look,
// 'is_finished' => $item->is_wc_look || $isConsideredFinished,
// 'last_learn' => $item->createtime,
// 'class_id' => $item->class_id//课时id,
// 'class_id' => $item->class_id
// ];
// }
// $progress_percent = $totalDuration > 0 ? round($learnedDuration / $totalDuration * 100) : 0;
//
// // 计算总进度(如果满足条件则直接显示100%)
// $progress_percent = ($totalDuration > 0)
// ? round($learnedDuration / $totalDuration * 100)
// : 0;
//
// // 应用优化规则:如果观看进度<10s或已完成>95%,则显示100%
// if ($progress_percent > self::FINISHED_THRESHOLD_PERCENT || $learnedDuration < self::MIN_CONSIDERED_FINISHED_SECONDS) {
// $progress_percent = 100;
// }
//
// return [
// 'finished_count' => $finishedCount,
// 'total_classes' => count($progressList),
// 'progress_percent' => $totalDuration > 0 ? round($learnedDuration / $totalDuration * 100) : 0,
// 'progress_percent' => min($progress_percent, 100), // 确保不超过100%
// 'total_duration' => $totalDuration, // 课程总时长(秒)
// 'total_learned_duration' => $totalLearnedDuration, // 用户实际观看总时长(秒)
// 'classes' => $classProgress
// ];
// }
public static function getCourseProgress($userId, $courseId)
{
// 获取所有课时进度
$progressList = CourseProgress::with(['class'])
->where('user_id', $userId)
// 1. 获取课程及所有课时(通过关联查询)
$course = Course::with(['getCourseClass' => function($query) {
$query->where('is_del', 0)->where('is_sell', 1)->order('sort', 'asc');
}])->where('id', $courseId)->find();
if (!$course) {
throw new Exception('课程不存在');
}
// 2. 获取用户的学习进度记录
$progressList = CourseProgress::where('user_id', $userId)
->where('course_id', $courseId)
->select();
->select()
->toArray();
// 转换为以class_id为键的数组
$progressMap = [];
foreach ($progressList as $progress) {
$progressMap[$progress['class_id']] = $progress;
}
// 统计计算
// 3. 统计计算
$finishedCount = 0;
$totalDuration = 0; // 课程总时长(所有课时的 tvtime 之和)
$learnedDuration = 0; // 有效学习时长(用于计算进度)
$totalLearnedDuration = 0; // 总观看时长(实际观看时间,不经过优化逻辑)
$totalDuration = 0;
$learnedDuration = 0;
$totalLearnedDuration = 0;
$classProgress = [];
foreach ($progressList as $item) {
foreach ($course->getCourseClass as $class) {
$class = $class->toArray();
$progress = $progressMap[$class['id']] ?? null;
// 使用数组访问方式
$lookTvtime = $progress ? $progress['look_tvtime'] : 0;
$isWcLook = $progress ? (bool)$progress['is_wc_look'] : false;
$tvtime = $class['tvtime'] ?? 0;
// 计算当前课时的观看比例
$currentProgress = ($item->tvtime > 0) ? ($item->look_tvtime / $item->tvtime) : 0;
$currentProgress = ($tvtime > 0) ? ($lookTvtime / $tvtime) : 0;
// 判断是否满足"视为完成"的条件(观看时间<10s 或 进度>95%)
$isConsideredFinished = ($item->look_tvtime < self::MIN_CONSIDERED_FINISHED_SECONDS) || ($currentProgress > self::FINISHED_THRESHOLD_PERCENT);
// 判断是否满足"视为完成"的条件
$isConsideredFinished = ($lookTvtime < self::MIN_CONSIDERED_FINISHED_SECONDS)
|| ($currentProgress > self::FINISHED_THRESHOLD_PERCENT);
// 计算有效学习时长(用于进度计算)
if ($item->is_wc_look || $isConsideredFinished) {
// 计算有效学习时长
if ($isWcLook || $isConsideredFinished) {
$finishedCount++;
$learnedDuration += $item->tvtime; // 视为完成则计入全部时长
$learnedDuration += $tvtime;
} else {
$learnedDuration += min($item->look_tvtime, $item->tvtime);
$learnedDuration += min($lookTvtime, $tvtime);
}
// 总观看时长(直接累加 look_tvtime,不经过优化逻辑)
$totalLearnedDuration += $item->look_tvtime;
// 课程总时长(所有课时的 tvtime 之和)
$totalDuration += $item->tvtime;
$classProgress[$item->class_id] = [
'progress' => $item->look_tvtime,
'duration' => $item->tvtime,
'is_finished' => $item->is_wc_look || $isConsideredFinished,
'last_learn' => $item->createtime,
'class_id' => $item->class_id
$totalLearnedDuration += $lookTvtime;
$totalDuration += $tvtime;
$classProgress[$class['id']] = [
'progress' => $lookTvtime,
'duration' => $tvtime,
'is_finished' => $isWcLook || $isConsideredFinished,
'last_learn' => $progress ? $progress['createtime'] : null,
'class_id' => $class['id'],
'title' => $class['title'],
'type' => $class['type']
];
}
// 计算总进度(如果满足条件则直接显示100%)
// 计算总进度
$progress_percent = ($totalDuration > 0)
? round($learnedDuration / $totalDuration * 100)
: 0;
// 应用优化规则:如果观看进度<10s或已完成>95%,则显示100%
if ($progress_percent > self::FINISHED_THRESHOLD_PERCENT || $learnedDuration < self::MIN_CONSIDERED_FINISHED_SECONDS) {
if ($progress_percent > self::FINISHED_THRESHOLD_PERCENT
|| $learnedDuration < self::MIN_CONSIDERED_FINISHED_SECONDS) {
$progress_percent = 100;
}
return [
'course_id' => $course->id,
'course_title' => $course->title,
'finished_count' => $finishedCount,
'total_classes' => count($progressList),
'progress_percent' => min($progress_percent, 100), // 确保不超过100%
'total_duration' => $totalDuration, // 课程总时长(秒)
'total_learned_duration' => $totalLearnedDuration, // 用户实际观看总时长(秒)
'total_classes' => count($course->getCourseClass),
'progress_percent' => min($progress_percent, 100),
'total_duration' => $totalDuration,
'total_learned_duration' => $totalLearnedDuration,
'classes' => $classProgress
];
}
......
......@@ -73,7 +73,7 @@ class CertOrder extends Model
$list = self::where($where)
->with(['user'=>['headico'],'cert'])
->order('createtime','desc')
->field('id,cert_id,user_id,name,updatetime')
->field('id,cert_id,user_id,name,updatetime,createtime')
->append(['updatetime_text'])
->paginate([
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment