1
0
mirror of https://gitee.com/koogua/course-tencent-cloud.git synced 2025-06-26 04:21:27 +08:00

Merge branch 'koogua/v1.6.8' into demo

# Conflicts:
#	app/Http/Admin/Views/chapter/lessons.volt
#	app/Http/Admin/Views/chapter/lessons_live.volt
#	app/Http/Admin/Views/chapter/lessons_offline.volt
#	app/Http/Admin/Views/chapter/lessons_read.volt
#	app/Http/Admin/Views/chapter/lessons_vod.volt
This commit is contained in:
xiaochong0302 2024-01-30 11:48:20 +08:00
commit 0b34f907a6
63 changed files with 433 additions and 948 deletions

View File

@ -1,3 +1,20 @@
### [v1.6.8](https://gitee.com/koogua/course-tencent-cloud/releases/v1.6.8)(2024-01-30)
- 修正course_user中active_time未更新问题
- 修正主页simple模式免费课程模块样式问题
- 修正chapter_user中plan_id=0问题
- 修正课时评论管理链接
- 修正用户active_time搜索条件
- 修正课时发布switch开关
- 精简chapter/lessons.volt
- 去除league/commonmark包
- 去除分类等必选判断
- 更新layui-v2.9.3
- 使用ServiceTrait精简代码
- 优化AccountTrait
- 优化错误处理
### [v1.6.7](https://gitee.com/koogua/course-tencent-cloud/releases/v1.6.7)(2023-12-15) ### [v1.6.7](https://gitee.com/koogua/course-tencent-cloud/releases/v1.6.7)(2023-12-15)
- 增加文章分类功能 - 增加文章分类功能

View File

@ -13,7 +13,7 @@
### 系统功能 ### 系统功能
实现了点播、直播、专栏、面授、问答、会员、积分、秒杀等。 实现了点播、直播、专栏、问答、会员、积分等。
友情提示: 友情提示:
@ -34,12 +34,6 @@ H5手机端演示
演示账号13507083515 / 123456 演示账号13507083515 / 123456
微信公众号演示:
![公众号二维码](https://portal-1255691183.file.myqcloud.com/img/content/616f998270eca.png)
演示账号13507083515 / 123456
支付流程演示: 支付流程演示:
- [MySQL提升课程全面讲解MySQL架构设计0.01元)](https://ctc.koogua.com/order/confirm?item_id=1390&item_type=1) - [MySQL提升课程全面讲解MySQL架构设计0.01元)](https://ctc.koogua.com/order/confirm?item_id=1390&item_type=1)
@ -55,9 +49,8 @@ Tips: 请用手机注册一个新账号,用户中心 -> 关注订阅,扫码
### 项目组件 ### 项目组件
- 后台框架:[phalcon 3.4.5](https://phalcon.io) - 后台框架:[phalcon 3.4.5](https://phalcon.io)
- 前端框架:[layui 2.8.8](https://layui.com) - 前端框架:[layui 2.9.3](https://layui.dev)
- 全文检索:[xunsearch 1.4.9](http://www.xunsearch.com) - 全文检索:[xunsearch 1.4.9](http://www.xunsearch.com)
- 即时通讯:[workerman 3.5.22](https://workerman.net)
- 基础依赖:[php7.3](https://php.net) [mysql5.7](https://mysql.com) [redis5.0](https://redis.io) - 基础依赖:[php7.3](https://php.net) [mysql5.7](https://mysql.com) [redis5.0](https://redis.io)
### 项目文档 ### 项目文档

View File

@ -7,7 +7,11 @@
namespace App\Console\Migrations; namespace App\Console\Migrations;
use App\Traits\Service as ServiceTrait;
abstract class Migration abstract class Migration
{ {
use ServiceTrait;
abstract public function run(); abstract public function run();
} }

View File

@ -1,162 +0,0 @@
<?php
/**
* @copyright Copyright (c) 2022 深圳市酷瓜软件有限公司
* @license https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* @link https://www.koogua.com
*/
namespace App\Console\Migrations;
use App\Models\Answer as AnswerModel;
use App\Models\Article as ArticleModel;
use App\Models\Course as CourseModel;
use App\Models\Help as HelpModel;
use App\Models\Page as PageModel;
use App\Models\PointGift as PointGiftModel;
use App\Models\Question as QuestionModel;
use League\CommonMark\GithubFlavoredMarkdownConverter;
use Phalcon\Mvc\Model\Resultset;
class V202207291145 extends Migration
{
/**
* @var GithubFlavoredMarkdownConverter
*/
protected $markdownConverter;
public function run()
{
$this->initMarkdownConverter();
$this->courseMarkdownToHtml();
$this->articleMarkdownToHtml();
$this->questionMarkdownToHtml();
$this->answerMarkdownToHtml();
$this->pageMarkdownToHtml();
$this->helpMarkdownToHtml();
$this->pointGiftMarkdownToHtml();
}
protected function initMarkdownConverter()
{
$this->markdownConverter = new GithubFlavoredMarkdownConverter([
'html_input' => 'escape',
'allow_unsafe_links' => false,
]);
}
protected function articleMarkdownToHtml()
{
/**
* @var $articles Resultset|ArticleModel[]
*/
$articles = ArticleModel::query()->execute();
if ($articles->count() == 0) return;
foreach ($articles as $article) {
$content = $this->markdownConverter->convertToHtml($article->content);
$article->content = $content;
$article->update();
}
}
protected function courseMarkdownToHtml()
{
/**
* @var $courses Resultset|CourseModel[]
*/
$courses = CourseModel::query()->execute();
if ($courses->count() == 0) return;
foreach ($courses as $course) {
$details = $this->markdownConverter->convertToHtml($course->details);
$course->details = $details;
$course->update();
}
}
protected function questionMarkdownToHtml()
{
/**
* @var $questions Resultset|QuestionModel[]
*/
$questions = QuestionModel::query()->execute();
if ($questions->count() == 0) return;
foreach ($questions as $question) {
$content = $this->markdownConverter->convertToHtml($question->content);
$question->content = $content;
$question->update();
}
}
protected function answerMarkdownToHtml()
{
/**
* @var $answers Resultset|AnswerModel[]
*/
$answers = AnswerModel::query()->execute();
if ($answers->count() == 0) return;
foreach ($answers as $answer) {
$content = $this->markdownConverter->convertToHtml($answer->content);
$answer->content = $content;
$answer->update();
}
}
protected function pageMarkdownToHtml()
{
/**
* @var $pages Resultset|PageModel[]
*/
$pages = PageModel::query()->execute();
if ($pages->count() == 0) return;
foreach ($pages as $page) {
$content = $this->markdownConverter->convertToHtml($page->content);
$page->content = $content;
$page->update();
}
}
protected function helpMarkdownToHtml()
{
/**
* @var $helps Resultset|HelpModel[]
*/
$helps = HelpModel::query()->execute();
if ($helps->count() == 0) return;
foreach ($helps as $help) {
$content = $this->markdownConverter->convertToHtml($help->content);
$help->content = $content;
$help->update();
}
}
protected function pointGiftMarkdownToHtml()
{
/**
* @var $gifts Resultset|PointGiftModel[]
*/
$gifts = PointGiftModel::query()
->where('type = :type:', ['type' => PointGiftModel::TYPE_GOODS])
->execute();
if ($gifts->count() == 0) return;
foreach ($gifts as $gift) {
$details = $this->markdownConverter->convertToHtml($gift->details);
$gift->details = $details;
$gift->update();
}
}
}

View File

@ -9,6 +9,7 @@ namespace App\Http\Admin\Services;
use App\Builders\AnswerList as AnswerListBuilder; use App\Builders\AnswerList as AnswerListBuilder;
use App\Builders\ReportList as ReportListBuilder; use App\Builders\ReportList as ReportListBuilder;
use App\Http\Admin\Services\Traits\AccountSearchTrait;
use App\Library\Paginator\Query as PagerQuery; use App\Library\Paginator\Query as PagerQuery;
use App\Models\Answer as AnswerModel; use App\Models\Answer as AnswerModel;
use App\Models\Question as QuestionModel; use App\Models\Question as QuestionModel;
@ -31,6 +32,7 @@ class Answer extends Service
{ {
use AnswerDataTrait; use AnswerDataTrait;
use AccountSearchTrait;
public function getPublishTypes() public function getPublishTypes()
{ {
@ -48,6 +50,8 @@ class Answer extends Service
$params = $pagerQuery->getParams(); $params = $pagerQuery->getParams();
$params = $this->handleAccountSearchParams($params);
$params['deleted'] = $params['deleted'] ?? 0; $params['deleted'] = $params['deleted'] ?? 0;
$sort = $pagerQuery->getSort(); $sort = $pagerQuery->getSort();

View File

@ -10,6 +10,7 @@ namespace App\Http\Admin\Services;
use App\Builders\ArticleList as ArticleListBuilder; use App\Builders\ArticleList as ArticleListBuilder;
use App\Builders\ReportList as ReportListBuilder; use App\Builders\ReportList as ReportListBuilder;
use App\Caches\Article as ArticleCache; use App\Caches\Article as ArticleCache;
use App\Http\Admin\Services\Traits\AccountSearchTrait;
use App\Library\Paginator\Query as PagerQuery; use App\Library\Paginator\Query as PagerQuery;
use App\Library\Utils\Word as WordUtil; use App\Library\Utils\Word as WordUtil;
use App\Models\Article as ArticleModel; use App\Models\Article as ArticleModel;
@ -34,6 +35,7 @@ class Article extends Service
{ {
use ArticleDataTrait; use ArticleDataTrait;
use AccountSearchTrait;
public function getXmTags($id) public function getXmTags($id)
{ {
@ -70,6 +72,8 @@ class Article extends Service
$params = $pagerQuery->getParams(); $params = $pagerQuery->getParams();
$params = $this->handleAccountSearchParams($params);
if (!empty($params['xm_tag_ids'])) { if (!empty($params['xm_tag_ids'])) {
$params['tag_id'] = explode(',', $params['xm_tag_ids']); $params['tag_id'] = explode(',', $params['xm_tag_ids']);
} }
@ -196,7 +200,7 @@ class Article extends Service
$data['published'] = $validator->checkPublishStatus($post['published']); $data['published'] = $validator->checkPublishStatus($post['published']);
} }
if (isset($post['category_id'])) { if (isset($post['category_id']) && !empty($post['category_id'])) {
$category = $validator->checkCategory($post['category_id']); $category = $validator->checkCategory($post['category_id']);
$data['category_id'] = $category->id; $data['category_id'] = $category->id;
} }

View File

@ -8,14 +8,13 @@
namespace App\Http\Admin\Services; namespace App\Http\Admin\Services;
use App\Builders\ConsultList as ConsultListBuilder; use App\Builders\ConsultList as ConsultListBuilder;
use App\Http\Admin\Services\Traits\AccountSearchTrait;
use App\Library\Paginator\Query as PagerQuery; use App\Library\Paginator\Query as PagerQuery;
use App\Library\Validators\Common as CommonValidator;
use App\Models\Chapter as ChapterModel; use App\Models\Chapter as ChapterModel;
use App\Models\Consult as ConsultModel; use App\Models\Consult as ConsultModel;
use App\Models\Course as CourseModel; use App\Models\Course as CourseModel;
use App\Models\Reason as ReasonModel; use App\Models\Reason as ReasonModel;
use App\Models\User as UserModel; use App\Models\User as UserModel;
use App\Repos\Account as AccountRepo;
use App\Repos\Chapter as ChapterRepo; use App\Repos\Chapter as ChapterRepo;
use App\Repos\Consult as ConsultRepo; use App\Repos\Consult as ConsultRepo;
use App\Repos\Course as CourseRepo; use App\Repos\Course as CourseRepo;
@ -26,6 +25,8 @@ use App\Validators\Consult as ConsultValidator;
class Consult extends Service class Consult extends Service
{ {
use AccountSearchTrait;
public function getPublishTypes() public function getPublishTypes()
{ {
return ConsultModel::publishTypes(); return ConsultModel::publishTypes();
@ -65,23 +66,10 @@ class Consult extends Service
$params = $pagerQuery->getParams(); $params = $pagerQuery->getParams();
$params = $this->handleAccountSearchParams($params);
$params['deleted'] = $params['deleted'] ?? 0; $params['deleted'] = $params['deleted'] ?? 0;
$accountRepo = new AccountRepo();
/**
* 兼容用户编号|手机号码|邮箱地址查询
*/
if (!empty($params['owner_id'])) {
if (CommonValidator::phone($params['owner_id'])) {
$account = $accountRepo->findByPhone($params['owner_id']);
$params['owner_id'] = $account ? $account->id : -1000;
} elseif (CommonValidator::email($params['owner_id'])) {
$account = $accountRepo->findByEmail($params['owner_id']);
$params['owner_id'] = $account ? $account->id : -1000;
}
}
$sort = $pagerQuery->getSort(); $sort = $pagerQuery->getSort();
$page = $pagerQuery->getPage(); $page = $pagerQuery->getPage();
$limit = $pagerQuery->getLimit(); $limit = $pagerQuery->getLimit();

View File

@ -165,12 +165,12 @@ class Course extends Service
$data['published'] = $validator->checkPublishStatus($post['published']); $data['published'] = $validator->checkPublishStatus($post['published']);
} }
if (isset($post['category_id'])) { if (isset($post['category_id']) && !empty($post['category_id'])) {
$category = $validator->checkCategory($post['category_id']); $category = $validator->checkCategory($post['category_id']);
$data['category_id'] = $category->id; $data['category_id'] = $category->id;
} }
if (isset($post['teacher_id'])) { if (isset($post['teacher_id']) && !empty($post['teacher_id'])) {
$teacher = $validator->checkTeacher($post['teacher_id']); $teacher = $validator->checkTeacher($post['teacher_id']);
$data['teacher_id'] = $teacher->id; $data['teacher_id'] = $teacher->id;
} }

View File

@ -8,10 +8,9 @@
namespace App\Http\Admin\Services; namespace App\Http\Admin\Services;
use App\Builders\CourseUserList as CourseUserListBuilder; use App\Builders\CourseUserList as CourseUserListBuilder;
use App\Http\Admin\Services\Traits\AccountSearchTrait;
use App\Library\Paginator\Query as PagerQuery; use App\Library\Paginator\Query as PagerQuery;
use App\Library\Validators\Common as CommonValidator;
use App\Models\CourseUser as CourseUserModel; use App\Models\CourseUser as CourseUserModel;
use App\Repos\Account as AccountRepo;
use App\Repos\CourseUser as CourseUserRepo; use App\Repos\CourseUser as CourseUserRepo;
use App\Services\Logic\Course\CourseUserTrait; use App\Services\Logic\Course\CourseUserTrait;
use App\Validators\CourseUser as CourseUserValidator; use App\Validators\CourseUser as CourseUserValidator;
@ -20,6 +19,7 @@ class CourseUser extends Service
{ {
use CourseUserTrait; use CourseUserTrait;
use AccountSearchTrait;
public function getSourceTypes() public function getSourceTypes()
{ {
@ -53,24 +53,11 @@ class CourseUser extends Service
$params = $pagerQuery->getParams(); $params = $pagerQuery->getParams();
$params = $this->handleAccountSearchParams($params);
$params['course_id'] = $course->id; $params['course_id'] = $course->id;
$params['deleted'] = 0; $params['deleted'] = 0;
$accountRepo = new AccountRepo();
/**
* 兼容用户编号|手机号码|邮箱地址查询
*/
if (!empty($params['user_id'])) {
if (CommonValidator::phone($params['user_id'])) {
$account = $accountRepo->findByPhone($params['user_id']);
$params['user_id'] = $account ? $account->id : -1000;
} elseif (CommonValidator::email($params['user_id'])) {
$account = $accountRepo->findByEmail($params['user_id']);
$params['user_id'] = $account ? $account->id : -1000;
}
}
$sort = $pagerQuery->getSort(); $sort = $pagerQuery->getSort();
$page = $pagerQuery->getPage(); $page = $pagerQuery->getPage();
$limit = $pagerQuery->getLimit(); $limit = $pagerQuery->getLimit();

View File

@ -8,8 +8,9 @@
namespace App\Http\Admin\Services; namespace App\Http\Admin\Services;
use App\Builders\OrderList as OrderListBuilder; use App\Builders\OrderList as OrderListBuilder;
use App\Http\Admin\Services\Traits\AccountSearchTrait;
use App\Http\Admin\Services\Traits\OrderSearchTrait;
use App\Library\Paginator\Query as PaginateQuery; use App\Library\Paginator\Query as PaginateQuery;
use App\Library\Validators\Common as CommonValidator;
use App\Models\Order as OrderModel; use App\Models\Order as OrderModel;
use App\Repos\Account as AccountRepo; use App\Repos\Account as AccountRepo;
use App\Repos\Order as OrderRepo; use App\Repos\Order as OrderRepo;
@ -19,6 +20,9 @@ use App\Validators\Order as OrderValidator;
class Order extends Service class Order extends Service
{ {
use AccountSearchTrait;
use OrderSearchTrait;
public function getItemTypes() public function getItemTypes()
{ {
return OrderModel::itemTypes(); return OrderModel::itemTypes();
@ -35,32 +39,15 @@ class Order extends Service
$params = $pageQuery->getParams(); $params = $pageQuery->getParams();
$params = $this->handleAccountSearchParams($params);
$params = $this->handleOrderSearchParams($params);
if (!empty($params['order_id'])) {
$params['id'] = $params['order_id'];
}
$params['deleted'] = $params['deleted'] ?? 0; $params['deleted'] = $params['deleted'] ?? 0;
/**
* 兼容订单编号或订单序号查询
*/
if (isset($params['id']) && strlen($params['id']) > 10) {
$orderRepo = new OrderRepo();
$order = $orderRepo->findBySn($params['id']);
$params['id'] = $order ? $order->id : -1000;
}
$accountRepo = new AccountRepo();
/**
* 兼容用户编号|手机号码|邮箱地址查询
*/
if (!empty($params['owner_id'])) {
if (CommonValidator::phone($params['owner_id'])) {
$account = $accountRepo->findByPhone($params['owner_id']);
$params['owner_id'] = $account ? $account->id : -1000;
} elseif (CommonValidator::email($params['owner_id'])) {
$account = $accountRepo->findByEmail($params['owner_id']);
$params['owner_id'] = $account ? $account->id : -1000;
}
}
$sort = $pageQuery->getSort(); $sort = $pageQuery->getSort();
$page = $pageQuery->getPage(); $page = $pageQuery->getPage();
$limit = $pageQuery->getLimit(); $limit = $pageQuery->getLimit();

View File

@ -10,6 +10,7 @@ namespace App\Http\Admin\Services;
use App\Builders\QuestionList as QuestionListBuilder; use App\Builders\QuestionList as QuestionListBuilder;
use App\Builders\ReportList as ReportListBuilder; use App\Builders\ReportList as ReportListBuilder;
use App\Caches\Question as QuestionCache; use App\Caches\Question as QuestionCache;
use App\Http\Admin\Services\Traits\AccountSearchTrait;
use App\Library\Paginator\Query as PagerQuery; use App\Library\Paginator\Query as PagerQuery;
use App\Models\Category as CategoryModel; use App\Models\Category as CategoryModel;
use App\Models\Question as QuestionModel; use App\Models\Question as QuestionModel;
@ -33,6 +34,7 @@ class Question extends Service
{ {
use QuestionDataTrait; use QuestionDataTrait;
use AccountSearchTrait;
public function getXmTags($id) public function getXmTags($id)
{ {
@ -64,6 +66,8 @@ class Question extends Service
$params = $pagerQuery->getParams(); $params = $pagerQuery->getParams();
$params = $this->handleAccountSearchParams($params);
if (!empty($params['xm_tag_ids'])) { if (!empty($params['xm_tag_ids'])) {
$params['tag_id'] = explode(',', $params['xm_tag_ids']); $params['tag_id'] = explode(',', $params['xm_tag_ids']);
} }
@ -182,7 +186,7 @@ class Question extends Service
$data['published'] = $validator->checkPublishStatus($post['published']); $data['published'] = $validator->checkPublishStatus($post['published']);
} }
if (isset($post['category_id'])) { if (isset($post['category_id']) && !empty($post['category_id'])) {
$category = $validator->checkCategory($post['category_id']); $category = $validator->checkCategory($post['category_id']);
$data['category_id'] = $category->id; $data['category_id'] = $category->id;
} }

View File

@ -8,8 +8,9 @@
namespace App\Http\Admin\Services; namespace App\Http\Admin\Services;
use App\Builders\RefundList as RefundListBuilder; use App\Builders\RefundList as RefundListBuilder;
use App\Http\Admin\Services\Traits\AccountSearchTrait;
use App\Http\Admin\Services\Traits\OrderSearchTrait;
use App\Library\Paginator\Query as PaginateQuery; use App\Library\Paginator\Query as PaginateQuery;
use App\Library\Validators\Common as CommonValidator;
use App\Models\Refund as RefundModel; use App\Models\Refund as RefundModel;
use App\Models\Task as TaskModel; use App\Models\Task as TaskModel;
use App\Repos\Account as AccountRepo; use App\Repos\Account as AccountRepo;
@ -22,6 +23,9 @@ use App\Validators\Refund as RefundValidator;
class Refund extends Service class Refund extends Service
{ {
use AccountSearchTrait;
use OrderSearchTrait;
public function getStatusTypes() public function getStatusTypes()
{ {
return RefundModel::statusTypes(); return RefundModel::statusTypes();
@ -33,32 +37,11 @@ class Refund extends Service
$params = $pageQuery->getParams(); $params = $pageQuery->getParams();
$params = $this->handleAccountSearchParams($params);
$params = $this->handleOrderSearchParams($params);
$params['deleted'] = $params['deleted'] ?? 0; $params['deleted'] = $params['deleted'] ?? 0;
/**
* 兼容订单编号或订单序号查询
*/
if (isset($params['order_id']) && strlen($params['order_id']) > 10) {
$orderRepo = new OrderRepo();
$order = $orderRepo->findBySn($params['order_id']);
$params['order_id'] = $order ? $order->id : -1000;
}
$accountRepo = new AccountRepo();
/**
* 兼容用户编号|手机号码|邮箱地址查询
*/
if (!empty($params['owner_id'])) {
if (CommonValidator::phone($params['owner_id'])) {
$account = $accountRepo->findByPhone($params['owner_id']);
$params['owner_id'] = $account ? $account->id : -1000;
} elseif (CommonValidator::email($params['owner_id'])) {
$account = $accountRepo->findByEmail($params['owner_id']);
$params['owner_id'] = $account ? $account->id : -1000;
}
}
$sort = $pageQuery->getSort(); $sort = $pageQuery->getSort();
$page = $pageQuery->getPage(); $page = $pageQuery->getPage();
$limit = $pageQuery->getLimit(); $limit = $pageQuery->getLimit();

View File

@ -8,13 +8,12 @@
namespace App\Http\Admin\Services; namespace App\Http\Admin\Services;
use App\Builders\ReviewList as ReviewListBuilder; use App\Builders\ReviewList as ReviewListBuilder;
use App\Http\Admin\Services\Traits\AccountSearchTrait;
use App\Library\Paginator\Query as PagerQuery; use App\Library\Paginator\Query as PagerQuery;
use App\Library\Validators\Common as CommonValidator;
use App\Models\Course as CourseModel; use App\Models\Course as CourseModel;
use App\Models\Reason as ReasonModel; use App\Models\Reason as ReasonModel;
use App\Models\Review as ReviewModel; use App\Models\Review as ReviewModel;
use App\Models\User as UserModel; use App\Models\User as UserModel;
use App\Repos\Account as AccountRepo;
use App\Repos\Course as CourseRepo; use App\Repos\Course as CourseRepo;
use App\Repos\Review as ReviewRepo; use App\Repos\Review as ReviewRepo;
use App\Services\CourseStat as CourseStatService; use App\Services\CourseStat as CourseStatService;
@ -24,6 +23,8 @@ use App\Validators\Review as ReviewValidator;
class Review extends Service class Review extends Service
{ {
use AccountSearchTrait;
public function getPublishTypes() public function getPublishTypes()
{ {
return ReviewModel::publishTypes(); return ReviewModel::publishTypes();
@ -63,23 +64,10 @@ class Review extends Service
$params = $pagerQuery->getParams(); $params = $pagerQuery->getParams();
$params = $this->handleAccountSearchParams($params);
$params['deleted'] = $params['deleted'] ?? 0; $params['deleted'] = $params['deleted'] ?? 0;
$accountRepo = new AccountRepo();
/**
* 兼容用户编号|手机号码|邮箱地址查询
*/
if (!empty($params['owner_id'])) {
if (CommonValidator::phone($params['owner_id'])) {
$account = $accountRepo->findByPhone($params['owner_id']);
$params['owner_id'] = $account ? $account->id : -1000;
} elseif (CommonValidator::email($params['owner_id'])) {
$account = $accountRepo->findByEmail($params['owner_id']);
$params['owner_id'] = $account ? $account->id : -1000;
}
}
$sort = $pagerQuery->getSort(); $sort = $pagerQuery->getSort();
$page = $pagerQuery->getPage(); $page = $pagerQuery->getPage();
$limit = $pagerQuery->getLimit(); $limit = $pagerQuery->getLimit();

View File

@ -172,10 +172,20 @@ class Role extends Service
} }
if (in_array('admin.category.list', $routes)) { if (in_array('admin.category.list', $routes)) {
$list[] = 'admin.article.category';
$list[] = 'admin.question.category';
$list[] = 'admin.course.category'; $list[] = 'admin.course.category';
$list[] = 'admin.help.category'; $list[] = 'admin.help.category';
} }
if (in_array('admin.article.category', $routes)) {
$list[] = 'admin.category.list';
}
if (in_array('admin.question.category', $routes)) {
$list[] = 'admin.category.list';
}
if (in_array('admin.course.category', $routes)) { if (in_array('admin.course.category', $routes)) {
$list[] = 'admin.category.list'; $list[] = 'admin.category.list';
} }

View File

@ -8,8 +8,9 @@
namespace App\Http\Admin\Services; namespace App\Http\Admin\Services;
use App\Builders\TradeList as TradeListBuilder; use App\Builders\TradeList as TradeListBuilder;
use App\Http\Admin\Services\Traits\AccountSearchTrait;
use App\Http\Admin\Services\Traits\OrderSearchTrait;
use App\Library\Paginator\Query as PaginateQuery; use App\Library\Paginator\Query as PaginateQuery;
use App\Library\Validators\Common as CommonValidator;
use App\Models\Refund as RefundModel; use App\Models\Refund as RefundModel;
use App\Models\Trade as TradeModel; use App\Models\Trade as TradeModel;
use App\Repos\Account as AccountRepo; use App\Repos\Account as AccountRepo;
@ -22,6 +23,9 @@ use App\Validators\Trade as TradeValidator;
class Trade extends Service class Trade extends Service
{ {
use AccountSearchTrait;
use OrderSearchTrait;
public function getChannelTypes() public function getChannelTypes()
{ {
return TradeModel::channelTypes(); return TradeModel::channelTypes();
@ -38,29 +42,8 @@ class Trade extends Service
$params = $pageQuery->getParams(); $params = $pageQuery->getParams();
/** $params = $this->handleAccountSearchParams($params);
* 兼容订单编号或订单序号查询 $params = $this->handleOrderSearchParams($params);
*/
if (isset($params['order_id']) && strlen($params['order_id']) > 10) {
$orderRepo = new OrderRepo();
$order = $orderRepo->findBySn($params['order_id']);
$params['order_id'] = $order ? $order->id : -1000;
}
$accountRepo = new AccountRepo();
/**
* 兼容用户编号|手机号码|邮箱地址查询
*/
if (!empty($params['owner_id'])) {
if (CommonValidator::phone($params['owner_id'])) {
$account = $accountRepo->findByPhone($params['owner_id']);
$params['owner_id'] = $account ? $account->id : -1000;
} elseif (CommonValidator::email($params['owner_id'])) {
$account = $accountRepo->findByEmail($params['owner_id']);
$params['owner_id'] = $account ? $account->id : -1000;
}
}
$sort = $pageQuery->getSort(); $sort = $pageQuery->getSort();
$page = $pageQuery->getPage(); $page = $pageQuery->getPage();

View File

@ -0,0 +1,49 @@
<?php
/**
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
* @license https://opensource.org/licenses/GPL-2.0
* @link https://www.koogua.com
*/
namespace App\Http\Admin\Services\Traits;
use App\Library\Validators\Common as CommonValidator;
use App\Repos\Account as AccountRepo;
trait AccountSearchTrait
{
protected function handleAccountSearchParams($params)
{
$accountRepo = new AccountRepo();
/**
* 兼容用户编号|手机号码|邮箱地址查询
*/
if (!empty($params['user_id'])) {
if (CommonValidator::phone($params['user_id'])) {
$account = $accountRepo->findByPhone($params['user_id']);
$params['user_id'] = $account ? $account->id : -1000;
} elseif (CommonValidator::email($params['user_id'])) {
$account = $accountRepo->findByEmail($params['user_id']);
$params['user_id'] = $account ? $account->id : -1000;
}
}
/**
* 兼容用户编号|手机号码|邮箱地址查询
*/
if (!empty($params['owner_id'])) {
if (CommonValidator::phone($params['owner_id'])) {
$account = $accountRepo->findByPhone($params['owner_id']);
$params['owner_id'] = $account ? $account->id : -1000;
} elseif (CommonValidator::email($params['owner_id'])) {
$account = $accountRepo->findByEmail($params['owner_id']);
$params['owner_id'] = $account ? $account->id : -1000;
}
}
return $params;
}
}

View File

@ -0,0 +1,32 @@
<?php
/**
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
* @license https://opensource.org/licenses/GPL-2.0
* @link https://www.koogua.com
*/
namespace App\Http\Admin\Services\Traits;
use App\Repos\Order as OrderRepo;
trait OrderSearchTrait
{
protected function handleOrderSearchParams($params)
{
/**
* 兼容订单编号或订单序号查询
*/
if (!empty($params['order_id']) && strlen($params['order_id']) > 10) {
$orderRepo = new OrderRepo();
$order = $orderRepo->findBySn($params['order_id']);
$params['order_id'] = $order ? $order->id : -1000;
}
return $params;
}
}

View File

@ -9,9 +9,9 @@ namespace App\Http\Admin\Services;
use App\Builders\UserList as UserListBuilder; use App\Builders\UserList as UserListBuilder;
use App\Caches\User as UserCache; use App\Caches\User as UserCache;
use App\Http\Admin\Services\Traits\AccountSearchTrait;
use App\Library\Paginator\Query as PaginateQuery; use App\Library\Paginator\Query as PaginateQuery;
use App\Library\Utils\Password as PasswordUtil; use App\Library\Utils\Password as PasswordUtil;
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\Models\User as UserModel;
use App\Repos\Account as AccountRepo; use App\Repos\Account as AccountRepo;
@ -26,6 +26,8 @@ use App\Validators\User as UserValidator;
class User extends Service class User extends Service
{ {
use AccountSearchTrait;
public function getEduRoleTypes() public function getEduRoleTypes()
{ {
return UserModel::eduRoleTypes(); return UserModel::eduRoleTypes();
@ -63,19 +65,10 @@ class User extends Service
$params = $pageQuery->getParams(); $params = $pageQuery->getParams();
$accountRepo = new AccountRepo(); $params = $this->handleAccountSearchParams($params);
/** if (!empty($params['user_id'])) {
* 兼容用户编号|手机号码|邮箱地址查询 $params['id'] = $params['user_id'];
*/
if (!empty($params['id'])) {
if (CommonValidator::phone($params['id'])) {
$account = $accountRepo->findByPhone($params['id']);
$params['id'] = $account ? $account->id : -1000;
} elseif (CommonValidator::email($params['id'])) {
$account = $accountRepo->findByEmail($params['id']);
$params['id'] = $account ? $account->id : -1000;
}
} }
$params['deleted'] = $params['deleted'] ?? 0; $params['deleted'] = $params['deleted'] ?? 0;

View File

@ -19,9 +19,9 @@
</div> </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>
<div class="layui-input-block"> <div class="layui-input-block">
<input class="layui-input" type="text" name="owner_id" placeholder="用户编号精确匹配"> <input class="layui-input" type="text" name="owner_id" placeholder="用户编号 / 手机号码 / 邮箱地址 精确匹配">
</div> </div>
</div> </div>
<div class="layui-form-item" id="time-range"> <div class="layui-form-item" id="time-range">
@ -64,7 +64,7 @@
<script> <script>
layui.use(['jquery', 'laydate'], function () { layui.use(['laydate'], function () {
var laydate = layui.laydate; var laydate = layui.laydate;

View File

@ -13,9 +13,9 @@
</div> </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>
<div class="layui-input-block"> <div class="layui-input-block">
<input class="layui-input" type="text" name="owner_id" placeholder="作者编号精确匹配"> <input class="layui-input" type="text" name="owner_id" placeholder="用户编号 / 手机号码 / 邮箱地址 精确匹配">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
@ -97,7 +97,7 @@
<script> <script>
layui.use(['jquery', 'laydate'], function () { layui.use(['laydate'], function () {
var laydate = layui.laydate; var laydate = layui.laydate;

View File

@ -2,6 +2,40 @@
{% block content %} {% block content %}
{{ partial('macros/course') }}
{%- macro attrs_info(model,attrs) %}
{% if model == 1 %}
<span>类型:{{ model_type(model) }}</span>
{% if attrs['duration'] > 0 %}
<span>时长:{{ attrs['duration']|duration }}</span>
{% else %}
<span>时长N/A</span>
{% endif %}
{% elseif model == 2 %}
<span>类型:{{ model_type(model) }}</span>
{% if attrs['start_time'] > 0 %}
<span>时间:{{ date('Y-m-d H:i',attrs['start_time']) }}</span>
{% else %}
<span>时间N/A</span>
{% endif %}
{% elseif model == 3 %}
<span>类型:{{ model_type(model) }}</span>
{% if attrs['word_count'] > 0 %}
<span>字数:{{ attrs['word_count'] }}</span>
{% else %}
<span>字数N/A</span>
{% endif %}
{% elseif model == 4 %}
<span>类型:{{ model_type(model) }}</span>
{% if attrs['start_time'] > 0 %}
<span>时间:{{ date('Y-m-d H:i',attrs['start_time']) }}</span>
{% else %}
<span>时间N/A</span>
{% endif %}
{% endif %}
{%- endmacro %}
{% set back_url = url({'for':'admin.course.chapters','id':course.id}) %} {% set back_url = url({'for':'admin.course.chapters','id':course.id}) %}
{% set add_chapter_url = url({'for':'admin.chapter.add'},{'type':'chapter','course_id':course.id}) %} {% set add_chapter_url = url({'for':'admin.chapter.add'},{'type':'chapter','course_id':course.id}) %}
{% set add_lesson_url = url({'for':'admin.chapter.add'},{'type':'lesson','course_id':course.id,'parent_id':chapter.id}) %} {% set add_lesson_url = url({'for':'admin.chapter.add'},{'type':'lesson','course_id':course.id,'parent_id':chapter.id}) %}
@ -21,14 +55,75 @@
</div> </div>
</div> </div>
{% if course.model == 1 %} <table class="layui-table layui-form kg-table">
{{ partial('chapter/lessons_vod') }} <colgroup>
{% elseif course.model == 2 %} <col>
{{ partial('chapter/lessons_live') }} <col>
{% elseif course.model == 3 %} <col>
{{ partial('chapter/lessons_read') }} <col>
{% elseif course.model == 4 %} <col>
{{ partial('chapter/lessons_offline') }} <col>
{% endif %} <col>
<col width="10%">
</colgroup>
<thead>
<tr>
<th>名称</th>
<th>学员</th>
<th>点赞</th>
<th>评论</th>
<th>排序</th>
<th>免费</th>
<th>发布</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for item in lessons %}
{% set chapter_url = url({'for':'home.chapter.show','id':item.id}) %}
{% set edit_url = url({'for':'admin.chapter.edit','id':item.id}) %}
{% set update_url = url({'for':'admin.chapter.update','id':item.id}) %}
{% set delete_url = url({'for':'admin.chapter.delete','id':item.id}) %}
{% set restore_url = url({'for':'admin.chapter.restore','id':item.id}) %}
{% set comments_url = url({'for':'admin.comment.list'},{'item_id':item.id,'item_type':1}) %}
<tr>
<td>
<p>
<a href="{{ edit_url }}">{{ item.title }}</a>
<span>({{ item.id }})</span>
<span class="layui-badge layui-bg-green">课</span>
</p>
<p>{{ attrs_info(item.model,item.attrs) }}</p>
</td>
<td>{{ item.user_count }}</td>
<td>{{ item.like_count }}</td>
<td>{{ item.comment_count }}</td>
<td><input class="layui-input kg-priority" type="text" name="priority" title="数值越小排序越靠前" value="{{ item.priority }}" data-url="{{ update_url }}"></td>
<td><input type="checkbox" name="free" value="1" lay-text="是|否" lay-skin="switch" lay-filter="go" data-url="{{ update_url }}" {% if item.free == 1 %}checked="checked"{% endif %}>
</td>
<td><input type="checkbox" name="published" value="1" lay-text="是|否" lay-skin="switch" lay-filter="go" data-url="{{ update_url }}"
{% if item.published == 1 %}checked="checked"{% endif %}></td>
<td class="center">
<div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul>
{% if item.published == 1 %}
<li><a href="{{ chapter_url }}" target="_blank">浏览课时</a></li>
{% endif %}
<li><a href="{{ edit_url }}">编辑课时</a></li>
{% if item.deleted == 0 %}
<li><a href="javascript:" class="kg-delete" data-url="{{ delete_url }}">删除课时</a></li>
{% else %}
<li><a href="javascript:" class="kg-restore" data-url="{{ restore_url }}">还原课时</a></li>
{% endif %}
<hr>
<li><a href="{{ comments_url }}">评论管理</a></li>
</ul>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %} {% endblock %}

View File

@ -1,88 +0,0 @@
{%- macro live_time_info(attrs) %}
{% if attrs['start_time'] > 0 %}
<p>开始:{{ date('Y-m-d H:i',attrs['start_time']) }}</p>
<p>结束:{{ date('Y-m-d H:i',attrs['end_time']) }}</p>
{% else %}
N/A
{% endif %}
{%- endmacro %}
{%- macro live_status_info(status) %}
{% if status == 'active' %}
<span class="layui-badge layui-bg-blue">活跃</span>
{% elseif status == 'inactive' %}
<span class="layui-badge layui-bg-gray">沉默</span>
{% elseif status == 'forbid' %}
<span class="layui-badge layui-bg-red">禁播</span>
{% endif %}
{%- endmacro %}
<table class="layui-table layui-form kg-table">
<colgroup>
<col>
<col>
<col>
<col>
<col>
<col>
<col>
<col>
<col>
<col width="10%">
</colgroup>
<thead>
<tr>
<th>编号</th>
<th>名称</th>
<th>学员</th>
<th>点赞</th>
<th>时间</th>
<th>推流</th>
<th>排序</th>
<th>免费</th>
<th>发布</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for item in lessons %}
{% set chapter_url = url({'for':'home.chapter.show','id':item.id}) %}
{% set edit_url = url({'for':'admin.chapter.edit','id':item.id}) %}
{% set update_url = url({'for':'admin.chapter.update','id':item.id}) %}
{% set delete_url = url({'for':'admin.chapter.delete','id':item.id}) %}
{% set restore_url = url({'for':'admin.chapter.restore','id':item.id}) %}
<tr>
<td>{{ item.id }}</td>
<td>
<a href="{{ edit_url }}">{{ item.title }}</a>
<span class="layui-badge layui-bg-green">课</span>
</td>
<td>{{ item.user_count }}</td>
<td>{{ item.like_count }}</td>
<td>{{ live_time_info(item.attrs) }}</td>
<td>{{ live_status_info(item.attrs['stream']['status']) }}</td>
<td><input class="layui-input kg-priority" type="text" name="priority" title="数值越小排序越靠前" value="{{ item.priority }}" data-url="{{ update_url }}"></td>
<td><input type="checkbox" name="free" value="1" lay-text="是|否" lay-skin="switch" lay-filter="go" data-url="{{ update_url }}"
{% if item.free == 1 %}checked="checked"{% endif %}></td>
<td><input type="checkbox" name="published" value="1" lay-text="是|否" lay-skin="switch" lay-filter="go" data-url="{{ update_url }}"
{% if item.published == 1 %}checked="checked"{% endif %}></td>
<td class="center">
<div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul>
{% if item.published == 1 %}
<li><a href="{{ chapter_url }}" target="_blank">浏览</a></li>
{% endif %}
<li><a href="{{ edit_url }}">编辑</a></li>
{% if item.deleted == 0 %}
<li><a href="javascript:" class="kg-delete" data-url="{{ delete_url }}">删除</a></li>
{% else %}
<li><a href="javascript:" class="kg-restore" data-url="{{ delete_url }}">还原</a></li>
{% endif %}
</ul>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>

View File

@ -1,65 +0,0 @@
{%- macro offline_time_info(attrs) %}
{% if attrs['start_time'] > 0 %}
<p>开始:{{ date('Y-m-d H:i',attrs['start_time']) }}</p>
<p>结束:{{ date('Y-m-d H:i',attrs['end_time']) }}</p>
{% else %}
N/A
{% endif %}
{%- endmacro %}
<table class="layui-table layui-form kg-table">
<colgroup>
<col>
<col>
<col>
<col>
<col>
<col>
<col width="12%">
</colgroup>
<thead>
<tr>
<th>编号</th>
<th>名称</th>
<th>时间</th>
<th>排序</th>
<th>免费</th>
<th>发布</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for item in lessons %}
{% set edit_url = url({'for':'admin.chapter.edit','id':item.id}) %}
{% set update_url = url({'for':'admin.chapter.update','id':item.id}) %}
{% set delete_url = url({'for':'admin.chapter.delete','id':item.id}) %}
{% set restore_url = url({'for':'admin.chapter.restore','id':item.id}) %}
<tr>
<td>{{ item.id }}</td>
<td>
<span><a href="{{ edit_url }}">{{ item.title }}</a></span>
<span class="layui-badge layui-bg-green">课</span>
</td>
<td>{{ offline_time_info(item.attrs) }}</td>
<td><input class="layui-input kg-priority" type="text" name="priority" title="数值越小排序越靠前" value="{{ item.priority }}" data-url="{{ update_url }}"></td>
<td><input type="checkbox" name="free" value="1" lay-text="是|否" lay-skin="switch" lay-filter="go" data-url="{{ update_url }}"
{% if item.free == 1 %}checked="checked"{% endif %}></td>
<td><input type="checkbox" name="published" value="1" lay-text="是|否" lay-skin="switch" lay-filter="go" data-url="{{ update_url }}"
{% if item.published == 1 %}checked="checked"{% endif %}></td>
<td class="center">
<div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul>
<li><a href="{{ edit_url }}">编辑</a></li>
{% if item.deleted == 0 %}
<li><a href="javascript:" class="kg-delete" data-url="{{ delete_url }}">删除</a></li>
{% else %}
<li><a href="javascript:" class="kg-restore" data-url="{{ delete_url }}">还原</a></li>
{% endif %}
</ul>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>

View File

@ -1,71 +0,0 @@
<table class="layui-table layui-form kg-table">
<colgroup>
<col>
<col>
<col>
<col>
<col>
<col>
<col>
<col>
<col width="10%">
</colgroup>
<thead>
<tr>
<th>编号</th>
<th>名称</th>
<th>学员</th>
<th>点赞</th>
<th>评论</th>
<th>排序</th>
<th>免费</th>
<th>发布</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for item in lessons %}
{% set chapter_url = url({'for':'home.chapter.show','id':item.id}) %}
{% set edit_url = url({'for':'admin.chapter.edit','id':item.id}) %}
{% set update_url = url({'for':'admin.chapter.update','id':item.id}) %}
{% set delete_url = url({'for':'admin.chapter.delete','id':item.id}) %}
{% set restore_url = url({'for':'admin.chapter.restore','id':item.id}) %}
{% set comments_url = url({'for':'admin.comment.list'},{'item_id':item.id,'item_type':1}) %}
<tr>
<td>{{ item.id }}</td>
<td>
<p>
<a href="{{ edit_url }}">{{ item.title }}</a>
<span class="layui-badge layui-bg-green">课</span>
</p>
</td>
<td>{{ item.user_count }}</td>
<td>{{ item.like_count }}</td>
<td>{{ item.comment_count }}</td>
<td><input class="layui-input kg-priority" type="text" name="priority" title="数值越小排序越靠前" value="{{ item.priority }}" data-url="{{ update_url }}"></td>
<td><input type="checkbox" name="free" value="1" lay-text="是|否" lay-skin="switch" lay-filter="go" data-url="{{ update_url }}"
{% if item.free == 1 %}checked="checked"{% endif %}></td>
<td><input type="checkbox" name="published" value="1" lay-text="是|否" lay-skin="switch" lay-filter="go" data-url="{{ update_url }}"
{% if item.published == 1 %}checked="checked"{% endif %}></td>
<td class="center">
<div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul>
{% if item.published == 1 %}
<li><a href="{{ chapter_url }}" target="_blank">浏览</a></li>
{% endif %}
<li><a href="{{ edit_url }}">编辑</a></li>
{% if item.deleted == 0 %}
<li><a href="javascript:" class="kg-delete" data-url="{{ delete_url }}">删除</a></li>
{% else %}
<li><a href="javascript:" class="kg-restore" data-url="{{ restore_url }}">还原</a></li>
{% endif %}
<hr>
<li><a href="{{ comments_url }}">评论管理</a></li>
</ul>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>

View File

@ -1,89 +0,0 @@
{%- macro file_status(value) %}
{% if value == 'pending' %}
待上传
{% elseif value == 'uploaded' %}
已上传
{% elseif value == 'translating' %}
转码中
{% elseif value == 'translated' %}
已转码
{% elseif value == 'failed' %}
已失败
{% endif %}
{%- endmacro %}
<table class="layui-table layui-form kg-table">
<colgroup>
<col>
<col>
<col>
<col>
<col>
<col>
<col>
<col>
<col width="10%">
</colgroup>
<thead>
<tr>
<th>编号</th>
<th>名称</th>
<th>学员</th>
<th>点赞</th>
<th>评论</th>
<th>排序</th>
<th>免费</th>
<th>发布</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for item in lessons %}
{% set chapter_url = url({'for':'home.chapter.show','id':item.id}) %}
{% set edit_url = url({'for':'admin.chapter.edit','id':item.id}) %}
{% set update_url = url({'for':'admin.chapter.update','id':item.id}) %}
{% set delete_url = url({'for':'admin.chapter.delete','id':item.id}) %}
{% set restore_url = url({'for':'admin.chapter.restore','id':item.id}) %}
{% set comments_url = url({'for':'admin.comment.list'},{'item_id':item.id,'item_type':1}) %}
<tr>
<td>{{ item.id }}</td>
<td>
<p>
<a href="{{ edit_url }}">{{ item.title }}</a>
<span class="layui-badge layui-bg-green">课</span>
</p>
<p class="meta">
<span>状态:{{ file_status(item.attrs['file']['status']) }}</span>
<span>时长:{{ item.attrs['duration']|duration }}</span>
</p>
</td>
<td>{{ item.user_count }}</td>
<td>{{ item.like_count }}</td>
<td>{{ item.comment_count }}</td>
<td><input class="layui-input kg-priority" type="text" name="priority" title="数值越小排序越靠前" value="{{ item.priority }}" data-url="{{ update_url }}"></td>
<td><input type="checkbox" name="free" value="1" lay-text="是|否" lay-skin="switch" lay-filter="go" data-url="{{ update_url }}"
{% if item.free == 1 %}checked="checked"{% endif %}></td>
<td><input type="checkbox" name="published" value="1" lay-text="是|否" lay-skin="switch" lay-filter="go" data-url="{{ update_url }}"
{% if item.published == 1 %}checked="checked"{% endif %}></td>
<td class="center">
<div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul>
{% if item.published == 1 %}
<li><a href="{{ chapter_url }}" target="_blank">浏览</a></li>
{% endif %}
<li><a href="{{ edit_url }}">编辑</a></li>
{% if item.deleted == 0 %}
<li><a href="javascript:" class="kg-delete" data-url="{{ delete_url }}">删除</a></li>
{% else %}
<li><a href="javascript:" class="kg-restore" data-url="{{ restore_url }}">还原</a></li>
{% endif %}
<hr>
<li><a href="{{ comments_url }}">评论管理</a></li>
</ul>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>

View File

@ -20,7 +20,8 @@
<table class="layui-table layui-form kg-table"> <table class="layui-table layui-form kg-table">
<colgroup> <colgroup>
<col width="50%"> <col width="5%">
<col>
<col> <col>
<col> <col>
<col> <col>
@ -29,7 +30,8 @@
</colgroup> </colgroup>
<thead> <thead>
<tr> <tr>
<th>作者</th> <th><input class="all" type="checkbox" lay-filter="all"></th>
<th>用户</th>
<th>内容</th> <th>内容</th>
<th>回复</th> <th>回复</th>
<th>点赞</th> <th>点赞</th>
@ -44,19 +46,25 @@
{% set delete_url = url({'for':'admin.comment.delete','id':item.id}) %} {% set delete_url = url({'for':'admin.comment.delete','id':item.id}) %}
{% set restore_url = url({'for':'admin.comment.restore','id':item.id}) %} {% set restore_url = url({'for':'admin.comment.restore','id':item.id}) %}
<tr> <tr>
<td><a href="{{ owner_url }}" target="_blank">{{ item.owner.name }}</a>{{ item.owner.id }}</td> <td><input class="item" type="checkbox" value="{{ item.id }}" lay-filter="item"></td>
<td><a href="{{ owner_url }}">{{ item.owner.name }}</a></td>
<td> <td>
<p class="layui-elip kg-item-elip" title="{{ item.content }}">{{ item.content }}</p> <p class="layui-elip kg-item-elip" title="{{ item.content }}">{{ item.content }}</p>
</td> </td>
<td>{{ item.reply_count }}</td> <td>{{ item.reply_count }}</td>
<td>{{ item.like_count }}</td> <td>{{ item.like_count }}</td>
<td>{{ date('Y-m-d',item.create_time) }}</td> <td>{{ date('Y-m-d H:i:s',item.create_time) }}</td>
<td class="center"> <td class="center">
{% if item.deleted == 0 %} <div class="kg-dropdown">
<a href="javascript:" class="layui-badge layui-bg-red kg-delete" data-url="{{ delete_url }}">删除</a> <button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
{% else %} <ul>
<a href="javascript:" class="layui-badge layui-bg-green kg-restore" data-url="{{ restore_url }}">还原</a> {% if item.deleted == 0 %}
{% endif %} <li><a href="javascript:" class="kg-delete" data-url="{{ delete_url }}">删除评论</a></li>
{% else %}
<li><a href="javascript:" class="kg-restore" data-url="{{ restore_url }}">还原评论</a></li>
{% endif %}
</ul>
</div>
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}

View File

@ -77,7 +77,7 @@
<script> <script>
layui.use(['jquery', 'laydate'], function () { layui.use(['laydate'], function () {
xmSelect.render({ xmSelect.render({
el: '#xm-course-id', el: '#xm-course-id',

View File

@ -65,11 +65,11 @@
<div class="kg-dropdown"> <div class="kg-dropdown">
<button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button> <button class="layui-btn layui-btn-sm">操作 <i class="layui-icon layui-icon-triangle-d"></i></button>
<ul> <ul>
<li><a href="{{ edit_url }}">编辑</a></li> <li><a href="{{ edit_url }}">编辑章节</a></li>
{% if item.deleted == 0 %} {% if item.deleted == 0 %}
<li><a href="javascript:" class="kg-delete" data-url="{{ delete_url }}">删除</a></li> <li><a href="javascript:" class="kg-delete" data-url="{{ delete_url }}">删除章节</a></li>
{% else %} {% else %}
<li><a href="javascript:" class="kg-restore" data-url="{{ restore_url }}">还原</a></li> <li><a href="javascript:" class="kg-restore" data-url="{{ restore_url }}">还原章节</a></li>
{% endif %} {% endif %}
</ul> </ul>
</div> </div>

View File

@ -109,7 +109,7 @@
<script> <script>
layui.use(['jquery', 'laydate'], function () { layui.use(['laydate'], function () {
var laydate = layui.laydate; var laydate = layui.laydate;

View File

@ -59,7 +59,7 @@
<script> <script>
layui.use(['jquery', 'laydate'], function () { layui.use(['laydate'], function () {
var laydate = layui.laydate; var laydate = layui.laydate;

View File

@ -13,9 +13,9 @@
</div> </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>
<div class="layui-input-block"> <div class="layui-input-block">
<input class="layui-input" type="text" name="owner_id" placeholder="作者编号精确匹配"> <input class="layui-input" type="text" name="owner_id" placeholder="用户编号 / 手机号码 / 邮箱地址 精确匹配">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
@ -89,7 +89,7 @@
<script> <script>
layui.use(['jquery', 'laydate'], function () { layui.use(['laydate'], function () {
var laydate = layui.laydate; var laydate = layui.laydate;

View File

@ -51,7 +51,7 @@
<script> <script>
layui.use(['jquery', 'laydate'], function () { layui.use(['laydate'], function () {
var laydate = layui.laydate; var laydate = layui.laydate;

View File

@ -77,7 +77,7 @@
<script> <script>
layui.use(['jquery', 'laydate'], function () { layui.use(['laydate'], function () {
xmSelect.render({ xmSelect.render({
el: '#xm-course-id', el: '#xm-course-id',

View File

@ -57,7 +57,7 @@
<script> <script>
layui.use(['jquery', 'laydate'], function () { layui.use(['laydate'], function () {
var laydate = layui.laydate; var laydate = layui.laydate;

View File

@ -57,7 +57,7 @@
<script> <script>
layui.use(['jquery', 'laydate'], function () { layui.use(['laydate'], function () {
var laydate = layui.laydate; var laydate = layui.laydate;

View File

@ -59,7 +59,7 @@
<script> <script>
layui.use(['jquery', 'laydate'], function () { layui.use(['laydate'], function () {
var laydate = layui.laydate; var laydate = layui.laydate;

View File

@ -9,7 +9,7 @@
<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 class="layui-input" type="text" name="id" placeholder="用户编号 / 手机号码 / 邮箱地址 精确匹配"> <input class="layui-input" type="text" name="user_id" placeholder="用户编号 / 手机号码 / 邮箱地址 精确匹配">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
@ -83,7 +83,7 @@
<script> <script>
layui.use(['jquery', 'laydate'], function () { layui.use(['laydate'], function () {
var laydate = layui.laydate; var laydate = layui.laydate;

View File

@ -11,7 +11,6 @@ use App\Models\User as UserModel;
use App\Services\Auth\Api as ApiAuth; use App\Services\Auth\Api as ApiAuth;
use App\Traits\Response as ResponseTrait; use App\Traits\Response as ResponseTrait;
use App\Traits\Security as SecurityTrait; use App\Traits\Security as SecurityTrait;
use App\Validators\Validator as AppValidator;
use Phalcon\Mvc\Dispatcher; use Phalcon\Mvc\Dispatcher;
class Controller extends \Phalcon\Mvc\Controller class Controller extends \Phalcon\Mvc\Controller
@ -31,10 +30,6 @@ class Controller extends \Phalcon\Mvc\Controller
$this->setCors(); $this->setCors();
} }
$validator = new AppValidator();
$validator->checkSiteStatus();
$this->checkRateLimit(); $this->checkRateLimit();
return true; return true;

View File

@ -102,7 +102,7 @@ class Controller extends \Phalcon\Mvc\Controller
$this->view->setVar('websocket_info', $this->websocketInfo); $this->view->setVar('websocket_info', $this->websocketInfo);
} }
protected function getAuthUser($cache = false) protected function getAuthUser($cache = true)
{ {
/** /**
* @var HomeAuth $auth * @var HomeAuth $auth

View File

@ -53,7 +53,7 @@
{% if free_courses|length > 0 %} {% if free_courses|length > 0 %}
<div class="index-wrap wrap"> <div class="index-wrap wrap">
<div class="header">免费课程</div> <div class="header">免费课程</div>
<div class="content"> <div class="content simple">
{{ show_courses(free_courses) }} {{ show_courses(free_courses) }}
</div> </div>
</div> </div>

View File

@ -29,7 +29,7 @@
<a class="qq" href="{{ link_url }}" title="客服QQ{{ contact_info.qq }}"><span class="iconfont icon-qq"></span></a> <a class="qq" href="{{ link_url }}" title="客服QQ{{ contact_info.qq }}"><span class="iconfont icon-qq"></span></a>
{% endif %} {% endif %}
{% if contact_info.wechat %} {% if contact_info.wechat %}
<a class="wechat" href="javascript:" title="微信公众号"><span class="iconfont icon-wechat"></span></a> <a class="wechat" href="javascript:" title="微信"><span class="iconfont icon-wechat"></span></a>
{% endif %} {% endif %}
{% if contact_info.toutiao %} {% if contact_info.toutiao %}
<a class="toutiao" href="javascript:" title="头条号"><span class="iconfont icon-toutiao"></span></a> <a class="toutiao" href="javascript:" title="头条号"><span class="iconfont icon-toutiao"></span></a>

View File

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

View File

@ -8,50 +8,19 @@
namespace App\Listeners; namespace App\Listeners;
use App\Services\Service as AppService; use App\Services\Service as AppService;
use App\Traits\Auth as AuthTrait; use App\Traits\Service as ServiceTrait;
use Phalcon\Mvc\User\Plugin as UserPlugin; use Phalcon\Mvc\User\Plugin as UserPlugin;
class Listener extends UserPlugin class Listener extends UserPlugin
{ {
use AuthTrait; use ServiceTrait;
public function getConfig() public function getLogger($channel = 'listen')
{ {
$appService = new AppService(); $appService = new AppService();
return $appService->getConfig();
}
public function getCache()
{
$appService = new AppService();
return $appService->getCache();
}
public function getRedis()
{
$appService = new AppService();
return $appService->getRedis();
}
public function getLogger($channel = null)
{
$appService = new AppService();
$channel = $channel ?: 'listen';
return $appService->getLogger($channel); return $appService->getLogger($channel);
} }
public function getSettings($section)
{
$appService = new AppService();
return $appService->getSettings($section);
}
} }

View File

@ -186,7 +186,7 @@ class Live extends Service
* @param string $appName * @param string $appName
* @return string * @return string
*/ */
function getPushUrl($streamName, $appName = 'live') public function getPushUrl($streamName, $appName = 'live')
{ {
$authEnabled = $this->settings['push']['auth_enabled']; $authEnabled = $this->settings['push']['auth_enabled'];
$authKey = $this->settings['push']['auth_key']; $authKey = $this->settings['push']['auth_key'];

View File

@ -8,25 +8,14 @@
namespace App\Validators; namespace App\Validators;
use App\Exceptions\Forbidden as ForbiddenException; use App\Exceptions\Forbidden as ForbiddenException;
use App\Exceptions\ServiceUnavailable;
use App\Exceptions\ServiceUnavailable as ServiceUnavailableException;
use App\Exceptions\Unauthorized as UnauthorizedException; use App\Exceptions\Unauthorized as UnauthorizedException;
use App\Services\Service as AppService; use App\Traits\Service as ServiceTrait;
use Phalcon\Di\Injectable; use Phalcon\Di\Injectable;
class Validator extends Injectable class Validator extends Injectable
{ {
public function checkSiteStatus() use ServiceTrait;
{
$service = new AppService();
$siteInfo = $service->getSettings('site');
if ($siteInfo['status'] == 'closed') {
throw new ServiceUnavailableException('sys.service_unavailable');
}
}
public function checkAuthUser($userId) public function checkAuthUser($userId)
{ {

View File

@ -17,16 +17,9 @@ class ConsoleErrorHandler extends Injectable
public function __construct() public function __construct()
{ {
set_error_handler([$this, 'handleError']);
set_exception_handler([$this, 'handleException']); set_exception_handler([$this, 'handleException']);
} }
public function handleError($severity, $message, $file, $line)
{
throw new \ErrorException($message, 0, $severity, $file, $line);
}
/** /**
* @param \Throwable $e * @param \Throwable $e
*/ */

View File

@ -21,16 +21,9 @@ class HttpErrorHandler extends Injectable
public function __construct() public function __construct()
{ {
set_error_handler([$this, 'handleError']);
set_exception_handler([$this, 'handleException']); set_exception_handler([$this, 'handleException']);
} }
public function handleError($severity, $message, $file, $line)
{
throw new \ErrorException($message, 0, $severity, $file, $line);
}
/** /**
* @param \Throwable $e * @param \Throwable $e
*/ */

View File

@ -20,7 +20,6 @@
"robmorgan/phinx": "^0.12", "robmorgan/phinx": "^0.12",
"overtrue/wechat": "^4.2", "overtrue/wechat": "^4.2",
"endroid/qr-code": "^3.9", "endroid/qr-code": "^3.9",
"league/commonmark": "^1.5",
"ezyang/htmlpurifier": "^4.14", "ezyang/htmlpurifier": "^4.14",
"zoujingli/ip2region": "^2.0" "zoujingli/ip2region": "^2.0"
}, },

290
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "a5d21272eaa0df8bfcd5a3cea6d61fad", "content-hash": "bfecc23cb2b7b3ba13d4d6aec67c80af",
"packages": [ "packages": [
{ {
"name": "bacon/bacon-qr-code", "name": "bacon/bacon-qr-code",
@ -1390,105 +1390,6 @@
}, },
"time": "2022-06-29T09:25:13+00:00" "time": "2022-06-29T09:25:13+00:00"
}, },
{
"name": "league/commonmark",
"version": "1.6.7",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/commonmark.git",
"reference": "2b8185c13bc9578367a5bf901881d1c1b5bbd09b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/2b8185c13bc9578367a5bf901881d1c1b5bbd09b",
"reference": "2b8185c13bc9578367a5bf901881d1c1b5bbd09b",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"ext-mbstring": "*",
"php": "^7.1 || ^8.0"
},
"conflict": {
"scrutinizer/ocular": "1.7.*"
},
"require-dev": {
"cebe/markdown": "~1.0",
"commonmark/commonmark.js": "0.29.2",
"erusev/parsedown": "~1.0",
"ext-json": "*",
"github/gfm": "0.29.0",
"michelf/php-markdown": "~1.4",
"mikehaertl/php-shellcommand": "^1.4",
"phpstan/phpstan": "^0.12.90",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.2",
"scrutinizer/ocular": "^1.5",
"symfony/finder": "^4.2"
},
"bin": [
"bin/commonmark"
],
"type": "library",
"autoload": {
"psr-4": {
"League\\CommonMark\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Colin O'Dell",
"email": "colinodell@gmail.com",
"homepage": "https://www.colinodell.com",
"role": "Lead Developer"
}
],
"description": "Highly-extensible PHP Markdown parser which fully supports the CommonMark spec and Github-Flavored Markdown (GFM)",
"homepage": "https://commonmark.thephpleague.com",
"keywords": [
"commonmark",
"flavored",
"gfm",
"github",
"github-flavored",
"markdown",
"md",
"parser"
],
"support": {
"docs": "https://commonmark.thephpleague.com/",
"issues": "https://github.com/thephpleague/commonmark/issues",
"rss": "https://github.com/thephpleague/commonmark/releases.atom",
"source": "https://github.com/thephpleague/commonmark"
},
"funding": [
{
"url": "https://www.colinodell.com/sponsor",
"type": "custom"
},
{
"url": "https://www.paypal.me/colinpodell/10.00",
"type": "custom"
},
{
"url": "https://github.com/colinodell",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/league/commonmark",
"type": "tidelift"
}
],
"time": "2022-01-13T17:18:13+00:00"
},
{ {
"name": "monolog/monolog", "name": "monolog/monolog",
"version": "2.8.0", "version": "2.8.0",
@ -2365,34 +2266,34 @@
"time": "2017-10-23T01:57:42+00:00" "time": "2017-10-23T01:57:42+00:00"
}, },
{ {
"name": "qcloud/cos-sdk-v5", "name": "qcloud/cos-sdk-v5",
"version": "v2.6.2", "version": "v2.6.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/tencentyun/cos-php-sdk-v5.git", "url": "https://github.com/tencentyun/cos-php-sdk-v5.git",
"reference": "92a1ee62b85ed4e7bf6836a684df5d7e3158d0ed" "reference": "92a1ee62b85ed4e7bf6836a684df5d7e3158d0ed"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/tencentyun/cos-php-sdk-v5/zipball/92a1ee62b85ed4e7bf6836a684df5d7e3158d0ed", "url": "https://api.github.com/repos/tencentyun/cos-php-sdk-v5/zipball/92a1ee62b85ed4e7bf6836a684df5d7e3158d0ed",
"reference": "92a1ee62b85ed4e7bf6836a684df5d7e3158d0ed", "reference": "92a1ee62b85ed4e7bf6836a684df5d7e3158d0ed",
"shasum": "", "shasum": "",
"mirrors": [ "mirrors": [
{ {
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true "preferred": true
} }
] ]
}, },
"require": { "require": {
"ext-curl": "*", "ext-curl": "*",
"ext-json": "*", "ext-json": "*",
"ext-mbstring": "*", "ext-mbstring": "*",
"ext-simplexml": "*", "ext-simplexml": "*",
"guzzlehttp/guzzle": "^6.2.1 || ^7.0", "guzzlehttp/guzzle": "^6.2.1 || ^7.0",
"guzzlehttp/guzzle-services": "^1.1", "guzzlehttp/guzzle-services": "^1.1",
"guzzlehttp/psr7": "^1.3.1 || ^2.0", "guzzlehttp/psr7": "^1.3.1 || ^2.0",
"php": ">=5.6" "php": ">=5.6"
}, },
"type": "library", "type": "library",
"extra": { "extra": {
@ -2434,9 +2335,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/tencentyun/cos-php-sdk-v5/issues", "issues": "https://github.com/tencentyun/cos-php-sdk-v5/issues",
"source": "https://github.com/tencentyun/cos-php-sdk-v5/tree/v2.6.2" "source": "https://github.com/tencentyun/cos-php-sdk-v5/tree/v2.6.2"
}, },
"time": "2023-04-07T07:38:24+00:00" "time": "2023-04-07T07:38:24+00:00"
}, },
{ {
"name": "ralouphie/getallheaders", "name": "ralouphie/getallheaders",
@ -4909,43 +4810,43 @@
], ],
"time": "2022-05-27T12:56:18+00:00" "time": "2022-05-27T12:56:18+00:00"
}, },
{ {
"name": "tencentcloud/tencentcloud-sdk-php", "name": "tencentcloud/tencentcloud-sdk-php",
"version": "3.0.889", "version": "3.0.889",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/TencentCloud/tencentcloud-sdk-php.git", "url": "https://github.com/TencentCloud/tencentcloud-sdk-php.git",
"reference": "a08031e5111f17131fceb429eebb8223c105d8b3" "reference": "a08031e5111f17131fceb429eebb8223c105d8b3"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/TencentCloud/tencentcloud-sdk-php/zipball/a08031e5111f17131fceb429eebb8223c105d8b3", "url": "https://api.github.com/repos/TencentCloud/tencentcloud-sdk-php/zipball/a08031e5111f17131fceb429eebb8223c105d8b3",
"reference": "a08031e5111f17131fceb429eebb8223c105d8b3", "reference": "a08031e5111f17131fceb429eebb8223c105d8b3",
"shasum": "", "shasum": "",
"mirrors": [ "mirrors": [
{ {
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true "preferred": true
} }
] ]
}, },
"require": { "require": {
"guzzlehttp/guzzle": "^6.3 || ^7.0", "guzzlehttp/guzzle": "^6.3 || ^7.0",
"php": ">=5.6.0" "php": ">=5.6.0"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^9.5" "phpunit/phpunit": "^9.5"
}, },
"type": "library", "type": "library",
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"TencentCloud\\": "./src/TencentCloud" "TencentCloud\\": "./src/TencentCloud"
}, },
"classmap": [ "classmap": [
"src/QcloudApi/QcloudApi.php" "src/QcloudApi/QcloudApi.php"
] ]
}, },
"notification-url": "https://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
"license": [ "license": [
"Apache-2.0" "Apache-2.0"
], ],
@ -4961,9 +4862,9 @@
"homepage": "https://github.com/TencentCloud/tencentcloud-sdk-php", "homepage": "https://github.com/TencentCloud/tencentcloud-sdk-php",
"support": { "support": {
"issues": "https://github.com/TencentCloud/tencentcloud-sdk-php/issues", "issues": "https://github.com/TencentCloud/tencentcloud-sdk-php/issues",
"source": "https://github.com/TencentCloud/tencentcloud-sdk-php/tree/3.0.889" "source": "https://github.com/TencentCloud/tencentcloud-sdk-php/tree/3.0.889"
}, },
"time": "2023-05-22T00:02:52+00:00" "time": "2023-05-22T00:02:52+00:00"
}, },
{ {
"name": "webmozart/assert", "name": "webmozart/assert",
@ -5099,29 +5000,29 @@
}, },
"time": "2022-04-19T20:14:54+00:00" "time": "2022-04-19T20:14:54+00:00"
}, },
{ {
"name": "workerman/gateway-worker", "name": "workerman/gateway-worker",
"version": "v3.0.28", "version": "v3.0.28",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/walkor/GatewayWorker.git", "url": "https://github.com/walkor/GatewayWorker.git",
"reference": "a7dffc53403133131a51b9fd3c6c6d70869cb6d3" "reference": "a7dffc53403133131a51b9fd3c6c6d70869cb6d3"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/walkor/GatewayWorker/zipball/a7dffc53403133131a51b9fd3c6c6d70869cb6d3", "url": "https://api.github.com/repos/walkor/GatewayWorker/zipball/a7dffc53403133131a51b9fd3c6c6d70869cb6d3",
"reference": "a7dffc53403133131a51b9fd3c6c6d70869cb6d3", "reference": "a7dffc53403133131a51b9fd3c6c6d70869cb6d3",
"shasum": "", "shasum": "",
"mirrors": [ "mirrors": [
{ {
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true "preferred": true
} }
] ]
}, },
"require": { "require": {
"php": ">=7.0", "php": ">=7.0",
"workerman/workerman": "^4.0.30" "workerman/workerman": "^4.0.30"
}, },
"type": "library", "type": "library",
"autoload": { "autoload": {
@ -5140,7 +5041,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/walkor/GatewayWorker/issues", "issues": "https://github.com/walkor/GatewayWorker/issues",
"source": "https://github.com/walkor/GatewayWorker/tree/v3.0.28" "source": "https://github.com/walkor/GatewayWorker/tree/v3.0.28"
}, },
"funding": [ "funding": [
{ {
@ -5152,7 +5053,7 @@
"type": "patreon" "type": "patreon"
} }
], ],
"time": "2023-03-24T03:56:27+00:00" "time": "2023-03-24T03:56:27+00:00"
}, },
{ {
"name": "workerman/gatewayclient", "name": "workerman/gatewayclient",
@ -5643,8 +5544,9 @@
"ext-redis": "~5.0", "ext-redis": "~5.0",
"ext-pdo": "*", "ext-pdo": "*",
"ext-json": "*", "ext-json": "*",
"ext-fileinfo": "*" "ext-fileinfo": "*",
"ext-gd": "*"
}, },
"platform-dev": [], "platform-dev": [],
"plugin-api-version": "2.0.0" "plugin-api-version": "2.3.0"
} }

View File

@ -85,9 +85,7 @@ layui.use(['jquery', 'layer', 'helper'], function () {
}); });
$('.icon-reply').on('click', function () { $('.icon-reply').on('click', function () {
$('html').animate({ $('html').scrollTop($('#comment-anchor').offset().top);
scrollTop: $('#comment-anchor').offset().top
}, 500);
}); });
}); });

View File

@ -35,9 +35,7 @@ layui.use(['jquery', 'helper'], function () {
}); });
$('.icon-reply').on('click', function () { $('.icon-reply').on('click', function () {
$('html').animate({ $('html').scrollTop($('#comment-anchor').offset().top);
scrollTop: $('#comment-anchor').offset().top
}, 500);
}); });
}); });

View File

@ -14,7 +14,7 @@ layui.use(['jquery', 'helper', 'util'], function () {
title: false, title: false,
closeBtn: 0, closeBtn: 0,
shadeClose: true, shadeClose: true,
content: content content: content,
}); });
} }
@ -25,7 +25,7 @@ layui.use(['jquery', 'helper', 'util'], function () {
title: false, title: false,
closeBtn: 0, closeBtn: 0,
shadeClose: true, shadeClose: true,
content: content content: content,
}); });
} }

View File

@ -85,9 +85,7 @@ layui.use(['jquery', 'helper'], function () {
}); });
$('.icon-reply').on('click', function () { $('.icon-reply').on('click', function () {
$('html').animate({ $('html').scrollTop($('#answer-anchor').offset().top);
scrollTop: $('#answer-anchor').offset().top
}, 500);
}); });
}); });

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
html #layuicss-skincodecss{display:none;position:absolute;width:1989px}.layui-code-view{display:block;position:relative;margin:10px 0;padding:0;border:1px solid #eee;border-left-width:6px;background-color:#fafafa;color:#333;font-family:Courier New;font-size:13px}.layui-code-title{position:relative;padding:0 10px;height:40px;line-height:40px;border-bottom:1px solid #eee;font-size:12px}.layui-code-title>.layui-code-about{position:absolute;right:10px;top:0;color:#b7b7b7}.layui-code-about>a{padding-left:10px}.layui-code-view>.layui-code-ol,.layui-code-view>.layui-code-ul{position:relative;overflow:auto}.layui-code-view>.layui-code-ol>li{position:relative;margin-left:45px;line-height:20px;padding:0 10px;border-left:1px solid #e2e2e2;list-style-type:decimal-leading-zero;*list-style-type:decimal;background-color:#fff}.layui-code-view>.layui-code-ol>li:first-child,.layui-code-view>.layui-code-ul>li:first-child{padding-top:10px}.layui-code-view>.layui-code-ol>li:last-child,.layui-code-view>.layui-code-ul>li:last-child{padding-bottom:10px}.layui-code-view>.layui-code-ul>li{position:relative;line-height:20px;padding:0 10px;list-style-type:none;*list-style-type:none;background-color:#fff}.layui-code-view pre{margin:0}.layui-code-dark{border:1px solid #0c0c0c;border-left-color:#3f3f3f;background-color:#0c0c0c;color:#c2be9e}.layui-code-dark>.layui-code-title{border-bottom:none}.layui-code-dark>.layui-code-ol>li,.layui-code-dark>.layui-code-ul>li{background-color:#3f3f3f;border-left:none}.layui-code-dark>.layui-code-ul>li{margin-left:6px}.layui-code-demo .layui-code{visibility:visible!important;margin:-15px;border-top:none;border-right:none;border-bottom:none}.layui-code-demo .layui-tab-content{padding:15px;border-top:none}

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 701 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

File diff suppressed because one or more lines are too long