where('slug', $slug) ->orWhere('id', (int) $slug) ->first(); abort_unless($post && $post->status === 'published', 404); $this->ensureReadable($post); // 浏览量由 /track-view 端点统计(页面整页缓存下控制器不执行,避免双计) $comments = $post->comments() ->where('status', 'published') ->orderBy('created_at', (int) blog_setting('comment_order', 1) === 1 ? 'asc' : 'desc') ->paginate(20); $rendered = $this->renderer->renderWithToc($post); return theme_view('show', [ 'post' => $post, 'comments' => $comments, 'contentHtml' => $rendered['html'], 'toc' => $rendered['toc'], ]); } private function ensureReadable(Post $post): void { if (! $post->read_password) { return; } $granted = session()->get("post_read_password.{$post->id}") === $post->read_password; $isEditor = auth()->check() && (auth()->user()->isAdmin() || auth()->user()->hasRole('editor')); if (! $granted && ! $isEditor) { abort(403, '该文章需要访问密码'); } } }