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

Count wordbook completion after second study

彭峰 1 день назад
Родитель
Сommit
a0ecfedbba

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

@@ -458,7 +458,7 @@ describe('home learning modules', () => {
     spyOn(api, 'get').and.callFake((action, params) => action === 'e_words_list'
       ? of({ retcode: 1, result: params?.['learningStatus'] === 'completed'
         ? [{ GeneralID: 602, Title: 'prepare@张雅茜', xxcs: 2, detail: [{ GeneralID: 702, Title: 'prepare', sy: '准备' }] }]
-        : [{ GeneralID: 601, Title: 'tend@张雅茜', xxcs: 0, detail: [{ GeneralID: 701, Title: 'tend', sy: '照顾' }] }],
+        : [{ GeneralID: 601, Title: 'tend@张雅茜', xxcs: 1, detail: [{ GeneralID: 701, Title: 'tend', sy: '照顾' }] }],
         page: { itemCount: 1, pendingCount: 1, completedCount: 1, pageCount: 1, pageIndex: 1, pageSize: 30 } } as ApiEnvelope<any>)
       : get(action, params));
     const harness = await RouterTestingHarness.create();
@@ -484,8 +484,8 @@ describe('home learning modules', () => {
   it('shows 30 wordbook words per page while counting every learning status', async () => {
     const api = TestBed.inject(ApiService) as unknown as LearningModulesApiService;
     const get = api.get.bind(api);
-    const pending = Array.from({ length: 65 }, (_, index) => ({ GeneralID: 601 + index, xxcs: 0, detail: [{ GeneralID: 701 + index, Title: `pending-${index + 1}` }] }));
-    const completed = Array.from({ length: 7 }, (_, index) => ({ GeneralID: 801 + index, xxcs: 1, detail: [{ GeneralID: 901 + index, Title: `completed-${index + 1}` }] }));
+    const pending = Array.from({ length: 65 }, (_, index) => ({ GeneralID: 601 + index, xxcs: 1, detail: [{ GeneralID: 701 + index, Title: `pending-${index + 1}` }] }));
+    const completed = Array.from({ length: 7 }, (_, index) => ({ GeneralID: 801 + index, xxcs: 2, detail: [{ GeneralID: 901 + index, Title: `completed-${index + 1}` }] }));
     const requests: Record<string, unknown>[] = [];
     spyOn(api, 'get').and.callFake((action, params) => {
       if (action !== 'e_words_list') return get(action, params);
@@ -524,7 +524,7 @@ describe('home learning modules', () => {
     const get = api.get.bind(api);
     const all = Array.from({ length: 139 }, (_, index) => ({
       GeneralID: 601 + index,
-      xxcs: index < 45 ? 1 : 0,
+      xxcs: 1,
       detail: [{ GeneralID: 701 + index, Title: `word-${index + 1}` }],
     }));
     const requests: Record<string, unknown>[] = [];
@@ -543,17 +543,17 @@ describe('home learning modules', () => {
     expect(requests.length).toBe(2);
     expect(requests[0]).toEqual(jasmine.objectContaining({ learningStatus: 'pending', psize: 30 }));
     expect(requests[1]).toEqual(jasmine.objectContaining({ cpage: 1, psize: 500 }));
-    expect(view().querySelectorAll('.word-selection-tabs b')[0].textContent).toContain('94');
-    expect(view().querySelectorAll('.word-selection-tabs b')[1].textContent).toContain('45');
+    expect(view().querySelectorAll('.word-selection-tabs b')[0].textContent).toContain('139');
+    expect(view().querySelectorAll('.word-selection-tabs b')[1].textContent).toContain('0');
     expect(view().querySelectorAll('.pending-column .word-select-list > button').length).toBe(30);
-    expect(view().querySelector('.mobile-pagination')?.textContent).toContain('第 1 / 4 页 · 共 94 个单词');
+    expect(view().querySelector('.pending-column .word-select-list > button')?.textContent).toContain('word-1');
+    expect(view().querySelector('.mobile-pagination')?.textContent).toContain('第 1 / 5 页 · 共 139 个单词');
     (view().querySelectorAll('.mobile-pagination button')[1] as HTMLButtonElement).click();
     harness.fixture.detectChanges();
-    expect(view().querySelector('.mobile-pagination')?.textContent).toContain('第 2 / 4 页');
+    expect(view().querySelector('.mobile-pagination')?.textContent).toContain('第 2 / 5 页');
     (view().querySelectorAll('.word-selection-tabs button')[1] as HTMLButtonElement).click();
     harness.fixture.detectChanges();
-    expect(view().querySelectorAll('.completed-column .word-select-list > button').length).toBe(30);
-    expect(view().querySelector('.mobile-pagination')?.textContent).toContain('第 1 / 2 页 · 共 45 个单词');
+    expect(view().querySelectorAll('.completed-column .word-select-list > button').length).toBe(0);
     expect(requests.length).toBe(2);
   });
 
@@ -568,8 +568,8 @@ describe('home learning modules', () => {
     const get = api.get.bind(api);
     spyOn(api, 'get').and.callFake((action, params) => action === 'e_words_list'
       ? of({ retcode: 1, result: api.lastLearningWordUpdate['save'] === 1 && params?.['learningStatus'] === 'completed'
-        ? [{ GeneralID: 601, Title: 'tend@张雅茜', xxcs: 1, detail: [word] }]
-        : api.lastLearningWordUpdate['save'] === 1 ? [] : [{ GeneralID: 601, Title: 'tend@张雅茜', xxcs: 0, detail: [word] }],
+        ? [{ GeneralID: 601, Title: 'tend@张雅茜', xxcs: 2, detail: [word] }]
+        : api.lastLearningWordUpdate['save'] === 1 ? [] : [{ GeneralID: 601, Title: 'tend@张雅茜', xxcs: 1, detail: [word] }],
         page: { itemCount: params?.['learningStatus'] === 'completed' ? 1 : api.lastLearningWordUpdate['save'] === 1 ? 0 : 1,
           pendingCount: api.lastLearningWordUpdate['save'] === 1 ? 0 : 1, completedCount: api.lastLearningWordUpdate['save'] === 1 ? 1 : 0,
           pageCount: 1, pageIndex: 1, pageSize: 30 } } as ApiEnvelope<any>)

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

@@ -590,7 +590,7 @@ export class LearningPageComponent implements OnInit, OnDestroy {
   }
 
   newWordLearned(word: Word): boolean {
-    return Number(word['xxcs'] ?? 0) > 0 || this.wordHistoricallyLearned(word);
+    return Number(word['xxcs'] ?? 0) >= 2;
   }
 
   selectionWordCompleted(word: Word): boolean {

+ 1 - 1
scripts/deploy-admin-functions.mjs

@@ -2595,7 +2595,7 @@ async function newWordPage(input, current) {
   const values = [DEFAULT_COMPANY_ID, String(uid)];
   const from = ' FROM "PracticeRecord" p JOIN "CommonModel" c ON c."company" = $1 AND CAST(c."modelId" AS text) = \'52\' AND CAST(c."generalId" AS text) = CAST(p."scid" AS text)';
   const where = ' WHERE p."company" = $1 AND CAST(p."yhid" AS text) = $2 AND LOWER(CAST(p."jrscb" AS text)) IN (\'1\',\'true\')';
-  const learned = 'CASE WHEN CAST(p."xxcs" AS text) ~ \'^[0-9]+(?:\\.[0-9]+)?$\' THEN CAST(p."xxcs" AS numeric) ELSE 0 END > 0';
+  const learned = 'CASE WHEN CAST(p."xxcs" AS text) ~ \'^[0-9]+(?:\\.[0-9]+)?$\' THEN CAST(p."xxcs" AS numeric) ELSE 0 END >= 2';
   const countRow = await Psql.one('SELECT COUNT(*) FILTER (WHERE NOT (' + learned + '))::int AS "pendingCount", COUNT(*) FILTER (WHERE ' + learned + ')::int AS "completedCount"' + from + where, values);
   const filter = status ? ' AND ' + (status === 'completed' ? learned : 'NOT (' + learned + ')') : '';
   const rows = await Psql.query('SELECT p.*, pc."generalId" AS "__practiceGeneralId", c.*, row_to_json(v) AS "__addon"' + from + ' LEFT JOIN "VocabularyWord" v ON v."company" = $1 AND CAST(v."id" AS text) = CAST(c."itemId" AS text) LEFT JOIN "CommonModel" pc ON pc."company" = $1 AND CAST(pc."modelId" AS text) = \'53\' AND CAST(pc."itemId" AS text) = CAST(p."id" AS text)' + where + filter + ' ORDER BY p."updatedAt" DESC, p."id" DESC LIMIT $3 OFFSET $4', values.concat([paging.size, (paging.index - 1) * paging.size]));