whereHas('members', fn ($query) => $query->where('users.id', $request->user()->id)) ->withCount('members') ->get(), ); } #[Apidoc\Title('通过班级码加入')] #[Apidoc\Url('/app/classes/join')] #[Apidoc\Method('POST')] public function join(Request $request): JsonResponse { $data = $request->validate(['join_code' => ['required', 'string']]); $class = SchoolClass::query()->where('join_code', strtoupper($data['join_code']))->where('is_active', true)->firstOrFail(); $class->members()->syncWithoutDetaching([$request->user()->id => ['role' => 'student']]); return ApiResponse::success($class, '已加入班级'); } #[Apidoc\Title('可学习资源')] #[Apidoc\Url('/app/resources')] #[Apidoc\Method('GET')] public function resources(Request $request, LearningAccessService $access): JsonResponse { $banks = $access->visibleBanksQuery($request->user()) ->withCount('questions') ->get(); $wrongCounts = WrongQuestion::query() ->where('user_id', $request->user()->id) ->whereNull('mastered_at') ->join('questions', 'questions.id', '=', 'wrong_questions.question_id') ->selectRaw('questions.question_bank_id, count(*) as total') ->groupBy('questions.question_bank_id') ->pluck('total', 'question_bank_id'); $banks->each(fn ($bank) => $bank->setAttribute('wrong_questions_count', (int) ($wrongCounts[$bank->id] ?? 0))); $papers = $access->visiblePapersQuery($request->user()) ->withCount('questions') ->latest() ->get(); return ApiResponse::success(['banks' => $banks, 'papers' => $papers]); } }