Explorar el Código

长按增加乱码批量修正功能

onecold hace 10 meses
padre
commit
456dcf1b83

+ 2 - 2
AppScope/app.json5

@@ -2,8 +2,8 @@
   "app": {
     "bundleName": "com.xgplayer.ttmusic.hm",
     "vendor": "example",
-    "versionCode": 20250926,
-    "versionName": "1.6.1",
+    "versionCode": 20250929,
+    "versionName": "1.6.2",
     "icon": "$media:app_icon",
     "label": "$string:app_name",
     "multiAppMode": {

+ 1 - 0
entry/src/main/ets/common/util/MediaTable.ets

@@ -216,6 +216,7 @@ export default class MediaTable {
   }
 
 
+
   //更新重命名数据操作
   public updateRename(newName: string, oldPath: string, newPath: string, callback: Function) {
     // Step 1: 查询原始记录

+ 27 - 14
entry/src/main/ets/common/util/Utility.ets

@@ -1380,7 +1380,7 @@ export class Utility {
 
 
   //按名称升序
-  static doSortListAscending( list:Array<VideoItem>){
+  static doSortListAscending( list:Array<VideoItem>,isShowFileName?:boolean){
     let options: Intl.CollatorOptions = {
       localeMatcher: "lookup",
       usage: "sort",
@@ -1395,20 +1395,16 @@ export class Utility {
       if (typeOrder !== 0) {
         return typeOrder;
       }
-      return collator.compare(a.name, b.name)
-      // const partsA = extractParts(a.name);
-      // const partsB = extractParts(b.name);
-      //
-      // const nonNumericComparison = collator.compare(partsA.nonNumeric, partsB.nonNumeric);
-      // if (nonNumericComparison !== 0) {
-      //   return nonNumericComparison;
-      // }
-      //
-      // return partsA.numeric - partsB.numeric;
+      if(isShowFileName){
+        return collator.compare(a.fileName||a.name, b.fileName||b.name)
+      }else{
+        return collator.compare(a.name, b.name)
+      }
+
     });
   }
   //按名称降序
-  static doSortListDescending(list:Array<VideoItem>){
+  static doSortListDescending(list:Array<VideoItem>,isShowFileName?:boolean){
     const options: Intl.CollatorOptions = {
       localeMatcher: "lookup",
       usage: "sort",
@@ -1423,7 +1419,13 @@ export class Utility {
       if (typeOrder !== 0) {
         return typeOrder;
       }
-      return collator.compare(b.name, a.name)
+
+      if(isShowFileName){
+        return collator.compare(b.fileName||b.name, a.fileName||a.name)
+      }else{
+        return collator.compare(b.name, a.name)
+      }
+
       // const partsA = extractParts(a.name);
       // const partsB = extractParts(b.name);
       //
@@ -2027,8 +2029,19 @@ function getFileFormatByPath(filePath: string): string {
 function hasGarbledText(tags: FFMpegTags): boolean {
   if (!tags) return false;
   const text = [tags.title, tags.artist,  tags.album].join("");
-  return /[À-ÿµØÇò]/.test(text); // 匹配常见乱码字符
+
+  return (
+    /[À-ÿµØÇò]/.test(text) ||        // 拉丁乱码
+    /[\uFFFD�]/.test(text) ||         // Unicode替换字符
+    /[�□▪▫▢▣▤▥▦▧▨▩▪▫◊○◌◍◎●◐◑◒◓◔◕◖◗◘◙◚◛◜◝◞◟◠◡◢◣◤◥◦◧◨◩◪◫◬◭◮◯]/.test(text) || // 几何图形
+    /[\uD800-\uDFFF]/.test(text)     // 无效的UTF-16代理对
+  );
 }
+// function hasGarbledText(tags: FFMpegTags): boolean {
+//   if (!tags) return false;
+//   const text = [tags.title, tags.artist,  tags.album].join("");
+//   return /[À-ÿµØÇò]/.test(text); // 匹配常见乱码字符
+// }
 
 
 /**

+ 2 - 0
entry/src/main/ets/pages/ChartsCount.ets

@@ -16,6 +16,7 @@ import { ComponentContent } from '@kit.ArkUI';
 // 批量编辑标签
 @Component
 export struct ChartsCount {
+  @Consume mType: number;
   private listScroller: ListScroller = new ListScroller()
   @State isLyric:boolean = true
   @State isCover:boolean = true
@@ -310,6 +311,7 @@ export struct ChartsCount {
                 // 动画闭包内控制Image组件的出现和消失
                 this.isShowDrawer = !this.isShowDrawer
                 this.offsetX = 0
+                // this.mType =0
               })
             })
           Blank().flexGrow(1)

+ 2 - 0
entry/src/main/ets/pages/Demo.ets

@@ -1,3 +1,5 @@
+
+
 @Entry
 @Component
 struct Demo {

+ 1 - 1
entry/src/main/ets/pages/NewIndex.ets

@@ -147,7 +147,7 @@ struct NewIndex {
       (this.modeType !== 0 && this.isCanBack)) {
       const eventData: emitter.EventData = {};
       emitter.emit({ eventId: 888 }, eventData); // 发送音频广播通知更新doSwipBack
-    }if(this.mType==4||this.mType==5){
+    }if(this.mType > 0){
       this.getUIContext()?.animateTo({ duration: 555 }, () => {
         // 动画闭包内控制Image组件的出现和消失
         // this.isShowDrawer = !this.isShowDrawer

+ 374 - 0
entry/src/main/ets/view/FixMessyView.ets

@@ -0,0 +1,374 @@
+import { common, ConfigurationConstant } from '@kit.AbilityKit';
+import { CommonConstants } from '../common/constants/CommonConstants';
+import { VideoItem } from '../viewmodel/VideoItem';
+import { LazyDataSource } from '../common/util/LazyDataSource';
+import { AppUtil, LogUtil, PreferencesUtil, StrUtil, ToastUtil } from '@pura/harmony-utils';
+import fs from '@ohos.file.fs';
+import { changeMusicCover, findLocalCoverImage, getApiLyric, repairAudioMetadata,
+  searchCover,
+  syncLyricToDB} from '../common/util/MusicTagUtils';
+import { util } from '@kit.ArkTS';
+import { extractHwMediaMetadata, FFMpegTags, Utility } from '../common/util/Utility';
+import { DialogHelper } from '@pura/harmony-dialog';
+import MediaTable from '../common/util/MediaTable';
+
+
+// 批量乱码修正,元数据接口用华为的接口获取
+@Component
+export struct FixMessyView {
+  private listScroller: ListScroller = new ListScroller()
+  onFixResult = (_result: boolean) => {
+  }
+
+  @Link isShowDrawer: boolean;
+  @State bundleName: string = ''
+  @State dataSource: LazyDataSource<VideoItem> = new LazyDataSource([])
+  @Prop selectedFiles: Array<VideoItem>
+  @StorageProp('topRectHeight') topRectHeight: number = 0;
+  @State isDarkMode: boolean = false
+  @StorageProp('currentColorMode') @Watch('onColorModeChange') currentMode: number =
+    ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT;
+  @StorageProp('themeColor') themeColor: string = CommonConstants.DEFAULT_THEME_COLOR;
+  context =  this.getUIContext().getHostContext() as common.UIAbilityContext
+  // 新增状态用于进度显示
+  @State currentProgress: number = 0;
+  @State totalFiles: number = 0;
+  @State currentFileIndex: number = 0;
+  @State currentFileName: string = '';
+  @State isEmbedding: boolean = false;
+  @State embedSuccessCount: number = 0;
+  @State embedFailedCount: number = 0;
+  private table: MediaTable = new MediaTable(this.context);
+  // 新增状态用于跟踪每个文件的嵌入状态
+  @State embedStatusMap: Map<string, boolean> = new Map<string, boolean>();
+
+
+  onColorModeChange() {
+    this.isDarkMode = this.currentMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK
+  }
+
+  async aboutToAppear() {
+
+    this.bundleName = AppUtil.getBundleName()
+    // 确保 selectedFiles 有默认值后再初始化 dataSource
+    if (this.selectedFiles && this.selectedFiles.length > 0) {
+      this.dataSource = new LazyDataSource(this.selectedFiles)
+    } else {
+      this.dataSource = new LazyDataSource([])
+    }
+    await new Promise<void>((resolve, reject) => {
+      this.table.getRdbStore(this.context,  (err:Error) => {
+        err ? reject(err) : resolve();
+      });
+    });
+  }
+
+
+
+  build() {
+    Column(){
+      this.topTitleBar()
+
+      this.startButton()
+      this.listView()
+
+    }
+    .height('100%')
+    .width('100%')
+    .backgroundColor($r('app.color.index_background'))
+  }
+
+  @Builder
+  listView() {
+    Column(){
+      List({ scroller: this.listScroller }) {
+        ListItemGroup({ header: this.listHeader() }) {
+          LazyForEach(this.dataSource, (item: VideoItem, index: number) => {
+            ListItem() {
+              Column() {
+                this.MusicItem(item, index)
+              }
+            }
+            .transition(TransitionEffect.asymmetric(
+              TransitionEffect.scale({ x: 1.2, y: 1.2 }).animation({ duration: 500 }),
+              TransitionEffect.scale({ x: 0, y: 0 })
+            ))
+            .clickEffect({ level: ClickEffectLevel.LIGHT })
+          }, (item: VideoItem) => item.filePath)
+        }
+
+      }
+      .cachedCount(2)
+      // .layoutWeight(1)
+      // .height('100%')
+      .transition(TransitionEffect.asymmetric(
+        TransitionEffect.scale({ x: 1.2, y: 1.2 }).animation({ duration: 500 }),
+        TransitionEffect.scale({ x: 0, y: 0 })
+      ))
+
+    }
+    .borderRadius(20)
+    .padding({top:10,bottom:6})
+    .height('auto')
+    .backgroundColor($r('app.color.start_window_background'))
+    .margin({top:20,right:20,left:20})
+    .layoutWeight(1)
+    .height('100%')
+  }
+
+  @Builder
+  listHeader() {
+    Stack({alignContent:Alignment.Start}){
+      Text(`共${this.selectedFiles.length}首歌`)
+        .fontSize(14)
+        .maxLines(1)
+        .textAlign(TextAlign.Start)
+        .padding({ left: 25 })
+        .fontColor($r('app.color.text_color'))
+        .margin({bottom:6,top:4,left: 6 })
+    }
+    .height('auto').width('100%')
+  }
+
+
+
+  @Builder
+  startButton(){
+    Stack(){
+      Progress({ value: this.currentProgress, total: this.totalFiles,
+        type: ProgressType.Capsule }).height(55)
+        .margin({top:20,right:20,left:20})
+        .backgroundColor($r('app.color.index_background'))
+      Button({ type: ButtonType.Capsule, stateEffect: true }) {
+        Row() {
+          // 菜单图标
+          SymbolGlyph($r('sys.symbol.star_trophy'))// .size({ width: 22, height: 22 })
+            .fontSize(22)
+            .fontColor([this.themeColor])
+            .alignSelf(ItemAlign.Center)
+            .margin({ left: 25 })
+
+          // 菜单标题
+          Text('开始乱码修正')
+            .margin({ left: 10, right: 20 })
+            .fontSize(15)
+            .fontWeight(480)
+          Blank()
+          // 右侧箭头
+          Image($r('app.media.arrow_right'))
+            .width(22)
+            .height(22)
+            .margin({ left: 0, right: 20 })
+            .align(Alignment.Center)
+        }
+        .width('100%')
+      }
+      .margin({top:20,right:20,left:20})
+      .height(55)
+      .enabled(!this.isEmbedding)
+      .backgroundColor($r('app.color.start_window_background'))
+      .clickEffect({ level: ClickEffectLevel.MIDDLE,scale:0.6 })
+      .onClick(()=>{
+        this.startEmbed()
+      })
+
+
+    }
+
+  }
+
+
+
+
+  /**
+   * 开始修复
+   */
+  async startEmbed() {
+    if (this.isEmbedding || !this.selectedFiles || this.selectedFiles.length === 0) {
+      return;
+    }
+
+
+
+
+    this.isEmbedding = true;
+    this.currentProgress = 0;
+    this.currentFileIndex = 0;
+    this.embedSuccessCount = 0;
+    this.embedFailedCount = 0;
+    this.totalFiles = this.selectedFiles.length;
+
+    // 清空之前的嵌入状态
+    this.embedStatusMap = new Map<string, boolean>();
+
+    // 创建异步任务数组
+    const embedTasks = this.selectedFiles.map(async (item: VideoItem, index: number) => {
+      try {
+        this.currentFileIndex = index + 1;
+        this.currentFileName = item.name;
+
+
+        let success = true;
+        let  hwTags = await extractHwMediaMetadata(item.filePath)
+        let artist = hwTags?.artist|| '';
+        let title = hwTags?.title|| '';
+        let album = hwTags?.album|| '';
+        console.info('onecold 乱码修正 artist='+artist);
+        console.info('onecold 乱码修正 title='+title);
+        console.info('onecold 乱码修正 album='+album);
+
+
+        const metadata:FFMpegTags = {
+          title: title,
+          artist: artist,
+          album: album,
+        };
+
+        //内嵌下标签的值,设置overwrite为true会直接修改原文件
+        const result:boolean = await repairAudioMetadata(
+          item.filePath,
+          item.lyricContent||'',
+          metadata,
+          true
+        );
+        //入库
+        if (result) {
+          this.table.updateMediaInfo(item.filePath,title, artist, album,
+            item.lyricContent||'','','','','','','','','', (success: boolean, error?: string) => {
+              if (success) {
+                console.info('onecold 乱码修正 更新库成功')
+              }else{
+                console.info('onecold 乱码修正  更新库失败')
+              }
+            });
+        }
+
+
+        // 更新嵌入状态
+        if (item.filePath) {
+          this.embedStatusMap.set(item.filePath, success);
+        }
+
+        if (success) {
+          this.embedSuccessCount++;
+        } else {
+          this.embedFailedCount++;
+        }
+        // 滚动到当前处理的项目位置
+        // this.listScroller.scrollToIndex(index);
+        this.currentProgress = Math.floor(((index + 1) / this.totalFiles) * 100);
+        return success;
+      } catch (error) {
+        console.error(`处理文件 ${item.name} 失败: ${JSON.stringify(error)}`);
+        this.embedFailedCount++;
+        return false;
+      }
+    });
+
+    try {
+      // 并发执行所有嵌入任务
+      await Promise.all(embedTasks);
+    } catch (error) {
+      this.onFixResult(false)
+      console.error(`批量嵌入过程出错: ${JSON.stringify(error)}`);
+    } finally {
+      ToastUtil.showToast(`嵌入完成: 成功 ${this.embedSuccessCount}, 失败 ${this.embedFailedCount}`)
+      this.isEmbedding = false;
+      this.currentProgress = 0;
+      this.totalFiles = this.selectedFiles.length;
+      this.onFixResult(true)
+      // 可以在这里添加完成后的提示或回调
+      console.info(`嵌入完成: 成功 ${this.embedSuccessCount}, 失败 ${this.embedFailedCount}`);
+    }
+  }
+
+
+  @Builder
+  topTitleBar() {
+    // 顶部安全区和自定义标题栏
+    Column() {
+      // 顶部安全区
+      Blank()
+        .height(this.topRectHeight)
+        .backgroundColor(this.isDarkMode ? $r('app.color.title_bar_bg') : this.themeColor)
+        .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])
+      // 自定义标题栏(Stack实现绝对居中)
+      Stack() {
+        // 居中标题
+        Text('批量乱码修正')
+          .fontSize(18)
+          .fontColor(Color.White)
+          .align(Alignment.Center)
+        // 左右按钮
+        Row() {
+          Image($r('app.media.left_back_white'))
+            .width(26)
+            .height(26)
+            .margin({ left: 12, right: 8 })
+            .onClick(() => {
+              this.getUIContext().animateTo({ duration: 666 }, () => {
+                // 动画闭包内控制Image组件的出现和消失
+                this.isShowDrawer = !this.isShowDrawer
+              })
+            })
+          Blank().flexGrow(1)
+          Blank().width(32)
+        }
+        .height(48)
+        .width('100%')
+        .alignItems(VerticalAlign.Center)
+      }
+      .height(48)
+      .width('100%')
+      .backgroundColor(this.isDarkMode ? $r('app.color.title_bar_bg') : this.themeColor)
+    }
+  }
+
+  @Builder
+  private MusicItem(item: VideoItem, index?: number) {
+    Button({ type: ButtonType.Normal, stateEffect: true }) {
+      Column() {
+        Row() {
+          SymbolGlyph($r('sys.symbol.music'))
+            .fontSize(20)
+            .fontColor([this.themeColor])
+            .alignSelf(ItemAlign.Center)
+            .padding({ left: 25 })
+          Text(item.name)
+            .fontSize(14)
+            .maxLines(1)
+            .padding({ left: 5 })
+            .textOverflow({ overflow: TextOverflow.MARQUEE })
+            .animation({
+              duration: 555,
+              curve: 'Linear',
+            })
+            .fontColor(Color.Gray)
+            .margin({ left: 8 })
+          Blank()
+          // 根据嵌入状态显示勾选图标
+          SymbolGlyph($r('sys.symbol.checkmark_circle'))
+            .fontSize(20)
+            .fontColor([this.themeColor])
+            .alignSelf(ItemAlign.Center)
+            .padding({ right: 25 })
+            .animation({
+              duration: 666,
+              curve: 'ease-in-out' // 可选动画曲线
+            })
+            .visibility(this.embedStatusMap.get(item.filePath)?Visibility.Visible:Visibility.None)
+
+        }
+        .layoutWeight(1)
+        .height('100%')
+        .width('100%')
+
+      }
+    }
+    .backgroundColor(Color.Transparent)
+    .width('100%')
+    .height(40)
+  }
+}
+
+

+ 62 - 18
entry/src/main/ets/view/LocalMusic.ets

@@ -81,6 +81,8 @@ import { KeyCode } from '@kit.InputKit';
 import { KnockController } from '../controller/KnockController';
 import { DeleteComptent } from '../view/DeleteComptent'
 import { ABLoopComptent } from '../view/ABLoopComptent';
+import { FixMessyView } from '../view/FixMessyView';
+
 const TAG = 'LocalMusic';
 
 const DEFAULT_INDEX =
@@ -210,6 +212,7 @@ export struct LocalMusic {
   private listScroller: ListScroller = new ListScroller()
   private playListScroller: Scroller = new Scroller()
   @State isOneKeyTags:boolean = false
+  @State isFixMessy:boolean = false
   @StorageProp('isLandscape') @Watch('onIsLandscapeChange')  isLandscape: boolean = false;
   @StorageProp('topRectHeight') topRectHeight: number = px2vp(AppUtil.getStatusBarHeight());
   @StorageProp('windowWidth') windowWidth: number = 0;
@@ -764,7 +767,7 @@ export struct LocalMusic {
         PreferencesUtil.putSync('isFirstApp', false)
       } else {
 
-        workerInstance.postMessage({ code: 2, data: this.context });
+        workerInstance.postMessage({ code: 2, data: this.context,data2:this.packName });
         workerInstance.postMessage({ code: 3, data: this.context });
         workerInstance.postMessage({ code: 4, data: this.context });
         this.getHistoryList(false)
@@ -958,7 +961,7 @@ export struct LocalMusic {
     this.isFavMusic = false
     console.info('onecold getSortedFiles 1 curPath '+curPath)
     if (isWorkerPost) {
-      workerInstance.postMessage({ code: 2, data: this.context }); //刷新媒体库列表
+      workerInstance.postMessage({ code: 2, data: this.context,data2:this.packName });
     }
     if (this.modeType !== 0) {
 
@@ -1288,10 +1291,10 @@ export struct LocalMusic {
         onAction: (index) => {
           switch (index) {
             case 0:
-              Utility.doSortListAscending(this.videoLocalList)
+              Utility.doSortListAscending(this.videoLocalList,this.isShowFileName)
               break;
             case 1:
-              Utility.doSortListDescending(this.videoLocalList)
+              Utility.doSortListDescending(this.videoLocalList,this.isShowFileName)
               break;
           }
           this.updateListData(this.videoLocalList)
@@ -1387,10 +1390,10 @@ export struct LocalMusic {
 
         break;
       case 4:
-        Utility.doSortListAscending(this.videoLocalList)
+        Utility.doSortListAscending(this.videoLocalList,this.isShowFileName)
         break;
       case 5:
-        Utility.doSortListDescending(this.videoLocalList)
+        Utility.doSortListDescending(this.videoLocalList,this.isShowFileName)
         break;
       case 6:
         this.videoLocalList.sort((a, b) => {
@@ -2116,8 +2119,9 @@ export struct LocalMusic {
 
           Row() {
             Button(this.isAllSelected ? '全不选' : '全选', { type: ButtonType.Circle, stateEffect: true })
-              .width('35%')
-              .height(60)
+              .width(50)
+              .height(50)
+              .fontSize(13)
               .margin({ top: 10, bottom: 10, right: 6 })
               .backgroundColor(this.themeColor)
               .clickEffect({ level: ClickEffectLevel.MIDDLE, scale: 0.5 })
@@ -2133,8 +2137,9 @@ export struct LocalMusic {
               })
 
             Button('内嵌标签', { type: ButtonType.Capsule, stateEffect: true })
-              .width(100)
-              .height(60)
+              .width(90)
+              .height(50)
+              .fontSize(13)
               .margin({ top: 10, bottom: 10, right: 6 })
               .clickEffect({ level: ClickEffectLevel.MIDDLE, scale: 0.5 })
               .backgroundColor(this.themeColor)
@@ -2144,6 +2149,20 @@ export struct LocalMusic {
               .onClick(() => {
                 this.isOneKeyTags = !this.isOneKeyTags
               })
+
+            Button('乱码修复', { type: ButtonType.Capsule, stateEffect: true })
+              .width(90)
+              .height(50)
+              .fontSize(13)
+              .margin({ top: 10, bottom: 10, right: 6 })
+              .clickEffect({ level: ClickEffectLevel.MIDDLE, scale: 0.5 })
+              .backgroundColor(this.themeColor)
+              .bindContentCover($$this.isFixMessy, this.FixMessyViewBuilder(), {
+                transition: TransitionEffect.translate({ x: 500 }).animation({ curve: curves.springMotion(0.6, 0.8) })
+              })
+              .onClick(() => {
+                this.isFixMessy = !this.isFixMessy
+              })
             // Button('剪切', { type: ButtonType.Circle, stateEffect: true })
             //   .width('35%')
             //   .height(60)
@@ -2179,8 +2198,9 @@ export struct LocalMusic {
             //   })
 
             Button('删除', { type: ButtonType.Circle, stateEffect: true })
-              .width('35%')
-              .height(60)
+              .width(50)
+              .height(50)
+              .fontSize(13)
               .margin({ top: 10, bottom: 10, right: 6 })
               .visibility(this.isFavMusic ? Visibility.None : Visibility.Visible)
               .backgroundColor(this.themeColor)
@@ -2189,8 +2209,9 @@ export struct LocalMusic {
                 this.showWarnIsDelete()
               })
             Button('取消', { type: ButtonType.Circle, stateEffect: true })
-              .width('35%')
-              .height(60)
+              .width(50)
+              .height(50)
+              .fontSize(13)
               .margin({ top: 10, bottom: 10, right: 6 })
               .backgroundColor(this.themeColor)
               .clickEffect({ level: ClickEffectLevel.MIDDLE, scale: 0.5 })
@@ -2210,7 +2231,7 @@ export struct LocalMusic {
             curve: 'ease-in-out' // 可选动画曲线
           })
           .position(this.isShowCoverHeader() ? { bottom: 78 }
-            : { bottom: this.isPhoneLan() ? 130 : 168 }) // 将 Row 固定在底部
+            : { bottom: this.isPhoneLan() ? 130 : 170 }) // 将 Row 固定在底部
 
 
         }
@@ -2260,6 +2281,29 @@ export struct LocalMusic {
     .height('100%')
   }
 
+  @Builder
+  FixMessyViewBuilder() {
+    Scroll() {
+      Column() {
+        FixMessyView(
+          {
+            selectedFiles:this.selectedFiles,
+            isShowDrawer:this.isFixMessy,
+            onFixResult:(result: boolean)=>{
+              this.isMultiSelect = false
+              if(result){//如果嵌入成功,更新数据
+                this.doUpdateData()
+              }
+
+            }
+          }
+        )
+      }
+    }
+    .width('100%')
+    .height('100%')
+  }
+
   asyncCurrentPathData() {
     if (this.modeType == 0) {
       workerInstance.postMessage({
@@ -2428,7 +2472,7 @@ export struct LocalMusic {
           LogUtil.info('onecold doFav currentPath =' + this.currentPath)
           this.getSortedFiles(this.currentPath)
         }
-        workerInstance.postMessage({ code: 2, data: this.context });
+        workerInstance.postMessage({ code: 2, data: this.context,data2:this.packName });
         workerInstance.postMessage({ code: 3, data: this.context });
         workerInstance.postMessage({ code: 4, data: this.context });
       }
@@ -3261,7 +3305,7 @@ export struct LocalMusic {
               if(this.modeType == 0){
                 this.asyncCurrentPathData()
               }else if(this.modeType ==1){
-                workerInstance.postMessage({ code: 2, data: this.context });
+                workerInstance.postMessage({ code: 2, data: this.context,data2:this.packName });
               }
             }
           })
@@ -5317,7 +5361,7 @@ export struct LocalMusic {
         this.deleteCache(this.currentPath)
         this.getSortedFiles(this.currentPath)
       }
-      workerInstance.postMessage({ code: 2, data: this.context });
+      workerInstance.postMessage({ code: 2, data: this.context,data2:this.packName });
       workerInstance.postMessage({ code: 3, data: this.context });
       workerInstance.postMessage({ code: 4, data: this.context });
     }, 999)

+ 3 - 3
entry/src/main/ets/workers/Worker.ets

@@ -26,7 +26,7 @@ workerPort.onmessage = async (e: MessageEvents) => {
       })
       break;
     case 2://查询媒体库列表
-      queryMediaKuList(e.data.data)
+      queryMediaKuList(e.data.data,e.data.data2)
       break;
     case 3://查询艺术家列表
       queryArtistTask(e.data.data)
@@ -110,7 +110,7 @@ async function scanDirectory(context: Context, curPath: string, lockPath: string
 
 
 //获取当前媒体库歌曲列表
-async function queryMediaKuList(context:Context){
+async function queryMediaKuList(context: Context,packageName: string) {
   const table: MediaTable = new MediaTable(context);
   try {
 
@@ -136,7 +136,7 @@ async function queryMediaKuList(context:Context){
       originalList.map(async  item => {
         try {
           const exists = await FileUtil.access(item.filePath);  // 改为异步校验
-          if (exists) return item;
+          if (exists||!(item.filePath.includes(packageName))) return item;//如果不是本DownLoad目录下包名文件,不能删除
 
           // 删除无效记录
           const isDeleted = await new Promise<boolean>(resolve => {

+ 11 - 1
lib/src/main/ets/LyricController.ets

@@ -31,7 +31,7 @@ export class LyricController {
     private alignMode: "left" | "center" = "center"
     private isHightLightCenter: boolean = true
     private textWeight: number = FontWeight.Medium
-
+    private transverterType: number = 0
     /**
      *  Listener to observe the lyric data set changed. This is a inner function, do not call this.
      */
@@ -122,6 +122,16 @@ export class LyricController {
         return this.textSize
     }
 
+    setTransverterType(type: number): LyricController {
+        this.transverterType = type
+        this.onInvalidated(true)
+        return this
+    }
+
+    getTransverterType(): number {
+        return this.transverterType
+    }
+
     setHightLightCenter(isHightLightCenter: boolean): LyricController {
         this.isHightLightCenter = isHightLightCenter
         this.onInvalidated(true)

+ 24 - 3
lib/src/main/ets/view/LyricView2.ets

@@ -4,7 +4,7 @@ import { Lyric } from '../bean/Lyric';
 import { ListAdapter } from '../extensions/ListAdapter';
 import { LyricLine } from '../bean/LyricLine';
 import { LyricWord } from '../bean/LyricWord';
-
+import { transverter, TransverterType, TransverterLanguage } from "@nutpi/chinese_transverter"
 /**
  * A component to display the lyric with scroll animation.
  * This component only support api 10+.
@@ -72,6 +72,7 @@ export struct LyricView2 {
     private loadTimeout = -1
     @State isHightLightCenter: boolean = true
     @State currentMediaPosition: number = 0
+    @State transverterType: number = 0
 
     private onDataChangedListener = (lyric: Lyric | null) => {
         clearTimeout(this.loadTimeout)
@@ -130,6 +131,7 @@ export struct LyricView2 {
     private getAttrFromController() {
         this.currentLyric = this.controller.getLyric()
         this.textSize = this.controller.getTextSize()
+        this.transverterType = this.controller.getTransverterType()
         this.isSingleLine = this.controller.getSingleLine()
         this.blurDegree = this.controller.getBlurDegree()
         this.isHightLightCenter = this.controller.getHightLightCenter()
@@ -278,7 +280,7 @@ export struct LyricView2 {
     // 普通歌词渲染(原有逻辑)
     @Builder
     NormalLyricLine(item: LyricLine, index: number) {
-        Text(item.text)
+        Text(this.getTransverterText(item.text))
             .fontSize(this.textSize)
             .opacity(this.calculateOpacityFactor(index, this.currentIndex))
             .blur(this.calculateBlurFactor(index, this.currentIndex))
@@ -303,7 +305,7 @@ export struct LyricView2 {
             ForEach(item.words, (word: LyricWord, wordIndex: number) => {
 
 
-                Text(word.word)
+                Text(this.getTransverterText(word.word))
                     .fontSize(index == this.currentIndex ?this.textSize*this.controller.getHighlightScale():this.textSize)
                     .fontColor(this.currentMediaPosition >= word.startTime ?
                         index == this.currentIndex ? this.textHighlightColor : this.textColor : this.textColor)
@@ -354,6 +356,25 @@ export struct LyricView2 {
         this.isUserTouching = false;
     }
 
+    getTransverterText(message: string):string{
+        if(this.transverterType==1){
+            return    transverter({
+                type: TransverterType.TRADITIONAL,
+                str: message,
+                language: TransverterLanguage.ZH_TW
+            });
+        }else if(this.transverterType==2){
+            return    transverter({
+                type: TransverterType.SIMPLIFIED,
+                str: message,
+                language: TransverterLanguage.ZH_CN
+            });
+        }else{
+            return message;
+        }
+
+    }
+
     @Builder
     SeekLine() {
         Row() {