* @Date: 2026-08-10 15:30:57 * @LastEditors: YwxApp * @LastEditTime: 2026-08-13 17:38:27 * @Description: * @FilePath: \ywxapp_dev\addon\articles\controller\ArticlesFrontend.php * @CustomString: Copyright (c) 2026 YwxApp */ // +---------------------------------------------------------------------- // | YwxApp [ WE CAN DO IT JUST THINK ] // +---------------------------------------------------------------------- // | 文章CMS前台基类:统一注入侧边栏/分类/标签等共享数据 // +---------------------------------------------------------------------- declare (strict_types = 1); namespace addon\articles\controller; use ywxapp\controller\FrontendBase; use think\facade\Cache; use addon\articles\model\Article; use addon\articles\model\ArticleCategory; use addon\articles\model\ArticleTag; use addon\articles\library\ArticleSchema; class ArticlesFrontend extends FrontendBase { protected $noNeedLogin = ['*']; protected $noNeedVerify = ['*']; protected function initialize() { parent::initialize(); // articles 前台页面自带完整 结构,清空 layout_name, // 避免被 common/layout 包裹导致双层 、标签外露、排版错乱。 //$this->view->config(['layout_name' => '']); ArticleSchema::ensure(); $isLogin = $this->auth && $this->auth->isLogin; $loginUser = $isLogin ? $this->auth->info : null; // 分类/标签变动频率低,缓存 5 分钟(缓存数组,避免序列化模型集合) $categories = Cache::remember('articles:categories', function () { return ArticleCategory::allEnable()->toArray(); }, 300); $tags = Cache::remember('articles:tags', function () { return ArticleTag::where('delete_at', 0)->order('id', 'desc')->limit(20)->select()->toArray(); }, 300); $this->view->assign([ 'categories' => $categories, 'tags' => $tags, 'hot' => Article::hot(10), 'is_login' => $isLogin, 'member' => $loginUser, 'nav_active' => '', ]); } /** * 浏览量计数(同一访客同一文章 5 分钟内只算 1 次) * * 用缓存节流而非 Session:前台对游客开放,游客请求未必启动 Session, * 且浏览量属统计类数据,不应强依赖会话。 * * @param int $id 文章ID */ protected function bumpViews(int $id): void { if ($id <= 0) { return; } $fingerprint = md5($this->request->ip() . '|' . (string) $this->request->header('user-agent', '')); $key = 'articles_view:' . $id . ':' . $fingerprint; if (Cache::get($key, 0)) { return; // 5 分钟内已计过 } Article::where('id', $id)->inc('view_count')->update(); Cache::set($key, 1, 300); } }