فهرست منبع

fix(mobile): provide skip controls for every word practice stage

彭峰 5 روز پیش
والد
کامیت
cfec1a3508

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

@@ -845,7 +845,7 @@ describe('home learning modules', () => {
     expect(learning().words().length).toBe(2);
     expect(learning().currentIndex()).toBe(0);
     const skip = Array.from(harness.routeNativeElement?.querySelectorAll<HTMLButtonElement>('.skippable-spelling-actions button') ?? [])
-      .find((button) => button.textContent?.includes('跳到下一关'))!;
+      .find((button) => button.textContent?.includes('跳过这一关'))!;
     skip.click();
     await harness.fixture.whenStable();
     harness.fixture.detectChanges();
@@ -1498,7 +1498,7 @@ describe('home learning modules', () => {
     harness.fixture.detectChanges();
     const spellingActions = harness.routeNativeElement?.querySelector('.teacher-spelling-actions') as HTMLElement;
     expect(spellingActions.querySelectorAll('button').length).toBe(3);
-    expect(spellingActions.textContent).toContain('跳到下一关');
+    expect(spellingActions.textContent).toContain('跳过这一关');
     expect((harness.fixture.debugElement.query(By.directive(LearningPageComponent)).componentInstance as LearningPageComponent).words().length).toBe(1);
     expect(localStorage.getItem('xiaoshu.learning.300.100.701._page_word_orilist')).not.toBeNull();
     (spellingActions.querySelectorAll('button')[1] as HTMLButtonElement).click();
@@ -1735,23 +1735,29 @@ describe('home learning modules', () => {
     await harness.fixture.whenStable();
     harness.fixture.detectChanges();
     const learning = () => harness.fixture.debugElement.query(By.directive(LearningPageComponent)).componentInstance as LearningPageComponent;
-    learning().skipStudyList();
+    const skipStage = () => {
+      const button = Array.from(harness.routeNativeElement?.querySelectorAll<HTMLButtonElement>('.sticky-actions button') ?? [])
+        .find(item => item.textContent?.includes('跳过这一关'));
+      expect(button).toBeDefined();
+      button!.click();
+    };
+    skipStage();
     await harness.fixture.whenStable();
     harness.fixture.detectChanges();
     expect(router.url).toContain('/pages/stu/stu3');
-    const pair = learning().words()[0];
-    learning().chooseMatch('left', pair);
-    learning().chooseMatch('right', pair);
-    learning().continueAfterStage();
+    expect(learning().matchLeft().length).toBe(1);
+    skipStage();
     await harness.fixture.whenStable();
     harness.fixture.detectChanges();
     expect(router.url).toContain('/pages/stu/stu4');
-    learning().chooseMeaning(learning().words()[0]);
-    learning().continueAfterStage();
+    expect(learning().correct()).toBe(0);
+    skipStage();
     await harness.fixture.whenStable();
     harness.fixture.detectChanges();
     expect(router.url).toContain('/pages/stu/pl_stu5');
-    learning().skipSpellingStage();
+    expect(router.url).toContain('orderId=901');
+    expect(learning().correct()).toBe(0);
+    skipStage();
     expect(learning().hasNextWordBatch).toBeFalse();
     await harness.fixture.whenStable();
     harness.fixture.detectChanges();

+ 4 - 2
projects/xiaoshu-mobile/src/app/features/learning/learning-page.component.html

@@ -266,7 +266,7 @@
     </div>
     <div class="sticky-actions">
       <button type="button" class="secondary-button" (click)="shuffleStudyWords()"><lucide-icon [img]="icons.RefreshCw" [size]="18" />再次乱序</button>
-      <button type="button" class="primary-button" (click)="skipStudyList()">跳到下一关<lucide-icon [img]="icons.ChevronRight" [size]="18" /></button>
+      <button type="button" class="primary-button" (click)="skipStudyList()">跳过这一关<lucide-icon [img]="icons.ChevronRight" [size]="18" /></button>
     </div>
   } @else if (isMatchingPage) {
     @if (completed()) {
@@ -285,6 +285,7 @@
           }
         </div>
       </div>
+      <div class="sticky-actions single"><button type="button" class="secondary-button" (click)="skipPracticeStage()">跳过这一关</button></div>
     }
   } @else if (isListeningPage) {
     @if (completed()) {
@@ -307,6 +308,7 @@
           }
         </div>
       }
+      <div class="sticky-actions single"><button type="button" class="secondary-button" (click)="skipPracticeStage()">跳过这一关</button></div>
     }
   } @else if (isSpellingPage) {
     @if (completed()) {
@@ -326,7 +328,7 @@
         </article>
         <div class="sticky-actions" [class.teacher-spelling-actions]="meta.path === 'pages/stu/pl_stu5'" [class.skippable-spelling-actions]="canSkipSpellingStage" [style.grid-template-columns]="canSkipSpellingStage ? 'repeat(3,minmax(0,1fr))' : null">
           <button type="button" class="secondary-button" (click)="resetSpelling()"><lucide-icon [img]="icons.RotateCcw" [size]="18" />重拼</button>
-          @if (canSkipSpellingStage) { <button type="button" class="secondary-button" (click)="skipSpellingStage()">跳到下一关</button> }
+          @if (canSkipSpellingStage) { <button type="button" class="secondary-button" (click)="skipSpellingStage()">跳过这一关</button> }
           <button type="button" class="primary-button" [disabled]="!spellingCorrect()" (click)="nextSpellingWord()">{{ currentIndex() === words().length - 1 ? '完成本关' : '下一个' }}<lucide-icon [img]="icons.ChevronRight" [size]="18" /></button>
         </div>
       }

+ 7 - 2
projects/xiaoshu-mobile/src/app/features/learning/learning-page.component.ts

@@ -410,8 +410,7 @@ export class LearningPageComponent implements OnInit, OnDestroy {
   }
 
   get canSkipSpellingStage(): boolean {
-    return this.meta.path === 'pages/stu/pl_stu5'
-      || (this.meta.path === 'pages/stu/stu5' && this.isNewWordSelfStudyStage);
+    return this.isSpellingPage && (this.canStartPointReading || this.isNewWordSelfStudyStage);
   }
 
   get hasNextWordBatch(): boolean {
@@ -854,6 +853,12 @@ export class LearningPageComponent implements OnInit, OnDestroy {
     this.play();
   }
 
+  skipPracticeStage(): void {
+    if ((!this.isMatchingPage && !this.isListeningPage) || this.completed() || this.submitting()) return;
+    this.completed.set(true);
+    this.continueAfterStage();
+  }
+
   skipSpellingStage(): void {
     if (!this.canSkipSpellingStage || this.completed() || this.submitting()) return;
     this.storageSet('skip_spelling_stage', true);