with(['categoryDictItem', 'university']); if ($type = $request->query('target_type')) { $query->where('target_type', $type); } if ($kw = trim((string) $request->query('keyword', ''))) { $query->where(function ($q) use ($kw) { $q->where('name', 'like', "%{$kw}%") ->orWhere('request_url', 'like', "%{$kw}%") ->orWhere('keyword', 'like', "%{$kw}%"); }); } if ($request->filled('status')) { $query->where('status', (int) $request->query('status')); } $paginator = $query ->orderBy('sort') ->orderByDesc('id') ->paginate((int) $request->query('page_size', 20)) ->withQueryString(); $paginator->getCollection()->transform(fn (CrawlAddress $row) => $this->serialize($row)); return $this->paginated($paginator); } public function options(Request $request): JsonResponse { $query = CrawlAddress::query() ->where('status', 1) ->orderBy('sort') ->orderBy('name'); if ($type = $request->query('target_type')) { $query->where('target_type', $type); } $items = $query->get()->map(fn (CrawlAddress $row) => $this->serialize($row)); return $this->ok(['items' => $items]); } public function store(Request $request): JsonResponse { $data = $this->validatePayload($request); $row = CrawlAddress::query()->create($data); return $this->ok($this->serialize($row->fresh(['categoryDictItem', 'university'])), '已创建'); } public function update(Request $request, int $crawlAddress): JsonResponse { $row = CrawlAddress::query()->findOrFail($crawlAddress); $data = $this->validatePayload($request, $row); $row->fill($data); $row->save(); return $this->ok($this->serialize($row->fresh(['categoryDictItem', 'university'])), '已保存'); } public function destroy(int $crawlAddress): JsonResponse { CrawlAddress::query()->whereKey($crawlAddress)->delete(); return $this->ok(null, '已删除'); } /** * @return array */ protected function validatePayload(Request $request, ?CrawlAddress $existing = null): array { $newsCategoryTypeId = DictType::query() ->where('code', 'news_category') ->where('status', 1) ->value('id'); $data = $request->validate([ 'target_type' => ['required', 'in:paper,industry_news,teacher'], 'name' => ['required', 'string', 'max:128'], 'request_url' => ['required', 'url', 'max:512'], 'keyword' => ['nullable', 'string', 'max:512'], 'category_dict_item_id' => [ 'nullable', 'integer', Rule::exists('dict_items', 'id')->where( fn ($q) => $q->where('dict_type_id', $newsCategoryTypeId)->where('status', 1) ), ], 'university_id' => ['nullable', 'integer', 'exists:universities,id'], 'sort' => ['nullable', 'integer', 'min:0'], 'status' => ['required', 'integer', 'in:0,1'], ]); $data['name'] = trim($data['name']); $data['keyword'] = isset($data['keyword']) ? trim((string) $data['keyword']) : null; if ($data['keyword'] === '') { $data['keyword'] = null; } $data['sort'] = (int) ($data['sort'] ?? 0); $data['status'] = (int) $data['status']; if ($data['target_type'] !== 'industry_news') { $data['category_dict_item_id'] = null; } if ($data['target_type'] !== 'teacher') { $data['university_id'] = null; } return $data; } /** * @return array */ protected function serialize(CrawlAddress $row): array { return [ 'id' => $row->id, 'target_type' => $row->target_type, 'name' => $row->name, 'request_url' => $row->request_url, 'keyword' => $row->keyword, 'category_dict_item_id' => $row->category_dict_item_id, 'category_label' => $row->categoryDictItem?->label, 'university_id' => $row->university_id, 'university_name' => $row->university?->name, 'sort' => (int) $row->sort, 'status' => (int) $row->status, 'created_at' => $row->created_at?->toIso8601String(), ]; } }