1
0
mirror of https://gitee.com/koogua/course-tencent-cloud.git synced 2025-06-17 15:55:31 +08:00

优化代码

This commit is contained in:
xiaochong0302 2020-09-12 19:57:28 +08:00
parent def5b3605a
commit d9016669e3
49 changed files with 470 additions and 276 deletions

View File

@ -15,7 +15,7 @@ abstract class Cache extends Component
public function __construct()
{
$this->cache = $this->getDI()->get('cache');
$this->cache = $this->getDI()->getShared('cache');
}
/**

View File

@ -20,7 +20,7 @@ abstract class Counter extends Component
public function __construct()
{
$this->cache = $this->getDI()->get('cache');
$this->cache = $this->getDI()->getShared('cache');
$this->redis = $this->cache->getRedis();
}

View File

@ -9,7 +9,7 @@ class CleanSessionTask extends Task
{
$config = $this->getConfig();
$cache = $this->getCache();
$redis = $cache->getRedis();
$redis = $this->getRedis();
$redis->select($config->path('session.db'));

View File

@ -14,7 +14,7 @@ class LiveNotifyTask extends Task
{
$cache = $this->getCache();
$redis = $cache->getRedis();
$redis = $this->getRedis();
$service = new LiveNotifyService();

View File

@ -14,7 +14,7 @@ class SyncCourseIndexTask extends Task
{
$cache = $this->getCache();
$redis = $cache->getRedis();
$redis = $this->getRedis();
$key = $this->getSyncKey();

View File

@ -14,7 +14,7 @@ class SyncGroupIndexTask extends Task
{
$cache = $this->getCache();
$redis = $cache->getRedis();
$redis = $this->getRedis();
$key = $this->getSyncKey();

View File

@ -18,7 +18,7 @@ class SyncLearningTask extends Task
{
$cache = $this->getCache();
$redis = $cache->getRedis();
$redis = $this->getRedis();
$syncer = new LearningSyncer();

View File

@ -14,7 +14,7 @@ class SyncUserIndexTask extends Task
{
$cache = $this->getCache();
$redis = $cache->getRedis();
$redis = $this->getRedis();
$key = $this->getSyncKey();

View File

@ -16,7 +16,7 @@ class Task extends \Phalcon\Cli\Task
*/
public function getConfig()
{
return $this->getDI()->get('config');
return $this->getDI()->getShared('config');
}
/**
@ -24,7 +24,15 @@ class Task extends \Phalcon\Cli\Task
*/
public function getCache()
{
return $this->getDI()->get('cache');
return $this->getDI()->getShared('cache');
}
/**
* @return \Redis
*/
public function getRedis()
{
return $this->getCache()->getRedis();
}
/**

View File

@ -44,7 +44,7 @@ class UpgradeTask extends Task
{
$config = $this->getConfig();
$cache = $this->getCache();
$redis = $cache->getRedis();
$redis = $this->getRedis();
$dbIndex = $config->path('annotation.db');
$statsKey = $config->path('annotation.statsKey');
@ -75,7 +75,7 @@ class UpgradeTask extends Task
{
$config = $this->getConfig();
$cache = $this->getCache();
$redis = $cache->getRedis();
$redis = $this->getRedis();
$dbIndex = $config->path('metadata.db');
$statsKey = $config->path('metadata.statsKey');

View File

@ -27,8 +27,8 @@
<div class="layui-form-item">
<label class="layui-form-label">位置</label>
<div class="layui-input-block">
<input type="radio" name="position" value="top" title="顶部" {% if nav.position == 1 %}checked{% endif %}>
<input type="radio" name="position" value="bottom" title="底部" {% if nav.position == 2 %}checked{% endif %}>
<input type="radio" name="position" value="1" title="顶部" {% if nav.position == 1 %}checked{% endif %}>
<input type="radio" name="position" value="2" title="底部" {% if nav.position == 2 %}checked{% endif %}>
</div>
</div>
<div class="layui-form-item">

View File

@ -7,19 +7,19 @@
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">App ID</label>
<label class="layui-form-label">公众号ID</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="app_id" value="{{ wxpay.app_id }}" lay-verify="required">
<input class="layui-input" type="text" name="app_id" value="{{ wxpay.mp_app_id }}" lay-verify="required">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">Mch ID</label>
<label class="layui-form-label">商户ID</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="mch_id" value="{{ wxpay.mch_id }}" lay-verify="required">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">Private Key</label>
<label class="layui-form-label">支付Key</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="key" value="{{ wxpay.key }}" lay-verify="required">
</div>

View File

@ -2,7 +2,8 @@
{% block content %}
{% set closed_tips_display = site.enabled == 0 ? 'display:block' : 'display:none' %}
{% set closed_tips_display = site.status == 'closed' ? 'display:block' : 'display:none' %}
{% set analytics_script_display = site.analytics_enabled == 1 ? 'display:block' : 'display:none' %}
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.setting.site'}) }}">
<fieldset class="layui-elem-field layui-field-title">
@ -11,8 +12,8 @@
<div class="layui-form-item">
<label class="layui-form-label">站点状态</label>
<div class="layui-input-block">
<input type="radio" name="enabled" value="1" title="正常" lay-filter="status" {% if site.enabled == 1 %}checked{% endif %}>
<input type="radio" name="enabled" value="0" title="关闭" lay-filter="status" {% if site.enabled == 0 %}checked{% endif %}>
<input type="radio" name="status" value="normal" title="正常" lay-filter="status" {% if site.status == 'normal' %}checked{% endif %}>
<input type="radio" name="status" value="closed" title="关闭" lay-filter="status" {% if site.status == 'closed' %}checked{% endif %}>
</div>
</div>
<div id="closed-tips-block" style="{{ closed_tips_display }}">
@ -89,9 +90,18 @@
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">站点统计</label>
<label class="layui-form-label">开启统计</label>
<div class="layui-input-block">
<textarea name="analytics" class="layui-textarea" placeholder="使用百度统计等第三方统计分析站点流量">{{ site.analytics }}</textarea>
<input type="radio" name="analytics_enabled" value="1" title="是" lay-filter="analytics_enabled" {% if site.analytics_enabled == 1 %}checked{% endif %}>
<input type="radio" name="analytics_enabled" value="0" title="否" lay-filter="analytics_enabled" {% if site.analytics_enabled == 0 %}checked{% endif %}>
</div>
</div>
<div id="analytics-script-block" style="{{ analytics_script_display }}">
<div class="layui-form-item">
<label class="layui-form-label">统计代码</label>
<div class="layui-input-block">
<textarea name="analytics_script" class="layui-textarea" placeholder="使用百度统计等第三方统计分析站点流量">{{ site.analytics_script }}</textarea>
</div>
</div>
</div>
<div class="layui-form-item">
@ -117,7 +127,16 @@
form.on('radio(status)', function (data) {
var block = $('#closed-tips-block');
if (data.value === '0') {
if (data.value === 'closed') {
block.show();
} else {
block.hide();
}
});
form.on('radio(analytics_enabled)', function (data) {
var block = $('#analytics-script-block');
if (data.value === '1') {
block.show();
} else {
block.hide();

View File

@ -2,6 +2,7 @@
namespace App\Http\Desktop\Controllers;
use App\Models\ChapterLive as LiveModel;
use App\Models\Course as CourseModel;
use App\Services\Frontend\Chapter\ChapterInfo as ChapterInfoService;
use App\Services\Frontend\Chapter\ChapterLike as ChapterLikeService;
@ -38,12 +39,21 @@ class ChapterController extends Controller
$catalog = $service->handle($chapter['course']['id']);
$this->seo->prependTitle(['章节', $chapter['title'], $chapter['course']['title']]);
$this->seo->setDescription($chapter['summary']);
if (!empty($chapter['summary'])) {
$this->seo->setDescription($chapter['summary']);
}
if ($chapter['model'] == CourseModel::MODEL_VOD) {
$this->view->pick('chapter/vod');
} elseif ($chapter['model'] == CourseModel::MODEL_LIVE) {
$this->view->pick('chapter/live');
if ($chapter['status'] == LiveModel::STATUS_ACTIVE) {
$this->view->pick('chapter/live_active');
} elseif ($chapter['status'] == LiveModel::STATUS_INACTIVE) {
$this->view->pick('chapter/live_inactive');
} elseif ($chapter['status'] == LiveModel::STATUS_FORBID) {
$this->view->pick('chapter/live_forbid');
}
} elseif ($chapter['model'] == CourseModel::MODEL_READ) {
$this->view->pick('chapter/read');
}

View File

@ -60,7 +60,11 @@ class Controller extends \Phalcon\Mvc\Controller
$this->checkCsrfToken();
}
$this->checkRateLimit();
$config = $this->getConfig();
if ($config->path('throttle.enabled')) {
$this->checkRateLimit();
}
return true;
}
@ -149,7 +153,7 @@ class Controller extends \Phalcon\Mvc\Controller
protected function checkSiteStatus()
{
if ($this->siteInfo['enabled'] == 0) {
if ($this->siteInfo['status'] == 'closed') {
$this->dispatcher->forward([
'controller' => 'error',
'action' => 'maintain',

View File

@ -54,6 +54,18 @@ class LiveController extends Controller
return $this->jsonSuccess($stats);
}
/**
* @Get("/{id:[0-9]+}/status", name="desktop.live.status")
*/
public function statusAction($id)
{
$service = new LiveService();
$status = $service->getStatus($id);
return $this->jsonSuccess(['status' => $status]);
}
/**
* @Post("/{id:[0-9]+}/user/bind", name="desktop.live.bind_user")
*/

View File

@ -2,7 +2,6 @@
namespace App\Http\Desktop\Services;
use App\Library\Cache\Backend\Redis as RedisCache;
use App\Services\Frontend\ChapterTrait;
use GatewayClient\Gateway;
@ -32,6 +31,13 @@ class Live extends Service
return $result;
}
public function getStatus($id)
{
$chapterLive = $this->checkChapterLive($id);
return $chapterLive->status;
}
public function getStats($id)
{
$chapter = $this->checkChapter($id);
@ -84,7 +90,7 @@ class Live extends Service
public function sendMessage($id)
{
$chapter = $this->checkChapterCache($id);
$chapter = $this->checkChapter($id);
$user = $this->getLoginUser();
@ -114,7 +120,7 @@ class Live extends Service
$redis = $this->getRedis();
$key = $this->getRedisListKey($id);
$key = $this->getRecentChatKey($id);
$redis->lPush($key, $encodeMessage);
@ -125,11 +131,6 @@ class Live extends Service
return $message;
}
protected function getGroupName($id)
{
return "live_{$id}";
}
protected function getRegisterAddress()
{
$config = $this->getConfig();
@ -139,17 +140,12 @@ class Live extends Service
protected function getRecentChatKey($id)
{
return "live_recent_chat:{$id}";
return "chapter_recent_chat:{$id}";
}
protected function getRedis()
protected function getGroupName($id)
{
/**
* @var RedisCache $cache
*/
$cache = $this->getDI()->get('cache');
return $cache->getRedis();
return "chapter_{$id}";
}
}

View File

@ -2,79 +2,24 @@
{% block content %}
{% set full_chapter_url = full_url({'for':'desktop.chapter.show','id':chapter.id}) %}
{% set course_url = url({'for':'desktop.course.show','id':chapter.course.id}) %}
{% set learning_url = url({'for':'desktop.chapter.learning','id':chapter.id}) %}
{% set live_chats_url = url({'for':'desktop.live.chats','id':chapter.id}) %}
{% set live_stats_url = url({'for':'desktop.live.stats','id':chapter.id}) %}
{% set send_msg_url = url({'for':'desktop.live.send_msg','id':chapter.id}) %}
{% set bind_user_url = url({'for':'desktop.live.bind_user','id':chapter.id}) %}
{% set like_url = url({'for':'desktop.chapter.like','id':chapter.id}) %}
{% set qrcode_url = url({'for':'desktop.qrcode'},{'text':full_chapter_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>
<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>0</em></a>
<a href="javascript:" title="分享到微信" data-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>
</span>
</div>
<div class="layout-main">
<div class="layout-content">
<div class="player-wrap wrap">
<div id="player"></div>
</div>
</div>
<div class="layout-sidebar">
<div class="layui-card chat-wrap">
<div class="layui-card-header">直播讨论</div>
<div class="layui-card-body">
<div class="chat-msg-list" id="chat-msg-list" data-url="{{ live_chats_url }}"></div>
<form class="layui-form chat-msg-form" method="post" action="{{ send_msg_url }}">
{% if auth_user.id > 0 %}
<input class="layui-input" type="text" name="content" maxlength="50" placeholder="快来一起互动吧" lay-verType="tips" lay-verify="required">
{% else %}
<input class="layui-input" type="text" placeholder="登录后才可以发言哦" readonly="readonly">
{% endif %}
<button class="layui-hide" type="submit" lay-submit="true" lay-filter="chat">发送</button>
</form>
</div>
</div>
</div>
</div>
<div class="layui-hide">
<input type="hidden" name="chapter.id" value="{{ chapter.id }}">
<input type="hidden" name="chapter.plan_id" value="{{ chapter.me.plan_id }}">
<input type="hidden" name="chapter.learning_url" value="{{ learning_url }}">
<input type="hidden" name="chapter.play_urls" value='{{ chapter.play_urls|json_encode }}'>
<input type="hidden" name="live_stats_url" value='{{ live_stats_url }}'>
<input type="hidden" name="bind_user_url" value='{{ bind_user_url }}'>
</div>
<div class="layui-hide">
<input type="hidden" name="share.title" value="{{ chapter.course.title }}">
<input type="hidden" name="share.pic" value="{{ chapter.course.cover }}">
<input type="hidden" name="share.url" value="{{ full_chapter_url }}">
<input type="hidden" name="share.qrcode" value="{{ qrcode_url }}">
</div>
{% if chapter.status == 'active' %}
{{ partial('live/live_active') }}
{% elseif chapter.status == 'inactive' %}
{{ partial('live/live_inactive') }}
{% elseif chapter.status =='forbid' %}
{{ partial('live/live_forbid') }}
{% endif %}
{% endblock %}
{% block include_js %}
{{ js_include('https://imgcache.qq.com/open/qcloud/video/vcplayer/TcPlayer-2.3.3.js', false) }}
{{ js_include('desktop/js/chapter.live.player.js') }}
{{ js_include('desktop/js/chapter.live.chat.js') }}
{{ js_include('desktop/js/chapter.action.js') }}
{{ js_include('desktop/js/course.share.js') }}
{% if chapter.status == 'active' %}
{{ js_include('https://imgcache.qq.com/open/qcloud/video/vcplayer/TcPlayer-2.3.3.js', false) }}
{{ js_include('desktop/js/chapter.live.player.js') }}
{{ js_include('desktop/js/chapter.live.chat.js') }}
{{ js_include('desktop/js/chapter.action.js') }}
{{ js_include('desktop/js/course.share.js') }}
{% endif %}
{% endblock %}

View File

@ -0,0 +1,80 @@
{% extends 'templates/main.volt' %}
{% block content %}
{% set full_chapter_url = full_url({'for':'desktop.chapter.show','id':chapter.id}) %}
{% set course_url = url({'for':'desktop.course.show','id':chapter.course.id}) %}
{% set learning_url = url({'for':'desktop.chapter.learning','id':chapter.id}) %}
{% set live_chats_url = url({'for':'desktop.live.chats','id':chapter.id}) %}
{% set live_stats_url = url({'for':'desktop.live.stats','id':chapter.id}) %}
{% set send_msg_url = url({'for':'desktop.live.send_msg','id':chapter.id}) %}
{% set bind_user_url = url({'for':'desktop.live.bind_user','id':chapter.id}) %}
{% set like_url = url({'for':'desktop.chapter.like','id':chapter.id}) %}
{% set qrcode_url = url({'for':'desktop.qrcode'},{'text':full_chapter_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>
<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>0</em></a>
<a href="javascript:" title="分享到微信" data-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>
</span>
</div>
<div class="layout-main">
<div class="layout-content">
<div class="player-wrap wrap">
<div id="player"></div>
</div>
</div>
<div class="layout-sidebar">
<div class="layui-card chat-wrap">
<div class="layui-card-header">直播讨论</div>
<div class="layui-card-body">
<div class="chat-msg-list" id="chat-msg-list" data-url="{{ live_chats_url }}"></div>
<form class="layui-form chat-msg-form" method="post" action="{{ send_msg_url }}">
{% if auth_user.id > 0 %}
<input class="layui-input" type="text" name="content" maxlength="50" placeholder="快来一起互动吧" lay-verType="tips" lay-verify="required">
{% else %}
<input class="layui-input" type="text" placeholder="登录后才可以发言哦" readonly="readonly">
{% endif %}
<button class="layui-hide" type="submit" lay-submit="true" lay-filter="chat">发送</button>
</form>
</div>
</div>
</div>
</div>
<div class="layui-hide">
<input type="hidden" name="chapter.id" value="{{ chapter.id }}">
<input type="hidden" name="chapter.plan_id" value="{{ chapter.me.plan_id }}">
<input type="hidden" name="chapter.learning_url" value="{{ learning_url }}">
<input type="hidden" name="chapter.play_urls" value='{{ chapter.play_urls|json_encode }}'>
<input type="hidden" name="live_stats_url" value='{{ live_stats_url }}'>
<input type="hidden" name="bind_user_url" value='{{ bind_user_url }}'>
</div>
<div class="layui-hide">
<input type="hidden" name="share.title" value="{{ chapter.course.title }}">
<input type="hidden" name="share.pic" value="{{ chapter.course.cover }}">
<input type="hidden" name="share.url" value="{{ full_chapter_url }}">
<input type="hidden" name="share.qrcode" value="{{ qrcode_url }}">
</div>
{% endblock %}
{% block include_js %}
{{ js_include('https://imgcache.qq.com/open/qcloud/video/vcplayer/TcPlayer-2.3.3.js', false) }}
{{ js_include('desktop/js/chapter.live.player.js') }}
{{ js_include('desktop/js/chapter.live.chat.js') }}
{{ js_include('desktop/js/chapter.action.js') }}
{{ js_include('desktop/js/course.share.js') }}
{% endblock %}

View File

@ -0,0 +1,15 @@
{% extends 'templates/main.volt' %}
{% block content %}
{% set course_url = url({'for':'desktop.course.show','id':chapter.course.id}) %}
<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>
</div>
{% endblock %}

View File

@ -0,0 +1,42 @@
{% extends 'templates/main.volt' %}
{% block content %}
{% set course_url = url({'for':'desktop.course.show','id':chapter.course.id}) %}
{% set live_status_url = url({'for':'desktop.live.status','id':chapter.id}) %}
{% set show_countdown = time() < chapter.start_time ? 1 : 0 %}
<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>
</div>
{% if show_countdown == 1 %}
<div class="countdown">
<div class="icon"><i class="layui-icon layui-icon-time"></i></div>
<div class="timer"></div>
<div class="tips">开播倒计时开始啦,敬请关注!</div>
</div>
{% else %}
<div class="countdown">
<div class="icon"><i class="layui-icon layui-icon-face-surprised"></i></div>
<div class="tips">直播已结束,谢谢关注!</div>
</div>
{% endif %}
<div class="layui-hide">
<input type="hidden" name="live.status_url" value="{{ live_status_url }}">
<input type="hidden" name="countdown.end_time" value="{{ chapter.start_time }}">
<input type="hidden" name="countdown.server_time" value="{{ time() }}">
</div>
{% endblock %}
{% block include_js %}
{{ js_include('desktop/js/chapter.live.countdown.js') }}
{% endblock %}

View File

@ -36,8 +36,8 @@
{% block include_js %}{% endblock %}
{% block inline_js %}{% endblock %}
{% if site_info.analytics %}
{{ site_info.analytics }}
{% if site_info.analytics_enabled == 1 %}
{{ site_info.analytics_script }}
{% endif %}
</body>

View File

@ -4,6 +4,7 @@ use App\Caches\Setting as SettingCache;
use App\Library\Validators\Common as CommonValidator;
use App\Services\Storage as StorageService;
use Koogua\Ip2Region\Searcher as Ip2RegionSearcher;
use Phalcon\Config;
use Phalcon\Di;
use Phalcon\Text;
@ -404,12 +405,15 @@ function kg_js_include($path, $local = true, $version = null)
*/
function kg_static_url($path, $local = true, $version = null)
{
/**
* @var Config $config
*/
$config = Di::getDefault()->getShared('config');
$baseUri = rtrim($config->static_base_uri, '/');
$baseUri = rtrim($config->get('static_base_uri'), '/');
$path = ltrim($path, '/');
$url = $local ? $baseUri . '/' . $path : $path;
$version = $version ? $version : $config->static_version;
$version = $version ? $version : $config->get('static_version');
if ($version) {
$url .= '?v=' . $version;

View File

@ -2,6 +2,7 @@
namespace App\Library;
use Phalcon\Config;
use Phalcon\Di;
use Phalcon\Logger as PhLogger;
use Phalcon\Logger\Adapter\File as FileLogger;
@ -15,7 +16,10 @@ class Logger
*/
public function getInstance($channel = null)
{
$config = Di::getDefault()->get('config');
/**
* @var Config $config
*/
$config = Di::getDefault()->getShared('config');
$channel = $channel ? $channel : 'common';
@ -23,7 +27,7 @@ class Logger
$path = log_path($filename);
$level = $config->env != ENV_DEV ? $config->log->level : PhLogger::DEBUG;
$level = $config->get('env') != ENV_DEV ? $config->path('log.level') : PhLogger::DEBUG;
$logger = new FileLogger($path);

View File

@ -21,7 +21,7 @@ class Chapter extends Model
* 推流状态
*/
const SS_ACTIVE = 'active'; // 活跃
const SS_INACTIVE = 'inactive'; // 非活跃
const SS_INACTIVE = 'inactive'; // 静默
const SS_FORBID = 'forbid'; // 禁播
/**

View File

@ -19,7 +19,7 @@ class Api extends AuthService
$config = $this->getConfig();
$expireTime = time() + $config->jwt->lifetime;
$expireTime = time() + $config->path('jwt.lifetime');
$builder->expiresAt($expireTime);
$builder->withClaim('user_id', $user->id);
@ -27,7 +27,7 @@ class Api extends AuthService
$singer = new JwtSingerSha256();
$key = new JwtSingerKey($config->jwt->key);
$key = new JwtSingerKey($config->path('jwt.key'));
$token = $builder->getToken($singer, $key);
@ -51,7 +51,7 @@ class Api extends AuthService
$token = $parser->parse($authToken);
$data = new JWTValidationData(time(), $config->jwt->leeway);
$data = new JWTValidationData(time(), $config->path('jwt.leeway'));
if (!$token->validate($data)) {
return null;
@ -59,7 +59,7 @@ class Api extends AuthService
$singer = new JwtSingerSha256();
if (!$token->verify($singer, $config->jwt->key)) {
if (!$token->verify($singer, $config->path('jwt.key'))) {
return null;
}
@ -76,9 +76,4 @@ class Api extends AuthService
return trim(str_ireplace('Bearer', '', $authorization));
}
protected function getConfig()
{
return $this->getDI()->get('config');
}
}

View File

@ -6,6 +6,7 @@ use App\Models\Chapter as ChapterModel;
use App\Models\Course as CourseModel;
use App\Repos\Chapter as ChapterRepo;
use App\Services\ChapterVod as ChapterVodService;
use App\Services\Frontend\ChapterLiveTrait;
use App\Services\Live as LiveService;
use WhichBrowser\Parser as BrowserParser;
@ -85,6 +86,7 @@ trait BasicInfoTrait
'play_urls' => $playUrls,
'start_time' => $live->start_time,
'end_time' => $live->end_time,
'status' => $live->status,
'user_count' => $chapter->user_count,
'like_count' => $chapter->like_count,
];

View File

@ -1,6 +1,6 @@
<?php
namespace App\Services\Frontend\Chapter;
namespace App\Services\Frontend;
trait ChapterLiveTrait
{

View File

@ -26,6 +26,27 @@ trait ChapterTrait
*/
protected $chapterUser;
public function checkChapterVod($id)
{
$validator = new ChapterValidator();
return $validator->checkChapterVod($id);
}
public function checkChapterLive($id)
{
$validator = new ChapterValidator();
return $validator->checkChapterLive($id);
}
public function checkChapterRead($id)
{
$validator = new ChapterValidator();
return $validator->checkChapterRead($id);
}
public function checkChapter($id)
{
$validator = new ChapterValidator();

View File

@ -2,7 +2,7 @@
namespace App\Services\Frontend\Teaching;
use App\Services\Frontend\Chapter\ChapterLiveTrait;
use App\Services\Frontend\ChapterLiveTrait;
use App\Services\Frontend\ChapterTrait;
use App\Services\Frontend\Service as FrontendService;
use App\Services\Live as LiveService;

View File

@ -2,7 +2,6 @@
namespace App\Services;
use App\Library\Cache\Backend\Redis as RedisCache;
use App\Models\Chapter as ChapterModel;
use App\Models\ChapterLive as ChapterLiveModel;
use App\Repos\Chapter as ChapterRepo;
@ -129,12 +128,9 @@ class LiveNotify extends Service
protected function sendBeginNotify(ChapterModel $chapter)
{
/**
* @var RedisCache $cache
*/
$cache = $this->getDI()->get('cache');
$cache = $this->getCache();
$redis = $cache->getRedis();
$redis = $this->getRedis();
$key = $this->getNotifyKey();

View File

@ -41,11 +41,11 @@ class AlipayGateway extends Service
*/
public function getInstance()
{
$config = $this->getDI()->get('config');
$config = $this->getConfig();
$level = $config->env == ENV_DEV ? 'debug' : 'info';
$level = $config->get('env') == ENV_DEV ? 'debug' : 'info';
$payConfig = [
$options = [
'app_id' => $this->settings['app_id'],
'ali_public_key' => $this->settings['public_key'],
'private_key' => $this->settings['private_key'],
@ -59,11 +59,11 @@ class AlipayGateway extends Service
],
];
if ($config->env == ENV_DEV) {
$payConfig['mode'] = 'dev';
if ($config->get('env') == ENV_DEV) {
$options['mode'] = 'dev';
}
return Pay::alipay($payConfig);
return Pay::alipay($options);
}
}

View File

@ -36,17 +36,19 @@ class WxpayGateway extends Service
*/
public function getInstance()
{
$config = $this->getDI()->get('config');
$config = $this->getConfig();
$level = $config->env == ENV_DEV ? 'debug' : 'info';
$level = $config->get('env') == ENV_DEV ? 'debug' : 'info';
$payConfig = [
'app_id' => $this->settings['app_id'],
$options = [
'appid' => $this->settings['app_id'], // App AppId
'app_id' => $this->settings['mp_app_id'], // 公众号 AppId
'miniapp_id' => $this->settings['mini_app_id'], // 小程序 AppId
'mch_id' => $this->settings['mch_id'],
'key' => $this->settings['key'],
'notify_url' => $this->settings['notify_url'],
'cert_client' => '',
'cert_key' => '',
'cert_client' => config_path('wxpay/client_cert.pem'),
'cert_key' => config_path('wxpay/client_key.pem'),
'log' => [
'file' => log_path('wxpay.log'),
'level' => $level,
@ -55,11 +57,11 @@ class WxpayGateway extends Service
],
];
if ($config->env == ENV_DEV) {
$payConfig['mode'] = 'dev';
if ($config->get('env') == ENV_DEV) {
$options['mode'] = 'dev';
}
return Pay::wechat($payConfig);
return Pay::wechat($options);
}
}

View File

@ -20,7 +20,7 @@ class Service extends Component
*/
public function getConfig()
{
return $this->getDI()->get('config');
return $this->getDI()->getShared('config');
}
/**
@ -28,7 +28,15 @@ class Service extends Component
*/
public function getCache()
{
return $this->getDI()->get('cache');
return $this->getDI()->getShared('cache');
}
/**
* @return \Redis
*/
public function getRedis()
{
return $this->getCache()->getRedis();
}
/**

View File

@ -2,42 +2,26 @@
namespace App\Services\Syncer;
use App\Library\Cache\Backend\Redis as RedisCache;
use App\Services\Service;
class CourseIndex extends Service
{
/**
* @var RedisCache
*/
protected $cache;
/**
* @var \Redis
*/
protected $redis;
/**
* @var int
*/
protected $lifetime = 86400;
public function __construct()
{
$this->cache = $this->getDI()->get('cache');
$this->redis = $this->cache->getRedis();
}
public function addItem($courseId)
{
$redis = $this->getRedis();
$key = $this->getSyncKey();
$this->redis->sAdd($key, $courseId);
$redis->sAdd($key, $courseId);
if ($this->redis->sCard($key) == 1) {
$this->redis->expire($key, $this->lifetime);
if ($redis->sCard($key) == 1) {
$redis->expire($key, $this->lifetime);
}
}

View File

@ -2,42 +2,26 @@
namespace App\Services\Syncer;
use App\Library\Cache\Backend\Redis as RedisCache;
use App\Services\Service;
class GroupIndex extends Service
{
/**
* @var RedisCache
*/
protected $cache;
/**
* @var \Redis
*/
protected $redis;
/**
* @var int
*/
protected $lifetime = 86400;
public function __construct()
{
$this->cache = $this->getDI()->get('cache');
$this->redis = $this->cache->getRedis();
}
public function addItem($groupId)
{
$redis = $this->getRedis();
$key = $this->getSyncKey();
$this->redis->sAdd($key, $groupId);
$redis->sAdd($key, $groupId);
if ($this->redis->sCard($key) == 1) {
$this->redis->expire($key, $this->lifetime);
if ($redis->sCard($key) == 1) {
$redis->expire($key, $this->lifetime);
}
}

View File

@ -2,7 +2,6 @@
namespace App\Services\Syncer;
use App\Library\Cache\Backend\Redis as RedisCache;
use App\Models\Learning as LearningModel;
use App\Services\Service;
use App\Traits\Client as ClientTrait;
@ -12,40 +11,27 @@ class Learning extends Service
use ClientTrait;
/**
* @var RedisCache
*/
protected $cache;
/**
* @var \Redis
*/
protected $redis;
/**
* @var int
*/
protected $lifetime = 86400;
public function __construct()
{
$this->cache = $this->getDI()->get('cache');
$this->redis = $this->cache->getRedis();
}
/**
* @param LearningModel $learning
* @param int $interval
*/
public function addItem(LearningModel $learning, $interval = 10)
{
$cache = $this->getCache();
$redis = $this->getRedis();
$itemKey = $this->getItemKey($learning->request_id);
/**
* @var LearningModel $cacheLearning
*/
$cacheLearning = $this->cache->get($itemKey);
$cacheLearning = $cache->get($itemKey);
if (!$cacheLearning) {
@ -54,7 +40,7 @@ class Learning extends Service
$learning->duration = $interval;
$learning->active_time = time();
$this->cache->save($itemKey, $learning, $this->lifetime);
$cache->save($itemKey, $learning, $this->lifetime);
} else {
@ -62,15 +48,15 @@ class Learning extends Service
$cacheLearning->position = $learning->position;
$cacheLearning->active_time = time();
$this->cache->save($itemKey, $cacheLearning, $this->lifetime);
$cache->save($itemKey, $cacheLearning, $this->lifetime);
}
$key = $this->getSyncKey();
$this->redis->sAdd($key, $learning->request_id);
$redis->sAdd($key, $learning->request_id);
if ($this->redis->sCard($key) == 1) {
$this->redis->expire($key, $this->lifetime);
if ($redis->sCard($key) == 1) {
$redis->expire($key, $this->lifetime);
}
}

View File

@ -2,42 +2,26 @@
namespace App\Services\Syncer;
use App\Library\Cache\Backend\Redis as RedisCache;
use App\Services\Service;
class UserIndex extends Service
{
/**
* @var RedisCache
*/
protected $cache;
/**
* @var \Redis
*/
protected $redis;
/**
* @var int
*/
protected $lifetime = 86400;
public function __construct()
{
$this->cache = $this->getDI()->get('cache');
$this->redis = $this->cache->getRedis();
}
public function addItem($userId)
{
$redis = $this->getRedis();
$key = $this->getSyncKey();
$this->redis->sAdd($key, $userId);
$redis->sAdd($key, $userId);
if ($this->redis->sCard($key) == 1) {
$this->redis->expire($key, $this->lifetime);
if ($redis->sCard($key) == 1) {
$redis->expire($key, $this->lifetime);
}
}

View File

@ -2,23 +2,18 @@
namespace App\Services;
use Phalcon\Cache\Backend\Redis as RedisCache;
class Throttle extends Service
{
public function checkRateLimit()
{
$config = $this->getDI()->get('config');
$config = $this->getConfig();
if ($config->throttle->enabled == false) {
if ($config->path('throttle.enabled') == false) {
return true;
}
/**
* @var RedisCache $cache
*/
$cache = $this->getDI()->get('cache');
$cache = $this->getCache();
$sign = $this->getRequestSignature();
@ -27,13 +22,13 @@ class Throttle extends Service
$rateLimit = $cache->get($cacheKey);
if ($rateLimit) {
if ($rateLimit >= $config->throttle->rate_limit) {
if ($rateLimit >= $config->path('throttle.rate_limit')) {
return false;
} else {
$cache->increment($cacheKey, 1);
}
} else {
$cache->save($cacheKey, 1, $config->throttle->lifetime);
$cache->save($cacheKey, 1, $config->path('throttle.lifetime'));
}
return true;

View File

@ -15,7 +15,7 @@ class Verify extends Service
public function __construct()
{
$this->cache = $this->getDI()->get('cache');
$this->cache = $this->getCache();
}
public function getSmsCode($phone, $lifetime = 300)

View File

@ -43,6 +43,45 @@ class Chapter extends Validator
return $chapter;
}
public function checkChapterVod($id)
{
$chapterRepo = new ChapterRepo();
$chapterVod = $chapterRepo->findChapterVod($id);
if (!$chapterVod) {
throw new BadRequestException('chapter.vod_not_found');
}
return $chapterVod;
}
public function checkChapterLive($id)
{
$chapterRepo = new ChapterRepo();
$chapterLive = $chapterRepo->findChapterLive($id);
if (!$chapterLive) {
throw new BadRequestException('chapter.live_not_found');
}
return $chapterLive;
}
public function checkChapterRead($id)
{
$chapterRepo = new ChapterRepo();
$chapterRead = $chapterRepo->findChapterRead($id);
if (!$chapterRead) {
throw new BadRequestException('chapter.read_not_found');
}
return $chapterRead;
}
public function checkChapter($id)
{
$chapterRepo = new ChapterRepo();

View File

@ -28,22 +28,19 @@ class ChapterLive extends Validator
public function checkTimeRange($startTime, $endTime)
{
$startTimeStamp = strtotime($startTime);
$endTimeStamp = strtotime($endTime);
if ($startTimeStamp < time()) {
if ($startTime < time()) {
throw new BadRequestException('chapter_live.start_lt_now');
}
if ($endTimeStamp < time()) {
if ($startTime < time()) {
throw new BadRequestException('chapter_live.end_lt_now');
}
if ($startTimeStamp >= $endTimeStamp) {
if ($startTime >= $endTime) {
throw new BadRequestException('chapter_live.start_gt_end');
}
if ($endTimeStamp - $startTimeStamp > 3 * 3600) {
if ($endTime - $startTime > 3 * 3600) {
throw new BadRequestException('chapter_live.time_too_long');
}
}

View File

@ -12,7 +12,7 @@ define('ENV_PRO', 'pro');
*/
function root_path($path = '')
{
return dirname(__DIR__) . ($path ? "/{$path}" : '');
return dirname(__DIR__) . trim_path($path);
}
/**
@ -23,7 +23,7 @@ function root_path($path = '')
*/
function app_path($path = '')
{
return root_path('app') . ($path ? "/{$path}" : '');
return root_path('app') . trim_path($path);
}
/**
@ -34,7 +34,7 @@ function app_path($path = '')
*/
function bootstrap_path($path = '')
{
return root_path('bootstrap') . ($path ? "/{$path}" : '');
return root_path('bootstrap') . trim_path($path);
}
/**
@ -45,7 +45,7 @@ function bootstrap_path($path = '')
*/
function config_path($path = '')
{
return root_path('config') . ($path ? "/{$path}" : '');
return root_path('config') . trim_path($path);
}
/**
@ -56,7 +56,7 @@ function config_path($path = '')
*/
function storage_path($path = '')
{
return root_path('storage') . ($path ? "/{$path}" : '');
return root_path('storage') . trim_path($path);
}
/**
@ -67,7 +67,7 @@ function storage_path($path = '')
*/
function vendor_path($path = '')
{
return root_path('vendor') . ($path ? "/{$path}" : '');
return root_path('vendor') . trim_path($path);
}
/**
@ -78,7 +78,7 @@ function vendor_path($path = '')
*/
function public_path($path = '')
{
return root_path('public') . ($path ? "/{$path}" : '');
return root_path('public') . trim_path($path);
}
/**
@ -89,7 +89,7 @@ function public_path($path = '')
*/
function cache_path($path = '')
{
return storage_path('cache') . ($path ? "/{$path}" : '');
return storage_path('cache') . trim_path($path);
}
/**
@ -100,7 +100,7 @@ function cache_path($path = '')
*/
function log_path($path = '')
{
return storage_path('log') . ($path ? "/{$path}" : '');
return storage_path('log') . trim_path($path);
}
/**
@ -111,18 +111,20 @@ function log_path($path = '')
*/
function tmp_path($path = '')
{
return storage_path('tmp') . ($path ? "/{$path}" : '');
return storage_path('tmp') . trim_path($path);
}
/**
* Rtrim slash
*
* @param string $str
* @param string $path
* @return string
*/
function rtrim_slash($str)
function trim_path($path)
{
return rtrim($str, '/');
$path = trim($path, '/');
return $path ? "/{$path}" : '';
}
/**

2
config/alipay/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.gitignore
!.gitignore

View File

@ -1,2 +0,0 @@
*
!.gitignore

View File

@ -1,2 +0,0 @@
*
!.gitignore

2
config/wxpay/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.gitignore
!.gitignore

View File

@ -909,6 +909,34 @@ body {
color: #666;
}
.countdown {
color: #666;
margin-top: 50px;
text-align: center;
}
.countdown .icon {
margin-bottom: 10px;
}
.countdown .icon .layui-icon {
font-size: 150px;
}
.countdown .tips {
font-size: 18px;
margin: 20px 0;
}
.countdown .timer {
font-size: 32px;
}
.countdown .timer span {
color: green;
padding: 10px;
}
.player-wrap {
position: relative;
width: 760px;

View File

@ -0,0 +1,32 @@
layui.use(['jquery', 'util'], function () {
var $ = layui.jquery;
var util = layui.util;
var endTime = $('input[name="countdown.end_time"]').val();
var serverTime = $('input[name="countdown.server_time"]').val();
var liveStatusUrl = $('input[name="live.status_url"]').val();
util.countdown(1000 * parseInt(endTime), 1000 * parseInt(serverTime), function (date, serverTime, timer) {
var items = [
{date: date[0], label: '天'},
{date: date[1], label: '时'},
{date: date[2], label: '分'},
{date: date[3], label: '秒'}
];
var html = '';
layui.each(items, function (index, item) {
html += '<span>' + item.date + '</span>' + item.label;
});
$('.countdown > .timer').html(html);
});
setInterval(function () {
$.get(liveStatusUrl, function (res) {
if (res.status === 1) {
window.location.reload();
}
});
}, 30000);
});