1
0
mirror of https://gitee.com/koogua/course-tencent-cloud.git synced 2025-06-26 20:52:44 +08:00

优化排版

This commit is contained in:
xiaochong0302 2023-12-10 20:55:26 +08:00
parent 817b32b067
commit dca1ccf79a
31 changed files with 168 additions and 260 deletions

View File

@ -1,90 +0,0 @@
<?php
/**
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
* @license https://opensource.org/licenses/GPL-2.0
* @link https://www.koogua.com
*/
namespace App\Caches;
use App\Models\Course as CourseModel;
use Phalcon\Mvc\Model\Resultset;
use Phalcon\Mvc\Model\ResultsetInterface;
class CourseRecommendedList extends Cache
{
protected $lifetime = 86400;
public function getLifetime()
{
return $this->lifetime;
}
public function getKey($id = null)
{
return "course_recommended_list:{$id}";
}
public function getContent($id = null)
{
$courses = $this->findCourses(5);
if ($courses->count() == 0) {
return [];
}
return $this->handleContent($courses);
}
/**
* @param CourseModel[] $courses
* @return array
*/
public function handleContent($courses)
{
$result = [];
foreach ($courses as $course) {
$userCount = $course->user_count;
if ($course->fake_user_count > $course->user_count) {
$userCount = $course->fake_user_count;
}
$result[] = [
'id' => $course->id,
'title' => $course->title,
'cover' => $course->cover,
'model' => $course->model,
'level' => $course->level,
'rating' => round($course->rating, 1),
'market_price' => (float)$course->market_price,
'vip_price' => (float)$course->vip_price,
'user_count' => $userCount,
'lesson_count' => $course->lesson_count,
'review_count' => $course->review_count,
'favorite_count' => $course->favorite_count,
];
}
return $result;
}
/**
* @param int $limit
* @return ResultsetInterface|Resultset|CourseModel[]
*/
public function findCourses($limit = 5)
{
return CourseModel::query()
->where('market_price > 0')
->andWhere('published = 1')
->andWhere('deleted = 0')
->orderBy('RAND()')
->limit($limit)
->execute();
}
}

View File

@ -8,12 +8,13 @@
namespace App\Console\Tasks; namespace App\Console\Tasks;
use App\Caches\CategoryList as CategoryListCache; use App\Caches\CategoryList as CategoryListCache;
use App\Caches\CategoryAllList as CategoryAllListCache;
use App\Caches\CategoryTreeList as CategoryTreeListCache; use App\Caches\CategoryTreeList as CategoryTreeListCache;
use App\Caches\IndexSlideList as IndexSlideListCache; use App\Caches\IndexSlideList as IndexSlideListCache;
use App\Models\Account as AccountModel; use App\Models\Account as AccountModel;
use App\Models\Category as CategoryModel; use App\Models\Category as CategoryModel;
use App\Repos\User as UserRepo; use App\Repos\User as UserRepo;
use App\Services\Utils\IndexCourseCache as IndexCourseCacheUtil; use App\Services\Utils\IndexPageCache as IndexPageCacheUtil;
class CleanDemoDataTask extends Task class CleanDemoDataTask extends Task
{ {
@ -81,17 +82,19 @@ class CleanDemoDataTask extends Task
protected function cleanCache() protected function cleanCache()
{ {
$util = new IndexCourseCacheUtil(); $util = new IndexPageCacheUtil();
$util->rebuild(); $util->rebuild();
$slideListCache = new IndexSlideListCache(); $slideListCache = new IndexSlideListCache();
$slideListCache->rebuild(); $slideListCache->rebuild();
$categoryListCache = new CategoryListCache(); $categoryListCache = new CategoryListCache();
$categoryAllListCache = new CategoryAllListCache();
$categoryTreeListCache = new CategoryTreeListCache(); $categoryTreeListCache = new CategoryTreeListCache();
foreach (CategoryModel::types() as $key => $value) { foreach (CategoryModel::types() as $key => $value) {
$categoryListCache->rebuild($key); $categoryListCache->rebuild($key);
$categoryAllListCache->rebuild($key);
$categoryTreeListCache->rebuild($key); $categoryTreeListCache->rebuild($key);
} }
} }
@ -114,7 +117,7 @@ class CleanDemoDataTask extends Task
$user = $userRepo->findById(100015); $user = $userRepo->findById(100015);
return $user ? true : false; return (bool)$user;
} }
} }

View File

@ -61,12 +61,15 @@ class AnswerController extends Controller
{ {
$answerService = new AnswerService(); $answerService = new AnswerService();
$publishTypes = $answerService->getPublishTypes();
$answer = $answerService->getAnswer($id); $answer = $answerService->getAnswer($id);
$questionService = new QuestionService(); $questionService = new QuestionService();
$question = $questionService->getQuestion($answer->question_id); $question = $questionService->getQuestion($answer->question_id);
$this->view->setVar('publish_types', $publishTypes);
$this->view->setVar('question', $question); $this->view->setVar('question', $question);
$this->view->setVar('answer', $answer); $this->view->setVar('answer', $answer);
} }

View File

@ -57,8 +57,11 @@ class ConsultController extends Controller
{ {
$consultService = new ConsultService(); $consultService = new ConsultService();
$publishTypes = $consultService->getPublishTypes();
$consult = $consultService->getConsult($id); $consult = $consultService->getConsult($id);
$this->view->setVar('publish_types', $publishTypes);
$this->view->setVar('consult', $consult); $this->view->setVar('consult', $consult);
} }

View File

@ -162,6 +162,10 @@ class Question extends Service
$data['keywords'] = $validator->checkKeywords($post['keywords']); $data['keywords'] = $validator->checkKeywords($post['keywords']);
} }
if (isset($post['summary'])) {
$data['summary'] = $validator->checkSummary($post['keywords']);
}
if (isset($post['anonymous'])) { if (isset($post['anonymous'])) {
$data['anonymous'] = $validator->checkAnonymousStatus($post['anonymous']); $data['anonymous'] = $validator->checkAnonymousStatus($post['anonymous']);
} }

View File

@ -7,16 +7,27 @@
<legend>编辑答案</legend> <legend>编辑答案</legend>
</fieldset> </fieldset>
<div class="layui-form-item"> <div class="layui-form-item">
<div class="layui-input-block" style="margin:0;"> <label class="layui-form-label">问题标题</label>
<input class="layui-input" type="text" name="title" value="{{ question.title }}" readonly="readonly"> <div class="layui-input-block">
<div class="layui-form-mid layui-word-aux">{{ question.title }}</div>
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<div class="layui-input-block" style="margin:0;"> <label class="layui-form-label">回答内容</label>
<div class="layui-input-block">
<textarea name="content" class="layui-hide" id="editor-textarea">{{ answer.content }}</textarea> <textarea name="content" class="layui-hide" id="editor-textarea">{{ answer.content }}</textarea>
</div> </div>
</div> </div>
<div class="layui-input-block kg-center" style="margin:0;"> <div class="layui-form-item">
<label class="layui-form-label">发布状态</label>
<div class="layui-input-block">
{% for value,title in publish_types %}
{% set checked = value == answer.published ? 'checked="checked"' : '' %}
<input type="radio" name="published" value="{{ value }}" title="{{ title }}" {{ checked }}>
{% endfor %}
</div>
</div>
<div class="layui-input-block">
<button class="layui-btn kg-submit" lay-submit="true" lay-filter="go">提交</button> <button class="layui-btn kg-submit" lay-submit="true" lay-filter="go">提交</button>
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button> <button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
<input type="hidden" name="referer" value="{{ request.getHTTPReferer() }}"> <input type="hidden" name="referer" value="{{ request.getHTTPReferer() }}">

View File

@ -52,10 +52,12 @@
</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 type="radio" name="closed" value="1" title="是" {% if article.closed == 1 %}checked="checked"{% endif %}> {% for value,title in publish_types %}
<input type="radio" name="closed" value="0" title="否" {% if article.closed == 0 %}checked="checked"{% endif %}> {% set checked = value == article.published ? 'checked="checked"' : '' %}
<input type="radio" name="published" value="{{ value }}" title="{{ title }}" {{ checked }}>
{% endfor %}
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
@ -66,10 +68,10 @@
</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 type="radio" name="published" value="1" title="是" {% if article.published == 1 %}checked="checked"{% endif %}> <input type="radio" name="closed" value="1" title="是" {% if article.closed == 1 %}checked="checked"{% endif %}>
<input type="radio" name="published" value="0" title="否" {% if article.published == 0 %}checked="checked"{% endif %}> <input type="radio" name="closed" value="0" title="否" {% if article.closed == 0 %}checked="checked"{% endif %}>
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">

View File

@ -18,6 +18,22 @@
<textarea name="answer" class="layui-textarea">{{ consult.answer }}</textarea> <textarea name="answer" class="layui-textarea">{{ consult.answer }}</textarea>
</div> </div>
</div> </div>
<div class="layui-form-item">
<label class="layui-form-label">发布</label>
<div class="layui-input-block">
{% for value,title in publish_types %}
{% set checked = value == consult.published ? 'checked="checked"' : '' %}
<input type="radio" name="published" value="{{ value }}" title="{{ title }}" {{ checked }}>
{% endfor %}
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">私密</label>
<div class="layui-input-block">
<input type="radio" name="private" value="1" title="是" {% if consult.private == 1 %}checked="checked"{% endif %}>
<input type="radio" name="private" value="0" title="否" {% if consult.private == 0 %}checked="checked"{% endif %}>
</div>
</div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label"></label> <label class="layui-form-label"></label>
<div class="layui-input-block"> <div class="layui-input-block">

View File

@ -6,12 +6,6 @@
<fieldset class="layui-elem-field layui-field-title"> <fieldset class="layui-elem-field layui-field-title">
<legend>编辑套餐</legend> <legend>编辑套餐</legend>
</fieldset> </fieldset>
<div class="layui-form-item">
<label class="layui-form-label">标题</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="title" value="{{ package.title }}" lay-verify="required">
</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-inline"> <div class="layui-input-inline">
@ -22,6 +16,12 @@
<button id="change-cover" class="layui-btn layui-btn-sm" type="button">更换</button> <button id="change-cover" class="layui-btn layui-btn-sm" type="button">更换</button>
</div> </div>
</div> </div>
<div class="layui-form-item">
<label class="layui-form-label">标题</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="title" value="{{ package.title }}" lay-verify="required">
</div>
</div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">简介</label> <label class="layui-form-label">简介</label>
<div class="layui-input-block"> <div class="layui-input-block">

View File

@ -2,6 +2,8 @@
{% block content %} {% block content %}
{% set update_url = url({'for':'admin.question.update','id':question.id}) %}
<fieldset class="layui-elem-field layui-field-title"> <fieldset class="layui-elem-field layui-field-title">
<legend>编辑问题</legend> <legend>编辑问题</legend>
</fieldset> </fieldset>
@ -9,12 +11,16 @@
<div class="layui-tab layui-tab-brief"> <div class="layui-tab layui-tab-brief">
<ul class="layui-tab-title kg-tab-title"> <ul class="layui-tab-title kg-tab-title">
<li class="layui-this">基本信息</li> <li class="layui-this">基本信息</li>
<li>搜索优化</li>
<li>内容详情</li> <li>内容详情</li>
</ul> </ul>
<div class="layui-tab-content"> <div class="layui-tab-content">
<div class="layui-tab-item layui-show"> <div class="layui-tab-item layui-show">
{{ partial('question/edit_basic') }} {{ partial('question/edit_basic') }}
</div> </div>
<div class="layui-tab-item">
{{ partial('question/edit_seo') }}
</div>
<div class="layui-tab-item"> <div class="layui-tab-item">
{{ partial('question/edit_desc') }} {{ partial('question/edit_desc') }}
</div> </div>

View File

@ -1,4 +1,4 @@
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.question.update','id':question.id}) }}"> <form class="layui-form kg-form" method="POST" action="{{ update_url }}">
<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">
@ -24,20 +24,23 @@
</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="keywords" value="{{ question.keywords }}" placeholder="多个关键字用逗号分隔"> {% for value,title in publish_types %}
{% set checked = value == question.published ? 'checked="checked"' : '' %}
<input type="radio" name="published" value="{{ value }}" title="{{ title }}" {{ checked }}>
{% endfor %}
</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 type="radio" name="anonymous" value="1" title="是" {% if question.anonymous == 1 %}checked="checked"{% endif %}> <input type="radio" name="anonymous" value="1" title="是" {% if question.anonymous == 1 %}checked="checked"{% endif %}>
<input type="radio" name="anonymous" value="0" title="否" {% if question.anonymous == 0 %}checked="checked"{% endif %}> <input type="radio" name="anonymous" value="0" title="否" {% if question.anonymous == 0 %}checked="checked"{% endif %}>
</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 type="radio" name="closed" value="1" title="是" {% if question.closed == 1 %}checked="checked"{% endif %}> <input type="radio" name="closed" value="1" title="是" {% if question.closed == 1 %}checked="checked"{% endif %}>
<input type="radio" name="closed" value="0" title="否" {% if question.closed == 0 %}checked="checked"{% endif %}> <input type="radio" name="closed" value="0" title="否" {% if question.closed == 0 %}checked="checked"{% endif %}>
@ -46,7 +49,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">
<button class="layui-btn kg-submit" lay-submit="true" lay-filter="go">提交</button> <button class="layui-btn" lay-submit="true" lay-filter="go">提交</button>
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button> <button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
</div> </div>
</div> </div>

View File

@ -1,4 +1,4 @@
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.question.update','id':question.id}) }}"> <form class="layui-form kg-form" method="POST" action="{{ update_url }}">
<div class="layui-form-item"> <div class="layui-form-item">
<div class="layui-input-block" style="margin:0;"> <div class="layui-input-block" style="margin:0;">
<textarea name="content" class="layui-hide" id="editor-textarea">{{ question.content }}</textarea> <textarea name="content" class="layui-hide" id="editor-textarea">{{ question.content }}</textarea>

View File

@ -0,0 +1,21 @@
<form class="layui-form kg-form" method="POST" action="{{ update_url }}">
<div class="layui-form-item">
<label class="layui-form-label">关键字</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="keywords" value="{{ question.keywords }}" placeholder="多个关键字用逗号分隔">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">内容摘要</label>
<div class="layui-input-block">
<textarea class="layui-textarea" name="summary">{{ question.summary }}</textarea>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"></label>
<div class="layui-input-block">
<button class="layui-btn" lay-submit="true" lay-filter="go">提交</button>
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
</div>
</div>
</form>

View File

@ -15,7 +15,6 @@ use App\Services\Logic\Course\CourseFavorite as CourseFavoriteService;
use App\Services\Logic\Course\CourseInfo as CourseInfoService; use App\Services\Logic\Course\CourseInfo as CourseInfoService;
use App\Services\Logic\Course\CourseList as CourseListService; use App\Services\Logic\Course\CourseList as CourseListService;
use App\Services\Logic\Course\PackageList as CoursePackageListService; use App\Services\Logic\Course\PackageList as CoursePackageListService;
use App\Services\Logic\Course\RecommendedList as CourseRecommendedListService;
use App\Services\Logic\Course\RelatedList as CourseRelatedListService; use App\Services\Logic\Course\RelatedList as CourseRelatedListService;
use App\Services\Logic\Course\ResourceList as CourseResourceListService; use App\Services\Logic\Course\ResourceList as CourseResourceListService;
use App\Services\Logic\Course\ReviewList as CourseReviewListService; use App\Services\Logic\Course\ReviewList as CourseReviewListService;
@ -174,19 +173,6 @@ class CourseController extends Controller
$this->view->setVar('items', $items); $this->view->setVar('items', $items);
} }
/**
* @Get("/{id:[0-9]+}/recommended", name="home.course.recommended")
*/
public function recommendedAction($id)
{
$service = new CourseRecommendedListService();
$courses = $service->handle($id);
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
$this->view->setVar('courses', $courses);
}
/** /**
* @Get("/{id:[0-9]+}/related", name="home.course.related") * @Get("/{id:[0-9]+}/related", name="home.course.related")
*/ */

View File

@ -79,7 +79,6 @@
</div> </div>
{% set show_sidebar_topics = 1 %} {% set show_sidebar_topics = 1 %}
{% set show_sidebar_recommended = 1 %}
{% set show_sidebar_related = 1 %} {% set show_sidebar_related = 1 %}
<div class="layout-sidebar"> <div class="layout-sidebar">
@ -89,10 +88,6 @@
{% set topics_url = url({'for':'home.course.topics','id':course.id}) %} {% set topics_url = url({'for':'home.course.topics','id':course.id}) %}
<div class="sidebar" id="sidebar-topics" data-url="{{ topics_url }}"></div> <div class="sidebar" id="sidebar-topics" data-url="{{ topics_url }}"></div>
{% endif %} {% endif %}
{% if show_sidebar_recommended %}
{% set recommended_url = url({'for':'home.course.recommended','id':course.id}) %}
<div class="sidebar" id="sidebar-recommended" data-url="{{ recommended_url }}"></div>
{% endif %}
{% if show_sidebar_related %} {% if show_sidebar_related %}
{% set related_url = url({'for':'home.course.related','id':course.id}) %} {% set related_url = url({'for':'home.course.related','id':course.id}) %}
<div class="sidebar" id="sidebar-related" data-url="{{ related_url }}"></div> <div class="sidebar" id="sidebar-related" data-url="{{ related_url }}"></div>

View File

@ -43,25 +43,18 @@
<a href="{{ course_url }}" title="{{ course.title }}" target="_blank">{{ course.title }}</a> <a href="{{ course_url }}" title="{{ course.title }}" target="_blank">{{ course.title }}</a>
</div> </div>
<div class="meta"> <div class="meta">
{% if course.market_price > course.vip_price %} {% if course.market_price == 0 %}
<span>{{ '¥%0.2f'|format(course.market_price) }}</span> <span class="free">全员免费</span>
{% if course.vip_price > 0 %} <span class="lesson">{{ course.lesson_count }}节课</span>
<span class="price">{{ '会员¥%0.2f'|format(course.vip_price) }}</span> <span class="user">{{ course.user_count }}人报名</span>
{% else %} {% elseif course.vip_price == 0 %}
<span class="free">会员免费</span> <span class="free">会员免费</span>
{% endif %} <span class="lesson">{{ course.lesson_count }}节课</span>
<span class="level">{{ level_type(course.level) }}</span>
<span class="user">{{ course.user_count }}人购买</span> <span class="user">{{ course.user_count }}人购买</span>
{% elseif course.market_price > 0 %} {% elseif course.market_price > 0 %}
<span class="price">{{ '¥%0.2f'|format(course.market_price) }}</span> <span class="price">{{ '¥%0.2f'|format(course.market_price) }}</span>
<span class="level">{{ level_type(course.level) }}</span>
<span class="lesson">{{ course.lesson_count }}节课</span> <span class="lesson">{{ course.lesson_count }}节课</span>
<span class="user">{{ course.user_count }}人购买</span> <span class="user">{{ course.user_count }}人购买</span>
{% else %}
<span class="free">免费</span>
<span class="level">{{ level_type(course.level) }}</span>
<span class="lesson">{{ course.lesson_count }}节课</span>
<span class="user">{{ course.user_count }}人报名</span>
{% endif %} {% endif %}
</div> </div>
</div> </div>

View File

@ -22,17 +22,13 @@
</ul> </ul>
</div> </div>
{% set s_type = request.get('type',['trim','string'],'course') %}
{% set s_query = request.get('query',['trim','striptags'],'') %}
{% set s_url = url({'for':'home.search.index'}) %}
<div class="user"> <div class="user">
<ul class="layui-nav"> <ul class="layui-nav">
<li class="layui-nav-item"> <li class="layui-nav-item">
<a href="javascript:" class="nav-search" data-type="{{ s_type }}" data-query="{{ s_query }}" data-url="{{ s_url }}"><i class="layui-icon layui-icon-search"></i> 搜索</a> <a class="nav-search" href="javascript:" data-url="{{ url({'for':'home.search.index'}) }}"><i class="layui-icon layui-icon-search"></i> 搜索</a>
</li> </li>
<li class="layui-nav-item"> <li class="layui-nav-item">
<a href="{{ url({'for':'home.vip.index'}) }}" class="nav-vip"><i class="layui-icon layui-icon-diamond"></i> 会员</a> <a class="nav-vip" href="{{ url({'for':'home.vip.index'}) }}"><i class="layui-icon layui-icon-diamond"></i> 会员</a>
</li> </li>
{% if auth_user.id > 0 %} {% if auth_user.id > 0 %}
<li class="layui-nav-item"> <li class="layui-nav-item">

View File

@ -8,13 +8,18 @@
{% set type = request.get('type','trim','course') %} {% set type = request.get('type','trim','course') %}
{% set query = request.get('query','striptags','') %} {% set query = request.get('query','striptags','') %}
<div class="layui-breadcrumb breadcrumb"> <form class="layui-form" method="GET" action="{{ url({'for':'home.search.index'}) }}">
<a href="/">首页</a> <div class="layui-form-item">
<a href="#">搜索</a> <div class="layui-inline">
<a><cite>{{ query }}</cite></a> <input class="layui-input query-input" type="text" name="query" value="{{ query }}" lay-verify="required">
</div> </div>
<div class="layui-inline">
<button class="layui-btn" lay-submit="true" lay-filter="search">搜索</button>
<input type="hidden" name="type" value="{{ type }}">
</div>
</div>
</form>
{% set tab_show = type %}
<div class="layout-main"> <div class="layout-main">
<div class="layout-content"> <div class="layout-content">
<div class="search-tab-wrap wrap"> <div class="search-tab-wrap wrap">
@ -50,4 +55,19 @@
</div> </div>
</div> </div>
{% endblock %}
{% block inline_js %}
<script>
layui.use(['form'], function () {
var form = layui.form;
form.on('submit(search)', function (data) {
if (data.field.query === '') {
return false;
}
});
});
</script>
{% endblock %} {% endblock %}

View File

@ -2,7 +2,7 @@
{% block content %} {% block content %}
{% set types = {'course':'课程','article':'文章','question':'问题'} %} {% set types = {'course':'课程','article':'专栏','question':'问题'} %}
{% set type = request.get('type','trim','course') %} {% set type = request.get('type','trim','course') %}
<div class="layout-main"> <div class="layout-main">

View File

@ -267,7 +267,7 @@ class Article extends Model
public function afterFetch() public function afterFetch()
{ {
if (!empty($this->cover) && !Text::startsWith($this->cover, 'http')) { if (!Text::startsWith($this->cover, 'http')) {
$this->cover = kg_cos_article_cover_url($this->cover); $this->cover = kg_cos_article_cover_url($this->cover);
} }

View File

@ -78,20 +78,16 @@ class ArticleList extends LogicService
$items = []; $items = [];
$baseUrl = kg_cos_url(); $cosUrl = kg_cos_url();
foreach ($articles as $article) { foreach ($articles as $article) {
if (!empty($question['cover']) && !Text::startsWith($question['cover'], 'http')) {
$question['cover'] = $cosUrl . $question['cover'];
}
$article['tags'] = json_decode($article['tags'], true); $article['tags'] = json_decode($article['tags'], true);
if (empty($article['cover'])) {
$article['cover'] = kg_default_article_cover_path();
}
if (!Text::startsWith($article['cover'], 'http')) {
$article['cover'] = $baseUrl . $article['cover'];
}
$category = $categories[$article['category_id']] ?? new \stdClass(); $category = $categories[$article['category_id']] ?? new \stdClass();
$owner = $users[$article['owner_id']] ?? new \stdClass(); $owner = $users[$article['owner_id']] ?? new \stdClass();

View File

@ -1,30 +0,0 @@
<?php
/**
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
* @license https://opensource.org/licenses/GPL-2.0
* @link https://www.koogua.com
*/
namespace App\Services\Logic\Course;
use App\Caches\CourseRecommendedList as CourseRecommendedListCache;
use App\Services\Logic\CourseTrait;
use App\Services\Logic\Service as LogicService;
class RecommendedList extends LogicService
{
use CourseTrait;
public function handle($id)
{
$course = $this->checkCourse($id);
$cache = new CourseRecommendedListCache();
$result = $cache->get($course->id);
return $result ?: [];
}
}

View File

@ -27,10 +27,10 @@ class CourseDeliver extends LogicService
protected function handleCourseUser(CourseModel $course, UserModel $user) protected function handleCourseUser(CourseModel $course, UserModel $user)
{ {
$expiryTime = strtotime("+{$course->study_expiry} months");
if ($course->model == CourseModel::MODEL_OFFLINE) { if ($course->model == CourseModel::MODEL_OFFLINE) {
$expiryTime = strtotime($course->attrs['end_date']); $expiryTime = strtotime($course->attrs['end_date']);
} else {
$expiryTime = strtotime("+{$course->study_expiry} months");
} }
$sourceType = CourseUserModel::SOURCE_CHARGE; $sourceType = CourseUserModel::SOURCE_CHARGE;
@ -50,8 +50,7 @@ class CourseDeliver extends LogicService
foreach ($relations as $relation) { foreach ($relations as $relation) {
if ($relation->deleted == 0) { if ($relation->deleted == 0) {
$relation->deleted = 1; $this->deleteCourseUser($relation);
$relation->update();
} }
} }
} }

View File

@ -89,7 +89,7 @@ class Consult extends Validator
public function checkPublishStatus($status) public function checkPublishStatus($status)
{ {
if (!in_array($status, [0, 1])) { if (!array_key_exists($status, ConsultModel::publishTypes())) {
throw new BadRequestException('consult.invalid_publish_status'); throw new BadRequestException('consult.invalid_publish_status');
} }
@ -98,18 +98,11 @@ class Consult extends Validator
public function checkReplyPriv(ConsultModel $consult, UserModel $user) public function checkReplyPriv(ConsultModel $consult, UserModel $user)
{ {
$repo = new CourseRepo(); $courseRepo = new CourseRepo();
$teachers = $repo->findTeachers($consult->course_id); $course = $courseRepo->findById($consult->course_id);
$isTeacher = false; if ($course->teacher_id != $user->id) {
if ($teachers->count() > 0) {
$teacherIds = kg_array_column($teachers->toArray(), 'id');
$isTeacher = in_array($user->id, $teacherIds);
}
if (!$isTeacher) {
throw new ForbiddenException('sys.forbidden'); throw new ForbiddenException('sys.forbidden');
} }
} }

View File

@ -90,6 +90,19 @@ class Question extends Validator
return $value; return $value;
} }
public function checkSummary($summary)
{
$value = $this->filter->sanitize($summary, ['trim', 'string']);
$length = kg_strlen($value);
if ($length > 255) {
throw new BadRequestException('question.summary_too_long');
}
return $value;
}
public function checkKeywords($keywords) public function checkKeywords($keywords)
{ {
$keywords = $this->filter->sanitize($keywords, ['trim', 'string']); $keywords = $this->filter->sanitize($keywords, ['trim', 'string']);

View File

@ -120,6 +120,7 @@ $error['article.not_found'] = '文章不存在';
$error['article.title_too_short'] = '标题太短少于2个字符'; $error['article.title_too_short'] = '标题太短少于2个字符';
$error['article.title_too_long'] = '标题太长多于50个字符'; $error['article.title_too_long'] = '标题太长多于50个字符';
$error['article.keyword_too_long'] = '关键字太长多于100个字符'; $error['article.keyword_too_long'] = '关键字太长多于100个字符';
$error['article.summary_too_long'] = '摘要太长多于255个字符';
$error['article.content_too_short'] = '内容太短少于10个字符'; $error['article.content_too_short'] = '内容太短少于10个字符';
$error['article.content_too_long'] = '内容太长多于30000个字符'; $error['article.content_too_long'] = '内容太长多于30000个字符';
$error['article.invalid_source_type'] = '无效的来源类型'; $error['article.invalid_source_type'] = '无效的来源类型';
@ -138,6 +139,7 @@ $error['question.not_found'] = '问题不存在';
$error['question.title_too_short'] = '标题太短少于5个字符'; $error['question.title_too_short'] = '标题太短少于5个字符';
$error['question.title_too_long'] = '标题太长多于50个字符'; $error['question.title_too_long'] = '标题太长多于50个字符';
$error['question.keyword_too_long'] = '关键字太长多于100个字符'; $error['question.keyword_too_long'] = '关键字太长多于100个字符';
$error['question.summary_too_long'] = '摘要太长多于255个字符';
$error['question.content_too_short'] = '内容太短少于10个字符'; $error['question.content_too_short'] = '内容太短少于10个字符';
$error['question.content_too_long'] = '内容太长多于30000个字符'; $error['question.content_too_long'] = '内容太长多于30000个字符';
$error['question.invalid_publish_status'] = '无效的发布状态'; $error['question.invalid_publish_status'] = '无效的发布状态';

View File

@ -330,6 +330,10 @@
height: 100%; height: 100%;
} }
.query-input {
width: 720px;
}
.search-tab { .search-tab {
margin: 0; margin: 0;
} }

View File

@ -1,23 +1,7 @@
layui.use(['jquery', 'form', 'layer'], function () { layui.use(['jquery', 'form'], function () {
var $ = layui.jquery; var $ = layui.jquery;
var form = layui.form; var form = layui.form;
var layer = layui.layer;
$('.publish').on('click', function () {
var layerWidth = 360;
var layerTop = $(this).offset().top + $(this).height() + 5 + 'px';
var layerLeft = ($(this).offset().left + $(this).width() - layerWidth) + 'px';
layer.open({
type: 1,
title: false,
closeBtn: false,
shadeClose: true,
content: $('#layer-publish'),
offset: [layerTop, layerLeft],
area: layerWidth + 'px',
});
});
form.on('select(source_type)', function (data) { form.on('select(source_type)', function (data) {
var block = $('#source-url-block'); var block = $('#source-url-block');
@ -35,8 +19,6 @@ layui.use(['jquery', 'form', 'layer'], function () {
name: 'xm_tag_ids', name: 'xm_tag_ids',
max: 3, max: 3,
data: xmTags, data: xmTags,
layVerify: 'required',
layVerType: 'msg',
autoRow: true, autoRow: true,
filterable: true, filterable: true,
filterMethod: function (val, item, index, prop) { filterMethod: function (val, item, index, prop) {

View File

@ -102,7 +102,6 @@ layui.use(['jquery', 'form', 'element', 'layer', 'helper'], function () {
$('.nav-search').on('click', function () { $('.nav-search').on('click', function () {
var content = '<form action="' + $(this).data('url') + '">'; var content = '<form action="' + $(this).data('url') + '">';
content += '<input type="text" name="query" autocomplete="off" placeholder="搜索内容,回车跳转">'; content += '<input type="text" name="query" autocomplete="off" placeholder="搜索内容,回车跳转">';
content += '<input type="hidden" name="type" value="' + $(this).data('type') + '">';
content += '</form>'; content += '</form>';
layer.open({ layer.open({
type: 1, type: 1,

View File

@ -145,11 +145,6 @@ layui.use(['jquery', 'layer', 'helper'], function () {
helper.ajaxLoadHtml($sdTopics.data('url'), $sdTopics.attr('id')); helper.ajaxLoadHtml($sdTopics.data('url'), $sdTopics.attr('id'));
} }
if ($('#sidebar-recommended').length > 0) {
var $sdRecommended = $('#sidebar-recommended');
helper.ajaxLoadHtml($sdRecommended.data('url'), $sdRecommended.attr('id'));
}
if ($('#sidebar-related').length > 0) { if ($('#sidebar-related').length > 0) {
var $sdRelated = $('#sidebar-related'); var $sdRelated = $('#sidebar-related');
helper.ajaxLoadHtml($sdRelated.data('url'), $sdRelated.attr('id')); helper.ajaxLoadHtml($sdRelated.data('url'), $sdRelated.attr('id'));

View File

@ -1,22 +1,7 @@
layui.use(['jquery', 'form', 'layer'], function () { layui.use(['jquery'], function () {
var $ = layui.jquery; var $ = layui.jquery;
$('.publish').on('click', function () {
var layerWidth = 360;
var layerTop = $(this).offset().top + $(this).height() + 5 + 'px';
var layerLeft = ($(this).offset().left + $(this).width() - layerWidth) + 'px';
layer.open({
type: 1,
title: false,
closeBtn: false,
shadeClose: true,
content: $('#layer-publish'),
offset: [layerTop, layerLeft],
area: [layerWidth + 'px', '360px'],
});
});
var xmTags = JSON.parse($('input[name=xm_tags]').val()); var xmTags = JSON.parse($('input[name=xm_tags]').val());
xmSelect.render({ xmSelect.render({
@ -24,8 +9,6 @@ layui.use(['jquery', 'form', 'layer'], function () {
name: 'xm_tag_ids', name: 'xm_tag_ids',
max: 3, max: 3,
data: xmTags, data: xmTags,
layVerify: 'required',
layVerType: 'msg',
autoRow: true, autoRow: true,
filterable: true, filterable: true,
filterMethod: function (val, item, index, prop) { filterMethod: function (val, item, index, prop) {