where('username', 'like', '%' . $params['username'] . '%'); } if (!empty($params['real_name'])) { $query->where('real_name', 'like', '%' . $params['real_name'] . '%'); } if (!empty($params['email'])) { $query->where('email', 'like', '%' . $params['email'] . '%'); } if (!empty($params['phone_number'])) { $query->where('phone_number', 'like', '%' . $params['phone_number'] . '%'); } if (isset($params['role'])) { $query->where('role', $params['role']); } if (isset($params['status'])) { $query->where('status', $params['status']); } if (isset($params['sex'])) { $query->where('sex', $params['sex']); } if (!empty($params['grade_id'])) { $query->where('grade_id', $params['grade_id']); } if (!empty($params['parent_id'])) { $query->where('parent_id', $params['parent_id']); } if (!empty($params['class_id'])) { $query->whereHas('studentClasses', function ($q) use ($params) { $q->where('class_id', $params['class_id']); $q->where('status', StudentClass::STATUS_NORMAL); }); } // 排序 $query->orderBy('id', 'desc'); return $this->paginate($query, $params); } /** * 获取学生详情 * @param int $id * @return array */ public function getStudentDetail(int $id): array { $student = Student::find($id); if (!$student) { throw new BusinessException(ResponseEnum::CLIENT_NOT_FOUND, '学生不存在'); } return $student->getFullInfo(); } /** * 创建学生 * @param array $data * @return array */ public function createStudent(array $data): array { // 检查用户名是否已存在 if (Student::where('username', $data['username'])->exists()) { throw new BusinessException(ResponseEnum::CLIENT_PARAMETER_ERROR, '用户名已存在'); } // 检查邮箱是否已存在 if (!empty($data['email']) && Student::where('email', $data['email'])->exists()) { throw new BusinessException(ResponseEnum::CLIENT_PARAMETER_ERROR, '邮箱已存在'); } // 检查手机号是否已存在 if (!empty($data['phone_number']) && Student::where('phone_number', $data['phone_number'])->exists()) { throw new BusinessException(ResponseEnum::CLIENT_PARAMETER_ERROR, '手机号已存在'); } // 生成密码盐值 $salt = Student::generateSalt(); $data['salt'] = $salt; $data['password'] = Student::encryptPassword($data['password'], $salt); $data['reg_time'] = now(); $data['reg_ip'] = request()->ip(); $student = Student::create($data); Log::info('创建学生', [ 'student_id' => $student->id, 'username' => $student->username, 'operator' => $this->getCurrentUser()['id'] ?? 0 ]); return $student->getFullInfo(); } /** * 更新学生 * @param int $id * @param array $data * @return array */ public function updateStudent(int $id, array $data): array { $student = Student::find($id); if (!$student) { throw new BusinessException(ResponseEnum::CLIENT_NOT_FOUND, '学生不存在'); } // 检查用户名是否已存在(排除自己) if (!empty($data['username']) && Student::where('username', $data['username'])->where('id', '!=', $id)->exists()) { throw new BusinessException(ResponseEnum::CLIENT_PARAMETER_ERROR, '用户名已存在'); } // 检查邮箱是否已存在(排除自己) if (!empty($data['email']) && Student::where('email', $data['email'])->where('id', '!=', $id)->exists()) { throw new BusinessException(ResponseEnum::CLIENT_PARAMETER_ERROR, '邮箱已存在'); } // 检查手机号是否已存在(排除自己) if (!empty($data['phone_number']) && Student::where('phone_number', $data['phone_number'])->where('id', '!=', $id)->exists()) { throw new BusinessException(ResponseEnum::CLIENT_PARAMETER_ERROR, '手机号已存在'); } // 如果修改密码,需要重新加密 if (!empty($data['password'])) { $salt = Student::generateSalt(); $data['salt'] = $salt; $data['password'] = Student::encryptPassword($data['password'], $salt); } $student->update($data); Log::info('更新学生', [ 'student_id' => $student->id, 'username' => $student->username, 'operator' => $this->getCurrentUser()['id'] ?? 0 ]); return $student->refresh()->getFullInfo(); } /** * 删除学生 * @param int $id * @return bool */ public function deleteStudent(int $id): bool { $student = Student::find($id); if (!$student) { throw new BusinessException(ResponseEnum::CLIENT_NOT_FOUND, '学生不存在'); } // 检查是否有关联的班级记录 if ($student->studentClasses()->exists()) { throw new BusinessException(ResponseEnum::CLIENT_PARAMETER_ERROR, '学生有关联的班级记录,无法删除'); } // 检查是否有子女关联 if ($student->children()->exists()) { throw new BusinessException(ResponseEnum::CLIENT_PARAMETER_ERROR, '该家长有关联的子女,无法删除'); } $student->delete(); Log::info('删除学生', [ 'student_id' => $id, 'username' => $student->username, 'operator' => $this->getCurrentUser()['id'] ?? 0 ]); return true; } /** * 重置学生密码 * @param int $id * @param string $newPassword * @return bool */ public function resetPassword(int $id, string $newPassword): bool { $student = Student::find($id); if (!$student) { throw new BusinessException(ResponseEnum::CLIENT_NOT_FOUND, '学生不存在'); } $salt = Student::generateSalt(); $student->update([ 'password' => Student::encryptPassword($newPassword, $salt), 'salt' => $salt ]); Log::info('重置学生密码', [ 'student_id' => $id, 'username' => $student->username, 'operator' => $this->getCurrentUser()['id'] ?? 0 ]); return true; } /** * 更新学生状态 * @param int $id * @param int $status * @return array */ public function updateStatus(int $id, int $status): array { $student = Student::find($id); if (!$student) { throw new BusinessException(ResponseEnum::CLIENT_NOT_FOUND, '学生不存在'); } $student->update(['status' => $status]); Log::info('更新学生状态', [ 'student_id' => $id, 'username' => $student->username, 'old_status' => $student->status, 'new_status' => $status, 'operator' => $this->getCurrentUser()['id'] ?? 0 ]); return $student->refresh()->getFullInfo(); } /** * 获取学生的班级历史 * @param int $id * @return array */ public function getStudentClassHistory(int $id): array { $student = Student::find($id); if (!$student) { throw new BusinessException(ResponseEnum::CLIENT_NOT_FOUND, '学生不存在'); } $classes = $student->studentClasses() ->with(['schoolClass.school', 'schoolClass.campus']) ->orderBy('join_time', 'desc') ->get(); return $classes->map(function ($studentClass) { return [ 'id' => $studentClass->id, 'school_name' => $studentClass->schoolClass->school->name ?? '', 'campus_name' => $studentClass->schoolClass->campus->name ?? '', 'class_name' => $studentClass->schoolClass->name ?? '', 'join_time' => $studentClass->join_time, 'leave_time' => $studentClass->leave_time, 'status' => $studentClass->status, 'status_name' => $studentClass->status_name, 'study_days' => $studentClass->getStudyDays(), 'remark' => $studentClass->remark ]; })->toArray(); } /** * 将学生分配到班级 * @param int $studentId * @param int $classId * @param array $data * @return array */ public function assignToClass(int $studentId, int $classId, array $data = []): array { $student = Student::find($studentId); if (!$student) { throw new BusinessException(ResponseEnum::CLIENT_NOT_FOUND, '学生不存在'); } $class = SchoolClass::find($classId); if (!$class) { throw new BusinessException(ResponseEnum::CLIENT_NOT_FOUND, '班级不存在'); } // 检查是否已经在该班级中 $existingRecord = StudentClass::where('student_id', $studentId) ->where('class_id', $classId) ->where('status', StudentClass::STATUS_NORMAL) ->first(); if ($existingRecord) { throw new BusinessException(ResponseEnum::CLIENT_PARAMETER_ERROR, '学生已在该班级中'); } // 将学生在其他班级的记录设为转班状态 StudentClass::where('student_id', $studentId) ->where('status', StudentClass::STATUS_NORMAL) ->update([ 'status' => StudentClass::STATUS_TRANSFERRED, 'leave_time' => now(), 'remark' => '转班' ]); // 创建新的班级记录 $studentClass = StudentClass::create([ 'student_id' => $studentId, 'school_id' => $class->school_id, 'class_id' => $classId, 'join_time' => $data['join_time'] ?? now(), 'status' => StudentClass::STATUS_NORMAL, 'remark' => $data['remark'] ?? '' ]); Log::info('学生分配到班级', [ 'student_id' => $studentId, 'class_id' => $classId, 'operator' => $this->getCurrentUser()['id'] ?? 0 ]); return $studentClass->load(['student', 'schoolClass'])->toArray(); } /** * 从班级中移除学生 * @param int $studentId * @param int $classId * @param array $data * @return bool */ public function removeFromClass(int $studentId, int $classId, array $data = []): bool { $studentClass = StudentClass::where('student_id', $studentId) ->where('class_id', $classId) ->where('status', StudentClass::STATUS_NORMAL) ->first(); if (!$studentClass) { throw new BusinessException(ResponseEnum::CLIENT_NOT_FOUND, '学生不在该班级中'); } $studentClass->update([ 'status' => $data['status'] ?? StudentClass::STATUS_TRANSFERRED, 'leave_time' => $data['leave_time'] ?? now(), 'remark' => $data['remark'] ?? '移除' ]); Log::info('从班级移除学生', [ 'student_id' => $studentId, 'class_id' => $classId, 'operator' => $this->getCurrentUser()['id'] ?? 0 ]); return true; } /** * 获取家长的子女列表 * @param int $parentId * @return array */ public function getParentChildren(int $parentId): array { $parent = Student::find($parentId); if (!$parent) { throw new BusinessException(ResponseEnum::CLIENT_NOT_FOUND, '家长不存在'); } if (!$parent->isParent()) { throw new BusinessException(ResponseEnum::CLIENT_PARAMETER_ERROR, '用户不是家长'); } return $parent->children()->with(['studentClasses.schoolClass'])->get()->map(function ($child) { return $child->getFullInfo(); })->toArray(); } /** * 绑定家长和子女关系 * @param int $parentId * @param int $childId * @return bool */ public function bindParentChild(int $parentId, int $childId): bool { $parent = Student::find($parentId); if (!$parent) { throw new BusinessException(ResponseEnum::CLIENT_NOT_FOUND, '家长不存在'); } if (!$parent->isParent()) { throw new BusinessException(ResponseEnum::CLIENT_PARAMETER_ERROR, '用户不是家长'); } $child = Student::find($childId); if (!$child) { throw new BusinessException(ResponseEnum::CLIENT_NOT_FOUND, '学生不存在'); } if (!$child->isStudent()) { throw new BusinessException(ResponseEnum::CLIENT_PARAMETER_ERROR, '用户不是学生'); } if ($child->parent_id) { throw new BusinessException(ResponseEnum::CLIENT_PARAMETER_ERROR, '学生已有家长'); } $child->update(['parent_id' => $parentId]); Log::info('绑定家长和子女关系', [ 'parent_id' => $parentId, 'child_id' => $childId, 'operator' => $this->getCurrentUser()['id'] ?? 0 ]); return true; } /** * 解除家长和子女关系 * @param int $childId * @return bool */ public function unbindParentChild(int $childId): bool { $child = Student::find($childId); if (!$child) { throw new BusinessException(ResponseEnum::CLIENT_NOT_FOUND, '学生不存在'); } if (!$child->parent_id) { throw new BusinessException(ResponseEnum::CLIENT_PARAMETER_ERROR, '学生没有家长'); } $parentId = $child->parent_id; $child->update(['parent_id' => null]); Log::info('解除家长和子女关系', [ 'parent_id' => $parentId, 'child_id' => $childId, 'operator' => $this->getCurrentUser()['id'] ?? 0 ]); return true; } /** * 获取学生统计信息 * @return array */ public function getStudentStatistics(): array { $totalStudents = Student::students()->count(); $totalParents = Student::parents()->count(); $normalStudents = Student::students()->where('status', Student::STATUS_NORMAL)->count(); $maleStudents = Student::students()->where('sex', Student::SEX_MALE)->count(); $femaleStudents = Student::students()->where('sex', Student::SEX_FEMALE)->count(); return [ 'total_students' => $totalStudents, 'total_parents' => $totalParents, 'normal_students' => $normalStudents, 'male_students' => $maleStudents, 'female_students' => $femaleStudents, 'status_distribution' => [ 'normal' => Student::where('status', Student::STATUS_NORMAL)->count(), 'disabled' => Student::where('status', Student::STATUS_DISABLED)->count(), 'arrears' => Student::where('status', Student::STATUS_ARREARS)->count(), 'inactive' => Student::where('status', Student::STATUS_INACTIVE)->count(), ] ]; } }