1
0
mirror of https://gitee.com/koogua/course-tencent-cloud.git synced 2025-07-24 00:41:43 +08:00

1.文章单页等增加关键字

2.专题增加封面上传
This commit is contained in:
koogua 2022-09-15 20:39:49 +08:00
parent c801559b62
commit 79a2253918
33 changed files with 355 additions and 11 deletions

View File

@ -169,6 +169,10 @@ class Article extends Service
$data['title'] = $validator->checkTitle($post['title']);
}
if (isset($post['keywords'])) {
$data['keywords'] = $validator->checkKeywords($post['keywords']);
}
if (isset($post['content'])) {
$data['content'] = $validator->checkContent($post['content']);
$data['word_count'] = WordUtil::getWordCount($data['content']);

View File

@ -103,6 +103,10 @@ class Help extends Service
$data['content'] = $validator->checkContent($post['content']);
}
if (isset($post['keywords'])) {
$data['keywords'] = $validator->checkKeywords($post['keywords']);
}
if (isset($post['priority'])) {
$data['priority'] = $validator->checkPriority($post['priority']);
}

View File

@ -122,14 +122,14 @@ class Package extends Service
$data = [];
if (isset($post['cover'])) {
$data['cover'] = $validator->checkCover($post['cover']);
}
if (isset($post['title'])) {
$data['title'] = $validator->checkTitle($post['title']);
}
if (isset($post['cover'])) {
$data['cover'] = $validator->checkCover($post['cover']);
}
if (isset($post['summary'])) {
$data['summary'] = $validator->checkSummary($post['summary']);
}

View File

@ -86,6 +86,10 @@ class Page extends Service
$data['content'] = $validator->checkContent($post['content']);
}
if (isset($post['keywords'])) {
$data['keywords'] = $validator->checkKeywords($post['keywords']);
}
if (isset($post['published'])) {
$data['published'] = $validator->checkPublishStatus($post['published']);
}

View File

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

View File

@ -112,6 +112,10 @@ class Topic extends Service
$data['title'] = $validator->checkTitle($post['title']);
}
if (isset($post['cover'])) {
$data['cover'] = $validator->checkCover($post['cover']);
}
if (isset($post['summary'])) {
$data['summary'] = $validator->checkSummary($post['summary']);
}

View File

@ -13,6 +13,12 @@
<div id="xm-tag-ids"></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="keywords" value="{{ article.keywords }}" placeholder="多个关键字用逗号分隔">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">来源类型</label>
<div class="layui-input-block">

View File

@ -23,6 +23,12 @@
<input class="layui-input" type="text" name="title" value="{{ help.title }}" lay-verify="required">
</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="keywords" value="{{ help.keywords }}" placeholder="多个关键字用逗号分隔">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">内容</label>
<div class="layui-input-block">

View File

@ -18,6 +18,12 @@
<input class="layui-input" type="text" name="alias" value="{{ page.alias }}" placeholder="可以通过 /page/{别名} 访问页面">
</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="keywords" value="{{ page.keywords }}" placeholder="多个关键字用逗号分隔">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">内容</label>
<div class="layui-input-block">

View File

@ -11,6 +11,12 @@
<div id="xm-tag-ids"></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="keywords" value="{{ question.keywords }}" placeholder="多个关键字用逗号分隔">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">匿名</label>
<div class="layui-input-block">

View File

@ -12,6 +12,16 @@
<input class="layui-input" type="text" name="title" value="{{ topic.title }}" lay-verify="required">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">封面</label>
<div class="layui-input-inline">
<img id="img-cover" class="kg-cover" src="{{ topic.cover }}">
<input type="hidden" name="cover" value="{{ topic.cover }}">
</div>
<div class="layui-input-inline" style="padding-top:35px;">
<button id="change-cover" class="layui-btn layui-btn-sm" type="button">更换</button>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">简介</label>
<div class="layui-input-block">
@ -38,6 +48,7 @@
{% block include_js %}
{{ js_include('lib/xm-select.js') }}
{{ js_include('admin/js/cover.upload.js') }}
{% endblock %}

View File

@ -451,6 +451,32 @@ function kg_parse_summary($content, $length = 150)
return kg_substr($content, 0, $length);
}
/**
* 解析关键字
*
* @param string $content
* @return string
*/
function kg_parse_keywords($content)
{
$search = ['|', ';', '', '、', ','];
$keywords = str_replace($search, '@', $content);
$keywords = explode('@', $keywords);
$list = [];
foreach ($keywords as $keyword) {
$keyword = trim($keyword);
if (kg_strlen($keyword) > 1) {
$list[] = $keyword;
}
}
return implode('', $list);
}
/**
* 解析内容中上传首图
*

View File

@ -64,6 +64,13 @@ class Article extends Model
*/
public $content = '';
/**
* 关键字
*
* @var string
*/
public $keywords = '';
/**
* 标签
*

View File

@ -150,7 +150,7 @@ class Category extends Model
public function beforeSave()
{
if (empty($this->icon)) {
$this->icon = kg_default_icon_path();
$this->icon = kg_default_category_icon_path();
} elseif (Text::startsWith($this->icon, 'http')) {
$this->icon = self::getIconPath($this->icon);
}
@ -166,7 +166,7 @@ class Category extends Model
public function afterFetch()
{
if (!Text::startsWith($this->icon, 'http')) {
$this->icon = kg_cos_icon_url($this->icon);
$this->icon = kg_cos_category_icon_url($this->icon);
}
}

View File

@ -34,6 +34,13 @@ class Help extends Model
*/
public $title = '';
/**
* 关键字
*
* @var string
*/
public $keywords = '';
/**
* 内容
*

View File

@ -34,6 +34,13 @@ class Page extends Model
*/
public $alias = '';
/**
* 关键字
*
* @var string
*/
public $keywords = '';
/**
* 内容
*

View File

@ -85,6 +85,13 @@ class Question extends Model
*/
public $tags = [];
/**
* 关键字
*
* @var string
*/
public $keywords = '';
/**
* 概要
*

View File

@ -149,7 +149,7 @@ class Tag extends Model
public function beforeSave()
{
if (empty($this->icon)) {
$this->icon = kg_default_icon_path();
$this->icon = kg_default_category_icon_path();
} elseif (Text::startsWith($this->icon, 'http')) {
$this->icon = self::getIconPath($this->icon);
}
@ -169,7 +169,7 @@ class Tag extends Model
public function afterFetch()
{
if (!Text::startsWith($this->icon, 'http')) {
$this->icon = kg_cos_icon_url($this->icon);
$this->icon = kg_cos_category_icon_url($this->icon);
}
if (is_string($this->scopes) && $this->scopes != 'all') {

View File

@ -9,6 +9,7 @@ namespace App\Models;
use App\Caches\MaxTopicId as MaxTopicIdCache;
use Phalcon\Mvc\Model\Behavior\SoftDelete;
use Phalcon\Text;
class Topic extends Model
{
@ -27,6 +28,13 @@ class Topic extends Model
*/
public $title = '';
/**
* 封面
*
* @var string
*/
public $cover = '';
/**
* 简介
*
@ -96,6 +104,15 @@ class Topic extends Model
$this->update_time = time();
}
public function beforeSave()
{
if (empty($this->cover)) {
$this->cover = kg_default_topic_cover_path();
} elseif (Text::startsWith($this->cover, 'http')) {
$this->cover = self::getCoverPath($this->cover);
}
}
public function afterCreate()
{
$cache = new MaxTopicIdCache();
@ -103,4 +120,20 @@ class Topic extends Model
$cache->rebuild();
}
public function afterFetch()
{
if (!Text::startsWith($this->cover, 'http')) {
$this->cover = kg_cos_topic_cover_url($this->cover);
}
}
public static function getCoverPath($url)
{
if (Text::startsWith($url, 'http')) {
return parse_url($url, PHP_URL_PATH);
}
return $url;
}
}

View File

@ -49,6 +49,7 @@ class ArticleInfo extends LogicService
'title' => $article->title,
'cover' => $article->cover,
'summary' => $article->summary,
'keywords' => $article->keywords,
'tags' => $article->tags,
'content' => $article->content,
'private' => $article->private,

View File

@ -28,6 +28,7 @@ class HelpInfo extends LogicService
return [
'id' => $help->id,
'title' => $help->title,
'keywords' => $help->keywords,
'content' => $help->content,
'published' => $help->published,
'deleted' => $help->deleted,

View File

@ -28,6 +28,7 @@ class PageInfo extends LogicService
return [
'id' => $page->id,
'title' => $page->title,
'keywords' => $page->keywords,
'content' => $page->content,
'published' => $page->published,
'deleted' => $page->deleted,

View File

@ -51,6 +51,7 @@ class QuestionInfo extends LogicService
'title' => $question->title,
'summary' => $question->summary,
'content' => $question->content,
'keywords' => $question->keywords,
'tags' => $question->tags,
'bounty' => $question->bounty,
'anonymous' => $question->anonymous,

View File

@ -28,6 +28,7 @@ class TopicInfo extends LogicService
return [
'id' => $topic->id,
'title' => $topic->title,
'topic' => $topic->cover,
'summary' => $topic->summary,
'published' => $topic->published,
'deleted' => $topic->deleted,

View File

@ -107,6 +107,19 @@ class Article extends Validator
return kg_clean_html($value);
}
public function checkKeywords($keywords)
{
$keywords = $this->filter->sanitize($keywords, ['trim', 'string']);
$length = kg_strlen($keywords);
if ($length > 100) {
throw new BadRequestException('article.keyword_too_long');
}
return kg_parse_keywords($keywords);
}
public function checkSourceType($type)
{
if (!array_key_exists($type, ArticleModel::sourceTypes())) {

View File

@ -148,7 +148,7 @@ class Course extends Validator
$length = kg_strlen($keywords);
if ($length > 100) {
throw new BadRequestException('course.keywords_too_long');
throw new BadRequestException('course.keyword_too_long');
}
$keywords = str_replace(['|', ';', '', '、', ','], '@', $keywords);

View File

@ -103,6 +103,19 @@ class Help extends Validator
return kg_clean_html($value);
}
public function checkKeywords($keywords)
{
$keywords = $this->filter->sanitize($keywords, ['trim', 'string']);
$length = kg_strlen($keywords);
if ($length > 100) {
throw new BadRequestException('help.keyword_too_long');
}
return kg_parse_keywords($keywords);
}
public function checkPriority($priority)
{
$value = $this->filter->sanitize($priority, ['trim', 'int']);

View File

@ -107,6 +107,19 @@ class Page extends Validator
return $value;
}
public function checkKeywords($keywords)
{
$keywords = $this->filter->sanitize($keywords, ['trim', 'string']);
$length = kg_strlen($keywords);
if ($length > 100) {
throw new BadRequestException('page.keyword_too_long');
}
return kg_parse_keywords($keywords);
}
public function checkContent($content)
{
$value = $this->filter->sanitize($content, ['trim']);

View File

@ -89,6 +89,19 @@ class Question extends Validator
return $value;
}
public function checkKeywords($keywords)
{
$keywords = $this->filter->sanitize($keywords, ['trim', 'string']);
$length = kg_strlen($keywords);
if ($length > 100) {
throw new BadRequestException('question.keyword_too_long');
}
return kg_parse_keywords($keywords);
}
public function checkContent($content)
{
$value = $this->filter->sanitize($content, ['trim']);

View File

@ -10,6 +10,7 @@ namespace App\Validators;
use App\Caches\MaxTopicId as MaxTopicIdCache;
use App\Caches\Topic as TopicCache;
use App\Exceptions\BadRequest as BadRequestException;
use App\Library\Validators\Common as CommonValidator;
use App\Models\Topic as TopicModel;
use App\Repos\Topic as TopicRepo;
@ -81,6 +82,17 @@ class Topic extends Validator
return $value;
}
public function checkCover($cover)
{
$value = $this->filter->sanitize($cover, ['trim', 'string']);
if (!CommonValidator::url($value)) {
throw new BadRequestException('topic.invalid_cover');
}
return kg_cos_img_style_trim($value);
}
public function checkSummary($summary)
{
$value = $this->filter->sanitize($summary, ['trim', 'string']);

View File

@ -120,6 +120,7 @@ $error['nav.has_child_node'] = '不允许相关操作(存在子节点)';
$error['article.not_found'] = '文章不存在';
$error['article.title_too_short'] = '标题太短少于2个字符';
$error['article.title_too_long'] = '标题太长多于50个字符';
$error['article.keyword_too_long'] = '关键字太长多于100个字符';
$error['article.content_too_short'] = '内容太短少于10个字符';
$error['article.content_too_long'] = '内容太长多于30000个字符';
$error['article.invalid_source_type'] = '无效的来源类型';
@ -138,6 +139,7 @@ $error['article.delete_not_allowed'] = '当前不允许删除文章';
$error['question.not_found'] = '问题不存在';
$error['question.title_too_short'] = '标题太短少于5个字符';
$error['question.title_too_long'] = '标题太长多于50个字符';
$error['question.keyword_too_long'] = '关键字太长多于100个字符';
$error['question.content_too_short'] = '内容太短少于10个字符';
$error['question.content_too_long'] = '内容太长多于30000个字符';
$error['question.invalid_publish_status'] = '无效的发布状态';
@ -172,7 +174,7 @@ $error['course.not_found'] = '课程不存在';
$error['course.title_too_short'] = '标题太短少于5个字符';
$error['course.title_too_long'] = '标题太长多于50个字符';
$error['course.summary_too_long'] = '标题太长多于255个字符';
$error['course.keywords_too_long'] = '关键字太长多于100个字符';
$error['course.keyword_too_long'] = '关键字太长多于100个字符';
$error['course.details_too_long'] = '详情太长多于5000个字符';
$error['course.invalid_model'] = '无效的模型类别';
$error['course.invalid_level'] = '无效的难度级别';
@ -203,6 +205,7 @@ $error['topic.not_found'] = '话题不存在';
$error['topic.title_too_short'] = '标题太短少于2个字符';
$error['topic.title_too_long'] = '标题太长多于50个字符';
$error['topic.summary_too_long'] = '简介太长多于255个字符';
$error['topic.invalid_cover'] = '无效的封面';
$error['topic.invalid_publish_status'] = '无效的发布状态';
/**
@ -328,6 +331,7 @@ $error['page.title_too_short'] = '标题太短少于2个字符';
$error['page.title_too_long'] = '标题太长多于50个字符';
$error['page.alias_too_short'] = '别名太短少于2个字符';
$error['page.alias_too_long'] = '别名太长多于50个字符';
$error['page.keyword_too_long'] = '关键字太长多于100个字符';
$error['page.content_too_short'] = '内容太短少于10个字符';
$error['page.content_too_long'] = '内容太长多于30000个字符';
$error['page.invalid_alias'] = '无效的别名(推荐使用英文作为别名)';
@ -339,6 +343,7 @@ $error['page.invalid_publish_status'] = '无效的发布状态';
$error['help.not_found'] = '帮助不存在';
$error['help.title_too_short'] = '标题太短少于2个字符';
$error['help.title_too_long'] = '标题太长多于50个字符';
$error['help.keyword_too_long'] = '关键字太长多于100个字符';
$error['help.content_too_short'] = '内容太短少于10个字符';
$error['help.content_too_long'] = '内容太长多于30000个字符';
$error['help.invalid_priority'] = '无效的排序数值范围1-255';

View File

@ -6,8 +6,9 @@
*/
use Phinx\Db\Adapter\MysqlAdapter;
use Phinx\Migration\AbstractMigration;
class V20220801025747 extends Phinx\Migration\AbstractMigration
final class V20220801025747 extends AbstractMigration
{
public function up()

View File

@ -0,0 +1,127 @@
<?php
/**
* @copyright Copyright (c) 2022 深圳市酷瓜软件有限公司
* @license https://opensource.org/licenses/GPL-2.0
* @link https://www.koogua.com
*/
use Phinx\Migration\AbstractMigration;
final class V20220915084746 extends AbstractMigration
{
public function up()
{
$this->alterArticleTable();
$this->alterQuestionTable();
$this->alterTopicTable();
$this->alterPageTable();
$this->alterHelpTable();
$this->handleTopics();
}
protected function alterArticleTable()
{
$table = $this->table('kg_article');
if ($table->hasColumn('keywords') == false) {
$table->addColumn('keywords', 'string', [
'null' => false,
'default' => '',
'limit' => 100,
'collation' => 'utf8mb4_general_ci',
'encoding' => 'utf8mb4',
'comment' => '关键字',
'after' => 'summary',
]);
}
$table->save();
}
protected function alterQuestionTable()
{
$table = $this->table('kg_question');
if ($table->hasColumn('keywords') == false) {
$table->addColumn('keywords', 'string', [
'null' => false,
'default' => '',
'limit' => 100,
'collation' => 'utf8mb4_general_ci',
'encoding' => 'utf8mb4',
'comment' => '关键字',
'after' => 'tags',
]);
}
$table->save();
}
protected function alterPageTable()
{
$table = $this->table('kg_page');
if ($table->hasColumn('keywords') == false) {
$table->addColumn('keywords', 'string', [
'null' => false,
'default' => '',
'limit' => 100,
'collation' => 'utf8mb4_general_ci',
'encoding' => 'utf8mb4',
'comment' => '关键字',
'after' => 'alias',
]);
}
$table->save();
}
protected function alterHelpTable()
{
$table = $this->table('kg_help');
if ($table->hasColumn('keywords') == false) {
$table->addColumn('keywords', 'string', [
'null' => false,
'default' => '',
'limit' => 100,
'collation' => 'utf8mb4_general_ci',
'encoding' => 'utf8mb4',
'comment' => '关键字',
'after' => 'title',
]);
}
$table->save();
}
protected function alterTopicTable()
{
$table = $this->table('kg_topic');
if ($table->hasColumn('cover') == false) {
$table->addColumn('cover', 'string', [
'null' => false,
'default' => '',
'limit' => 100,
'collation' => 'utf8mb4_general_ci',
'encoding' => 'utf8mb4',
'comment' => '封面',
'after' => 'title',
]);
}
$table->save();
}
protected function handleTopics()
{
$this->getQueryBuilder()
->update('kg_topic')
->set('cover', '/img/default/topic_cover.png')
->where(['cover' => ''])
->execute();
}
}