ChartsCount.ets 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. import { common, ConfigurationConstant } from '@kit.AbilityKit';
  2. import { CommonConstants } from '../common/constants/CommonConstants';
  3. import { VideoItem } from '../viewmodel/VideoItem';
  4. import { LazyDataSource } from '../common/util/LazyDataSource';
  5. import { LogUtil, PreferencesUtil, StrUtil, ToastUtil } from '@pura/harmony-utils';
  6. import fs from '@ohos.file.fs';
  7. import { changeMusicCover, findLocalCoverImage, getApiLyric, repairAudioMetadata,
  8. searchCover,
  9. syncLyricToDB} from '../common/util/MusicTagUtils';
  10. import { util } from '@kit.ArkTS';
  11. import { FFMpegTags } from '../common/util/Utility';
  12. import MediaTable from '../common/util/MediaTable';
  13. // 批量编辑标签
  14. @Component
  15. export struct ChartsCount {
  16. private listScroller: ListScroller = new ListScroller()
  17. @State isLyric:boolean = true
  18. @State isCover:boolean = true
  19. @Link isShowDrawer: boolean;
  20. @Link offsetX: number;
  21. @State dataSource: LazyDataSource<VideoItem> = new LazyDataSource([])
  22. @State selectedFiles: Array<VideoItem> = []
  23. @StorageProp('topRectHeight') topRectHeight: number = 0;
  24. @State isDarkMode: boolean = false
  25. @StorageProp('currentColorMode') @Watch('onColorModeChange') currentMode: number =
  26. ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT;
  27. @StorageProp('themeColor') themeColor: string = CommonConstants.DEFAULT_THEME_COLOR;
  28. context = this.getUIContext().getHostContext() as common.UIAbilityContext
  29. private table: MediaTable = new MediaTable(this.context)
  30. onColorModeChange() {
  31. this.isDarkMode = this.currentMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK
  32. }
  33. async aboutToAppear() {
  34. await new Promise<void>((resolve, reject) => {
  35. this.table.getRdbStore(this.context, (err:Error) => {
  36. err ? reject(err) : resolve();
  37. });
  38. });
  39. this.table.queryByPlayCountDesc(0, async (result: VideoItem[]) => {
  40. this.selectedFiles = result
  41. // 确保 selectedFiles 有默认值后再初始化 dataSource
  42. if (this.selectedFiles && this.selectedFiles.length > 0) {
  43. // this.dataSource = new LazyDataSource(this.selectedFiles)
  44. this.dataSource.pushArrayData(this.selectedFiles)
  45. } else {
  46. this.dataSource = new LazyDataSource([])
  47. }
  48. })
  49. }
  50. build() {
  51. Column(){
  52. this.topTitleBar()
  53. this.listView()
  54. }
  55. .height('100%')
  56. .width('100%')
  57. .backgroundColor($r('app.color.index_background'))
  58. }
  59. @Builder
  60. listView() {
  61. Column(){
  62. List({ scroller: this.listScroller }) {
  63. // ListItemGroup({ header: this.listHeader() }) {
  64. LazyForEach(this.dataSource, (item: VideoItem, index: number) => {
  65. ListItem() {
  66. Column() {
  67. this.MusicItem(item, index)
  68. }
  69. }
  70. .borderRadius(14)
  71. .backgroundColor($r('app.color.start_window_background'))
  72. .margin({top:7,bottom:7})
  73. .transition(TransitionEffect.asymmetric(
  74. TransitionEffect.scale({ x: 1.2, y: 1.2 }).animation({ duration: 500 }),
  75. TransitionEffect.scale({ x: 0, y: 0 })
  76. ))
  77. .clickEffect({ level: ClickEffectLevel.LIGHT })
  78. }, (item: VideoItem) => item.filePath)
  79. // }
  80. }
  81. .cachedCount(2)
  82. // .layoutWeight(1)
  83. // .height('100%')
  84. .transition(TransitionEffect.asymmetric(
  85. TransitionEffect.scale({ x: 1.2, y: 1.2 }).animation({ duration: 500 }),
  86. TransitionEffect.scale({ x: 0, y: 0 })
  87. ))
  88. }
  89. .borderRadius(20)
  90. .padding({top:10,bottom:6})
  91. .height('auto')
  92. .margin({top:20,right:20,left:20})
  93. .layoutWeight(1)
  94. .height('100%')
  95. }
  96. @Builder
  97. listHeader() {
  98. Stack({alignContent:Alignment.Start}){
  99. Text(`共${this.selectedFiles.length}首歌`)
  100. .fontSize(14)
  101. .maxLines(1)
  102. .textAlign(TextAlign.Start)
  103. .padding({ left: 25 })
  104. .fontColor($r('app.color.text_color'))
  105. .margin({bottom:6,top:4,left: 6 })
  106. }
  107. .height('auto').width('100%')
  108. }
  109. @Builder
  110. topTitleBar() {
  111. // 顶部安全区和自定义标题栏
  112. Column() {
  113. // 顶部安全区
  114. Blank()
  115. .height(this.topRectHeight)
  116. .backgroundColor(this.isDarkMode ? $r('app.color.title_bar_bg') : this.themeColor)
  117. .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])
  118. // 自定义标题栏(Stack实现绝对居中)
  119. Stack() {
  120. // 居中标题
  121. Text('歌曲统计')
  122. .fontSize(18)
  123. .fontColor(Color.White)
  124. .align(Alignment.Center)
  125. // 左右按钮
  126. Row() {
  127. Image($r('app.media.menu'))
  128. .width(26)
  129. .height(26)
  130. .margin({ left: 12, right: 8 })
  131. .onClick(() => {
  132. this.getUIContext().animateTo({ duration: 666 }, () => {
  133. // 动画闭包内控制Image组件的出现和消失
  134. this.isShowDrawer = !this.isShowDrawer
  135. this.offsetX = 0
  136. })
  137. })
  138. Blank().flexGrow(1)
  139. Blank().width(32)
  140. }
  141. .height(48)
  142. .width('100%')
  143. .alignItems(VerticalAlign.Center)
  144. }
  145. .height(48)
  146. .width('100%')
  147. .backgroundColor(this.isDarkMode ? $r('app.color.title_bar_bg') : this.themeColor)
  148. }
  149. }
  150. @Builder
  151. private MusicItem(item: VideoItem, index?: number) {
  152. Button({ type: ButtonType.Normal, stateEffect: true }) {
  153. Column() {
  154. Row() {
  155. Image(item.pixelMapPath)
  156. .width(80)
  157. .height(80)
  158. .borderRadius(8)
  159. .alt($r('app.media.music_red'))
  160. .alignSelf(ItemAlign.Center)
  161. .interpolation(ImageInterpolation.Medium)// 用于重采样后的抗锯齿
  162. .autoResize(true) // 重采样,可减少内存占用
  163. .padding({ left: 10,top:3,bottom:3 })
  164. Column(){
  165. Text(item.name)
  166. .fontSize(16)
  167. .maxLines(1)
  168. .textOverflow({ overflow: TextOverflow.MARQUEE })//超长滚动
  169. .fontColor($r('app.color.text_color'))
  170. .padding({ left: 10 })
  171. .textAlign(TextAlign.Start)
  172. .margin({ left: 5 })
  173. Text(StrUtil.isEmpty(item.artist) ? item.cTime : item.artist )
  174. .fontSize(14)
  175. .fontColor(Color.Gray)
  176. .textOverflow({ overflow: TextOverflow.MARQUEE })//超长滚动
  177. .textAlign(TextAlign.Start)
  178. .padding({ top: 5,left: 10 })
  179. .margin({ left: 5 })
  180. }
  181. .alignItems(HorizontalAlign.Start)
  182. Blank()
  183. // 根据嵌入状态显示勾选图标
  184. Text(item.playCount+'')
  185. .fontSize(15)
  186. .maxLines(1)
  187. .padding({ right: 5 })
  188. .textOverflow({ overflow: TextOverflow.MARQUEE })
  189. .animation({
  190. duration: 555,
  191. curve: 'Linear',
  192. })
  193. .fontColor($r('app.color.text_color'))
  194. .margin({ right: 18 })
  195. }
  196. .layoutWeight(1)
  197. .height('100%')
  198. .width('100%')
  199. }
  200. }
  201. .backgroundColor(Color.Transparent)
  202. .width('100%')
  203. .height(99)
  204. }
  205. }