Bladeren bron

修复部分分页bug

chendeben 7 maanden geleden
bovenliggende
commit
0f57836ea5
2 gewijzigde bestanden met toevoegingen van 218 en 15 verwijderingen
  1. 118 8
      entry/src/main/ets/common/util/MediaTable.ets
  2. 100 7
      entry/src/main/ets/view/LocalMusic.ets

+ 118 - 8
entry/src/main/ets/common/util/MediaTable.ets

@@ -96,6 +96,7 @@ export interface PageQueryResult {
   items: VideoItem[];
   totalCount: number;
   hasMore: boolean;
+  countMap?: Map<string, number>;
 }
 
 export default  class MediaTable {
@@ -605,6 +606,58 @@ export default  class MediaTable {
     });
   }
 
+  /**
+   * 按艺术家查询歌曲列表(用于艺术家详情页)
+   */
+  public async querySongsByArtist(artist: string, sortType?: number): Promise<VideoItem[]> {
+    try {
+      const predicates = new relationalStore.RdbPredicates(RdbUtils.MEDIA_TABLE.tableName);
+      predicates.equalTo(DB_COLUMNS.ARTIST, artist);
+      predicates.equalTo(DB_COLUMNS.TYPE, CommonConstants.TYPE_LOCAL);
+      this.applySortConditions(predicates, sortType);
+
+      return await new Promise((resolve, reject) => {
+        this.accountTable.query(predicates, (resultSet: relationalStore.ResultSet) => {
+          try {
+            const result = this.parseResultSetToVideoItems(resultSet);
+            resolve(result);
+          } catch (err) {
+            reject(err);
+          }
+        });
+      });
+    } catch (err) {
+      Logger.error(`querySongsByArtist error: ${err.code}  - ${err.message}`);
+      return [];
+    }
+  }
+
+  /**
+   * 按专辑查询歌曲列表(用于专辑详情页)
+   */
+  public async querySongsByAlbum(album: string, sortType?: number): Promise<VideoItem[]> {
+    try {
+      const predicates = new relationalStore.RdbPredicates(RdbUtils.MEDIA_TABLE.tableName);
+      predicates.equalTo(DB_COLUMNS.ALBUM, album);
+      predicates.equalTo(DB_COLUMNS.TYPE, CommonConstants.TYPE_LOCAL);
+      this.applySortConditions(predicates, sortType);
+
+      return await new Promise((resolve, reject) => {
+        this.accountTable.query(predicates, (resultSet: relationalStore.ResultSet) => {
+          try {
+            const result = this.parseResultSetToVideoItems(resultSet);
+            resolve(result);
+          } catch (err) {
+            reject(err);
+          }
+        });
+      });
+    } catch (err) {
+      Logger.error(`querySongsByAlbum error: ${err.code}  - ${err.message}`);
+      return [];
+    }
+  }
+
 
 
   // 解析去重列数据(如artist/album)
@@ -1264,35 +1317,60 @@ export default  class MediaTable {
             }
             
             // 排序
-            filteredArtists.sort((a, b) => a.localeCompare(b));
+            let allCountMap: Map<string, number> | undefined = undefined;
+            if (options.sortType === 8 || options.sortType === 9) {
+              allCountMap = new Map<string, number>();
+              for (const artist of filteredArtists) {
+                const count = await this.getCountByColumn(DB_COLUMNS.ARTIST, artist);
+                allCountMap.set(artist, count);
+              }
+              filteredArtists.sort((a, b) => {
+                const countA = allCountMap?.get(a) ?? 0;
+                const countB = allCountMap?.get(b) ?? 0;
+                const diff = options.sortType === 8 ? countA - countB : countB - countA;
+                return diff !== 0 ? diff : a.localeCompare(b);
+              });
+            } else if (options.sortType === 5) {
+              filteredArtists.sort((a, b) => b.localeCompare(a));
+            } else {
+              filteredArtists.sort((a, b) => a.localeCompare(b));
+            }
             
             const totalCount = filteredArtists.length;
             const offset = options.pageIndex * options.pageSize;
             const pagedArtists = filteredArtists.slice(offset, offset + options.pageSize);
             
-            // 为每个艺术家查询第一首歌
+            // 为每个艺术家查询第一首歌,作为封面来源
             const items: VideoItem[] = [];
+            const countMap = new Map<string, number>();
             for (const artist of pagedArtists) {
               const songPredicates = new relationalStore.RdbPredicates(RdbUtils.MEDIA_TABLE.tableName);
               songPredicates.equalTo(DB_COLUMNS.ARTIST, artist);
               songPredicates.limitAs(1);
               
+              let coverPath = '';
               await new Promise<void>((resolveInner) => {
                 this.accountTable.query(songPredicates, (songResultSet: relationalStore.ResultSet) => {
                   if (songResultSet.rowCount > 0) {
                     songResultSet.goToFirstRow();
                     const item = this.buildVideoItem(songResultSet);
-                    items.push(item);
+                    coverPath = item.pixelMapPath ?? '';
                   }
                   songResultSet.close();
                   resolveInner();
                 });
               });
+              const artistSongCount = allCountMap?.get(artist) ?? await this.getCountByColumn(DB_COLUMNS.ARTIST, artist);
+              countMap.set(artist, artistSongCount);
+              const artistItem = new VideoItem(artist, artist, artist, CommonConstants.TYPE_IS_ARTIST, 0, '');
+              artistItem.pixelMapPath = coverPath;
+              artistItem.artist = artist;
+              items.push(artistItem);
             }
             
             const hasMore = (offset + items.length) < totalCount;
             Logger.info('heanup MediaTable', `queryArtistsPaged: 查询完成 items=${items.length}, total=${totalCount}, hasMore=${hasMore}`);
-            resolve({ items, totalCount, hasMore });
+            resolve({ items, totalCount, hasMore, countMap });
           } catch (err) {
             const error = err as Error;
             Logger.error('heanup MediaTable', `queryArtistsPaged error: ${error.message}`);
@@ -1337,35 +1415,60 @@ export default  class MediaTable {
             }
             
             // 排序
-            filteredAlbums.sort((a, b) => a.localeCompare(b));
+            let allCountMap: Map<string, number> | undefined = undefined;
+            if (options.sortType === 8 || options.sortType === 9) {
+              allCountMap = new Map<string, number>();
+              for (const album of filteredAlbums) {
+                const count = await this.getCountByColumn(DB_COLUMNS.ALBUM, album);
+                allCountMap.set(album, count);
+              }
+              filteredAlbums.sort((a, b) => {
+                const countA = allCountMap?.get(a) ?? 0;
+                const countB = allCountMap?.get(b) ?? 0;
+                const diff = options.sortType === 8 ? countA - countB : countB - countA;
+                return diff !== 0 ? diff : a.localeCompare(b);
+              });
+            } else if (options.sortType === 5) {
+              filteredAlbums.sort((a, b) => b.localeCompare(a));
+            } else {
+              filteredAlbums.sort((a, b) => a.localeCompare(b));
+            }
             
             const totalCount = filteredAlbums.length;
             const offset = options.pageIndex * options.pageSize;
             const pagedAlbums = filteredAlbums.slice(offset, offset + options.pageSize);
             
-            // 为每个专辑查询第一首歌
+            // 为每个专辑查询第一首歌,作为封面来源
             const items: VideoItem[] = [];
+            const countMap = new Map<string, number>();
             for (const album of pagedAlbums) {
               const songPredicates = new relationalStore.RdbPredicates(RdbUtils.MEDIA_TABLE.tableName);
               songPredicates.equalTo(DB_COLUMNS.ALBUM, album);
               songPredicates.limitAs(1);
               
+              let coverPath = '';
               await new Promise<void>((resolveInner) => {
                 this.accountTable.query(songPredicates, (songResultSet: relationalStore.ResultSet) => {
                   if (songResultSet.rowCount > 0) {
                     songResultSet.goToFirstRow();
                     const item = this.buildVideoItem(songResultSet);
-                    items.push(item);
+                    coverPath = item.pixelMapPath ?? '';
                   }
                   songResultSet.close();
                   resolveInner();
                 });
               });
+              const albumSongCount = allCountMap?.get(album) ?? await this.getCountByColumn(DB_COLUMNS.ALBUM, album);
+              countMap.set(album, albumSongCount);
+              const albumItem = new VideoItem(album, album, album, CommonConstants.TYPE_IS_ALBUM, 0, '');
+              albumItem.pixelMapPath = coverPath;
+              albumItem.album = album;
+              items.push(albumItem);
             }
             
             const hasMore = (offset + items.length) < totalCount;
             Logger.info('heanup MediaTable', `queryAlbumsPaged: 查询完成 items=${items.length}, total=${totalCount}, hasMore=${hasMore}`);
-            resolve({ items, totalCount, hasMore });
+            resolve({ items, totalCount, hasMore, countMap });
           } catch (err) {
             const error = err as Error;
             Logger.error('heanup MediaTable', `queryAlbumsPaged error: ${error.message}`);
@@ -1380,6 +1483,13 @@ export default  class MediaTable {
     }
   }
 
+  private async getCountByColumn(columnName: string, value: string): Promise<number> {
+    const predicates = new relationalStore.RdbPredicates(RdbUtils.MEDIA_TABLE.tableName);
+    predicates.equalTo(columnName, value);
+    predicates.equalTo(DB_COLUMNS.TYPE, CommonConstants.TYPE_LOCAL);
+    return await this.getTotalCount(predicates);
+  }
+
 }
 
 function generateBucket(item: VideoItem): relationalStore.ValuesBucket {

+ 100 - 7
entry/src/main/ets/view/LocalMusic.ets

@@ -401,8 +401,10 @@ export struct LocalMusic {
   @StorageProp('mediaKuList')  mediaKuList: Array<VideoItem> = []; //媒体库文件
   @State artistList: Array<VideoItem> = []; //艺术家文件
   @State artistMap: Map<string, VideoItem[]> = new Map(); //艺术家Map
+  @State artistSongCountMap: Map<string, number> = new Map();
   @State albumList: Array<VideoItem> = []; //专辑文件
   @State albumMap: Map<string, VideoItem[]> = new Map(); //专辑Map
+  @State albumSongCountMap: Map<string, number> = new Map();
   private mScrollMap: Map<string, number> = new Map(); // 艺术家、专辑名->滚动index
   @State imageOpacities: number[] = [];
   @Consume isCanBack: boolean
@@ -553,7 +555,6 @@ export struct LocalMusic {
 
       case 3:
         this.rightTopImage = $r('sys.symbol.sort')
-        this.updateListData(this.albumList)
         this.titleName = Utility.resourceToString(this.context,$r('app.string.album'))
         break
     }
@@ -1211,6 +1212,11 @@ export struct LocalMusic {
           this.artistList = message.data2; // 只包含前100个艺术家
           const artistTotalCount: number = message.totalCount ?? this.artistList.length;
           this.artistCount = artistTotalCount;
+          const nextArtistCountMap = new Map(this.artistSongCountMap);
+          this.artistMap.forEach((songs, artist) => {
+            nextArtistCountMap.set(artist, songs.length);
+          });
+          this.artistSongCountMap = nextArtistCountMap;
           Logger.info(`heanup 查询艺术家列表 缓存数=${this.artistList.length}, 总数=${artistTotalCount}`)
           PreferencesUtil.putSync('artistCount', artistTotalCount)
 
@@ -1234,6 +1240,11 @@ export struct LocalMusic {
           this.albumList = message.data2
           const albumTotalCount: number = message.totalCount ?? this.albumList.length;
           this.albumCount = albumTotalCount;
+          const nextAlbumCountMap = new Map(this.albumSongCountMap);
+          this.albumMap.forEach((songs, album) => {
+            nextAlbumCountMap.set(album, songs.length);
+          });
+          this.albumSongCountMap = nextAlbumCountMap;
           Logger.info(`heanup 查询专辑列表 缓存数=${this.albumList.length}, 总数=${albumTotalCount}`)
           
           // 专辑模式下重新加载第一页(分页查询)
@@ -4479,13 +4490,13 @@ export struct LocalMusic {
             .margin({ left: 10, right: 20 })
             .fontColor($r('app.color.text_color'))
           Row() {
-            Text(`${this.artistMap.get(item.name)?.length ?? 0}首`)
+            Text(`${this.getArtistSongCount(item.name)}首`)
               .fontSize(this.twoFingerType == 1 ? 11 : this.twoFingerType == 2 ? 12 : 14)
               .padding({ top: 8 })
               .visibility(this.modeType === 2 ? Visibility.Visible : Visibility.None)
               .fontColor($r('app.color.text_color'))
               .margin({ left: 10 })
-            Text(`${this.albumMap.get(item.name)?.length ?? 0}首`)
+            Text(`${this.getAlbumSongCount(item.name)}首`)
               .fontSize(this.twoFingerType == 1 ? 11 : this.twoFingerType == 2 ? 12 : 14)
               .padding({ top: 8 })
               .visibility(this.modeType === 3 ? Visibility.Visible : Visibility.None)
@@ -5143,12 +5154,12 @@ export struct LocalMusic {
                 $r('app.color.text_color'))
 
             Column() {
-              Text(`${this.artistMap.get(item.name)?.length ?? 0}首`)
+              Text(`${this.getArtistSongCount(item.name)}首`)
                 .fontSize(11)
                 .fontSize(this.columns == 4 ||this.columns==3? 10 : this.columns == 2 ? 12 : 14)
                 .visibility(this.modeType === 2 && !this.isCanBack ? Visibility.Visible : Visibility.None)
                 .fontColor($r('app.color.text_color'))
-              Text(`${this.albumMap.get(item.name)?.length ?? 0}首`)
+              Text(`${this.getAlbumSongCount(item.name)}首`)
                 .fontSize(11)
                 .fontSize(this.columns == 4 ||this.columns==3? 10 : this.columns == 2 ? 12 : 14)
                 .visibility(this.modeType === 3 && !this.isCanBack ? Visibility.Visible : Visibility.None)
@@ -5521,12 +5532,12 @@ export struct LocalMusic {
                 $r('app.color.text_color'))
 
             Column() {
-              Text(`${this.artistMap.get(item.name)?.length ?? 0}首`)
+              Text(`${this.getArtistSongCount(item.name)}首`)
                 .fontSize(11)
                 .fontSize(this.twoFingerType == 1 ? 10 : this.twoFingerType == 2 ? 12 : 14)
                 .visibility(this.modeType === 2 && !this.isCanBack ? Visibility.Visible : Visibility.None)
                 .fontColor($r('app.color.text_color'))
-              Text(`${this.albumMap.get(item.name)?.length ?? 0}首`)
+              Text(`${this.getAlbumSongCount(item.name)}首`)
                 .fontSize(11)
                 .fontSize(this.twoFingerType == 1 ? 10 : this.twoFingerType == 2 ? 12 : 14)
                 .visibility(this.modeType === 3 && !this.isCanBack ? Visibility.Visible : Visibility.None)
@@ -6160,6 +6171,9 @@ export struct LocalMusic {
     .onReachEnd(() => {
       // 触底加载下一页
       Logger.info('heanup LocalMusic', `onReachEnd: hasMore=${this.hasMoreData}, isLoading=${this.isLoadingPage}`);
+      if (this.isCanBack && (this.modeType === 2 || this.modeType === 3)) {
+        return;
+      }
       if (this.hasMoreData && !this.isLoadingPage) {
         this.loadNextPage();
       }
@@ -6426,15 +6440,31 @@ export struct LocalMusic {
           this.mScrollMap.set('lastListArtistScrollOffset', offsetA)
         }
         let mList = this.artistMap.get(item.name)
+        if (mList === undefined || ArrayUtil.isEmpty(mList)) {
+          mList = await this.table.querySongsByArtist(item.name, this.sortType);
+          if (ArrayUtil.isNotEmpty(mList)) {
+            this.artistMap.set(item.name, mList);
+          }
+        }
         if (mList !== undefined && ArrayUtil.isNotEmpty(mList)) {
           Utility.doSortListAscending(mList)
+          const nextArtistCountMap = new Map(this.artistSongCountMap);
+          nextArtistCountMap.set(item.name, mList.length);
+          this.artistSongCountMap = nextArtistCountMap;
           this.isCanBack = true
+          this.hasMoreData = false
+          this.isLoadingPage = false
+          this.pageCache.clear()
+          this.totalCount = mList.length
           this.titleName = item.name
           this.currentTitleName = '艺术家:' + item.name
           if (item.pixelMapPath) {
             this.currentTitleCover = item.pixelMapPath
           }
           this.updateListData(mList)
+        } else {
+          ToastUtil.showToast('未找到该艺术家的歌曲');
+          return;
         }
         this.rightTopImage = $r('sys.symbol.chevron_left')
         //进入歌单的时候的滚动位置在顶部
@@ -6482,9 +6512,22 @@ export struct LocalMusic {
           this.mScrollMap.set('lastListAlBumScrollOffset', offset)
         }
         let albumList = this.albumMap.get(item.name)
+        if (albumList === undefined || ArrayUtil.isEmpty(albumList)) {
+          albumList = await this.table.querySongsByAlbum(item.name, this.sortType);
+          if (ArrayUtil.isNotEmpty(albumList)) {
+            this.albumMap.set(item.name, albumList);
+          }
+        }
         if (albumList !== undefined && ArrayUtil.isNotEmpty(albumList)) {
           Utility.doSortListAscending(albumList)
+          const nextAlbumCountMap = new Map(this.albumSongCountMap);
+          nextAlbumCountMap.set(item.name, albumList.length);
+          this.albumSongCountMap = nextAlbumCountMap;
           this.isCanBack = true
+          this.hasMoreData = false
+          this.isLoadingPage = false
+          this.pageCache.clear()
+          this.totalCount = albumList.length
           this.titleName = item.name
           this.currentTitleName = '专辑:' + item.name
           if (item.pixelMapPath) {
@@ -6493,6 +6536,9 @@ export struct LocalMusic {
           this.updateListData(albumList)
           this.mScrollMap.set(item.name, this.selectedIndex)
           this.rightTopImage = $r('sys.symbol.chevron_left')
+        } else {
+          ToastUtil.showToast('未找到该专辑的歌曲');
+          return;
         }
         //进入歌单的时候的滚动位置在顶部
         if(this.twoFingerType==4){
@@ -6910,6 +6956,14 @@ export struct LocalMusic {
       // 4. 更新状态和缓存
       this.totalCount = result.totalCount;
       this.hasMoreData = result.hasMore;
+      if (this.modeType === 1) {
+        this.mediaKuCount = result.totalCount;
+      }
+      if (this.modeType === 2 && result.countMap) {
+        this.mergeArtistCountMap(result.countMap);
+      } else if (this.modeType === 3 && result.countMap) {
+        this.mergeAlbumCountMap(result.countMap);
+      }
       
       Logger.info('heanup LocalMusic', `loadPage: 查询完成 items=${result.items.length}, total=${result.totalCount}, hasMore=${result.hasMore}`);
       
@@ -6958,6 +7012,30 @@ export struct LocalMusic {
     }
   }
 
+  private mergeArtistCountMap(countMap: Map<string, number>): void {
+    const nextMap = new Map(this.artistSongCountMap);
+    countMap.forEach((count, artist) => {
+      nextMap.set(artist, count);
+    });
+    this.artistSongCountMap = nextMap;
+  }
+
+  private mergeAlbumCountMap(countMap: Map<string, number>): void {
+    const nextMap = new Map(this.albumSongCountMap);
+    countMap.forEach((count, album) => {
+      nextMap.set(album, count);
+    });
+    this.albumSongCountMap = nextMap;
+  }
+
+  private getArtistSongCount(artist: string): number {
+    return this.artistSongCountMap.get(artist) ?? this.artistMap.get(artist)?.length ?? 0;
+  }
+
+  private getAlbumSongCount(album: string): number {
+    return this.albumSongCountMap.get(album) ?? this.albumMap.get(album)?.length ?? 0;
+  }
+
   /**
    * 加载文件夹列表(仅用于modeType=0的首页模式)
    */
@@ -7023,6 +7101,16 @@ export struct LocalMusic {
       return this.fullSongList;
     }
 
+    if (this.isHistory) {
+      return this.historyList;
+    }
+    if (this.isFavMusic) {
+      return this.favList;
+    }
+    if (this.isCanBack && (this.modeType === 2 || this.modeType === 3)) {
+      return this.videoLocalList.filter((item: VideoItem) => item.type === CommonConstants.TYPE_LOCAL);
+    }
+
     try {
       Logger.info('heanup LocalMusic', `loadFullSongList: 开始加载完整列表 mode=${this.modeType}`);
       
@@ -7087,6 +7175,11 @@ export struct LocalMusic {
     this.pageCache.clear();
     this.hasMoreData = true;
     this.totalCount = 0;
+    if (this.modeType === 2) {
+      this.artistSongCountMap = new Map();
+    } else if (this.modeType === 3) {
+      this.albumSongCountMap = new Map();
+    }
     await this.loadPage(0, false);
   }