with(['category', 'source']) ->when($request->filled('q'), function ($query) use ($request): void { $query->whereFullText(['title', 'excerpt', 'body'], (string) $request->string('q')); }) ->latest('updated_at') ->paginate(20) ->withQueryString(); return view('admin.articles.index', [ 'items' => $items, 'filters' => $request->only(['q']), ]); } public function create(): View { return view('admin.articles.form', [ 'item' => new Article(), 'categories' => Category::query()->where('type', 'news')->orderBy('name')->get(), 'sources' => Source::query()->where('is_whitelisted', true)->orderBy('name')->get(), 'statusOptions' => EntityStatus::cases(), 'submitRoute' => route('admin.articles.store'), 'method' => 'POST', ]); } public function store(ArticleRequest $request): RedirectResponse { $item = Article::query()->create($this->normalizePayload($request->validated())); $this->changeLogService->log('created', $item); return redirect()->route('admin.articles.edit', $item)->with('status', '资讯已创建'); } public function edit(Article $article): View { return view('admin.articles.form', [ 'item' => $article, 'categories' => Category::query()->where('type', 'news')->orderBy('name')->get(), 'sources' => Source::query()->where('is_whitelisted', true)->orderBy('name')->get(), 'statusOptions' => EntityStatus::cases(), 'submitRoute' => route('admin.articles.update', $article), 'method' => 'PUT', ]); } public function update(ArticleRequest $request, Article $article): RedirectResponse { $before = $article->getAttributes(); $article->fill($this->normalizePayload($request->validated())); $article->save(); $this->changeLogService->log('updated', $article, $before); return redirect()->route('admin.articles.edit', $article)->with('status', '资讯已更新'); } public function publish(Article $article): RedirectResponse { $before = $article->getAttributes(); $article->status = EntityStatus::Published; $article->published_at = $article->published_at ?? now(); $article->save(); $this->changeLogService->log('published', $article, $before); return redirect()->route('admin.articles.edit', $article)->with('status', '资讯已发布'); } public function markStale(Article $article): RedirectResponse { $before = $article->getAttributes(); $article->is_stale = true; $article->status = EntityStatus::Stale; $article->save(); $this->changeLogService->log('marked_stale', $article, $before); return redirect()->route('admin.articles.edit', $article)->with('status', '资讯已标记失效'); } private function normalizePayload(array $data): array { $data['is_stale'] = (bool) ($data['is_stale'] ?? false); if (($data['status'] ?? null) === EntityStatus::Published->value && empty($data['published_at'])) { $data['published_at'] = now(); } return $data; } }