|
|
@@ -1,5 +1,5 @@
|
|
|
import { CommonModule } from '@angular/common';
|
|
|
-import { ChangeDetectionStrategy, Component, computed, inject, OnDestroy, OnInit, signal } from '@angular/core';
|
|
|
+import { ChangeDetectionStrategy, Component, computed, ElementRef, HostListener, inject, OnDestroy, OnInit, signal } from '@angular/core';
|
|
|
import { FormsModule } from '@angular/forms';
|
|
|
import { ActivatedRoute, Router } from '@angular/router';
|
|
|
import { AlertCircle, BarChart3, BookOpen, CalendarDays, ChevronRight, GraduationCap, LoaderCircle, LucideAngularModule, Search, X } from 'lucide-angular';
|
|
|
@@ -67,13 +67,33 @@ export class CourseCenterPageComponent implements OnInit, OnDestroy {
|
|
|
readonly scheduleRange = signal<ScheduleRange>('day');
|
|
|
readonly selectedDate = signal(this.today());
|
|
|
readonly selectedStudent = signal('all');
|
|
|
+ readonly studentMenuOpen = signal(false);
|
|
|
+ private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);
|
|
|
+ readonly allStudentCount = computed(() => this.studentOptions().reduce((sum, student) => sum + student.count, 0));
|
|
|
+ readonly studentFilterLabel = computed(() => {
|
|
|
+ const student = this.studentOptions().find(item => item.id === this.selectedStudent());
|
|
|
+ return student ? `${student.name}(${student.count})` : `全部学员(${this.allStudentCount()})`;
|
|
|
+ });
|
|
|
+
|
|
|
+ @HostListener('document:click', ['$event'])
|
|
|
+ closeStudentMenuOutside(event: MouseEvent): void {
|
|
|
+ if (!(event.target instanceof Node) || !this.host.nativeElement.querySelector('.student-filter')?.contains(event.target)) this.studentMenuOpen.set(false);
|
|
|
+ }
|
|
|
+
|
|
|
+ @HostListener('document:keydown.escape')
|
|
|
+ closeStudentMenu(): void {
|
|
|
+ if (!this.studentMenuOpen()) return;
|
|
|
+ this.studentMenuOpen.set(false);
|
|
|
+ this.host.nativeElement.querySelector<HTMLButtonElement>('.student-filter-trigger')?.focus();
|
|
|
+ }
|
|
|
+
|
|
|
readonly historyMonth = signal('all');
|
|
|
readonly historyStudentQuery = signal('');
|
|
|
readonly calendarMonth = signal(this.firstOfMonth(new Date()));
|
|
|
readonly now = signal(Date.now());
|
|
|
readonly loading = signal(false);
|
|
|
readonly error = signal('');
|
|
|
- readonly studentOptions = computed(() => this.serverStudents());
|
|
|
+ readonly studentOptions = computed(() => this.serverStudents().map(student => ({...student, id: String(student.id), name: String(student.name || '').trim() || `学员 ${student.id}`})));
|
|
|
readonly historyMonthOptions = computed(() => this.buildHistoryMonthOptions());
|
|
|
readonly historyFilterActive = computed(() => this.historyMonth() !== 'all' || Boolean(this.historyStudentQuery().trim()));
|
|
|
readonly scopedSchedules = computed(() => this.schedules().filter((item) => this.matchesStudent(item)));
|
|
|
@@ -233,6 +253,8 @@ export class CourseCenterPageComponent implements OnInit, OnDestroy {
|
|
|
}
|
|
|
|
|
|
setStudentFilter(value: string): void {
|
|
|
+ this.studentMenuOpen.set(false);
|
|
|
+ this.host.nativeElement.querySelector<HTMLButtonElement>('.student-filter-trigger')?.focus();
|
|
|
this.selectedStudent.set(value || 'all');
|
|
|
this.load();
|
|
|
this.syncScheduleState();
|