user(); $isTeacher = $currentUser?->isTeacher() ?? false; return $schema->schema([ TextInput::make('student_id') ->label('学生ID') ->disabled() ->hidden(fn (?Student $record) => blank($record)) ->formatStateUsing(fn (?Student $record): string => $record?->student_id ?? ''), TextInput::make('name') ->label('姓名') ->required() ->maxLength(128) ->placeholder('请输入学生姓名') ->autofocus(), TextInput::make('grade') ->label('年级') ->required() ->maxLength(32) ->placeholder('例如:高一、高二'), TextInput::make('class_name') ->label('班级') ->maxLength(64) ->placeholder('例如:1班、2班'), Select::make('teacher_id') ->label('指导老师') ->options(fn () => self::teacherOptionsForCurrentUser()) ->searchable() ->required() ->preload() ->placeholder('请选择指导老师') ->hidden(fn () => $isTeacher), Textarea::make('remark') ->label('备注') ->rows(3) ->placeholder('选填') ->columnSpanFull(), ])->columns(2); } public static function table(Table $table): Table { $currentUser = auth()->user(); return $table ->query( Student::query() ->with(['teacher.user', 'user']) ->when($currentUser?->isTeacher() ?? false, function ($query) use ($currentUser) { // 如果是老师登录,只显示该老师的学生 $teacherId = $currentUser->teacher?->teacher_id; if ($teacherId) { $query->where('teacher_id', $teacherId); } }) ) ->columns([ Tables\Columns\TextColumn::make('student_id') ->label('学生ID') ->badge() ->color('primary') ->copyable() ->copyMessage('学生ID已复制') ->copyMessageDuration(1500) ->sortable() ->searchable(), Tables\Columns\TextColumn::make('name') ->label('姓名') ->weight('bold') ->searchable() ->sortable(), Tables\Columns\TextColumn::make('grade') ->label('年级') ->badge() ->color('success') ->sortable(), Tables\Columns\TextColumn::make('class_name') ->label('班级') ->placeholder('未分配') ->sortable() ->formatStateUsing(fn ($state) => $state ?: '未分配'), Tables\Columns\TextColumn::make('teacher.user.full_name') ->label('指导老师') ->sortable() ->searchable() ->getStateUsing(fn (Student $record) => $record->teacher?->user?->full_name ?? $record->teacher?->name ?? '未分配') ->visible(fn () => !($currentUser?->isTeacher() ?? false)), // 老师登录时不显示老师列 ]) ->filters([ Tables\Filters\SelectFilter::make('grade') ->label('年级') ->options(fn () => self::gradeOptions()) ->placeholder('全部年级'), Tables\Filters\SelectFilter::make('class_name') ->label('班级') ->options(fn () => self::classOptions()) ->placeholder('全部班级'), Tables\Filters\SelectFilter::make('teacher_id') ->label('指导老师') ->options(fn () => self::teacherOptionsForCurrentUser()) ->placeholder('全部老师') ->visible(fn () => !($currentUser?->isTeacher() ?? false)), // 老师登录时隐藏老师筛选 ]) ->actions([]) ->bulkActions([]) ->emptyStateHeading('暂无学生记录') ->emptyStateDescription('开始创建你的第一个学生吧') ->emptyStateActions([]); } public static function getPages(): array { return [ 'index' => Pages\ListStudents::route('/'), 'create' => Pages\CreateStudent::route('/create'), 'view' => Pages\ViewStudent::route('/{record}'), 'edit' => Pages\EditStudent::route('/{record}/edit'), ]; } protected static function teacherOptions(): array { // 使用缓存优化性能,缓存1小时 $options = cache()->remember('teacher_options', 3600, function () { return self::queryTeacherOptions(); }); // 如果缓存因历史关联错误导致为空,自动重建一次 if (empty($options)) { $options = self::queryTeacherOptions(); cache()->put('teacher_options', $options, 3600); } return $options; } protected static function teacherOptionsForCurrentUser(): array { $currentRecordId = request()->route('record') ?? request()->input('record'); $currentStudentTeacher = null; if ($currentRecordId) { $currentStudentTeacher = \App\Models\Student::query() ->select('teacher_id') ->find($currentRecordId); } // 如果是老师登录,只返回自己的选项 if (auth()->user()?->isTeacher() ?? false) { $teacherId = auth()->user()->teacher?->teacher_id; $teacherName = auth()->user()->teacher?->user?->full_name ?? auth()->user()->teacher?->name ?? '当前老师'; if ($teacherId) { return [$teacherId => $teacherName]; } return []; } // 如果是管理员,返回所有老师 $options = self::teacherOptions(); // 确保当前记录的老师在选项里,避免验证器 in 失败 if ($currentStudentTeacher && $currentStudentTeacher->teacher_id && !isset($options[$currentStudentTeacher->teacher_id])) { $fallbackLabel = '老师 ' . $currentStudentTeacher->teacher_id; $options[$currentStudentTeacher->teacher_id] = $fallbackLabel; } return $options; } protected static function gradeOptions(): array { // 使用缓存优化性能,缓存30分钟 return cache()->remember('grade_options', 1800, function () { return Student::query() ->select('grade') ->distinct() ->whereNotNull('grade') ->orderBy('grade') ->pluck('grade', 'grade') ->toArray(); }); } protected static function classOptions(): array { // 使用缓存优化性能,缓存30分钟 return Cache::remember('class_options', 1800, function () { return Student::query() ->select('class_name') ->whereNotNull('class_name') ->where('class_name', '!=', '') ->distinct() ->orderBy('class_name') ->pluck('class_name', 'class_name') ->toArray(); }); } /** * 清除相关缓存 */ public static function clearCaches(): void { Cache::forget('teacher_options'); Cache::forget('grade_options'); Cache::forget('class_options'); } /** * 查询老师选项(解耦缓存,便于复用和自动重建) */ protected static function queryTeacherOptions(): array { $byRole = Teacher::with(['user' => function ($query) { $query->select('user_id', 'full_name', 'role'); }]) ->whereHas('user', function ($query) { $query->where('role', 'teacher'); }) ->select('teacher_id', 'user_id', 'name') ->get() ->map(function ($teacher) { return [ 'id' => $teacher->teacher_id, 'name' => $teacher->user->full_name ?? $teacher->name ?? $teacher->teacher_id, ]; }) ->pluck('name', 'id') ->toArray(); if (!empty($byRole)) { return $byRole; } // 兜底:直接列出 teachers 表的记录,避免选项为空导致 in 校验报错 return Teacher::query() ->select('teacher_id', 'name') ->get() ->mapWithKeys(function ($teacher) { $label = $teacher->name ?: ('老师 ' . $teacher->teacher_id); return [$teacher->teacher_id => $label]; }) ->toArray(); } /** * 在保存前自动设置老师ID */ public static function beforeSave(): void { $currentUser = auth()->user(); if ($currentUser?->isTeacher() ?? false) { // 如果是老师,自动设置老师ID request()->merge(['teacher_id' => $currentUser->teacher?->teacher_id]); } } }