mirror of
https://gitee.com/koogua/course-tencent-cloud.git
synced 2025-06-24 20:06:09 +08:00
跟蹤學習記錄數據流
This commit is contained in:
parent
4665bdda33
commit
98e6a69e4a
@ -67,15 +67,21 @@ class SyncLearningTask extends Task
|
||||
$dbLearning = $learningRepo->findByRequestId($cacheLearning->request_id);
|
||||
|
||||
if (!$dbLearning) {
|
||||
|
||||
$cacheLearning->create();
|
||||
|
||||
$this->updateChapterUser($cacheLearning);
|
||||
|
||||
} else {
|
||||
$dbLearning->duration = $cacheLearning->duration;
|
||||
|
||||
$dbLearning->duration += $cacheLearning->duration;
|
||||
$dbLearning->position = $cacheLearning->position;
|
||||
$dbLearning->active_time = $cacheLearning->active_time;
|
||||
$dbLearning->update();
|
||||
}
|
||||
|
||||
$this->updateChapterUser($dbLearning);
|
||||
$dbLearning->update();
|
||||
|
||||
$this->updateChapterUser($dbLearning);
|
||||
}
|
||||
|
||||
$this->cache->delete($itemKey);
|
||||
}
|
||||
@ -87,7 +93,7 @@ class SyncLearningTask extends Task
|
||||
{
|
||||
$chapterUserRepo = new ChapterUserRepo();
|
||||
|
||||
$chapterUser = $chapterUserRepo->findChapterUser($learning->chapter_id, $learning->user_id);
|
||||
$chapterUser = $chapterUserRepo->findPlanChapterUser($learning->chapter_id, $learning->user_id, $learning->plan_id);
|
||||
|
||||
if (!$chapterUser) return;
|
||||
|
||||
@ -130,44 +136,42 @@ class SyncLearningTask extends Task
|
||||
$chapterUser->update();
|
||||
|
||||
if ($chapterUser->consumed == 1) {
|
||||
$this->updateCourseUser($chapterUser->course_id, $chapterUser->user_id);
|
||||
$this->updateCourseUser($learning);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $courseId
|
||||
* @param int $userId
|
||||
* @param LearningModel $learning
|
||||
*/
|
||||
protected function updateCourseUser($courseId, $userId)
|
||||
protected function updateCourseUser(LearningModel $learning)
|
||||
{
|
||||
$courseUserRepo = new CourseUserRepo();
|
||||
|
||||
$courseUser = $courseUserRepo->findCourseUser($courseId, $userId);
|
||||
$courseUser = $courseUserRepo->findPlanCourseUser($learning->course_id, $learning->user_id, $learning->plan_id);
|
||||
|
||||
if (!$courseUser) return;
|
||||
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$courseLessons = $courseRepo->findLessons($courseId);
|
||||
$courseLessons = $courseRepo->findLessons($learning->course_id);
|
||||
|
||||
if ($courseLessons->count() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$userLearnings = $courseRepo->findUserLearnings($courseId, $userId, $courseUser->plan_id);
|
||||
$userLearnings = $courseRepo->findUserLearnings($learning->course_id, $learning->user_id, $learning->plan_id);
|
||||
|
||||
if ($userLearnings->count() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @var array $consumedUserLearnings
|
||||
*/
|
||||
$consumedUserLearnings = $userLearnings->filter(function ($item) {
|
||||
if ($item->consumed == 1) {
|
||||
return $item;
|
||||
$consumedUserLearnings = [];
|
||||
|
||||
foreach ($userLearnings->toArray() as $userLearning) {
|
||||
if ($userLearning['consumed'] == 1) {
|
||||
$consumedUserLearnings[] = $userLearning;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (count($consumedUserLearnings) == 0) {
|
||||
return;
|
||||
@ -175,8 +179,8 @@ class SyncLearningTask extends Task
|
||||
|
||||
$duration = 0;
|
||||
|
||||
foreach ($consumedUserLearnings as $learning) {
|
||||
$duration += $learning['duration'];
|
||||
foreach ($consumedUserLearnings as $userLearning) {
|
||||
$duration += $userLearning['duration'];
|
||||
}
|
||||
|
||||
$courseLessonIds = kg_array_column($courseLessons->toArray(), 'id');
|
||||
|
@ -157,16 +157,16 @@
|
||||
|
||||
var changeVideoTemplate = function (format) {
|
||||
var template = $('input[name=video_template]');
|
||||
if (format == 'mp4') {
|
||||
template.val('10,20,30');
|
||||
if (format === 'mp4') {
|
||||
template.val('100010,100020,100030');
|
||||
} else {
|
||||
template.val('210,220,230');
|
||||
template.val('100210,100220,100230');
|
||||
}
|
||||
};
|
||||
|
||||
var changeAudioTemplate = function (format) {
|
||||
var template = $('input[name=audio_template]');
|
||||
if (format == 'mp3') {
|
||||
if (format === 'mp3') {
|
||||
template.val('1010');
|
||||
} else {
|
||||
template.val('1110');
|
||||
@ -175,7 +175,7 @@
|
||||
|
||||
form.on('radio(storage-type)', function (data) {
|
||||
var block = $('#storage-region-block');
|
||||
if (data.value == 'fixed') {
|
||||
if (data.value === 'fixed') {
|
||||
block.show();
|
||||
} else {
|
||||
block.hide();
|
||||
@ -184,7 +184,7 @@
|
||||
|
||||
form.on('radio(watermark-enabled)', function (data) {
|
||||
var block = $('#watermark-template-block');
|
||||
if (data.value == 1) {
|
||||
if (data.value === 1) {
|
||||
block.show();
|
||||
} else {
|
||||
block.hide();
|
||||
@ -193,7 +193,7 @@
|
||||
|
||||
form.on('radio(key-anti-enabled)', function (data) {
|
||||
var block = $('#key-anti-block');
|
||||
if (data.value == 1) {
|
||||
if (data.value === 1) {
|
||||
block.show();
|
||||
} else {
|
||||
block.hide();
|
||||
|
@ -1,4 +1,4 @@
|
||||
<table class="kg-table layui-table layui-form">
|
||||
<table class="kg-table layui-table">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
@ -25,7 +25,7 @@
|
||||
<p>类型:{{ item.client_type }}</p>
|
||||
<p>地址:<a href="javascript:" class="kg-ip2region" title="查看位置" data-ip="{{ item.client_ip }}">{{ item.client_ip }}</a></p>
|
||||
</td>
|
||||
<td>{{ item.duration|play_duration }}</td>
|
||||
<td>{{ item.duration|total_duration }}</td>
|
||||
<td>{{ date('Y-m-d H:i:s',item.active_time) }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
@ -3,6 +3,7 @@
|
||||
namespace App\Http\Web\Controllers;
|
||||
|
||||
use App\Models\ContentImage as ContentImageModel;
|
||||
use App\Services\Frontend\Chapter\Learning as LearningService;
|
||||
use App\Services\Storage as StorageService;
|
||||
use App\Traits\Response as ResponseTrait;
|
||||
use PHPQRCode\QRcode as PHPQRCode;
|
||||
@ -51,4 +52,16 @@ class PublicController extends \Phalcon\Mvc\Controller
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/learning", name="web.learning")
|
||||
*/
|
||||
public function learningAction()
|
||||
{
|
||||
$service = new LearningService();
|
||||
|
||||
$service->handle();
|
||||
|
||||
return $this->jsonSuccess();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -30,17 +30,40 @@
|
||||
|
||||
var interval = null;
|
||||
var intervalTime = 5000;
|
||||
var requestId = getRequestId();
|
||||
var chapterId = '{{ chapter.id }}';
|
||||
var playUrl = 'https://1255691183.vod2.myqcloud.com/81258db0vodtransgzp1255691183/89b3d8955285890796532522693/v.f220.m3u8?t=5ee5c6ed&exper=0&us=697028&sign=2b7fd89eff92236184eadbaa14a895dd';
|
||||
var position = 0;
|
||||
var chapterId = '{{ chapter.id }}';
|
||||
var courseId = '{{ chapter.course.id }}';
|
||||
var planId = '{{ chapter.me.plan_id }}';
|
||||
var userId = '{{ auth_user.id }}';
|
||||
var requestId = getRequestId();
|
||||
var playUrls = JSON.parse('{{ chapter.play_urls|json_encode }}');
|
||||
|
||||
var player = new TcPlayer('player', {
|
||||
m3u8: playUrl,
|
||||
autoplay: true,
|
||||
var options = {
|
||||
autoplay: false,
|
||||
width: 760,
|
||||
height: 450,
|
||||
listener: function (msg) {
|
||||
clarity: 'hd',
|
||||
clarityLabel: {
|
||||
od: '高清',
|
||||
hd: '标清',
|
||||
sd: '流畅'
|
||||
}
|
||||
};
|
||||
|
||||
if ('hd' in playUrls) {
|
||||
options.m3u8 = playUrls.hd.url;
|
||||
}
|
||||
|
||||
if ('sd' in playUrls) {
|
||||
options.m3u8_hd = playUrls.sd.url;
|
||||
}
|
||||
|
||||
if ('fd' in playUrls) {
|
||||
options.m3u8_sd = playUrls.fd.url;
|
||||
}
|
||||
|
||||
if (userId !== '0') {
|
||||
options.listener = function (msg) {
|
||||
if (msg.type === 'play') {
|
||||
start();
|
||||
} else if (msg.type === 'pause') {
|
||||
@ -49,7 +72,9 @@
|
||||
stop();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var player = new TcPlayer('player', options);
|
||||
|
||||
if (position > 0) {
|
||||
player.currentTime(position);
|
||||
@ -70,11 +95,14 @@
|
||||
|
||||
function learning() {
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: '/admin/vod/learning',
|
||||
type: 'POST',
|
||||
url: '/learning',
|
||||
data: {
|
||||
request_id: requestId,
|
||||
chapter_id: chapterId,
|
||||
course_id: courseId,
|
||||
user_id: userId,
|
||||
plan_id: planId,
|
||||
interval: intervalTime,
|
||||
position: player.currentTime(),
|
||||
}
|
||||
|
@ -49,4 +49,18 @@ class ChapterUser extends Repository
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $chapterId
|
||||
* @param int $userId
|
||||
* @param int $planId
|
||||
* @return ChapterUserModel|Model|bool
|
||||
*/
|
||||
public function findPlanChapterUser($chapterId, $userId, $planId)
|
||||
{
|
||||
return ChapterUserModel::findFirst([
|
||||
'conditions' => 'chapter_id = ?1 AND user_id = ?2 AND plan_id = ?3 AND deleted = 0',
|
||||
'bind' => [1 => $chapterId, 2 => $userId, 3 => $planId],
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -65,6 +65,20 @@ class CourseUser extends Repository
|
||||
return CourseUserModel::findFirst($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $courseId
|
||||
* @param int $userId
|
||||
* @param int $planId
|
||||
* @return CourseUserModel|Model|bool
|
||||
*/
|
||||
public function findPlanCourseUser($courseId, $userId, $planId)
|
||||
{
|
||||
return CourseUserModel::findFirst([
|
||||
'conditions' => 'course_id = ?1 AND user_id = ?2 AND plan_id = ?3 AND deleted = 0',
|
||||
'bind' => [1 => $courseId, 2 => $userId, 3 => $planId],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $courseId
|
||||
* @param int $userId
|
||||
|
@ -24,11 +24,45 @@ class ChapterVod extends Service
|
||||
|
||||
$vod = new Vod();
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($transcode as $key => $file) {
|
||||
$transcode[$key]['url'] = $vod->getPlayUrl($file['url']);
|
||||
|
||||
$file['url'] = $vod->getPlayUrl($file['url']);
|
||||
|
||||
$definition = $this->getDefinitionType($file['height'], $file['rate']);
|
||||
|
||||
$result[$definition] = $file;
|
||||
}
|
||||
|
||||
return $transcode;
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function getDefinitionType($height, $rate)
|
||||
{
|
||||
$default = 'od';
|
||||
|
||||
$vodTemplates = $this->getVodTemplates();
|
||||
|
||||
foreach ($vodTemplates as $key => $template) {
|
||||
if ($height >= $template['height'] || $rate >= $template['rate']) {
|
||||
return $key;
|
||||
}
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function getVodTemplates()
|
||||
{
|
||||
return [
|
||||
'hd' => ['height' => 720, 'rate' => 1800],
|
||||
'sd' => ['height' => 540, 'rate' => 1000],
|
||||
'fd' => ['height' => 360, 'rate' => 400],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -45,9 +45,9 @@ class ChapterInfo extends FrontendService
|
||||
$this->user = $user;
|
||||
|
||||
$this->setCourseUser($course, $user);
|
||||
$this->setChapterUser($chapter, $user);
|
||||
|
||||
$this->handleCourseUser($course, $user);
|
||||
|
||||
$this->setChapterUser($chapter, $user);
|
||||
$this->handleChapterUser($chapter, $user);
|
||||
|
||||
return $this->handleChapter($chapter, $user);
|
||||
@ -60,11 +60,19 @@ class ChapterInfo extends FrontendService
|
||||
$result['course'] = $this->handleCourse($this->course);
|
||||
|
||||
$me = [
|
||||
'plan_id' => 0,
|
||||
'joined' => 0,
|
||||
'owned' => 0,
|
||||
'agreed' => 0,
|
||||
'opposed' => 0,
|
||||
];
|
||||
|
||||
$me['owned'] = $this->ownedChapter;
|
||||
if ($this->courseUser) {
|
||||
$me['plan_id'] = $this->courseUser->plan_id;
|
||||
}
|
||||
|
||||
$me['joined'] = $this->joinedChapter ? 1 : 0;
|
||||
$me['owned'] = $this->ownedChapter ? 1 : 0;
|
||||
|
||||
if ($user->id > 0) {
|
||||
|
||||
@ -217,9 +225,12 @@ class ChapterInfo extends FrontendService
|
||||
$courseUser->user_id = $user->id;
|
||||
$courseUser->source_type = CourseUserModel::SOURCE_FREE;
|
||||
$courseUser->role_type = CourseUserModel::ROLE_STUDENT;
|
||||
$courseUser->expiry_time = strtotime('+3 years');
|
||||
|
||||
$courseUser->create();
|
||||
|
||||
$this->courseUser = $courseUser;
|
||||
|
||||
$this->incrCourseUserCount($course);
|
||||
}
|
||||
|
||||
@ -227,14 +238,7 @@ class ChapterInfo extends FrontendService
|
||||
{
|
||||
if ($user->id == 0) return;
|
||||
|
||||
/**
|
||||
* 一个课程可能购买学习多次
|
||||
*/
|
||||
if ($this->chapterUser && $this->courseUser) {
|
||||
if ($this->chapterUser->plan_id == $this->courseUser->plan_id) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ($this->joinedChapter) return;
|
||||
|
||||
if (!$this->ownedChapter) return;
|
||||
|
||||
@ -247,6 +251,8 @@ class ChapterInfo extends FrontendService
|
||||
|
||||
$chapterUser->create();
|
||||
|
||||
$this->chapterUser = $chapterUser;
|
||||
|
||||
$this->incrChapterUserCount($chapter);
|
||||
}
|
||||
|
||||
|
@ -14,24 +14,24 @@ class Learning extends FrontendService
|
||||
|
||||
use ChapterTrait;
|
||||
|
||||
public function handle($id)
|
||||
public function handle()
|
||||
{
|
||||
$chapter = $this->checkChapterCache($id);
|
||||
|
||||
$user = $this->getCurrentUser();
|
||||
|
||||
$post = $this->request->getPost();
|
||||
|
||||
if ($user->id == 0) return;
|
||||
$chapter = $this->checkChapterCache($post['chapter_id']);
|
||||
|
||||
$user = $this->getLoginUser();
|
||||
|
||||
$validator = new LearningValidator();
|
||||
|
||||
$data = [
|
||||
'course_id' => $chapter->course_id,
|
||||
'chapter_id' => $chapter->id,
|
||||
'user_id' => $user->id,
|
||||
];
|
||||
|
||||
$data['request_id'] = $validator->checkRequestId($post['request_id']);
|
||||
$data['plan_id'] = $validator->checkPlanId($post['plan_id']);
|
||||
|
||||
/**
|
||||
* @var array $attrs
|
||||
|
@ -22,7 +22,7 @@ trait ChapterTrait
|
||||
protected $joinedChapter = false;
|
||||
|
||||
/**
|
||||
* @var ChapterUserModel
|
||||
* @var ChapterUserModel|null
|
||||
*/
|
||||
protected $chapterUser;
|
||||
|
||||
@ -42,12 +42,18 @@ trait ChapterTrait
|
||||
|
||||
public function setChapterUser(ChapterModel $chapter, UserModel $user)
|
||||
{
|
||||
$chapterUserRepo = new ChapterUserRepo();
|
||||
$chapterUser = null;
|
||||
|
||||
$chapterUser = $chapterUserRepo->findChapterUser($chapter->id, $user->id);
|
||||
$courseUser = $this->courseUser;
|
||||
|
||||
if ($chapterUser) {
|
||||
$this->chapterUser = $chapterUser;
|
||||
if ($user->id > 0 && $courseUser) {
|
||||
$chapterUserRepo = new ChapterUserRepo();
|
||||
$chapterUser = $chapterUserRepo->findChapterUser($chapter->id, $user->id);
|
||||
}
|
||||
|
||||
$this->chapterUser = $chapterUser;
|
||||
|
||||
if ($chapterUser && $chapterUser->plan_id == $courseUser->plan_id) {
|
||||
$this->joinedChapter = true;
|
||||
}
|
||||
|
||||
|
@ -53,6 +53,7 @@ class CourseInfo extends FrontendService
|
||||
];
|
||||
|
||||
$me = [
|
||||
'plan_id' => 0,
|
||||
'joined' => 0,
|
||||
'owned' => 0,
|
||||
'reviewed' => 0,
|
||||
@ -60,6 +61,9 @@ class CourseInfo extends FrontendService
|
||||
'progress' => 0,
|
||||
];
|
||||
|
||||
$me['joined'] = $this->joinedCourse ? 1 : 0;
|
||||
$me['owned'] = $this->ownedCourse ? 1 : 0;
|
||||
|
||||
if ($user->id > 0) {
|
||||
|
||||
$favoriteRepo = new CourseFavoriteRepo();
|
||||
@ -73,10 +77,8 @@ class CourseInfo extends FrontendService
|
||||
if ($this->courseUser) {
|
||||
$me['reviewed'] = $this->courseUser->reviewed ? 1 : 0;
|
||||
$me['progress'] = $this->courseUser->progress ? 1 : 0;
|
||||
$me['plan_id'] = $this->courseUser->plan_id;
|
||||
}
|
||||
|
||||
$me['joined'] = $this->joinedCourse ? 1 : 0;
|
||||
$me['owned'] = $this->ownedCourse ? 1 : 0;
|
||||
}
|
||||
|
||||
$result['me'] = $me;
|
||||
|
@ -4,7 +4,6 @@ namespace App\Services\Syncer;
|
||||
|
||||
use App\Library\Cache\Backend\Redis as RedisCache;
|
||||
use App\Models\Learning as LearningModel;
|
||||
use App\Repos\Chapter as ChapterRepo;
|
||||
use App\Services\Service;
|
||||
use App\Traits\Client as ClientTrait;
|
||||
|
||||
@ -50,11 +49,6 @@ class Learning extends Service
|
||||
|
||||
if (!$cacheLearning) {
|
||||
|
||||
$chapterRepo = new ChapterRepo();
|
||||
|
||||
$chapter = $chapterRepo->findById($learning->chapter_id);
|
||||
|
||||
$learning->course_id = $chapter->course_id;
|
||||
$learning->client_type = $this->getClientType();
|
||||
$learning->client_ip = $this->getClientIp();
|
||||
$learning->duration = $interval;
|
||||
|
@ -380,7 +380,7 @@ class Vod extends Service
|
||||
|
||||
foreach ($videoTransTemplates as $key => $template) {
|
||||
|
||||
$caseA = $originVideoInfo['width'] >= $template['width'];
|
||||
$caseA = $originVideoInfo['height'] >= $template['height'];
|
||||
$caseB = $originVideoInfo['bit_rate'] >= 1000 * $template['bit_rate'];
|
||||
|
||||
if ($caseA || $caseB) {
|
||||
@ -589,15 +589,15 @@ class Vod extends Service
|
||||
public function getVideoTransTemplates()
|
||||
{
|
||||
$hls = [
|
||||
210 => ['width' => 480, 'bit_rate' => 256, 'frame_rate' => 24],
|
||||
220 => ['width' => 640, 'bit_rate' => 512, 'frame_rate' => 24],
|
||||
230 => ['width' => 1280, 'bit_rate' => 1024, 'frame_rate' => 25],
|
||||
100210 => ['height' => 360, 'bit_rate' => 400, 'frame_rate' => 25],
|
||||
100220 => ['height' => 540, 'bit_rate' => 1000, 'frame_rate' => 25],
|
||||
100230 => ['height' => 720, 'bit_rate' => 1800, 'frame_rate' => 25],
|
||||
];
|
||||
|
||||
$mp4 = [
|
||||
10 => ['width' => 480, 'bit_rate' => 256, 'frame_rate' => 24],
|
||||
20 => ['width' => 640, 'bit_rate' => 512, 'frame_rate' => 24],
|
||||
30 => ['width' => 1280, 'bit_rate' => 1024, 'frame_rate' => 25],
|
||||
100010 => ['height' => 360, 'bit_rate' => 400, 'frame_rate' => 25],
|
||||
100020 => ['height' => 540, 'bit_rate' => 1000, 'frame_rate' => 25],
|
||||
100030 => ['height' => 720, 'bit_rate' => 1800, 'frame_rate' => 25],
|
||||
];
|
||||
|
||||
$format = $this->settings['video_format'];
|
||||
|
@ -3,22 +3,18 @@
|
||||
namespace App\Validators;
|
||||
|
||||
use App\Exceptions\BadRequest as BadRequestException;
|
||||
use App\Repos\Chapter as ChapterRepo;
|
||||
use App\Library\Validators\Common as CommonValidator;
|
||||
|
||||
class Learning extends Validator
|
||||
{
|
||||
|
||||
public function checkChapterId($chapterId)
|
||||
public function checkPlanId($planId)
|
||||
{
|
||||
$chapterRepo = new ChapterRepo();
|
||||
|
||||
$chapter = $chapterRepo->findById($chapterId);
|
||||
|
||||
if (!$chapter) {
|
||||
throw new BadRequestException('learning.invalid_chapter_id');
|
||||
if (!CommonValidator::date($planId, 'Ymd')) {
|
||||
throw new BadRequestException('learning.invalid_plan_id');
|
||||
}
|
||||
|
||||
return $chapterId;
|
||||
return $planId;
|
||||
}
|
||||
|
||||
public function checkRequestId($requestId)
|
||||
@ -50,7 +46,7 @@ class Learning extends Validator
|
||||
|
||||
public function checkPosition($position)
|
||||
{
|
||||
$value = $this->filter->sanitize($position, ['trim', 'int']);
|
||||
$value = $this->filter->sanitize($position, ['trim', 'float']);
|
||||
|
||||
if ($value < 0 || $value > 3 * 3600) {
|
||||
throw new BadRequestException('learning.invalid_position');
|
||||
|
@ -320,7 +320,7 @@ $error['course_query.invalid_sort'] = '无效的排序类别';
|
||||
/**
|
||||
* 课时学习
|
||||
*/
|
||||
$error['learning.invalid_chapter_id'] = '无效的章节编号';
|
||||
$error['learning.invalid_plan_id'] = '无效的计划编号';
|
||||
$error['learning.invalid_request_id'] = '无效的请求编号';
|
||||
$error['learning.invalid_position'] = '无效的播放位置';
|
||||
$error['learning.invalid_interval'] = '无效的间隔时间';
|
||||
|
@ -363,7 +363,6 @@
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 80%;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.course-meta .share {
|
||||
|
Loading…
x
Reference in New Issue
Block a user