Bladeren bron

Merge remote-tracking branch 'origin/master'

chendeben 1 jaar geleden
bovenliggende
commit
0fd7913490

+ 2 - 2
AppScope/app.json5

@@ -2,8 +2,8 @@
   "app": {
     "bundleName": "com.xgplayer.ttmusic.hm",
     "vendor": "example",
-    "versionCode": 20250730,
-    "versionName": "1.4.9",
+    "versionCode": 20250810,
+    "versionName": "1.5.1",
     "icon": "$media:app_icon",
     "label": "$string:app_name",
     "multiAppMode": {

+ 4 - 0
entry/src/main/ets/common/constants/CommonConstants.ets

@@ -16,6 +16,10 @@
 import { SettingPage } from '../../pages/SettingPage';
 import { VideoSpeed } from '../../viewmodel/VideoSpeed';
 
+export const STR_LOCK_VIDEO: string = '.私密音频';
+export const STR_FAC_VIDEO: string = '.我的收藏';
+export const STR_HISTORY_MUSIC: string = '.最近播放';
+export const VIP_FILEPATH: string = '.vv'
 /**
  * Common constants for all features.
  */

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

@@ -241,6 +241,11 @@ export default class MediaTable {
       obj.genre  = resultSet.getString(resultSet.getColumnIndex('genre'));
       obj.track  = resultSet.getString(resultSet.getColumnIndex('track'));
 
+      obj.bits_per_raw_sample  = resultSet.getString(resultSet.getColumnIndex('bits_per_raw_sample'));
+      obj.channels  = resultSet.getString(resultSet.getColumnIndex('channels'));
+      obj.channel_layout  = resultSet.getString(resultSet.getColumnIndex('channel_layout'));
+      obj.start_time  = resultSet.getString(resultSet.getColumnIndex('start_time'));
+
       const valueBucket: relationalStore.ValuesBucket = obj
       // Step 4: 执行更新
       const updatePredicates = new relationalStore.RdbPredicates(RdbUtils.MEDIA_TABLE.tableName);
@@ -567,6 +572,11 @@ export default class MediaTable {
     item.genre = safeGet('genre');
     item.track = safeGet('track');
 
+    item.bits_per_raw_sample = safeGet('bits_per_raw_sample');
+    item.channels = safeGet('channels');
+    item.channel_layout = safeGet('channel_layout');
+    item.start_time = safeGet('start_time');
+
     return item;
   }
 
@@ -661,5 +671,18 @@ function generateBucket(item: VideoItem): relationalStore.ValuesBucket {
     obj.track = item.track;
   }
 
+  if(item.bits_per_raw_sample){
+    obj.bits_per_raw_sample = item.bits_per_raw_sample;
+  }
+  if(item.channels){
+    obj.channels = item.channels;
+  }
+  if(item.channel_layout){
+    obj.channel_layout = item.channel_layout;
+  }
+  if(item.start_time){
+    obj.start_time = item.start_time;
+  }
+
   return obj;
 }

+ 12 - 1
entry/src/main/ets/common/util/RdbUtils.ets

@@ -70,12 +70,18 @@ export default class RdbUtils {
       '        genre TEXT,\n' +
       '        track TEXT,\n' +
 
+      '        bits_per_raw_sample TEXT,\n' +
+      '        channels TEXT,\n' +
+      '        channel_layout TEXT,\n' +
+      '        start_time TEXT,\n' +
+
       '        mimeType TEXT' +
       ')',
     columns: ['id', 'name', 'filePath','mtype', 'videoSize', 'cTime','size', 'artist', 'album',
       'fileName','parentPath','isFav','pixelMapPath','pixelMapToString',
       'duration',   'sampleRate','playCount',  'lastPlayedStr', 'trackCount',
-      'lyricContent','md5Str','extra_json','pyStr','bit_rate','probe_score','year','nb_streams','nb_programs','genre','track','mimeType']
+      'lyricContent','md5Str','extra_json','pyStr','bit_rate','probe_score','year','nb_streams','nb_programs',
+      'genre','track',  'bits_per_raw_sample','channels',  'channel_layout','start_time',  'mimeType']
   };
 
   constructor(tableName: string, sqlCreateTable: string, columns: Array<string>) {
@@ -158,6 +164,11 @@ export default class RdbUtils {
             'genre': 'TEXT',
             'track': 'TEXT',
 
+            'bits_per_raw_sample': 'TEXT',
+            'channels': 'TEXT',
+            'channel_layout': 'TEXT',
+            'start_time': 'TEXT',
+
           };
           
           // 逐个添加列,不依赖于检查结果

+ 9 - 3
entry/src/main/ets/common/util/UserUtil.ets

@@ -1,13 +1,12 @@
 import { cryptoFramework } from "@kit.CryptoArchitectureKit";
 import { LogUtil, PreferencesUtil, StrUtil, ToastUtil } from "@pura/harmony-utils";
-import { CommonConstants } from "../constants/CommonConstants";
+import { CommonConstants, STR_LOCK_VIDEO, VIP_FILEPATH } from "../constants/CommonConstants";
 import { http } from "@kit.NetworkKit";
 import { bundleManager } from "@kit.AbilityKit";
 import { BusinessError } from '@kit.BasicServicesKit';
 import { hilog } from "@kit.PerformanceAnalysisKit";
 import { FileUtil } from "@pura/harmony-utils";
 import { fileUri, picker } from "@kit.CoreFileKit";
-import { LocalMusic } from "../../view/LocalMusic";
 import { VipPage } from "../../pages/VipPage";
 
 // 用户相关接口定义
@@ -351,10 +350,12 @@ export default class UserUtil {
           let hasActiveSubscription = false;
           let subscriptionName = '';
           let subscriptionEndDate = '';
+          let plan_id = '';
           if (subInfo && subInfo.has_active_subscription && subInfo.subscriptions && subInfo.subscriptions.length > 0) {
             hasActiveSubscription = true;
             subscriptionName = subInfo.subscriptions[0].plan_name;
             subscriptionEndDate = subInfo.subscriptions[0].end_date;
+            plan_id = subInfo.subscriptions[0].plan_id
           }
           // 保存登录状态
           PreferencesUtil.putSync('isLogin', true);
@@ -365,6 +366,11 @@ export default class UserUtil {
           PreferencesUtil.putSync('subscriptionEndDate', subscriptionEndDate);
           PreferencesUtil.putSync('hasActiveSubscription', hasActiveSubscription);
           PreferencesUtil.putSync('userToken', json.data.system_info?.token || '');
+          if(plan_id=='1'){
+            PreferencesUtil.putSync('isForever', true);
+          }else{
+            PreferencesUtil.putSync('isForever', false);
+          }
           return json.data;
         } else {
           return null;
@@ -430,7 +436,7 @@ export default class UserUtil {
             const documentViewPicker = new picker.DocumentViewPicker()
             let documentSaveResult = await documentViewPicker.save({ pickerMode: picker.DocumentPickerMode.DOWNLOAD })
             let download_path = new fileUri.FileUri(documentSaveResult[0]).path + '/'
-            let filePath = download_path + LocalMusic.STR_LOCK_VIDEO+ '/' + VipPage.VIP_FILEPATH
+            let filePath = download_path + STR_LOCK_VIDEO+ '/' + VIP_FILEPATH
             if (FileUtil.accessSync(filePath)) {
               FileUtil.unlink(filePath);
             }

+ 200 - 83
entry/src/main/ets/common/util/Utility.ets

@@ -17,12 +17,11 @@ import { dataSharePredicates, uniformTypeDescriptor } from '@kit.ArkData';
 import { systemShare } from '@kit.ShareKit';
 import { fileUri, picker } from '@kit.CoreFileKit';
 import {  common, UIAbility, Want } from '@kit.AbilityKit';
-import { CommonConstants } from '../constants/CommonConstants';
+import { CommonConstants, STR_LOCK_VIDEO, VIP_FILEPATH } from '../constants/CommonConstants';
 import { window } from '@kit.ArkUI';
 import { bundleManager } from '@kit.AbilityKit'
 import { pinyin4js } from '@ohos/pinyin4js';
 import { VipData } from '../../viewmodel/VipData';
-import { LocalMusic } from '../../view/LocalMusic';
 import { VipPage } from '../../pages/VipPage';
 import { FFmpeg, FFProgressMessageParser } from '@sj/ffmpeg';
 
@@ -67,6 +66,12 @@ interface FFprobeStream {
   sample_rate?: string; // 采样率
   bit_rate?: string;    // 比特率
   disposition?: StreamDisposition;  // 添加disposition属性
+
+  bits_per_raw_sample?: string;  // 位深
+  channels?: string; // 声道数
+  channel_layout?: string;    // 声道布局
+  start_time?: string;  // 起始播放
+
 }
 
 interface StreamDisposition {
@@ -138,10 +143,8 @@ export class Utility {
     let isNoble = false
     if(StrUtil.isNotEmpty(expireDate)){
       if(expireDate===VipPage.FOREVER_DATE){
-        PreferencesUtil.putSync('isForever',true)
         isNoble = true
       }else{
-        PreferencesUtil.putSync('isForever',false)
         const currentDate = new Date();
         const targetDate = DateUtil.getFormatDate(expireDate)
 
@@ -407,8 +410,9 @@ export class Utility {
     return false;
   }
 
+
   // 获取缩略图
-  static async getFetchFrameByTime(filePath: string) {
+  static async getFetchFrameByTime(filePath: string,time?:number) {
     if(Utility.isMusicByExtension(filePath)){
       return undefined
     }
@@ -421,6 +425,10 @@ export class Utility {
       avImageGenerator.fdSrc = avFileDescriptor;
       // 初始化入参
       let timeUs = 0
+      console.info('onecold time='+time)
+      if(time){
+        timeUs = (time > 0) ? time*60 : 0
+      }
       let queryOption = media.AVImageQueryOptions.AV_IMAGE_QUERY_NEXT_SYNC
       let param: media.PixelMapParams = {
         width : 300,
@@ -809,22 +817,29 @@ export class Utility {
         },
       }).then(async () => {
         try {
-          let videoItem:VideoItem = new VideoItem('',inputPath,inputPath,type,0,'')
           const metadata: FFprobeMetadata = JSON.parse(outputJson);
           const format = metadata.format;
-
+          console.log(`onecold outputJson:${outputJson}`);
           let file = fs.openSync(inputPath, fs.OpenMode.READ_ONLY | fs.OpenMode.CREATE)
           console.info('readMetaInfoFFmpeg asset file.path: ', file.path);
-          videoItem = new VideoItem(file.name,inputPath,inputPath,type,0,'')
+          let videoItem = new VideoItem(file.name,inputPath,inputPath,type,0,'')
           await fs.stat(file.fd).then(async (stat: fs.Stat) => {
 
             // 获取音频流的采样率
-            let sampleRate = '';
+            let sampleRate:string|undefined = '';
+            let bits_per_raw_sample:string|undefined = '';
+            let channels:string|undefined = '';
+            let channel_layout:string|undefined = '';
+            let start_time:string|undefined = '';
             if (metadata.streams  && metadata.streams.length  > 0) {
               // 查找第一个音频流
               const audioStream = metadata.streams.find(stream  => StrUtil.isNotEmpty(stream.sample_rate));
-              if (audioStream&&audioStream.sample_rate)  {
+              if (audioStream)  {
                 sampleRate = audioStream.sample_rate;
+                bits_per_raw_sample = audioStream.bits_per_raw_sample
+                channel_layout = audioStream.channel_layout
+                channels = audioStream.channels
+                start_time = audioStream.start_time
               }
             }
 
@@ -859,6 +874,7 @@ export class Utility {
             if (!name) {
               name = getFileNameWithoutExtension(inputPath);
             }
+            let pixelMap:image.PixelMap|undefined|null = undefined
             // Create VideoItem
             videoItem = new VideoItem(
               name,
@@ -886,6 +902,12 @@ export class Utility {
             videoItem.lyricContent  = tags.LYRICS || tags.lyrics  ||  tags.USLT || tags.UNSYNCEDLYRICS || '';
             videoItem.genre  = tags.genre||tags.GENRE|| Utility.resourceToString(context, $r('app.string.unknown'));
             videoItem.track  = tags.track||tags.TRACK|| Utility.resourceToString(context, $r('app.string.unknown'));
+
+            videoItem.bits_per_raw_sample = bits_per_raw_sample ||'1'
+            videoItem.channel_layout = channel_layout || ''
+            videoItem.channels = channels ||'0'
+            videoItem.start_time = start_time || '00:00'
+
             videoItem.mimeType = format.format_name
             // 检查是否有封面图片流
             const hasCover = metadata.streams.some(stream  =>
@@ -899,13 +921,22 @@ export class Utility {
             try {
               if (hasCover) {
                   //提取封面
-                  await getFFmpegCover(inputPath, imagePath);
-                  imagePath = fileUri.getUriFromPath(imagePath)
-                  videoItem.pixelMapPath  = imagePath;
+                  let isSuccess:boolean= await getFFmpegCover(inputPath, imagePath);
+
+                  if(isSuccess){
+                    imagePath = fileUri.getUriFromPath(imagePath)
+                  }else{
+                    imagePath = ''
+                  }
+                videoItem.pixelMapPath  = imagePath;
               }else if(Utility.isVideoByExtension(inputPath)){
-                //提取封面
-                await getVideoFFmpegCover(inputPath, imagePath);
-                videoItem.mimeType = getFileFormatByPath(inputPath)
+                pixelMap = await Utility.getFetchFrameByTime(inputPath)
+                if(pixelMap!==undefined&&pixelMap!==null){
+                  imagePath = await ImageUtil.savePixelMap(pixelMap,context.filesDir,md5Name)
+                  imagePath = fileUri.getUriFromPath(imagePath)
+                }else{
+                  imagePath = ''
+                }
                 imagePath = fileUri.getUriFromPath(imagePath)
                 videoItem.pixelMapPath  = imagePath;
               }
@@ -1214,19 +1245,7 @@ export class Utility {
   }
 
 
-  static getFileDirName(filePath: string,rootPath:string): string{
-    if(filePath===rootPath){
-      return '首页'
-    }
-    let result = FileUtil.getFileName(filePath)
-    if(StrUtil.isEmpty(result))
-      return ''
-
 
-    if(result.startsWith('.'))
-      result = result.replace(/\./g, '')
-    return result
-  }
 
 
 
@@ -1358,7 +1377,7 @@ export class Utility {
       const documentViewPicker = new picker.DocumentViewPicker()
       let documentSaveResult = await documentViewPicker.save({ pickerMode: picker.DocumentPickerMode.DOWNLOAD })
       let download_path = new fileUri.FileUri(documentSaveResult[0]).path + '/'
-      let filePath = download_path + LocalMusic.STR_LOCK_VIDEO+ '/' + VipPage.VIP_FILEPATH
+      let filePath = download_path + STR_LOCK_VIDEO+ '/' + VIP_FILEPATH
       let expireDate =  Utility.readDataFromFile(filePath)
 
       return expireDate;
@@ -1510,57 +1529,122 @@ function formatDuration(seconds: string, forceHHMMSS: boolean = false): string {
 }
 
 
-// 定义解析结果的数据结构
+
+/**
+ * 定义解析结果的数据结构
+ */
 class MusicInfo {
   artist: string = "";  // 艺术家名称
-  title: string = "";  // 歌曲名称
+  title: string = "";   // 歌曲名称
   isValid: boolean = false;  // 格式是否有效
 }
+
+/**
+ * 精简版常见中文姓氏(音乐场景优化版)
+ */
+const COMMON_CHINESE_SURNAMES = [
+// 超常见姓氏(覆盖约80%人口)
+  '李','王','张','刘','陈','杨','黄','赵','吴','周',
+  '徐','孙','马','朱','胡','林','郭','何','高','罗',
+  '郑','梁','谢','宋','唐','许','韩','邓','曹','彭',
+  '曾','萧','田','董','潘','袁','于','蔡','余','杜',
+
+  // 音乐行业常见姓氏(歌手高频姓)
+  '汪','苏','薛','谭','华','金','魏','陶','姜','窦',
+  '章','毛','易','方','宋','任','沈','贾','江','孔',
+
+  // 组合/乐队常见字
+  '羽','泉','信','乐','花','飞','龙','风','云','草'
+];
+
 /**
- * 解析音乐文件名
- * @param fileName - 待解析的文件名(需包含扩展名)
- * @returns 包含解析结果的MusicInfo对象
+ * 歌手特征关键词(优化版)
  */
+const ARTIST_KEYWORDS = [
+// 中文特征
+  '乐队','组合','乐团','和','&','合唱',' featuring',
+  // 英文特征
+  'feat','ft','with','vs','presents','presents',
+  // 符号特征
+  '×','X','※','◆','♫'
+];
 /**
- * 智能解析音乐文件名(支持多种分隔符和前缀序号)
+ * 智能解析音乐文件名(支持多种分隔符和格式
  * @param fileName - 待解析的完整文件名
  * @returns 结构化音乐信息
  */
+/**
+ * 智能解析音乐文件名
+ */
 function parseMusicFileName(fileName: string): MusicInfo {
-  const result = new MusicInfo();
+  const result: MusicInfo = new MusicInfo();
+  if (!fileName) return result;
 
-  // 1. 预处理:移除首尾空格(保留中间空格)
-  const cleanName = fileName.trim();
+  // 预处理
+  const cleanName: string = fileName.trim();
+  const lastDotIndex: number = cleanName.lastIndexOf('.');
+  const baseName: string = lastDotIndex > 0 ?
+  cleanName.substring(0,  lastDotIndex).trim() :
+    cleanName;
 
-  // 2. 提取文件扩展名(以最后一个点分隔)
-  const lastDotIndex = cleanName.lastIndexOf('.');
-  if (lastDotIndex < 0) return result; // 无扩展名
+  // 支持的分隔符(明确定义类型)
+  const separators: string[] = ['-', '-', '—', '~', '~'];
 
-  const baseName = cleanName.substring(0,  lastDotIndex).trim();
-  const extension = cleanName.substring(lastDotIndex  + 1);
+  // 寻找分隔位置
+  let bestSplitIndex: number = -1;
 
-  // 3. 支持多种分隔符(中英文短横线)
-  const separators = ['-', '-', '—']; // 半角/全角短横线
-  let dashIndex = -1;
-
-  // 查找最后一个有效分隔符位置
   for (const sep of separators) {
-    const index = baseName.lastIndexOf(sep);
-    if (index > dashIndex) dashIndex = index;
+    const index: number = baseName.lastIndexOf(sep);
+    if (index > bestSplitIndex) {
+      bestSplitIndex = index;
+    }
   }
 
-  // 4. 核心解析逻辑
-  if (dashIndex > 0 && dashIndex < baseName.length  - 1) {
-    let artistPart = baseName.substring(0,  dashIndex).trim();
-    result.title  = baseName.substring(dashIndex  + 1).trim();
+  // 分割字符串
+  if (bestSplitIndex > 0 && bestSplitIndex < baseName.length  - 1) {
+    let part1: string = baseName.substring(0,  bestSplitIndex).trim();
+    let part2: string = baseName.substring(bestSplitIndex  + 1).trim();
+
+    // 处理前缀序号
+    part1 = part1.replace(/^\d+[\s\.\-- —~~]*/, '').trim();
 
-    // 5. 处理前缀序号(如"04 - ")
-    const numPrefixRegex = /^\d+\s*[--—]\s*/; // 匹配数字+分隔符组合
-    artistPart = artistPart.replace(numPrefixRegex,  '').trim();
+    // 判断歌手部分(明确定义返回类型)
+    const identifyArtist = (str: string): boolean => {
+      return COMMON_CHINESE_SURNAMES.some((surname:  string) =>
+      str.startsWith(surname)  ||
+      new RegExp(`[ ,,、&&]${surname}`).test(str)
+      ) || ARTIST_KEYWORDS.some((keyword:  string) =>
+      str.includes(keyword)
+      );
+    };
+
+    // 判断歌手位置
+    const part1IsArtist: boolean = identifyArtist(part1);
+    const part2IsArtist: boolean = identifyArtist(part2);
+
+    if (part1IsArtist && !part2IsArtist) {
+      result.artist  = part1;
+      result.title  = part2;
+    } else if (part2IsArtist && !part1IsArtist) {
+      result.artist  = part2;
+      result.title  = part1;
+    } else {
+      result.artist  = part1.length  <= part2.length  ? part1 : part2;
+      result.title  = part1.length  <= part2.length  ? part2 : part1;
+    }
 
-    // 6. 最终有效性验证
-    result.artist  = artistPart;
-    result.isValid  = (result.artist.length  > 0 && result.title.length  > 0);
+    // 后处理
+    result.title  = result.title
+      .replace(/(?:\(|()[^))]*(?:)|\))/g, '')
+      .replace(/\s*[—-]\s*(?:Live|Version|Remix|伴奏).*/i, '')
+      .trim();
+
+    // 有效性验证
+    result.isValid  = result.artist.length  > 0 &&
+      result.title.length  > 0;
+  } else {
+    result.title  = baseName;
+    result.isValid  = result.title.length  > 0;
   }
 
   return result;
@@ -1578,37 +1662,70 @@ function getFileNameWithoutExtension(filePath: string): string {
  * @param inputPath 音乐文件路径
  * @returns Promise<void>
  */
-async function getFFmpegCover(inputPath: string, outputPath: string) {
+// async function getFFmpegCover(inputPath: string, outputPath: string) : Promise<boolean>{
+//   let commands = ["ffmpeg", "-y","-i", inputPath, "-map", "0:v", "-c:v", "copy", outputPath];
+//   FFmpeg.execute(commands, {
+//     logCallback: (logLevel: number, logMessage: string) => {
+//       console.info(`[FFmpeg LOG] [${logLevel}]${logMessage}`)
+//     },
+//     progressCallback: (message: string) => {
+//       console.info(`[FFmpeg progress]${JSON.stringify(FFProgressMessageParser.parse(message))}`)
+//     },
+//   })
+//     .then(() => {
+//       return true
+//       console.info("FFmpeg execution succeeded.");
+//     })
+//     .catch((error: Error) => {
+//       return false
+//       console.error(`FFmpeg execution failed with error: ${error.message}`);
+//     });
+//   return ;
+// }
+
+/**
+ * 从音乐文件中提取封面
+ * @param inputPath 音乐文件路径
+ * @param outputPath 封面输出路径
+ * @returns Promise<boolean> 表示操作是否成功
+ */
+async function getFFmpegCover(inputPath: string, outputPath: string): Promise<boolean> {
   let commands = ["ffmpeg", "-y","-i", inputPath, "-map", "0:v", "-c:v", "copy", outputPath];
-  FFmpeg.execute(commands, {
-    logCallback: (logLevel: number, logMessage: string) => {
-      console.info(`[FFmpeg LOG] [${logLevel}]${logMessage}`)
-    },
-    progressCallback: (message: string) => {
-      console.info(`[FFmpeg progress]${JSON.stringify(FFProgressMessageParser.parse(message))}`)
-    },
-  })
-    .then(() => {
-      console.info("FFmpeg execution succeeded.");
-    })
-    .catch((error: Error) => {
-      console.error(`FFmpeg execution failed with error: ${error.message}`);
+
+  try {
+    await FFmpeg.execute(commands,  {
+      logCallback: (logLevel: number, logMessage: string) => {
+        console.info(`[FFmpeg  LOG] [${logLevel}] ${logMessage}`);
+      },
+      progressCallback: (message: string) => {
+        console.info(`[FFmpeg  progress] ${JSON.stringify(FFProgressMessageParser.parse(message))}`);
+      },
     });
+    console.info("FFmpeg  execution succeeded.");
+    return true;
+  } catch (error) {
+    console.error(`FFmpeg  execution failed with error: ${error instanceof Error ? error.message  : String(error)}`);
+    return false;
+  }
 }
 /**
  * 从视频文件中提取封面 提前视频第5帧的封面
  * @param inputPath 文件路径
  * @returns Promise<void>
  */
-async function getVideoFFmpegCover(inputPath: string, outputPath: string,duration?:string) {
-  let durationText = "00:00:05"
-  if(duration&&Number(duration) >300000){//如果时间超过5分钟,截10s的缩略图
-    durationText = "00:00:10"
-  }
-  if(duration&&Number(duration) <5000){//如果时间小5s,截0s的缩略图
-    durationText = "00:00:01"
-  }
-  let commands = ["ffmpeg", "-y","-i", inputPath, "-ss", "00:00:03", "-t", "1","-r",'1','-q:v','2','-f','image2', outputPath];
+async function getVideoFFmpegCover(inputPath: string, outputPath: string) {
+
+  // 更可靠的命令,专门提取视频第一帧作为封面
+  const commands = [
+    "ffmpeg",
+    "-y",                  // 覆盖输出文件(如果存在)
+    "-i", inputPath,       // 输入文件
+    "-ss", "00:00:00",     // 定位到开始位置
+    "-vframes", "1",       // 只提取1帧
+    "-q:v", "2",           // 高质量JPEG(1-31,2是最高质量)
+    "-f", "image2",        // 强制输出为图像格式
+    outputPath
+  ];
   FFmpeg.execute(commands, {
     logCallback: (logLevel: number, logMessage: string) => {
       console.info(`[FFmpegX LOG] [${logLevel}]${logMessage}`)

+ 7 - 3
entry/src/main/ets/controller/AvSessionController.ets

@@ -19,7 +19,7 @@ import { BusinessError } from '@kit.BasicServicesKit';
 import { avSession } from '@kit.AVSessionKit';
 import { BackgroundTaskManager } from '../common/util/BackgroundTaskManager';
 import { VideoItem } from '../viewmodel/VideoItem';
-import { ImageUtil, PreferencesUtil } from '@pura/harmony-utils';
+import { ImageUtil, PreferencesUtil, StrUtil } from '@pura/harmony-utils';
 import { image } from '@kit.ImageKit';
 import { SettingPage } from '../pages/SettingPage';
 import { Utility } from '../common/util/Utility';
@@ -137,8 +137,12 @@ export class AvSessionController {
       let pixelMapPath:string|undefined = curSource.pixelMapPath
 
       let imagePixMap: PixelMap|string ;
-      if(pixelMapPath){
-        imagePixMap = await ImageUtil.imagePathToPixelMap(pixelMapPath)
+      if(pixelMapPath&&StrUtil.isNotEmpty(pixelMapPath)){
+        if(pixelMapPath.startsWith('http')){
+          imagePixMap =pixelMapPath
+        }else{
+          imagePixMap = await ImageUtil.imagePathToPixelMap(pixelMapPath)
+        }
       }else{
         imagePixMap = await ImageUtil.getPixelMapFromMedia($r('app.media.ic_avatar2'));
       }

+ 153 - 0
entry/src/main/ets/controller/KnockController.ets

@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// [Start knock_controller_create]
+import { harmonyShare, systemShare } from '@kit.ShareKit';
+import { fileUri } from '@kit.CoreFileKit';
+import { BusinessError } from '@kit.BasicServicesKit';
+import { uniformTypeDescriptor } from '@kit.ArkData';
+import { common } from '@kit.AbilityKit';
+// [StartExclude knock_controller_create]
+// import { VIDEO_SOURCES, VideoData } from '../model/VideoData';
+import { window } from '@kit.ArkUI';
+import { VideoItem } from '../viewmodel/VideoItem';
+import Logger from '../common/util/Logger';
+import { LogUtil } from '@pura/harmony-utils';
+
+const TAG = 'KnockController';
+// [EndExclude knock_controller_create]
+export class KnockController {
+  private static controller: KnockController;
+  private context: common.UIAbilityContext | undefined = undefined;
+  // Knock listening status
+  private isKnockListening: boolean = false;
+  private  currentSong: VideoItem | undefined = undefined;
+
+  public static getInstance(context: common.UIAbilityContext): KnockController {
+    if (!KnockController.controller) {
+      KnockController.controller = new KnockController(context);
+    }
+    return KnockController.controller;
+  }
+
+  constructor(context: common.UIAbilityContext) {
+    this.context = context;
+  }
+
+  // [Start share_linking]
+  /**
+   * knock listening callback
+   * @param target After the Huawei Share event is triggered,
+   * you can call back the parameters and share them across devices.
+   */
+  public immersiveCallback(target: harmonyShare.SharableTarget) {
+    // [StartExclude knock_controller_create]
+    // share app linking
+    LogUtil.info('onecold KnockController  碰一碰 ');
+    try {
+       this.currentSong = AppStorage.get('currentSong');
+
+       if(this.currentSong){
+         let mediaData: VideoItem = this.currentSong;
+         let artist = ''
+         if(mediaData.artist){
+           artist = mediaData.artist
+         }
+         // Video thumbnail image sandbox path
+         let coverUri: string = fileUri.getUriFromPath(mediaData.pixelMapPath);
+         console.info('onecold KnockController  碰一碰 coverUri '+coverUri);
+         console.info('onecold KnockController  碰一碰 mediaData.filePath '+fileUri.getUriFromPath(mediaData.filePath));
+         // Get video thumbnail URI path
+         let shareData: systemShare.SharedData = new systemShare.SharedData({
+           utd: uniformTypeDescriptor.UniformDataType.MEDIA,
+           uri: fileUri.getUriFromPath(mediaData.filePath),
+           thumbnailUri: coverUri,
+           title: mediaData.name,
+           description: artist
+         });
+         // Initiate a share
+         target.share(shareData).then(() => {
+           Logger.info(TAG, 'Share link success');
+         }).catch((error: BusinessError) => {
+           Logger.error(TAG, `Share link  error. code: ${error.code}, message: ${error.message}`);
+         });
+       }
+
+
+    } catch (err) {
+      Logger.error(TAG, `Share link exception. code: ${err.code}, message: ${err.message}`);
+    }
+    // [EndExclude knock_controller_create]
+  }
+  // [End share_linking]
+
+  /**
+   *  Add knock listening
+   */
+  public immersiveListening() {
+    if (canIUse('SystemCapability.Collaboration.HarmonyShare') && !this.isKnockListening) {
+      harmonyShare.on('knockShare', (target: harmonyShare.SharableTarget) => {
+        this.immersiveCallback(target);
+      });
+      this.isKnockListening = true;
+    }
+  }
+
+  /**
+   *  remove knock listening
+   */
+  public immersiveDisableListening() {
+    if (canIUse('SystemCapability.Collaboration.HarmonyShare') && this.isKnockListening) {
+      harmonyShare.off('knockShare');
+      this.isKnockListening = false;
+    }
+  }
+
+  /**
+   *  Add knock listening in 2in1 device type.
+   */
+  public immersiveListeningPC() {
+    if (canIUse('SystemCapability.Collaboration.HarmonyShare') && !this.isKnockListening) {
+      window.getLastWindow(this.context).then((data) => {
+        let mainWindowID: number = data.getWindowProperties().id;
+        // harmonyShare.on('knockShare', { windowId:mainWindowID }, (target: harmonyShare.SharableTarget) => {
+        //   this.immersiveCallback(target);
+        // });
+
+        harmonyShare.on('knockShare', (target: harmonyShare.SharableTarget) => {
+          this.immersiveCallback(target);
+        });
+      })
+
+      this.isKnockListening = true;
+    }
+  }
+
+  /**
+   *  Remove knock listening in 2in1 device type.
+   */
+  public immersiveDisableListeningPC() {
+    if (canIUse('SystemCapability.Collaboration.HarmonyShare') && this.isKnockListening) {
+      window.getLastWindow(this.context).then((data) => {
+        let mainWindowID: number = data.getWindowProperties().id;
+        // harmonyShare.off('knockShare', { windowId:mainWindowID });
+        harmonyShare.off('knockShare');
+      })
+
+      this.isKnockListening = false;
+    }
+  }
+}
+// [End knock_controller_create]

+ 76 - 37
entry/src/main/ets/entryability/EntryAbility.ets

@@ -25,6 +25,8 @@ import statusBarManager from '@hms.pcService.statusBarManager';
 import StatusBarViewExtensionAbility from '@hms.pcService.StatusBarViewExtensionAbility';
 import { SpiderMan } from '@simplepeng/spider-man';
 import { smartMobilityCommon } from '@kit.CarKit';
+import { url } from '@kit.ArkTS';
+import { display } from '@kit.ArkUI';
 
 /**
  * 主Ability类,继承自UIAbility
@@ -36,7 +38,9 @@ import { smartMobilityCommon } from '@kit.CarKit';
 export default class EntryAbility extends UIAbility {
     // UI上下文对象,用于获取窗口信息
     private uiContext?: UIContext;
-    private awareness: smartMobilityCommon.SmartMobilityAwareness = smartMobilityCommon.getSmartMobilityAwareness();
+    // private awareness: smartMobilityCommon.SmartMobilityAwareness = smartMobilityCommon.getSmartMobilityAwareness();
+    private awareness: smartMobilityCommon.SmartMobilityAwareness|undefined = canIUse("SystemCapability.CarService.DistributedEngine")?smartMobilityCommon.getSmartMobilityAwareness():undefined;
+
     /**
      * 窗口尺寸变化回调函数
      * @param windowSize 新的窗口尺寸对象
@@ -54,8 +58,8 @@ export default class EntryAbility extends UIAbility {
         let heightBp: HeightBreakpoint = this.uiContext!.getWindowHeightBreakpoint();
         AppStorage.setOrCreate('currentHeightBreakpoint', heightBp);
         // 记录尺寸变化日志
-        LogUtil.info('pura onWindowSizeChange currentHeightBreakpoint= '+heightBp);
-        LogUtil.info( 'pura onWindowSizeChange currentWidthBreakpoint= '+widthBp);
+        // LogUtil.info('pura onWindowSizeChange currentHeightBreakpoint= '+heightBp);
+        // LogUtil.info( 'pura onWindowSizeChange currentWidthBreakpoint= '+widthBp);
         AppStorage.setOrCreate('windowWidth', windowSize.width);
         AppStorage.setOrCreate('windowHeight', windowSize.height);
         if(windowSize.width > windowSize.height){
@@ -63,8 +67,8 @@ export default class EntryAbility extends UIAbility {
         }else{
             AppStorage.setOrCreate('isLandscape', false);
         }
-        LogUtil.info('hicar onWindowSizeChange width= '+windowSize.width);
-        LogUtil.info( 'hicar onWindowSizeChange height= '+windowSize.height);
+        // LogUtil.info('hicar onWindowSizeChange width= '+windowSize.width);
+        // LogUtil.info( 'hicar onWindowSizeChange height= '+windowSize.height);
 
     };
 
@@ -80,6 +84,15 @@ export default class EntryAbility extends UIAbility {
         }
 
     }
+    onDisplayIdChange=(displayId: number)=> {
+        let curDisplay = display.getDisplayByIdSync(displayId);
+        console.info('twocold curDisplay 2 = '+curDisplay.name);
+        if(curDisplay.name =='HiCar'||curDisplay.name =='SuperLauncher'){
+            AppStorage.setOrCreate('curDisplayIsHiCar', true);
+        }else{
+            AppStorage.setOrCreate('curDisplayIsHiCar', false);
+        }
+    }
 
     async onCreate(want:Want, launchParam:AbilityConstant.LaunchParam) {
         AppStorage.setOrCreate('context', this.context);
@@ -87,7 +100,7 @@ export default class EntryAbility extends UIAbility {
         setTimeout(async ()=>{
             this.loadDoWant(want)
             await this.handleParam(want)
-        },1000)
+        },2000)
 
         this.handleWeChatCallIfNeed(want)
 
@@ -110,7 +123,7 @@ export default class EntryAbility extends UIAbility {
 
     //处理其他app点击其他应用打开播放器播放视频或者音频
     loadDoWant(want: Want){
-
+        // console.info('onecold KnockController  碰一碰 want ='+JSON.stringify(want));
         let uri = want.uri;
         if (uri == null || uri == undefined|| StrUtil.isEmpty(uri)) {
             console.info('uri is invalid');
@@ -160,14 +173,17 @@ export default class EntryAbility extends UIAbility {
 
     onDestroy() {
         hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
-        let types: smartMobilityCommon.SmartMobilityType[] = [smartMobilityCommon.SmartMobilityType.CAR_HOP];
-        // 出行连接状态回调函数
-        const callBack = (info: smartMobilityCommon.SmartMobilityInfo) => {
-            hilog.info(0x0000, 'Received smart mobility info: ', JSON.stringify(info));
-        };
-        // 解注册智慧出行连接状态的监听 示例2
-        this.awareness.off('smartMobilityStatus', types, callBack);
-    }
+        if(this.awareness){
+            let types: smartMobilityCommon.SmartMobilityType[] = [smartMobilityCommon.SmartMobilityType.CAR_HOP];
+            // 出行连接状态回调函数
+            const callBack = (info: smartMobilityCommon.SmartMobilityInfo) => {
+                hilog.info(0x0000, 'Received smart mobility info: ', JSON.stringify(info));
+            };
+            // 解注册智慧出行连接状态的监听 示例2
+            this.awareness.off('smartMobilityStatus', types, callBack);
+        }
+        }
+
 
     onWindowStageCreate(windowStage: window.WindowStage) {
         // Main window is created, set main page for this ability
@@ -182,6 +198,14 @@ export default class EntryAbility extends UIAbility {
             // LogUtil.info( 'getMainWindow = ');
             globalThis.windowClass = data // 赋值给全局变量windowClass
 
+            let curDisplay = display.getDisplayByIdSync(windowClass.getWindowProperties().displayId);
+            console.info('twocold curDisplay = '+curDisplay.name);
+            if(curDisplay.name =='HiCar'||curDisplay.name =='SuperLauncher'){
+                AppStorage.setOrCreate('curDisplayIsHiCar', true);
+            }else{
+                AppStorage.setOrCreate('curDisplayIsHiCar', false);
+            }
+
             windowClass.setWindowLayoutFullScreen(true).then(() => {
                 console.info('Succeeded in setting the window layout to full-screen mode.');
             }).catch((e: BusinessError) => {
@@ -203,6 +227,7 @@ export default class EntryAbility extends UIAbility {
 
             LogUtil.info('onecold  topRectHeight = '+topRectHeight);
             windowClass.on('avoidAreaChange', this.onAvoidAreaChange)
+            windowClass.on('displayIdChange', this.onDisplayIdChange)
         })
 
 
@@ -229,8 +254,13 @@ export default class EntryAbility extends UIAbility {
 
                 AppStorage.setOrCreate('windowWidth', data.getWindowProperties().windowRect.width);
                 AppStorage.setOrCreate('windowHeight', data.getWindowProperties().windowRect.height);
-                LogUtil.info('hicar getMainWindow width= '+data.getWindowProperties().windowRect.width);
-                LogUtil.info( 'hicar getMainWindow height= '+data.getWindowProperties().windowRect.height);
+                if(data.getWindowProperties().windowRect.width > data.getWindowProperties().windowRect.height){
+                    AppStorage.setOrCreate('isLandscape', true);
+                }else{
+                    AppStorage.setOrCreate('isLandscape', false);
+                }
+                // LogUtil.info('hicar getMainWindow width= '+data.getWindowProperties().windowRect.width);
+                // LogUtil.info( 'hicar getMainWindow height= '+data.getWindowProperties().windowRect.height);
             }).catch((err: BusinessError) => {
                 console.error(`Failed to obtain the main window. Cause code: ${err.code}, message: ${err.message}`);
             });
@@ -258,32 +288,41 @@ export default class EntryAbility extends UIAbility {
 
 
     getHiCarStatus(){
-        this.awareness = smartMobilityCommon.getSmartMobilityAwareness();
-
-        // 业务类型
-        let types: smartMobilityCommon.SmartMobilityType[] = [smartMobilityCommon.SmartMobilityType.HICAR];
-        // 获取出行业务连接状态
-        let info = this.awareness.getSmartMobilityStatus(types[0]);
-
-        hilog.info(0x0000, 'getHiCarStatus  info: ', JSON.stringify(info));
-        if(info&&info.status==1){
-            AppStorage.setOrCreate('isHiCarStatus', true);
-        }else{
-            AppStorage.setOrCreate('isHiCarStatus', false);
+        if (!this.awareness){
+            this.awareness=canIUse("SystemCapability.CarService.DistributedEngine")?smartMobilityCommon.getSmartMobilityAwareness():undefined;
         }
-
-        // 出行连接状态回调函数
-        const callBack = (info: smartMobilityCommon.SmartMobilityInfo) => {
-            hilog.info(0x0000, 'getHiCarStatus Received smart mobility info: ', JSON.stringify(info));
+        console.log('enter getHiCarStatus,awareness:'+JSON.stringify(this.awareness));
+        if(this.awareness){
+            // this.awareness = smartMobilityCommon.getSmartMobilityAwareness();
+            console.log('enter awareness');
+            // 业务类型
+            let types: smartMobilityCommon.SmartMobilityType[] = [smartMobilityCommon.SmartMobilityType.HICAR];
+            // 获取出行业务连接状态
+            let info = this.awareness.getSmartMobilityStatus(types[0]);
+
+            hilog.info(0x0000, 'getHiCarStatus  info: ', JSON.stringify(info));
             if(info&&info.status==1){
                 AppStorage.setOrCreate('isHiCarStatus', true);
             }else{
                 AppStorage.setOrCreate('isHiCarStatus', false);
             }
-            this.sendChangeEvent()
-        };
-        // 注册智慧出行连接状态的监听
-        this.awareness.on('smartMobilityStatus', types, callBack);
+
+            // 出行连接状态回调函数
+            const callBack = (info: smartMobilityCommon.SmartMobilityInfo) => {
+                hilog.info(0x0000, 'getHiCarStatus Received smart mobility info: ', JSON.stringify(info));
+                if(info&&info.status==1){
+                    AppStorage.setOrCreate('isHiCarStatus', true);
+                }else{
+                    AppStorage.setOrCreate('isHiCarStatus', false);
+                }
+                this.sendChangeEvent()
+            };
+            // 注册智慧出行连接状态的监听
+            this.awareness.on('smartMobilityStatus', types, callBack);
+        }else{
+            AppStorage.setOrCreate('isHiCarStatus', false);
+        }
+
 
 
     }

+ 2 - 2
entry/src/main/ets/pages/AboutPage.ets

@@ -117,8 +117,8 @@ export struct AboutPage{
           // 左右按钮
           Row() {
             Image($r('app.media.menu'))
-              .width(24)
-              .height(24)
+              .width(26)
+              .height(26)
               .margin({ left: 12, right: 8 })
               .onClick(() => {
                 animateTo({ duration: 555 }, () => {

+ 154 - 147
entry/src/main/ets/pages/NewIndex.ets

@@ -1,6 +1,6 @@
 import { AppUtil, DeviceUtil, DisplayUtil, LogUtil, PreferencesUtil, ToastUtil } from '@pura/harmony-utils';
 import TitleBar from '../view/TitleBar';
-import { router } from '@kit.ArkUI';
+import { curves, router } from '@kit.ArkUI';
 import mainViewModel, { MainViewModel } from '../viewmodel/MainViewModel';
 import ItemData from '../viewmodel/ItemData';
 import type { sysResource } from '../viewmodel/ItemData';
@@ -16,7 +16,6 @@ import { common } from '@kit.AbilityKit';
 import { PrintBiddingTokenUtils } from '../common/util/PrintBiddintTokenUtils';
 import { ArrayList } from '@kit.ArkTS';
 import { CSJUtil } from '../common/util/CSJUtil';
-import { LocalMusic } from '../view/LocalMusic';
 import { StreamContent } from '../view/StreamContent';
 import { AvSessionController } from '../controller/AvSessionController';
 import { BreakpointSystem, BreakpointTypeEnum } from '../common/util/BreakpointSystem';
@@ -38,6 +37,8 @@ import { smartMobilityCommon } from '@kit.CarKit';
 import { UpdateLogManager } from '../common/util/UpdateLogManager';
 import OnlineUpdateLogDialog from '../dialog/OnlineUpdateLog';
 import OnlineUpdateLog from '../dialog/OnlineUpdateLog';
+import { LocalMusic } from '../view/LocalMusic';
+
 // import { FFmpeg, FFProgressMessageParser } from '@sj/ffmpeg';
 
 const TAG = 'NewIndex'; // 日志标签
@@ -281,7 +282,7 @@ struct NewIndex {
       Column() {
         this.getLeftView()
       }
-
+      .backgroundColor(Color.Transparent)
       Column() {
         Stack() {
           // 本地音乐内容区
@@ -302,7 +303,10 @@ struct NewIndex {
             Column()
               .width('100%')
               .height('100%')
-              .backgroundColor(Color.Transparent)
+              .backgroundBlurStyle(BlurStyle.BACKGROUND_THIN)
+              .transition(TransitionEffect.OPACITY.animation({
+                curve: curves.springMotion(0, 1)
+              }))
               .onClick(() => {
                 // 点击遮罩层关闭抽屉
                 this.getUIContext()?.animateTo({ duration: 555 }, () => {
@@ -394,8 +398,6 @@ struct NewIndex {
     Column() {
       Column() {
 
-        this.buildUserInfoCard()
-
         this.getDrawerView()
       }
       .width('100%')
@@ -414,7 +416,8 @@ struct NewIndex {
       bottomRight: 20
     })
     // .backgroundColor($r('app.color.silvery'))
-    .backgroundColor($r('app.color.index_background'))
+    // .backgroundColor($r('app.color.index_background'))
+    .backgroundColor($r('app.color.user_center_card_background'))
     .alignItems(HorizontalAlign.Start)
     .translate({ x: this.offsetX, y: 0, z: 0 })
     .transition({ type: TransitionType.Insert, translate: { x: -DisplayUtil.getWidth(), y: 0 } })
@@ -565,152 +568,156 @@ struct NewIndex {
    */
   @Builder
   getDrawerView() {
+
     List({ space: 0, scroller: this.scroller }) {
-      ForEach(this.isHiCar()||!this.isShowTitleBar?mainViewModel.getDrawerData():mainViewModel.getDrawerData2(), (item: ItemData, index: number) => {
-        ListItem() {
-          Button({ type: ButtonType.Capsule, stateEffect: true }) {
-            Row() {
-              // 菜单图标
-              if (typeof item.img === 'object' && item.img !== null && (item.img as sysResource).type === 'symbol') {
-                SymbolGlyph((item.img as sysResource).value as Resource)// .size({ width: 22, height: 22 })
-                  .fontSize(22)
-                  .fontColor([this.themeColor])
-                  .alignSelf(ItemAlign.Center)
-                  .margin({ left: 25 })
-              } else {
-                Image(item.img as Resource)
+      ListItemGroup({ header: this.buildUserInfoCard() }) {
+        ForEach(this.isHiCar()||!this.isShowTitleBar?mainViewModel.getDrawerData():mainViewModel.getDrawerData2(), (item: ItemData, index: number) => {
+          ListItem() {
+            Button({ type: ButtonType.Capsule, stateEffect: true }) {
+              Row() {
+                // 菜单图标
+                if (typeof item.img === 'object' && item.img !== null && (item.img as sysResource).type === 'symbol') {
+                  SymbolGlyph((item.img as sysResource).value as Resource)// .size({ width: 22, height: 22 })
+                    .fontSize(22)
+                    .fontColor([this.themeColor])
+                    .alignSelf(ItemAlign.Center)
+                    .margin({ left: 25 })
+                } else {
+                  Image(item.img as Resource)
+                    .height(22)
+                    .alignSelf(ItemAlign.Center)
+                    .fillColor(this.themeColor)
+                    .margin({ left: 25 })
+                }
+
+                // 菜单标题
+                Text(item.title)
+                  .margin({ left: 10, right: 20 })
+                  .fontSize(15)
+                  .fontColor(this.isTextSelected(index) ? this.themeColor : $r('app.color.index_tab_font_color'))
+                  .fontWeight(480)
+                Blank()
+                // 右侧箭头
+                Image($r('app.media.arrow_right'))
+                  .width(22)
                   .height(22)
-                  .alignSelf(ItemAlign.Center)
-                  .fillColor(this.themeColor)
-                  .margin({ left: 25 })
+                  .margin({ left: 20, right: 0 })
+                  .align(Alignment.Center)
               }
-
-              // 菜单标题
-              Text(item.title)
-                .margin({ left: 10, right: 20 })
-                .fontSize(15)
-                .fontColor(this.isTextSelected(index) ? this.themeColor : $r('app.color.index_tab_font_color'))
-                .fontWeight(480)
-              Blank()
-              // 右侧箭头
-              Image($r('app.media.arrow_right'))
-                .width(22)
-                .height(22)
-                .margin({ left: 20, right: 0 })
-                .align(Alignment.Center)
+              .width('100%')
+              .height(55)
             }
-            .width('100%')
-            .height(55)
-          }
-          .backgroundColor(Color.Transparent)
-          .clickEffect({ level: ClickEffectLevel.MIDDLE,scale:0.6 })
-          .onClick(async () => {
-            // 根据 item.id 跳转或切换功能
-            switch (item.id) {
-              case MainViewModel.MENU_MUSIC:
-                this.mType = 0
-                this.modeType = 0
-                this.doShowDrawer()
-                break
-              case MainViewModel.MENU_FILE_SCAN:
-                this.mType = 2
-                this.doShowDrawer()
-                break
-            // case MainViewModel.MENU_HOME:
-            //   this.mType = 0
-            //   this.modeType = 0
-            //   this.getUIContext()?.animateTo({ duration: 555 }, () => {
-            //     this.isShowDrawer = false
-            //   })
-            //   break
-              case MainViewModel.MENU_MIEDIA_KU:
-                this.modeType = 1
-                this.mType = 0
-                this.doShowDrawer()
-                break
-              case MainViewModel.MENU_MIEDIA_ARTIST:
-                this.modeType = 2
-                this.mType = 0
-                this.doShowDrawer()
-                break
-              case MainViewModel.MENU_MIEDIA_ALBUM:
-                this.modeType = 3
-                this.mType = 0
-                this.doShowDrawer()
-                break
-              case MainViewModel.MENU_SETTING:
-                this.mType = 3
-                this.doShowDrawer()
-
-                break
-              case MainViewModel.MENU_VIP:
-                router.pushUrl({
-                  url: 'pages/VipPage'
-                }, router.RouterMode.Single);
-                break
-              case MainViewModel.MENU_USER:
-                this.mType = 1
-                this.doShowDrawer()
-                break
-              case MainViewModel.MENU_NET_CONNECT:
-                this.mType = 1
-                this.doShowDrawer()
-                break
-              case MainViewModel.MENU_SIMI:
-                router.pushUrl({
-                  url: 'pages/VerifyPage'
-                });
-                break
-
-              case MainViewModel.MENU_DUTY:
-                router.pushUrl({
-                  url: 'pages/WebIndex',
-                  params: { titleName: '用户协议', webUrl: CommonConstants.NEW_DUTY }
-                });
-                break
-              case MainViewModel.MENU_HAOPING:
-                Utility.gotoMarket(getContext(this) as common.UIAbilityContext, this.bundleName)
-                break
-
-              case MainViewModel.MENU_ABOUT:
-                this.mType = 4
-                this.doShowDrawer()
-                break
-              case MainViewModel.MENU_UPDATE:
-                AlertDialog.show({
-                  title: '版本更新',
-                  message: '当前版本为最新版本:' + this.versionName,
-                  autoCancel: true,
-                  alignment: DialogAlignment.Center,
-                  offset: { dx: 0, dy: -20 }, //在Y轴方向上的编译量
-                  confirm: {
-                    value: '确定',
-                    fontColor: Color.White,
-                    backgroundColor: $r('app.color.title_bar_bg'),
-                    action: () => {
+            .backgroundColor(Color.Transparent)
+            .clickEffect({ level: ClickEffectLevel.MIDDLE,scale:0.6 })
+            .onClick(async () => {
+              // 根据 item.id 跳转或切换功能
+              switch (item.id) {
+                case MainViewModel.MENU_MUSIC:
+                  this.mType = 0
+                  this.modeType = 0
+                  this.doShowDrawer()
+                  break
+                case MainViewModel.MENU_FILE_SCAN:
+                  this.mType = 2
+                  this.doShowDrawer()
+                  break
+                // case MainViewModel.MENU_HOME:
+                //   this.mType = 0
+                //   this.modeType = 0
+                //   this.getUIContext()?.animateTo({ duration: 555 }, () => {
+                //     this.isShowDrawer = false
+                //   })
+                //   break
+                case MainViewModel.MENU_MIEDIA_KU:
+                  this.modeType = 1
+                  this.mType = 0
+                  this.doShowDrawer()
+                  break
+                case MainViewModel.MENU_MIEDIA_ARTIST:
+                  this.modeType = 2
+                  this.mType = 0
+                  this.doShowDrawer()
+                  break
+                case MainViewModel.MENU_MIEDIA_ALBUM:
+                  this.modeType = 3
+                  this.mType = 0
+                  this.doShowDrawer()
+                  break
+                case MainViewModel.MENU_SETTING:
+                  this.mType = 3
+                  this.doShowDrawer()
+
+                  break
+                case MainViewModel.MENU_VIP:
+                  router.pushUrl({
+                    url: 'pages/VipPage'
+                  }, router.RouterMode.Single);
+                  break
+                case MainViewModel.MENU_USER:
+                  this.mType = 1
+                  this.doShowDrawer()
+                  break
+                case MainViewModel.MENU_NET_CONNECT:
+                  this.mType = 1
+                  this.doShowDrawer()
+                  break
+                case MainViewModel.MENU_SIMI:
+                  router.pushUrl({
+                    url: 'pages/VerifyPage'
+                  });
+                  break
+
+                case MainViewModel.MENU_DUTY:
+                  router.pushUrl({
+                    url: 'pages/WebIndex',
+                    params: { titleName: '用户协议', webUrl: CommonConstants.NEW_DUTY }
+                  });
+                  break
+                case MainViewModel.MENU_HAOPING:
+                  Utility.gotoMarket(getContext(this) as common.UIAbilityContext, this.bundleName)
+                  break
+
+                case MainViewModel.MENU_ABOUT:
+                  this.mType = 4
+                  this.doShowDrawer()
+                  break
+                case MainViewModel.MENU_UPDATE:
+                  AlertDialog.show({
+                    title: '版本更新',
+                    message: '当前版本为最新版本:' + this.versionName,
+                    autoCancel: true,
+                    alignment: DialogAlignment.Center,
+                    offset: { dx: 0, dy: -20 }, //在Y轴方向上的编译量
+                    confirm: {
+                      value: '确定',
+                      fontColor: Color.White,
+                      backgroundColor: $r('app.color.title_bar_bg'),
+                      action: () => {
+                      }
                     }
-                  }
-                })
-                break
-              case MainViewModel.MENU_YSZC:
-                router.pushUrl({
-                  url: 'pages/WebIndex',
-                  params: { titleName: '隐私政策', webUrl: CommonConstants.NEW_YS_HW }
-                });
-                break
-
-              case MainViewModel.MENU_SHARE:
-                this.gotoShare()
-                break
-            }
-          })
-        }
-        .transition(TransitionEffect.move(TransitionEdge.BOTTOM)
-          .animation({ duration: 600, curve: Curve.Ease, delay: 60 * index }))
-        .width('90%')
-        .height(55)
+                  })
+                  break
+                case MainViewModel.MENU_YSZC:
+                  router.pushUrl({
+                    url: 'pages/WebIndex',
+                    params: { titleName: '隐私政策', webUrl: CommonConstants.NEW_YS_HW }
+                  });
+                  break
+
+                case MainViewModel.MENU_SHARE:
+                  this.gotoShare()
+                  break
+              }
+            })
+          }
+          .transition(TransitionEffect.move(TransitionEdge.BOTTOM)
+            .animation({ duration: 600, curve: Curve.Ease, delay: 60 * index }))
+          .width('90%')
+          .height(55)
+
+        })
+      }
 
-      })
     }
     .width('86%')
     .borderRadius(20)

+ 87 - 49
entry/src/main/ets/pages/ScanFilePage.ets

@@ -5,12 +5,11 @@ import lottie from '@ohos/lottie'
 import { AnimationItem } from '@ohos/lottie'
 import { MessageEvents, taskpool, worker } from '@kit.ArkTS'
 import { fileUri, picker } from '@kit.CoreFileKit'
-import { LocalMusic } from '../view/LocalMusic'
 import { Utility } from '../common/util/Utility'
 import MediaTable from '../common/util/MediaTable'
 import { VideoItem } from '../viewmodel/VideoItem'
 import Logger from '../common/util/Logger'
-import { CommonConstants } from '../common/constants/CommonConstants'
+import { CommonConstants, STR_LOCK_VIDEO } from '../common/constants/CommonConstants'
 import { emitter } from '@kit.BasicServicesKit'
 import { BreakpointTypeEnum } from '../common/util/BreakpointSystem'
 import { resourceManager } from '@kit.LocalizationKit'
@@ -83,7 +82,7 @@ export struct ScanFilePage{
     let documentSaveResult = await documentViewPicker.save({ pickerMode: picker.DocumentPickerMode.DOWNLOAD })
     this.rootPath = new fileUri.FileUri(documentSaveResult[0]).path
 
-    this.lockPath =  this.rootPath +'/'+ LocalMusic.STR_LOCK_VIDEO
+    this.lockPath =  this.rootPath +'/'+ STR_LOCK_VIDEO
     LogUtil.info('onecold 文件扫描 aboutToAppear')
     this.initLottie(this.path,true)
     setTimeout(()=>{
@@ -220,8 +219,8 @@ export struct ScanFilePage{
                 this.mainCanvasRenderingContext.imageSmoothingQuality = 'medium'
               })
           }
-          .transition(TransitionEffect.move(TransitionEdge.BOTTOM)
-            .animation({ duration: 380, curve: Curve.Ease,delay:30 }))
+          .transition(TransitionEffect.move(TransitionEdge.END)
+            .animation({ duration: 380, curve: Curve.Ease,delay:300 }))
 
           Text(this.strText)
             .height(50)
@@ -230,21 +229,35 @@ export struct ScanFilePage{
             .fontWeight(480)
             .visibility(this.textVisi)
 
-          Button($r('app.string.start_scan'), { type: ButtonType.Capsule, stateEffect: false })
+          Button({ type: ButtonType.Capsule, stateEffect: true }) {
+            Row(){
+              SymbolGlyph($r('sys.symbol.magnifyingglass'))
+                .fontSize(22)
+                .fontColor([Color.White])
+              Text($r('app.string.start_scan'))
+                .margin({ left: 8 })
+                .fontSize(18)
+                .fontColor(Color.White)
+                .fontWeight(480)
+                .textAlign(TextAlign.Center)
+            }
+            .justifyContent(FlexAlign.Center)
+          }
+          .width(180)
+          .height(55)
+          .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.5})
+          .margin({ top: 10, bottom: 10 })
+          .backgroundColor(this.themeColor)
+          .enabled(this.isStart ?false:true)
+          .onClick(() => {
+            this.doOptimize(false)
+
+          })
+          .alignSelf(ItemAlign.Center)
+          .transition(TransitionEffect.move(TransitionEdge.END)
+            .animation({ duration: 380, curve: Curve.Ease,delay:300 }))
 
-            .width(180)
-            .height(55)
-            .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.5})
-            .margin({ top: 10, bottom: 10 })
-            .backgroundColor(this.themeColor)
-            .enabled(this.isStart ?false:true)
-            .onClick(() => {
-              this.doOptimize(false)
 
-            })
-            .alignSelf(ItemAlign.Center)
-            .transition(TransitionEffect.move(TransitionEdge.BOTTOM)
-              .animation({ duration: 380, curve: Curve.Ease,delay:30 }))
 
           Column() {
             Row() {
@@ -315,46 +328,71 @@ export struct ScanFilePage{
           .margin({ left:25,right: 25,top:20,bottom:20  })
           .borderRadius(20)
           .justifyContent(FlexAlign.Center)
-          .transition(TransitionEffect.move(TransitionEdge.BOTTOM)
-            .animation({ duration: 380, curve: Curve.Ease,delay:60 }))
+          .transition(TransitionEffect.move(TransitionEdge.END)
+            .animation({ duration: 380, curve: Curve.Ease,delay:300 }))
 
           Row() {
 
+            Button({ type: ButtonType.Capsule, stateEffect: true }) {
+              Row(){
+                SymbolGlyph($r('sys.symbol.picture'))
+                  .fontSize(19)
+                  .fontColor([Color.White])
+                Text($r('app.string.onekey_cover'))
+                  .margin({ left: 4 })
+                  .fontSize(15)
+                  .fontColor(Color.White)
+                  .fontWeight(480)
+                  .textAlign(TextAlign.Center)
+              }
+              .justifyContent(FlexAlign.Center)
+            }
+            .width(150)
+            .height(55)
+            .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.5})
+            .margin({ top: 10, bottom: 10,right:10 })
+            .backgroundColor(this.themeColor)
+            .enabled(this.isStartCover ?false:true)
+            .onClick(() => {
+              if(PreferencesUtil.getStringSync('COVER_API','')===''){
+                this.showTipsDialog()
+                return
+              }
+              this.doOptimize(true)
 
-            Button($r('app.string.onekey_cover'), { type: ButtonType.Capsule, stateEffect: false })
-              .width(150)
-              .height(55)
-              .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.5})
-              .margin({ top: 10, bottom: 10,right:10 })
-              .backgroundColor(this.themeColor)
-              .enabled(this.isStartCover ?false:true)
-              .onClick(() => {
-                if(PreferencesUtil.getStringSync('COVER_API','')===''){
-                  this.showTipsDialog()
-                  return
-                }
-                this.doOptimize(true)
-
-              })
-              .alignSelf(ItemAlign.Center)
+            })
+            .alignSelf(ItemAlign.Center)
 
-            Button($r('app.string.sync_data'), { type: ButtonType.Capsule, stateEffect: false })
-              .width(150)
-              .height(55)
-              .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.5})
-              .margin({ left:10,top: 10, bottom: 10 })
-              .backgroundColor(this.themeColor)
-              .enabled(this.isStartSync ?false:true)
-              .onClick(() => {
-                this.doSyncData()
+            Button({ type: ButtonType.Capsule, stateEffect: true }) {
+              Row(){
+                SymbolGlyph($r('sys.symbol.arrow_counterclockwise'))
+                  .fontSize(19)
+                  .fontColor([Color.White])
+                Text($r('app.string.sync_data'))
+                  .margin({ left: 4 })
+                  .fontSize(15)
+                  .fontColor(Color.White)
+                  .fontWeight(480)
+                  .textAlign(TextAlign.Center)
+              }
+              .justifyContent(FlexAlign.Center)
+            }
+            .width(150)
+            .height(55)
+            .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.5})
+            .margin({ top: 10, bottom: 10,right:10 })
+            .backgroundColor(this.themeColor)
+            .enabled(this.isStartSync ?false:true)
+            .onClick(() => {
+              this.doSyncData()
 
-              })
-              .alignSelf(ItemAlign.Center)
+            })
+            .alignSelf(ItemAlign.Center)
 
 
           }
-          .transition(TransitionEffect.move(TransitionEdge.BOTTOM)
-            .animation({ duration: 380, curve: Curve.Ease,delay:90 }))
+          .transition(TransitionEffect.move(TransitionEdge.END)
+            .animation({ duration: 380, curve: Curve.Ease,delay:300 }))
 
         }
 

+ 271 - 87
entry/src/main/ets/pages/SettingPage.ets

@@ -38,7 +38,7 @@ export struct SettingPage {
   static readonly IS_CUSTOMIZE_BG: string = 'is_customize_bg';
   static readonly IS_GRID_MUSIC: string = 'is_grid_music';
   static readonly IS_CUSTOMIZE_BG_PATH: string = 'is_customize_bg_path';
-  static readonly IS_SCROLL_HIDE: string = 'isScrollHide';
+  static readonly IS_SCROLL_HIDE: string = 'isAutoScrollHide';
   static readonly IS_SAMETIME_PLAY: string = 'isSameTimePlay';
   static readonly CUSTOMIZE_BG_BLUR: string = 'customize_bg_blur';
   static readonly BG_BRIGHTNESS: string = 'bg_brightness';
@@ -56,6 +56,7 @@ export struct SettingPage {
   public static IS_PLAYLIST_BG_GRASS: string = 'isPlayListBgGrass';
   static readonly IS_SWIPE: string = 'isSwipe'
   static readonly IS_AUTO_HIDE_PROGRESS: string = 'IS_AUTO_HIDE_PROGRESS';
+  public static OPEN_SKIPSONG_ANIMATE: string = 'openSkipSongAnimate';
 
   public static THEME_COLOR_LIST: Array<ThemeColorItem> = [
     { name: '玫瑰粉', color: '#FF4081', isVip: false },
@@ -114,6 +115,7 @@ export struct SettingPage {
   @State isSwipe: boolean = false //listItem的左滑开关
   @State isPlayListBgGrass: boolean = true//是否播放列表玻璃透明效果
   @State is_auto_hide_progress: boolean = false
+  @State openSkipSongAnimate: boolean = true//切歌动画效果
 
 
   @State customizeBgPath: string | undefined = '';
@@ -235,6 +237,7 @@ export struct SettingPage {
     this.isPlayListBgGrass = PreferencesUtil.getBooleanSync(SettingPage.IS_PLAYLIST_BG_GRASS, true)
     this.isSwipe = PreferencesUtil.getBooleanSync(SettingPage.IS_SWIPE, true)
     this.is_auto_hide_progress = PreferencesUtil.getBooleanSync(SettingPage.IS_AUTO_HIDE_PROGRESS, false)
+    this.openSkipSongAnimate = PreferencesUtil.getBooleanSync(SettingPage.OPEN_SKIPSONG_ANIMATE, true)
     // 只用 themeMode 控制主题
     this.themeMode = PreferencesUtil.getNumberSync(SettingPage.THEME_MODE, 0)
     this.applyThemeMode(this.themeMode)
@@ -386,11 +389,10 @@ export struct SettingPage {
       // 主题色分组卡片
       Column() {
         Row() {
+          SymbolGlyph($r('sys.symbol.paintpalette'))
+            .fontSize(20)
+            .fontColor([this.themeColor])
 
-          Image($r('app.media.theme'))
-            .width(20)
-            .height(20)
-            .fillColor(this.themeColor)
           Text('主题色')
             .fontSize(15)
             .fontWeight(500)
@@ -535,8 +537,8 @@ export struct SettingPage {
         // 左侧返回按钮
         Row() {
           Image($r('app.media.menu'))
-            .width(29)
-            .height(29)
+            .width(26)
+            .height(26)
             .margin({ left: 12, right: 8 })
             .onClick(() => {
               animateTo({ duration: 555 }, () => {
@@ -573,9 +575,15 @@ export struct SettingPage {
             Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
             // 主题设置弹框入口
             Button({ type: ButtonType.Normal, stateEffect: true }) {
+
               Row() {
+                SymbolGlyph($r('sys.symbol.sun_max'))
+                  .fontSize(20)
+                  .fontColor([this.themeColor])
+                  .alignSelf(ItemAlign.Center)
+                  .margin({ left: 15 })
                 Text('主题设置')
-                  .margin({ left: 18 })
+                  .margin({ left: 8 })
                   .fontSize(15)
                   .fontColor(Color.Gray)
                   .fontWeight(480)
@@ -611,8 +619,13 @@ export struct SettingPage {
             Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
             Button({ type: ButtonType.Normal, stateEffect: true }) {
               Row() {
+                SymbolGlyph($r('sys.symbol.paintpalette'))
+                  .fontSize(20)
+                  .fontColor([this.themeColor])
+                  .alignSelf(ItemAlign.Center)
+                  .margin({ left: 15 })
                 Text('自定义背景')
-                  .margin({ left: 18 })
+                  .margin({ left: 8 })
                   .fontSize(15)
                   .fontColor(Color.Gray)
                   .fontWeight(480)
@@ -650,35 +663,41 @@ export struct SettingPage {
             Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
 
             // 滚动隐藏'
-            Row() {
-              Text('滚动隐藏')
-                .margin({ left: 18 })
-                .fontSize(15)
-                .fontColor(Color.Gray)
-                .fontWeight(480)
-                .layoutWeight(1)
-              Toggle({ type: ToggleType.Switch, isOn: this.isScrollHide })
-                .selectedColor(this.themeColor)
-                .switchPointColor(Color.White)
-                .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.5})
-                .margin({ right: 18 })
-                .onChange((checked: boolean) => {
-                  this.isScrollHide = checked;
-                  PreferencesUtil.put(SettingPage.IS_SCROLL_HIDE, this.isScrollHide)
-                  this.sendChangeEvent()
-                })
-                .width(50)
-                .height(30);
-            }
-            .height(55)
-            .clickEffect({ level: ClickEffectLevel.HEAVY })
-
-            Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
-
+            // Row() {
+            //   Text('滚动隐藏')
+            //     .margin({ left: 18 })
+            //     .fontSize(15)
+            //     .fontColor(Color.Gray)
+            //     .fontWeight(480)
+            //     .layoutWeight(1)
+            //   Toggle({ type: ToggleType.Switch, isOn: this.isScrollHide })
+            //     .selectedColor(this.themeColor)
+            //     .switchPointColor(Color.White)
+            //     .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.5})
+            //     .margin({ right: 18 })
+            //     .onChange((checked: boolean) => {
+            //       this.isScrollHide = checked;
+            //       PreferencesUtil.put(SettingPage.IS_SCROLL_HIDE, this.isScrollHide)
+            //       this.sendChangeEvent()
+            //     })
+            //     .width(50)
+            //     .height(30);
+            // }
+            // .height(55)
+            // .visibility(Visibility.None)
+            // .clickEffect({ level: ClickEffectLevel.HEAVY })
+            //
+            // Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
+            //   .visibility(Visibility.None)
             // 网格布局
             Row() {
-              Text('网格模式')
-                .margin({ left: 18 })
+              SymbolGlyph($r('sys.symbol.square_grid_2x2'))
+                .fontSize(20)
+                .fontColor([this.themeColor])
+                .alignSelf(ItemAlign.Center)
+                .margin({ left: 15 })
+              Text('卡片模式')
+                .margin({ left: 8 })
                 .fontSize(15)
                 .fontColor(Color.Gray)
                 .fontWeight(480)
@@ -701,8 +720,13 @@ export struct SettingPage {
             Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
             // 封面方形
             Row() {
+              SymbolGlyph($r('sys.symbol.rectangle'))
+                .fontSize(20)
+                .fontColor([this.themeColor])
+                .alignSelf(ItemAlign.Center)
+                .margin({ left: 15 })
               Text('封面方形')
-                .margin({ left: 18 })
+                .margin({ left: 8 })
                 .fontSize(15)
                 .fontColor(Color.Gray)
                 .fontWeight(480)
@@ -726,8 +750,13 @@ export struct SettingPage {
             Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
             //播放列表透明
             Row() {
+              SymbolGlyph($r('sys.symbol.circle_lefthalf_inset_filled'))
+                .fontSize(20)
+                .fontColor([this.themeColor])
+                .alignSelf(ItemAlign.Center)
+                .margin({ left: 15 })
               Text('播放列表背景透明')
-                .margin({ left: 18 })
+                .margin({ left: 8 })
                 .fontSize(15)
                 .fontColor(Color.Gray)
                 .fontWeight(480)
@@ -752,8 +781,13 @@ export struct SettingPage {
 
             // 网格封面大
             Row() {
+              SymbolGlyph($r('sys.symbol.picture'))
+                .fontSize(20)
+                .fontColor([this.themeColor])
+                .alignSelf(ItemAlign.Center)
+                .margin({ left: 15 })
               Text('列表封面大小')
-                .margin({ left: 18 })
+                .margin({ left: 8 })
                 .fontSize(15)
                 .fontColor(Color.Gray)
                 .fontWeight(480)
@@ -780,8 +814,13 @@ export struct SettingPage {
             Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
             // 封面顶部
             Row() {
+              SymbolGlyph($r('sys.symbol.arrowshape_up'))
+                .fontSize(20)
+                .fontColor([this.themeColor])
+                .alignSelf(ItemAlign.Center)
+                .margin({ left: 15 })
               Text('封面顶部')
-                .margin({ left: 18 })
+                .margin({ left: 8 })
                 .fontSize(15)
                 .fontColor(Color.Gray)
                 .fontWeight(480)
@@ -811,8 +850,13 @@ export struct SettingPage {
                 })
               // 封面顶部
               Row() {
+                SymbolGlyph($r('sys.symbol.shutter_photo'))
+                  .fontSize(20)
+                  .fontColor([this.themeColor])
+                  .alignSelf(ItemAlign.Center)
+                  .margin({ left: 15 })
                 Text('顶部大封面')
-                  .margin({ left: 18 })
+                  .margin({ left: 8 })
                   .fontSize(15)
                   .fontColor(Color.Gray)
                   .fontWeight(480)
@@ -842,13 +886,48 @@ export struct SettingPage {
                 curve: 'ease-in-out' // 可选动画曲线
               })
 
+            Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
+
+            // 切歌动画效果
+            Row() {
+              SymbolGlyph($r('sys.symbol.music'))
+                .fontSize(20)
+                .fontColor([this.themeColor])
+                .alignSelf(ItemAlign.Center)
+                .margin({ left: 15 })
+              Text('切歌动画效果')
+                .margin({ left: 8 })
+                .fontSize(15)
+                .fontColor(Color.Gray)
+                .fontWeight(480)
+                .layoutWeight(1)
+              Toggle({ type: ToggleType.Switch, isOn: this.openSkipSongAnimate })
+                .selectedColor(this.themeColor)
+                .switchPointColor(Color.White)
+                .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.5})
+                .margin({ right: 18 })
+                .onChange((checked: boolean) => {
+                  this.openSkipSongAnimate = checked;
+                  PreferencesUtil.put(SettingPage.OPEN_SKIPSONG_ANIMATE, this.openSkipSongAnimate)
+                  this.sendChangeEvent()
+                })
+                .width(50)
+                .height(30);
+            }
+            .height(55)
+            .clickEffect({ level: ClickEffectLevel.HEAVY })
 
             Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
 
             // 圆形播放按钮
             Row() {
+              SymbolGlyph($r('sys.symbol.circle'))
+                .fontSize(20)
+                .fontColor([this.themeColor])
+                .alignSelf(ItemAlign.Center)
+                .margin({ left: 15 })
               Text('圆形播放按钮')
-                .margin({ left: 18 })
+                .margin({ left: 8 })
                 .fontSize(15)
                 .fontColor(Color.Gray)
                 .fontWeight(480)
@@ -900,8 +979,13 @@ export struct SettingPage {
             Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
             // 启动时播放
             Row() {
+              SymbolGlyph($r('sys.symbol.play_circle'))
+                .fontSize(20)
+                .fontColor([this.themeColor])
+                .alignSelf(ItemAlign.Center)
+                .margin({ left: 15 })
               Text('启动时播放')
-                .margin({ left: 18 })
+                .margin({ left: 8 })
                 .fontSize(15)
                 .fontColor(Color.Gray)
                 .fontWeight(480)
@@ -925,8 +1009,13 @@ export struct SettingPage {
             Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
             // 列表是否可左滑
             Row() {
+              SymbolGlyph($r('sys.symbol.indentation_left'))
+                .fontSize(20)
+                .fontColor([this.themeColor])
+                .alignSelf(ItemAlign.Center)
+                .margin({ left: 15 })
               Text('列表是否可左滑')
-                .margin({ left: 18 })
+                .margin({ left: 8 })
                 .fontSize(15)
                 .fontColor(Color.Gray)
                 .fontWeight(480)
@@ -949,8 +1038,13 @@ export struct SettingPage {
             Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
             // 记住播放进度
             Row() {
+              SymbolGlyph($r('sys.symbol.rectangle_split_3x1'))
+                .fontSize(20)
+                .fontColor([this.themeColor])
+                .alignSelf(ItemAlign.Center)
+                .margin({ left: 15 })
               Text('记住最后一首进度')
-                .margin({ left: 18 })
+                .margin({ left: 8 })
                 .fontSize(15)
                 .fontColor(Color.Gray)
                 .fontWeight(480)
@@ -974,8 +1068,13 @@ export struct SettingPage {
             Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
             // 记忆播放
             Row() {
+              SymbolGlyph($r('sys.symbol.route_plan'))
+                .fontSize(20)
+                .fontColor([this.themeColor])
+                .alignSelf(ItemAlign.Center)
+                .margin({ left: 15 })
               Text('记忆播放')
-                .margin({ left: 18 })
+                .margin({ left: 8 })
                 .fontSize(15)
                 .fontColor(Color.Gray)
                 .fontWeight(480)
@@ -1001,8 +1100,13 @@ export struct SettingPage {
 
             // 长按默认倍数
             Row() {
+              SymbolGlyph($r('sys.symbol.timer'))
+                .fontSize(20)
+                .fontColor([this.themeColor])
+                .alignSelf(ItemAlign.Center)
+                .margin({ left: 15 })
               Text('长按默认倍数')
-                .margin({ left: 18 })
+                .margin({ left: 8 })
                 .fontSize(15)
                 .fontColor(Color.Gray)
                 .fontWeight(480)
@@ -1039,8 +1143,13 @@ export struct SettingPage {
             Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
             // 默认排序模式
             Row() {
+              SymbolGlyph($r('sys.symbol.text_and_arrow_down'))
+                .fontSize(20)
+                .fontColor([this.themeColor])
+                .alignSelf(ItemAlign.Center)
+                .margin({ left: 15 })
               Text('默认排序模式')
-                .margin({ left: 18 })
+                .margin({ left: 8 })
                 .fontSize(15)
                 .fontColor(Color.Gray)
                 .fontWeight(480)
@@ -1071,8 +1180,13 @@ export struct SettingPage {
             Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
             // 保存播放模式
             Row() {
+              SymbolGlyph($r('sys.symbol.clock'))
+                .fontSize(20)
+                .fontColor([this.themeColor])
+                .alignSelf(ItemAlign.Center)
+                .margin({ left: 15 })
               Text('保存播放模式')
-                .margin({ left: 18 })
+                .margin({ left: 8 })
                 .fontSize(15)
                 .fontColor(Color.Gray)
                 .fontWeight(480)
@@ -1095,8 +1209,13 @@ export struct SettingPage {
             Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
               .visibility(Visibility.None)
             Row() {
+              SymbolGlyph($r('sys.symbol.sun_max'))
+                .fontSize(20)
+                .fontColor([this.themeColor])
+                .alignSelf(ItemAlign.Center)
+                .margin({ left: 15 })
               Text('与其他应用同时播放')
-                .margin({ left: 18 })
+                .margin({ left: 8 })
                 .fontSize(15)
                 .fontColor(Color.Gray)
                 .fontWeight(480)
@@ -1120,8 +1239,13 @@ export struct SettingPage {
             Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
             // 播放背景随音乐封面
             Row() {
+              SymbolGlyph($r('sys.symbol.paperplane'))
+                .fontSize(20)
+                .fontColor([this.themeColor])
+                .alignSelf(ItemAlign.Center)
+                .margin({ left: 15 })
               Text('播放背景随音乐封面')
-                .margin({ left: 18 })
+                .margin({ left: 8 })
                 .fontSize(15)
                 .fontColor(Color.Gray)
                 .fontWeight(480)
@@ -1207,8 +1331,13 @@ export struct SettingPage {
 
 
       Row() {
+        SymbolGlyph($r('sys.symbol.text_clipboard'))
+          .fontSize(20)
+          .fontColor([this.themeColor])
+          .alignSelf(ItemAlign.Center)
+          .margin({ left: 15 })
         Text('显示分类导航')
-          .margin({ left: 18 })
+          .margin({ left: 8 })
           .fontSize(15)
           .fontColor(Color.Gray)
           .fontWeight(480)
@@ -1232,8 +1361,13 @@ export struct SettingPage {
       Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
 
       Row() {
+        SymbolGlyph($r('sys.symbol.label'))
+          .fontSize(20)
+          .fontColor([this.themeColor])
+          .alignSelf(ItemAlign.Center)
+          .margin({ left: 15 })
         Text('显示播放全部')
-          .margin({ left: 18 })
+          .margin({ left: 8 })
           .fontSize(15)
           .fontColor(Color.Gray)
           .fontWeight(480)
@@ -1257,8 +1391,13 @@ export struct SettingPage {
       Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
       // 显示私密音频
       Row() {
+        SymbolGlyph($r('sys.symbol.lock'))
+          .fontSize(20)
+          .fontColor([this.themeColor])
+          .alignSelf(ItemAlign.Center)
+          .margin({ left: 15 })
         Text('显示私密音频')
-          .margin({ left: 18 })
+          .margin({ left: 8 })
           .fontSize(15)
           .fontColor(Color.Gray)
           .fontWeight(480)
@@ -1282,8 +1421,13 @@ export struct SettingPage {
       Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
       // 播放页单行歌词
       Row() {
+        SymbolGlyph($r('sys.symbol.close_sidebar'))
+          .fontSize(20)
+          .fontColor([this.themeColor])
+          .alignSelf(ItemAlign.Center)
+          .margin({ left: 15 })
         Text('播放页单行歌词')
-          .margin({ left: 18 })
+          .margin({ left: 8 })
           .fontSize(15)
           .fontColor(Color.Gray)
           .fontWeight(480)
@@ -1308,8 +1452,13 @@ export struct SettingPage {
 
       // 二级菜单新风格
       Row() {
+        SymbolGlyph($r('sys.symbol.satellite_map'))
+          .fontSize(20)
+          .fontColor([this.themeColor])
+          .alignSelf(ItemAlign.Center)
+          .margin({ left: 15 })
         Text('二级菜单新风格')
-          .margin({ left: 18 })
+          .margin({ left: 8 })
           .fontSize(15)
           .fontColor(Color.Gray)
           .fontWeight(480)
@@ -1333,8 +1482,13 @@ export struct SettingPage {
       Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
       // 播放页返回键
       Row() {
+        SymbolGlyph($r('sys.symbol.arrow_left'))
+          .fontSize(20)
+          .fontColor([this.themeColor])
+          .alignSelf(ItemAlign.Center)
+          .margin({ left: 15 })
         Text('显示播放页返回键')
-          .margin({ left: 18 })
+          .margin({ left: 8 })
           .fontSize(15)
           .fontColor(Color.Gray)
           .fontWeight(480)
@@ -1356,35 +1510,45 @@ export struct SettingPage {
       .clickEffect({ level: ClickEffectLevel.HEAVY })
 
       Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
-      // 自动隐藏进度条两侧的按钮
-      Row() {
-        Text('自动隐藏进度条两侧的按钮')
-          .margin({ left: 18 })
-          .fontSize(15)
-          .fontColor(Color.Gray)
-          .fontWeight(480)
-          .layoutWeight(1)
-        Toggle({ type: ToggleType.Switch, isOn: this.is_auto_hide_progress })
-          .selectedColor(this.themeColor)
-          .switchPointColor(Color.White)
-          .margin({ right: 18 })
-          .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.5})
-          .onChange((checked: boolean) => {
-            this.is_auto_hide_progress = checked;
-            PreferencesUtil.put(SettingPage.IS_AUTO_HIDE_PROGRESS, this.is_auto_hide_progress)
-            this.sendChangeEvent()
-          })
-          .width(50)
-          .height(30);
-      }
-      .height(55)
-      .clickEffect({ level: ClickEffectLevel.HEAVY })
-
-      Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
+      // // 自动隐藏进度条两侧的按钮
+      // Row() {
+      //   SymbolGlyph($r('sys.symbol.sun_max'))
+      //     .fontSize(20)
+      //     .fontColor([this.themeColor])
+      //     .alignSelf(ItemAlign.Center)
+      //     .margin({ left: 15 })
+      //   Text('自动隐藏进度条两侧的按钮')
+      //     .margin({ left: 8 })
+      //     .fontSize(15)
+      //     .fontColor(Color.Gray)
+      //     .fontWeight(480)
+      //     .layoutWeight(1)
+      //   Toggle({ type: ToggleType.Switch, isOn: this.is_auto_hide_progress })
+      //     .selectedColor(this.themeColor)
+      //     .switchPointColor(Color.White)
+      //     .margin({ right: 18 })
+      //     .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.5})
+      //     .onChange((checked: boolean) => {
+      //       this.is_auto_hide_progress = checked;
+      //       PreferencesUtil.put(SettingPage.IS_AUTO_HIDE_PROGRESS, this.is_auto_hide_progress)
+      //       this.sendChangeEvent()
+      //     })
+      //     .width(50)
+      //     .height(30);
+      // }
+      // .height(55)
+      // .clickEffect({ level: ClickEffectLevel.HEAVY })
+      //
+      // Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
       // 显示我的收藏
       Row() {
+        SymbolGlyph($r('sys.symbol.heart'))
+          .fontSize(20)
+          .fontColor([this.themeColor])
+          .alignSelf(ItemAlign.Center)
+          .margin({ left: 15 })
         Text('显示我的收藏')
-          .margin({ left: 18 })
+          .margin({ left: 8 })
           .fontSize(15)
           .fontColor(Color.Gray)
           .fontWeight(480)
@@ -1408,8 +1572,13 @@ export struct SettingPage {
       Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
       // 显示最近播放
       Row() {
+        SymbolGlyph($r('sys.symbol.clock'))
+          .fontSize(20)
+          .fontColor([this.themeColor])
+          .alignSelf(ItemAlign.Center)
+          .margin({ left: 15 })
         Text('显示最近播放')
-          .margin({ left: 18 })
+          .margin({ left: 8 })
           .fontSize(15)
           .fontColor(Color.Gray)
           .fontWeight(480)
@@ -1450,8 +1619,13 @@ export struct SettingPage {
     Button({ type: ButtonType.Capsule, stateEffect: true }) {
       Column() {
         Row() {
+          SymbolGlyph($r('sys.symbol.hand_draw'))
+            .fontSize(20)
+            .fontColor([this.themeColor])
+            .alignSelf(ItemAlign.Center)
+            .margin({ left: 15 })
           Text('设置教程:')
-            .margin({ left: 18 })
+            .margin({ left: 8 })
             .fontSize(15)
             .fontColor(Color.Gray)
             .fontWeight(480)
@@ -1503,8 +1677,13 @@ export struct SettingPage {
       // 歌词API
       Button({ type: ButtonType.Normal, stateEffect: true }) {
         Row() {
+          SymbolGlyph($r('sys.symbol.lightbulb'))
+            .fontSize(20)
+            .fontColor([this.themeColor])
+            .alignSelf(ItemAlign.Center)
+            .margin({ left: 15 })
           Text('歌词:')
-            .margin({ left: 18, right: 6 })
+            .margin({ left: 8, right: 6 })
             .fontSize(15)
             .fontColor(Color.Gray)
           Text(this.lyricApiUrl)
@@ -1532,8 +1711,13 @@ export struct SettingPage {
       // 封面API
       Button({ type: ButtonType.Normal, stateEffect: true }) {
         Row() {
+          SymbolGlyph($r('sys.symbol.picture'))
+            .fontSize(20)
+            .fontColor([this.themeColor])
+            .alignSelf(ItemAlign.Center)
+            .margin({ left: 15 })
           Text('封面:')
-            .margin({ left: 18, right: 6 })
+            .margin({ left: 8, right: 6 })
             .fontSize(15)
             .fontColor(Color.Gray)
           Text(this.coverApiUrl)

+ 2 - 3
entry/src/main/ets/pages/SplashIndex.ets

@@ -3,7 +3,7 @@ import { common } from '@kit.AbilityKit'
 import data_preferences from '@ohos.data.preferences'
 import Logger from '../common/util/Logger'
 import { router, window } from '@kit.ArkUI'
-import { CommonConstants } from '../common/constants/CommonConstants'
+import { CommonConstants, STR_LOCK_VIDEO, VIP_FILEPATH } from '../common/constants/CommonConstants'
 import { CSJUtil } from '../common/util/CSJUtil'
 import { ConfigManager } from '../common/util/ConfigManager'
 // import { AdSlotBuilder, CSJAdCreator, CSJAdSdk, CSJSplashAd,
@@ -17,7 +17,6 @@ import { DemoConstants } from '../entryability/DemoConstants'
 import { AppUtil, Base64Util, FileUtil, LogUtil, StrUtil, ToastUtil } from '@pura/harmony-utils'
 import { Utility } from '../common/util/Utility'
 import { VideoItem } from '../viewmodel/VideoItem'
-import { LocalMusic } from '../view/LocalMusic'
 import { fileIo, fileUri, picker, ReadTextOptions } from '@kit.CoreFileKit'
 import { VipPage } from './VipPage'
 import { VipData } from '../viewmodel/VipData'
@@ -142,7 +141,7 @@ struct  SplashIndex{
     let documentSaveResult = await documentViewPicker.save({ pickerMode: picker.DocumentPickerMode.DOWNLOAD })
     let download_path = new fileUri.FileUri(documentSaveResult[0]).path
     this.rootPath = download_path
-    let vPath = download_path + '/'+ LocalMusic.STR_LOCK_VIDEO+ '/' + VipPage.VIP_FILEPATH
+    let vPath = download_path + '/'+ STR_LOCK_VIDEO+ '/' + VIP_FILEPATH
     this.expireDate =  this.readDataFromFile(vPath)
     Utility.setNoble(this.expireDate)
     this.doMain()

+ 4 - 3
entry/src/main/ets/pages/UserCenter.ets

@@ -412,8 +412,8 @@ export struct UserCenter {
           // 左右按钮
           Row() {
             Image($r('app.media.menu'))
-              .width(32)
-              .height(32)
+              .width(26)
+              .height(26)
               .margin({ left: 12, right: 8 })
               .onClick(() => {
                 animateTo({ duration: 555 }, () => {
@@ -437,7 +437,7 @@ export struct UserCenter {
       Scroll() {
         Column() {
           this.buildUserInfoCard()
-          if(!Utility.isNoble()||!Utility.isForever()){
+          if(!Utility.isForever()){
             this.buildVipPlans()
           }
           this.buildVipFeatures()
@@ -560,6 +560,7 @@ export struct UserCenter {
                 PreferencesUtil.putSync('subscriptionEndDate', '');
                 PreferencesUtil.putSync('hasActiveSubscription', false);
                 PreferencesUtil.putSync('userToken', '');
+                PreferencesUtil.putSync('isForever', false);
                 emitter.emit({ eventId: 1001 }, {})
                 ToastUtil.showToast('已退出登录')
               })

+ 3 - 4
entry/src/main/ets/pages/VipPage.ets

@@ -1,7 +1,7 @@
 import { promptAction, router, window } from '@kit.ArkUI';
 import TitleBar from '../view/TitleBar';
 import { webview } from '@kit.ArkWeb';
-import { CommonConstants } from '../common/constants/CommonConstants';
+import { CommonConstants, STR_LOCK_VIDEO, VIP_FILEPATH } from '../common/constants/CommonConstants';
 import { AES,
   AppUtil,
   Base64Util,
@@ -19,7 +19,6 @@ import { Utility } from '../common/util/Utility';
 import fileIo, { ReadTextOptions } from '@ohos.file.fs';
 import { fileUri, picker } from '@kit.CoreFileKit';
 import { VipData } from '../viewmodel/VipData';
-import { LocalMusic } from '../view/LocalMusic';
 import { DialogHelper } from '@pura/harmony-dialog';
 import { common, ConfigurationConstant } from '@kit.AbilityKit';
 import * as wxOpenSdk from '@tencent/wechat_open_sdk';
@@ -67,7 +66,7 @@ export  struct  VipPage{
 
 
 
-  static readonly VIP_FILEPATH: string = '.vv'
+  // static readonly VIP_FILEPATH: string = '.vv'
 
   @State appName:string = ''
   @State expireDate:string = ''
@@ -104,7 +103,7 @@ export  struct  VipPage{
     const documentViewPicker = new picker.DocumentViewPicker()
     let documentSaveResult = await documentViewPicker.save({ pickerMode: picker.DocumentPickerMode.DOWNLOAD })
     let download_path = new fileUri.FileUri(documentSaveResult[0]).path + '/'
-    this.filePath = download_path + LocalMusic.STR_LOCK_VIDEO+ '/' + VipPage.VIP_FILEPATH
+    this.filePath = download_path + STR_LOCK_VIDEO+ '/' + VIP_FILEPATH
 
     this.expireDate =  this.readDataFromFile(this.filePath)
     this.bundleName = await  AppUtil.getBundleName()

File diff suppressed because it is too large
+ 378 - 235
entry/src/main/ets/view/LocalMusic.ets


+ 7 - 0
entry/src/main/ets/viewmodel/VideoItem.ets

@@ -57,6 +57,13 @@ export class VideoItem  {
   genre?:string//风格
   track?:string//音轨号
 
+  bits_per_raw_sample?:string//位深
+  channels?:string//声道数
+  channel_layout?:string//声道布局:stereo为标准立体声(左+右)
+  start_time?:string//起始时间:
+
+
+
   constructor(name: string, id: string, filePath: string, type:number,videoSize:number,cTime: string,pixelMap?: image.PixelMap,
     size?: string,pixelMapPath?: string,artist?: string,album?: string,fileName?: string, lastPlayed?:Date) {
     this.name = name;

+ 6 - 3
entry/src/main/module.json5

@@ -49,7 +49,7 @@
           {
             "actions": [
               "action.system.home",
-              "ohos.want.action.viewData",
+              "ohos.want.action.viewData",//碰一碰分享增加
               "ohos.want.action.sendData"
             ],
             "uris": [
@@ -76,10 +76,13 @@
                 "type": "video/*",
                 "linkFeature": "FileOpen",
                 "maxFileSupported": 1
-              }
+              },
+
             ],
+//            "domainVerify": true,//碰一碰分享增加
             "entities": [
-              "entity.system.home"
+              "entity.system.home",
+//              "entity.system.browsable"//碰一碰分享增加
             ],
 
           }

+ 5 - 1
entry/src/main/resources/base/element/string.json

@@ -446,7 +446,7 @@
     },
     {
       "name": "sync_tips",
-      "value": "如果你在系统的文件管理删除了音乐媒体文件,可以使用校正数据来删除校正对于的数据库。"
+      "value": "如果你在系统的文件管理删除了音乐媒体文件,可以使用校正数据来删除校正对应的数据。"
     },
     {
       "name": "sync_dataing",
@@ -459,6 +459,10 @@
     {
       "name": "lossless",
       "value": "Lossless"
+    },
+    {
+      "name": "select_all",
+      "value": "多选"
     }
   ]
 }

+ 5 - 23
oh-package-lock.json5

@@ -12,21 +12,19 @@
     "@chinalike/popup@^0.0.7": "@chinalike/popup@0.0.7",
     "@keke/color-picker@^1.0.4": "@keke/color-picker@1.0.4",
     "@ohos/juniversalchardet@^2.0.2": "@ohos/juniversalchardet@2.0.2",
-    "@ohos/lottie@^2.0.19": "@ohos/lottie@2.0.19",
+    "@ohos/lottie@^2.0.23": "@ohos/lottie@2.0.23",
     "@ohos/pinyin4js@^2.0.2": "@ohos/pinyin4js@2.0.2",
     "@ohos/pulltorefresh@^2.1.1": "@ohos/pulltorefresh@2.1.1",
     "@pura/harmony-dialog@^1.0.6": "@pura/harmony-dialog@1.0.6",
     "@pura/harmony-utils@^1.2.4": "@pura/harmony-utils@1.2.4",
     "@pura/spinkit@^1.0.4": "@pura/spinkit@1.0.4",
     "@seagazer/cclyric@lib": "@seagazer/cclyric@lib",
-    "@sgaolei/lrc_parser@^1.0.0": "@sgaolei/lrc_parser@1.0.0",
     "@simplepeng/spider-man@^1.0.1": "@simplepeng/spider-man@1.0.1",
     "@sj/ffmpeg@^1.2.5": "@sj/ffmpeg@1.2.5",
     "@taobao-ohos/utdid_sdk@oh_modules/.ohpm/@cashier_alipay+cashiersdk@15.8.32/oh_modules/@cashier_alipay/cashiersdk/lib/utdid_sdk-1.0.9.har": "@taobao-ohos/utdid_sdk@oh_modules/.ohpm/@cashier_alipay+cashiersdk@15.8.32/oh_modules/@cashier_alipay/cashiersdk/lib/utdid_sdk-1.0.9.har",
     "class-transformer@^0.5.1": "class-transformer@0.5.1",
     "libblueshield.so@oh_modules/.ohpm/@alipay+blueshieldsdk@cow+0gass5tzqhymzjby2f6sd+g2xtoatqsiyvi9qsy=/oh_modules/@alipay/blueshieldsdk/src/main/cpp/types/libblueshield": "libblueshield.so@oh_modules/.ohpm/@alipay+blueshieldsdk@cow+0gass5tzqhymzjby2f6sd+g2xtoatqsiyvi9qsy=/oh_modules/@alipay/blueshieldsdk/src/main/cpp/types/libblueshield",
     "libffmpeg.so@oh_modules/.ohpm/@sj+ffmpeg@1.2.5/oh_modules/@sj/ffmpeg/src/main/cpp/types/libffmpeg": "libffmpeg.so@oh_modules/.ohpm/@sj+ffmpeg@1.2.5/oh_modules/@sj/ffmpeg/src/main/cpp/types/libffmpeg",
-    "liblrcparser.so@oh_modules/.ohpm/@sgaolei+lrc_parser@1.0.0/oh_modules/@sgaolei/lrc_parser/src/main/cpp/types/liblrcparser": "liblrcparser.so@oh_modules/.ohpm/@sgaolei+lrc_parser@1.0.0/oh_modules/@sgaolei/lrc_parser/src/main/cpp/types/liblrcparser",
     "pako@^2.1.0": "pako@2.1.0"
   },
   "packages": {
@@ -79,11 +77,11 @@
       "resolved": "https://repo.harmonyos.com/ohpm/@ohos/juniversalchardet/-/juniversalchardet-2.0.2.har",
       "registryType": "ohpm"
     },
-    "@ohos/lottie@2.0.19": {
+    "@ohos/lottie@2.0.23": {
       "name": "@ohos/lottie",
-      "version": "2.0.19",
-      "integrity": "sha512-6YGMeuHCdJ4PrJGPj3ycJob61TYbEcgk4GugbcuTGS6eJHJpDUuTja9lPhDmD6RL/etm3i2j4IVd+QCpfI6TWA==",
-      "resolved": "https://repo.harmonyos.com/ohpm/@ohos/lottie/-/lottie-2.0.19.har",
+      "version": "2.0.23",
+      "integrity": "sha512-SiVmsyllXLcvSrh98qsXtjSoVaxy1bm8sGZzmz94DZOjdQ2zSCnTzY627EevkCCFxAA5HIbqFPUWokhc8bp/3Q==",
+      "resolved": "https://repo.harmonyos.com/ohpm/@ohos/lottie/-/lottie-2.0.23.har",
       "registryType": "ohpm"
     },
     "@ohos/pinyin4js@2.0.2": {
@@ -133,16 +131,6 @@
       "resolved": "lib",
       "registryType": "local"
     },
-    "@sgaolei/lrc_parser@1.0.0": {
-      "name": "@sgaolei/lrc_parser",
-      "version": "1.0.0",
-      "integrity": "sha512-JnkArqOidM0qN+Daoxka+PvMq4Eqyv39/oZ/4vHTYlU5ssCTUqJ0GWF7ti9ZQTrDbg89Shx6hjODVXhs3IjgAg==",
-      "resolved": "https://repo.harmonyos.com/ohpm/@sgaolei/lrc_parser/-/lrc_parser-1.0.0.har",
-      "registryType": "ohpm",
-      "dependencies": {
-        "liblrcparser.so": "file:./src/main/cpp/types/liblrcparser"
-      }
-    },
     "@simplepeng/spider-man@1.0.1": {
       "name": "@simplepeng/spider-man",
       "version": "1.0.1",
@@ -186,12 +174,6 @@
       "resolved": "oh_modules/.ohpm/@sj+ffmpeg@1.2.5/oh_modules/@sj/ffmpeg/src/main/cpp/types/libffmpeg",
       "registryType": "local"
     },
-    "liblrcparser.so@oh_modules/.ohpm/@sgaolei+lrc_parser@1.0.0/oh_modules/@sgaolei/lrc_parser/src/main/cpp/types/liblrcparser": {
-      "name": "liblrcparser.so",
-      "version": "1.0.0",
-      "resolved": "oh_modules/.ohpm/@sgaolei+lrc_parser@1.0.0/oh_modules/@sgaolei/lrc_parser/src/main/cpp/types/liblrcparser",
-      "registryType": "local"
-    },
     "pako@2.1.0": {
       "name": "pako",
       "version": "2.1.0",

+ 2 - 3
oh-package.json5

@@ -14,18 +14,17 @@
   "dependencies": {
     "@pura/harmony-utils": "^1.2.4",
     "@pura/harmony-dialog": "^1.0.6",
-    "@ohos/lottie": "^2.0.19",
     "@ohos/pulltorefresh": "^2.1.1",
     "@chinalike/popup": "^0.0.7",
     "@seagazer/cclyric": "file:./lib",
     "@changwei/chardet": "^1.0.0",
     "@cashier_alipay/cashiersdk": "^15.8.32",
     "@keke/color-picker": "^1.0.4",
-    "@sgaolei/lrc_parser": "^1.0.0",
     "@ohos/pinyin4js": "^2.0.2",
     "@simplepeng/spider-man": "^1.0.1",
     "@ohos/juniversalchardet": "^2.0.2",
-    "@sj/ffmpeg": "^1.2.5"
+    "@sj/ffmpeg": "^1.2.5",
+    "@ohos/lottie": "^2.0.23"
   },
   "dynamicDependencies": {}
 }

Some files were not shown because too many files changed in this diff