mirror of
https://gitee.com/koogua/course-tencent-cloud.git
synced 2025-06-17 15:55:31 +08:00
专栏阶段性提交2
This commit is contained in:
parent
d98b936969
commit
c5ef9a2b2d
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,6 +2,7 @@
|
||||
/vendor
|
||||
/config/config.php
|
||||
/config/xs.course.ini
|
||||
/config/xs.article.ini
|
||||
/config/xs.group.ini
|
||||
/config/xs.user.ini
|
||||
/config/alipay/*.crt
|
||||
|
78
app/Builders/ArticleFavoriteList.php
Normal file
78
app/Builders/ArticleFavoriteList.php
Normal file
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace App\Builders;
|
||||
|
||||
use App\Repos\Article as ArticleRepo;
|
||||
use App\Repos\User as UserRepo;
|
||||
|
||||
class ArticleFavoriteList extends Builder
|
||||
{
|
||||
|
||||
public function handleArticles(array $relations)
|
||||
{
|
||||
$articles = $this->getArticles($relations);
|
||||
|
||||
foreach ($relations as $key => $value) {
|
||||
$relations[$key]['article'] = $articles[$value['article_id']] ?? new \stdClass();
|
||||
}
|
||||
|
||||
return $relations;
|
||||
}
|
||||
|
||||
public function handleUsers(array $relations)
|
||||
{
|
||||
$users = $this->getUsers($relations);
|
||||
|
||||
foreach ($relations as $key => $value) {
|
||||
$relations[$key]['user'] = $users[$value['user_id']] ?? new \stdClass();
|
||||
}
|
||||
|
||||
return $relations;
|
||||
}
|
||||
|
||||
public function getArticles(array $relations)
|
||||
{
|
||||
$ids = kg_array_column($relations, 'article_id');
|
||||
|
||||
$articleRepo = new ArticleRepo();
|
||||
|
||||
$columns = [
|
||||
'id', 'title', 'cover',
|
||||
'view_count', 'like_count', 'comment_count', 'favorite_count',
|
||||
];
|
||||
|
||||
$articles = $articleRepo->findByIds($ids, $columns);
|
||||
|
||||
$baseUrl = kg_cos_url();
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($articles->toArray() as $article) {
|
||||
$article['cover'] = $baseUrl . $article['cover'];
|
||||
$result[$article['id']] = $article;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getUsers(array $relations)
|
||||
{
|
||||
$ids = kg_array_column($relations, 'user_id');
|
||||
|
||||
$userRepo = new UserRepo();
|
||||
|
||||
$users = $userRepo->findByIds($ids, ['id', 'name', 'avatar']);
|
||||
|
||||
$baseUrl = kg_cos_url();
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($users->toArray() as $user) {
|
||||
$user['avatar'] = $baseUrl . $user['avatar'];
|
||||
$result[$user['id']] = $user;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
29
app/Caches/MaxCommentId.php
Normal file
29
app/Caches/MaxCommentId.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Caches;
|
||||
|
||||
use App\Models\Comment as CommentModel;
|
||||
|
||||
class MaxCommentId extends Cache
|
||||
{
|
||||
|
||||
protected $lifetime = 365 * 86400;
|
||||
|
||||
public function getLifetime()
|
||||
{
|
||||
return $this->lifetime;
|
||||
}
|
||||
|
||||
public function getKey($id = null)
|
||||
{
|
||||
return 'max_comment_id';
|
||||
}
|
||||
|
||||
public function getContent($id = null)
|
||||
{
|
||||
$comment = CommentModel::findFirst(['order' => 'id DESC']);
|
||||
|
||||
return $comment->id ?? 0;
|
||||
}
|
||||
|
||||
}
|
125
app/Console/Tasks/ArticleIndexTask.php
Normal file
125
app/Console/Tasks/ArticleIndexTask.php
Normal file
@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Tasks;
|
||||
|
||||
use App\Models\Article as ArticleModel;
|
||||
use App\Services\Search\ArticleDocument;
|
||||
use App\Services\Search\ArticleSearcher;
|
||||
use Phalcon\Mvc\Model\Resultset;
|
||||
use Phalcon\Mvc\Model\ResultsetInterface;
|
||||
|
||||
class ArticleIndexTask extends Task
|
||||
{
|
||||
|
||||
/**
|
||||
* 搜索测试
|
||||
*
|
||||
* @command: php console.php article_index search {query}
|
||||
* @param array $params
|
||||
* @throws \XSException
|
||||
*/
|
||||
public function searchAction($params)
|
||||
{
|
||||
$query = $params[0] ?? null;
|
||||
|
||||
if (!$query) {
|
||||
exit('please special a query word' . PHP_EOL);
|
||||
}
|
||||
|
||||
$result = $this->searchArticles($query);
|
||||
|
||||
var_export($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空索引
|
||||
*
|
||||
* @command: php console.php article_index clean
|
||||
*/
|
||||
public function cleanAction()
|
||||
{
|
||||
$this->cleanArticleIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* 重建索引
|
||||
*
|
||||
* @command: php console.php article_index rebuild
|
||||
*/
|
||||
public function rebuildAction()
|
||||
{
|
||||
$this->rebuildArticleIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空索引
|
||||
*/
|
||||
protected function cleanArticleIndex()
|
||||
{
|
||||
$handler = new ArticleSearcher();
|
||||
|
||||
$index = $handler->getXS()->getIndex();
|
||||
|
||||
echo '------ start clean article index ------' . PHP_EOL;
|
||||
|
||||
$index->clean();
|
||||
|
||||
echo '------ end clean article index ------' . PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 重建索引
|
||||
*/
|
||||
protected function rebuildArticleIndex()
|
||||
{
|
||||
$articles = $this->findArticles();
|
||||
|
||||
if ($articles->count() == 0) return;
|
||||
|
||||
$handler = new ArticleSearcher();
|
||||
|
||||
$documenter = new ArticleDocument();
|
||||
|
||||
$index = $handler->getXS()->getIndex();
|
||||
|
||||
echo '------ start rebuild article index ------' . PHP_EOL;
|
||||
|
||||
$index->beginRebuild();
|
||||
|
||||
foreach ($articles as $article) {
|
||||
$document = $documenter->setDocument($article);
|
||||
$index->add($document);
|
||||
}
|
||||
|
||||
$index->endRebuild();
|
||||
|
||||
echo '------ end rebuild article index ------' . PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 搜索文章
|
||||
*
|
||||
* @param string $query
|
||||
* @return array
|
||||
* @throws \XSException
|
||||
*/
|
||||
protected function searchArticles($query)
|
||||
{
|
||||
$handler = new ArticleSearcher();
|
||||
|
||||
return $handler->search($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找文章
|
||||
*
|
||||
* @return ResultsetInterface|Resultset|ArticleModel[]
|
||||
*/
|
||||
protected function findArticles()
|
||||
{
|
||||
return ArticleModel::query()
|
||||
->where('published = 1')
|
||||
->execute();
|
||||
}
|
||||
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
namespace App\Console\Tasks;
|
||||
|
||||
use App\Library\Sitemap;
|
||||
use App\Models\Article as ArticleModel;
|
||||
use App\Models\Course as CourseModel;
|
||||
use App\Models\Help as HelpModel;
|
||||
use App\Models\ImGroup as ImGroupModel;
|
||||
@ -35,6 +36,7 @@ class SitemapTask extends Task
|
||||
|
||||
$this->addIndex();
|
||||
$this->addCourses();
|
||||
$this->addArticles();
|
||||
$this->addTeachers();
|
||||
$this->addTopics();
|
||||
$this->addImGroups();
|
||||
@ -74,6 +76,21 @@ class SitemapTask extends Task
|
||||
}
|
||||
}
|
||||
|
||||
protected function addArticles()
|
||||
{
|
||||
/**
|
||||
* @var Resultset|ArticleModel[] $articles
|
||||
*/
|
||||
$articles = ArticleModel::query()->where('published = 1')->execute();
|
||||
|
||||
if ($articles->count() == 0) return;
|
||||
|
||||
foreach ($articles as $article) {
|
||||
$loc = sprintf('%s/article/%s', $this->siteUrl, $article->id);
|
||||
$this->sitemap->addItem($loc, 0.8);
|
||||
}
|
||||
}
|
||||
|
||||
protected function addTeachers()
|
||||
{
|
||||
/**
|
||||
|
60
app/Console/Tasks/SyncArticleIndexTask.php
Normal file
60
app/Console/Tasks/SyncArticleIndexTask.php
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Tasks;
|
||||
|
||||
use App\Repos\Article as ArticleRepo;
|
||||
use App\Services\Search\ArticleDocument;
|
||||
use App\Services\Search\ArticleSearcher;
|
||||
use App\Services\Sync\ArticleIndex as ArticleIndexSync;
|
||||
|
||||
class SyncArticleIndexTask extends Task
|
||||
{
|
||||
|
||||
public function mainAction()
|
||||
{
|
||||
$redis = $this->getRedis();
|
||||
|
||||
$key = $this->getSyncKey();
|
||||
|
||||
$articleIds = $redis->sRandMember($key, 1000);
|
||||
|
||||
if (!$articleIds) return;
|
||||
|
||||
$articleRepo = new ArticleRepo();
|
||||
|
||||
$articles = $articleRepo->findByIds($articleIds);
|
||||
|
||||
if ($articles->count() == 0) return;
|
||||
|
||||
$document = new ArticleDocument();
|
||||
|
||||
$handler = new ArticleSearcher();
|
||||
|
||||
$index = $handler->getXS()->getIndex();
|
||||
|
||||
$index->openBuffer();
|
||||
|
||||
foreach ($articles as $article) {
|
||||
|
||||
$doc = $document->setDocument($article);
|
||||
|
||||
if ($article->published == 1) {
|
||||
$index->update($doc);
|
||||
} else {
|
||||
$index->del($article->id);
|
||||
}
|
||||
}
|
||||
|
||||
$index->closeBuffer();
|
||||
|
||||
$redis->sRem($key, ...$articleIds);
|
||||
}
|
||||
|
||||
protected function getSyncKey()
|
||||
{
|
||||
$sync = new ArticleIndexSync();
|
||||
|
||||
return $sync->getSyncKey();
|
||||
}
|
||||
|
||||
}
|
@ -74,7 +74,6 @@ class Category extends Service
|
||||
$data['type'] = $validator->checkType($post['type']);
|
||||
$data['name'] = $validator->checkName($post['name']);
|
||||
$data['priority'] = $validator->checkPriority($post['priority']);
|
||||
$data['published'] = $validator->checkPublishStatus($post['published']);
|
||||
|
||||
$category = new CategoryModel();
|
||||
|
||||
|
@ -64,7 +64,6 @@ class Help extends Service
|
||||
$data['title'] = $validator->checkTitle($post['title']);
|
||||
$data['content'] = $validator->checkContent($post['content']);
|
||||
$data['priority'] = $validator->checkPriority($post['priority']);
|
||||
$data['published'] = $validator->checkPublishStatus($post['published']);
|
||||
$data['category_id'] = $category->id;
|
||||
|
||||
$help = new HelpModel();
|
||||
|
@ -72,7 +72,6 @@ class Nav extends Service
|
||||
$data['url'] = $validator->checkUrl($post['url']);
|
||||
$data['target'] = $validator->checkTarget($post['target']);
|
||||
$data['position'] = $validator->checkPosition($post['position']);
|
||||
$data['published'] = $validator->checkPublishStatus($post['published']);
|
||||
|
||||
$nav = new NavModel();
|
||||
|
||||
|
@ -43,7 +43,6 @@ class Page extends Service
|
||||
|
||||
$data['title'] = $validator->checkTitle($post['title']);
|
||||
$data['content'] = $validator->checkContent($post['content']);
|
||||
$data['published'] = $validator->checkPublishStatus($post['published']);
|
||||
|
||||
$page = new PageModel();
|
||||
|
||||
|
@ -31,13 +31,6 @@
|
||||
<input class="layui-input" type="text" name="priority" value="10" lay-verify="number">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">发布</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="published" value="1" title="是" checked="checked">
|
||||
<input type="radio" name="published" value="0" title="否">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"></label>
|
||||
<div class="layui-input-block">
|
||||
|
@ -51,13 +51,6 @@
|
||||
<input type="radio" name="target" value="_self" title="原窗口">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">发布</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="published" value="1" title="是" checked="checked">
|
||||
<input type="radio" name="published" value="0" title="否">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"></label>
|
||||
<div class="layui-input-block">
|
||||
|
@ -29,7 +29,7 @@ class ArticleController extends Controller
|
||||
$sorts = $service->handleSorts();
|
||||
$params = $service->getParams();
|
||||
|
||||
$this->seo->prependTitle('文章');
|
||||
$this->seo->prependTitle('专栏');
|
||||
|
||||
$this->view->setVar('categories', $categories);
|
||||
$this->view->setVar('sorts', $sorts);
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Http\Home\Controllers;
|
||||
|
||||
use App\Services\Logic\Search\Article as ArticleSearchService;
|
||||
use App\Services\Logic\Search\Course as CourseSearchService;
|
||||
use App\Services\Logic\Search\Group as GroupSearchService;
|
||||
use App\Services\Logic\Search\User as UserSearchService;
|
||||
@ -41,11 +42,14 @@ class SearchController extends Controller
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
* @return CourseSearchService|GroupSearchService|UserSearchService
|
||||
* @return ArticleSearchService|CourseSearchService|GroupSearchService|UserSearchService
|
||||
*/
|
||||
protected function getSearchService($type)
|
||||
{
|
||||
switch ($type) {
|
||||
case 'article':
|
||||
$service = new ArticleSearchService();
|
||||
break;
|
||||
case 'group':
|
||||
$service = new GroupSearchService();
|
||||
break;
|
||||
|
@ -5,6 +5,7 @@ namespace App\Http\Home\Controllers;
|
||||
use App\Repos\WeChatSubscribe as WeChatSubscribeRepo;
|
||||
use App\Services\Logic\Account\OAuthProvider as OAuthProviderService;
|
||||
use App\Services\Logic\User\Console\AccountInfo as AccountInfoService;
|
||||
use App\Services\Logic\User\Console\ArticleList as ArticleListService;
|
||||
use App\Services\Logic\User\Console\ConnectDelete as ConnectDeleteService;
|
||||
use App\Services\Logic\User\Console\ConnectList as ConnectListService;
|
||||
use App\Services\Logic\User\Console\ConsultList as ConsultListService;
|
||||
@ -134,6 +135,19 @@ class UserConsoleController extends Controller
|
||||
$this->view->setVar('pager', $pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/articles", name="home.uc.articles")
|
||||
*/
|
||||
public function articlesAction()
|
||||
{
|
||||
$service = new ArticleListService();
|
||||
|
||||
$pager = $service->handle();
|
||||
|
||||
$this->view->pick('user/console/articles');
|
||||
$this->view->setVar('pager', $pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/favorites", name="home.uc.favorites")
|
||||
*/
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
namespace App\Http\Home\Controllers;
|
||||
|
||||
use App\Services\Logic\User\ArticleList as UserArticleListService;
|
||||
use App\Services\Logic\User\CourseList as UserCourseListService;
|
||||
use App\Services\Logic\User\FavoriteList as UserFavoriteListService;
|
||||
use App\Services\Logic\User\FriendList as UserFriendListService;
|
||||
use App\Services\Logic\User\GroupList as UserGroupListService;
|
||||
use App\Services\Logic\User\UserInfo as UserInfoService;
|
||||
@ -46,18 +46,18 @@ class UserController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/{id:[0-9]+}/favorites", name="home.user.favorites")
|
||||
* @Get("/{id:[0-9]+}/articles", name="home.user.articles")
|
||||
*/
|
||||
public function favoritesAction($id)
|
||||
public function articlesAction($id)
|
||||
{
|
||||
$service = new UserFavoriteListService();
|
||||
$service = new UserArticleListService();
|
||||
|
||||
$pager = $service->handle($id);
|
||||
|
||||
$pager->target = 'tab-favorites';
|
||||
$pager->target = 'tab-articles';
|
||||
|
||||
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
|
||||
$this->view->pick('user/favorites');
|
||||
$this->view->pick('user/articles');
|
||||
$this->view->setVar('pager', $pager);
|
||||
}
|
||||
|
||||
|
@ -97,6 +97,7 @@
|
||||
{% set course_title = item.course.title %}
|
||||
{% set course_url = url({'for':'home.course.show','id':item.course.id}) %}
|
||||
<div class="course-card">
|
||||
<span class="model layui-badge layui-bg-green">{{ model_info(item.course.model) }}</span>
|
||||
<div class="cover">
|
||||
<a href="{{ course_url }}" title="{{ course_title }}" target="_blank">
|
||||
<img src="{{ item.course.cover }}!cover_270" alt="{{ course_title }}">
|
||||
|
29
app/Http/Home/Views/search/article.volt
Normal file
29
app/Http/Home/Views/search/article.volt
Normal file
@ -0,0 +1,29 @@
|
||||
{% if pager.total_pages > 0 %}
|
||||
<div class="search-course-list">
|
||||
{% for item in pager.items %}
|
||||
{% set article_url = url({'for':'home.article.show','id':item.id}) %}
|
||||
{% set owner_url = url({'for':'home.user.show','id':item.owner.id}) %}
|
||||
<div class="search-course-card clearfix">
|
||||
<div class="cover">
|
||||
<a href="{{ article_url }}" target="_blank">
|
||||
<img src="{{ item.cover }}!cover_270" alt="{{ item.title }}">
|
||||
</a>
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="title layui-elip">
|
||||
<a href="{{ course_url }}" target="_blank">{{ item.title }}</a>
|
||||
</div>
|
||||
<div class="summary">{{ item.summary }}</div>
|
||||
<div class="meta">
|
||||
<span>作者:<a href="{{ owner_url }}" target="_blank">{{ item.owner.name }}</a></span>
|
||||
<span>浏览:{{ item.view_count }}</span>
|
||||
<span>点赞:{{ item.like_count }}</span>
|
||||
<span>评论:{{ item.comment_count }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
{{ partial('search/empty') }}
|
||||
{% endif %}
|
@ -5,17 +5,17 @@
|
||||
{% set teacher_url = url({'for':'home.teacher.show','id':item.teacher.id}) %}
|
||||
<div class="search-course-card clearfix">
|
||||
<div class="cover">
|
||||
<a href="{{ course_url }}">
|
||||
<a href="{{ course_url }}" target="_blank">
|
||||
<img src="{{ item.cover }}!cover_270" alt="{{ item.title }}">
|
||||
</a>
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="title layui-elip">
|
||||
<a href="{{ course_url }}">{{ item.title }}</a>
|
||||
<a href="{{ course_url }}" target="_blank">{{ item.title }}</a>
|
||||
</div>
|
||||
<div class="summary">{{ item.summary }}</div>
|
||||
<div class="meta">
|
||||
<span>讲师:<a href="{{ teacher_url }}">{{ item.teacher.name }}</a></span>
|
||||
<span>讲师:<a href="{{ teacher_url }}" target="_blank">{{ item.teacher.name }}</a></span>
|
||||
<span>难度:{{ level_info(item.level) }}</span>
|
||||
<span>课时:{{ item.lesson_count }}</span>
|
||||
<span>学员:{{ item.user_count }}</span>
|
||||
|
@ -6,17 +6,17 @@
|
||||
{% set item.about = item.about ? item.about : '这个家伙真懒,什么也没有留下!' %}
|
||||
<div class="search-group-card clearfix">
|
||||
<div class="avatar">
|
||||
<a href="{{ group_url }}">
|
||||
<a href="{{ group_url }}" target="_blank">
|
||||
<img src="{{ item.avatar }}!avatar_160" alt="{{ item.name }}">
|
||||
</a>
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="name layui-elip">
|
||||
<a href="{{ group_url }}">{{ item.name }}</a>
|
||||
<a href="{{ group_url }}" target="_blank">{{ item.name }}</a>
|
||||
</div>
|
||||
<div class="about layui-elip">{{ item.about }}</div>
|
||||
<div class="meta">
|
||||
<span>组长:<a href="{{ owner_url }}">{{ item.owner.name }}</a></span>
|
||||
<span>组长:<a href="{{ owner_url }}" target="_blank">{{ item.owner.name }}</a></span>
|
||||
<span>成员:{{ item.user_count }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
{{ partial('macros/course') }}
|
||||
|
||||
{% set types = {'course':'课程','group':'群组','user':'用户'} %}
|
||||
{% set types = {'course':'课程','article':'专栏','group':'群组','user':'用户'} %}
|
||||
{% set type = request.get('type','trim','course') %}
|
||||
{% set query = request.get('query','striptags','') %}
|
||||
|
||||
@ -31,6 +31,10 @@
|
||||
<div class="layui-tab-item layui-show">
|
||||
{{ partial('search/course') }}
|
||||
</div>
|
||||
{% elseif type == 'article' %}
|
||||
<div class="layui-tab-item layui-show">
|
||||
{{ partial('search/article') }}
|
||||
</div>
|
||||
{% elseif type == 'group' %}
|
||||
<div class="layui-tab-item layui-show">
|
||||
{{ partial('search/group') }}
|
||||
|
@ -7,13 +7,13 @@
|
||||
{% set item.about = item.about ? item.about : '这个家伙真懒,什么也没有留下!' %}
|
||||
<div class="search-group-card clearfix">
|
||||
<div class="avatar">
|
||||
<a href="{{ user_url }}">
|
||||
<a href="{{ user_url }}" target="_blank">
|
||||
<img src="{{ item.avatar }}!avatar_160" alt="{{ item.name }}">
|
||||
</a>
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="name layui-elip">
|
||||
<a href="{{ user_url }}">{{ item.name }}</a>
|
||||
<a href="{{ user_url }}" target="_blank">{{ item.name }}</a>
|
||||
</div>
|
||||
<div class="about layui-elip">{{ item.about }}</div>
|
||||
<div class="meta">
|
||||
|
32
app/Http/Home/Views/user/articles.volt
Normal file
32
app/Http/Home/Views/user/articles.volt
Normal file
@ -0,0 +1,32 @@
|
||||
{{ partial('macros/article') }}
|
||||
|
||||
{% if pager.total_pages > 0 %}
|
||||
<div class="article-list clearfix">
|
||||
<div class="layui-row layui-col-space20">
|
||||
{% for item in pager.items %}
|
||||
{% set article_url = url({'for':'home.article.show','id':item.id}) %}
|
||||
<div class="layui-col-md3">
|
||||
<div class="course-card">
|
||||
<span class="type layui-badge layui-bg-green">{{ source_type(item.source_type) }}</span>
|
||||
<div class="cover">
|
||||
<a href="{{ article_url }}" target="_blank">
|
||||
<img src="{{ item.cover }}!cover_270" alt="{{ item.title }}" title="{{ item.title }}">
|
||||
</a>
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="title layui-elip">
|
||||
<a href="{{ article_url }}" title="{{ item.title }}" target="_blank">{{ item.title }}</a>
|
||||
</div>
|
||||
<div class="meta">
|
||||
<span class="view">{{ item.view_count }} 浏览</span>
|
||||
<span class="like">{{ item.like_count }} 点赞</span>
|
||||
<span class="comment">{{ item.comment_count }} 评论</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{{ partial('partials/pager_ajax') }}
|
||||
{% endif %}
|
64
app/Http/Home/Views/user/console/articles.volt
Normal file
64
app/Http/Home/Views/user/console/articles.volt
Normal file
@ -0,0 +1,64 @@
|
||||
{% extends 'templates/main.volt' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{{ partial('macros/article') }}
|
||||
|
||||
<div class="layout-main clearfix">
|
||||
<div class="my-sidebar">{{ partial('user/console/menu') }}</div>
|
||||
<div class="my-content">
|
||||
<div class="wrap">
|
||||
<div class="my-nav">
|
||||
<span class="title">我的文章</span>
|
||||
</div>
|
||||
{% if pager.total_pages > 0 %}
|
||||
<table class="layui-table">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>文章</th>
|
||||
<th>浏览</th>
|
||||
<th>点赞</th>
|
||||
<th>评论</th>
|
||||
<th>收藏</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in pager.items %}
|
||||
{% set article_url = url({'for':'home.article.show','id':item.id}) %}
|
||||
<tr>
|
||||
<td>
|
||||
<p>标题:<a href="{{ article_url }}" target="_blank">{{ item.title }}</a></p>
|
||||
<p class="meta">
|
||||
来源:<span class="layui-badge layui-bg-gray">{{ source_type(item.source_type) }}</span>
|
||||
分类:<span class="layui-badge layui-bg-gray">{{ item.category.name }}</span>
|
||||
时间:{{ item.create_time|time_ago }}
|
||||
</p>
|
||||
</td>
|
||||
<td>{{ item.view_count }}</td>
|
||||
<td>{{ item.like_count }}</td>
|
||||
<td>{{ item.comment_count }}</td>
|
||||
<td>{{ item.favorite_count }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{{ partial('partials/pager') }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block include_js %}
|
||||
|
||||
{{ js_include('home/js/user.console.js') }}
|
||||
|
||||
{% endblock %}
|
@ -4,48 +4,25 @@
|
||||
|
||||
{{ partial('macros/course') }}
|
||||
|
||||
{% set types = {'course':'课程','article':'文章'} %}
|
||||
{% set type = request.get('type','trim','course') %}
|
||||
|
||||
<div class="layout-main clearfix">
|
||||
<div class="my-sidebar">{{ partial('user/console/menu') }}</div>
|
||||
<div class="my-content">
|
||||
<div class="wrap">
|
||||
<div class="my-nav">
|
||||
<span class="title">我的收藏</span>
|
||||
{% for key,value in types %}
|
||||
{% set class = (type == key) ? 'layui-btn layui-btn-xs' : 'none' %}
|
||||
{% set url = url({'for':'home.uc.favorites'},{'type':key}) %}
|
||||
<a class="{{ class }}" href="{{ url }}">{{ value }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% if pager.total_pages > 0 %}
|
||||
<table class="layui-table" lay-size="lg">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col width="12%">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>课程</th>
|
||||
<th>学员</th>
|
||||
<th>评分</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in pager.items %}
|
||||
{% set course_url = url({'for':'home.course.show','id':item.id}) %}
|
||||
{% set favorite_url = url({'for':'home.course.favorite','id':item.id}) %}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{{ course_url }}" target="_blank">{{ item.title }}</a>
|
||||
<span class="layui-badge layui-bg-gray">{{ model_info(item.model) }}</span>
|
||||
</td>
|
||||
<td>{{ item.user_count }}</td>
|
||||
<td>{{ "%0.1f"|format(item.rating) }}</td>
|
||||
<td class="center">
|
||||
<button class="layui-btn layui-btn-sm kg-delete" data-tips="确定要取消收藏吗?" data-url="{{ favorite_url }}">取消</button>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{{ partial('partials/pager') }}
|
||||
{% if type == 'course' %}
|
||||
{{ partial('user/console/favorites_course') }}
|
||||
{% elseif type == 'article' %}
|
||||
{{ partial('user/console/favorites_article') }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
36
app/Http/Home/Views/user/console/favorites_article.volt
Normal file
36
app/Http/Home/Views/user/console/favorites_article.volt
Normal file
@ -0,0 +1,36 @@
|
||||
{% if pager.total_pages > 0 %}
|
||||
<table class="layui-table" lay-size="lg">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col width="12%">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>文章</th>
|
||||
<th>浏览</th>
|
||||
<th>点赞</th>
|
||||
<th>评论</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in pager.items %}
|
||||
{% set article_url = url({'for':'home.article.show','id':item.id}) %}
|
||||
{% set favorite_url = url({'for':'home.article.favorite','id':item.id}) %}
|
||||
<tr>
|
||||
<td><a href="{{ article_url }}" target="_blank">{{ item.title }}</a></td>
|
||||
<td>{{ item.view_count }}</td>
|
||||
<td>{{ item.like_count }}</td>
|
||||
<td>{{ item.comment_count }}</td>
|
||||
<td class="center">
|
||||
<button class="layui-btn layui-btn-sm kg-delete" data-tips="确定要取消收藏吗?" data-url="{{ favorite_url }}">取消</button>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{{ partial('partials/pager') }}
|
||||
{% endif %}
|
36
app/Http/Home/Views/user/console/favorites_course.volt
Normal file
36
app/Http/Home/Views/user/console/favorites_course.volt
Normal file
@ -0,0 +1,36 @@
|
||||
{% if pager.total_pages > 0 %}
|
||||
<table class="layui-table" lay-size="lg">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col width="12%">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>课程</th>
|
||||
<th>学员</th>
|
||||
<th>评分</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in pager.items %}
|
||||
{% set course_url = url({'for':'home.course.show','id':item.id}) %}
|
||||
{% set favorite_url = url({'for':'home.course.favorite','id':item.id}) %}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{{ course_url }}" target="_blank">{{ item.title }}</a>
|
||||
<span class="layui-badge layui-bg-gray">{{ model_info(item.model) }}</span>
|
||||
</td>
|
||||
<td>{{ item.user_count }}</td>
|
||||
<td>{{ "%0.1f"|format(item.rating) }}</td>
|
||||
<td class="center">
|
||||
<button class="layui-btn layui-btn-sm kg-delete" data-tips="确定要取消收藏吗?" data-url="{{ favorite_url }}">取消</button>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{{ partial('partials/pager') }}
|
||||
{% endif %}
|
@ -18,10 +18,11 @@
|
||||
</div>
|
||||
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header">课程中心</div>
|
||||
<div class="layui-card-header">内容中心</div>
|
||||
<div class="layui-card-body">
|
||||
<ul class="my-menu">
|
||||
<li><a href="{{ url({'for':'home.uc.courses'}) }}">我的课程</a></li>
|
||||
<li><a href="{{ url({'for':'home.uc.articles'}) }}">我的文章</a></li>
|
||||
<li><a href="{{ url({'for':'home.uc.favorites'}) }}">我的收藏</a></li>
|
||||
<li><a href="{{ url({'for':'home.uc.reviews'}) }}">我的评价</a></li>
|
||||
<li><a href="{{ url({'for':'home.uc.consults'}) }}">我的咨询</a></li>
|
||||
|
@ -1,7 +1,7 @@
|
||||
{{ partial('macros/course') }}
|
||||
|
||||
{% if pager.total_pages > 0 %}
|
||||
<div class="course-list learning-course-list clearfix">
|
||||
<div class="course-list clearfix">
|
||||
<div class="layui-row layui-col-space20">
|
||||
{% for item in pager.items %}
|
||||
<div class="layui-col-md3">
|
||||
|
@ -1,14 +0,0 @@
|
||||
{{ partial('macros/course') }}
|
||||
|
||||
{% if pager.total_pages > 0 %}
|
||||
<div class="course-list clearfix">
|
||||
<div class="layui-row layui-col-space20">
|
||||
{% for item in pager.items %}
|
||||
<div class="layui-col-md3">
|
||||
{{ course_card(item) }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{{ partial('partials/pager_ajax') }}
|
||||
{% endif %}
|
@ -38,12 +38,12 @@
|
||||
</div>
|
||||
|
||||
{% set show_tab_courses = user.course_count > 0 %}
|
||||
{% set show_tab_favorites = user.favorite_count > 0 %}
|
||||
{% set show_tab_articles = user.article_count > 0 %}
|
||||
{% set show_tab_friends = user.friend_count > 0 %}
|
||||
{% set show_tab_groups = user.group_count > 0 %}
|
||||
|
||||
{% set courses_url = url({'for':'home.user.courses','id':user.id}) %}
|
||||
{% set favorites_url = url({'for':'home.user.favorites','id':user.id}) %}
|
||||
{% set articles_url = url({'for':'home.user.articles','id':user.id}) %}
|
||||
{% set friends_url = url({'for':'home.user.friends','id':user.id}) %}
|
||||
{% set groups_url = url({'for':'home.user.groups','id':user.id}) %}
|
||||
|
||||
@ -53,8 +53,8 @@
|
||||
{% if show_tab_courses %}
|
||||
<li class="layui-this">课程<span class="tab-count">{{ user.course_count }}</span></li>
|
||||
{% endif %}
|
||||
{% if show_tab_favorites %}
|
||||
<li>收藏<span class="tab-count">{{ user.favorite_count }}</span></li>
|
||||
{% if show_tab_articles %}
|
||||
<li>文章<span class="tab-count">{{ user.article_count }}</span></li>
|
||||
{% endif %}
|
||||
{% if show_tab_friends %}
|
||||
<li>好友<span class="tab-count">{{ user.friend_count }}</span></li>
|
||||
@ -67,8 +67,8 @@
|
||||
{% if show_tab_courses %}
|
||||
<div class="layui-tab-item layui-show" id="tab-courses" data-url="{{ courses_url }}"></div>
|
||||
{% endif %}
|
||||
{% if show_tab_favorites %}
|
||||
<div class="layui-tab-item" id="tab-favorites" data-url="{{ favorites_url }}"></div>
|
||||
{% if show_tab_articles %}
|
||||
<div class="layui-tab-item" id="tab-articles" data-url="{{ articles_url }}"></div>
|
||||
{% endif %}
|
||||
{% if show_tab_friends %}
|
||||
<div class="layui-tab-item" id="tab-friends" data-url="{{ friends_url }}"></div>
|
||||
|
@ -209,6 +209,10 @@ class Article extends Model
|
||||
$this->cover = self::getCoverPath($this->cover);
|
||||
}
|
||||
|
||||
if (empty($this->summary)) {
|
||||
$this->summary = kg_parse_summary($this->content);
|
||||
}
|
||||
|
||||
if (is_array($this->tags)) {
|
||||
$this->tags = kg_json_encode($this->tags);
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ class Category extends Model
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $published = 0;
|
||||
public $published = 1;
|
||||
|
||||
/**
|
||||
* 删除标识
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Caches\MaxCommentId as MaxCommentIdCache;
|
||||
use Phalcon\Mvc\Model\Behavior\SoftDelete;
|
||||
|
||||
class Comment extends Model
|
||||
@ -19,105 +20,105 @@ class Comment extends Model
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $id;
|
||||
public $id = 0;
|
||||
|
||||
/**
|
||||
* 内容
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $content;
|
||||
public $content = '';
|
||||
|
||||
/**
|
||||
* 父级编号
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $parent_id;
|
||||
public $parent_id = 0;
|
||||
|
||||
/**
|
||||
* 作者编号
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $owner_id;
|
||||
public $owner_id = 0;
|
||||
|
||||
/**
|
||||
* 目标用户
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $to_user_id;
|
||||
public $to_user_id = 0;
|
||||
|
||||
/**
|
||||
* 条目编号
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $item_id;
|
||||
public $item_id = 0;
|
||||
|
||||
/**
|
||||
* 条目类型
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $item_type;
|
||||
public $item_type = 0;
|
||||
|
||||
/**
|
||||
* 终端类型
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $client_type;
|
||||
public $client_type = 0;
|
||||
|
||||
/**
|
||||
* 终端IP
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $client_ip;
|
||||
public $client_ip = '';
|
||||
|
||||
/**
|
||||
* 发布标识
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $published;
|
||||
public $published = 1;
|
||||
|
||||
/**
|
||||
* 删除标识
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $deleted;
|
||||
public $deleted = 0;
|
||||
|
||||
/**
|
||||
* 回复数
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $reply_count;
|
||||
public $reply_count = 0;
|
||||
|
||||
/**
|
||||
* 点赞数
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $like_count;
|
||||
public $like_count = 0;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $create_time;
|
||||
public $create_time = 0;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $update_time;
|
||||
public $update_time = 0;
|
||||
|
||||
public function getSource(): string
|
||||
{
|
||||
@ -146,6 +147,13 @@ class Comment extends Model
|
||||
$this->update_time = time();
|
||||
}
|
||||
|
||||
public function afterCreate()
|
||||
{
|
||||
$cache = new MaxCommentIdCache();
|
||||
|
||||
$cache->rebuild();
|
||||
}
|
||||
|
||||
public static function itemTypes()
|
||||
{
|
||||
return [
|
||||
|
@ -338,6 +338,10 @@ class Course extends Model
|
||||
$this->cover = self::getCoverPath($this->cover);
|
||||
}
|
||||
|
||||
if (empty($this->summary)) {
|
||||
$this->summary = kg_parse_summary($this->details);
|
||||
}
|
||||
|
||||
if (is_array($this->attrs)) {
|
||||
$this->attrs = kg_json_encode($this->attrs);
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ class Help extends Model
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $published = 0;
|
||||
public $published = 1;
|
||||
|
||||
/**
|
||||
* 删除标识
|
||||
|
@ -71,7 +71,7 @@ class ImGroup extends Model
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $published = 0;
|
||||
public $published = 1;
|
||||
|
||||
/**
|
||||
* 删除状态
|
||||
|
@ -87,7 +87,7 @@ class Nav extends Model
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $published = 0;
|
||||
public $published = 1;
|
||||
|
||||
/**
|
||||
* 删除标识
|
||||
|
@ -34,7 +34,7 @@ class Page extends Model
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $published = 0;
|
||||
public $published = 1;
|
||||
|
||||
/**
|
||||
* 删除标识
|
||||
|
@ -82,7 +82,7 @@ class Review extends Model
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $published = 0;
|
||||
public $published = 1;
|
||||
|
||||
/**
|
||||
* 删除标识
|
||||
|
@ -63,6 +63,10 @@ class Article extends Repository
|
||||
$builder->andWhere('deleted = :deleted:', ['deleted' => $where['deleted']]);
|
||||
}
|
||||
|
||||
if ($sort == 'featured') {
|
||||
$builder->andWhere('featured = 1');
|
||||
}
|
||||
|
||||
switch ($sort) {
|
||||
case 'like':
|
||||
$orderBy = 'like_count DESC';
|
||||
@ -70,6 +74,9 @@ class Article extends Repository
|
||||
case 'popular':
|
||||
$orderBy = 'view_count DESC';
|
||||
break;
|
||||
case 'comment':
|
||||
$orderBy = 'comment_count DESC';
|
||||
break;
|
||||
default:
|
||||
$orderBy = 'id DESC';
|
||||
break;
|
||||
|
@ -2,12 +2,46 @@
|
||||
|
||||
namespace App\Repos;
|
||||
|
||||
use App\Library\Paginator\Adapter\QueryBuilder as PagerQueryBuilder;
|
||||
use App\Models\ArticleFavorite as ArticleFavoriteModel;
|
||||
use Phalcon\Mvc\Model;
|
||||
|
||||
class ArticleFavorite extends Repository
|
||||
{
|
||||
|
||||
public function paginate($where = [], $sort = 'latest', $page = 1, $limit = 15)
|
||||
{
|
||||
$builder = $this->modelsManager->createBuilder();
|
||||
|
||||
$builder->from(ArticleFavoriteModel::class);
|
||||
|
||||
$builder->where('1 = 1');
|
||||
|
||||
if (!empty($where['article_id'])) {
|
||||
$builder->andWhere('article_id = :article_id:', ['article_id' => $where['article_id']]);
|
||||
}
|
||||
|
||||
if (!empty($where['user_id'])) {
|
||||
$builder->andWhere('user_id = :user_id:', ['user_id' => $where['user_id']]);
|
||||
}
|
||||
|
||||
switch ($sort) {
|
||||
default:
|
||||
$orderBy = 'id DESC';
|
||||
break;
|
||||
}
|
||||
|
||||
$builder->orderBy($orderBy);
|
||||
|
||||
$pager = new PagerQueryBuilder([
|
||||
'builder' => $builder,
|
||||
'page' => $page,
|
||||
'limit' => $limit,
|
||||
]);
|
||||
|
||||
return $pager->paginate();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $articleId
|
||||
* @param int $userId
|
||||
|
@ -4,6 +4,7 @@ namespace App\Repos;
|
||||
|
||||
use App\Library\Paginator\Adapter\QueryBuilder as PagerQueryBuilder;
|
||||
use App\Models\Article as ArticleModel;
|
||||
use App\Models\ArticleFavorite as ArticleFavoriteModel;
|
||||
use App\Models\CourseFavorite as CourseFavoriteModel;
|
||||
use App\Models\CourseUser as CourseUserModel;
|
||||
use App\Models\ImUser as ImUserModel;
|
||||
@ -169,8 +170,8 @@ class User extends Repository
|
||||
public function countArticles($userId)
|
||||
{
|
||||
return (int)ArticleModel::count([
|
||||
'conditions' => 'user_id = :user_id: AND published = 1',
|
||||
'bind' => ['user_id' => $userId],
|
||||
'conditions' => 'owner_id = :owner_id: AND published = 1',
|
||||
'bind' => ['owner_id' => $userId],
|
||||
]);
|
||||
}
|
||||
|
||||
@ -182,4 +183,12 @@ class User extends Repository
|
||||
]);
|
||||
}
|
||||
|
||||
public function countArticleFavorites($userId)
|
||||
{
|
||||
return (int)ArticleFavoriteModel::count([
|
||||
'conditions' => 'user_id = :user_id:',
|
||||
'bind' => ['user_id' => $userId],
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -54,7 +54,6 @@ class ArticleInfo extends LogicService
|
||||
'like_count' => $article->like_count,
|
||||
'comment_count' => $article->comment_count,
|
||||
'favorite_count' => $article->favorite_count,
|
||||
'allow_comment' => $article->allow_comment,
|
||||
'create_time' => $article->create_time,
|
||||
'update_time' => $article->update_time,
|
||||
];
|
||||
@ -67,6 +66,8 @@ class ArticleInfo extends LogicService
|
||||
'favorited' => 0,
|
||||
];
|
||||
|
||||
$me['allow_comment'] = $article->allow_comment ? 1 : 0;
|
||||
|
||||
if ($user->id > 0) {
|
||||
|
||||
$likeRepo = new ArticleLikeRepo();
|
||||
|
@ -32,7 +32,7 @@ class ArticleList extends LogicService
|
||||
return $this->handleArticles($pager);
|
||||
}
|
||||
|
||||
protected function handleArticles($pager)
|
||||
public function handleArticles($pager)
|
||||
{
|
||||
if ($pager->total_items == 0) {
|
||||
return $pager;
|
||||
@ -69,6 +69,8 @@ class ArticleList extends LogicService
|
||||
'title' => $article['title'],
|
||||
'cover' => $article['cover'],
|
||||
'summary' => $article['summary'],
|
||||
'source_type' => $article['source_type'],
|
||||
'source_url' => $article['source_url'],
|
||||
'tags' => $article['tags'],
|
||||
'category' => $category,
|
||||
'owner' => $owner,
|
||||
|
84
app/Services/Logic/Search/Article.php
Normal file
84
app/Services/Logic/Search/Article.php
Normal file
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Logic\Search;
|
||||
|
||||
use App\Library\Paginator\Adapter\XunSearch as XunSearchPaginator;
|
||||
use App\Library\Paginator\Query as PagerQuery;
|
||||
use App\Services\Search\ArticleSearcher as ArticleSearcherService;
|
||||
|
||||
class Article extends Handler
|
||||
{
|
||||
|
||||
public function search()
|
||||
{
|
||||
$pagerQuery = new PagerQuery();
|
||||
|
||||
$params = $pagerQuery->getParams();
|
||||
$page = $pagerQuery->getPage();
|
||||
$limit = $pagerQuery->getLimit();
|
||||
|
||||
$searcher = new ArticleSearcherService();
|
||||
|
||||
$paginator = new XunSearchPaginator([
|
||||
'xs' => $searcher->getXS(),
|
||||
'highlight' => $searcher->getHighlightFields(),
|
||||
'query' => $params['query'],
|
||||
'page' => $page,
|
||||
'limit' => $limit,
|
||||
]);
|
||||
|
||||
$pager = $paginator->getPaginate();
|
||||
|
||||
return $this->handleArticles($pager);
|
||||
}
|
||||
|
||||
public function getHotQuery($limit = 10, $type = 'total')
|
||||
{
|
||||
$searcher = new ArticleSearcherService();
|
||||
|
||||
return $searcher->getHotQuery($limit, $type);
|
||||
}
|
||||
|
||||
public function getRelatedQuery($query, $limit = 10)
|
||||
{
|
||||
$searcher = new ArticleSearcherService();
|
||||
|
||||
return $searcher->getRelatedQuery($query, $limit);
|
||||
}
|
||||
|
||||
protected function handleArticles($pager)
|
||||
{
|
||||
if ($pager->total_items == 0) {
|
||||
return $pager;
|
||||
}
|
||||
|
||||
$items = [];
|
||||
|
||||
$baseUrl = kg_cos_url();
|
||||
|
||||
foreach ($pager->items as $item) {
|
||||
|
||||
$item['cover'] = $baseUrl . $item['cover'];
|
||||
|
||||
$items[] = [
|
||||
'id' => (int)$item['id'],
|
||||
'title' => (string)$item['title'],
|
||||
'cover' => (string)$item['cover'],
|
||||
'summary' => (string)$item['summary'],
|
||||
'create_time' => (int)$item['create_time'],
|
||||
'view_count' => (int)$item['view_count'],
|
||||
'like_count' => (int)$item['like_count'],
|
||||
'favorite_count' => (int)$item['favorite_count'],
|
||||
'comment_count' => (int)$item['comment_count'],
|
||||
'tags' => json_decode($item['tags'], true),
|
||||
'owner' => json_decode($item['owner'], true),
|
||||
'category' => json_decode($item['category'], true),
|
||||
];
|
||||
}
|
||||
|
||||
$pager->items = $items;
|
||||
|
||||
return $pager;
|
||||
}
|
||||
|
||||
}
|
45
app/Services/Logic/User/ArticleList.php
Normal file
45
app/Services/Logic/User/ArticleList.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Logic\User;
|
||||
|
||||
use App\Library\Paginator\Query as PagerQuery;
|
||||
use App\Repos\Article as ArticleRepo;
|
||||
use App\Services\Logic\Article\ArticleList as ArticleListService;
|
||||
use App\Services\Logic\Service as LogicService;
|
||||
use App\Services\Logic\UserTrait;
|
||||
|
||||
class ArticleList extends LogicService
|
||||
{
|
||||
|
||||
use UserTrait;
|
||||
|
||||
public function handle($id)
|
||||
{
|
||||
$user = $this->checkUser($id);
|
||||
|
||||
$pagerQuery = new PagerQuery();
|
||||
|
||||
$params = $pagerQuery->getParams();
|
||||
|
||||
$params['owner_id'] = $user->id;
|
||||
$params['published'] = 1;
|
||||
|
||||
$sort = $pagerQuery->getSort();
|
||||
$page = $pagerQuery->getPage();
|
||||
$limit = $pagerQuery->getLimit();
|
||||
|
||||
$articleRepo = new ArticleRepo();
|
||||
|
||||
$pager = $articleRepo->paginate($params, $sort, $page, $limit);
|
||||
|
||||
return $this->handleArticles($pager);
|
||||
}
|
||||
|
||||
protected function handleArticles($pager)
|
||||
{
|
||||
$service = new ArticleListService();
|
||||
|
||||
return $service->handleArticles($pager);
|
||||
}
|
||||
|
||||
}
|
20
app/Services/Logic/User/Console/ArticleList.php
Normal file
20
app/Services/Logic/User/Console/ArticleList.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Logic\User\Console;
|
||||
|
||||
use App\Services\Logic\Service as LogicService;
|
||||
use App\Services\Logic\User\ArticleList as UserArticleListService;
|
||||
|
||||
class ArticleList extends LogicService
|
||||
{
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$user = $this->getLoginUser();
|
||||
|
||||
$service = new UserArticleListService();
|
||||
|
||||
return $service->handle($user->id);
|
||||
}
|
||||
|
||||
}
|
@ -63,7 +63,6 @@ class ConsultList extends Service
|
||||
'update_time' => $consult['update_time'],
|
||||
'course' => $course,
|
||||
'chapter' => $chapter,
|
||||
'show' => false,
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -2,19 +2,96 @@
|
||||
|
||||
namespace App\Services\Logic\User\Console;
|
||||
|
||||
use App\Services\Logic\Service;
|
||||
use App\Services\Logic\User\FavoriteList as UserFavoriteListService;
|
||||
use App\Builders\ArticleFavoriteList as ArticleFavoriteListBuilder;
|
||||
use App\Builders\CourseFavoriteList as CourseFavoriteListBuilder;
|
||||
use App\Library\Paginator\Query as PagerQuery;
|
||||
use App\Repos\ArticleFavorite as ArticleFavoriteRepo;
|
||||
use App\Repos\CourseFavorite as CourseFavoriteRepo;
|
||||
use App\Services\Logic\Service as LogicService;
|
||||
|
||||
class FavoriteList extends Service
|
||||
class FavoriteList extends LogicService
|
||||
{
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$user = $this->getLoginUser();
|
||||
|
||||
$service = new UserFavoriteListService();
|
||||
$pagerQuery = new PagerQuery();
|
||||
|
||||
return $service->handle($user->id);
|
||||
$params = $pagerQuery->getParams();
|
||||
|
||||
$type = $params['type'] ?? 'course';
|
||||
|
||||
$params['user_id'] = $user->id;
|
||||
|
||||
$sort = $pagerQuery->getSort();
|
||||
$page = $pagerQuery->getPage();
|
||||
$limit = $pagerQuery->getLimit();
|
||||
|
||||
if ($type == 'course') {
|
||||
|
||||
$favoriteRepo = new CourseFavoriteRepo();
|
||||
|
||||
$pager = $favoriteRepo->paginate($params, $sort, $page, $limit);
|
||||
|
||||
return $this->handleCourses($pager);
|
||||
|
||||
} elseif ($type == 'article') {
|
||||
|
||||
$favoriteRepo = new ArticleFavoriteRepo();
|
||||
|
||||
$pager = $favoriteRepo->paginate($params, $sort, $page, $limit);
|
||||
|
||||
return $this->handleArticles($pager);
|
||||
}
|
||||
}
|
||||
|
||||
protected function handleCourses($pager)
|
||||
{
|
||||
if ($pager->total_items == 0) {
|
||||
return $pager;
|
||||
}
|
||||
|
||||
$builder = new CourseFavoriteListBuilder();
|
||||
|
||||
$relations = $pager->items->toArray();
|
||||
|
||||
$courses = $builder->getCourses($relations);
|
||||
|
||||
$items = [];
|
||||
|
||||
foreach ($relations as $relation) {
|
||||
$course = $courses[$relation['course_id']] ?? new \stdClass();
|
||||
$items[] = $course;
|
||||
}
|
||||
|
||||
$pager->items = $items;
|
||||
|
||||
return $pager;
|
||||
}
|
||||
|
||||
protected function handleArticles($pager)
|
||||
{
|
||||
if ($pager->total_items == 0) {
|
||||
return $pager;
|
||||
}
|
||||
|
||||
$builder = new ArticleFavoriteListBuilder();
|
||||
|
||||
$relations = $pager->items->toArray();
|
||||
|
||||
$articles = $builder->getArticles($relations);
|
||||
|
||||
$items = [];
|
||||
|
||||
foreach ($relations as $relation) {
|
||||
$article = $articles[$relation['article_id']] ?? new \stdClass();
|
||||
$items[] = $article;
|
||||
}
|
||||
|
||||
$pager->items = $items;
|
||||
|
||||
return $pager;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,62 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Logic\User;
|
||||
|
||||
use App\Builders\CourseFavoriteList as CourseFavoriteListBuilder;
|
||||
use App\Library\Paginator\Query as PagerQuery;
|
||||
use App\Repos\CourseFavorite as CourseFavoriteRepo;
|
||||
use App\Services\Logic\Service;
|
||||
use App\Services\Logic\UserTrait;
|
||||
|
||||
class FavoriteList extends Service
|
||||
{
|
||||
|
||||
use UserTrait;
|
||||
|
||||
public function handle($id)
|
||||
{
|
||||
$user = $this->checkUser($id);
|
||||
|
||||
$pagerQuery = new PagerQuery();
|
||||
|
||||
$params = $pagerQuery->getParams();
|
||||
|
||||
$params['user_id'] = $user->id;
|
||||
$params['deleted'] = 0;
|
||||
|
||||
$sort = $pagerQuery->getSort();
|
||||
$page = $pagerQuery->getPage();
|
||||
$limit = $pagerQuery->getLimit();
|
||||
|
||||
$favoriteRepo = new CourseFavoriteRepo();
|
||||
|
||||
$pager = $favoriteRepo->paginate($params, $sort, $page, $limit);
|
||||
|
||||
return $this->handleCourses($pager);
|
||||
}
|
||||
|
||||
protected function handleCourses($pager)
|
||||
{
|
||||
if ($pager->total_items == 0) {
|
||||
return $pager;
|
||||
}
|
||||
|
||||
$builder = new CourseFavoriteListBuilder();
|
||||
|
||||
$relations = $pager->items->toArray();
|
||||
|
||||
$courses = $builder->getCourses($relations);
|
||||
|
||||
$items = [];
|
||||
|
||||
foreach ($relations as $relation) {
|
||||
$course = $courses[$relation['course_id']] ?? new \stdClass();
|
||||
$items[] = $course;
|
||||
}
|
||||
|
||||
$pager->items = $items;
|
||||
|
||||
return $pager;
|
||||
}
|
||||
|
||||
}
|
@ -36,7 +36,7 @@ class UserInfo extends Service
|
||||
'vip' => $user->vip,
|
||||
'locked' => $user->locked,
|
||||
'course_count' => $user->course_count,
|
||||
'favorite_count' => $user->favorite_count,
|
||||
'article_count' => $user->article_count,
|
||||
'friend_count' => $imUser->friend_count,
|
||||
'group_count' => $imUser->group_count,
|
||||
'active_time' => $user->active_time,
|
||||
|
@ -61,13 +61,18 @@ class ArticleDocument extends Component
|
||||
|
||||
$article->cover = ArticleModel::getCoverPath($article->cover);
|
||||
|
||||
if (empty($article->summary)) {
|
||||
$article->summary = kg_parse_summary($article->content);
|
||||
}
|
||||
|
||||
return [
|
||||
'id' => $article->id,
|
||||
'title' => $article->title,
|
||||
'cover' => $article->cover,
|
||||
'summary' => $article->summary,
|
||||
'category_id' => $article->category_id,
|
||||
'owner_id' => $article->teacher_id,
|
||||
'owner_id' => $article->owner_id,
|
||||
'create_time' => $article->create_time,
|
||||
'tags' => $article->tags,
|
||||
'category' => $category,
|
||||
'owner' => $owner,
|
||||
|
@ -61,6 +61,10 @@ class CourseDocument extends Component
|
||||
|
||||
$course->cover = CourseModel::getCoverPath($course->cover);
|
||||
|
||||
if (empty($article->summary)) {
|
||||
$course->summary = kg_parse_summary($course->details);
|
||||
}
|
||||
|
||||
return [
|
||||
'id' => $course->id,
|
||||
'title' => $course->title,
|
||||
|
@ -26,6 +26,9 @@ type = string
|
||||
index = self
|
||||
tokenizer = full
|
||||
|
||||
[create_time]
|
||||
type = string
|
||||
|
||||
[tags]
|
||||
type = string
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
project.name = article
|
||||
project.default_charset = UTF-8
|
||||
|
||||
server.index = xunsearch:8383
|
||||
server.search = xunsearch:8384
|
||||
server.index = 8383
|
||||
server.search = 8384
|
||||
|
||||
[id]
|
||||
type = id
|
||||
@ -26,6 +26,9 @@ type = string
|
||||
index = self
|
||||
tokenizer = full
|
||||
|
||||
[create_time]
|
||||
type = string
|
||||
|
||||
[tags]
|
||||
type = string
|
||||
|
||||
|
@ -1542,18 +1542,8 @@
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
.learning-course-card {
|
||||
height: 260px;
|
||||
}
|
||||
|
||||
.learning-course-card .progress {
|
||||
padding-top: 15px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.learning-course-card .duration {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
.user-tab .course-card .info {
|
||||
padding: 10px 8px;
|
||||
}
|
||||
|
||||
.user-card {
|
||||
|
@ -8,9 +8,9 @@ layui.use(['jquery', 'helper'], function () {
|
||||
helper.ajaxLoadHtml($tabCourses.data('url'), $tabCourses.attr('id'));
|
||||
}
|
||||
|
||||
if ($('#tab-favorites').length > 0) {
|
||||
var $tabFavorites = $('#tab-favorites');
|
||||
helper.ajaxLoadHtml($tabFavorites.data('url'), $tabFavorites.attr('id'));
|
||||
if ($('#tab-articles').length > 0) {
|
||||
var $tabArticles = $('#tab-articles');
|
||||
helper.ajaxLoadHtml($tabArticles.data('url'), $tabArticles.attr('id'));
|
||||
}
|
||||
|
||||
if ($('#tab-friends').length > 0) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user