mirror of
https://gitee.com/koogua/course-tencent-cloud.git
synced 2025-06-22 19:44:02 +08:00
1.kg_course表增加索引
2.优化错误页 3.优化富文本内容长度获取 4.优化layer关闭窗口后发布状态同步
This commit is contained in:
parent
0dec52806b
commit
1bef24f217
@ -1,3 +1,6 @@
|
|||||||
|
### [v1.6.7](https://gitee.com/koogua/course-tencent-cloud/releases/v1.6.7)(2023-10-30)
|
||||||
|
|
||||||
|
|
||||||
### [v1.6.6](https://gitee.com/koogua/course-tencent-cloud/releases/v1.6.6)(2023-08-30)
|
### [v1.6.6](https://gitee.com/koogua/course-tencent-cloud/releases/v1.6.6)(2023-08-30)
|
||||||
|
|
||||||
- 还原意外删除的AnswerList.php文件
|
- 还原意外删除的AnswerList.php文件
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
namespace App\Builders;
|
namespace App\Builders;
|
||||||
|
|
||||||
use App\Caches\CategoryList as CategoryListCache;
|
use App\Caches\CategoryAllList as CategoryAllListCache;
|
||||||
use App\Models\Category as CategoryModel;
|
use App\Models\Category as CategoryModel;
|
||||||
use App\Repos\User as UserRepo;
|
use App\Repos\User as UserRepo;
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ class ArticleList extends Builder
|
|||||||
|
|
||||||
public function getCategories()
|
public function getCategories()
|
||||||
{
|
{
|
||||||
$cache = new CategoryListCache();
|
$cache = new CategoryAllListCache();
|
||||||
|
|
||||||
$items = $cache->get(CategoryModel::TYPE_ARTICLE);
|
$items = $cache->get(CategoryModel::TYPE_ARTICLE);
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
namespace App\Builders;
|
namespace App\Builders;
|
||||||
|
|
||||||
use App\Caches\CategoryList as CategoryListCache;
|
use App\Caches\CategoryAllList as CategoryAllListCache;
|
||||||
use App\Models\Category as CategoryModel;
|
use App\Models\Category as CategoryModel;
|
||||||
use App\Repos\User as UserRepo;
|
use App\Repos\User as UserRepo;
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ class CourseList extends Builder
|
|||||||
|
|
||||||
public function getCategories()
|
public function getCategories()
|
||||||
{
|
{
|
||||||
$cache = new CategoryListCache();
|
$cache = new CategoryAllListCache();
|
||||||
|
|
||||||
$items = $cache->get(CategoryModel::TYPE_COURSE);
|
$items = $cache->get(CategoryModel::TYPE_COURSE);
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
namespace App\Builders;
|
namespace App\Builders;
|
||||||
|
|
||||||
use App\Caches\CategoryList as CategoryListCache;
|
use App\Caches\CategoryAllList as CategoryAllListCache;
|
||||||
use App\Models\Category as CategoryModel;
|
use App\Models\Category as CategoryModel;
|
||||||
|
|
||||||
class HelpList extends Builder
|
class HelpList extends Builder
|
||||||
@ -26,7 +26,7 @@ class HelpList extends Builder
|
|||||||
|
|
||||||
public function getCategories()
|
public function getCategories()
|
||||||
{
|
{
|
||||||
$cache = new CategoryListCache();
|
$cache = new CategoryAllListCache();
|
||||||
|
|
||||||
$items = $cache->get(CategoryModel::TYPE_HELP);
|
$items = $cache->get(CategoryModel::TYPE_HELP);
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
namespace App\Builders;
|
namespace App\Builders;
|
||||||
|
|
||||||
use App\Caches\CategoryList as CategoryListCache;
|
use App\Caches\CategoryAllList as CategoryAllListCache;
|
||||||
use App\Models\Category as CategoryModel;
|
use App\Models\Category as CategoryModel;
|
||||||
use App\Repos\User as UserRepo;
|
use App\Repos\User as UserRepo;
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ class QuestionList extends Builder
|
|||||||
|
|
||||||
public function getCategories()
|
public function getCategories()
|
||||||
{
|
{
|
||||||
$cache = new CategoryListCache();
|
$cache = new CategoryAllListCache();
|
||||||
|
|
||||||
$items = $cache->get(CategoryModel::TYPE_QUESTION);
|
$items = $cache->get(CategoryModel::TYPE_QUESTION);
|
||||||
|
|
||||||
|
50
app/Caches/CategoryAllList.php
Normal file
50
app/Caches/CategoryAllList.php
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||||
|
* @license https://opensource.org/licenses/GPL-2.0
|
||||||
|
* @link https://www.koogua.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Caches;
|
||||||
|
|
||||||
|
use App\Models\Category as CategoryModel;
|
||||||
|
use Phalcon\Mvc\Model\Resultset;
|
||||||
|
|
||||||
|
class CategoryAllList extends Cache
|
||||||
|
{
|
||||||
|
|
||||||
|
protected $lifetime = 365 * 86400;
|
||||||
|
|
||||||
|
public function getLifetime()
|
||||||
|
{
|
||||||
|
return $this->lifetime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getKey($type = null)
|
||||||
|
{
|
||||||
|
return "category_all_list:{$type}";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param null $type
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getContent($type = null)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Resultset $categories
|
||||||
|
*/
|
||||||
|
$categories = CategoryModel::query()
|
||||||
|
->columns(['id', 'parent_id', 'name', 'priority', 'level', 'path'])
|
||||||
|
->where('type = :type:', ['type' => $type])
|
||||||
|
->orderBy('level ASC, priority ASC')
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
if ($categories->count() == 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $categories->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -8,6 +8,7 @@
|
|||||||
namespace App\Http\Admin\Services;
|
namespace App\Http\Admin\Services;
|
||||||
|
|
||||||
use App\Caches\Category as CategoryCache;
|
use App\Caches\Category as CategoryCache;
|
||||||
|
use App\Caches\CategoryAllList as CategoryAllListCache;
|
||||||
use App\Caches\CategoryList as CategoryListCache;
|
use App\Caches\CategoryList as CategoryListCache;
|
||||||
use App\Caches\CategoryTreeList as CategoryTreeListCache;
|
use App\Caches\CategoryTreeList as CategoryTreeListCache;
|
||||||
use App\Models\Category as CategoryModel;
|
use App\Models\Category as CategoryModel;
|
||||||
@ -140,7 +141,6 @@ class Category extends Service
|
|||||||
$category->update();
|
$category->update();
|
||||||
|
|
||||||
$this->updateCategoryStats($category);
|
$this->updateCategoryStats($category);
|
||||||
|
|
||||||
$this->rebuildCategoryCache($category);
|
$this->rebuildCategoryCache($category);
|
||||||
|
|
||||||
return $category;
|
return $category;
|
||||||
@ -182,7 +182,6 @@ class Category extends Service
|
|||||||
$category->update($data);
|
$category->update($data);
|
||||||
|
|
||||||
$this->updateCategoryStats($category);
|
$this->updateCategoryStats($category);
|
||||||
|
|
||||||
$this->rebuildCategoryCache($category);
|
$this->rebuildCategoryCache($category);
|
||||||
|
|
||||||
return $category;
|
return $category;
|
||||||
@ -201,7 +200,6 @@ class Category extends Service
|
|||||||
$category->update();
|
$category->update();
|
||||||
|
|
||||||
$this->updateCategoryStats($category);
|
$this->updateCategoryStats($category);
|
||||||
|
|
||||||
$this->rebuildCategoryCache($category);
|
$this->rebuildCategoryCache($category);
|
||||||
|
|
||||||
return $category;
|
return $category;
|
||||||
@ -216,7 +214,6 @@ class Category extends Service
|
|||||||
$category->update();
|
$category->update();
|
||||||
|
|
||||||
$this->updateCategoryStats($category);
|
$this->updateCategoryStats($category);
|
||||||
|
|
||||||
$this->rebuildCategoryCache($category);
|
$this->rebuildCategoryCache($category);
|
||||||
|
|
||||||
return $category;
|
return $category;
|
||||||
@ -250,6 +247,10 @@ class Category extends Service
|
|||||||
$cache = new CategoryTreeListCache();
|
$cache = new CategoryTreeListCache();
|
||||||
|
|
||||||
$cache->rebuild($category->type);
|
$cache->rebuild($category->type);
|
||||||
|
|
||||||
|
$cache = new CategoryAllListCache();
|
||||||
|
|
||||||
|
$cache->rebuild($category->type);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function enableChildCategories($parentId)
|
protected function enableChildCategories($parentId)
|
||||||
|
@ -201,7 +201,9 @@ class Chapter extends Service
|
|||||||
}
|
}
|
||||||
|
|
||||||
$lessonCount = $chapterRepo->countLessons($chapter->id);
|
$lessonCount = $chapterRepo->countLessons($chapter->id);
|
||||||
|
|
||||||
$chapter->lesson_count = $lessonCount;
|
$chapter->lesson_count = $lessonCount;
|
||||||
|
|
||||||
$chapter->update();
|
$chapter->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -453,6 +453,7 @@ class Course extends Service
|
|||||||
$courseTeacher->user_id = $teacherId;
|
$courseTeacher->user_id = $teacherId;
|
||||||
$courseTeacher->role_type = CourseUserModel::ROLE_TEACHER;
|
$courseTeacher->role_type = CourseUserModel::ROLE_TEACHER;
|
||||||
$courseTeacher->source_type = CourseUserModel::SOURCE_IMPORT;
|
$courseTeacher->source_type = CourseUserModel::SOURCE_IMPORT;
|
||||||
|
$courseTeacher->expiry_time = strtotime('+30 years');
|
||||||
$courseTeacher->create();
|
$courseTeacher->create();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Admin\Services;
|
namespace App\Http\Admin\Services;
|
||||||
|
|
||||||
use App\Caches\IndexSlideList as IndexSlideListCache;
|
use App\Services\Utils\IndexPageCache as IndexPageCacheUtil;
|
||||||
use App\Services\Utils\IndexCourseCache as IndexCourseCacheUtil;
|
|
||||||
|
|
||||||
class Util extends Service
|
class Util extends Service
|
||||||
{
|
{
|
||||||
@ -17,29 +16,25 @@ class Util extends Service
|
|||||||
{
|
{
|
||||||
$items = $this->request->getPost('items');
|
$items = $this->request->getPost('items');
|
||||||
|
|
||||||
if ($items['slide'] == 1) {
|
$sections = [
|
||||||
$cache = new IndexSlideListCache();
|
'slide',
|
||||||
$cache->rebuild();
|
'featured_course',
|
||||||
|
'new_course',
|
||||||
|
'free_course',
|
||||||
|
'vip_course',
|
||||||
|
];
|
||||||
|
|
||||||
|
if (empty($items)) {
|
||||||
|
$items = $sections;
|
||||||
}
|
}
|
||||||
|
|
||||||
$util = new IndexCourseCacheUtil();
|
$util = new IndexPageCacheUtil();
|
||||||
|
|
||||||
if ($items['featured_course'] == 1) {
|
foreach ($sections as $section) {
|
||||||
$util->rebuild('featured_course');
|
if (in_array($section, $items)) {
|
||||||
|
$util->rebuild($section);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($items['new_course'] == 1) {
|
|
||||||
$util->rebuild('new_course');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($items['free_course'] == 1) {
|
|
||||||
$util->rebuild('free_course');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($items['vip_course'] == 1) {
|
|
||||||
$util->rebuild('vip_course');
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -80,8 +80,10 @@
|
|||||||
<td>{{ item.like_count }}</td>
|
<td>{{ item.like_count }}</td>
|
||||||
<td>{{ item.favorite_count }}</td>
|
<td>{{ item.favorite_count }}</td>
|
||||||
<td>{{ publish_status(item.published) }}</td>
|
<td>{{ publish_status(item.published) }}</td>
|
||||||
<td><input type="checkbox" name="featured" value="1" lay-skin="switch" lay-text="是|否" lay-filter="featured" data-url="{{ update_url }}" {% if item.featured == 1 %}checked="checked"{% endif %}></td>
|
<td><input type="checkbox" name="featured" value="1" lay-skin="switch" lay-text="是|否" lay-filter="featured" data-url="{{ update_url }}"
|
||||||
<td><input type="checkbox" name="comment" value="1" lay-skin="switch" lay-text="是|否" lay-filter="closed" data-url="{{ update_url }}" {% if item.closed == 1 %}checked="checked"{% endif %}></td>
|
{% if item.featured == 1 %}checked="checked"{% endif %}></td>
|
||||||
|
<td><input type="checkbox" name="comment" value="1" lay-skin="switch" lay-text="是|否" lay-filter="closed" data-url="{{ update_url }}"
|
||||||
|
{% if item.closed == 1 %}checked="checked"{% endif %}></td>
|
||||||
<td class="center">
|
<td class="center">
|
||||||
<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>
|
||||||
@ -126,7 +128,13 @@
|
|||||||
var featured = checked ? 1 : 0;
|
var featured = checked ? 1 : 0;
|
||||||
var url = $(this).data('url');
|
var url = $(this).data('url');
|
||||||
var tips = featured === 1 ? '确定要推荐?' : '确定要取消推荐?';
|
var tips = featured === 1 ? '确定要推荐?' : '确定要取消推荐?';
|
||||||
layer.confirm(tips, function () {
|
layer.confirm(tips, {
|
||||||
|
cancel: function (index) {
|
||||||
|
layer.close(index);
|
||||||
|
data.elem.checked = !checked;
|
||||||
|
form.render();
|
||||||
|
}
|
||||||
|
}, function () {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
url: url,
|
url: url,
|
||||||
|
@ -96,8 +96,10 @@
|
|||||||
<p>市场:{{ '¥%0.2f'|format(item.market_price) }}</p>
|
<p>市场:{{ '¥%0.2f'|format(item.market_price) }}</p>
|
||||||
<p>会员:{{ '¥%0.2f'|format(item.vip_price) }}</p>
|
<p>会员:{{ '¥%0.2f'|format(item.vip_price) }}</p>
|
||||||
</td>
|
</td>
|
||||||
<td><input type="checkbox" name="featured" value="1" lay-skin="switch" lay-text="是|否" lay-filter="featured" data-url="{{ update_url }}" {% if item.featured == 1 %}checked="checked"{% endif %}></td>
|
<td><input type="checkbox" name="featured" value="1" lay-skin="switch" lay-text="是|否" lay-filter="featured" data-url="{{ update_url }}"
|
||||||
<td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}" {% if item.published == 1 %}checked="checked"{% endif %}></td>
|
{% if item.featured == 1 %}checked="checked"{% endif %}></td>
|
||||||
|
<td><input type="checkbox" name="published" value="1" lay-skin="switch" lay-text="是|否" lay-filter="published" data-url="{{ update_url }}"
|
||||||
|
{% if item.published == 1 %}checked="checked"{% endif %}></td>
|
||||||
<td class="center">
|
<td class="center">
|
||||||
<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>
|
||||||
@ -144,7 +146,13 @@
|
|||||||
var featured = checked ? 1 : 0;
|
var featured = checked ? 1 : 0;
|
||||||
var url = $(this).data('url');
|
var url = $(this).data('url');
|
||||||
var tips = featured === 1 ? '确定要推荐?' : '确定要取消推荐?';
|
var tips = featured === 1 ? '确定要推荐?' : '确定要取消推荐?';
|
||||||
layer.confirm(tips, function () {
|
layer.confirm(tips, {
|
||||||
|
cancel: function (index) {
|
||||||
|
layer.close(index);
|
||||||
|
data.elem.checked = !checked;
|
||||||
|
form.render();
|
||||||
|
}
|
||||||
|
}, function () {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
url: url,
|
url: url,
|
||||||
|
@ -78,7 +78,8 @@
|
|||||||
<td>{{ item.like_count }}</td>
|
<td>{{ item.like_count }}</td>
|
||||||
<td>{{ item.favorite_count }}</td>
|
<td>{{ item.favorite_count }}</td>
|
||||||
<td>{{ publish_status(item.published) }}</td>
|
<td>{{ publish_status(item.published) }}</td>
|
||||||
<td><input type="checkbox" name="closed" value="1" lay-skin="switch" lay-text="是|否" lay-filter="closed" data-url="{{ update_url }}" {% if item.closed == 1 %}checked="checked"{% endif %}></td>
|
<td><input type="checkbox" name="closed" value="1" lay-skin="switch" lay-text="是|否" lay-filter="closed" data-url="{{ update_url }}"
|
||||||
|
{% if item.closed == 1 %}checked="checked"{% endif %}></td>
|
||||||
<td class="center">
|
<td class="center">
|
||||||
<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>
|
||||||
@ -124,7 +125,13 @@
|
|||||||
var closed = checked ? 1 : 0;
|
var closed = checked ? 1 : 0;
|
||||||
var url = $(this).data('url');
|
var url = $(this).data('url');
|
||||||
var tips = closed === 1 ? '确定要关闭讨论?' : '确定要开启讨论?';
|
var tips = closed === 1 ? '确定要关闭讨论?' : '确定要开启讨论?';
|
||||||
layer.confirm(tips, function () {
|
layer.confirm(tips, {
|
||||||
|
cancel: function (index) {
|
||||||
|
layer.close(index);
|
||||||
|
data.elem.checked = !checked;
|
||||||
|
form.render();
|
||||||
|
}
|
||||||
|
}, function () {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
url: url,
|
url: url,
|
||||||
|
@ -52,7 +52,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<p>课程:<a href="{{ list_by_course_url }}">{{ item.course.title }}</a>({{ item.course.id }})</p>
|
<p>课程:<a href="{{ list_by_course_url }}">{{ item.course.title }}</a>({{ item.course.id }})</p>
|
||||||
<p class="layui-elip kg-item-elip" title="{{ item.content }}">评价:{{ item.content }}</p>
|
<p>评价:<span title="{{ item.content }}">{{ substr(item.content,0,30) }}</span>({{ item.id }})</p>
|
||||||
<p>时间:{{ date('Y-m-d H:i:s',item.create_time) }}</p>
|
<p>时间:{{ date('Y-m-d H:i:s',item.create_time) }}</p>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -2,17 +2,7 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
{%- macro client_type_info(value) %}
|
{{ partial('macros/common') }}
|
||||||
{% if value == 1 %}
|
|
||||||
desktop
|
|
||||||
{% elseif value == 2 %}
|
|
||||||
mobile
|
|
||||||
{% elseif value == 3 %}
|
|
||||||
app
|
|
||||||
{% elseif value == 4 %}
|
|
||||||
小程序
|
|
||||||
{% endif %}
|
|
||||||
{%- endmacro %}
|
|
||||||
|
|
||||||
<table class="layui-table kg-table">
|
<table class="layui-table kg-table">
|
||||||
<colgroup>
|
<colgroup>
|
||||||
@ -20,7 +10,6 @@
|
|||||||
<col>
|
<col>
|
||||||
<col>
|
<col>
|
||||||
<col>
|
<col>
|
||||||
<col>
|
|
||||||
</colgroup>
|
</colgroup>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@ -36,11 +25,11 @@
|
|||||||
{% set active_time = item.active_time > 0 ? date('Y-m-d H:i:s',item.active_time) : 'N/A' %}
|
{% set active_time = item.active_time > 0 ? date('Y-m-d H:i:s',item.active_time) : 'N/A' %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<p class="layui-elip">课程:{{ item.course.title }}</p>
|
<p class="layui-elip">课程:{{ item.course.title }}({{ item.course.id }})</p>
|
||||||
<p class="layui-elip">章节:{{ item.chapter.title }}</p>
|
<p class="layui-elip">章节:{{ item.chapter.title }}({{ item.chaper.id }})</p>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<p>类型:{{ client_type_info(item.client_type) }}</p>
|
<p>类型:{{ client_type(item.client_type) }}</p>
|
||||||
<p>地址:<a href="javascript:" class="kg-ip2region" title="查看位置" data-ip="{{ item.client_ip }}">{{ item.client_ip }}</a></p>
|
<p>地址:<a href="javascript:" class="kg-ip2region" title="查看位置" data-ip="{{ item.client_ip }}">{{ item.client_ip }}</a></p>
|
||||||
</td>
|
</td>
|
||||||
<td>{{ duration }}</td>
|
<td>{{ duration }}</td>
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
<div class="layui-fluid">
|
<div class="layui-fluid">
|
||||||
<div class="kg-tips">
|
<div class="kg-tips">
|
||||||
<i class="layui-icon layui-icon-face-surprised"></i>
|
<i class="layui-icon layui-icon-face-surprised"></i>
|
||||||
|
<div class="message">无操作权限,请先登录认证</div>
|
||||||
<div class="layui-text">
|
<div class="layui-text">
|
||||||
<h1>
|
<h1>
|
||||||
<span class="layui-anim layui-anim-loop">4</span>
|
<span class="layui-anim layui-anim-loop">4</span>
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
<div class="layui-fluid">
|
<div class="layui-fluid">
|
||||||
<div class="kg-tips">
|
<div class="kg-tips">
|
||||||
<i class="layui-icon layui-icon-face-surprised"></i>
|
<i class="layui-icon layui-icon-face-surprised"></i>
|
||||||
|
<div class="message">无操作权限,禁止访问</div>
|
||||||
<div class="layui-text">
|
<div class="layui-text">
|
||||||
<h1>
|
<h1>
|
||||||
<span class="layui-anim layui-anim-loop">4</span>
|
<span class="layui-anim layui-anim-loop">4</span>
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
<div class="layui-fluid">
|
<div class="layui-fluid">
|
||||||
<div class="kg-tips">
|
<div class="kg-tips">
|
||||||
<i class="layui-icon layui-icon-face-surprised"></i>
|
<i class="layui-icon layui-icon-face-surprised"></i>
|
||||||
|
<div class="message">迷失自我,相关资源不存在</div>
|
||||||
<div class="layui-text">
|
<div class="layui-text">
|
||||||
<h1>
|
<h1>
|
||||||
<span class="layui-anim layui-anim-loop">4</span>
|
<span class="layui-anim layui-anim-loop">4</span>
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
<div class="layui-fluid">
|
<div class="layui-fluid">
|
||||||
<div class="kg-tips">
|
<div class="kg-tips">
|
||||||
<i class="layui-icon layui-icon-face-surprised"></i>
|
<i class="layui-icon layui-icon-face-surprised"></i>
|
||||||
|
<div class="message">尴尬到家,服务器内部错误</div>
|
||||||
<div class="layui-text">
|
<div class="layui-text">
|
||||||
<h1>
|
<h1>
|
||||||
<span class="layui-anim layui-anim-loop">5</span>
|
<span class="layui-anim layui-anim-loop">5</span>
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
<div class="layui-fluid">
|
<div class="layui-fluid">
|
||||||
<div class="kg-tips">
|
<div class="kg-tips">
|
||||||
<i class="layui-icon layui-icon-face-surprised"></i>
|
<i class="layui-icon layui-icon-face-surprised"></i>
|
||||||
|
<div class="message">压力山大,当前服务不可用</div>
|
||||||
<div class="layui-text">
|
<div class="layui-text">
|
||||||
<h1>
|
<h1>
|
||||||
<span class="layui-anim layui-anim-loop">5</span>
|
<span class="layui-anim layui-anim-loop">5</span>
|
||||||
|
@ -16,7 +16,7 @@ class AppInfo
|
|||||||
|
|
||||||
protected $link = 'https://www.koogua.com';
|
protected $link = 'https://www.koogua.com';
|
||||||
|
|
||||||
protected $version = '1.6.6';
|
protected $version = '1.6.7';
|
||||||
|
|
||||||
public function __get($name)
|
public function __get($name)
|
||||||
{
|
{
|
||||||
|
@ -424,6 +424,21 @@ function kg_cos_img_style_trim($path)
|
|||||||
return preg_replace('/!\w+/', '', $path);
|
return preg_replace('/!\w+/', '', $path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取编辑器内容长度
|
||||||
|
*
|
||||||
|
* @param string $content
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
function kg_editor_content_length($content)
|
||||||
|
{
|
||||||
|
$content = trim($content);
|
||||||
|
|
||||||
|
$content = strip_tags($content,'<img>');
|
||||||
|
|
||||||
|
return kg_strlen($content);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清理html内容
|
* 清理html内容
|
||||||
*
|
*
|
||||||
|
@ -85,6 +85,7 @@ class Category extends Repository
|
|||||||
->where('type = :type:', ['type' => $type])
|
->where('type = :type:', ['type' => $type])
|
||||||
->andWhere('parent_id = 0')
|
->andWhere('parent_id = 0')
|
||||||
->andWhere('published = 1')
|
->andWhere('published = 1')
|
||||||
|
->andWhere('deleted = 0')
|
||||||
->orderBy('priority ASC')
|
->orderBy('priority ASC')
|
||||||
->execute();
|
->execute();
|
||||||
}
|
}
|
||||||
@ -98,6 +99,7 @@ class Category extends Repository
|
|||||||
return CategoryModel::query()
|
return CategoryModel::query()
|
||||||
->where('parent_id = :parent_id:', ['parent_id' => $categoryId])
|
->where('parent_id = :parent_id:', ['parent_id' => $categoryId])
|
||||||
->andWhere('published = 1')
|
->andWhere('published = 1')
|
||||||
|
->andWhere('deleted = 0')
|
||||||
->orderBy('priority ASC')
|
->orderBy('priority ASC')
|
||||||
->execute();
|
->execute();
|
||||||
}
|
}
|
||||||
@ -105,7 +107,7 @@ class Category extends Repository
|
|||||||
public function countChildCategories($categoryId)
|
public function countChildCategories($categoryId)
|
||||||
{
|
{
|
||||||
return (int)CategoryModel::count([
|
return (int)CategoryModel::count([
|
||||||
'conditions' => 'parent_id = :parent_id: AND published = 1',
|
'conditions' => 'parent_id = :parent_id: AND published = 1 AND deleted = 0',
|
||||||
'bind' => ['parent_id' => $categoryId],
|
'bind' => ['parent_id' => $categoryId],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ class Course extends Repository
|
|||||||
|
|
||||||
if (!empty($where['level'])) {
|
if (!empty($where['level'])) {
|
||||||
if (is_array($where['level'])) {
|
if (is_array($where['level'])) {
|
||||||
$builder->inWhere('level', $where['model']);
|
$builder->inWhere('level', $where['level']);
|
||||||
} else {
|
} else {
|
||||||
$builder->andWhere('level = :level:', ['level' => $where['level']]);
|
$builder->andWhere('level = :level:', ['level' => $where['level']]);
|
||||||
}
|
}
|
||||||
|
@ -102,11 +102,11 @@ class ReviewList extends LogicService
|
|||||||
|
|
||||||
$result = [];
|
$result = [];
|
||||||
|
|
||||||
foreach ($reviews as $consult) {
|
foreach ($reviews as $review) {
|
||||||
$result[$consult['id']] = [
|
$result[$review['id']] = [
|
||||||
'logged' => $user->id > 0 ? 1 : 0,
|
'logged' => $user->id > 0 ? 1 : 0,
|
||||||
'liked' => in_array($consult['id'], $likedIds) ? 1 : 0,
|
'liked' => in_array($review['id'], $likedIds) ? 1 : 0,
|
||||||
'owned' => $consult['owner_id'] == $user->id ? 1 : 0,
|
'owned' => $review['owner_id'] == $user->id ? 1 : 0,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,16 +16,14 @@ use App\Services\Logic\CourseTrait;
|
|||||||
use App\Services\Logic\Point\History\CourseReview as CourseReviewPointHistory;
|
use App\Services\Logic\Point\History\CourseReview as CourseReviewPointHistory;
|
||||||
use App\Services\Logic\ReviewTrait;
|
use App\Services\Logic\ReviewTrait;
|
||||||
use App\Services\Logic\Service as LogicService;
|
use App\Services\Logic\Service as LogicService;
|
||||||
use App\Traits\Client as ClientTrait;
|
|
||||||
use App\Validators\CourseUser as CourseUserValidator;
|
use App\Validators\CourseUser as CourseUserValidator;
|
||||||
use App\Validators\Review as ReviewValidator;
|
|
||||||
|
|
||||||
class ReviewCreate extends LogicService
|
class ReviewCreate extends LogicService
|
||||||
{
|
{
|
||||||
|
|
||||||
use ClientTrait;
|
|
||||||
use CourseTrait;
|
use CourseTrait;
|
||||||
use ReviewTrait;
|
use ReviewTrait;
|
||||||
|
use ReviewDataTrait;
|
||||||
|
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
@ -41,19 +39,10 @@ class ReviewCreate extends LogicService
|
|||||||
|
|
||||||
$validator->checkIfReviewed($course->id, $user->id);
|
$validator->checkIfReviewed($course->id, $user->id);
|
||||||
|
|
||||||
$validator = new ReviewValidator();
|
$data = $this->handlePostData($post);
|
||||||
|
|
||||||
$data = [
|
$data['course_id'] = $course->id;
|
||||||
'client_type' => $this->getClientType(),
|
$data['owner_id'] = $user->id;
|
||||||
'client_ip' => $this->getClientIp(),
|
|
||||||
'course_id' => $course->id,
|
|
||||||
'owner_id' => $user->id,
|
|
||||||
];
|
|
||||||
|
|
||||||
$data['content'] = $validator->checkContent($post['content']);
|
|
||||||
$data['rating1'] = $validator->checkRating($post['rating1']);
|
|
||||||
$data['rating2'] = $validator->checkRating($post['rating2']);
|
|
||||||
$data['rating3'] = $validator->checkRating($post['rating3']);
|
|
||||||
$data['published'] = 1;
|
$data['published'] = 1;
|
||||||
|
|
||||||
$review = new ReviewModel();
|
$review = new ReviewModel();
|
||||||
|
39
app/Services/Logic/Review/ReviewDataTrait.php
Normal file
39
app/Services/Logic/Review/ReviewDataTrait.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||||
|
* @license https://opensource.org/licenses/GPL-2.0
|
||||||
|
* @link https://www.koogua.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Services\Logic\Review;
|
||||||
|
|
||||||
|
use App\Traits\Client as ClientTrait;
|
||||||
|
use App\Validators\Review as ReviewValidator;
|
||||||
|
|
||||||
|
trait ReviewDataTrait
|
||||||
|
{
|
||||||
|
|
||||||
|
use ClientTrait;
|
||||||
|
|
||||||
|
protected function handlePostData($post)
|
||||||
|
{
|
||||||
|
$data = [];
|
||||||
|
|
||||||
|
$data['client_type'] = $this->getClientType();
|
||||||
|
$data['client_ip'] = $this->getClientIp();
|
||||||
|
|
||||||
|
$validator = new ReviewValidator();
|
||||||
|
|
||||||
|
$data['content'] = $validator->checkContent($post['content']);
|
||||||
|
$data['rating1'] = $validator->checkRating($post['rating1']);
|
||||||
|
$data['rating2'] = $validator->checkRating($post['rating2']);
|
||||||
|
$data['rating3'] = $validator->checkRating($post['rating3']);
|
||||||
|
|
||||||
|
if (isset($post['anonymous'])) {
|
||||||
|
$data['anonymous'] = $validator->checkAnonymous($post['anonymous']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
namespace App\Services\Utils;
|
namespace App\Services\Utils;
|
||||||
|
|
||||||
|
use App\Caches\IndexSlideList as IndexSlideListCache;
|
||||||
use App\Caches\IndexFeaturedCourseList as IndexFeaturedCourseListCache;
|
use App\Caches\IndexFeaturedCourseList as IndexFeaturedCourseListCache;
|
||||||
use App\Caches\IndexFreeCourseList as IndexFreeCourseListCache;
|
use App\Caches\IndexFreeCourseList as IndexFreeCourseListCache;
|
||||||
use App\Caches\IndexNewCourseList as IndexNewCourseListCache;
|
use App\Caches\IndexNewCourseList as IndexNewCourseListCache;
|
||||||
@ -17,11 +18,16 @@ use App\Caches\IndexSimpleVipCourseList as IndexSimpleVipCourseListCache;
|
|||||||
use App\Caches\IndexVipCourseList as IndexVipCourseListCache;
|
use App\Caches\IndexVipCourseList as IndexVipCourseListCache;
|
||||||
use App\Services\Service as AppService;
|
use App\Services\Service as AppService;
|
||||||
|
|
||||||
class IndexCourseCache extends AppService
|
class IndexPageCache extends AppService
|
||||||
{
|
{
|
||||||
|
|
||||||
public function rebuild($section = null)
|
public function rebuild($section = null)
|
||||||
{
|
{
|
||||||
|
if (!$section || $section == 'slide') {
|
||||||
|
$cache = new IndexSlideListCache();
|
||||||
|
$cache->rebuild();
|
||||||
|
}
|
||||||
|
|
||||||
if (!$section || $section == 'featured_course') {
|
if (!$section || $section == 'featured_course') {
|
||||||
$cache = new IndexFeaturedCourseListCache();
|
$cache = new IndexFeaturedCourseListCache();
|
||||||
$cache->rebuild();
|
$cache->rebuild();
|
@ -159,9 +159,7 @@ class Account extends Validator
|
|||||||
|
|
||||||
$account = $this->checkAccount($name);
|
$account = $this->checkAccount($name);
|
||||||
|
|
||||||
$hash = PasswordUtil::hash($password, $account->salt);
|
if (!PasswordUtil::checkHash($password, $account->salt, $account->password)) {
|
||||||
|
|
||||||
if ($hash != $account->password) {
|
|
||||||
throw new BadRequestException('account.login_pwd_incorrect');
|
throw new BadRequestException('account.login_pwd_incorrect');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ class Answer extends Validator
|
|||||||
|
|
||||||
$value = $storage->handle($value);
|
$value = $storage->handle($value);
|
||||||
|
|
||||||
$length = kg_strlen($value);
|
$length = kg_editor_content_length($value);
|
||||||
|
|
||||||
if ($length < 10) {
|
if ($length < 10) {
|
||||||
throw new BadRequestException('answer.content_too_short');
|
throw new BadRequestException('answer.content_too_short');
|
||||||
|
@ -99,7 +99,7 @@ class Article extends Validator
|
|||||||
|
|
||||||
$value = $storage->handle($value);
|
$value = $storage->handle($value);
|
||||||
|
|
||||||
$length = kg_strlen($value);
|
$length = kg_editor_content_length($value);
|
||||||
|
|
||||||
if ($length < 10) {
|
if ($length < 10) {
|
||||||
throw new BadRequestException('article.content_too_short');
|
throw new BadRequestException('article.content_too_short');
|
||||||
|
@ -26,7 +26,7 @@ class ChapterVod extends Validator
|
|||||||
|
|
||||||
public function checkDuration($duration)
|
public function checkDuration($duration)
|
||||||
{
|
{
|
||||||
$value = $value = $this->filter->sanitize($duration, ['trim', 'int']);
|
$value = $this->filter->sanitize($duration, ['trim', 'int']);
|
||||||
|
|
||||||
if ($value < 10 || $value > 10 * 3600) {
|
if ($value < 10 || $value > 10 * 3600) {
|
||||||
throw new BadRequestException('chapter_vod.invalid_duration');
|
throw new BadRequestException('chapter_vod.invalid_duration');
|
||||||
|
@ -124,7 +124,7 @@ class Course extends Validator
|
|||||||
|
|
||||||
$value = $storage->handle($value);
|
$value = $storage->handle($value);
|
||||||
|
|
||||||
$length = kg_strlen($value);
|
$length = kg_editor_content_length($value);
|
||||||
|
|
||||||
if ($length > 30000) {
|
if ($length > 30000) {
|
||||||
throw new BadRequestException('course.details_too_long');
|
throw new BadRequestException('course.details_too_long');
|
||||||
@ -257,11 +257,11 @@ class Course extends Validator
|
|||||||
|
|
||||||
public function checkPublishAbility(CourseModel $course)
|
public function checkPublishAbility(CourseModel $course)
|
||||||
{
|
{
|
||||||
if ($course->model == CourseModel::MODEL_OFFLINE) return true;
|
|
||||||
|
|
||||||
if ($course->teacher_id == 0) {
|
if ($course->teacher_id == 0) {
|
||||||
throw new BadRequestException('course.teacher_not_assigned');
|
throw new BadRequestException('course.teacher_not_assigned');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ class Help extends Validator
|
|||||||
|
|
||||||
$value = $storage->handle($value);
|
$value = $storage->handle($value);
|
||||||
|
|
||||||
$length = kg_strlen($value);
|
$length = kg_editor_content_length($value);
|
||||||
|
|
||||||
if ($length < 10) {
|
if ($length < 10) {
|
||||||
throw new BadRequestException('help.content_too_short');
|
throw new BadRequestException('help.content_too_short');
|
||||||
|
@ -129,7 +129,7 @@ class Page extends Validator
|
|||||||
|
|
||||||
$value = $storage->handle($value);
|
$value = $storage->handle($value);
|
||||||
|
|
||||||
$length = kg_strlen($value);
|
$length = kg_editor_content_length($value);
|
||||||
|
|
||||||
if ($length < 10) {
|
if ($length < 10) {
|
||||||
throw new BadRequestException('page.content_too_short');
|
throw new BadRequestException('page.content_too_short');
|
||||||
|
@ -91,7 +91,7 @@ class PointGift extends Validator
|
|||||||
|
|
||||||
$value = $storage->handle($value);
|
$value = $storage->handle($value);
|
||||||
|
|
||||||
$length = kg_strlen($value);
|
$length = kg_editor_content_length($value);
|
||||||
|
|
||||||
if ($length > 30000) {
|
if ($length > 30000) {
|
||||||
throw new BadRequestException('point_gift.details_too_long');
|
throw new BadRequestException('point_gift.details_too_long');
|
||||||
|
@ -111,7 +111,7 @@ class Question extends Validator
|
|||||||
|
|
||||||
$value = $storage->handle($value);
|
$value = $storage->handle($value);
|
||||||
|
|
||||||
$length = kg_strlen($value);
|
$length = kg_editor_content_length($value);
|
||||||
|
|
||||||
if ($length > 30000) {
|
if ($length > 30000) {
|
||||||
throw new BadRequestException('question.content_too_long');
|
throw new BadRequestException('question.content_too_long');
|
||||||
|
@ -61,6 +61,15 @@ class Review extends Validator
|
|||||||
return $rating;
|
return $rating;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function checkAnonymous($status)
|
||||||
|
{
|
||||||
|
if (!in_array($status, [0, 1])) {
|
||||||
|
throw new BadRequestException('review.invalid_anonymous_status');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $status;
|
||||||
|
}
|
||||||
|
|
||||||
public function checkPublishStatus($status)
|
public function checkPublishStatus($status)
|
||||||
{
|
{
|
||||||
if (!in_array($status, [0, 1])) {
|
if (!in_array($status, [0, 1])) {
|
||||||
|
39
db/migrations/20230910174508.php
Normal file
39
db/migrations/20230910174508.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2023 深圳市酷瓜软件有限公司
|
||||||
|
* @license https://opensource.org/licenses/GPL-2.0
|
||||||
|
* @link https://www.koogua.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
use Phinx\Migration\AbstractMigration;
|
||||||
|
|
||||||
|
final class V20230910174508 extends AbstractMigration
|
||||||
|
{
|
||||||
|
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
$this->alterCourseTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function alterCourseTable()
|
||||||
|
{
|
||||||
|
$table = $this->table('kg_course');
|
||||||
|
|
||||||
|
if (!$table->hasIndexByName('category_id')) {
|
||||||
|
$table->addIndex(['category_id'], [
|
||||||
|
'name' => 'category_id',
|
||||||
|
'unique' => false,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$table->hasIndexByName('teacher_id')) {
|
||||||
|
$table->addIndex(['teacher_id'], [
|
||||||
|
'name' => 'teacher_id',
|
||||||
|
'unique' => false,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$table->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -84,7 +84,13 @@ layui.use(['jquery', 'form', 'element', 'layer', 'kgDropdown'], function () {
|
|||||||
var published = checked ? 1 : 0;
|
var published = checked ? 1 : 0;
|
||||||
var url = $(this).data('url');
|
var url = $(this).data('url');
|
||||||
var tips = published === 1 ? '确定要上线?' : '确定要下线?';
|
var tips = published === 1 ? '确定要上线?' : '确定要下线?';
|
||||||
layer.confirm(tips, function () {
|
layer.confirm(tips, {
|
||||||
|
cancel: function (index) {
|
||||||
|
layer.close(index);
|
||||||
|
data.elem.checked = !checked;
|
||||||
|
form.render();
|
||||||
|
}
|
||||||
|
}, function () {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
url: url,
|
url: url,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user