query('category'); $q = trim((string) $request->query('q', '')); $categories = Category::ofType('article')->orderBy('sort')->orderBy('name')->get(); $articles = Article::published() ->when($categoryId, fn ($query) => $query->where('category_id', $categoryId)) ->when($q, function ($query) use ($q) { $query->where(function ($sub) use ($q) { $sub->where('title', 'like', "%{$q}%") ->orWhere('summary', 'like', "%{$q}%"); }); }) ->paginate(10) ->withQueryString(); return view('articles.index', compact('articles', 'categories', 'q', 'categoryId')); } public function show(Article $article): View { $user = request()->user(); // 公开:已审且已发布;作者本人或审核员:可看自己投稿(含待审/驳回) $canView = $article->status === 'approved' && $article->published_at !== null; if (! $canView && $user) { $canView = $article->user_id === $user->id || $user->canPerm('articles.moderate'); } if (! $canView) { abort(404); } return view('articles.show', compact('article')); } /** * 用户投稿表单(需登录)。 */ public function create(): View { $categories = Category::ofType('article')->orderBy('sort')->orderBy('name')->get(); return view('articles.submit', compact('categories')); } /** * 提交用户投稿:写入 articles(user_id + status=pending),审核前仅作者可见。 */ public function storeSubmission(Request $request) { $data = $request->validate([ 'category_id' => ['nullable', 'exists:categories,id'], 'title' => ['required', 'string', 'max:160'], 'summary' => ['nullable', 'string', 'max:255'], 'body' => ['required', 'string'], 'template' => ['required', 'in:standard,tech,feature'], 'cover' => ['nullable', 'string', 'max:255'], ]); $data['body'] = \Purifier::clean($data['body'], 'article'); $base = Str::slug(Str::ascii($data['title'])) ?: ('article-' . date('YmdHis')); $slug = $base; $i = 1; // withTrashed:软删除行仍占用 slug 唯一索引,须一并检查避免 Duplicate entry while (Article::withTrashed()->where('slug', $slug)->exists()) { $slug = $base . '-' . $i++; } Article::create([ 'category_id' => $data['category_id'] ?? null, 'user_id' => Auth::id(), 'title' => $data['title'], 'slug' => $slug, 'summary' => $data['summary'] ?? null, 'body' => $data['body'], 'template' => $data['template'], 'cover' => $data['cover'] ?? null, 'author' => Auth::user()->name, 'status' => 'pending', 'published_at' => null, ]); return redirect()->route('articles.mine') ->with('success', '投稿已提交,管理员审核通过后将公开展示'); } /** * 我的投稿:当前用户自己的全部文章(含待审/驳回)。 */ public function mine(): View { $articles = Article::where('user_id', Auth::id()) ->orderByDesc('created_at') ->paginate(10); return view('articles.mine', compact('articles')); } }