afterStateUpdated(function (TeacherStudentSelector $component, string|int|null $state) { // 当老师选择变化时,清空学生选择并更新学生选项 if ($this->isTeacherField()) { $component->getContainer()->getComponent('student_id')->state(''); } }); // 初始化老师选项 $this->loadTeacherOptions(); } protected function isTeacherField(): bool { return $this->getName() === 'teacher_id'; } protected function loadTeacherOptions(): void { try { $teachers = Teacher::query() ->leftJoin('users as u', 'teachers.teacher_id', '=', 'u.user_id') ->select( 'teachers.teacher_id', 'teachers.name', 'teachers.subject', 'u.username', 'u.email' ) ->orderBy('teachers.name') ->get(); // 检查是否有学生没有对应的老师记录 $teacherIds = $teachers->pluck('teacher_id')->toArray(); $missingTeacherIds = Student::query() ->distinct() ->whereNotIn('teacher_id', $teacherIds) ->pluck('teacher_id') ->toArray(); $teachersArray = $teachers->all(); if (!empty($missingTeacherIds)) { foreach ($missingTeacherIds as $missingId) { $teachersArray[] = (object) [ 'teacher_id' => $missingId, 'name' => '未知老师 (' . $missingId . ')', 'subject' => '未知', 'username' => null, 'email' => null ]; } usort($teachersArray, function($a, $b) { return strcmp($a->name, $b->name); }); } $this->teacherOptions = collect($teachersArray)->mapWithKeys(function ($teacher) { return [ $teacher->teacher_id => trim($teacher->name . ($teacher->subject ? " ({$teacher->subject})" : '')) ]; })->toArray(); } catch (\Exception $e) { \Illuminate\Support\Facades\Log::error('加载老师列表失败', [ 'error' => $e->getMessage() ]); $this->teacherOptions = []; } } protected function loadStudentOptions(?string $teacherId = null): array { if (empty($teacherId)) { return []; } try { return Student::query() ->leftJoin('users as u', 'students.student_id', '=', 'u.user_id') ->where('students.teacher_id', $teacherId) ->select( 'students.student_id', 'students.name', 'students.grade', 'students.class_name', 'u.username', 'u.email' ) ->orderBy('students.grade') ->orderBy('students.class_name') ->orderBy('students.name') ->get() ->mapWithKeys(function ($student) { return [ $student->student_id => trim($student->name . " ({$student->grade} - {$student->class_name})") ]; }) ->toArray(); } catch (\Exception $e) { \Illuminate\Support\Facades\Log::error('加载学生列表失败', [ 'teacher_id' => $teacherId, 'error' => $e->getMessage() ]); return []; } } public function teacherOptions(array $options): static { $this->teacherOptions = $options; return $this; } public function studentOptions(array $options): static { $this->studentOptions = $options; return $this; } public function required(bool $condition = true): static { $this->required = $condition; return $this; } public function enableTeacherFilter(bool $condition = true): static { $this->enableTeacherFilter = $condition; return $this; } public function teacherLabel(string $label): static { $this->teacherLabel = $label; return $this; } public function studentLabel(string $label): static { $this->studentLabel = $label; return $this; } public function teacherPlaceholder(string $placeholder): static { $this->teacherPlaceholder = $placeholder; return $this; } public function studentPlaceholder(string $placeholder): static { $this->studentPlaceholder = $placeholder; return $this; } public function teacherHelperText(?string $text): static { $this->teacherHelperText = $text; return $this; } public function studentHelperText(?string $text): static { $this->studentHelperText = $text; return $this; } public function getTeacherOptions(): array { return $this->teacherOptions; } public function getStudentOptions(?string $teacherId = null): array { return $this->enableTeacherFilter ? $this->loadStudentOptions($teacherId) : $this->studentOptions; } public function isRequired(): bool { return $this->required; } public function isTeacherFilterEnabled(): bool { return $this->enableTeacherFilter; } public function getTeacherLabel(): string { return $this->teacherLabel; } public function getStudentLabel(): string { return $this->studentLabel; } public function getTeacherPlaceholder(): string { return $this->teacherPlaceholder; } public function getStudentPlaceholder(): string { return $this->studentPlaceholder; } public function getTeacherHelperText(): ?string { return $this->teacherHelperText; } public function getStudentHelperText(): ?string { return $this->studentHelperText; } public static function make(string $name): static { return new static($name); } }