query('type', '')); $keyword = trim((string) $request->query('keyword', '')); $idiomQuery = Riddle::query(); if ($selectedType !== '' && isset($typeOptions[$selectedType])) { // 题型筛选只接受系统支持值,避免非法参数污染查询。 $idiomQuery->ofType($selectedType); } if ($keyword !== '') { // 关键词同时匹配答案与提示,方便后台快速定位题目。 $idiomQuery->where(function ($query) use ($keyword): void { $query->where('answer', 'like', '%'.$keyword.'%') ->orWhere('hint', 'like', '%'.$keyword.'%'); }); } $idioms = $idiomQuery ->orderBy('type') ->orderBy('sort') ->orderBy('id') ->get(); $typeStats = Riddle::query() ->selectRaw('type, COUNT(*) as total') ->groupBy('type') ->pluck('total', 'type') ->all(); return view('admin.riddles.index', [ 'idioms' => $idioms, 'typeOptions' => $typeOptions, 'selectedType' => $selectedType, 'keyword' => $keyword, 'typeStats' => $typeStats, ]); } /** * 方法功能:创建新的猜谜活动题目。 */ public function store(Request $request): RedirectResponse { $data = $this->validateRiddlePayload($request); // 新增时默认启用,便于后台批量补题后立即可用。 $data['is_active'] = $request->boolean('is_active', true); Riddle::create($data); $typeLabel = Riddle::labelForType($data['type']); return redirect() ->route('admin.riddles.index', $this->buildIndexFilters($request)) ->with('success', "{$typeLabel}题目已添加!"); } /** * 方法功能:更新已有题目内容与题型。 */ public function update(Request $request, Riddle $idiom): RedirectResponse { $data = $this->validateRiddlePayload($request); // 编辑时显式按复选框结果落库,避免旧状态残留。 $data['is_active'] = $request->boolean('is_active'); $idiom->update($data); return redirect() ->route('admin.riddles.index', $this->buildIndexFilters($request)) ->with('success', "题目「{$idiom->answer}」已更新!"); } /** * 方法功能:通过 AJAX 切换题目的启用状态。 */ public function toggle(Riddle $idiom): JsonResponse { // 开关按钮只变更启用状态,不改动其他题库字段。 $idiom->update(['is_active' => ! $idiom->is_active]); return response()->json([ 'ok' => true, 'is_active' => $idiom->is_active, 'message' => $idiom->is_active ? "「{$idiom->answer}」已启用" : "「{$idiom->answer}」已禁用", ]); } /** * 方法功能:删除指定题目。 */ public function destroy(Request $request, Riddle $idiom): RedirectResponse { $answer = $idiom->answer; $idiom->delete(); return redirect() ->route('admin.riddles.index', $this->buildIndexFilters($request)) ->with('success', "题目「{$answer}」已删除!"); } /** * 方法功能:校验后台题库保存载荷。 * * @return array{type:string,answer:string,hint:string,sort:int} */ private function validateRiddlePayload(Request $request): array { return $request->validate([ 'type' => ['required', 'string', Rule::in(Riddle::supportedTypes())], 'answer' => ['required', 'string', 'max:120'], 'hint' => ['required', 'string', 'max:255'], 'sort' => ['required', 'integer', 'min:0'], 'is_active' => ['sometimes', 'boolean'], ]); } /** * 方法功能:保留列表筛选参数,方便后台操作后返回原筛选结果。 * * @return array */ private function buildIndexFilters(Request $request): array { $filters = []; $type = trim((string) $request->input('redirect_type', $request->query('type', ''))); $keyword = trim((string) $request->input('redirect_keyword', $request->query('keyword', ''))); if ($type !== '') { $filters['type'] = $type; } if ($keyword !== '') { $filters['keyword'] = $keyword; } return $filters; } }