// +---------------------------------------------------------------------- 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 think\facade\Cache; use think\facade\View; use think\facade\Request; /** * Index 类 * * @author ywxapp */ class Index extends BlogFrontend { public function initialize() {} /** * Summary of needLogin * @var array */ protected $noNeedLogin = ['*']; /** * 网站首页 */ public function index() { // 尝试从缓存获取首页数据(v2 键:绕过旧版本可能残留的损坏缓存) $cacheKey = 'homepage_data_v2'; $data = Cache::get($cacheKey); // 判断缓存中的文章是否为空(兼容数组与模型集合对象) $articlesEmpty = true; if (! empty($data) && ! empty($data['articles'])) { $cachedArticles = $data['articles']; $articlesEmpty = (is_object($cachedArticles) && method_exists($cachedArticles, 'isEmpty')) ? $cachedArticles->isEmpty() : (count($cachedArticles) === 0); } if (empty($data) || $articlesEmpty) { // 获取最新文章 $articles = ArticleModel::with(['user', 'category', 'tags']) ->where('status', 1) ->order('create_at', 'desc') ->limit(10) ->select(); // 获取热门文章 $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(); $data = [ 'articles' => $articles, 'hotArticles' => $hotArticles, 'recommendedArticles' => $recommendedArticles, 'categories' => $categories, 'tags' => $tags, 'latestComments' => $latestComments, ]; // 仅在存在文章时缓存,避免空结果被长期缓存挡住新数据 if (! empty($articles) && ! $articles->isEmpty()) { Cache::set($cacheKey, $data, 3600); } } $this->view->assign('articles', $data['articles']); $this->view->assign('hotArticles', $data['hotArticles']); $this->view->assign('recommendedArticles', $data['recommendedArticles']); $this->view->assign('categories', $data['categories']); $this->view->assign('tags', $data['tags']); $this->view->assign('latestComments', $data['latestComments']); return $this->view->fetch('index/index'); } /** * 分类文章列表(无 $id 时展示全部分类) */ public function category($id = null) { if ($id === null) { $categories = CategoryModel::withCount(['articles' => function ($query, &$alias) { $query->where('status', 1); $alias = 'card_count'; }])->order('sort', 'asc')->select(); return View::fetch('category/index', [ 'category' => null, 'categories' => $categories, ]); } $category = CategoryModel::find($id); if (! $category) { return $this->result->error('分类不存在'); } $page = Request::param('page', 1); $pageSize = 10; $articles = ArticleModel::with(['user', 'tags']) ->where('cid', $id) ->where('status', 1) ->order('create_at', 'desc') ->paginate([ 'list_rows' => $pageSize, 'page' => $page, ]); return View::fetch('category/index', [ 'category' => $category, 'articles' => $articles, ]); } /** * 标签文章列表(无 $id 时展示全部标签) */ public function tag($id = null) { if ($id === null) { $tags = TagModel::withCount('articles')->order('create_at', 'desc')->select(); return View::fetch('tag/index', [ 'tag' => null, 'tags' => $tags, ]); } $tag = TagModel::find($id); if (! $tag) { return $this->result->error('标签不存在'); } $page = Request::param('page', 1); $pageSize = 10; $articles = $tag->articles() ->with(['user', 'category']) ->where('status', 1) ->order('create_at', 'desc') ->paginate([ 'list_rows' => $pageSize, 'page' => $page, ]); return View::fetch('tag/index', [ 'tag' => $tag, 'articles' => $articles, ]); } /** * 搜索页面 */ public function search() { $keyword = Request::param('keyword', ''); if (empty($keyword)) { return $this->result->error('请输入搜索关键词'); } $page = Request::param('page', 1); $pageSize = 10; $articles = \addon\blog\service\BlogSearchService::search($keyword, (int) $page, $pageSize); return View::fetch('index/search', [ 'keyword' => $keyword, 'articles' => $articles, ]); } /** * 关于页面 */ public function about() { return View::fetch('index/about'); } /** * 联系页面 */ public function contact() { return View::fetch('index/contact'); } /** * 附近文章(GEO/LBS) */ public function nearby() { $lat = (float) Request::param('lat', 0); $lng = (float) Request::param('lng', 0); $radius = (float) Request::param('radius', 10); $list = \addon\blog\service\BlogSearchService::nearby($lat, $lng, $radius, 30); $data = []; foreach ($list as $a) { $data[] = [ 'id' => $a->id, 'title' => $a->title, 'distance' => isset($a->distance_km) ? round($a->distance_km, 2) : null, 'category' => $a->category ? $a->category->name : '', 'url' => url('blog/article/detail', ['id' => $a->id]), ]; } if (Request::isAjax()) { return json(['code' => 1, 'data' => $data]); } return View::fetch('index/nearby', [ 'list' => $data, 'lat' => $lat, 'lng' => $lng, 'radius' => $radius, ]); } }