mirror of
https://gitee.com/koogua/course-tencent-cloud.git
synced 2025-07-10 10:40:03 +08:00
整理功能
This commit is contained in:
parent
23e19cd279
commit
ab27040f2f
@ -1,99 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Builders;
|
||||
|
||||
use App\Repos\Chapter as ChapterRepo;
|
||||
use App\Repos\Course as CourseRepo;
|
||||
use App\Repos\User as UserRepo;
|
||||
|
||||
class CommentList extends Builder
|
||||
{
|
||||
|
||||
public function handleCourses(array $comments)
|
||||
{
|
||||
$courses = $this->getCourses($comments);
|
||||
|
||||
foreach ($comments as $key => $comment) {
|
||||
$comments[$key]['course'] = $courses[$comment['course_id']] ?? new \stdClass();
|
||||
}
|
||||
|
||||
return $comments;
|
||||
}
|
||||
|
||||
public function handleChapters(array $comments)
|
||||
{
|
||||
$chapters = $this->getChapters($comments);
|
||||
|
||||
foreach ($comments as $key => $comment) {
|
||||
$comments[$key]['chapter'] = $chapters[$comment['chapter_id']] ?? new \stdClass();
|
||||
}
|
||||
|
||||
return $comments;
|
||||
}
|
||||
|
||||
public function handleUsers(array $comments)
|
||||
{
|
||||
$users = $this->getUsers($comments);
|
||||
|
||||
foreach ($comments as $key => $comment) {
|
||||
$comments[$key]['user'] = $users[$comment['user_id']] ?? new \stdClass();
|
||||
}
|
||||
|
||||
return $comments;
|
||||
}
|
||||
|
||||
public function getCourses(array $comments)
|
||||
{
|
||||
$ids = kg_array_column($comments, 'course_id');
|
||||
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$courses = $courseRepo->findByIds($ids, ['id', 'title']);
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($courses->toArray() as $course) {
|
||||
$result[$course['id']] = $course;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getChapters(array $comments)
|
||||
{
|
||||
$ids = kg_array_column($comments, 'chapter_id');
|
||||
|
||||
$chapterRepo = new ChapterRepo();
|
||||
|
||||
$chapters = $chapterRepo->findByIds($ids, ['id', 'title']);
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($chapters->toArray() as $chapter) {
|
||||
$result[$chapter['id']] = $chapter;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getUsers(array $comments)
|
||||
{
|
||||
$ids = kg_array_column($comments, 'user_id');
|
||||
|
||||
$userRepo = new UserRepo();
|
||||
|
||||
$users = $userRepo->findByIds($ids, ['id', 'name', 'avatar']);
|
||||
|
||||
$baseUrl = kg_ci_base_url();
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($users->toArray() as $user) {
|
||||
$user['avatar'] = $baseUrl . $user['avatar'];
|
||||
$result[$user['id']] = $user;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
@ -29,8 +29,7 @@ class ChapterCounter extends Counter
|
||||
|
||||
return [
|
||||
'user_count' => $chapter->user_count,
|
||||
'lesson_count' => $chapter->lesson_count,
|
||||
'comment_count' => $chapter->comment_count,
|
||||
'consult_count' => $chapter->consult_count,
|
||||
'like_count' => $chapter->like_count,
|
||||
];
|
||||
}
|
||||
|
@ -1,36 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Caches;
|
||||
|
||||
use App\Repos\Comment as CommentRepo;
|
||||
|
||||
class CommentCounter extends Counter
|
||||
{
|
||||
|
||||
protected $lifetime = 1 * 86400;
|
||||
|
||||
public function getLifetime()
|
||||
{
|
||||
return $this->lifetime;
|
||||
}
|
||||
|
||||
public function getKey($id = null)
|
||||
{
|
||||
return "comment_counter:{$id}";
|
||||
}
|
||||
|
||||
public function getContent($id = null)
|
||||
{
|
||||
$commentRepo = new CommentRepo();
|
||||
|
||||
$comment = $commentRepo->findById($id);
|
||||
|
||||
if (!$comment) return null;
|
||||
|
||||
return [
|
||||
'reply_count' => $comment->reply_count,
|
||||
'like_count' => $comment->like_count,
|
||||
];
|
||||
}
|
||||
|
||||
}
|
@ -65,7 +65,7 @@ class CourseRecommendedList extends Cache
|
||||
public function findCourses($limit = 5)
|
||||
{
|
||||
return CourseModel::query()
|
||||
->where('published = 1 AND deleted = 0 AND market_price > 0')
|
||||
->where('published = 1 AND market_price > 0')
|
||||
->orderBy('RAND()')
|
||||
->limit($limit)
|
||||
->execute();
|
||||
|
@ -58,7 +58,7 @@ class CourseTopicList extends Cache
|
||||
public function findTopics($limit = 5)
|
||||
{
|
||||
return TopicModel::query()
|
||||
->where('published = 1 AND deleted = 0')
|
||||
->where('published = 1')
|
||||
->orderBy('RAND()')
|
||||
->limit($limit)
|
||||
->execute();
|
||||
|
@ -63,7 +63,7 @@ class IndexSlideList extends Cache
|
||||
public function findSlides($limit = 5)
|
||||
{
|
||||
return SlideModel::query()
|
||||
->where('published = 1 AND deleted = 0')
|
||||
->where('published = 1')
|
||||
->orderBy('priority ASC')
|
||||
->limit($limit)
|
||||
->execute();
|
||||
|
@ -16,7 +16,7 @@ class MaxImGroupId extends Cache
|
||||
|
||||
public function getKey($id = null)
|
||||
{
|
||||
return 'max_im_chat_group_id';
|
||||
return 'max_im_group_id';
|
||||
}
|
||||
|
||||
public function getContent($id = null)
|
55
app/Console/Tasks/CleanSessionTask.php
Normal file
55
app/Console/Tasks/CleanSessionTask.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Tasks;
|
||||
|
||||
use App\Library\Cache\Backend\Redis as RedisCache;
|
||||
use Phalcon\Cli\Task;
|
||||
|
||||
class CleanSessionTask extends Task
|
||||
{
|
||||
|
||||
/**
|
||||
* @var RedisCache
|
||||
*/
|
||||
protected $cache;
|
||||
|
||||
/**
|
||||
* @var \Redis
|
||||
*/
|
||||
protected $redis;
|
||||
|
||||
public function mainAction()
|
||||
{
|
||||
$this->cache = $this->getDI()->get('cache');
|
||||
|
||||
$this->redis = $this->cache->getRedis();
|
||||
|
||||
$keys = $this->querySessionKeys(10000);
|
||||
|
||||
if (count($keys) == 0) return;
|
||||
|
||||
$config = $this->getDI()->get('config');
|
||||
|
||||
$lifetime = $config->session->lifetime;
|
||||
|
||||
foreach ($keys as $key) {
|
||||
$ttl = $this->redis->ttl($key);
|
||||
$content = $this->redis->get($key);
|
||||
if (empty($content) && $ttl < $lifetime * 0.5) {
|
||||
$this->redis->del($key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找待清理会话
|
||||
*
|
||||
* @param int $limit
|
||||
* @return array
|
||||
*/
|
||||
protected function querySessionKeys($limit)
|
||||
{
|
||||
return $this->cache->queryKeys('_PHCR', $limit);
|
||||
}
|
||||
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Tasks;
|
||||
|
||||
use App\Caches\CommentCounter as CommentCounterCache;
|
||||
use App\Library\Cache\Backend\Redis as RedisCache;
|
||||
use App\Repos\Comment as CommentRepo;
|
||||
use App\Services\Syncer\CommentCounter as CommentCounterSyncer;
|
||||
|
||||
class SyncCommentCounterTask extends Task
|
||||
{
|
||||
|
||||
/**
|
||||
* @var RedisCache
|
||||
*/
|
||||
protected $cache;
|
||||
|
||||
/**
|
||||
* @var \Redis
|
||||
*/
|
||||
protected $redis;
|
||||
|
||||
public function mainAction()
|
||||
{
|
||||
$this->cache = $this->getDI()->get('cache');
|
||||
|
||||
$this->redis = $this->cache->getRedis();
|
||||
|
||||
$this->rebuild();
|
||||
}
|
||||
|
||||
protected function rebuild()
|
||||
{
|
||||
$key = $this->getCacheKey();
|
||||
|
||||
$commentIds = $this->redis->sRandMember($key, 500);
|
||||
|
||||
if (!$commentIds) return;
|
||||
|
||||
$commentRepo = new CommentRepo();
|
||||
|
||||
$comments = $commentRepo->findByIds($commentIds);
|
||||
|
||||
if ($comments->count() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$counterCache = new CommentCounterCache();
|
||||
|
||||
$allowRecount = $this->allowRecount();
|
||||
|
||||
foreach ($comments as $comment) {
|
||||
|
||||
if ($allowRecount) {
|
||||
|
||||
$comment->reply_count = $commentRepo->countReplies($comment->id);
|
||||
$comment->like_count = $commentRepo->countLikes($comment->id);
|
||||
$comment->update();
|
||||
|
||||
$counterCache->rebuild($comment->id);
|
||||
|
||||
} else {
|
||||
|
||||
$counter = $counterCache->get($comment->id);
|
||||
|
||||
if ($counter) {
|
||||
$comment->reply_count = $counter['reply_count'];
|
||||
$comment->like_count = $counter['like_count'];
|
||||
$comment->update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->redis->sRem($key, ...$commentIds);
|
||||
}
|
||||
|
||||
protected function getCacheKey()
|
||||
{
|
||||
$syncer = new CommentCounterSyncer();
|
||||
|
||||
return $syncer->getSyncKey();
|
||||
}
|
||||
|
||||
protected function allowRecount()
|
||||
{
|
||||
return date('H') % 4 == 0;
|
||||
}
|
||||
|
||||
}
|
@ -1,121 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Controllers;
|
||||
|
||||
use App\Http\Admin\Services\Comment as CommentService;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/admin/comment")
|
||||
*/
|
||||
class CommentController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Get("/search", name="admin.comment.search")
|
||||
*/
|
||||
public function searchAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/list", name="admin.comment.list")
|
||||
*/
|
||||
public function listAction()
|
||||
{
|
||||
$courseId = $this->request->getQuery('course_id', 'int', 0);
|
||||
$chapterId = $this->request->getQuery('chapter_id', 'int', 0);
|
||||
|
||||
$commentService = new CommentService();
|
||||
|
||||
$pager = $commentService->getComments();
|
||||
|
||||
$chapter = null;
|
||||
|
||||
if ($chapterId > 0) {
|
||||
$chapter = $commentService->getChapter($chapterId);
|
||||
$courseId = $chapter->course_id;
|
||||
}
|
||||
|
||||
$course = null;
|
||||
|
||||
if ($courseId > 0) {
|
||||
$course = $commentService->getCourse($courseId);
|
||||
}
|
||||
|
||||
$this->view->setVar('pager', $pager);
|
||||
$this->view->setVar('course', $course);
|
||||
$this->view->setVar('chapter', $chapter);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id:[0-9]+}/edit", name="admin.comment.edit")
|
||||
*/
|
||||
public function editAction($id)
|
||||
{
|
||||
$commentService = new CommentService();
|
||||
|
||||
$comment = $commentService->getComment($id);
|
||||
|
||||
$this->view->setVar('comment', $comment);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id:[0-9]+}/update", name="admin.comment.update")
|
||||
*/
|
||||
public function updateAction($id)
|
||||
{
|
||||
$commentService = new CommentService();
|
||||
|
||||
$commentService->update($id);
|
||||
|
||||
$location = $this->request->getHTTPReferer();
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '更新评论成功',
|
||||
];
|
||||
|
||||
return $this->jsonSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id:[0-9]+}/delete", name="admin.comment.delete")
|
||||
*/
|
||||
public function deleteAction($id)
|
||||
{
|
||||
$commentService = new CommentService();
|
||||
|
||||
$commentService->deleteComment($id);
|
||||
|
||||
$location = $this->request->getHTTPReferer();
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '删除评论成功',
|
||||
];
|
||||
|
||||
return $this->jsonSuccess($content);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @Post("/{id:[0-9]+}/restore", name="admin.comment.restore")
|
||||
*/
|
||||
public function restoreAction($id)
|
||||
{
|
||||
$commentService = new CommentService();
|
||||
|
||||
$commentService->restoreComment($id);
|
||||
|
||||
$location = $this->request->getHTTPReferer();
|
||||
|
||||
$content = [
|
||||
'location' => $location,
|
||||
'msg' => '还原评论成功',
|
||||
];
|
||||
|
||||
return $this->jsonSuccess($content);
|
||||
}
|
||||
|
||||
}
|
@ -325,37 +325,6 @@ class AuthNode extends Service
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'id' => '2-4',
|
||||
'title' => '评论管理',
|
||||
'type' => 'menu',
|
||||
'children' => [
|
||||
[
|
||||
'id' => '2-4-1',
|
||||
'title' => '评论列表',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.comment.list',
|
||||
],
|
||||
[
|
||||
'id' => '2-4-2',
|
||||
'title' => '搜索评论',
|
||||
'type' => 'menu',
|
||||
'route' => 'admin.comment.search',
|
||||
],
|
||||
[
|
||||
'id' => '2-4-3',
|
||||
'title' => '编辑评论',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.comment.edit',
|
||||
],
|
||||
[
|
||||
'id' => '2-4-4',
|
||||
'title' => '删除评论',
|
||||
'type' => 'button',
|
||||
'route' => 'admin.comment.delete',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'id' => '2-5',
|
||||
'title' => '轮播管理',
|
||||
|
@ -36,7 +36,7 @@ class Category extends Service
|
||||
|
||||
return $categoryRepo->findAll([
|
||||
'parent_id' => 0,
|
||||
'deleted' => 0,
|
||||
'published' => 1,
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -1,151 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Builders\CommentList as CommentListBuilder;
|
||||
use App\Library\Paginator\Query as PagerQuery;
|
||||
use App\Repos\Chapter as ChapterRepo;
|
||||
use App\Repos\Comment as CommentRepo;
|
||||
use App\Repos\Course as CourseRepo;
|
||||
use App\Validators\Comment as CommentValidator;
|
||||
|
||||
class Comment extends Service
|
||||
{
|
||||
|
||||
public function getComments()
|
||||
{
|
||||
$pagerQuery = new PagerQuery();
|
||||
|
||||
$params = $pagerQuery->getParams();
|
||||
|
||||
$params['deleted'] = $params['deleted'] ?? 0;
|
||||
|
||||
$sort = $pagerQuery->getSort();
|
||||
$page = $pagerQuery->getPage();
|
||||
$limit = $pagerQuery->getLimit();
|
||||
|
||||
$commentRepo = new CommentRepo();
|
||||
|
||||
$pager = $commentRepo->paginate($params, $sort, $page, $limit);
|
||||
|
||||
return $this->handleComments($pager);
|
||||
}
|
||||
|
||||
public function getCourse($courseId)
|
||||
{
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
return $courseRepo->findById($courseId);
|
||||
}
|
||||
|
||||
public function getChapter($chapterId)
|
||||
{
|
||||
$chapterRepo = new ChapterRepo();
|
||||
|
||||
return $chapterRepo->findById($chapterId);
|
||||
}
|
||||
|
||||
public function getComment($id)
|
||||
{
|
||||
return $this->findOrFail($id);
|
||||
}
|
||||
|
||||
public function updateComment($id)
|
||||
{
|
||||
$comment = $this->findOrFail($id);
|
||||
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$validator = new CommentValidator();
|
||||
|
||||
$data = [];
|
||||
|
||||
if (isset($post['content'])) {
|
||||
$data['content'] = $validator->checkContent($post['content']);
|
||||
}
|
||||
|
||||
if (isset($post['published'])) {
|
||||
$data['published'] = $validator->checkPublishStatus($post['published']);
|
||||
}
|
||||
|
||||
$comment->update($data);
|
||||
|
||||
return $comment;
|
||||
}
|
||||
|
||||
public function deleteComment($id)
|
||||
{
|
||||
$comment = $this->findOrFail($id);
|
||||
|
||||
$comment->deleted = 1;
|
||||
|
||||
$comment->update();
|
||||
|
||||
$chapterRepo = new ChapterRepo();
|
||||
|
||||
$chapter = $chapterRepo->findById($comment->chapter_id);
|
||||
|
||||
$chapter->comment_count -= 1;
|
||||
|
||||
$chapter->update();
|
||||
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$course = $courseRepo->findById($comment->course_id);
|
||||
|
||||
$course->comment_count -= 1;
|
||||
|
||||
$course->update();
|
||||
}
|
||||
|
||||
public function restoreComment($id)
|
||||
{
|
||||
$comment = $this->findOrFail($id);
|
||||
|
||||
$comment->deleted = 0;
|
||||
|
||||
$comment->update();
|
||||
|
||||
$chapterRepo = new ChapterRepo();
|
||||
|
||||
$chapter = $chapterRepo->findById($comment->chapter_id);
|
||||
|
||||
$chapter->comment_count += 1;
|
||||
|
||||
$chapter->update();
|
||||
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$course = $courseRepo->findById($comment->course_id);
|
||||
|
||||
$course->comment_count += 1;
|
||||
|
||||
$course->update();
|
||||
}
|
||||
|
||||
private function findOrFail($id)
|
||||
{
|
||||
$validator = new CommentValidator();
|
||||
|
||||
return $validator->checkComment($id);
|
||||
}
|
||||
|
||||
private function handleComments($pager)
|
||||
{
|
||||
if ($pager->total_items > 0) {
|
||||
|
||||
$builder = new CommentListBuilder();
|
||||
|
||||
$pipeA = $pager->items->toArray();
|
||||
$pipeB = $builder->handleCourses($pipeA);
|
||||
$pipeC = $builder->handleChapters($pipeB);
|
||||
$pipeD = $builder->handleUsers($pipeC);
|
||||
$pipeE = $builder->objects($pipeD);
|
||||
|
||||
$pager->items = $pipeE;
|
||||
}
|
||||
|
||||
return $pager;
|
||||
}
|
||||
|
||||
}
|
@ -35,19 +35,17 @@ class Nav extends Service
|
||||
return $navRepo->findAll([
|
||||
'parent_id' => 0,
|
||||
'position' => 'top',
|
||||
'deleted' => 0,
|
||||
'published' => 1,
|
||||
]);
|
||||
}
|
||||
|
||||
public function getChildNavs($parentId)
|
||||
{
|
||||
$deleted = $this->request->getQuery('deleted', 'int', 0);
|
||||
|
||||
$navRepo = new NavRepo();
|
||||
|
||||
return $navRepo->findAll([
|
||||
'parent_id' => $parentId,
|
||||
'deleted' => $deleted,
|
||||
'published' => 1,
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -1,30 +0,0 @@
|
||||
<fieldset class="layui-elem-field layui-field-title">
|
||||
<legend>编辑评论</legend>
|
||||
</fieldset>
|
||||
|
||||
<form class="layui-form" method="POST" action="{{ url({'for':'admin.comment.update','id':comment.id}) }}">
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">内容</label>
|
||||
<div class="layui-input-block">
|
||||
<textarea name="content" lay-verify="required" class="layui-textarea">{{ comment.content }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">开启</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="published" value="1" title="是" {% if comment.published == 1 %}checked="true"{% endif %}>
|
||||
<input type="radio" name="published" value="0" title="否" {% if comment.published == 0 %}checked="true"{% endif %}>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"></label>
|
||||
<div class="layui-input-block">
|
||||
<button class="layui-btn" lay-submit lay-filter="go">提交</button>
|
||||
<button type="reset" class="kg-back layui-btn layui-btn-primary">返回</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
@ -1,73 +0,0 @@
|
||||
<div class="kg-nav">
|
||||
<div class="kg-nav-left">
|
||||
<span class="layui-breadcrumb">
|
||||
<a class="kg-back"><i class="layui-icon layui-icon-return"></i> 返回</a>
|
||||
{% if course %}
|
||||
<a><cite>{{ course.title }}</cite></a>
|
||||
{% endif %}
|
||||
{% if chapter %}
|
||||
<a><cite>{{ chapter.title }}</cite></a>
|
||||
{% endif %}
|
||||
<a><cite>评论管理</cite></a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="kg-nav-right">
|
||||
<a class="layui-btn layui-btn-sm" href="{{ url({'for':'admin.comment.search'}) }}">
|
||||
<i class="layui-icon layui-icon-search"></i>搜索评论
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="kg-table layui-table layui-form">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col width="10%">
|
||||
<col width="10%">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>评论</th>
|
||||
<th>用户</th>
|
||||
<th>时间</th>
|
||||
<th>发布</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in pager.items %}
|
||||
<tr>
|
||||
<td>
|
||||
<p>课程:<a href="{{ url({'for':'admin.comment.list'},{'course_id':item.course.id}) }}">{{ item.course.title }}</a></p>
|
||||
{% if item.chapter %}
|
||||
<p>章节:<a href="{{ url({'for':'admin.comment.list'},{'chapter_id':item.chapter.id}) }}">{{ item.chapter.title }}</a></p>
|
||||
{% endif %}
|
||||
<p>评论:<a href="javascript:" title="{{ item.content }}">{{ substr(item.content,0,30) }}</a></p>
|
||||
</td>
|
||||
<td>
|
||||
<p>昵称:{{ item.user.name }}</p>
|
||||
<p>编号:{{ item.user.id }}</p>
|
||||
</td>
|
||||
<td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>
|
||||
<td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ url({'for':'admin.comment.update','id':item.id}) }}" {% if item.published == 1 %}checked{% endif %}></td>
|
||||
<td align="center">
|
||||
<div class="layui-dropdown">
|
||||
<button class="layui-btn layui-btn-sm">操作 <span class="layui-icon layui-icon-triangle-d"></span>
|
||||
</button>
|
||||
<ul>
|
||||
<li><a href="{{ url({'for':'admin.comment.edit','id':item.id}) }}">编辑</a></li>
|
||||
{% if item.deleted == 0 %}
|
||||
<li><a href="javascript:" class="kg-delete" data-url="{{ url({'for':'admin.comment.delete','id':item.id}) }}">删除</a></li>
|
||||
{% else %}
|
||||
<li><a href="javascript:" class="kg-restore" data-url="{{ url({'for':'admin.comment.restore','id':item.id}) }}">还原</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{{ partial('partials/pager') }}
|
@ -1,67 +0,0 @@
|
||||
<fieldset class="layui-elem-field layui-field-title">
|
||||
<legend>搜索评论</legend>
|
||||
</fieldset>
|
||||
|
||||
<form class="layui-form" method="GET" action="{{ url({'for':'admin.comment.list'}) }}">
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">评论编号</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="id" placeholder="评论编号精确匹配">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">课程编号</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="course_id" placeholder="课程编号精确匹配">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">章节编号</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="chapter_id" placeholder="章节编号精确匹配">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">用户编号</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="author_id" placeholder="用户编号精确匹配">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">发布</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="published" value="1" title="是">
|
||||
<input type="radio" name="published" value="0" title="否">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">删除</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="deleted" value="1" title="是">
|
||||
<input type="radio" name="deleted" value="0" title="否">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"></label>
|
||||
<div class="layui-input-block">
|
||||
<button class="layui-btn" lay-submit>提交</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
<script>
|
||||
|
||||
layui.use('form', function () {
|
||||
var form = layui.form;
|
||||
});
|
||||
|
||||
</script>
|
@ -1,81 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Web\Controllers;
|
||||
|
||||
use App\Services\Frontend\Comment\CommentCreate as CommentCreateService;
|
||||
use App\Services\Frontend\Comment\CommentDelete as CommentDeleteService;
|
||||
use App\Services\Frontend\Comment\CommentInfo as CommentInfoService;
|
||||
use App\Services\Frontend\Comment\CommentLike as CommentLikeService;
|
||||
use App\Services\Frontend\Comment\CommentUpdate as CommentUpdateService;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/comment")
|
||||
*/
|
||||
class CommentController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Get("/{id:[0-9]+}/info", name="web.comment.info")
|
||||
*/
|
||||
public function infoAction($id)
|
||||
{
|
||||
$service = new CommentInfoService();
|
||||
|
||||
$comment = $service->handle($id);
|
||||
|
||||
return $this->jsonSuccess(['comment' => $comment]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/create", name="web.comment.create")
|
||||
*/
|
||||
public function createAction()
|
||||
{
|
||||
$service = new CommentCreateService();
|
||||
|
||||
$comment = $service->handle();
|
||||
|
||||
$service = new CommentInfoService();
|
||||
|
||||
$comment = $service->handle($comment->id);
|
||||
|
||||
return $this->jsonSuccess(['comment' => $comment]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id:[0-9]+}/update", name="web.comment.update")
|
||||
*/
|
||||
public function updateAction($id)
|
||||
{
|
||||
$service = new CommentUpdateService();
|
||||
|
||||
$comment = $service->handle($id);
|
||||
|
||||
return $this->jsonSuccess(['comment' => $comment]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id:[0-9]+}/delete", name="web.comment.delete")
|
||||
*/
|
||||
public function deleteAction($id)
|
||||
{
|
||||
$service = new CommentDeleteService();
|
||||
|
||||
$service->handle($id);
|
||||
|
||||
return $this->jsonSuccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id:[0-9]+}/like", name="web.comment.like")
|
||||
*/
|
||||
public function likeAction($id)
|
||||
{
|
||||
$service = new CommentLikeService();
|
||||
|
||||
$service->handle($id);
|
||||
|
||||
return $this->jsonSuccess();
|
||||
}
|
||||
|
||||
}
|
@ -14,6 +14,16 @@ use App\Services\Frontend\Consult\ConsultUpdate as ConsultUpdateService;
|
||||
class ConsultController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Get("/add", name="web.consult.add")
|
||||
*/
|
||||
public function addAction()
|
||||
{
|
||||
$chapterId = $this->request->getQuery('chapter_id');
|
||||
|
||||
$this->view->setVar('chapter_id', $chapterId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id:[0-9]+}/info", name="web.consult.info")
|
||||
*/
|
||||
@ -39,7 +49,12 @@ class ConsultController extends Controller
|
||||
|
||||
$consult = $service->handle($consult->id);
|
||||
|
||||
return $this->jsonSuccess(['consult' => $consult]);
|
||||
$content = [
|
||||
'consult' => $consult,
|
||||
'msg' => '提交课程咨询成功',
|
||||
];
|
||||
|
||||
return $this->jsonSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -51,7 +66,12 @@ class ConsultController extends Controller
|
||||
|
||||
$consult = $service->handle($id);
|
||||
|
||||
return $this->jsonSuccess(['consult' => $consult]);
|
||||
$content = [
|
||||
'consult' => $consult,
|
||||
'msg' => '更新课程咨询成功',
|
||||
];
|
||||
|
||||
return $this->jsonSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -63,7 +83,9 @@ class ConsultController extends Controller
|
||||
|
||||
$service->handle($id);
|
||||
|
||||
return $this->jsonSuccess();
|
||||
$content = ['msg' => '删除课程咨询成功'];
|
||||
|
||||
return $this->jsonSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5,7 +5,6 @@ namespace App\Http\Web\Controllers;
|
||||
use App\Http\Web\Services\CourseQuery as CourseQueryService;
|
||||
use App\Services\Frontend\Course\ChapterList as CourseChapterListService;
|
||||
use App\Services\Frontend\Course\ConsultList as CourseConsultListService;
|
||||
use App\Services\Frontend\Course\CourseBasic as CourseBasicService;
|
||||
use App\Services\Frontend\Course\CourseInfo as CourseInfoService;
|
||||
use App\Services\Frontend\Course\CourseList as CourseListService;
|
||||
use App\Services\Frontend\Course\Favorite as CourseFavoriteService;
|
||||
@ -59,7 +58,7 @@ class CourseController extends Controller
|
||||
$pager->target = 'course-list';
|
||||
|
||||
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
|
||||
$this->view->pick('course/ajax_pager');
|
||||
$this->view->pick('course/pager');
|
||||
$this->view->setVar('pager', $pager);
|
||||
}
|
||||
|
||||
@ -98,7 +97,7 @@ class CourseController extends Controller
|
||||
$teachers = $service->handle($id);
|
||||
|
||||
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
|
||||
$this->view->pick('course/ajax_teachers');
|
||||
$this->view->pick('course/teachers');
|
||||
$this->view->setVar('teachers', $teachers);
|
||||
}
|
||||
|
||||
@ -112,7 +111,7 @@ class CourseController extends Controller
|
||||
$chapters = $service->handle($id);
|
||||
|
||||
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
|
||||
$this->view->pick('course/ajax_chapters');
|
||||
$this->view->pick('course/chapters');
|
||||
$this->view->setVar('chapters', $chapters);
|
||||
}
|
||||
|
||||
@ -126,7 +125,7 @@ class CourseController extends Controller
|
||||
$packages = $service->handle($id);
|
||||
|
||||
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
|
||||
$this->view->pick('course/ajax_packages');
|
||||
$this->view->pick('course/packages');
|
||||
$this->view->setVar('packages', $packages);
|
||||
}
|
||||
|
||||
@ -142,7 +141,7 @@ class CourseController extends Controller
|
||||
$pager->target = 'tab-consults';
|
||||
|
||||
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
|
||||
$this->view->pick('course/ajax_consults');
|
||||
$this->view->pick('course/consults');
|
||||
$this->view->setVar('pager', $pager);
|
||||
}
|
||||
|
||||
@ -158,7 +157,7 @@ class CourseController extends Controller
|
||||
$pager->target = 'tab-reviews';
|
||||
|
||||
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
|
||||
$this->view->pick('course/ajax_reviews');
|
||||
$this->view->pick('course/reviews');
|
||||
$this->view->setVar('pager', $pager);
|
||||
}
|
||||
|
||||
@ -172,7 +171,7 @@ class CourseController extends Controller
|
||||
$courses = $service->handle($id);
|
||||
|
||||
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
|
||||
$this->view->pick('course/ajax_recommended');
|
||||
$this->view->pick('course/recommended');
|
||||
$this->view->setVar('courses', $courses);
|
||||
}
|
||||
|
||||
@ -186,7 +185,7 @@ class CourseController extends Controller
|
||||
$courses = $service->handle($id);
|
||||
|
||||
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
|
||||
$this->view->pick('course/ajax_related');
|
||||
$this->view->pick('course/related');
|
||||
$this->view->setVar('courses', $courses);
|
||||
}
|
||||
|
||||
@ -200,23 +199,10 @@ class CourseController extends Controller
|
||||
$topics = $service->handle($id);
|
||||
|
||||
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
|
||||
$this->view->pick('course/ajax_topics');
|
||||
$this->view->pick('course/topics');
|
||||
$this->view->setVar('topics', $topics);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id:[0-9]+}/rating", name="web.course.rating")
|
||||
*/
|
||||
public function ratingAction($id)
|
||||
{
|
||||
$service = new CourseBasicService();
|
||||
|
||||
$course = $service->handle($id);
|
||||
|
||||
$this->view->pick('course/rating');
|
||||
$this->view->setVar('course', $course);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/{id:[0-9]+}/favorite", name="web.course.favorite")
|
||||
*/
|
||||
|
@ -14,6 +14,16 @@ use App\Services\Frontend\Review\ReviewUpdate as ReviewUpdateService;
|
||||
class ReviewController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Get("/add", name="web.review.add")
|
||||
*/
|
||||
public function addAction()
|
||||
{
|
||||
$courseId = $this->request->getQuery('course_id');
|
||||
|
||||
$this->view->setVar('course_id', $courseId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id:[0-9]+}/info", name="web.review.info")
|
||||
*/
|
||||
@ -73,7 +83,9 @@ class ReviewController extends Controller
|
||||
|
||||
$service->handle($id);
|
||||
|
||||
return $this->jsonSuccess();
|
||||
$content = ['msg' => '删除课程评价成功'];
|
||||
|
||||
return $this->jsonSuccess($content);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -31,7 +31,7 @@ class TeacherController extends Controller
|
||||
$pager->target = 'teacher-list';
|
||||
|
||||
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
|
||||
$this->view->pick('teacher/ajax_pager');
|
||||
$this->view->pick('teacher/pager');
|
||||
$this->view->setVar('pager', $pager);
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ class UserController extends Controller
|
||||
$pager->target = 'tab-courses';
|
||||
|
||||
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
|
||||
$this->view->pick('user/ajax_courses');
|
||||
$this->view->pick('user/courses');
|
||||
$this->view->setVar('pager', $pager);
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@ class UserController extends Controller
|
||||
$pager->target = 'tab-favorites';
|
||||
|
||||
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
|
||||
$this->view->pick('user/ajax_favorites');
|
||||
$this->view->pick('user/favorites');
|
||||
$this->view->setVar('pager', $pager);
|
||||
}
|
||||
|
||||
@ -70,7 +70,7 @@ class UserController extends Controller
|
||||
$pager->target = 'tab-friends';
|
||||
|
||||
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
|
||||
$this->view->pick('user/ajax_friends');
|
||||
$this->view->pick('user/friends');
|
||||
$this->view->setVar('pager', $pager);
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
{% set danmu_url = url({'for':'web.chapter.danmu','id':chapter.id}) %}
|
||||
{% set like_url = url({'for':'web.chapter.like','id':chapter.id}) %}
|
||||
{% set qrcode_url = url({'for':'web.qrcode_img'},{'text':chapter_full_url}) %}
|
||||
{% set consult_url = url({'for':'web.consult.add'},{'chapter_id':chapter.id}) %}
|
||||
|
||||
<div class="breadcrumb">
|
||||
<span class="layui-breadcrumb">
|
||||
@ -14,9 +15,10 @@
|
||||
<a><cite>{{ chapter.title }}</cite></a>
|
||||
</span>
|
||||
<span class="share">
|
||||
<a href="javascript:" title="点赞" data-url="{{ like_url }}"><i class="layui-icon layui-icon-praise icon-praise"></i><em class="like-count">{{ chapter.like_count }}</em></a>
|
||||
<a href="javascript:" title="学习人次"><i class="layui-icon layui-icon-user"></i><em>{{ chapter.user_count }}</em></a>
|
||||
<a href="javascript:" title="分享到微信" data-url=""><i class="layui-icon layui-icon-login-wechat icon-wechat"></i></a>
|
||||
<a href="javascript:" title="我要点赞" data-url="{{ like_url }}"><i class="layui-icon layui-icon-praise icon-praise"></i><em class="like-count">{{ chapter.like_count }}</em></a>
|
||||
<a href="javascript:" title="我要提问" data-url="{{ consult_url }}"><i class="layui-icon layui-icon-help icon-help"></i></a>
|
||||
<a href="javascript:" title="分享到微信"><i class="layui-icon layui-icon-login-wechat icon-wechat"></i></a>
|
||||
<a href="javascript:" title="分享到QQ空间"><i class="layui-icon layui-icon-login-qq icon-qq"></i></a>
|
||||
<a href="javascript:" title="分享到微博"><i class="layui-icon layui-icon-login-weibo icon-weibo"></i></a>
|
||||
</span>
|
||||
@ -115,6 +117,7 @@
|
||||
{{ js_include('lib/jquery.danmu.min.js') }}
|
||||
{{ js_include('web/js/course.share.js') }}
|
||||
{{ js_include('web/js/chapter.like.js') }}
|
||||
{{ js_include('web/js/chapter.vod.js') }}
|
||||
{{ js_include('web/js/chapter.vod.player.js') }}
|
||||
|
||||
{% endblock %}
|
27
app/Http/Web/Views/consult/add.volt
Normal file
27
app/Http/Web/Views/consult/add.volt
Normal file
@ -0,0 +1,27 @@
|
||||
{% extends 'templates/layer.volt' %}
|
||||
|
||||
{% block content %}
|
||||
<form class="layui-form" method="post" action="{{ url({'for':'web.consult.create'}) }}">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">咨询内容</label>
|
||||
<div class="layui-input-block">
|
||||
<textarea name="question" class="layui-textarea" placeholder="请详细描述问题,我们会尽快回复您"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">私密问题</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="private" value="1" title="是">
|
||||
<input type="radio" name="private" value="0" title="否" checked="checked">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"></label>
|
||||
<div class="layui-input-block">
|
||||
<button class="layui-btn" lay-submit="true" lay-filter="go">提交</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
|
||||
<input type="hidden" name="chapter_id" value="{{ chapter_id }}">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
@ -1,7 +1,7 @@
|
||||
{%- macro vod_lesson_info(lesson) %}
|
||||
{% set url = lesson.me.owned ? url({'for':'web.chapter.show','id':lesson.id}) : 'javascript:' %}
|
||||
{% set url = lesson.me.owned ? url({'for':'web.chapter.show','id':lesson.id}) : '' %}
|
||||
{% set priv = lesson.me.owned ? 'allow' : 'deny' %}
|
||||
<a class="{{ priv }}" href="{{ url }}">
|
||||
<a class="{{ priv }} view-lesson" href="javascript:" data-url="{{ url }}">
|
||||
<i class="layui-icon layui-icon-play"></i>
|
||||
<span class="title">{{ lesson.title }}</span>
|
||||
{% if lesson.free == 1 %}
|
||||
@ -15,10 +15,10 @@
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro live_lesson_info(lesson) %}
|
||||
{% set url = lesson.me.owned ? url({'for':'web.chapter.show','id':lesson.id}) : 'javascript:' %}
|
||||
{% set url = lesson.me.owned ? url({'for':'web.chapter.show','id':lesson.id}) : '' %}
|
||||
{% set priv = lesson.me.owned ? 'allow' : 'deny' %}
|
||||
{% set over_flag = lesson.attrs.end_time < time() ? '已结束' : '' %}
|
||||
<a class="{{ priv }}" href="{{ url }}">
|
||||
<a class="{{ priv }} view-lesson" href="javascript:" data-url="{{ url }}">
|
||||
<i class="layui-icon layui-icon-video"></i>
|
||||
<span class="title">{{ lesson.title }}</span>
|
||||
{% if lesson.free == 1 %}
|
||||
@ -32,9 +32,9 @@
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro read_lesson_info(lesson) %}
|
||||
{% set url = lesson.me.owned ? url({'for':'web.chapter.show','id':lesson.id}) : 'javascript:' %}
|
||||
{% set url = lesson.me.owned ? url({'for':'web.chapter.show','id':lesson.id}) : '' %}
|
||||
{% set priv = lesson.me.owned ? 'allow' : 'deny' %}
|
||||
<a class="{{ priv }}" href="{{ url }}">
|
||||
<a class="{{ priv }} view-lesson" href="javascript:" data-url="{{ url }}">
|
||||
<i class="layui-icon layui-icon-read"></i>
|
||||
<span class="title">{{ lesson.title|e }}</span>
|
||||
{% if lesson.free == 1 %}
|
@ -13,7 +13,7 @@
|
||||
<div class="title">{{ item.question }}</div>
|
||||
<div class="content">{{ item.answer }}</div>
|
||||
<div class="footer">
|
||||
<span class="time">{{ time_ago('Y-m-d',item.create_time) }}</span>
|
||||
<span class="time">{{ item.create_time|time_ago }}</span>
|
||||
<a href="javascript:" class="like" title="点赞" data-url="{{ like_url }}">
|
||||
<i class="layui-icon layui-icon-praise icon-praise"></i>
|
||||
<em class="like-count">{{ item.like_count }}</em>
|
@ -15,7 +15,7 @@
|
||||
<span>会员价 <i>{{ '¥%0.2f'|format(package.vip_price) }}</i></span>
|
||||
</div>
|
||||
<div class="order">
|
||||
<a class="layui-btn layui-btn-sm layui-bg-red" href="{{ order_url }}">立即购买</a>
|
||||
<a class="layui-btn layui-btn-sm layui-bg-red btn-buy" href="javascript:" data-url="{{ order_url }}">立即购买</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="package-course-list">
|
@ -4,6 +4,11 @@
|
||||
|
||||
{{ partial('partials/macro_course') }}
|
||||
|
||||
{% set favorite_star_class = course.me.favorited ? 'layui-icon-star-fill' : 'layui-icon-star' %}
|
||||
{% set full_course_url = full_url({'for':'web.course.show','id':course.id}) %}
|
||||
{% set favorite_url = url({'for':'web.course.favorite','id':course.id}) %}
|
||||
{% set qrcode_url = url({'for':'web.qrcode_img'},{'text':full_course_url}) %}
|
||||
|
||||
<div class="breadcrumb">
|
||||
<span class="layui-breadcrumb">
|
||||
<a href="{{ url({'for':'web.course.list'}) }}">全部课程</a>
|
||||
@ -12,11 +17,15 @@
|
||||
{% endfor %}
|
||||
<a><cite>{{ course.title }}</cite></a>
|
||||
</span>
|
||||
<div class="share">
|
||||
<a href="javascript:" title="收藏" data-url="{{ favorite_url }}"><i class="layui-icon {{ favorite_star_class }} icon-star"></i></a>
|
||||
<a href="javascript:" title="分享到微信" data-url="{{ qrcode_url }}"><i class="layui-icon layui-icon-login-wechat icon-wechat"></i></a>
|
||||
<a href="javascript:" title="分享到QQ空间"><i class="layui-icon layui-icon-login-qq icon-qq"></i></a>
|
||||
<a href="javascript:" title="分享到微博"><i class="layui-icon layui-icon-login-weibo icon-weibo"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="course-meta wrap clearfix">
|
||||
{{ partial('course/show_meta') }}
|
||||
</div>
|
||||
{{ partial('course/show_meta') }}
|
||||
|
||||
<div class="layout-main clearfix">
|
||||
|
||||
@ -95,6 +104,13 @@
|
||||
|
||||
</div>
|
||||
|
||||
<div class="layui-hide">
|
||||
<input type="hidden" name="share.title" value="{{ course.title }}">
|
||||
<input type="hidden" name="share.pic" value="{{ course.cover }}">
|
||||
<input type="hidden" name="share.url" value="{{ full_course_url }}">
|
||||
<input type="hidden" name="share.qrcode" value="{{ qrcode_url }}">
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block include_js %}
|
||||
|
@ -1,53 +1,52 @@
|
||||
<div class="cover">
|
||||
<img src="{{ course.cover }}" alt="{{ course.title|e }}">
|
||||
</div>
|
||||
|
||||
<div class="info">
|
||||
{% if course.model == 'vod' %}
|
||||
<p>课程时长 <span>{{ course.attrs.duration|total_duration }}</span></p>
|
||||
{% elseif course.model == 'live' %}
|
||||
<p>直播时间 <span>{{ course.attrs.start_date }} ~ {{ course.attrs.end_date }}</span></p>
|
||||
{% endif %}
|
||||
{% if course.market_price > 0 %}
|
||||
<p>
|
||||
学习期限 <span class="expiry">{{ course.study_expiry }}个月</span>
|
||||
退款期限 <span class="expiry">{{ course.refund_expiry }}天</span>
|
||||
</p>
|
||||
{% endif %}
|
||||
<p>
|
||||
{% if course.market_price > 0 %}
|
||||
市场价格 <span class="price">{{ '¥%0.2f'|format(course.market_price) }}</span>
|
||||
{% else %}
|
||||
市场价格 <span class="free">免费</span>
|
||||
{% endif %}
|
||||
{% if course.vip_price > 0 %}
|
||||
会员价格 <span class="price">{{ '¥%0.2f'|format(course.vip_price) }}</span>
|
||||
{% else %}
|
||||
会员价格 <span class="free">免费</span>
|
||||
{% endif %}
|
||||
</p>
|
||||
<p>
|
||||
难度 <span>{{ level_info(course.level) }}</span>
|
||||
课时 <span>{{ course.lesson_count }}</span>
|
||||
学员 <span>{{ course.user_count }}</span>
|
||||
评分 <span>{{ course.rating }}</span>
|
||||
</p>
|
||||
|
||||
{% set favorite_url = url({'for':'web.course.favorite','id':course.id}) %}
|
||||
{% set full_course_url = full_url({'for':'web.course.show','id':course.id}) %}
|
||||
{% set qrcode_url = url({'for':'web.qrcode_img'},{'text':full_course_url}) %}
|
||||
|
||||
<div class="layui-hide">
|
||||
<input type="hidden" name="share.title" value="{{ course.title }}">
|
||||
<input type="hidden" name="share.pic" value="{{ course.cover }}">
|
||||
<input type="hidden" name="share.url" value="{{ full_course_url }}">
|
||||
<input type="hidden" name="share.qrcode" value="{{ qrcode_url }}">
|
||||
<div class="course-meta wrap clearfix">
|
||||
<div class="cover">
|
||||
<img src="{{ course.cover }}" alt="{{ course.title|e }}">
|
||||
</div>
|
||||
|
||||
<div class="share">
|
||||
<a href="javascript:" title="收藏" data-url="{{ favorite_url }}"><i class="layui-icon layui-icon-star icon-star"></i></a>
|
||||
<a href="javascript:" title="分享到微信" data-url="{{ qrcode_url }}"><i class="layui-icon layui-icon-login-wechat icon-wechat"></i></a>
|
||||
<a href="javascript:" title="分享到QQ空间"><i class="layui-icon layui-icon-login-qq icon-qq"></i></a>
|
||||
<a href="javascript:" title="分享到微博"><i class="layui-icon layui-icon-login-weibo icon-weibo"></i></a>
|
||||
<div class="info">
|
||||
{% if course.model == 'vod' %}
|
||||
<p>课程时长 <span>{{ course.attrs.duration|total_duration }}</span></p>
|
||||
{% elseif course.model == 'live' %}
|
||||
<p>直播时间 <span>{{ course.attrs.start_date }} ~ {{ course.attrs.end_date }}</span></p>
|
||||
{% endif %}
|
||||
{% if course.market_price > 0 %}
|
||||
<p>
|
||||
学习期限 <span class="expiry">{{ course.study_expiry }}个月</span>
|
||||
退款期限 <span class="expiry">{{ course.refund_expiry }}天</span>
|
||||
</p>
|
||||
{% endif %}
|
||||
<p>
|
||||
{% if course.market_price > 0 %}
|
||||
市场价格 <span class="price">{{ '¥%0.2f'|format(course.market_price) }}</span>
|
||||
{% else %}
|
||||
市场价格 <span class="free">免费</span>
|
||||
{% endif %}
|
||||
{% if course.vip_price > 0 %}
|
||||
会员价格 <span class="price">{{ '¥%0.2f'|format(course.vip_price) }}</span>
|
||||
{% else %}
|
||||
会员价格 <span class="free">免费</span>
|
||||
{% endif %}
|
||||
</p>
|
||||
<p>
|
||||
难度级别 <span>{{ level_info(course.level) }}</span>
|
||||
学习人次 <span>{{ course.user_count }}</span>
|
||||
综合评分 <span>{{ course.ratings.rating }}</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="rating">
|
||||
<p class="item">
|
||||
<span class="name">内容实用</span>
|
||||
<span class="star">{{ star_info(course.ratings.rating1) }}</span>
|
||||
<span class="score">{{ course.ratings.rating1 }}分</span>
|
||||
</p>
|
||||
<p class="item">
|
||||
<span class="name">简洁易懂</span>
|
||||
<span class="star">{{ star_info(course.ratings.rating2) }}</span>
|
||||
<span class="score">{{ course.ratings.rating2 }}分</span>
|
||||
</p>
|
||||
<p class="item">
|
||||
<span class="name">逻辑清晰</span>
|
||||
<span class="star">{{ star_info(course.ratings.rating3) }}</span>
|
||||
<span class="score">{{ course.ratings.rating3 }}分</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
@ -20,6 +20,13 @@
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro star_info(rating) %}
|
||||
{% set stars = [1,2,3,4,5] %}
|
||||
{% for val in stars if val <= rating %}
|
||||
<i class="layui-icon layui-icon-star-fill"></i>
|
||||
{% endfor %}
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro course_card(course) %}
|
||||
{% set course_url = url({'for':'web.course.show','id':course.id}) %}
|
||||
<div class="course-card">
|
||||
|
@ -30,7 +30,7 @@
|
||||
<label class="layui-form-label"></label>
|
||||
<div class="layui-input-block">
|
||||
<button class="layui-btn" lay-submit="true" lay-filter="go">提交</button>
|
||||
<button type="button" class="layui-btn layui-btn-primary cancel-rating">取消</button>
|
||||
<button type="button" class="layui-btn layui-btn-primary btn-cancel">取消</button>
|
||||
<input type="hidden" name="course_id" value="{{ course.id }}">
|
||||
<input type="hidden" name="rating1" value="5">
|
||||
<input type="hidden" name="rating2" value="5">
|
@ -143,9 +143,10 @@ class Redis extends \Phalcon\Cache\Backend\Redis
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param string $prefix
|
||||
* @param int $limit
|
||||
* @return array
|
||||
*/
|
||||
public function queryKeys($prefix = null): array
|
||||
public function queryKeys($prefix = null, $limit = 1000): array
|
||||
{
|
||||
$result = [];
|
||||
|
||||
@ -158,6 +159,7 @@ class Redis extends \Phalcon\Cache\Backend\Redis
|
||||
$it = null;
|
||||
|
||||
while ($keys = $redis->scan($it, $pattern)) {
|
||||
if (count($result) > $limit) break;
|
||||
$result = array_merge($result, $keys);
|
||||
}
|
||||
|
||||
|
@ -31,16 +31,16 @@ class ChapterCounter extends Listener
|
||||
$this->syncChapterCounter($chapter);
|
||||
}
|
||||
|
||||
public function incrCommentCount(Event $event, $source, ChapterModel $chapter)
|
||||
public function incrConsultCount(Event $event, $source, ChapterModel $chapter)
|
||||
{
|
||||
$this->counter->hIncrBy($chapter->id, 'comment_count');
|
||||
$this->counter->hIncrBy($chapter->id, 'consult_count');
|
||||
|
||||
$this->syncChapterCounter($chapter);
|
||||
}
|
||||
|
||||
public function decrCommentCount(Event $event, $source, ChapterModel $chapter)
|
||||
public function decrConsultCount(Event $event, $source, ChapterModel $chapter)
|
||||
{
|
||||
$this->counter->hDecrBy($chapter->id, 'comment_count');
|
||||
$this->counter->hDecrBy($chapter->id, 'consult_count');
|
||||
|
||||
$this->syncChapterCounter($chapter);
|
||||
}
|
||||
|
@ -1,55 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Listeners;
|
||||
|
||||
use App\Caches\CommentCounter as CacheCommentCounter;
|
||||
use App\Models\Comment as CommentModel;
|
||||
use App\Services\Syncer\CommentCounter as CommentCounterSyncer;
|
||||
use Phalcon\Events\Event;
|
||||
|
||||
class CommentCounter extends Listener
|
||||
{
|
||||
|
||||
protected $counter;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->counter = new CacheCommentCounter();
|
||||
}
|
||||
|
||||
public function incrReplyCount(Event $event, $source, CommentModel $comment)
|
||||
{
|
||||
$this->counter->hIncrBy($comment->id, 'reply_count');
|
||||
|
||||
$this->syncCommentCounter($comment);
|
||||
}
|
||||
|
||||
public function decrReplyCount(Event $event, $source, CommentModel $comment)
|
||||
{
|
||||
$this->counter->hDecrBy($comment->id, 'reply_count');
|
||||
|
||||
$this->syncCommentCounter($comment);
|
||||
}
|
||||
|
||||
public function incrLikeCount(Event $event, $source, CommentModel $comment)
|
||||
{
|
||||
$this->counter->hIncrBy($comment->id, 'like_count');
|
||||
|
||||
$this->syncCommentCounter($comment);
|
||||
}
|
||||
|
||||
public function decrLikeCount(Event $event, $source, CommentModel $comment)
|
||||
{
|
||||
$this->counter->hDecrBy($comment->id, 'like_count');
|
||||
|
||||
$this->syncCommentCounter($comment);
|
||||
}
|
||||
|
||||
protected function syncCommentCounter(CommentModel $comment)
|
||||
{
|
||||
$syncer = new CommentCounterSyncer();
|
||||
|
||||
$syncer->addItem($comment->id);
|
||||
}
|
||||
|
||||
}
|
@ -68,20 +68,6 @@ class CourseCounter extends Listener
|
||||
$this->syncCourseIndex($course);
|
||||
}
|
||||
|
||||
public function incrCommentCount(Event $event, $source, CourseModel $course)
|
||||
{
|
||||
$this->counter->hIncrBy($course->id, 'comment_count');
|
||||
|
||||
$this->syncCourseCounter($course);
|
||||
}
|
||||
|
||||
public function decrCommentCount(Event $event, $source, CourseModel $course)
|
||||
{
|
||||
$this->counter->hDecrBy($course->id, 'comment_count');
|
||||
|
||||
$this->syncCourseCounter($course);
|
||||
}
|
||||
|
||||
public function incrFavoriteCount(Event $event, $source, CourseModel $course)
|
||||
{
|
||||
$this->counter->hIncrBy($course->id, 'favorite_count');
|
||||
|
@ -21,11 +21,6 @@ class UserDailyCounter extends Listener
|
||||
$this->counter->hIncrBy($user->id, 'favorite_count');
|
||||
}
|
||||
|
||||
public function incrCommentCount(Event $event, $source, UserModel $user)
|
||||
{
|
||||
$this->counter->hIncrBy($user->id, 'comment_count');
|
||||
}
|
||||
|
||||
public function incrDanmuCount(Event $event, $source, UserModel $user)
|
||||
{
|
||||
$this->counter->hIncrBy($user->id, 'danmu_count');
|
||||
@ -46,11 +41,6 @@ class UserDailyCounter extends Listener
|
||||
$this->counter->hIncrBy($user->id, 'order_count');
|
||||
}
|
||||
|
||||
public function incrCommentLikeCount(Event $event, $source, UserModel $user)
|
||||
{
|
||||
$this->counter->hIncrBy($user->id, 'comment_like_count');
|
||||
}
|
||||
|
||||
public function incrConsultLikeCount(Event $event, $source, UserModel $user)
|
||||
{
|
||||
$this->counter->hIncrBy($user->id, 'consult_like_count');
|
||||
|
@ -1,132 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Phalcon\Mvc\Model\Behavior\SoftDelete;
|
||||
|
||||
class Comment extends Model
|
||||
{
|
||||
|
||||
/**
|
||||
* 主键编号
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* 父级编号
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $parent_id;
|
||||
|
||||
/**
|
||||
* 课程编号
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $course_id;
|
||||
|
||||
/**
|
||||
* 章节编号
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $chapter_id;
|
||||
|
||||
/**
|
||||
* 用户编号
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $user_id;
|
||||
|
||||
/**
|
||||
* 回复用户
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $to_user_id;
|
||||
|
||||
/**
|
||||
* 内容
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $content;
|
||||
|
||||
/**
|
||||
* 回复数
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $reply_count;
|
||||
|
||||
/**
|
||||
* 点赞数
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $like_count;
|
||||
|
||||
/**
|
||||
* 发布标识
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $published;
|
||||
|
||||
/**
|
||||
* 删除标识
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $deleted;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $create_time;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $update_time;
|
||||
|
||||
public function getSource(): string
|
||||
{
|
||||
return 'kg_comment';
|
||||
}
|
||||
|
||||
public function initialize()
|
||||
{
|
||||
parent::initialize();
|
||||
|
||||
$this->addBehavior(
|
||||
new SoftDelete([
|
||||
'field' => 'deleted',
|
||||
'value' => 1,
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
public function beforeCreate()
|
||||
{
|
||||
$this->create_time = time();
|
||||
}
|
||||
|
||||
public function beforeUpdate()
|
||||
{
|
||||
$this->update_time = time();
|
||||
|
||||
if ($this->deleted == 1) {
|
||||
$this->published = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Phalcon\Mvc\Model\Behavior\SoftDelete;
|
||||
|
||||
class CommentLike extends Model
|
||||
{
|
||||
|
||||
/**
|
||||
* 主键编号
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* 评论编号
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $comment_id;
|
||||
|
||||
/**
|
||||
* 用户编号
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $user_id;
|
||||
|
||||
/**
|
||||
* 删除标识
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $deleted;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $create_time;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $update_time;
|
||||
|
||||
public function getSource(): string
|
||||
{
|
||||
return 'kg_comment_like';
|
||||
}
|
||||
|
||||
public function initialize()
|
||||
{
|
||||
parent::initialize();
|
||||
|
||||
$this->addBehavior(
|
||||
new SoftDelete([
|
||||
'field' => 'deleted',
|
||||
'value' => 1,
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
public function beforeCreate()
|
||||
{
|
||||
$this->create_time = time();
|
||||
}
|
||||
|
||||
public function beforeUpdate()
|
||||
{
|
||||
$this->update_time = time();
|
||||
}
|
||||
|
||||
}
|
@ -7,6 +7,13 @@ use Phalcon\Mvc\Model\Behavior\SoftDelete;
|
||||
class Consult extends Model
|
||||
{
|
||||
|
||||
/**
|
||||
* 优先级
|
||||
*/
|
||||
const PRIORITY_HIGH = 10; // 高
|
||||
const PRIORITY_MIDDLE = 20; // 中
|
||||
const PRIORITY_LOW = 30; // 低
|
||||
|
||||
/**
|
||||
* 主键编号
|
||||
*
|
||||
@ -21,6 +28,13 @@ class Consult extends Model
|
||||
*/
|
||||
public $course_id;
|
||||
|
||||
/**
|
||||
* 章节编号
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $chapter_id;
|
||||
|
||||
/**
|
||||
* 用户编号
|
||||
*
|
||||
|
@ -51,7 +51,14 @@ class ImGroup extends Model
|
||||
public $about;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
* 发布状态
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $published;
|
||||
|
||||
/**
|
||||
* 删除状态
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
@ -109,6 +116,10 @@ class ImGroup extends Model
|
||||
public function beforeUpdate()
|
||||
{
|
||||
$this->update_time = time();
|
||||
|
||||
if ($this->deleted == 1) {
|
||||
$this->published = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public function afterFetch()
|
||||
|
@ -1,111 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repos;
|
||||
|
||||
use App\Library\Paginator\Adapter\QueryBuilder as PagerQueryBuilder;
|
||||
use App\Models\Comment as CommentModel;
|
||||
use App\Models\CommentLike as CommentLikeModel;
|
||||
use Phalcon\Mvc\Model;
|
||||
use Phalcon\Mvc\Model\Resultset;
|
||||
use Phalcon\Mvc\Model\ResultsetInterface;
|
||||
|
||||
class Comment extends Repository
|
||||
{
|
||||
|
||||
public function paginate($where = [], $sort = 'latest', $page = 1, $limit = 15)
|
||||
{
|
||||
$builder = $this->modelsManager->createBuilder();
|
||||
|
||||
$builder->from(CommentModel::class);
|
||||
|
||||
$builder->where('1 = 1');
|
||||
|
||||
if (!empty($where['id'])) {
|
||||
$builder->andWhere('id = :id:', ['id' => $where['id']]);
|
||||
}
|
||||
|
||||
if (!empty($where['parent_id'])) {
|
||||
$builder->andWhere('parent_id = :parent_id:', ['parent_id' => $where['parent_id']]);
|
||||
}
|
||||
|
||||
if (!empty($where['course_id'])) {
|
||||
$builder->andWhere('course_id = :course_id:', ['course_id' => $where['course_id']]);
|
||||
}
|
||||
|
||||
if (!empty($where['chapter_id'])) {
|
||||
$builder->andWhere('chapter_id = :chapter_id:', ['chapter_id' => $where['chapter_id']]);
|
||||
}
|
||||
|
||||
if (!empty($where['user_id'])) {
|
||||
$builder->andWhere('user_id = :user_id:', ['user_id' => $where['user_id']]);
|
||||
}
|
||||
|
||||
if (isset($where['published'])) {
|
||||
$builder->andWhere('published = :published:', ['published' => $where['published']]);
|
||||
}
|
||||
|
||||
if (isset($where['deleted'])) {
|
||||
$builder->andWhere('deleted = :deleted:', ['deleted' => $where['deleted']]);
|
||||
}
|
||||
|
||||
switch ($sort) {
|
||||
default:
|
||||
$orderBy = 'id DESC';
|
||||
break;
|
||||
}
|
||||
|
||||
$builder->orderBy($orderBy);
|
||||
|
||||
$pager = new PagerQueryBuilder([
|
||||
'builder' => $builder,
|
||||
'page' => $page,
|
||||
'limit' => $limit,
|
||||
]);
|
||||
|
||||
return $pager->paginate();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @return CommentModel|Model|bool
|
||||
*/
|
||||
public function findById($id)
|
||||
{
|
||||
return CommentModel::findFirst($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $ids
|
||||
* @param string|array $columns
|
||||
* @return ResultsetInterface|Resultset|CommentModel[]
|
||||
*/
|
||||
public function findByIds($ids, $columns = '*')
|
||||
{
|
||||
return CommentModel::query()
|
||||
->columns($columns)
|
||||
->inWhere('id', $ids)
|
||||
->execute();
|
||||
}
|
||||
|
||||
public function countComments()
|
||||
{
|
||||
return (int)CommentModel::count(['conditions' => 'deleted = 0']);
|
||||
}
|
||||
|
||||
public function countReplies($commentId)
|
||||
{
|
||||
return (int)CommentModel::count([
|
||||
'conditions' => 'parent_id = :parent_id: AND deleted = 0',
|
||||
'bind' => ['parent_id' => $commentId],
|
||||
]);
|
||||
}
|
||||
|
||||
public function countLikes($commentId)
|
||||
{
|
||||
return (int)CommentLikeModel::count([
|
||||
'conditions' => 'comment_id = :comment_id: AND deleted = 0',
|
||||
'bind' => ['comment_id' => $commentId],
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repos;
|
||||
|
||||
use App\Models\CommentLike as CommentLikeModel;
|
||||
use Phalcon\Mvc\Model;
|
||||
|
||||
class CommentLike extends Repository
|
||||
{
|
||||
|
||||
/**
|
||||
* @param int $commentId
|
||||
* @param int $userId
|
||||
* @return CommentLikeModel|Model|bool
|
||||
*/
|
||||
public function findCommentLike($commentId, $userId)
|
||||
{
|
||||
return CommentLikeModel::findFirst([
|
||||
'conditions' => 'comment_id = :comment_id: AND user_id = :user_id:',
|
||||
'bind' => ['comment_id' => $commentId, 'user_id' => $userId],
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Frontend\Comment;
|
||||
|
||||
use App\Models\Chapter as ChapterModel;
|
||||
use App\Models\Comment as CommentModel;
|
||||
use App\Models\Course as CourseModel;
|
||||
use App\Models\User as UserModel;
|
||||
use App\Services\Frontend\ChapterTrait;
|
||||
use App\Services\Frontend\CourseTrait;
|
||||
use App\Services\Frontend\Service as FrontendService;
|
||||
use App\Validators\Comment as CommentValidator;
|
||||
use App\Validators\UserDailyLimit as UserDailyLimitValidator;
|
||||
|
||||
class CommentCreate extends FrontendService
|
||||
{
|
||||
|
||||
use ChapterTrait, CourseTrait;
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$user = $this->getLoginUser();
|
||||
|
||||
$chapter = $this->checkChapter($post['chapter_id']);
|
||||
|
||||
$course = $this->checkCourse($chapter->course_id);
|
||||
|
||||
$validator = new UserDailyLimitValidator();
|
||||
|
||||
$validator->checkCommentLimit($user);
|
||||
|
||||
$validator = new CommentValidator();
|
||||
|
||||
$data = [];
|
||||
|
||||
$data['content'] = $validator->checkContent($post['content']);
|
||||
|
||||
if (isset($post['parent_id'])) {
|
||||
$parent = $validator->checkParent($post['parent_id']);
|
||||
$data['parent_id'] = $parent->id;
|
||||
}
|
||||
|
||||
$comment = new CommentModel();
|
||||
|
||||
$data['course_id'] = $course->id;
|
||||
$data['chapter_id'] = $chapter->id;
|
||||
$data['user_id'] = $user->id;
|
||||
|
||||
$comment->create($data);
|
||||
|
||||
$this->incrChapterCommentCount($chapter);
|
||||
|
||||
$this->incrCourseCommentCount($course);
|
||||
|
||||
$this->incrUserDailyCommentCount($user);
|
||||
|
||||
return $comment;
|
||||
}
|
||||
|
||||
protected function incrChapterCommentCount(ChapterModel $chapter)
|
||||
{
|
||||
$this->eventsManager->fire('chapterCounter:incrCommentCount', $this, $chapter);
|
||||
}
|
||||
|
||||
protected function incrCourseCommentCount(CourseModel $course)
|
||||
{
|
||||
$this->eventsManager->fire('courseCounter:incrCommentCount', $this, $course);
|
||||
}
|
||||
|
||||
protected function incrUserDailyCommentCount(UserModel $user)
|
||||
{
|
||||
$this->eventsManager->fire('userDailyCounter:incrCommentCount', $this, $user);
|
||||
}
|
||||
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Frontend\Comment;
|
||||
|
||||
use App\Models\Chapter as ChapterModel;
|
||||
use App\Models\Course as CourseModel;
|
||||
use App\Services\Frontend\ChapterTrait;
|
||||
use App\Services\Frontend\CommentTrait;
|
||||
use App\Services\Frontend\CourseTrait;
|
||||
use App\Services\Frontend\Service as FrontendService;
|
||||
use App\Validators\Comment as CommentValidator;
|
||||
|
||||
class CommentDelete extends FrontendService
|
||||
{
|
||||
|
||||
use CommentTrait, ChapterTrait, CourseTrait;
|
||||
|
||||
public function handle($id)
|
||||
{
|
||||
$comment = $this->checkComment($id);
|
||||
|
||||
$chapter = $this->checkChapter($comment->chapter_id);
|
||||
|
||||
$course = $this->checkCourse($comment->course_id);
|
||||
|
||||
$user = $this->getLoginUser();
|
||||
|
||||
$validator = new CommentValidator();
|
||||
|
||||
$validator->checkOwner($user->id, $comment->user_id);
|
||||
|
||||
$comment->delete();
|
||||
|
||||
$this->decrChapterCommentCount($chapter);
|
||||
|
||||
$this->decrCourseCommentCount($course);
|
||||
}
|
||||
|
||||
protected function decrChapterCommentCount(ChapterModel $chapter)
|
||||
{
|
||||
$this->eventsManager->fire('chapterCounter:decrCommentCount', $this, $chapter);
|
||||
}
|
||||
|
||||
protected function decrCourseCommentCount(CourseModel $course)
|
||||
{
|
||||
$this->eventsManager->fire('courseCounter:decrCommentCount', $this, $course);
|
||||
}
|
||||
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Frontend\Comment;
|
||||
|
||||
use App\Models\Comment as CommentModel;
|
||||
use App\Repos\User as UserRepo;
|
||||
use App\Services\Frontend\CommentTrait;
|
||||
use App\Services\Frontend\Service as FrontendService;
|
||||
|
||||
class CommentInfo extends FrontendService
|
||||
{
|
||||
|
||||
use CommentTrait;
|
||||
|
||||
public function handle($id)
|
||||
{
|
||||
$comment = $this->checkComment($id);
|
||||
|
||||
return $this->handleComment($comment);
|
||||
}
|
||||
|
||||
protected function handleComment(CommentModel $comment)
|
||||
{
|
||||
$result = [
|
||||
'id' => $comment->id,
|
||||
'content' => $comment->content,
|
||||
'like_count' => $comment->like_count,
|
||||
'create_time' => $comment->create_time,
|
||||
'update_time' => $comment->update_time,
|
||||
];
|
||||
|
||||
$userRepo = new UserRepo();
|
||||
|
||||
$owner = $userRepo->findById($comment->user_id);
|
||||
|
||||
$result['user'] = [
|
||||
'id' => $owner->id,
|
||||
'name' => $owner->name,
|
||||
'avatar' => $owner->avatar,
|
||||
];
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Frontend\Comment;
|
||||
|
||||
use App\Models\Comment as CommentModel;
|
||||
use App\Models\CommentLike as CommentLikeModel;
|
||||
use App\Models\User as UserModel;
|
||||
use App\Services\Frontend\CommentTrait;
|
||||
use App\Services\Frontend\Service as FrontendService;
|
||||
use App\Validators\Comment as CommentValidator;
|
||||
use App\Validators\UserDailyLimit as UserDailyLimitValidator;
|
||||
use Phalcon\Events\Manager as EventsManager;
|
||||
|
||||
class CommentLike extends FrontendService
|
||||
{
|
||||
|
||||
use CommentTrait;
|
||||
|
||||
public function handle($id)
|
||||
{
|
||||
$comment = $this->checkComment($id);
|
||||
|
||||
$user = $this->getLoginUser();
|
||||
|
||||
$validator = new UserDailyLimitValidator();
|
||||
|
||||
$validator->checkCommentLikeLimit($user);
|
||||
|
||||
$validator = new CommentValidator();
|
||||
|
||||
$commentLike = $validator->checkIfLiked($comment->id, $user->id);
|
||||
|
||||
if (!$commentLike) {
|
||||
|
||||
$commentLike = new CommentLikeModel();
|
||||
|
||||
$commentLike->create([
|
||||
'comment_id' => $comment->id,
|
||||
'user_id' => $user->id,
|
||||
]);
|
||||
|
||||
$this->incrLikeCount($comment);
|
||||
|
||||
} else {
|
||||
|
||||
if ($commentLike->deleted == 0) {
|
||||
|
||||
$commentLike->update(['deleted' => 1]);
|
||||
|
||||
$this->decrLikeCount($comment);
|
||||
|
||||
} else {
|
||||
|
||||
$commentLike->update(['deleted' => 0]);
|
||||
|
||||
$this->incrLikeCount($comment);
|
||||
}
|
||||
}
|
||||
|
||||
$this->incrUserDailyCommentLikeCount($user);
|
||||
|
||||
return $comment;
|
||||
}
|
||||
|
||||
protected function incrLikeCount(CommentModel $comment)
|
||||
{
|
||||
$this->getPhEventsManager()->fire('commentCounter:incrLikeCount', $this, $comment);
|
||||
}
|
||||
|
||||
protected function decrLikeCount(CommentModel $comment)
|
||||
{
|
||||
$this->getPhEventsManager()->fire('commentCounter:decrLikeCount', $this, $comment);
|
||||
}
|
||||
|
||||
protected function incrUserDailyCommentLikeCount(UserModel $user)
|
||||
{
|
||||
$this->getPhEventsManager()->fire('userDailyCounter:incrCommentLikeCount', $this, $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return EventsManager
|
||||
*/
|
||||
protected function getPhEventsManager()
|
||||
{
|
||||
return $this->getDI()->get('eventsManager');
|
||||
}
|
||||
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Frontend\Comment;
|
||||
|
||||
use App\Services\Frontend\CommentTrait;
|
||||
use App\Services\Frontend\Service as FrontendService;
|
||||
use App\Validators\Comment as CommentValidator;
|
||||
|
||||
class CommentUpdate extends FrontendService
|
||||
{
|
||||
|
||||
use CommentTrait;
|
||||
|
||||
public function handle($id)
|
||||
{
|
||||
$post = $this->request->getPost();
|
||||
|
||||
$user = $this->getLoginUser();
|
||||
|
||||
$comment = $this->checkComment($id);
|
||||
|
||||
$validator = new CommentValidator();
|
||||
|
||||
$validator->checkOwner($user->id, $comment->user_id);
|
||||
|
||||
$data = [];
|
||||
|
||||
$data['content'] = $validator->checkContent($post['content']);
|
||||
|
||||
if (isset($post['mentions'])) {
|
||||
$data['mentions'] = $validator->checkMentions($post['mentions']);
|
||||
}
|
||||
|
||||
$comment->update($data);
|
||||
}
|
||||
|
||||
protected function handleMentions($mentions)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Frontend;
|
||||
|
||||
use App\Validators\Comment as CommentValidator;
|
||||
|
||||
trait CommentTrait
|
||||
{
|
||||
|
||||
public function checkComment($id)
|
||||
{
|
||||
$validator = new CommentValidator();
|
||||
|
||||
return $validator->checkComment($id);
|
||||
}
|
||||
|
||||
}
|
@ -2,9 +2,11 @@
|
||||
|
||||
namespace App\Services\Frontend\Consult;
|
||||
|
||||
use App\Models\Chapter as ChapterModel;
|
||||
use App\Models\Consult as ConsultModel;
|
||||
use App\Models\Course as CourseModel;
|
||||
use App\Models\User as UserModel;
|
||||
use App\Services\Frontend\ChapterTrait;
|
||||
use App\Services\Frontend\CourseTrait;
|
||||
use App\Services\Frontend\Service as FrontendService;
|
||||
use App\Validators\Consult as ConsultValidator;
|
||||
@ -13,7 +15,7 @@ use App\Validators\UserDailyLimit as UserDailyLimitValidator;
|
||||
class ConsultCreate extends FrontendService
|
||||
{
|
||||
|
||||
use CourseTrait;
|
||||
use CourseTrait, ChapterTrait;
|
||||
|
||||
public function handle()
|
||||
{
|
||||
@ -21,7 +23,9 @@ class ConsultCreate extends FrontendService
|
||||
|
||||
$user = $this->getLoginUser();
|
||||
|
||||
$course = $this->checkCourseCache($post['course_id']);
|
||||
$chapter = $this->checkChapter($post['chapter_id']);
|
||||
|
||||
$course = $this->checkCourse($chapter->course_id);
|
||||
|
||||
$validator = new UserDailyLimitValidator();
|
||||
|
||||
@ -31,26 +35,51 @@ class ConsultCreate extends FrontendService
|
||||
|
||||
$question = $validator->checkQuestion($post['question']);
|
||||
|
||||
$priority = $this->getPriority($course, $user);
|
||||
|
||||
$consult = new ConsultModel();
|
||||
|
||||
$consult->course_id = $course->id;
|
||||
$consult->user_id = $user->id;
|
||||
$consult->question = $question;
|
||||
$consult->priority = $priority;
|
||||
$consult->course_id = $course->id;
|
||||
$consult->chapter_id = $chapter->id;
|
||||
$consult->user_id = $user->id;
|
||||
|
||||
$consult->create();
|
||||
|
||||
$this->incrCourseConsultCount($course);
|
||||
|
||||
$this->incrChapterConsultCount($chapter);
|
||||
$this->incrUserDailyConsultCount($user);
|
||||
|
||||
return $consult;
|
||||
}
|
||||
|
||||
protected function getPriority(CourseModel $course, UserModel $user)
|
||||
{
|
||||
$charge = $course->market_price > 0;
|
||||
$vip = $user->vip == 1;
|
||||
|
||||
if ($vip && $charge) {
|
||||
$priority = ConsultModel::PRIORITY_HIGH;
|
||||
} elseif ($charge) {
|
||||
$priority = ConsultModel::PRIORITY_MIDDLE;
|
||||
} else {
|
||||
$priority = ConsultModel::PRIORITY_LOW;
|
||||
}
|
||||
|
||||
return $priority;
|
||||
}
|
||||
|
||||
protected function incrCourseConsultCount(CourseModel $course)
|
||||
{
|
||||
$this->eventsManager->fire('courseCounter:incrConsultCount', $this, $course);
|
||||
}
|
||||
|
||||
protected function incrChapterConsultCount(ChapterModel $chapter)
|
||||
{
|
||||
$this->eventsManager->fire('chapterCounter:incrConsultCount', $this, $chapter);
|
||||
}
|
||||
|
||||
protected function incrUserDailyConsultCount(UserModel $user)
|
||||
{
|
||||
$this->eventsManager->fire('userDailyCounter:incrConsultCount', $this, $user);
|
||||
|
@ -27,7 +27,6 @@ class ConsultList extends FrontendService
|
||||
'course_id' => $course->id,
|
||||
'private' => 0,
|
||||
'published' => 1,
|
||||
'deleted' => 0,
|
||||
];
|
||||
|
||||
$consultRepo = new ConsultRepo();
|
||||
|
@ -4,6 +4,7 @@ namespace App\Services\Frontend\Course;
|
||||
|
||||
use App\Models\Course as CourseModel;
|
||||
use App\Models\User as UserModel;
|
||||
use App\Repos\Course as CourseRepo;
|
||||
use App\Repos\CourseFavorite as CourseFavoriteRepo;
|
||||
use App\Services\Frontend\CourseTrait;
|
||||
use App\Services\Frontend\Service as FrontendService;
|
||||
@ -26,6 +27,17 @@ class CourseInfo extends FrontendService
|
||||
|
||||
protected function handleCourse(CourseModel $course, UserModel $user)
|
||||
{
|
||||
$repo = new CourseRepo();
|
||||
|
||||
$rating = $repo->findCourseRating($course->id);
|
||||
|
||||
$ratings = [
|
||||
'rating' => $rating->rating,
|
||||
'rating1' => $rating->rating1,
|
||||
'rating2' => $rating->rating2,
|
||||
'rating3' => $rating->rating3,
|
||||
];
|
||||
|
||||
$result = [
|
||||
'id' => $course->id,
|
||||
'title' => $course->title,
|
||||
@ -39,7 +51,7 @@ class CourseInfo extends FrontendService
|
||||
'vip_price' => $course->vip_price,
|
||||
'study_expiry' => $course->study_expiry,
|
||||
'refund_expiry' => $course->refund_expiry,
|
||||
'rating' => $course->rating,
|
||||
'ratings' => $ratings,
|
||||
'model' => $course->model,
|
||||
'level' => $course->level,
|
||||
'attrs' => $course->attrs,
|
||||
@ -47,7 +59,6 @@ class CourseInfo extends FrontendService
|
||||
'lesson_count' => $course->lesson_count,
|
||||
'package_count' => $course->package_count,
|
||||
'review_count' => $course->review_count,
|
||||
'comment_count' => $course->comment_count,
|
||||
'consult_count' => $course->consult_count,
|
||||
'favorite_count' => $course->favorite_count,
|
||||
];
|
||||
|
@ -26,7 +26,6 @@ class ReviewList extends FrontendService
|
||||
$params = [
|
||||
'course_id' => $course->id,
|
||||
'published' => 1,
|
||||
'deleted' => 0,
|
||||
];
|
||||
|
||||
$reviewRepo = new ReviewRepo();
|
||||
|
@ -1,94 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Validators;
|
||||
|
||||
use App\Exceptions\BadRequest as BadRequestException;
|
||||
use App\Repos\Chapter as ChapterRepo;
|
||||
use App\Repos\Comment as CommentRepo;
|
||||
use App\Repos\CommentLike as CommentLikeRepo;
|
||||
use App\Repos\Course as CourseRepo;
|
||||
|
||||
class Comment extends Validator
|
||||
{
|
||||
|
||||
public function checkComment($id)
|
||||
{
|
||||
$commentRepo = new CommentRepo();
|
||||
|
||||
$comment = $commentRepo->findById($id);
|
||||
|
||||
if (!$comment) {
|
||||
throw new BadRequestException('comment.not_found');
|
||||
}
|
||||
|
||||
return $comment;
|
||||
}
|
||||
|
||||
public function checkChapter($chapterId)
|
||||
{
|
||||
$chapterRepo = new ChapterRepo();
|
||||
|
||||
$chapter = $chapterRepo->findById($chapterId);
|
||||
|
||||
if (!$chapter) {
|
||||
throw new BadRequestException('comment.invalid_chapter_id');
|
||||
}
|
||||
|
||||
return $chapter;
|
||||
}
|
||||
|
||||
public function checkParent($parentId)
|
||||
{
|
||||
$commentRepo = new CourseRepo();
|
||||
|
||||
$parent = $commentRepo->findById($parentId);
|
||||
|
||||
if (!$parent) {
|
||||
throw new BadRequestException('comment.invalid_parent_id');
|
||||
}
|
||||
|
||||
return $parent;
|
||||
}
|
||||
|
||||
public function checkContent($content)
|
||||
{
|
||||
$value = $this->filter->sanitize($content, ['trim', 'string']);
|
||||
|
||||
$length = kg_strlen($value);
|
||||
|
||||
if ($length < 1) {
|
||||
throw new BadRequestException('comment.content_too_short');
|
||||
}
|
||||
|
||||
if ($length > 1000) {
|
||||
throw new BadRequestException('comment.content_too_long');
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function checkPublishStatus($status)
|
||||
{
|
||||
if (!in_array($status, [0, 1])) {
|
||||
throw new BadRequestException('consult.invalid_publish_status');
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
public function checkIfLiked($chapterId, $userId)
|
||||
{
|
||||
$repo = new CommentLikeRepo();
|
||||
|
||||
$like = $repo->findCommentLike($chapterId, $userId);
|
||||
|
||||
if ($like) {
|
||||
if ($like->deleted == 0 && time() - $like->create_time > 5 * 60) {
|
||||
throw new BadRequestException('comment.has_liked');
|
||||
}
|
||||
}
|
||||
|
||||
return $like;
|
||||
}
|
||||
|
||||
}
|
@ -29,6 +29,13 @@ class Consult extends Validator
|
||||
return $validator->checkCourse($id);
|
||||
}
|
||||
|
||||
public function checkChapter($id)
|
||||
{
|
||||
$validator = new Chapter();
|
||||
|
||||
return $validator->checkChapter($id);
|
||||
}
|
||||
|
||||
public function checkQuestion($question)
|
||||
{
|
||||
$value = $this->filter->sanitize($question, ['trim', 'string']);
|
||||
|
@ -27,17 +27,6 @@ class UserDailyLimit extends Validator
|
||||
}
|
||||
}
|
||||
|
||||
public function checkCommentLimit(UserModel $user)
|
||||
{
|
||||
$count = $this->counter->hGet($user->id, 'comment_count');
|
||||
|
||||
$limit = $user->vip ? 100 : 50;
|
||||
|
||||
if ($count > $limit) {
|
||||
throw new BadRequestException('user_daily_limit.reach_comment_limit');
|
||||
}
|
||||
}
|
||||
|
||||
public function checkDanmuLimit(UserModel $user)
|
||||
{
|
||||
$count = $this->counter->hGet($user->id, 'danmu_count');
|
||||
@ -89,17 +78,6 @@ class UserDailyLimit extends Validator
|
||||
}
|
||||
}
|
||||
|
||||
public function checkCommentLikeLimit(UserModel $user)
|
||||
{
|
||||
$count = $this->counter->hGet($user->id, 'comment_like_count');
|
||||
|
||||
$limit = $user->vip ? 200 : 100;
|
||||
|
||||
if ($count > $limit) {
|
||||
throw new BadRequestException('user_daily_limit.reach_like_limit');
|
||||
}
|
||||
}
|
||||
|
||||
public function checkConsultLikeLimit(UserModel $user)
|
||||
{
|
||||
$count = $this->counter->hGet($user->id, 'consult_like_count');
|
||||
|
@ -201,21 +201,12 @@ $error['review.has_liked'] = '你已经点过赞啦';
|
||||
$error['consult.not_found'] = '咨询不存在';
|
||||
$error['consult.invalid_private_status'] = '无效的私密状态';
|
||||
$error['consult.invalid_publish_status'] = '无效的发布状态';
|
||||
$error['consult.question_too_short'] = '提问太短(少于5个字符)';
|
||||
$error['consult.question_too_long'] = '提问太长(多于1000个字符)';
|
||||
$error['consult.answer_too_short'] = '回复太短(少于5个字符)';
|
||||
$error['consult.answer_too_long'] = '回复太长(多于1000个字符)';
|
||||
$error['consult.question_too_short'] = '问题内容太短(少于5个字符)';
|
||||
$error['consult.question_too_long'] = '问题内容太长(多于1000个字符)';
|
||||
$error['consult.answer_too_short'] = '回复内容太短(少于5个字符)';
|
||||
$error['consult.answer_too_long'] = '回复内容太长(多于1000个字符)';
|
||||
$error['consult.has_liked'] = '你已经点过赞啦';
|
||||
|
||||
/**
|
||||
* 评论相关
|
||||
*/
|
||||
$error['comment.not_found'] = '评价不存在';
|
||||
$error['comment.invalid_publish_status'] = '无效的发布状态';
|
||||
$error['comment.content_too_short'] = '评价太短(少于1个字符)';
|
||||
$error['comment.content_too_long'] = '评价太长(多于1000个字符)';
|
||||
$error['comment.has_liked'] = '你已经点过赞啦';
|
||||
|
||||
/**
|
||||
* 单页相关
|
||||
*/
|
||||
|
@ -1,7 +1,6 @@
|
||||
<?php
|
||||
|
||||
use App\Listeners\ChapterCounter;
|
||||
use App\Listeners\CommentCounter;
|
||||
use App\Listeners\ConsultCounter;
|
||||
use App\Listeners\CourseCounter;
|
||||
use App\Listeners\Pay;
|
||||
@ -14,7 +13,6 @@ return [
|
||||
'pay' => Pay::class,
|
||||
'courseCounter' => CourseCounter::class,
|
||||
'chapterCounter' => ChapterCounter::class,
|
||||
'commentCounter' => CommentCounter::class,
|
||||
'consultCounter' => ConsultCounter::class,
|
||||
'reviewCounter' => ReviewCounter::class,
|
||||
'userDailyCounter' => UserDailyCounter::class,
|
||||
|
@ -432,38 +432,17 @@ body {
|
||||
}
|
||||
|
||||
.course-meta .info {
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 80%;
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.course-meta .share {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
.course-meta .rating {
|
||||
float: right;
|
||||
padding: 10px 50px 0 0;
|
||||
}
|
||||
|
||||
.course-meta .share a {
|
||||
margin-right: 5px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.course-meta .share a:hover {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.course-meta .price {
|
||||
color: red;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.course-meta .free {
|
||||
color: green;
|
||||
}
|
||||
|
||||
.course-meta span {
|
||||
color: #666;
|
||||
margin: 0 5px;
|
||||
.course-meta p {
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
.course-meta .cover img {
|
||||
@ -471,8 +450,30 @@ body {
|
||||
height: 118px;
|
||||
}
|
||||
|
||||
.course-meta p {
|
||||
line-height: 30px;
|
||||
.course-meta .info .price {
|
||||
color: red;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.course-meta .info .free {
|
||||
color: green;
|
||||
}
|
||||
|
||||
.course-meta .info span {
|
||||
color: #666;
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.course-meta .rating span {
|
||||
margin: 0 3px;
|
||||
}
|
||||
|
||||
.course-meta .rating .layui-icon {
|
||||
color: orange;
|
||||
}
|
||||
|
||||
.course-meta .rating .score {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.layui-tab-title li {
|
||||
|
21
public/static/web/js/chapter.vod.js
Normal file
21
public/static/web/js/chapter.vod.js
Normal file
@ -0,0 +1,21 @@
|
||||
layui.use(['jquery', 'helper'], function () {
|
||||
|
||||
var $ = layui.jquery;
|
||||
var helper = layui.helper;
|
||||
|
||||
/**
|
||||
* 咨询
|
||||
*/
|
||||
$('.icon-help').on('click', function () {
|
||||
var url = $(this).parent().data('url');
|
||||
helper.checkLogin(function () {
|
||||
layer.open({
|
||||
type: 2,
|
||||
title: '课程咨询',
|
||||
content: [url, 'no'],
|
||||
area: ['640px', '300px']
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
@ -3,12 +3,13 @@ layui.use(['jquery', 'rate'], function () {
|
||||
var $ = layui.jquery;
|
||||
var rate = layui.rate;
|
||||
|
||||
$('.cancel-rating').on('click', function () {
|
||||
$('.btn-cancel').on('click', function () {
|
||||
parent.layer.closeAll();
|
||||
});
|
||||
|
||||
rate.render({
|
||||
elem: '#rating1',
|
||||
value: 5,
|
||||
choose: function (value) {
|
||||
$('input[name=rating1]').val(value);
|
||||
}
|
||||
@ -16,6 +17,7 @@ layui.use(['jquery', 'rate'], function () {
|
||||
|
||||
rate.render({
|
||||
elem: '#rating2',
|
||||
value: 5,
|
||||
choose: function (value) {
|
||||
$('input[name=rating2]').val(value);
|
||||
}
|
||||
@ -23,6 +25,7 @@ layui.use(['jquery', 'rate'], function () {
|
||||
|
||||
rate.render({
|
||||
elem: '#rating3',
|
||||
value: 5,
|
||||
choose: function (value) {
|
||||
$('input[name=rating3]').val(value);
|
||||
}
|
||||
|
@ -4,6 +4,9 @@ layui.use(['jquery', 'layer', 'helper'], function () {
|
||||
var layer = layui.layer;
|
||||
var helper = layui.helper;
|
||||
|
||||
/**
|
||||
* 收藏
|
||||
*/
|
||||
$('.icon-star').on('click', function () {
|
||||
var $this = $(this);
|
||||
helper.checkLogin(function () {
|
||||
@ -23,6 +26,9 @@ layui.use(['jquery', 'layer', 'helper'], function () {
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* 打赏
|
||||
*/
|
||||
$('.btn-reward').on('click', function () {
|
||||
var url = $(this).data('url');
|
||||
helper.checkLogin(function () {
|
||||
@ -30,7 +36,10 @@ layui.use(['jquery', 'layer', 'helper'], function () {
|
||||
});
|
||||
});
|
||||
|
||||
$('.btn-buy').on('click', function () {
|
||||
/**
|
||||
* 购买(课程|套餐)
|
||||
*/
|
||||
$('body').on('click', '.btn-buy', function () {
|
||||
var url = $(this).data('url');
|
||||
helper.checkLogin(function () {
|
||||
window.location.href = url;
|
||||
@ -47,6 +56,22 @@ layui.use(['jquery', 'layer', 'helper'], function () {
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* 浏览章节
|
||||
*/
|
||||
$('body').on('click', '.view-lesson', function () {
|
||||
if ($(this).hasClass('deny')) {
|
||||
return false;
|
||||
}
|
||||
var url = $(this).data('url');
|
||||
helper.checkLogin(function () {
|
||||
window.location.href = url;
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* 点赞(咨询|评价)
|
||||
*/
|
||||
$('body').on('click', '.icon-praise', function () {
|
||||
var $this = $(this);
|
||||
var $likeCount = $this.next();
|
||||
|
Loading…
x
Reference in New Issue
Block a user