|
@@ -126,6 +126,8 @@ export class LearningPageComponent implements OnInit, OnDestroy {
|
|
|
readonly correct = signal(0);
|
|
readonly correct = signal(0);
|
|
|
readonly unknown = signal<Word[]>([]);
|
|
readonly unknown = signal<Word[]>([]);
|
|
|
readonly loading = signal(false);
|
|
readonly loading = signal(false);
|
|
|
|
|
+ readonly calendarLoading = signal(false);
|
|
|
|
|
+ readonly calendarError = signal('');
|
|
|
readonly submitting = signal(false);
|
|
readonly submitting = signal(false);
|
|
|
readonly selectionTotal=signal(0);readonly selectionPage=signal(1);readonly selectionLoading=signal(false);private selectionRequest?:Subscription;
|
|
readonly selectionTotal=signal(0);readonly selectionPage=signal(1);readonly selectionLoading=signal(false);private selectionRequest?:Subscription;
|
|
|
readonly error = signal('');
|
|
readonly error = signal('');
|
|
@@ -247,6 +249,7 @@ export class LearningPageComponent implements OnInit, OnDestroy {
|
|
|
const [year, month, day] = value.split('-').map(Number);
|
|
const [year, month, day] = value.split('-').map(Number);
|
|
|
return new Intl.DateTimeFormat('zh-CN', { month: 'long', day: 'numeric', weekday: 'short' }).format(new Date(year, month - 1, day, 12));
|
|
return new Intl.DateTimeFormat('zh-CN', { month: 'long', day: 'numeric', weekday: 'short' }).format(new Date(year, month - 1, day, 12));
|
|
|
});
|
|
});
|
|
|
|
|
+ readonly memoryTotalCount = computed(() => this.reviewPageData()?.summary.total||0);
|
|
|
readonly memoryCompletedCount = computed(() => this.reviewPageData()?.summary.completed||0);
|
|
readonly memoryCompletedCount = computed(() => this.reviewPageData()?.summary.completed||0);
|
|
|
readonly memoryDueCount = computed(() => this.reviewPageData()?.summary.due||0);
|
|
readonly memoryDueCount = computed(() => this.reviewPageData()?.summary.due||0);
|
|
|
readonly memoryProgress=computed(()=>{const s=this.reviewPageData()?.summary;return s?.total?Math.round(s.completed/s.total*100):0;});
|
|
readonly memoryProgress=computed(()=>{const s=this.reviewPageData()?.summary;return s?.total?Math.round(s.completed/s.total*100):0;});
|
|
@@ -265,6 +268,7 @@ export class LearningPageComponent implements OnInit, OnDestroy {
|
|
|
private readonly wordPreviewPageSize = 30;
|
|
private readonly wordPreviewPageSize = 30;
|
|
|
private examTimer: ReturnType<typeof setInterval> | null = null;
|
|
private examTimer: ReturnType<typeof setInterval> | null = null;
|
|
|
private antiStartedAt = Date.now();
|
|
private antiStartedAt = Date.now();
|
|
|
|
|
+ private calendarRequest?: Subscription;
|
|
|
|
|
|
|
|
ngOnInit(): void {
|
|
ngOnInit(): void {
|
|
|
if (isTeacherLedLearningPath(this.meta.path) && !this.isReadOnlyWordView && !this.isReadOnlySelectionPage && !this.canStartPointReading) {
|
|
if (isTeacherLedLearningPath(this.meta.path) && !this.isReadOnlyWordView && !this.isReadOnlySelectionPage && !this.canStartPointReading) {
|
|
@@ -280,7 +284,7 @@ export class LearningPageComponent implements OnInit, OnDestroy {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
ngOnDestroy(): void {
|
|
ngOnDestroy(): void {
|
|
|
- this.calendarRequestId++;this.selectionRequest?.unsubscribe();
|
|
|
|
|
|
|
+ this.calendarRequestId++;this.calendarRequest?.unsubscribe();this.selectionRequest?.unsubscribe();
|
|
|
this.stopExamTimer();
|
|
this.stopExamTimer();
|
|
|
this.platform.stopAudio();
|
|
this.platform.stopAudio();
|
|
|
}
|
|
}
|
|
@@ -412,7 +416,7 @@ export class LearningPageComponent implements OnInit, OnDestroy {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
if (this.isCalendarPage) {
|
|
if (this.isCalendarPage) {
|
|
|
- this.loadCalendar();
|
|
|
|
|
|
|
+ this.loadCalendar(true);
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
if (this.isAntiForgetPage) {
|
|
if (this.isAntiForgetPage) {
|
|
@@ -956,6 +960,7 @@ export class LearningPageComponent implements OnInit, OnDestroy {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
selectMemoryDay(day: AntiForgetCalendarDay): void {
|
|
selectMemoryDay(day: AntiForgetCalendarDay): void {
|
|
|
|
|
+ if (day.date === this.memorySelectedDate() && day.inCurrentMonth) return;
|
|
|
this.memorySelectedDate.set(day.date);
|
|
this.memorySelectedDate.set(day.date);
|
|
|
this.reviewListPage.set(1);this.loadCalendar();
|
|
this.reviewListPage.set(1);this.loadCalendar();
|
|
|
if (!day.inCurrentMonth) {
|
|
if (!day.inCurrentMonth) {
|
|
@@ -1536,9 +1541,24 @@ export class LearningPageComponent implements OnInit, OnDestroy {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
turnReviewPage(delta:number):void{this.reviewListPage.update(p=>Math.max(1,Math.min(this.reviewPageData()?.page.pageCount||1,p+delta)));this.loadCalendar();}
|
|
turnReviewPage(delta:number):void{this.reviewListPage.update(p=>Math.max(1,Math.min(this.reviewPageData()?.page.pageCount||1,p+delta)));this.loadCalendar();}
|
|
|
- private loadCalendar(): void {
|
|
|
|
|
- const requestId=++this.calendarRequestId;this.loading.set(true);
|
|
|
|
|
- this.api.post<ReviewPage>('app_review_page',{uid:this.session.user()?.userId,studentId:this.memoryStudentId()||undefined,date:this.memorySelectedDate()||this.dateOnly(),page:this.reviewListPage(),pageSize:20}).pipe(finalize(()=>{if(requestId===this.calendarRequestId)this.loading.set(false);})).subscribe({next:({result})=>{if(requestId!==this.calendarRequestId)return;this.reviewPageData.set(result);this.calendarItems.set(result.items);if(!this.memorySelectedDate())this.memorySelectedDate.set(this.dateOnly());},error:(e:ApiError)=>{if(requestId===this.calendarRequestId)this.error.set(e.message);}});
|
|
|
|
|
|
|
+ retryCalendar(): void { this.loadCalendar(); }
|
|
|
|
|
+
|
|
|
|
|
+ private loadCalendar(initial = false): void {
|
|
|
|
|
+ const requestId=++this.calendarRequestId;
|
|
|
|
|
+ this.calendarRequest?.unsubscribe();
|
|
|
|
|
+ this.calendarError.set('');
|
|
|
|
|
+ if (initial) this.loading.set(true); else this.calendarLoading.set(true);
|
|
|
|
|
+ this.calendarRequest = this.api.post<ReviewPage>('app_review_page',{uid:this.session.user()?.userId,studentId:this.memoryStudentId()||undefined,date:this.memorySelectedDate()||this.dateOnly(),page:this.reviewListPage(),pageSize:20}).pipe(finalize(()=>{
|
|
|
|
|
+ if(requestId!==this.calendarRequestId)return;
|
|
|
|
|
+ if(initial)this.loading.set(false);else this.calendarLoading.set(false);
|
|
|
|
|
+ })).subscribe({next:({result})=>{
|
|
|
|
|
+ if(requestId!==this.calendarRequestId)return;
|
|
|
|
|
+ this.reviewPageData.set(result);this.calendarItems.set(result.items);
|
|
|
|
|
+ if(!this.memorySelectedDate())this.memorySelectedDate.set(this.dateOnly());
|
|
|
|
|
+ },error:(e:ApiError)=>{
|
|
|
|
|
+ if(requestId!==this.calendarRequestId)return;
|
|
|
|
|
+ if(initial)this.error.set(e.message);else this.calendarError.set(e.message);
|
|
|
|
|
+ }});
|
|
|
}
|
|
}
|
|
|
private calendarRequestId=0;
|
|
private calendarRequestId=0;
|
|
|
|
|
|
|
@@ -1791,6 +1811,8 @@ export class LearningPageComponent implements OnInit, OnDestroy {
|
|
|
this.wordPreviewPage.set(1);
|
|
this.wordPreviewPage.set(1);
|
|
|
this.wordPreviewTotal.set(0);
|
|
this.wordPreviewTotal.set(0);
|
|
|
this.wordPreviewLoading.set(false);
|
|
this.wordPreviewLoading.set(false);
|
|
|
|
|
+ this.calendarLoading.set(false);
|
|
|
|
|
+ this.calendarError.set('');
|
|
|
this.selected.set(new Set());
|
|
this.selected.set(new Set());
|
|
|
this.selectionRevealed.set(new Set());
|
|
this.selectionRevealed.set(new Set());
|
|
|
this.selectionAssessment.set({});
|
|
this.selectionAssessment.set({});
|