orderBy('name') ->withCount(['threads' => fn ($q) => $q->where('status', ForumThread::STATUS_APPROVED)]) ->get(); return view('forum.index', compact('boards')); } public function board(ForumBoard $board): View { $threads = $board->threads() ->visible(Auth::user()) ->with('user') ->orderByDesc('is_pinned') ->orderByDesc('last_reply_at') ->orderByDesc('created_at') ->paginate(15); return view('forum.board', compact('board', 'threads')); } public function thread(ForumThread $thread): View { if ($thread->trashed()) { abort(404); } $user = Auth::user(); $isMod = $user && $user->canPerm('forum.moderate'); $isOwner = $user && $thread->user_id === $user->id; // 待审且非作者、非审核员:不可见 if ($thread->status !== ForumThread::STATUS_APPROVED && ! $isMod && ! $isOwner) { abort(404); } $thread->increment('views'); $replies = $thread->replies() ->visible($user) ->with('user') ->orderBy('created_at') ->paginate(20); return view('forum.thread', compact('thread', 'replies')); } public function store(Request $request) { $data = $request->validate([ 'board_id' => ['required', 'exists:forum_boards,id'], 'title' => ['required', 'string', 'max:120'], 'body' => ['required', 'string', 'max:8000'], ]); $thread = ForumThread::create([ 'board_id' => $data['board_id'], 'user_id' => Auth::id(), 'title' => $data['title'], 'body' => $data['body'], 'status' => ForumThread::STATUS_PENDING, 'last_reply_at' => now(), ]); $request->user()->awardPoints(10); return redirect()->route('forum.thread', $thread) ->with('success', '帖子已提交,管理员审核通过后将公开展示'); } public function reply(Request $request, ForumThread $thread) { if ($thread->is_locked) { return back()->withErrors(['body' => '该帖子已锁定,无法回复。']); } // 待审帖子的回复入口对普通用户不可见(thread() 已拦截),此处仅作兜底 if ($thread->status !== ForumThread::STATUS_APPROVED && ! Auth::user()?->canPerm('forum.moderate')) { return back()->withErrors(['body' => '该帖子尚未通过审核,暂不可回复。']); } $data = $request->validate([ 'body' => ['required', 'string', 'max:8000'], ]); ForumReply::create([ 'thread_id' => $thread->id, 'user_id' => Auth::id(), 'body' => $data['body'], 'status' => ForumReply::STATUS_PENDING, ]); $thread->update(['last_reply_at' => now()]); $request->user()->awardPoints(5); return back()->with('success', '回复已提交,审核通过后将公开展示'); } }