with(['category', 'source']) ->when($request->filled('q'), function ($query) use ($request): void { $query->whereFullText(['name', 'summary', 'description'], (string) $request->string('q')); }) ->latest('updated_at') ->paginate(20) ->withQueryString(); return view('admin.tools.index', [ 'items' => $items, 'filters' => $request->only(['q']), ]); } public function create(): View { return view('admin.tools.form', [ 'item' => new Tool(), 'categories' => Category::query()->where('type', 'tool')->orderBy('name')->get(), 'sources' => Source::query()->where('is_whitelisted', true)->orderBy('name')->get(), 'statusOptions' => EntityStatus::cases(), 'submitRoute' => route('admin.tools.store'), 'method' => 'POST', ]); } public function store(ToolRequest $request): RedirectResponse { $data = $this->normalizePayload($request->validated()); $item = Tool::query()->create($data); $this->changeLogService->log('created', $item); return redirect()->route('admin.tools.edit', $item)->with('status', '工具已创建'); } public function edit(Tool $tool): View { return view('admin.tools.form', [ 'item' => $tool, 'categories' => Category::query()->where('type', 'tool')->orderBy('name')->get(), 'sources' => Source::query()->where('is_whitelisted', true)->orderBy('name')->get(), 'statusOptions' => EntityStatus::cases(), 'submitRoute' => route('admin.tools.update', $tool), 'method' => 'PUT', ]); } public function update(ToolRequest $request, Tool $tool): RedirectResponse { $before = $tool->getAttributes(); $tool->fill($this->normalizePayload($request->validated())); $tool->save(); $this->changeLogService->log('updated', $tool, $before); return redirect()->route('admin.tools.edit', $tool)->with('status', '工具已更新'); } public function publish(Tool $tool): RedirectResponse { $before = $tool->getAttributes(); $tool->status = EntityStatus::Published; $tool->published_at = $tool->published_at ?? now(); $tool->save(); $this->changeLogService->log('published', $tool, $before); return redirect()->route('admin.tools.edit', $tool)->with('status', '工具已发布'); } public function markStale(Tool $tool): RedirectResponse { $before = $tool->getAttributes(); $tool->is_stale = true; $tool->status = EntityStatus::Stale; $tool->save(); $this->changeLogService->log('marked_stale', $tool, $before); return redirect()->route('admin.tools.edit', $tool)->with('status', '工具已标记失效'); } private function normalizePayload(array $data): array { $data['has_api'] = (bool) ($data['has_api'] ?? false); $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; } }