1
0
mirror of https://gitee.com/koogua/course-tencent-cloud.git synced 2025-08-03 04:55:53 +08:00

整理功能

This commit is contained in:
xiaochong0302 2020-07-20 20:08:51 +08:00
parent ab27040f2f
commit ac51d23934
43 changed files with 245 additions and 259 deletions

View File

@ -1,61 +0,0 @@
<?php
namespace App\Caches;
use App\Models\Course as CourseModel;
use App\Repos\Topic as TopicRepo;
class TopicCourseList extends Cache
{
protected $lifetime = 1 * 86400;
public function getLifetime()
{
return $this->lifetime;
}
public function getKey($id = null)
{
return "topic_course_list:{$id}";
}
public function getContent($id = null)
{
$topicRepo = new TopicRepo();
$courses = $topicRepo->findCourses($id);
if ($courses->count() == 0) {
return [];
}
return $this->handleContent($courses);
}
/**
* @param CourseModel[] $courses
* @return array
*/
public function handleContent($courses)
{
$result = [];
foreach ($courses as $course) {
$result[] = [
'id' => $course->id,
'title' => $course->title,
'cover' => $course->cover,
'market_price' => $course->market_price,
'vip_price' => $course->vip_price,
'model' => $course->model,
'level' => $course->level,
'user_count' => $course->user_count,
'lesson_count' => $course->lesson_count,
];
}
return $result;
}
}

View File

@ -23,12 +23,10 @@ class UserDailyCounter extends Counter
{
return [
'favorite_count' => 0,
'comment_count' => 0,
'danmu_count' => 0,
'consult_count' => 0,
'order_count' => 0,
'chapter_like_count' => 0,
'comment_like_count' => 0,
'consult_like_count' => 0,
'review_like_count' => 0,
];

View File

@ -16,7 +16,8 @@ class Controller extends \Phalcon\Mvc\Controller
*/
protected $authUser;
use ResponseTrait, SecurityTrait;
use ResponseTrait;
use SecurityTrait;
public function beforeExecuteRoute(Dispatcher $dispatcher)
{

View File

@ -14,7 +14,9 @@ use App\Traits\Security as SecurityTrait;
class SessionController extends \Phalcon\Mvc\Controller
{
use AuthTrait, ResponseTrait, SecurityTrait;
use AuthTrait;
use ResponseTrait;
use SecurityTrait;
/**
* @Route("/login", name="admin.login")

View File

@ -9,7 +9,8 @@ use Phalcon\Mvc\Dispatcher;
class Controller extends \Phalcon\Mvc\Controller
{
use ResponseTrait, SecurityTrait;
use ResponseTrait;
use SecurityTrait;
public function beforeExecuteRoute(Dispatcher $dispatcher)
{

View File

@ -9,7 +9,8 @@ use Phalcon\Mvc\Dispatcher;
class Controller extends \Phalcon\Mvc\Controller
{
use ResponseTrait, SecurityTrait;
use ResponseTrait;
use SecurityTrait;
public function beforeExecuteRoute(Dispatcher $dispatcher)
{

View File

@ -34,7 +34,8 @@ class Controller extends \Phalcon\Mvc\Controller
*/
protected $authUser;
use ResponseTrait, SecurityTrait;
use ResponseTrait;
use SecurityTrait;
public function beforeExecuteRoute(Dispatcher $dispatcher)
{

View File

@ -16,7 +16,8 @@ class LayerController extends \Phalcon\Mvc\Controller
*/
protected $authUser;
use ResponseTrait, SecurityTrait;
use ResponseTrait;
use SecurityTrait;
public function beforeExecuteRoute(Dispatcher $dispatcher)
{

View File

@ -14,7 +14,8 @@ use PHPQRCode\QRcode as PHPQRCode;
class PublicController extends \Phalcon\Mvc\Controller
{
use ResponseTrait, SecurityTrait;
use ResponseTrait;
use SecurityTrait;
/**
* @Get("/content/img/{id:[0-9]+}", name="web.content_img")

View File

@ -31,7 +31,8 @@ use GatewayClient\Gateway;
class Im extends Service
{
use ImFriendTrait, ImGroupTrait;
use ImFriendTrait;
use ImGroupTrait;
public function init()
{

View File

@ -1,9 +0,0 @@
<?php
namespace App\Http\Web\Services;
class Order extends Service
{
}

View File

@ -0,0 +1,15 @@
<div class="breadcrumb">
<span class="layui-breadcrumb">
<a class="kg-back" href="javascript:"><i class="layui-icon layui-icon-return"></i> 返回课程</a>
<a><cite>{{ chapter.course.title }}</cite></a>
<a><cite>{{ chapter.title }}</cite></a>
</span>
<span class="share">
<a href="javascript:" title="学习人次"><i class="layui-icon layui-icon-user"></i><em>{{ chapter.user_count }}</em></a>
<a href="javascript:" title="我要点赞" data-url="{{ like_url }}"><i class="layui-icon layui-icon-praise icon-praise {{ liked_class }}"></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><em>{{ chapter.consult_count }}</em></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>
</div>

View File

@ -3,6 +3,7 @@
{% block content %}
{% set chapter_full_url = full_url({'for':'web.chapter.show','id':chapter.id}) %}
{% set course_url = url({'for':'web.course.show','id':chapter.course.id}) %}
{% set learning_url = url({'for':'web.chapter.learning','id':chapter.id}) %}
{% set live_chats_url = url({'for':'web.live.chats','id':chapter.id}) %}
{% set live_stats_url = url({'for':'web.live.stats','id':chapter.id}) %}
@ -13,6 +14,7 @@
<div class="breadcrumb">
<span class="layui-breadcrumb">
<a href="{{ course_url }}"><i class="layui-icon layui-icon-return"></i> 返回课程</a>
<a><cite>{{ chapter.course.title }}</cite></a>
<a><cite>{{ chapter.title }}</cite></a>
</span>

View File

@ -3,12 +3,14 @@
{% block content %}
{% set chapter_full_url = full_url({'for':'web.chapter.show','id':chapter.id}) %}
{% set course_url = url({'for':'web.course.show','id':chapter.course.id}) %}
{% set learning_url = url({'for':'web.chapter.learning','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}) %}
<div class="breadcrumb">
<span class="layui-breadcrumb">
<a href="{{ course_url }}"><i class="layui-icon layui-icon-return"></i> 返回课程</a>
<a><cite>{{ chapter.course.title }}</cite></a>
<a><cite>{{ chapter.title }}</cite></a>
</span>

View File

@ -3,21 +3,24 @@
{% block content %}
{% set chapter_full_url = full_url({'for':'web.chapter.show','id':chapter.id}) %}
{% set course_url = url({'for':'web.course.show','id':chapter.course.id}) %}
{% set learning_url = url({'for':'web.chapter.learning','id':chapter.id}) %}
{% 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}) %}
{% set liked_class = chapter.me.liked ? 'active' : '' %}
<div class="breadcrumb">
<span class="layui-breadcrumb">
<a href="{{ course_url }}"><i class="layui-icon layui-icon-return"></i> 返回课程</a>
<a><cite>{{ chapter.course.title }}</cite></a>
<a><cite>{{ chapter.title }}</cite></a>
</span>
<span class="share">
<a href="javascript:" title="学习人次"><i class="layui-icon layui-icon-user"></i><em>{{ chapter.user_count }}</em></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="我要点赞" data-url="{{ like_url }}"><i class="layui-icon layui-icon-praise icon-praise {{ liked_class }}"></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><em>{{ chapter.consult_count }}</em></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>
@ -111,7 +114,7 @@
{% block include_js %}
<script src="//imgcache.qq.com/open/qcloud/video/vcplayer/TcPlayer-2.3.2.js"></script>
<script src="//imgcache.qq.com/open/qcloud/video/vcplayer/TcPlayer-2.3.3.js"></script>
{{ js_include('lib/jquery.min.js') }}
{{ js_include('lib/jquery.danmu.min.js') }}

View File

@ -5,7 +5,7 @@
<div class="layui-form-item">
<label class="layui-form-label">咨询内容</label>
<div class="layui-input-block">
<textarea name="question" class="layui-textarea" placeholder="请详细描述问题,我们会尽快回复您"></textarea>
<textarea name="question" class="layui-textarea" placeholder="请详细描述问题,我们会尽快回复您" lay-verify="required"></textarea>
</div>
</div>
<div class="layui-form-item">

View File

@ -11,7 +11,7 @@
</div>
<div class="info">
<div class="title">{{ item.question }}</div>
<div class="content">{{ item.answer }}</div>
<div class="content">{% if item.answer %} {{ item.answer }} {% else %} 稍安勿燥,请耐心等待我们的回复吧 {% endif %}</div>
<div class="footer">
<span class="time">{{ item.create_time|time_ago }}</span>
<a href="javascript:" class="like" title="点赞" data-url="{{ like_url }}">

View File

@ -4,7 +4,8 @@
{{ partial('partials/macro_course') }}
{% set favorite_star_class = course.me.favorited ? 'layui-icon-star-fill' : 'layui-icon-star' %}
{% set favorite_title = course.me.favorited ? '取消收藏' : '收藏' %}
{% set favorite_star = 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}) %}
@ -18,7 +19,7 @@
<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="{{ favorite_title }}" data-url="{{ favorite_url }}"><i class="layui-icon {{ favorite_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>

View File

@ -4,32 +4,36 @@
</div>
<div class="info">
{% if course.model == 'vod' %}
<p>课程时长 <span>{{ course.attrs.duration|total_duration }}</span></p>
<p class="item">
<span class="key">课程时长</span><span class="value">{{ 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 class="item">
<span class="key">直播时间</span><span>{{ course.attrs.start_date }} ~ {{ course.attrs.end_date }}</span>
</p>
{% endif %}
<p>
{% if course.market_price > 0 %}
<p class="item">
<span class="key">学习期限</span><span class="value">{{ course.study_expiry }}个月</span>
<span class="key">退款期限</span><span class="value">{{ course.refund_expiry }}天</span>
</p>
{% endif %}
<p class="item">
{% if course.market_price > 0 %}
市场价格 <span class="price">{{ '¥%0.2f'|format(course.market_price) }}</span>
<span class="key">市场价格</span><span class="price">{{ '¥%0.2f'|format(course.market_price) }}</span>
{% else %}
市场价格 <span class="free">免费</span>
<span class="key">市场价格</span><span class="free">免费</span>
{% endif %}
{% if course.vip_price > 0 %}
会员价格 <span class="price">{{ '¥%0.2f'|format(course.vip_price) }}</span>
<span class="key">会员价格</span><span class="price">{{ '¥%0.2f'|format(course.vip_price) }}</span>
{% else %}
会员价格 <span class="free">免费</span>
<span class="key">会员价格</span><span class="free">免费</span>
{% endif %}
</p>
<p>
难度级别 <span>{{ level_info(course.level) }}</span>
学习人次 <span>{{ course.user_count }}</span>
综合评分 <span>{{ course.ratings.rating }}</span>
<p class="item">
<span class="key">难度级别</span><span class="value">{{ level_info(course.level) }}</span>
<span class="key">学习人次</span><span class="value">{{ course.user_count }}</span>
<span class="key">综合评分</span><span class="value">{{ course.ratings.rating }}</span>
</p>
</div>
<div class="rating">

View File

@ -22,7 +22,7 @@
<span class="icon"><i class="layui-icon layui-icon-cellphone"></i></span>
<span class="title">手机绑定</span>
{% if account.phone %}
<span class="summary">已绑定手机:{{ account.phone }}</span>
<span class="summary">已绑定手机:{{ account.phone|anonymous }}</span>
<span class="action"><a class="layui-btn layui-btn-sm" href="{{ act_phone_url }}">修改</a></span>
{% else %}
<span class="summary">可用于登录和重置密码</span>
@ -33,7 +33,7 @@
<span class="icon"><i class="layui-icon layui-icon-email"></i></span>
<span class="title">邮箱绑定</span>
{% if account.phone %}
<span class="summary">已绑定邮箱:{{ account.email }}</span>
<span class="summary">已绑定邮箱:{{ account.email|anonymous }}</span>
<span class="action"><a class="layui-btn layui-btn-sm" href="{{ act_email_url }}">修改</a></span>
{% else %}
<span class="summary">可用于登录和重置密码</span>

View File

@ -1,5 +1,6 @@
<?php
use App\Library\Validators\Common as CommonValidator;
use App\Services\Storage as StorageService;
use Koogua\Ip2Region\Searcher as Ip2RegionSearcher;
use Phalcon\Di;
@ -207,6 +208,39 @@ function kg_ci_cover_img_url($path)
return kg_ci_img_url($path);
}
/**
* 隐藏部分字符
*
* @param string $str
* @return string
*/
function kg_anonymous($str)
{
$length = mb_strlen($str);
if (CommonValidator::email($str)) {
$start = 3;
$end = mb_stripos($str, '@');
} elseif (CommonValidator::phone($str)) {
$start = 3;
$end = $length - 4;
} elseif (CommonValidator::idCard($str)) {
$start = 3;
$end = $length - 4;
} else {
$start = 1;
$end = $length - 2;
}
$list = [];
for ($i = 0; $i < $length; $i++) {
$list[] = ($i < $start || $i > $end) ? mb_substr($str, $i, 1) : '*';
}
return join('', $list);
}
/**
* 格式化数字
*
@ -252,48 +286,12 @@ function kg_time_ago($time)
}
/**
* 播放时长
* 格式化时长
*
* @param int $time
* @return string
*/
function kg_play_duration($time)
{
$result = '00:00';
if ($time > 0) {
$hours = floor($time / 3600);
$minutes = floor(($time - $hours * 3600) / 60);
$seconds = $time % 60;
$format = [];
if ($hours > 0) {
$format[] = sprintf('%02d', $hours);
}
if ($minutes >= 0) {
$format[] = sprintf('%02d', $minutes);
}
if ($seconds >= 0) {
$format[] = sprintf('%02d', $seconds);
}
$result = implode(':', $format);
}
return $result;
}
/**
* 总时长
*
* @param int $time
* @return string
*/
function kg_total_duration($time)
function kg_duration($time)
{
$result = '00分钟';

View File

@ -54,12 +54,8 @@ class Volt extends Provider
return 'kg_can(' . $resolvedArgs . ')';
});
$compiler->addFilter('play_duration', function ($resolvedArgs) {
return 'kg_play_duration(' . $resolvedArgs . ')';
});
$compiler->addFilter('total_duration', function ($resolvedArgs) {
return 'kg_total_duration(' . $resolvedArgs . ')';
$compiler->addFilter('duration', function ($resolvedArgs) {
return 'kg_duration(' . $resolvedArgs . ')';
});
$compiler->addFilter('human_number', function ($resolvedArgs) {
@ -70,6 +66,10 @@ class Volt extends Provider
return 'kg_time_ago(' . $resolvedArgs . ')';
});
$compiler->addFilter('anonymous', function ($resolvedArgs) {
return 'kg_anonymous(' . $resolvedArgs . ')';
});
return $volt;
});
}

View File

@ -86,6 +86,20 @@ class Consult extends Repository
->execute();
}
/**
* @param int $chapterId
* @param int $userId
* @return ConsultModel|Model|bool
*/
public function findUserLastChapterConsult($chapterId, $userId)
{
return ConsultModel::findFirst([
'conditions' => 'chapter_id = ?1 AND user_id = ?2 AND deleted = 0',
'bind' => [1 => $chapterId, 2 => $userId],
'order' => 'id DESC',
]);
}
public function countConsults()
{
return (int)ConsultModel::count(['conditions' => 'deleted = 0']);

View File

@ -8,6 +8,7 @@ use App\Models\Course as CourseModel;
use App\Models\CourseUser as CourseUserModel;
use App\Models\User as UserModel;
use App\Repos\Chapter as ChapterRepo;
use App\Repos\ChapterLike as ChapterLikeRepo;
use App\Services\ChapterVod as ChapterVodService;
use App\Services\Frontend\ChapterTrait;
use App\Services\Frontend\CourseTrait;
@ -27,7 +28,8 @@ class ChapterInfo extends FrontendService
*/
protected $user;
use CourseTrait, ChapterTrait;
use CourseTrait;
use ChapterTrait;
public function handle($id)
{
@ -47,10 +49,10 @@ class ChapterInfo extends FrontendService
$this->setChapterUser($chapter, $user);
$this->handleChapterUser($chapter, $user);
return $this->handleChapter($chapter);
return $this->handleChapter($chapter, $user);
}
protected function handleChapter(ChapterModel $chapter)
protected function handleChapter(ChapterModel $chapter, UserModel $user)
{
$result = $this->formatChapter($chapter);
@ -61,18 +63,30 @@ class ChapterInfo extends FrontendService
'position' => 0,
'joined' => 0,
'owned' => 0,
'liked' => 0,
];
if ($this->courseUser) {
$me['plan_id'] = $this->courseUser->plan_id;
}
if ($user->id) {
if ($this->chapterUser) {
$me['position'] = $this->chapterUser->position;
}
$likeRepo = new ChapterLikeRepo();
$me['joined'] = $this->joinedChapter ? 1 : 0;
$me['owned'] = $this->ownedChapter ? 1 : 0;
$like = $likeRepo->findChapterLike($chapter->id, $user->id);
if ($like && $like->deleted == 0) {
$me['liked'] = 1;
}
if ($this->courseUser) {
$me['plan_id'] = $this->courseUser->plan_id;
}
if ($this->chapterUser) {
$me['position'] = $this->chapterUser->position;
}
$me['joined'] = $this->joinedChapter ? 1 : 0;
$me['owned'] = $this->ownedChapter ? 1 : 0;
}
$result['me'] = $me;
@ -85,12 +99,6 @@ class ChapterInfo extends FrontendService
'id' => $course->id,
'title' => $course->title,
'cover' => $course->cover,
'market_price' => $course->market_price,
'vip_price' => $course->vip_price,
'model' => $course->model,
'level' => $course->level,
'user_count' => $course->user_count,
'lesson_count' => $course->lesson_count,
];
}
@ -98,7 +106,7 @@ class ChapterInfo extends FrontendService
{
$item = [];
switch ($this->course->model) {
switch ($chapter->model) {
case CourseModel::MODEL_VOD:
$item = $this->formatChapterVod($chapter);
break;
@ -127,7 +135,7 @@ class ChapterInfo extends FrontendService
'play_urls' => $playUrls,
'user_count' => $chapter->user_count,
'like_count' => $chapter->like_count,
'comment_count' => $chapter->comment_count,
'consult_count' => $chapter->consult_count,
];
}
@ -166,7 +174,7 @@ class ChapterInfo extends FrontendService
'play_urls' => $playUrls,
'user_count' => $chapter->user_count,
'like_count' => $chapter->like_count,
'comment_count' => $chapter->comment_count,
'consult_count' => $chapter->consult_count,
];
}
@ -184,7 +192,7 @@ class ChapterInfo extends FrontendService
'content' => $read->content,
'user_count' => $chapter->user_count,
'like_count' => $chapter->like_count,
'comment_count' => $chapter->comment_count,
'consult_count' => $chapter->consult_count,
];
}

View File

@ -11,7 +11,7 @@ use App\Services\Frontend\Service as FrontendService;
use App\Services\Live as LiveService;
use WhichBrowser\Parser as BrowserParser;
class ChapterBasic extends FrontendService
class ChapterInfoBasic extends FrontendService
{
use ChapterTrait;

View File

@ -5,9 +5,9 @@ namespace App\Services\Frontend\Chapter;
use App\Models\Chapter as ChapterModel;
use App\Models\ChapterLike as ChapterLikeModel;
use App\Models\User as UserModel;
use App\Repos\ChapterLike as ChapterLikeRepo;
use App\Services\Frontend\ChapterTrait;
use App\Services\Frontend\Service as FrontendService;
use App\Validators\Chapter as ChapterValidator;
use App\Validators\UserDailyLimit as UserDailyLimitValidator;
use Phalcon\Events\Manager as EventsManager;
@ -26,9 +26,9 @@ class ChapterLike extends FrontendService
$validator->checkChapterLikeLimit($user);
$validator = new ChapterValidator();
$likeRepo = new ChapterLikeRepo();
$chapterLike = $validator->checkIfLiked($chapter->id, $user->id);
$chapterLike = $likeRepo->findChapterLike($chapter->id, $user->id);
if (!$chapterLike) {

View File

@ -15,7 +15,8 @@ use App\Validators\UserDailyLimit as UserDailyLimitValidator;
class ConsultCreate extends FrontendService
{
use CourseTrait, ChapterTrait;
use CourseTrait;
use ChapterTrait;
public function handle()
{
@ -35,6 +36,8 @@ class ConsultCreate extends FrontendService
$question = $validator->checkQuestion($post['question']);
$validator->checkIfDuplicated($chapter->id, $user->id, $question);
$priority = $this->getPriority($course, $user);
$consult = new ConsultModel();
@ -44,6 +47,7 @@ class ConsultCreate extends FrontendService
$consult->course_id = $course->id;
$consult->chapter_id = $chapter->id;
$consult->user_id = $user->id;
$consult->published = 1;
$consult->create();

View File

@ -11,7 +11,8 @@ use App\Validators\Consult as ConsultValidator;
class ConsultDelete extends FrontendService
{
use CourseTrait, ConsultTrait;
use ConsultTrait;
use CourseTrait;
public function handle($id)
{

View File

@ -10,7 +10,8 @@ use App\Validators\Consult as ConsultValidator;
class ConsultUpdate extends FrontendService
{
use CourseTrait, ConsultTrait;
use CourseTrait;
use ConsultTrait;
public function handle($id)
{

View File

@ -6,7 +6,7 @@ use App\Models\Course as CourseModel;
use App\Services\Frontend\CourseTrait;
use App\Services\Frontend\Service as FrontendService;
class CourseBasic extends FrontendService
class CourseInfoBasic extends FrontendService
{
use CourseTrait;

View File

@ -5,9 +5,9 @@ namespace App\Services\Frontend\Course;
use App\Models\Course as CourseModel;
use App\Models\CourseFavorite as CourseFavoriteModel;
use App\Models\User as UserModel;
use App\Repos\CourseFavorite as CourseFavoriteRepo;
use App\Services\Frontend\CourseTrait;
use App\Services\Frontend\Service as FrontendService;
use App\Validators\Course as CourseValidator;
use App\Validators\UserDailyLimit as UserDailyLimitValidator;
class Favorite extends FrontendService
@ -25,9 +25,9 @@ class Favorite extends FrontendService
$validator->checkFavoriteLimit($user);
$validator = new CourseValidator();
$favoriteRepo = new CourseFavoriteRepo();
$favorite = $validator->checkIfFavorited($course->id, $user->id);
$favorite = $favoriteRepo->findCourseFavorite($course->id, $user->id);
if (!$favorite) {

View File

@ -33,8 +33,6 @@ class UserInfo extends FrontendService
'lock_expiry_time' => $user->lock_expiry_time,
'edu_role' => $user->edu_role,
'admin_role' => $user->admin_role,
'notice_count' => $user->notice_count,
'msg_count' => $user->msg_count,
];
}

View File

@ -11,7 +11,8 @@ use App\Validators\Review as ReviewValidator;
class ReviewDelete extends FrontendService
{
use CourseTrait, ReviewTrait;
use CourseTrait;
use ReviewTrait;
public function handle($id)
{

View File

@ -10,7 +10,8 @@ use App\Validators\Review as ReviewValidator;
class ReviewUpdate extends FrontendService
{
use CourseTrait, ReviewTrait;
use CourseTrait;
use ReviewTrait;
public function handle($id)
{

View File

@ -8,7 +8,6 @@ use App\Exceptions\BadRequest as BadRequestException;
use App\Models\Chapter as ChapterModel;
use App\Models\Course as CourseModel;
use App\Repos\Chapter as ChapterRepo;
use App\Repos\ChapterLike as ChapterLikeRepo;
use App\Repos\Course as CourseRepo;
class Chapter extends Validator
@ -174,19 +173,4 @@ class Chapter extends Validator
}
}
public function checkIfLiked($chapterId, $userId)
{
$repo = new ChapterLikeRepo();
$like = $repo->findChapterLike($chapterId, $userId);
if ($like) {
if ($like->deleted == 0 && time() - $like->create_time > 5 * 60) {
throw new BadRequestException('chapter.has_liked');
}
}
return $like;
}
}

View File

@ -42,7 +42,7 @@ class Consult extends Validator
$length = kg_strlen($value);
if ($length < 5) {
if ($length < 15) {
throw new BadRequestException('consult.question_too_short');
}
@ -59,7 +59,7 @@ class Consult extends Validator
$length = kg_strlen($value);
if ($length < 5) {
if ($length < 15) {
throw new BadRequestException('consult.answer_too_short');
}
@ -88,6 +88,30 @@ class Consult extends Validator
return $status;
}
public function checkIfDuplicated($chapterId, $userId, $question)
{
$repo = new ConsultRepo();
$consult = $repo->findUserLastChapterConsult($chapterId, $userId);
if (!$consult) return;
$subInQuestion = kg_substr($question, 0, 20);
$subDbQuestion = kg_substr($consult->question, 0, 20);
similar_text($subInQuestion, $subDbQuestion, $percent);
if ($percent > 80) {
throw new BadRequestException('consult.question_duplicated');
}
similar_text($question, $consult->question, $percent);
if ($percent > 80) {
throw new BadRequestException('consult.question_duplicated');
}
}
public function checkIfLiked($chapterId, $userId)
{
$repo = new ConsultLikeRepo();

View File

@ -8,7 +8,6 @@ use App\Exceptions\BadRequest as BadRequestException;
use App\Library\Validators\Common as CommonValidator;
use App\Models\Course as CourseModel;
use App\Repos\Course as CourseRepo;
use App\Repos\CourseFavorite as CourseFavoriteRepo;
class Course extends Validator
{
@ -243,19 +242,4 @@ class Course extends Validator
}
}
public function checkIfFavorited($courseId, $userId)
{
$repo = new CourseFavoriteRepo();
$favorite = $repo->findCourseFavorite($courseId, $userId);
if ($favorite) {
if ($favorite->deleted == 0 && time() - $favorite->create_time > 5 * 60) {
throw new BadRequestException('course.has_favorited');
}
}
return $favorite;
}
}

View File

@ -112,7 +112,6 @@ $error['course.invalid_refund_expiry'] = '无效的退款期限';
$error['course.invalid_publish_status'] = '无效的发布状态';
$error['course.pub_chapter_not_found'] = '尚未发现已发布的课时';
$error['course.pub_chapter_not_enough'] = '已发布的课时太少小于30%';
$error['course.has_favorited'] = '你已收藏过该课程啦';
/**
* 话题相关
@ -159,7 +158,6 @@ $error['chapter.read_not_ready'] = '文章内容尚未就绪';
$error['chapter.live_not_start'] = '直播尚未开始';
$error['chapter.live_time_empty'] = '直播时间尚未设置';
$error['chapter.child_existed'] = '不允许相关操作(存在子章节)';
$error['chapter.has_liked'] = '你已经点过赞啦';
/**
* 点播相关
@ -201,9 +199,10 @@ $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_duplicated'] = '你已经咨询过类似问题啦';
$error['consult.question_too_short'] = '问题内容太短少于15个字符';
$error['consult.question_too_long'] = '问题内容太长多于1000个字符';
$error['consult.answer_too_short'] = '回复内容太短(少于5个字符';
$error['consult.answer_too_short'] = '回复内容太短(少于15个字符';
$error['consult.answer_too_long'] = '回复内容太长多于1000个字符';
$error['consult.has_liked'] = '你已经点过赞啦';

View File

@ -450,6 +450,14 @@ body {
height: 118px;
}
.course-meta .info span {
margin-right: 5px;
}
.course-meta .info .value {
color: #666;
}
.course-meta .info .price {
color: red;
font-size: 14px;
@ -459,13 +467,8 @@ body {
color: green;
}
.course-meta .info span {
color: #666;
margin: 0 5px;
}
.course-meta .rating span {
margin: 0 3px;
margin-right: 5px;
}
.course-meta .rating .layui-icon {
@ -841,6 +844,10 @@ body {
cursor: pointer;
}
.share .layui-icon-star-fill {
color: orange;
}
.share .active, .share .layui-icon:hover {
color: green;
}
@ -870,6 +877,7 @@ body {
left: 180px;
bottom: 38px;
width: 420px;
z-index: 999;
display: none;
}

View File

@ -5,19 +5,22 @@ layui.use(['jquery', 'helper'], function () {
$('.icon-praise').on('click', function () {
var $this = $(this);
var $parent = $this.parent();
var $likeCount = $this.next();
var likeCount = parseInt($likeCount.text());
helper.checkLogin(function () {
$.ajax({
type: 'POST',
url: $this.parent().data('url'),
url: $parent.data('url'),
success: function () {
if ($this.hasClass('active')) {
$this.removeClass('active');
$parent.attr('title', '点赞');
$likeCount.text(likeCount - 1);
likeCount -= 1;
} else {
$this.addClass('active');
$parent.attr('title', '取消点赞');
$likeCount.text(likeCount + 1);
likeCount += 1;
}

View File

@ -16,6 +16,7 @@ layui.use(['jquery', 'form', 'layer', 'helper'], function () {
var danmuListUrl = $('input[name="chapter.danmu_url"]').val();
var playUrls = JSON.parse($('input[name="chapter.play_urls"]').val());
var $danmuText = $('input[name="danmu.text"]');
var $danmuForm = $('.danmu-form');
var playerOptions = {
autoplay: false,
@ -73,13 +74,24 @@ layui.use(['jquery', 'form', 'layer', 'helper'], function () {
*/
$('#player').hover(function () {
clearTimeout(dt);
$('.danmu-form').show();
$danmuForm.show();
}, function () {
dt = setTimeout(function () {
$('.danmu-form').hide();
$danmuForm.hide();
}, 2500);
});
/**
* 文本框获得焦点后清理dt不然对输入有干扰
*/
$danmuText.focus(function () {
clearTimeout(dt);
});
/**
* @todo 弹幕层和播放器控制层css有抵触待解决
*/
$('#danmu').danmu({
left: 20,
top: 20,

View File

@ -1,8 +1,7 @@
layui.use(['jquery', 'layer', 'helper'], function () {
layui.use(['jquery', 'layer'], function () {
var $ = layui.jquery;
var layer = layui.layer;
var helper = layui.helper;
var myShare = {
title: $('input[name="share.title"]').val(),
@ -11,29 +10,6 @@ layui.use(['jquery', 'layer', 'helper'], function () {
qrcode: $('input[name="share.qrcode"]').val()
};
$('.icon-praise').on('click', function () {
var $this = $(this);
var $likeCount = $this.next();
var likeCount = parseInt($likeCount.text());
helper.checkLogin(function () {
$.ajax({
type: 'POST',
url: $this.parent().data('url'),
success: function () {
if ($this.hasClass('active')) {
$this.removeClass('active');
$likeCount.text(likeCount - 1);
likeCount -= 1;
} else {
$this.addClass('active');
$likeCount.text(likeCount + 1);
likeCount += 1;
}
}
});
});
});
$('.icon-wechat').on('click', function () {
var content = '<div class="qrcode"><img src="' + myShare.qrcode + '" alt="分享到微信"></div>';
layer.open({

View File

@ -9,17 +9,20 @@ layui.use(['jquery', 'layer', 'helper'], function () {
*/
$('.icon-star').on('click', function () {
var $this = $(this);
var $parent = $this.parent();
helper.checkLogin(function () {
$.ajax({
type: 'POST',
url: $this.parent().data('url'),
url: $parent.data('url'),
success: function () {
if ($this.hasClass('layui-icon-star-fill')) {
$this.removeClass('layui-icon-star-fill');
$this.addClass('layui-icon-star');
$parent.attr('title', '收藏');
} else {
$this.removeClass('layui-icon-star');
$this.addClass('layui-icon-star-fill');
$parent.attr('title', '取消收藏');
}
}
});
@ -74,19 +77,22 @@ layui.use(['jquery', 'layer', 'helper'], function () {
*/
$('body').on('click', '.icon-praise', function () {
var $this = $(this);
var $parent = $this.parent();
var $likeCount = $this.next();
var likeCount = parseInt($likeCount.text());
helper.checkLogin(function () {
$.ajax({
type: 'POST',
url: $this.parent().data('url'),
url: $parent.data('url'),
success: function () {
if ($this.hasClass('active')) {
$this.removeClass('active');
$parent.attr('title', '点赞');
$likeCount.text(likeCount - 1);
likeCount -= 1;
} else {
$this.addClass('active');
$parent.attr('title', '取消点赞');
$likeCount.text(likeCount + 1);
likeCount += 1;
}