Просмотр исходного кода

fix(mobile): disable audio in student vocabulary preview

彭峰 2 недель назад
Родитель
Сommit
98fda8ac6a

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

@@ -294,6 +294,55 @@ describe('home learning modules', () => {
     });
   });
 
+  it('silently reveals pending and completed words opened from student learning content', async () => {
+    const play = spyOn(TestBed.inject(PlatformService), 'play');
+    const harness = await RouterTestingHarness.create();
+    await harness.navigateByUrl('/pages/his/his');
+    (harness.routeNativeElement?.querySelector('.current-learning-list button') as HTMLButtonElement).click();
+    await harness.fixture.whenStable();
+    harness.fixture.detectChanges();
+    (harness.routeNativeElement?.querySelector('.node-list button') as HTMLButtonElement).click();
+    await harness.fixture.whenStable();
+    harness.fixture.detectChanges();
+
+    expect(TestBed.inject(Router).url).toContain('readonly=1');
+    const learning = harness.fixture.debugElement.query(By.directive(LearningPageComponent)).componentInstance as LearningPageComponent;
+    for (const [index, meaning] of ['n. 香蕉', 'n. 苹果'].entries()) {
+      (harness.routeNativeElement?.querySelectorAll('.word-selection-tabs button')[index] as HTMLButtonElement).click();
+      harness.fixture.detectChanges();
+      expect(harness.routeNativeElement?.querySelector('.audio')).toBeNull();
+      expect(harness.routeNativeElement?.textContent).not.toContain('读音');
+      const word = harness.routeNativeElement?.querySelector('.word-reveal') as HTMLButtonElement;
+      word.click();
+      harness.fixture.detectChanges();
+      expect(word.textContent).toContain(meaning);
+      expect(word.getAttribute('aria-expanded')).toBe('true');
+      word.click();
+      harness.fixture.detectChanges();
+      expect(word.getAttribute('aria-expanded')).toBe('false');
+    }
+    learning.words().forEach((word) => learning.play(word));
+    expect(play).not.toHaveBeenCalled();
+  });
+
+  it('still pronounces pending and completed words when a coach reveals them', async () => {
+    user.set({ userId: 300, userName: 'coach', honeyName: '张老师', groupId: 3 });
+    session.groupId.set(3);
+    session.student.set({ userId: 100, userName: 'student', groupId: 1 });
+    const play = spyOn(TestBed.inject(PlatformService), 'play');
+    const harness = await RouterTestingHarness.create();
+    await harness.navigateByUrl('/pages/stu/stu_abc?nids=811,812&pnid=801');
+    for (const index of [0, 1]) {
+      (harness.routeNativeElement?.querySelectorAll('.word-selection-tabs button')[index] as HTMLButtonElement).click();
+      harness.fixture.detectChanges();
+      expect(harness.routeNativeElement?.querySelector('.audio')).not.toBeNull();
+      (harness.routeNativeElement?.querySelector('.word-reveal') as HTMLButtonElement).click();
+    }
+    expect(play).toHaveBeenCalledTimes(2);
+    expect(play.calls.argsFor(0)[0]).toContain('banana.mp3');
+    expect(play.calls.argsFor(1)[0]).toContain('apple.mp3');
+  });
+
   it('shows named schedule students below the trigger and closes after selection or Escape', async () => {
     user.set({userId:300,userName:'coach',honeyName:'张老师',groupId:3});
     const harness=await RouterTestingHarness.create();

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

@@ -119,7 +119,7 @@
 
         @if (activeSelectionBucket() === 'pending') {
           <section class="word-selection-list pending-column" role="tabpanel" aria-label="还没学的单词">
-            <p class="word-column-help">{{ isReadOnlySelectionPage ? '这些单词尚未完成学习,可点击单词查看释义和读音。' : '先回忆中文,核对后选择“认识”或“加入学习”。' }}</p>
+            <p class="word-column-help">{{ isReadOnlySelectionPage ? '这些单词尚未完成学习,可点击单词查看释义。' : '先回忆中文,核对后选择“认识”或“加入学习”。' }}</p>
             <div class="word-select-list">
               @for (word of pendingSelectionWords(); track word.id) {
                 <article class="word-refine-item" [class.selected]="selected().has(word.id)">
@@ -133,9 +133,9 @@
                     }
                     <button type="button" class="word-reveal" [attr.aria-expanded]="selectionWordRevealed(word)" (click)="revealSelectionWord(word)">
                       <strong>{{ word.word }}</strong>
-                      <small [class.revealed]="selectionWordRevealed(word)">{{ selectionWordRevealed(word) ? (word.meaning || '暂无释义') : '先说出中文意思,再点击核对' }}</small>
+                      <small [class.revealed]="selectionWordRevealed(word)">{{ selectionWordRevealed(word) ? (word.meaning || '暂无释义') : isReadOnlySelectionPage ? '点击查看释义' : '先说出中文意思,再点击核对' }}</small>
                     </button>
-                    <span class="audio" aria-hidden="true"><lucide-icon [img]="icons.Volume2" [size]="18" /></span>
+                    @if (!isReadOnlySelectionPage) { <span class="audio" aria-hidden="true"><lucide-icon [img]="icons.Volume2" [size]="18" /></span> }
                   </div>
                   @if (selectionWordRevealed(word) && !isReadOnlySelectionPage) {
                     <div class="word-assessment">
@@ -162,7 +162,7 @@
                       <strong>{{ word.word }}</strong>
                       <small [class.revealed]="selectionWordRevealed(word)">{{ selectionWordRevealed(word) ? (word.meaning || '暂无释义') : selectionCompletionLabel(word) + ' · 点击查看释义' }}</small>
                     </button>
-                    <span class="audio" aria-hidden="true"><lucide-icon [img]="icons.Volume2" [size]="18" /></span>
+                    @if (!isReadOnlySelectionPage) { <span class="audio" aria-hidden="true"><lucide-icon [img]="icons.Volume2" [size]="18" /></span> }
                   </div>
                   @if (!wordHistoricallyLearned(word)) {
                     <div class="completed-word-action">

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

@@ -625,6 +625,7 @@ export class LearningPageComponent implements OnInit, OnDestroy {
   }
 
   play(word = this.current()): void {
+    if (this.isReadOnlySelectionPage || this.isReadOnlyWordView) return;
     if (!word?.audio) {
       this.platform.toast('该单词暂无音频', 'error');
       return;