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

增加问题推荐

This commit is contained in:
xiaochong0302 2023-12-11 12:23:42 +08:00
parent 4c3436dc95
commit 12ceda62df
16 changed files with 180 additions and 35 deletions

View File

@ -75,7 +75,7 @@ class FeaturedArticleList extends Cache
->where('featured = 1')
->andWhere('published = 1')
->andWhere('deleted = 0')
->orderBy('id DESC')
->orderBy('RAND()')
->limit($limit)
->execute();
}

View File

@ -77,7 +77,7 @@ class FeaturedCourseList extends Cache
->where('featured = 1')
->andWhere('published = 1')
->andWhere('deleted = 0')
->orderBy('id DESC')
->orderBy('RAND()')
->limit($limit)
->execute();
}

View File

@ -0,0 +1,74 @@
<?php
/**
* @copyright Copyright (c) 2023 深圳市酷瓜软件有限公司
* @license https://opensource.org/licenses/GPL-2.0
* @link https://www.koogua.com
*/
namespace App\Caches;
use App\Models\Question as QuestionModel;
use Phalcon\Mvc\Model\Resultset;
use Phalcon\Mvc\Model\ResultsetInterface;
class FeaturedQuestionList extends Cache
{
protected $lifetime = 86400;
public function getLifetime()
{
$tomorrow = strtotime('tomorrow');
return $tomorrow - time();
}
public function getKey($id = null)
{
return 'featured_question_list';
}
public function getContent($id = null)
{
$limit = 5;
$questions = $this->findQuestions($limit);
if ($questions->count() == 0) {
return [];
}
$result = [];
foreach ($questions as $question) {
$result[] = [
'id' => $question->id,
'title' => $question->title,
'cover' => $question->cover,
'favorite_count' => $question->favorite_count,
'answer_count' => $question->answer_count,
'view_count' => $question->view_count,
'like_count' => $question->like_count,
];
}
return $result;
}
/**
* @param int $limit
* @return ResultsetInterface|Resultset|QuestionModel[]
*/
protected function findQuestions($limit = 5)
{
return QuestionModel::query()
->where('featured = 1')
->andWhere('published = 1')
->andWhere('deleted = 0')
->orderBy('RAND()')
->limit($limit)
->execute();
}
}

View File

@ -170,6 +170,10 @@ class Question extends Service
$data['anonymous'] = $validator->checkAnonymousStatus($post['anonymous']);
}
if (isset($post['featured'])) {
$data['featured'] = $validator->checkFeatureStatus($post['featured']);
}
if (isset($post['closed'])) {
$data['closed'] = $validator->checkCloseStatus($post['closed']);
}

View File

@ -33,10 +33,10 @@
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">匿名提问</label>
<label class="layui-form-label">推荐问题</label>
<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="0" title="否" {% if question.anonymous == 0 %}checked="checked"{% endif %}>
<input type="radio" name="featured" value="1" title="是" {% if question.featured == 1 %}checked="checked"{% endif %}>
<input type="radio" name="featured" value="0" title="否" {% if question.featured == 0 %}checked="checked"{% endif %}>
</div>
</div>
<div class="layui-form-item">

View File

@ -37,6 +37,7 @@
<col>
<col>
<col>
<col>
<col width="10%">
</colgroup>
<thead>
@ -46,6 +47,7 @@
<th>问题信息</th>
<th>统计信息</th>
<th>状态</th>
<th>推荐</th>
<th>关闭</th>
<th>操作</th>
</tr>
@ -87,6 +89,8 @@
</p>
</td>
<td>{{ publish_status(item.published) }}</td>
<td><input type="checkbox" name="featured" value="1" lay-text="是|否" lay-skin="switch" lay-filter="go" data-url="{{ update_url }}"
{% if item.featured == 1 %}checked="checked"{% endif %}></td>
<td><input type="checkbox" name="closed" value="1" lay-text="是|否" lay-skin="switch" lay-filter="go" data-url="{{ update_url }}"
{% if item.closed == 1 %}checked="checked"{% endif %}></td>
<td class="center">

View File

@ -54,10 +54,10 @@
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">匿名</label>
<label class="layui-form-label">推荐</label>
<div class="layui-input-block">
<input type="radio" name="anonymous" value="1" title="是">
<input type="radio" name="anonymous" value="0" title="否">
<input type="radio" name="featured" value="1" title="是">
<input type="radio" name="featured" value="0" title="否">
</div>
</div>
<div class="layui-form-item">

View File

@ -8,13 +8,13 @@
{% set type = request.get('type','trim','course') %}
{% set query = request.get('query','striptags','') %}
<form class="layui-form" method="GET" action="{{ url({'for':'home.search.index'}) }}">
<form class="layui-form search-form" method="GET" action="{{ url({'for':'home.search.index'}) }}">
<div class="layui-form-item">
<div class="layui-inline">
<input class="layui-input query-input" type="text" name="query" value="{{ query }}" lay-verify="required">
</div>
<div class="layui-inline">
<button class="layui-btn" lay-submit="true" lay-filter="search">搜索</button>
<button class="layui-btn search-btn" lay-submit="true" lay-filter="search">搜索</button>
<input type="hidden" name="type" value="{{ type }}">
</div>
</div>

View File

@ -5,7 +5,7 @@
<div class="sidebar-article-list">
{% for article in articles %}
{% set article_url = url({'for':'home.article.show','id':article.id}) %}
<div class="title">
<div class="title layui-elip">
<a href="{{ article_url }}" target="_blank">{{ article.title }}</a>
</div>
<div class="meta">

View File

@ -0,0 +1,20 @@
{% if questions|length > 0 %}
<div class="layui-card">
<div class="layui-card-header">推荐问题</div>
<div class="layui-card-body">
<div class="sidebar-question-list">
{% for question in questions %}
{% set question_url = url({'for':'home.question.show','id':question.id}) %}
<div class="title layui-elip">
<a href="{{ question_url }}" target="_blank">{{ question.title }}</a>
</div>
<div class="meta">
<span class="view">{{ question.view_count }} 浏览</span>
<span class="like">{{ question.like_count }} 点赞</span>
<span class="comment">{{ question.comment_count }} 评论</span>
</div>
{% endfor %}
</div>
</div>
</div>
{% endif %}

View File

@ -149,6 +149,13 @@ class Question extends Model
*/
public $published = self::PUBLISH_PENDING;
/**
* 推荐标识
*
* @var integer
*/
public $featured = 0;
/**
* 删除标识
*
@ -318,9 +325,10 @@ class Question extends Model
public static function sortTypes()
{
return [
'latest' => '最新问',
'latest' => '最新',
'active' => '最新回答',
'unanswered' => '尚未回答',
'featured' => '推荐问题',
];
}

View File

@ -58,6 +58,20 @@ class Question extends Repository
}
}
if (!empty($where['published'])) {
if (is_array($where['published'])) {
$builder->inWhere('published', $where['published']);
} else {
$builder->andWhere('published = :published:', ['published' => $where['published']]);
}
}
if (!empty($where['create_time'][0]) && !empty($where['create_time'][1])) {
$startTime = strtotime($where['create_time'][0]);
$endTime = strtotime($where['create_time'][1]);
$builder->betweenWhere('create_time', $startTime, $endTime);
}
if (!empty($where['owner_id'])) {
$builder->andWhere('owner_id = :owner_id:', ['owner_id' => $where['owner_id']]);
}
@ -74,33 +88,23 @@ class Question extends Repository
$builder->andWhere('closed = :closed:', ['closed' => $where['closed']]);
}
if (isset($where['featured'])) {
$builder->andWhere('featured = :featured:', ['featured' => $where['featured']]);
}
if (isset($where['solved'])) {
$builder->andWhere('solved = :solved:', ['solved' => $where['solved']]);
}
if (!empty($where['published'])) {
if (is_array($where['published'])) {
$builder->inWhere('published', $where['published']);
} else {
$builder->andWhere('published = :published:', ['published' => $where['published']]);
}
}
if (!empty($where['create_time'][0]) && !empty($where['create_time'][1])) {
$startTime = strtotime($where['create_time'][0]);
$endTime = strtotime($where['create_time'][1]);
$builder->betweenWhere('create_time', $startTime, $endTime);
}
if (isset($where['deleted'])) {
$builder->andWhere('deleted = :deleted:', ['deleted' => $where['deleted']]);
}
if ($sort == 'unanswered') {
if ($sort == 'featured') {
$builder->andWhere('featured = 1');
} elseif ($sort == 'unanswered') {
$builder->andWhere('answer_count = 0');
}
if ($sort == 'reported') {
} elseif ($sort == 'reported') {
$builder->andWhere('report_count > 0');
}

View File

@ -82,8 +82,8 @@ class ArticleList extends LogicService
foreach ($articles as $article) {
if (!empty($question['cover']) && !Text::startsWith($question['cover'], 'http')) {
$question['cover'] = $cosUrl . $question['cover'];
if (!empty($article['cover']) && !Text::startsWith($article['cover'], 'http')) {
$article['cover'] = $cosUrl . $article['cover'];
}
$article['tags'] = json_decode($article['tags'], true);

View File

@ -11,7 +11,6 @@ use App\Caches\MaxQuestionId as MaxQuestionIdCache;
use App\Caches\Question as QuestionCache;
use App\Exceptions\BadRequest as BadRequestException;
use App\Models\Question as QuestionModel;
use App\Models\Reason as ReasonModel;
use App\Repos\Question as QuestionRepo;
use App\Services\EditorStorage as EditorStorageService;
@ -151,6 +150,15 @@ class Question extends Validator
return $status;
}
public function checkFeatureStatus($status)
{
if (!in_array($status, [0, 1])) {
throw new BadRequestException('question.invalid_feature_status');
}
return $status;
}
public function checkCloseStatus($status)
{
if (!in_array($status, [0, 1])) {

View File

@ -14,6 +14,7 @@ final class V20231108085025 extends AbstractMigration
public function up()
{
$this->alterVipTable();
$this->alterQuestionTable();
$this->alterArticleTable();
$this->alterConsultTable();
$this->alterResourceTable();
@ -45,6 +46,24 @@ final class V20231108085025 extends AbstractMigration
$table->save();
}
protected function alterQuestionTable()
{
$table = $this->table('kg_question');
if (!$table->hasColumn('featured')) {
$table->addColumn('featured', 'integer', [
'null' => false,
'default' => '0',
'limit' => MysqlAdapter::INT_REGULAR,
'signed' => false,
'comment' => '推荐标识',
'after' => 'published',
]);
}
$table->save();
}
protected function alterArticleTable()
{
$table = $this->table('kg_article');

View File

@ -330,8 +330,12 @@
height: 100%;
}
.query-input {
width: 720px;
.search-form .query-input {
width: 696px;
}
.search-form .search-btn {
padding: 0 30px;
}
.search-tab {