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

Merge branch 'koogua/v1.4.6' into demo

# Conflicts:
#	app/Http/Admin/Controllers/Controller.php
#	app/Services/Auth/Api.php
#	app/Services/Auth/Home.php
This commit is contained in:
koogua 2021-10-16 16:24:51 +08:00
commit f9f1d1129a
57 changed files with 740 additions and 284 deletions

View File

@ -1,3 +1,16 @@
### [v1.4.6](https://gitee.com/koogua/course-tencent-cloud/releases/v1.4.6)(2021-10-09)
- 完善首页文章缓存的获取条件
- 完善热门专题的获取条件
- 优化课程章节列表逻辑
- 更新教学中心我的课程获取逻辑
- 修正后台点播和面授类型课时列表宽度未100%铺满问题
- 完善添加积分礼品的逻辑
- 修正编辑课程类型礼品时编辑器初始化js报错
- 修正非root用户后台添加用户时报错
- 手机端访问web端地址自动跳转到手机端
- 增加锁定用户逻辑(会自动登出锁定用户)
### [v1.4.5](https://gitee.com/koogua/course-tencent-cloud/releases/v1.4.5)(2021-09-27) ### [v1.4.5](https://gitee.com/koogua/course-tencent-cloud/releases/v1.4.5)(2021-09-27)
- 修正点击内容分享到微信会额外出现公众号二维码的问题 - 修正点击内容分享到微信会额外出现公众号二维码的问题

View File

@ -29,9 +29,15 @@
演示账号100015@163.com / 123456 (前后台通用) 演示账号100015@163.com / 123456 (前后台通用)
移动端演示: H5手机端演示:
![移动端二维码](https://images.gitee.com/uploads/images/2020/1127/093203_265221a2_23592.png) ![H5二维码](https://images.gitee.com/uploads/images/2021/1011/091358_05e79898_23592.png)
演示账号13507083515 / 123456
微信公众号演示:
![公众号二维码](https://images.gitee.com/uploads/images/2021/1011/090813_3b88ecc3_23592.jpeg)
演示账号13507083515 / 123456 演示账号13507083515 / 123456

View File

@ -64,6 +64,7 @@ class CourseTopicList extends Cache
{ {
return TopicModel::query() return TopicModel::query()
->where('published = 1') ->where('published = 1')
->andWhere('deleted = 0')
->orderBy('RAND()') ->orderBy('RAND()')
->limit($limit) ->limit($limit)
->execute(); ->execute();

View File

@ -32,6 +32,7 @@ class IndexArticleList extends Cache
$where = [ $where = [
'published' => ArticleModel::PUBLISH_APPROVED, 'published' => ArticleModel::PUBLISH_APPROVED,
'private' => 0,
'deleted' => 0, 'deleted' => 0,
]; ];

View File

@ -26,7 +26,7 @@ class ArticleController extends Controller
['type' => CategoryModel::TYPE_ARTICLE] ['type' => CategoryModel::TYPE_ARTICLE]
); );
$this->response->redirect($location); return $this->response->redirect($location);
} }
/** /**

View File

@ -8,6 +8,8 @@
namespace App\Http\Admin\Controllers; namespace App\Http\Admin\Controllers;
use App\Models\Audit as AuditModel; use App\Models\Audit as AuditModel;
use App\Models\Role as RoleModel;
use App\Models\User as UserModel;
use App\Services\Auth\Admin as AdminAuth; use App\Services\Auth\Admin as AdminAuth;
use App\Traits\Response as ResponseTrait; use App\Traits\Response as ResponseTrait;
use App\Traits\Security as SecurityTrait; use App\Traits\Security as SecurityTrait;
@ -21,6 +23,11 @@ class Controller extends \Phalcon\Mvc\Controller
*/ */
protected $authInfo; protected $authInfo;
/**
* @var UserModel
*/
protected $authUser;
use ResponseTrait; use ResponseTrait;
use SecurityTrait; use SecurityTrait;
@ -41,6 +48,8 @@ class Controller extends \Phalcon\Mvc\Controller
return false; return false;
} }
$this->authUser = $this->getAuthUser();
/** /**
* demo分支拒绝数据提交100001帐号除外 * demo分支拒绝数据提交100001帐号除外
*/ */
@ -53,9 +62,9 @@ class Controller extends \Phalcon\Mvc\Controller
} }
/** /**
* 管理员忽略权限检查 * root用户忽略权限检查
*/ */
if ($this->authInfo['root'] == 1) { if ($this->authUser->admin_role == RoleModel::ROLE_ROOT) {
return true; return true;
} }
@ -101,7 +110,7 @@ class Controller extends \Phalcon\Mvc\Controller
public function initialize() public function initialize()
{ {
$this->view->setVar('auth_info', $this->authInfo); $this->view->setVar('auth_user', $this->authUser);
} }
public function afterExecuteRoute(Dispatcher $dispatcher) public function afterExecuteRoute(Dispatcher $dispatcher)
@ -110,8 +119,8 @@ class Controller extends \Phalcon\Mvc\Controller
$audit = new AuditModel(); $audit = new AuditModel();
$audit->user_id = $this->authInfo['id']; $audit->user_id = $this->authUser->id;
$audit->user_name = $this->authInfo['name']; $audit->user_name = $this->authUser->name;
$audit->user_ip = $this->request->getClientAddress(); $audit->user_ip = $this->request->getClientAddress();
$audit->req_route = $this->router->getMatchedRoute()->getName(); $audit->req_route = $this->router->getMatchedRoute()->getName();
$audit->req_path = $this->request->getServer('REQUEST_URI'); $audit->req_path = $this->request->getServer('REQUEST_URI');
@ -131,4 +140,14 @@ class Controller extends \Phalcon\Mvc\Controller
return $auth->getAuthInfo(); return $auth->getAuthInfo();
} }
protected function getAuthUser()
{
/**
* @var AdminAuth $auth
*/
$auth = $this->getDI()->get('auth');
return $auth->getCurrentUser();
}
} }

View File

@ -26,7 +26,7 @@ class CourseController extends Controller
['type' => CategoryModel::TYPE_COURSE] ['type' => CategoryModel::TYPE_COURSE]
); );
$this->response->redirect($location); return $this->response->redirect($location);
} }
/** /**

View File

@ -26,7 +26,7 @@ class HelpController extends Controller
['type' => CategoryModel::TYPE_HELP] ['type' => CategoryModel::TYPE_HELP]
); );
$this->response->redirect($location); return $this->response->redirect($location);
} }
/** /**

View File

@ -28,7 +28,7 @@ class PublicController extends \Phalcon\Mvc\Controller
return $this->jsonError(['msg' => '会话已过期,请重新登录']); return $this->jsonError(['msg' => '会话已过期,请重新登录']);
} }
$this->response->redirect(['for' => 'admin.login']); return $this->response->redirect(['for' => 'admin.login']);
} }
/** /**

View File

@ -26,7 +26,7 @@ class QuestionController extends Controller
['type' => CategoryModel::TYPE_ARTICLE] ['type' => CategoryModel::TYPE_ARTICLE]
); );
$this->response->redirect($location); return $this->response->redirect($location);
} }
/** /**

View File

@ -31,7 +31,7 @@ class SessionController extends \Phalcon\Mvc\Controller
$user = $this->getCurrentUser(); $user = $this->getCurrentUser();
if ($user->id > 0) { if ($user->id > 0) {
$this->response->redirect(['for' => 'admin.index']); return $this->response->redirect(['for' => 'admin.index']);
} }
$sessionService = new SessionService(); $sessionService = new SessionService();
@ -66,7 +66,7 @@ class SessionController extends \Phalcon\Mvc\Controller
$sessionService->logout(); $sessionService->logout();
$this->response->redirect(['for' => 'admin.login']); return $this->response->redirect(['for' => 'admin.login']);
} }
} }

View File

@ -62,7 +62,7 @@ class UserController extends Controller
$adminRole = $this->request->getPost('admin_role', 'int', 0); $adminRole = $this->request->getPost('admin_role', 'int', 0);
if ($adminRole == RoleModel::ROLE_ROOT) { if ($adminRole == RoleModel::ROLE_ROOT) {
$this->response->redirect(['action' => 'list']); return $this->response->redirect(['action' => 'list']);
} }
$userService = new UserService(); $userService = new UserService();
@ -91,7 +91,7 @@ class UserController extends Controller
$adminRoles = $userService->getAdminRoles(); $adminRoles = $userService->getAdminRoles();
if ($user->admin_role == RoleModel::ROLE_ROOT) { if ($user->admin_role == RoleModel::ROLE_ROOT) {
$this->response->redirect(['for' => 'admin.user.list']); return $this->response->redirect(['for' => 'admin.user.list']);
} }
$this->view->setVar('user', $user); $this->view->setVar('user', $user);
@ -119,7 +119,7 @@ class UserController extends Controller
$adminRole = $this->request->getPost('admin_role', 'int', 0); $adminRole = $this->request->getPost('admin_role', 'int', 0);
if ($adminRole == RoleModel::ROLE_ROOT) { if ($adminRole == RoleModel::ROLE_ROOT) {
$this->response->redirect(['action' => 'list']); return $this->response->redirect(['action' => 'list']);
} }
$type = $this->request->getPost('type', 'string', 'user'); $type = $this->request->getPost('type', 'string', 'user');

View File

@ -25,7 +25,11 @@ class PointGift extends Service
{ {
$courseRepo = new CourseRepo(); $courseRepo = new CourseRepo();
$where = ['free' => 0, 'published' => 1]; $where = [
'free' => 0,
'published' => 1,
'deleted' => 0,
];
$pager = $courseRepo->paginate($where, $sort = 'latest', 1, 10000); $pager = $courseRepo->paginate($where, $sort = 'latest', 1, 10000);
@ -162,10 +166,22 @@ class PointGift extends Service
$course = $validator->checkCourse($post['xm_course_id']); $course = $validator->checkCourse($post['xm_course_id']);
$giftRepo = new PointGiftRepo();
$gift = $giftRepo->findByCourseId($course->id);
if ($gift) return $gift;
$gift = new PointGiftModel(); $gift = new PointGiftModel();
$gift->type = PointGiftModel::TYPE_COURSE; $gift->type = PointGiftModel::TYPE_COURSE;
$gift->name = $course->title; $gift->name = $course->title;
$gift->cover = $course->cover;
$gift->attrs = [
'id' => $course->id,
'title' => $course->title,
'price' => $course->market_price,
];
$gift->create(); $gift->create();

View File

@ -26,28 +26,30 @@ class Session extends Service
public function login() public function login()
{ {
$currentUser = $this->getCurrentUser(); $user = $this->getCurrentUser();
if ($currentUser->id > 0) { if ($user->id > 0) {
$this->response->redirect(['for' => 'home.index']); return $this->response->redirect(['for' => 'home.index']);
} }
$post = $this->request->getPost(); $post = $this->request->getPost();
$accountValidator = new AccountValidator(); $validator = new AccountValidator();
$user = $accountValidator->checkAdminLogin($post['account'], $post['password']); $user = $validator->checkAdminLogin($post['account'], $post['password']);
$captchaSettings = $this->getSettings('captcha'); $validator->checkIfAllowLogin($user);
$captcha = $this->getSettings('captcha');
/** /**
* 验证码是一次性的,放到最后检查,减少第三方调用 * 验证码是一次性的,放到最后检查,减少第三方调用
*/ */
if ($captchaSettings['enabled'] == 1) { if ($captcha['enabled'] == 1) {
$captchaValidator = new CaptchaValidator(); $validator = new CaptchaValidator();
$captchaValidator->checkCode($post['ticket'], $post['rand']); $validator->checkCode($post['ticket'], $post['rand']);
} }
$this->auth->saveAuthInfo($user); $this->auth->saveAuthInfo($user);

View File

@ -18,6 +18,8 @@ use App\Repos\Account as AccountRepo;
use App\Repos\Online as OnlineRepo; use App\Repos\Online as OnlineRepo;
use App\Repos\Role as RoleRepo; use App\Repos\Role as RoleRepo;
use App\Repos\User as UserRepo; use App\Repos\User as UserRepo;
use App\Services\Auth\Api as ApiAuth;
use App\Services\Auth\Home as HomeAuth;
use App\Validators\Account as AccountValidator; use App\Validators\Account as AccountValidator;
use App\Validators\User as UserValidator; use App\Validators\User as UserValidator;
@ -209,6 +211,10 @@ class User extends Service
$user->update($data); $user->update($data);
if ($user->locked == 1) {
$this->destroyUserLogin($user);
}
if ($oldAdminRole > 0) { if ($oldAdminRole > 0) {
$this->updateAdminUserCount($oldAdminRole); $this->updateAdminUserCount($oldAdminRole);
} }
@ -271,6 +277,17 @@ class User extends Service
$cache->rebuild($user->id); $cache->rebuild($user->id);
} }
protected function destroyUserLogin(UserModel $user)
{
$homeAuth = new HomeAuth();
$homeAuth->logoutClients($user->id);
$apiAuth = new ApiAuth();
$apiAuth->logoutClients($user->id);
}
protected function updateAdminUserCount($roleId) protected function updateAdminUserCount($roleId)
{ {
$roleRepo = new RoleRepo(); $roleRepo = new RoleRepo();

View File

@ -15,7 +15,6 @@
<col> <col>
<col> <col>
<col> <col>
<col>
<col width="12%"> <col width="12%">
</colgroup> </colgroup>
<thead> <thead>

View File

@ -23,7 +23,6 @@
<col> <col>
<col> <col>
<col> <col>
<col>
<col width="10%"> <col width="10%">
</colgroup> </colgroup>
<thead> <thead>

View File

@ -29,7 +29,7 @@
</ul> </ul>
<ul class="layui-nav layui-layout-right"> <ul class="layui-nav layui-layout-right">
<li class="layui-nav-item"> <li class="layui-nav-item">
<a href="javascript:">{{ auth_info.name }}</a> <a href="javascript:">{{ auth_user.name }}</a>
<dl class="layui-nav-child"> <dl class="layui-nav-child">
<dd><a href="{{ url({'for':'home.uc.profile'}) }}" target="_blank">基本资料</a></dd> <dd><a href="{{ url({'for':'home.uc.profile'}) }}" target="_blank">基本资料</a></dd>
<dd><a href="{{ url({'for':'home.uc.account'}) }}" target="_blank">安全设置</a></dd> <dd><a href="{{ url({'for':'home.uc.account'}) }}" target="_blank">安全设置</a></dd>
@ -62,9 +62,6 @@
<div class="layui-body"> <div class="layui-body">
<iframe name="content" style="width:100%;height:100%;border:0;" src="{{ url({'for':'admin.main'}) }}"></iframe> <iframe name="content" style="width:100%;height:100%;border:0;" src="{{ url({'for':'admin.main'}) }}"></iframe>
</div> </div>
<div class="layui-copyright">
Powered by <a href="{{ app_info.link }}" title="{{ app_info.name }}" target="_blank">{{ app_info.alias }} {{ app_info.version }}</a>
</div>
</div> </div>
</body> </body>
</html> </html>

View File

@ -10,7 +10,7 @@
<label class="layui-form-label">礼品类型</label> <label class="layui-form-label">礼品类型</label>
<div class="layui-input-block"> <div class="layui-input-block">
{% for value,title in types %} {% for value,title in types %}
<input type="radio" name="item_type" value="{{ value }}" title="{{ title }}" lay-filter="type"> <input type="radio" name="type" value="{{ value }}" title="{{ title }}" lay-filter="type">
{% endfor %} {% endfor %}
</div> </div>
</div> </div>

View File

@ -14,14 +14,18 @@
{% block link_css %} {% block link_css %}
{{ css_link('https://cdn.jsdelivr.net/npm/vditor/dist/index.css', false) }} {% if gift.type == 2 %}
{{ css_link('https://cdn.jsdelivr.net/npm/vditor/dist/index.css', false) }}
{% endif %}
{% endblock %} {% endblock %}
{% block include_js %} {% block include_js %}
{{ js_include('https://cdn.jsdelivr.net/npm/vditor/dist/index.min.js', false) }} {% if gift.type == 2 %}
{{ js_include('admin/js/cover.upload.js') }} {{ js_include('https://cdn.jsdelivr.net/npm/vditor/dist/index.min.js', false) }}
{{ js_include('admin/js/vditor.js') }} {{ js_include('admin/js/cover.upload.js') }}
{{ js_include('admin/js/vditor.js') }}
{% endif %}
{% endblock %} {% endblock %}

View File

@ -10,7 +10,7 @@
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">课程名称</label> <label class="layui-form-label">课程名称</label>
<div class="layui-form-mid layui-word-aux">{{ gift.name }}</div> <div class="layui-form-mid layui-word-aux">{{ gift.name }}{{ '¥%0.2f'|format(gift.attrs['price']) }}</div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">所需积分</label> <label class="layui-form-label">所需积分</label>
@ -24,6 +24,13 @@
<input class="layui-input" type="text" name="stock" value="{{ gift.stock }}" lay-verify="number"> <input class="layui-input" type="text" name="stock" value="{{ gift.stock }}" lay-verify="number">
</div> </div>
</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 gift.published == 1 %}checked="checked"{% endif %}>
<input type="radio" name="published" value="0" title="否" {% if gift.published == 0 %}checked="checked"{% endif %}>
</div>
</div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label"></label> <label class="layui-form-label"></label>
<div class="layui-input-block"> <div class="layui-input-block">

View File

@ -49,6 +49,13 @@
<input class="layui-input" type="text" name="redeem_limit" value="{{ gift.redeem_limit }}" lay-verify="number"> <input class="layui-input" type="text" name="redeem_limit" value="{{ gift.redeem_limit }}" lay-verify="number">
</div> </div>
</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 gift.published == 1 %}checked="checked"{% endif %}>
<input type="radio" name="published" value="0" title="否" {% if gift.published == 0 %}checked="checked"{% endif %}>
</div>
</div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label"></label> <label class="layui-form-label"></label>
<div class="layui-input-block"> <div class="layui-input-block">

View File

@ -25,19 +25,19 @@
<input type="radio" name="edu_role" value="2" title="讲师"> <input type="radio" name="edu_role" value="2" title="讲师">
</div> </div>
</div> </div>
{% if auth_info.root == 1 %} <div class="layui-form-item">
<div class="layui-form-item"> <label class="layui-form-label">后台角色</label>
<label class="layui-form-label">后台角色</label> <div class="layui-input-block">
<div class="layui-input-block"> <input type="radio" name="admin_role" value="0" title="无" checked="checked">
<input type="radio" name="admin_role" value="0" title="无" checked="checked"> {% if auth_user.admin_role == 1 %}
{% for role in admin_roles %} {% for role in admin_roles %}
{% if role.id > 1 %} {% if role.id > 1 %}
<input type="radio" name="admin_role" value="{{ role.id }}" title="{{ role.name }}"> <input type="radio" name="admin_role" value="{{ role.id }}" title="{{ role.name }}">
{% endif %} {% endif %}
{% endfor %} {% endfor %}
</div> {% endif %}
</div> </div>
{% endif %} </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label"></label> <label class="layui-form-label"></label>
<div class="layui-input-block"> <div class="layui-input-block">

View File

@ -33,7 +33,7 @@
<input type="radio" name="edu_role" value="2" title="讲师" {% if user.edu_role == 2 %}checked="checked"{% endif %}> <input type="radio" name="edu_role" value="2" title="讲师" {% if user.edu_role == 2 %}checked="checked"{% endif %}>
</div> </div>
</div> </div>
{% if auth_info.root == 1 %} {% if auth_user.admin_role == 1 %}
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">后台角色</label> <label class="layui-form-label">后台角色</label>
<div class="layui-input-block"> <div class="layui-input-block">
@ -75,7 +75,7 @@
</div> </div>
</form> </form>
{% if auth_info.root == 1 %} {% if auth_user.admin_role == 1 %}
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.user.update','id':user.id}) }}"> <form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.user.update','id':user.id}) }}">
<fieldset class="layui-elem-field layui-field-title"> <fieldset class="layui-elem-field layui-field-title">
<legend>编辑帐号</legend> <legend>编辑帐号</legend>

View File

@ -59,6 +59,8 @@ class Account extends Service
$user = $validator->checkUserLogin($post['account'], $post['password']); $user = $validator->checkUserLogin($post['account'], $post['password']);
$validator->checkIfAllowLogin($user);
$token = $this->auth->saveAuthInfo($user); $token = $this->auth->saveAuthInfo($user);
$this->eventsManager->fire('Account:afterLogin', $this, $user); $this->eventsManager->fire('Account:afterLogin', $this, $user);
@ -83,6 +85,8 @@ class Account extends Service
$user = $validator->checkVerifyLogin($post['account'], $post['verify_code']); $user = $validator->checkVerifyLogin($post['account'], $post['verify_code']);
$validator->checkIfAllowLogin($user);
$token = $this->auth->saveAuthInfo($user); $token = $this->auth->saveAuthInfo($user);
$this->eventsManager->fire('Account:afterLogin', $this, $user); $this->eventsManager->fire('Account:afterLogin', $this, $user);

View File

@ -8,6 +8,7 @@
namespace App\Http\Home\Controllers; namespace App\Http\Home\Controllers;
use App\Http\Home\Services\Account as AccountService; use App\Http\Home\Services\Account as AccountService;
use App\Http\Home\Services\FullH5Url as FullH5UrlService;
use App\Services\Logic\Account\EmailUpdate as EmailUpdateService; use App\Services\Logic\Account\EmailUpdate as EmailUpdateService;
use App\Services\Logic\Account\OAuthProvider as OAuthProviderService; use App\Services\Logic\Account\OAuthProvider as OAuthProviderService;
use App\Services\Logic\Account\PasswordReset as PasswordResetService; use App\Services\Logic\Account\PasswordReset as PasswordResetService;
@ -22,8 +23,15 @@ class AccountController extends Controller
*/ */
public function registerAction() public function registerAction()
{ {
$service = new FullH5UrlService();
if ($service->isMobileBrowser() && $service->h5Enabled()) {
$location = $service->getAccountRegisterUrl();
return $this->response->redirect($location);
}
if ($this->authUser->id > 0) { if ($this->authUser->id > 0) {
$this->response->redirect('/'); return $this->response->redirect('/');
} }
$returnUrl = $this->request->getHTTPReferer(); $returnUrl = $this->request->getHTTPReferer();
@ -67,8 +75,15 @@ class AccountController extends Controller
*/ */
public function loginAction() public function loginAction()
{ {
$service = new FullH5UrlService();
if ($service->isMobileBrowser() && $service->h5Enabled()) {
$location = $service->getAccountLoginUrl();
return $this->response->redirect($location);
}
if ($this->authUser->id > 0) { if ($this->authUser->id > 0) {
$this->response->redirect('/'); return $this->response->redirect('/');
} }
$service = new AccountService(); $service = new AccountService();
@ -129,7 +144,7 @@ class AccountController extends Controller
$service->logout(); $service->logout();
$this->response->redirect(['for' => 'home.index']); return $this->response->redirect(['for' => 'home.index']);
} }
/** /**
@ -137,8 +152,15 @@ class AccountController extends Controller
*/ */
public function forgetPasswordAction() public function forgetPasswordAction()
{ {
$service = new FullH5UrlService();
if ($service->isMobileBrowser() && $service->h5Enabled()) {
$location = $service->getAccountForgetUrl();
return $this->response->redirect($location);
}
if ($this->authUser->id > 0) { if ($this->authUser->id > 0) {
$this->response->redirect(['for' => 'home.index']); return $this->response->redirect(['for' => 'home.index']);
} }
$service = new AccountService(); $service = new AccountService();

View File

@ -8,6 +8,7 @@
namespace App\Http\Home\Controllers; namespace App\Http\Home\Controllers;
use App\Http\Home\Services\Answer as AnswerService; use App\Http\Home\Services\Answer as AnswerService;
use App\Http\Home\Services\FullH5Url as FullH5UrlService;
use App\Http\Home\Services\Question as QuestionService; use App\Http\Home\Services\Question as QuestionService;
use App\Models\Answer as AnswerModel; use App\Models\Answer as AnswerModel;
use App\Services\Logic\Answer\AnswerAccept as AnswerAcceptService; use App\Services\Logic\Answer\AnswerAccept as AnswerAcceptService;
@ -53,6 +54,13 @@ class AnswerController extends Controller
*/ */
public function showAction($id) public function showAction($id)
{ {
$service = new FullH5UrlService();
if ($service->isMobileBrowser() && $service->h5Enabled()) {
$location = $service->getAnswerInfoUrl($id);
return $this->response->redirect($location);
}
$service = new AnswerInfoService(); $service = new AnswerInfoService();
$answer = $service->handle($id); $answer = $service->handle($id);
@ -75,7 +83,7 @@ class AnswerController extends Controller
['answer_id' => $id], ['answer_id' => $id],
); );
$this->response->redirect($location); return $this->response->redirect($location);
} }
/** /**

View File

@ -9,6 +9,7 @@ namespace App\Http\Home\Controllers;
use App\Http\Home\Services\Article as ArticleService; use App\Http\Home\Services\Article as ArticleService;
use App\Http\Home\Services\ArticleQuery as ArticleQueryService; use App\Http\Home\Services\ArticleQuery as ArticleQueryService;
use App\Http\Home\Services\FullH5Url as FullH5UrlService;
use App\Models\Article as ArticleModel; use App\Models\Article as ArticleModel;
use App\Services\Logic\Article\ArticleClose as ArticleCloseService; use App\Services\Logic\Article\ArticleClose as ArticleCloseService;
use App\Services\Logic\Article\ArticleCreate as ArticleCreateService; use App\Services\Logic\Article\ArticleCreate as ArticleCreateService;
@ -33,6 +34,13 @@ class ArticleController extends Controller
*/ */
public function listAction() public function listAction()
{ {
$service = new FullH5UrlService();
if ($service->isMobileBrowser() && $service->h5Enabled()) {
$location = $service->getArticleListUrl();
return $this->response->redirect($location);
}
$service = new ArticleQueryService(); $service = new ArticleQueryService();
$sorts = $service->handleSorts(); $sorts = $service->handleSorts();
@ -101,6 +109,13 @@ class ArticleController extends Controller
*/ */
public function showAction($id) public function showAction($id)
{ {
$service = new FullH5UrlService();
if ($service->isMobileBrowser() && $service->h5Enabled()) {
$location = $service->getArticleInfoUrl($id);
return $this->response->redirect($location);
}
$service = new ArticleInfoService(); $service = new ArticleInfoService();
$article = $service->handle($id); $article = $service->handle($id);

View File

@ -7,6 +7,7 @@
namespace App\Http\Home\Controllers; namespace App\Http\Home\Controllers;
use App\Http\Home\Services\FullH5Url as FullH5UrlService;
use App\Models\ChapterLive as LiveModel; use App\Models\ChapterLive as LiveModel;
use App\Models\Course as CourseModel; use App\Models\Course as CourseModel;
use App\Services\Logic\Chapter\ChapterInfo as ChapterInfoService; use App\Services\Logic\Chapter\ChapterInfo as ChapterInfoService;
@ -39,6 +40,13 @@ class ChapterController extends Controller
*/ */
public function showAction($id) public function showAction($id)
{ {
$service = new FullH5UrlService();
if ($service->isMobileBrowser() && $service->h5Enabled()) {
$location = $service->getChapterInfoUrl($id);
return $this->response->redirect($location);
}
if ($this->authUser->id == 0) { if ($this->authUser->id == 0) {
return $this->response->redirect(['for' => 'home.account.login']); return $this->response->redirect(['for' => 'home.account.login']);
} }

View File

@ -8,6 +8,7 @@
namespace App\Http\Home\Controllers; namespace App\Http\Home\Controllers;
use App\Http\Home\Services\CourseQuery as CourseQueryService; use App\Http\Home\Services\CourseQuery as CourseQueryService;
use App\Http\Home\Services\FullH5Url as FullH5UrlService;
use App\Services\Logic\Course\ChapterList as CourseChapterListService; use App\Services\Logic\Course\ChapterList as CourseChapterListService;
use App\Services\Logic\Course\ConsultList as CourseConsultListService; use App\Services\Logic\Course\ConsultList as CourseConsultListService;
use App\Services\Logic\Course\CourseFavorite as CourseFavoriteService; use App\Services\Logic\Course\CourseFavorite as CourseFavoriteService;
@ -32,6 +33,13 @@ class CourseController extends Controller
*/ */
public function listAction() public function listAction()
{ {
$service = new FullH5UrlService();
if ($service->isMobileBrowser() && $service->h5Enabled()) {
$location = $service->getCourseListUrl();
return $this->response->redirect($location);
}
$service = new CourseQueryService(); $service = new CourseQueryService();
$topCategories = $service->handleTopCategories(); $topCategories = $service->handleTopCategories();
@ -73,6 +81,13 @@ class CourseController extends Controller
*/ */
public function showAction($id) public function showAction($id)
{ {
$service = new FullH5UrlService();
if ($service->isMobileBrowser() && $service->h5Enabled()) {
$location = $service->getCourseInfoUrl($id);
return $this->response->redirect($location);
}
$service = new CourseInfoService(); $service = new CourseInfoService();
$course = $service->handle($id); $course = $service->handle($id);

View File

@ -7,6 +7,7 @@
namespace App\Http\Home\Controllers; namespace App\Http\Home\Controllers;
use App\Http\Home\Services\FullH5Url as FullH5UrlService;
use App\Http\Home\Services\Index as IndexService; use App\Http\Home\Services\Index as IndexService;
use App\Services\Logic\Help\HelpInfo as HelpInfoService; use App\Services\Logic\Help\HelpInfo as HelpInfoService;
use App\Services\Logic\Help\HelpList as HelpListService; use App\Services\Logic\Help\HelpList as HelpListService;
@ -22,6 +23,13 @@ class HelpController extends Controller
*/ */
public function indexAction() public function indexAction()
{ {
$service = new FullH5UrlService();
if ($service->isMobileBrowser() && $service->h5Enabled()) {
$location = $service->getHelpIndexUrl();
return $this->response->redirect($location);
}
$service = new HelpListService(); $service = new HelpListService();
$items = $service->handle(); $items = $service->handle();
@ -36,6 +44,13 @@ class HelpController extends Controller
*/ */
public function showAction($id) public function showAction($id)
{ {
$service = new FullH5UrlService();
if ($service->isMobileBrowser() && $service->h5Enabled()) {
$location = $service->getHelpInfoUrl($id);
return $this->response->redirect($location);
}
$service = new HelpInfoService(); $service = new HelpInfoService();
$help = $service->handle($id); $help = $service->handle($id);

View File

@ -21,7 +21,7 @@ class ImController extends Controller
parent::initialize(); parent::initialize();
if ($this->authUser->id == 0) { if ($this->authUser->id == 0) {
$this->response->redirect(['for' => 'home.account.login']); return $this->response->redirect(['for' => 'home.account.login']);
} }
} }

View File

@ -7,6 +7,7 @@
namespace App\Http\Home\Controllers; namespace App\Http\Home\Controllers;
use App\Http\Home\Services\FullH5Url as FullH5UrlService;
use App\Http\Home\Services\ImGroup as ImGroupService; use App\Http\Home\Services\ImGroup as ImGroupService;
use Phalcon\Mvc\View; use Phalcon\Mvc\View;
@ -21,6 +22,13 @@ class ImGroupController extends Controller
*/ */
public function listAction() public function listAction()
{ {
$service = new FullH5UrlService();
if ($service->isMobileBrowser() && $service->h5Enabled()) {
$location = $service->getImGroupListUrl();
return $this->response->redirect($location);
}
$this->seo->prependTitle('群组'); $this->seo->prependTitle('群组');
$this->view->pick('im/group/list'); $this->view->pick('im/group/list');
@ -47,6 +55,13 @@ class ImGroupController extends Controller
*/ */
public function showAction($id) public function showAction($id)
{ {
$service = new FullH5UrlService();
if ($service->isMobileBrowser() && $service->h5Enabled()) {
$location = $service->getImGroupIndexUrl($id);
return $this->response->redirect($location);
}
$service = new ImGroupService(); $service = new ImGroupService();
$group = $service->getGroup($id); $group = $service->getGroup($id);

View File

@ -7,32 +7,24 @@
namespace App\Http\Home\Controllers; namespace App\Http\Home\Controllers;
use App\Http\Home\Services\FullH5Url as FullH5UrlService;
use App\Http\Home\Services\Index as IndexService; use App\Http\Home\Services\Index as IndexService;
use App\Traits\Client as ClientTrait;
use Phalcon\Mvc\Dispatcher;
class IndexController extends Controller class IndexController extends Controller
{ {
use ClientTrait;
public function beforeExecuteRoute(Dispatcher $dispatcher)
{
if ($this->isMobileBrowser() && $this->h5Enabled()) {
$this->response->redirect('/h5', true);
return false;
}
return parent::beforeExecuteRoute($dispatcher);
}
/** /**
* @Get("/", name="home.index") * @Get("/", name="home.index")
*/ */
public function indexAction() public function indexAction()
{ {
$service = new FullH5UrlService();
if ($service->isMobileBrowser() && $service->h5Enabled()) {
$location = $service->getHomeUrl();
return $this->response->redirect($location);
}
$this->seo->setKeywords($this->siteInfo['keywords']); $this->seo->setKeywords($this->siteInfo['keywords']);
$this->seo->setDescription($this->siteInfo['description']); $this->seo->setDescription($this->siteInfo['description']);
@ -71,11 +63,4 @@ class IndexController extends Controller
$this->view->setVar('vip_courses', $service->getSimpleVipCourses()); $this->view->setVar('vip_courses', $service->getSimpleVipCourses());
} }
protected function h5Enabled()
{
$file = public_path('h5/index.html');
return file_exists($file);
}
} }

View File

@ -107,7 +107,7 @@ class OrderController extends Controller
$order = $service->handle($sn); $order = $service->handle($sn);
if ($order['status'] != OrderModel::STATUS_PENDING) { if ($order['status'] != OrderModel::STATUS_PENDING) {
$this->response->redirect(['for' => 'home.uc.orders']); return $this->response->redirect(['for' => 'home.uc.orders']);
} }
$this->seo->prependTitle('支付订单'); $this->seo->prependTitle('支付订单');

View File

@ -7,6 +7,7 @@
namespace App\Http\Home\Controllers; namespace App\Http\Home\Controllers;
use App\Http\Home\Services\FullH5Url as FullH5UrlService;
use App\Http\Home\Services\Index as IndexService; use App\Http\Home\Services\Index as IndexService;
use App\Services\Logic\Page\PageInfo as PageInfoService; use App\Services\Logic\Page\PageInfo as PageInfoService;
@ -21,6 +22,13 @@ class PageController extends Controller
*/ */
public function showAction($id) public function showAction($id)
{ {
$service = new FullH5UrlService();
if ($service->isMobileBrowser() && $service->h5Enabled()) {
$location = $service->getPageInfoUrl($id);
return $this->response->redirect($location);
}
$service = new PageInfoService(); $service = new PageInfoService();
$page = $service->handle($id); $page = $service->handle($id);

View File

@ -41,7 +41,7 @@ class PublicController extends \Phalcon\Mvc\Controller
$location = $service->getFileUrl($file->path); $location = $service->getFileUrl($file->path);
$this->response->redirect($location, true); return $this->response->redirect($location, true);
} else { } else {

View File

@ -7,6 +7,7 @@
namespace App\Http\Home\Controllers; namespace App\Http\Home\Controllers;
use App\Http\Home\Services\FullH5Url as FullH5UrlService;
use App\Http\Home\Services\Question as QuestionService; use App\Http\Home\Services\Question as QuestionService;
use App\Http\Home\Services\QuestionQuery as QuestionQueryService; use App\Http\Home\Services\QuestionQuery as QuestionQueryService;
use App\Models\Question as QuestionModel; use App\Models\Question as QuestionModel;
@ -32,6 +33,13 @@ class QuestionController extends Controller
*/ */
public function listAction() public function listAction()
{ {
$service = new FullH5UrlService();
if ($service->isMobileBrowser() && $service->h5Enabled()) {
$location = $service->getQuestionListUrl();
return $this->response->redirect($location);
}
$service = new QuestionQueryService(); $service = new QuestionQueryService();
$sorts = $service->handleSorts(); $sorts = $service->handleSorts();
@ -98,6 +106,13 @@ class QuestionController extends Controller
*/ */
public function showAction($id) public function showAction($id)
{ {
$service = new FullH5UrlService();
if ($service->isMobileBrowser() && $service->h5Enabled()) {
$location = $service->getQuestionInfoUrl($id);
return $this->response->redirect($location);
}
$service = new QuestionInfoService(); $service = new QuestionInfoService();
$question = $service->handle($id); $question = $service->handle($id);

View File

@ -28,7 +28,7 @@ class SearchController extends Controller
$type = $this->request->get('type', ['trim', 'string'], 'course'); $type = $this->request->get('type', ['trim', 'string'], 'course');
if (empty($query)) { if (empty($query)) {
$this->response->redirect(['for' => 'home.course.list']); return $this->response->redirect(['for' => 'home.course.list']);
} }
$this->seo->prependTitle(['搜索', $query]); $this->seo->prependTitle(['搜索', $query]);

View File

@ -7,6 +7,7 @@
namespace App\Http\Home\Controllers; namespace App\Http\Home\Controllers;
use App\Http\Home\Services\FullH5Url as FullH5UrlService;
use App\Services\Logic\Teacher\TeacherList as TeacherListService; use App\Services\Logic\Teacher\TeacherList as TeacherListService;
use Phalcon\Mvc\View; use Phalcon\Mvc\View;
@ -21,6 +22,13 @@ class TeacherController extends Controller
*/ */
public function listAction() public function listAction()
{ {
$service = new FullH5UrlService();
if ($service->isMobileBrowser() && $service->h5Enabled()) {
$location = $service->getTeacherListUrl();
return $this->response->redirect($location);
}
$this->seo->prependTitle('教师'); $this->seo->prependTitle('教师');
} }
@ -44,6 +52,13 @@ class TeacherController extends Controller
*/ */
public function showAction($id) public function showAction($id)
{ {
$service = new FullH5UrlService();
if ($service->isMobileBrowser() && $service->h5Enabled()) {
$location = $service->getTeacherIndexUrl($id);
return $this->response->redirect($location);
}
$this->dispatcher->forward([ $this->dispatcher->forward([
'controller' => 'user', 'controller' => 'user',
'action' => 'show', 'action' => 'show',

View File

@ -7,6 +7,7 @@
namespace App\Http\Home\Controllers; namespace App\Http\Home\Controllers;
use App\Http\Home\Services\FullH5Url as FullH5UrlService;
use App\Services\Logic\User\AnswerList as UserAnswerListService; use App\Services\Logic\User\AnswerList as UserAnswerListService;
use App\Services\Logic\User\ArticleList as UserArticleListService; use App\Services\Logic\User\ArticleList as UserArticleListService;
use App\Services\Logic\User\CourseList as UserCourseListService; use App\Services\Logic\User\CourseList as UserCourseListService;
@ -27,6 +28,13 @@ class UserController extends Controller
*/ */
public function showAction($id) public function showAction($id)
{ {
$service = new FullH5UrlService();
if ($service->isMobileBrowser() && $service->h5Enabled()) {
$location = $service->getUserIndexUrl($id);
return $this->response->redirect($location);
}
$service = new UserInfoService(); $service = new UserInfoService();
$user = $service->handle($id); $user = $service->handle($id);

View File

@ -7,6 +7,7 @@
namespace App\Http\Home\Controllers; namespace App\Http\Home\Controllers;
use App\Http\Home\Services\FullH5Url as FullH5UrlService;
use App\Services\Logic\Vip\CourseList as VipCourseListService; use App\Services\Logic\Vip\CourseList as VipCourseListService;
use App\Services\Logic\Vip\OptionList as VipOptionListService; use App\Services\Logic\Vip\OptionList as VipOptionListService;
use App\Services\Logic\Vip\UserList as VipUserListService; use App\Services\Logic\Vip\UserList as VipUserListService;
@ -23,6 +24,13 @@ class VipController extends Controller
*/ */
public function indexAction() public function indexAction()
{ {
$service = new FullH5UrlService();
if ($service->isMobileBrowser() && $service->h5Enabled()) {
$location = $service->getVipIndexUrl();
return $this->response->redirect($location);
}
$service = new VipOptionListService(); $service = new VipOptionListService();
$vipOptions = $service->handle(); $vipOptions = $service->handle();

View File

@ -51,6 +51,8 @@ class Account extends Service
$user = $validator->checkUserLogin($post['account'], $post['password']); $user = $validator->checkUserLogin($post['account'], $post['password']);
$validator->checkIfAllowLogin($user);
$validator = new CaptchaValidator(); $validator = new CaptchaValidator();
$validator->checkCode($post['ticket'], $post['rand']); $validator->checkCode($post['ticket'], $post['rand']);
@ -68,6 +70,8 @@ class Account extends Service
$user = $validator->checkVerifyLogin($post['account'], $post['verify_code']); $user = $validator->checkVerifyLogin($post['account'], $post['verify_code']);
$validator->checkIfAllowLogin($user);
$this->auth->saveAuthInfo($user); $this->auth->saveAuthInfo($user);
$this->eventsManager->fire('Account:afterLogin', $this, $user); $this->eventsManager->fire('Account:afterLogin', $this, $user);

View File

@ -0,0 +1,149 @@
<?php
/**
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
* @license https://opensource.org/licenses/GPL-2.0
* @link https://www.koogua.com
*/
namespace App\Http\Home\Services;
use App\Traits\Client as ClientTrait;
class FullH5Url extends Service
{
protected $baseUrl;
use ClientTrait;
public function __construct()
{
$this->baseUrl = $this->getBaseUrl();
}
public function getHomeUrl()
{
return sprintf('%s/index/index', $this->baseUrl);
}
public function getAccountRegisterUrl()
{
return sprintf('%s/account/register', $this->baseUrl);
}
public function getAccountLoginUrl()
{
return sprintf('%s/account/login', $this->baseUrl);
}
public function getAccountForgetUrl()
{
return sprintf('%s/account/forget', $this->baseUrl);
}
public function getVipIndexUrl()
{
return sprintf('%s/vip/index', $this->baseUrl);
}
public function getHelpIndexUrl()
{
return sprintf('%s/help/index', $this->baseUrl);
}
public function getCourseListUrl()
{
return sprintf('%s/course/list', $this->baseUrl);
}
public function getArticleListUrl()
{
return sprintf('%s/article/list', $this->baseUrl);
}
public function getQuestionListUrl()
{
return sprintf('%s/question/list', $this->baseUrl);
}
public function getLiveListUrl()
{
return sprintf('%s/discovery/index', $this->baseUrl);
}
public function getTeacherListUrl()
{
return sprintf('%s/discovery/index', $this->baseUrl);
}
public function getImGroupListUrl()
{
return sprintf('%s/discovery/index', $this->baseUrl);
}
public function getPointGiftListUrl()
{
return sprintf('%s/point/gift/list', $this->baseUrl);
}
public function getPageInfoUrl($id)
{
return sprintf('%s/page/info?id=%s', $this->baseUrl, $id);
}
public function getHelpInfoUrl($id)
{
return sprintf('%s/help/info?id=%s', $this->baseUrl, $id);
}
public function getArticleInfoUrl($id)
{
return sprintf('%s/article/info?id=%s', $this->baseUrl, $id);
}
public function getQuestionInfoUrl($id)
{
return sprintf('%s/question/info?id=%s', $this->baseUrl, $id);
}
public function getAnswerInfoUrl($id)
{
return sprintf('%s/answer/info?id=%s', $this->baseUrl, $id);
}
public function getCourseInfoUrl($id)
{
return sprintf('%s/course/info?id=%s', $this->baseUrl, $id);
}
public function getChapterInfoUrl($id)
{
return sprintf('%s/chapter/info?id=%s', $this->baseUrl, $id);
}
public function getUserIndexUrl($id)
{
return sprintf('%s/user/index?id=%s', $this->baseUrl, $id);
}
public function getTeacherIndexUrl($id)
{
return sprintf('%s/teacher/index?id=%s', $this->baseUrl, $id);
}
public function getImGroupIndexUrl($id)
{
return sprintf('%s/im/group/index?id=%s', $this->baseUrl, $id);
}
public function getPointGiftInfoUrl($id)
{
return sprintf('%s/point/gift/info?id=%s', $this->baseUrl, $id);
}
protected function getBaseUrl()
{
return sprintf('%s/h5/#/pages', kg_site_url());
}
}

View File

@ -0,0 +1,86 @@
<?php
/**
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
* @license https://opensource.org/licenses/GPL-2.0
* @link https://www.koogua.com
*/
namespace App\Http\Home\Services;
class FullWebUrl extends Service
{
protected $baseUrl;
public function __construct()
{
$this->baseUrl = $this->getBaseUrl();
}
public function getHomeUrl()
{
return $this->baseUrl;
}
public function getArticleShowUrl($id)
{
$route = $this->url->get(['for' => 'home.article.show', 'id' => $id]);
return $this->baseUrl . $route;
}
public function getQuestionShowUrl($id)
{
$route = $this->url->get(['for' => 'home.question.show', 'id' => $id]);
return $this->baseUrl . $route;
}
public function getCourseShowUrl($id)
{
$route = $this->url->get(['for' => 'home.course.show', 'id' => $id]);
return $this->baseUrl . $route;
}
public function getChapterShowUrl($id)
{
$route = $this->url->get(['for' => 'home.chapter.show', 'id' => $id]);
return $this->baseUrl . $route;
}
public function getUserShowUrl($id)
{
$route = $this->url->get(['for' => 'home.user.show', 'id' => $id]);
return $this->baseUrl . $route;
}
public function getTeacherShowUrl($id)
{
$route = $this->url->get(['for' => 'home.teacher.show', 'id' => $id]);
return $this->baseUrl . $route;
}
public function getImGroupShowUrl($id)
{
$route = $this->url->get(['for' => 'home.im_group.show', 'id' => $id]);
return $this->baseUrl . $route;
}
public function getPointGiftShowUrl($id)
{
$route = $this->url->get(['for' => 'home.point_gift.show', 'id' => $id]);
return $this->baseUrl . $route;
}
protected function getBaseUrl()
{
return kg_site_url();
}
}

View File

@ -7,6 +7,8 @@
namespace App\Http\Home\Services; namespace App\Http\Home\Services;
use App\Traits\Client as ClientTrait;
class ShareUrl extends Service class ShareUrl extends Service
{ {
@ -15,150 +17,105 @@ class ShareUrl extends Service
* *
* @var string * @var string
*/ */
protected $webBaseUrl; protected $fullWebUrl;
/** /**
* H5站点URL * H5站点URL
* *
* @var string * @var string
*/ */
protected $h5BaseUrl; protected $fullH5Url;
use ClientTrait;
public function __construct() public function __construct()
{ {
$this->webBaseUrl = $this->getWebBaseUrl(); $this->fullWebUrl = new FullWebUrl();
$this->h5BaseUrl = $this->getH5BaseUrl(); $this->fullH5Url = new FullH5Url();
} }
public function handle($id, $type, $referer = 0) public function handle($id, $type)
{ {
if ($type == 'article') { if ($type == 'article') {
$result = $this->getArticleUrl($id, $referer); $result = $this->getArticleUrl($id);
} elseif ($type == 'question') {
$result = $this->getQuestionUrl($id);
} elseif ($type == 'course') { } elseif ($type == 'course') {
$result = $this->getCourseUrl($id, $referer); $result = $this->getCourseUrl($id);
} elseif ($type == 'chapter') { } elseif ($type == 'chapter') {
$result = $this->getChapterUrl($id, $referer); $result = $this->getChapterUrl($id);
} elseif ($type == 'package') {
$result = $this->getPackageUrl($id, $referer);
} elseif ($type == 'vip') {
$result = $this->getVipUrl($id, $referer);
} elseif ($type == 'user') { } elseif ($type == 'user') {
$result = $this->getUserUrl($id, $referer); $result = $this->getUserUrl($id);
} elseif ($type == 'teacher') {
$result = $this->getTeacherUrl($id);
} else { } else {
$result = $this->getHomeUrl($referer); $result = $this->getHomeUrl();
} }
return $this->h5Enabled() ? $result['h5'] : $result['web']; return $this->h5Enabled() ? $result['h5'] : $result['web'];
} }
public function getHomeUrl($referer = 0) public function getHomeUrl()
{ {
$webUrl = sprintf('%s?referer=%s', $this->webBaseUrl, $referer); $webUrl = $this->fullWebUrl->getHomeUrl();
$h5Url = sprintf('%s?referer=%s', $this->h5BaseUrl, $referer); $h5Url = $this->fullH5Url->getHomeUrl();
return ['web' => $webUrl, 'h5' => $h5Url]; return ['web' => $webUrl, 'h5' => $h5Url];
} }
public function getArticleUrl($id, $referer = 0) public function getArticleUrl($id = 0)
{ {
$route = $this->url->get( $webUrl = $this->fullWebUrl->getArticleShowUrl($id);
['for' => 'home.article.show', 'id' => $id],
['referer' => $referer]
);
$webUrl = $this->webBaseUrl . $route; $h5Url = $this->fullH5Url->getArticleInfoUrl($id);
$h5Url = sprintf('%s/article/info?id=%s&referer=%s', $this->h5BaseUrl, $id, $referer);
return ['web' => $webUrl, 'h5' => $h5Url]; return ['web' => $webUrl, 'h5' => $h5Url];
} }
public function getCourseUrl($id, $referer = 0) public function getQuestionUrl($id = 0)
{ {
$route = $this->url->get( $webUrl = $this->fullWebUrl->getQuestionShowUrl($id);
['for' => 'home.course.show', 'id' => $id],
['referer' => $referer]
);
$webUrl = $this->webBaseUrl . $route; $h5Url = $this->fullH5Url->getQuestionInfoUrl($id);
$h5Url = sprintf('%s/course/info?id=%s&referer=%s', $this->h5BaseUrl, $id, $referer);
return ['web' => $webUrl, 'h5' => $h5Url]; return ['web' => $webUrl, 'h5' => $h5Url];
} }
public function getChapterUrl($id, $referer = 0) public function getCourseUrl($id = 0)
{ {
$route = $this->url->get( $webUrl = $this->fullWebUrl->getCourseShowUrl($id);
['for' => 'home.chapter.show', 'id' => $id],
['referer' => $referer]
);
$webUrl = $this->webBaseUrl . $route; $h5Url = $this->fullH5Url->getCourseInfoUrl($id);
$h5Url = sprintf('%s/chapter/info?id=%s&referer=%s', $this->h5BaseUrl, $id, $referer);
return ['web' => $webUrl, 'h5' => $h5Url]; return ['web' => $webUrl, 'h5' => $h5Url];
} }
public function getPackageUrl($id, $referer = 0) public function getChapterUrl($id = 0)
{ {
$route = $this->url->get( $webUrl = $this->fullWebUrl->getChapterShowUrl($id);
['for' => 'home.package.show', 'id' => $id],
['referer' => $referer]
);
$webUrl = $this->webBaseUrl . $route; $h5Url = $this->fullH5Url->getChapterInfoUrl($id);
$h5Url = sprintf('%s/package/info?id=%s&referer=%s', $this->h5BaseUrl, $id, $referer);
return ['web' => $webUrl, 'h5' => $h5Url]; return ['web' => $webUrl, 'h5' => $h5Url];
} }
public function getUserUrl($id, $referer = 0) public function getUserUrl($id = 0)
{ {
$route = $this->url->get( $webUrl = $this->fullWebUrl->getUserShowUrl($id);
['for' => 'home.user.show', 'id' => $id],
['referer' => $referer]
);
$webUrl = $this->webBaseUrl . $route; $h5Url = $this->fullH5Url->getUserIndexUrl($id);
$h5Url = sprintf('%s/user/index?id=%s&referer=%s', $this->h5BaseUrl, $id, $referer);
return ['web' => $webUrl, 'h5' => $h5Url]; return ['web' => $webUrl, 'h5' => $h5Url];
} }
public function getVipUrl($id, $referer = 0) public function getTeacherUrl($id = 0)
{ {
$route = $this->url->get( $webUrl = $this->fullWebUrl->getTeacherShowUrl($id);
['for' => 'home.vip.index'],
['id' => $id, 'referer' => $referer]
);
$webUrl = $this->webBaseUrl . $route; $h5Url = $this->fullH5Url->getTeacherIndexUrl($id);
$h5Url = sprintf('%s/vip/index?id=%s&referer=%s', $this->h5BaseUrl, $id, $referer);
return ['web' => $webUrl, 'h5' => $h5Url]; return ['web' => $webUrl, 'h5' => $h5Url];
} }
protected function h5Enabled()
{
$file = public_path('h5/index.html');
return file_exists($file);
}
protected function getWebBaseUrl()
{
return kg_site_url();
}
protected function getH5BaseUrl()
{
return sprintf('%s/h5/#/pages', kg_site_url());
}
} }

View File

@ -16,7 +16,7 @@ class AppInfo
protected $link = 'https://koogua.com'; protected $link = 'https://koogua.com';
protected $version = '1.4.5'; protected $version = '1.4.6';
public function __get($name) public function __get($name)
{ {

View File

@ -76,6 +76,32 @@ class PointGift extends Repository
]); ]);
} }
/**
* @param int $courseId
* @return PointGiftModel|Model|bool
*/
public function findByCourseId($courseId)
{
/**
* @todo 重新设计表结构
*
* 没有预留独立的条目编号,先这么将就实现吧
*/
$records = PointGiftModel::query()
->where('type = :type:', ['type' => PointGiftModel::TYPE_COURSE])
->execute();
if ($records->count() == 0) return false;
foreach ($records as $record) {
if ($record->attrs['id'] == $courseId) {
return $record;
}
}
return false;
}
/** /**
* @param array $ids * @param array $ids
* @param string|array $columns * @param string|array $columns

View File

@ -24,10 +24,12 @@ class Api extends AuthService
$lifetime = $this->getTokenLifetime(); $lifetime = $this->getTokenLifetime();
$clientType = $this->getClientType();
/** /**
* demo版本不限制多人登录 * demo版本不限制多人登录
*/ */
// $this->logoutOtherClients($user->id); // $this->logoutClients($user->id, $clientType);
$this->createUserToken($user->id, $token, $lifetime); $this->createUserToken($user->id, $token, $lifetime);
@ -73,6 +75,52 @@ class Api extends AuthService
return $authInfo ?: null; return $authInfo ?: null;
} }
public function logoutClients($userId, $clientType = null)
{
$repo = new UserTokenRepo();
$records = $repo->findByUserId($userId);
if ($records->count() == 0) return;
if ($clientType) {
$this->logoutSpecialClients($records, $clientType);
} else {
$this->logoutAllClients($records);
}
}
/**
* @param $userTokens UserTokenModel[]
*/
protected function logoutAllClients($userTokens)
{
$cache = $this->getCache();
foreach ($userTokens as $record) {
$record->delete();
$key = $this->getTokenCacheKey($record->token);
$cache->delete($key);
}
}
/**
* @param $userTokens UserTokenModel[]
* @param int $clientType
*/
protected function logoutSpecialClients($userTokens, $clientType)
{
$cache = $this->getCache();
foreach ($userTokens as $record) {
if ($record->client_type == $clientType) {
$record->delete();
$key = $this->getTokenCacheKey($record->token);
$cache->delete($key);
}
}
}
protected function createUserToken($userId, $token, $lifetime) protected function createUserToken($userId, $token, $lifetime)
{ {
$userToken = new UserTokenModel(); $userToken = new UserTokenModel();
@ -86,27 +134,6 @@ class Api extends AuthService
$userToken->create(); $userToken->create();
} }
protected function logoutOtherClients($userId)
{
$repo = new UserTokenRepo();
$records = $repo->findByUserId($userId);
$cache = $this->getCache();
$clientType = $this->getClientType();
if ($records->count() == 0) return;
foreach ($records as $record) {
if ($record->client_type == $clientType) {
$record->delete();
$key = $this->getTokenCacheKey($record->token);
$cache->delete($key);
}
}
}
protected function generateToken($userId) protected function generateToken($userId)
{ {
return md5(uniqid() . time() . $userId); return md5(uniqid() . time() . $userId);

View File

@ -27,7 +27,7 @@ class Home extends AuthService
/** /**
* demo版本不限制多人登录 * demo版本不限制多人登录
*/ */
// $this->logoutOtherClients($user->id); // $this->logoutClients($user->id);
$this->createUserSession($user->id, $sessionId, $lifetime); $this->createUserSession($user->id, $sessionId, $lifetime);
@ -62,20 +62,7 @@ class Home extends AuthService
return 'home_auth_info'; return 'home_auth_info';
} }
protected function createUserSession($userId, $sessionId, $lifetime) public function logoutClients($userId)
{
$userSession = new UserSessionModel();
$userSession->user_id = $userId;
$userSession->session_id = $sessionId;
$userSession->client_type = $this->getClientType();
$userSession->client_ip = $this->getClientIp();
$userSession->expire_time = time() + $lifetime;
$userSession->create();
}
protected function logoutOtherClients($userId)
{ {
$cache = $this->getCache(); $cache = $this->getCache();
@ -92,6 +79,19 @@ class Home extends AuthService
} }
} }
protected function createUserSession($userId, $sessionId, $lifetime)
{
$userSession = new UserSessionModel();
$userSession->user_id = $userId;
$userSession->session_id = $sessionId;
$userSession->client_type = $this->getClientType();
$userSession->client_ip = $this->getClientIp();
$userSession->expire_time = time() + $lifetime;
$userSession->create();
}
protected function getSessionLifetime() protected function getSessionLifetime()
{ {
$config = $this->getConfig(); $config = $this->getConfig();

View File

@ -39,35 +39,42 @@ class ChapterList extends LogicService
if (count($chapters) == 0) return []; if (count($chapters) == 0) return [];
if ($user->id > 0 && $this->courseUser) { if ($user->id > 0 && $this->courseUser) {
$mapping = $this->getLearningMapping($course->id, $user->id, $this->courseUser->plan_id); $chapters = $this->handleLoginUserChapters($chapters, $course, $user);
foreach ($chapters as &$chapter) {
foreach ($chapter['children'] as &$lesson) {
/**
* @todo v1.4.1之前缓存中无published字段临时给默认值
*/
$lesson['published'] = $lesson['published'] ?? 1;
$owned = ($this->ownedCourse || $lesson['free'] == 1) && $lesson['published'] == 1;
$lesson['me'] = [
'owned' => $owned ? 1 : 0,
'progress' => $mapping[$lesson['id']]['progress'] ?? 0,
'duration' => $mapping[$lesson['id']]['duration'] ?? 0,
];
}
}
} else { } else {
foreach ($chapters as &$chapter) { $chapters = $this->handleGuestUserChapters($chapters);
foreach ($chapter['children'] as &$lesson) { }
/**
* @todo v1.4.1之前缓存中无published字段临时给默认值 return $chapters;
*/ }
$lesson['published'] = $lesson['published'] ?? 1;
$owned = ($this->ownedCourse || $lesson['free'] == 1) && $lesson['published'] == 1; protected function handleLoginUserChapters(array $chapters, CourseModel $course, UserModel $user)
$lesson['me'] = [ {
'owned' => $owned ? 1 : 0, $mapping = $this->getLearningMapping($course->id, $user->id, $this->courseUser->plan_id);
'progress' => 0,
'duration' => 0, foreach ($chapters as &$chapter) {
]; foreach ($chapter['children'] as &$lesson) {
} $owned = ($this->ownedCourse || $lesson['free'] == 1) && $lesson['published'] == 1;
$lesson['me'] = [
'owned' => $owned ? 1 : 0,
'progress' => $mapping[$lesson['id']]['progress'] ?? 0,
'duration' => $mapping[$lesson['id']]['duration'] ?? 0,
];
}
}
return $chapters;
}
protected function handleGuestUserChapters(array $chapters)
{
foreach ($chapters as &$chapter) {
foreach ($chapter['children'] as &$lesson) {
$owned = ($this->ownedCourse || $lesson['free'] == 1) && $lesson['published'] == 1;
$lesson['me'] = [
'owned' => $owned ? 1 : 0,
'progress' => 0,
'duration' => 0,
];
} }
} }

View File

@ -55,6 +55,11 @@ class GiftInfo extends LogicService
$gift->name = $course->title; $gift->name = $course->title;
$gift->cover = $course->cover; $gift->cover = $course->cover;
$gift->details = $course->details; $gift->details = $course->details;
$gift->attrs = [
'id' => $course->id,
'title' => $course->title,
'price' => $course->market_price,
];
return $gift; return $gift;
} }

View File

@ -7,56 +7,19 @@
namespace App\Services\Logic\Teacher\Console; namespace App\Services\Logic\Teacher\Console;
use App\Builders\CourseUserList as CourseUserListBuilder;
use App\Library\Paginator\Query as PagerQuery;
use App\Models\CourseUser as CourseUserModel;
use App\Repos\CourseUser as CourseUserRepo;
use App\Services\Logic\Service as LogicService; use App\Services\Logic\Service as LogicService;
use App\Services\Logic\UserTrait; use App\Services\Logic\Teacher\CourseList as CourseListService;
class CourseList extends LogicService class CourseList extends LogicService
{ {
use UserTrait;
public function handle() public function handle()
{ {
$user = $this->getLoginUser(); $user = $this->getLoginUser();
$pagerQuery = new PagerQuery(); $service = new CourseListService();
$params = $pagerQuery->getParams(); return $service->handle($user->id);
$params['user_id'] = $user->id;
$params['role_type'] = CourseUserModel::ROLE_TEACHER;
$params['deleted'] = 0;
$sort = $pagerQuery->getSort();
$page = $pagerQuery->getPage();
$limit = $pagerQuery->getLimit();
$courseUserRepo = new CourseUserRepo();
$pager = $courseUserRepo->paginate($params, $sort, $page, $limit);
return $this->handleCourses($pager);
}
protected function handleCourses($pager)
{
if ($pager->total_items == 0) {
return $pager;
}
$builder = new CourseUserListBuilder();
$relations = $pager->items->toArray();
$courses = $builder->getCourses($relations);
$pager->items = $courses;
return $pager;
} }
} }

View File

@ -67,4 +67,11 @@ trait Client
return $result->isMobile(); return $result->isMobile();
} }
public function h5Enabled()
{
$file = public_path('h5/index.html');
return file_exists($file);
}
} }

View File

@ -12,6 +12,7 @@ use App\Exceptions\Forbidden as ForbiddenException;
use App\Library\Utils\Password as PasswordUtil; use App\Library\Utils\Password as PasswordUtil;
use App\Library\Validators\Common as CommonValidator; use App\Library\Validators\Common as CommonValidator;
use App\Models\Account as AccountModel; use App\Models\Account as AccountModel;
use App\Models\User as UserModel;
use App\Repos\Account as AccountRepo; use App\Repos\Account as AccountRepo;
use App\Repos\User as UserRepo; use App\Repos\User as UserRepo;
@ -166,4 +167,14 @@ class Account extends Validator
return $user; return $user;
} }
public function checkIfAllowLogin(UserModel $user)
{
$locked = $user->locked == 1;
$expired = $user->lock_expiry_time > time();
if ($locked && !$expired) {
throw new ForbiddenException('account.locked');
}
}
} }

View File

@ -14,7 +14,6 @@ use App\Library\Validators\Common as CommonValidator;
use App\Models\User as UserModel; use App\Models\User as UserModel;
use App\Repos\Role as RoleRepo; use App\Repos\Role as RoleRepo;
use App\Repos\User as UserRepo; use App\Repos\User as UserRepo;
use App\Services\Auth\Admin as AdminAuth;
class User extends Validator class User extends Validator
{ {
@ -218,18 +217,4 @@ class User extends Validator
} }
} }
public function checkIfCanEditUser($user)
{
/**
* @var AdminAuth $auth
*/
$auth = $this->getDI()->get('auth');
$authUser = $auth->getAuthInfo();
if ($authUser['id']) {
}
}
} }

View File

@ -46,7 +46,7 @@ $error['captcha.invalid_code'] = '无效的验证码';
* 帐号相关 * 帐号相关
*/ */
$error['account.not_found'] = '账号不存在'; $error['account.not_found'] = '账号不存在';
$error['account.login_block'] = '账号被锁定,无法登录'; $error['account.locked'] = '账号被锁定,无法登录';
$error['account.login_pwd_incorrect'] = '登录密码不正确'; $error['account.login_pwd_incorrect'] = '登录密码不正确';
$error['account.invalid_login_name'] = '无效的登录名'; $error['account.invalid_login_name'] = '无效的登录名';
$error['account.invalid_email'] = '无效的电子邮箱'; $error['account.invalid_email'] = '无效的电子邮箱';