withCount('members')->latest(); if ($request->user()->role !== 'admin') { $query->where('owner_id', $request->user()->id); } return ApiResponse::page($query->paginate((int) $request->query('per_page', 20))); } #[Apidoc\Title('创建班级')] #[Apidoc\Url('/admin/classes')] #[Apidoc\Method('POST')] #[Apidoc\RouteMiddleware(['permission:classes'])] public function store(Request $request): JsonResponse { $data = $request->validate([ 'name' => ['required', 'string', 'max:100'], 'description' => ['nullable', 'string'], ]); $class = SchoolClass::create($data + [ 'owner_id' => $request->user()->id, 'join_code' => strtoupper(Str::random(8)), 'is_active' => true, ]); return ApiResponse::success($class, '班级已创建'); } #[Apidoc\Title('分配成员')] #[Apidoc\Url('/admin/classes/{class}/members')] #[Apidoc\Method('POST')] #[Apidoc\RouteMiddleware(['permission:classes'])] public function addMember(Request $request, mixed $class): JsonResponse { $class = $this->resolveClass($class); abort_if($request->user()->role !== 'admin' && $class->owner_id !== $request->user()->id, 403, '权限不足'); $data = $request->validate([ 'user_id' => ['required', 'exists:users,id'], 'role' => ['nullable', 'in:student,assistant'], ]); $class->members()->syncWithoutDetaching([ $data['user_id'] => ['role' => $data['role'] ?? 'student'], ]); return ApiResponse::success($class->load('members'), '成员已加入'); } private function resolveClass(mixed $class): SchoolClass { if ($class instanceof SchoolClass && $class->exists) { return $class; } return SchoolClass::query()->findOrFail((int) $class); } }