// +---------------------------------------------------------------------- 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 */ 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, ]); } }