Files
YwxAppThink/addon/blog/controller/Article.php
T

302 lines
8.9 KiB
PHP

<?php
// +----------------------------------------------------------------------
// | YwxApp [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2026-2036 http://ywxapp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: ywxapp<admin@ywxapp.cn>
// +----------------------------------------------------------------------
declare (strict_types = 1);
namespace addon\blog\controller;
use addon\blog\model\BlogArticle as ArticleModel;
use addon\blog\model\BlogCategory as CategoryModel;
use addon\blog\model\BlogComment as CommentModel;
use addon\blog\model\BlogTag as TagModel;
use addon\blog\model\BlogLike as LikeModel;
use addon\blog\model\BlogFavorite as FavoriteModel;
use ywxapp\model\MemberUser;
use think\facade\Cache;
use think\facade\Request;
use think\facade\View;
/**
* Article 类
*
* @author ywxapp <admin@ywxapp.cn>
*/
class Article extends BlogFrontend
{
public function initialize()
{
}
protected $noNeedLogin = ['*'];
/**
* 网站首页
*/
public function index()
{
$page = Request::param('page', 1);
$articles = ArticleModel::with(['user', 'category', 'tags'])
->where('status', 1)
->order('create_at', 'desc')
->paginate(['list_rows' => 10, 'page' => $page]);
$hotArticles = ArticleModel::with(['user', 'category'])
->where('status', 1)
->order('view_count', 'desc')
->limit(5)
->select();
$recommendedArticles = ArticleModel::with(['user', 'category'])
->where('status', 1)
->where('is_top', 1)
->order('like_count', 'desc')
->limit(5)
->select();
$categories = CategoryModel::withCount(['articles' =>
function ($query, &$alias) {
$query->where('status', 1);
$alias = 'card_count';
}])
->order('sort', 'asc')
->select();
$tags = TagModel::withCount('articles')
->order('create_at', 'desc')
->limit(20)
->select();
$latestComments = CommentModel::with(['user', 'article'])
->where('status', 1)
->order('create_at', 'desc')
->limit(5)
->select();
$this->view->assign('articles', $articles);
$this->view->assign('hotArticles', $hotArticles);
$this->view->assign('recommendedArticles', $recommendedArticles);
$this->view->assign('categories', $categories);
$this->view->assign('tags', $tags);
$this->view->assign('latestComments', $latestComments);
return $this->view->fetch();
}
/**
* 文章详情页
*/
public function detail($id)
{
$article = ArticleModel::with(['user', 'category', 'tags'])
->where('id', $id)
->where('status', 1)
->find();
if (!$article) {
return $this->error('文章不存在或已被删除');
}
$article->view_count += 1;
$article->save();
$comments = CommentModel::with([
'member',
'children' =>
function ($q) {
$q->with(['user'])->where('status', 1)->order('create_at', 'asc');
},
])
->where('aid', $id)
->where('pid', 0)
->where('status', 1)
->order('create_at', 'desc')
->paginate(10);
$relatedArticles = \addon\blog\service\BlogSearchService::related($article->id, 5);
return View::fetch('article/detail', [
'article' => $article,
'comments' => $comments,
'relatedArticles' => $relatedArticles
]);
}
/**
* 文章点赞
*/
public function like($id)
{
if (! $this->auth->isLogin) {
return json(['code' => 0, 'msg' => '请先登录']);
}
$uid = $this->auth->model->uid;
$article = ArticleModel::find($id);
if (!$article) {
return json(['code' => 0, 'msg' => '文章不存在']);
}
$like = LikeModel::where('uid', $uid)
->where('aid', $id)
->find();
if ($like) {
$like->delete();
$article->like_count = max(0, $article->like_count - 1);
$action = 'cancel';
} else {
$like = new LikeModel();
$like->uid = $uid;
$like->aid = $id;
$like->save();
$article->like_count += 1;
$action = 'add';
}
$article->save();
return json([
'code' => 1,
'msg' => $action == 'add' ? '点赞成功' : '已取消点赞',
'count' => $article->like_count,
'action' => $action
]);
}
/**
* 文章收藏
*/
public function favorite($id)
{
if (! $this->auth->isLogin) {
return json(['code' => 0, 'msg' => '请先登录']);
}
$uid = $this->auth->model->uid;
$article = ArticleModel::find($id);
if (!$article) {
return json(['code' => 0, 'msg' => '文章不存在']);
}
$favorite = FavoriteModel::where('uid', $uid)
->where('aid', $id)
->find();
if ($favorite) {
$favorite->delete();
$article->favorite_count = max(0, $article->favorite_count - 1);
$action = 'cancel';
} else {
$favorite = new FavoriteModel();
$favorite->uid = $uid;
$favorite->aid = $id;
$favorite->save();
$article->favorite_count += 1;
$action = 'add';
}
$article->save();
return json([
'code' => 1,
'msg' => $action == 'add' ? '收藏成功' : '已取消收藏',
'count' => $article->favorite_count,
'action' => $action
]);
}
/**
* 获取文章评论
*/
public function getComments($id)
{
$page = Request::param('page', 1);
$pageSize = Request::param('page_size', 10);
$comments = CommentModel::with(['user'])
->where('aid', $id)
->where('pid', 0)
->where('status', 1)
->order('create_at', 'desc')
->page($page, $pageSize)
->select();
$total = CommentModel::where('aid', $id)
->where('pid', 0)
->where('status', 1)
->count();
$commentList = [];
foreach ($comments as $comment) {
$commentList[] = [
'id' => $comment->id,
'content' => $comment->content,
'create_at' => date('Y-m-d H:i', $comment->create_at),
'member' => [
'uid' => $comment->user->uid,
'nickname' => $comment->user->nickname,
'avatar' => $comment->user->avatar ?? '/static/images/avatar.png'
],
'like_count' => $comment->like_count
];
}
return json([
'code' => 1,
'data' => [
'list' => $commentList,
'total' => $total,
'page' => $page,
'page_size' => $pageSize
]
]);
}
/**
* 个人博客主页:展示该用户的资料 + 已发布文章(多用户门户)
*/
public function author($id)
{
$author = MemberUser::find($id);
if (!$author) {
return $this->error('用户不存在');
}
$stats = [
'articles' => ArticleModel::where('uid', $id)->where('status', 1)->count(),
'views' => (int) ArticleModel::where('uid', $id)->where('status', 1)->sum('view_count'),
'likes' => (int) ArticleModel::where('uid', $id)->where('status', 1)->sum('like_count'),
];
$join = $author->create_at;
if (is_numeric($join)) {
$join = date('Y-m-d', (int) $join);
} else {
$ts = strtotime((string) $join);
$join = $ts !== false ? date('Y-m-d', $ts) : (string) $join;
}
$avatar = $author->avatar ?: '/static/blog/img/portrait.jpg';
$articles = ArticleModel::with(['user', 'category', 'tags'])
->where('uid', $id)
->where('status', 1)
->order('create_at', 'desc')
->paginate(10);
return View::fetch('article/author', [
'author' => $author,
'avatar' => $avatar,
'author_join' => $join,
'stats' => $stats,
'articles' => $articles,
]);
}
}