Răsfoiți Sursa

fix(mobile): allow vocabulary repeats by individual word progress

彭峰 5 zile în urmă
părinte
comite
b554db601a

+ 12 - 8
projects/xiaoshu-mobile/src/app/core/home-learning-modules.integration.spec.ts

@@ -891,7 +891,7 @@ describe('home learning modules', () => {
     expect(play.calls.argsFor(1)[0]).toContain('apple.mp3');
   });
 
-  it('offers four course passes, gates repeats by the whole book and keeps first-pass progress at 100%', async () => {
+  it('allows second and third passes per word before the whole book is finished and stops selection after three passes', async () => {
     user.set({userId:300,groupId:3});session.groupId.set(3);session.student.set({userId:100,groupId:1});
     const api=TestBed.inject(ApiService) as unknown as LearningModulesApiService;
     api.courseWords=[{GeneralID:1001,NodeID:811,Title:'apple',w_learned:1},{GeneralID:1002,NodeID:811,Title:'banana',w_learned:2},{GeneralID:1003,NodeID:811,Title:'pear',w_learned:3}];
@@ -902,21 +902,23 @@ describe('home learning modules', () => {
     harness.fixture.detectChanges();
     expect(harness.routeNativeElement!.querySelectorAll('.course-pass-tabs button').length).toBe(4);
     tab(1).click();harness.fixture.detectChanges();
-    expect(harness.routeNativeElement!.querySelector('.word-select-check')).toBeNull();
+    expect(harness.routeNativeElement!.querySelector('.word-select-check')).not.toBeNull();
+    expect(harness.routeNativeElement!.textContent).toContain('选择单词开始第二遍学习');
     expect(learning().firstPassProgress()).toBe(75);
-    api.courseBookCounts=[0,1,1,1];tab(0).click();tab(1).click();harness.fixture.detectChanges();
-    expect(learning().firstPassProgress()).toBe(100);
     const select=harness.routeNativeElement!.querySelector('.word-select-check') as HTMLButtonElement;
     select.click();harness.fixture.detectChanges();
     expect(learning().selected().size).toBe(1);
     tab(2).click();harness.fixture.detectChanges();
-    expect(harness.routeNativeElement!.querySelector('.word-select-check')).toBeNull();
-    api.courseBookCounts=[0,0,2,1];tab(1).click();tab(2).click();harness.fixture.detectChanges();
-    expect(harness.routeNativeElement!.querySelector('.word-select-check')).not.toBeNull();
+    const secondPass=harness.routeNativeElement!.querySelector('.word-select-check') as HTMLButtonElement;
+    expect(secondPass).not.toBeNull();
+    secondPass.click();harness.fixture.detectChanges();
+    expect(learning().selected().size).toBe(2);
+    secondPass.click();harness.fixture.detectChanges();
+    expect(learning().selected().size).toBe(1);
     tab(3).click();harness.fixture.detectChanges();
     expect(harness.routeNativeElement!.textContent).toContain('已完成三遍学习');
     expect(harness.routeNativeElement!.querySelector('.word-select-check')).toBeNull();
-    expect(learning().firstPassProgress()).toBe(100);
+    expect(learning().firstPassProgress()).toBe(75);
     // Selecting a learned word must actually enter the regular learning flow.
     tab(1).click();harness.fixture.detectChanges();
     (harness.routeNativeElement!.querySelector('.selection-header .primary-button') as HTMLButtonElement).click();
@@ -944,6 +946,8 @@ describe('home learning modules', () => {
     tab(3).click();harness.fixture.detectChanges();
     expect(learning().words().find(word=>word.word==='apple')?.['w_learned']).toBe(3);
     expect(harness.routeNativeElement!.querySelector('.word-select-check')).toBeNull();
+    expect(learning().firstPassProgress()).toBe(75);
+    api.courseBookCounts=[0,0,1,3];tab(0).click();tab(3).click();harness.fixture.detectChanges();
     expect(learning().firstPassProgress()).toBe(100);
   },30000);
 

+ 1 - 6
projects/xiaoshu-mobile/src/app/features/learning/learning-page.component.ts

@@ -652,18 +652,13 @@ export class LearningPageComponent implements OnInit, OnDestroy {
   }
 
   canRelearnCourseWord(word: Word): boolean {
-    const pass = this.courseWordPass(word);
-    const counts = this.bookPassCounts();
-    return !this.isReadOnlySelectionPage && !!counts && pass < 3
-      && (pass === 0 || counts.slice(0, pass).every(count => count === 0));
+    return !this.isReadOnlySelectionPage && this.courseWordPass(word) < 3;
   }
 
   get coursePassHint(): string {
     const pass = this.coursePass();
     if (pass === 0) return this.isReadOnlySelectionPage ? '这些单词尚未完成第一遍学习,点击可查看释义。' : '先回忆中文,核对后选择“认识”或“加入学习”。';
     if (pass === 3) return '这些单词已完成三遍学习,可查看和听读音。';
-    if (!this.bookPassCounts()) return '正在读取整本学习进度,读取完成后可继续学习。';
-    if (this.bookPassCounts()!.slice(0, pass).some(count => count > 0)) return `整本单词完成第${pass === 1 ? '一' : '二'}遍后,可从这里选择单词继续学习。`;
     return this.isReadOnlySelectionPage ? `这些单词已学${pass}遍,可由老师选词继续学习。` : `选择单词开始第${pass === 1 ? '二' : '三'}遍学习。`;
   }