Quellcode durchsuchen

继续美化音乐卡片UI2

onecold vor 4 Monaten
Ursprung
Commit
89e2402cda

+ 10 - 2
entry/src/main/ets/common/player/MusicCardManager.ets

@@ -104,10 +104,12 @@ export class MusicCardManager {
 
     const lyricLines = resolveMusicCardLyricLines(snapshot.lyricText, snapshot.currentPositionMs)
     if (lyricLines.hasLyric) {
+      snapshot.lyricLine0 = lyricLines.line0
       snapshot.lyricLine1 = lyricLines.line1
       snapshot.lyricLine2 = lyricLines.line2
       snapshot.hasLyric = true
     } else {
+      snapshot.lyricLine0 = ''
       snapshot.lyricLine1 = snapshot.title
       snapshot.lyricLine2 = snapshot.artist
       snapshot.hasLyric = false
@@ -155,10 +157,12 @@ export class MusicCardManager {
 
     const lyricLines = resolveMusicCardLyricLines(snapshot.lyricText, snapshot.currentPositionMs)
     if (lyricLines.hasLyric) {
+      snapshot.lyricLine0 = lyricLines.line0
       snapshot.lyricLine1 = lyricLines.line1
       snapshot.lyricLine2 = lyricLines.line2
       snapshot.hasLyric = true
     } else {
+      snapshot.lyricLine0 = ''
       snapshot.lyricLine1 = snapshot.title
       snapshot.lyricLine2 = snapshot.artist
       snapshot.hasLyric = false
@@ -178,7 +182,7 @@ export class MusicCardManager {
       `musicCard notifyPlaybackStateChanged title=${snapshot.title}, artist=${snapshot.artist}, ` +
       `coverImageName=${snapshot.coverImageName}, coverPath=${snapshot.coverPath}, hasCoverImage=${snapshot.hasCoverImage}, ` +
       `hasSong=${snapshot.hasSong}, isPlaying=${snapshot.isPlaying}, positionMs=${snapshot.currentPositionMs}, ` +
-      `durationMs=${snapshot.durationMs}, lyricLine1=${snapshot.lyricLine1}, lyricLine2=${snapshot.lyricLine2}`)
+      `durationMs=${snapshot.durationMs}, lyricLine0=${snapshot.lyricLine0}, lyricLine1=${snapshot.lyricLine1}, lyricLine2=${snapshot.lyricLine2}`)
     snapshot.updatedAtMs = Date.now()
     const saved = MusicCardSnapshotStore.writeSnapshot(snapshot, context)
     if (!saved) {
@@ -252,7 +256,7 @@ export class MusicCardManager {
       `musicCard updateAllForms payload title=${payload.title}, artist=${payload.artist}, ` +
       `coverImageName=${payload.coverImageName}, coverPath=${payload.coverPath}, hasCoverImage=${payload.hasCoverImage}, ` +
       `hasSong=${payload.hasSong}, isPlaying=${payload.isPlaying}, currentPositionMs=${payload.currentPositionMs}, ` +
-      `durationMs=${payload.durationMs}, lyricLine1=${payload.lyricLine1}, lyricLine2=${payload.lyricLine2}`)
+      `durationMs=${payload.durationMs}, lyricLine0=${payload.lyricLine0}, lyricLine1=${payload.lyricLine1}, lyricLine2=${payload.lyricLine2}`)
     for (let i = 0; i < formIds.length; i++) {
       const formId = formIds[i]
       if (!formId) {
@@ -274,6 +278,7 @@ export class MusicCardManager {
       bindingPayload.durationMs = payload.durationMs
       bindingPayload.currentTimeText = payload.currentTimeText
       bindingPayload.durationTimeText = payload.durationTimeText
+      bindingPayload.lyricLine0 = payload.lyricLine0
       bindingPayload.lyricLine1 = payload.lyricLine1
       bindingPayload.lyricLine2 = payload.lyricLine2
       bindingPayload.hasLyric = payload.hasLyric
@@ -388,6 +393,9 @@ export class MusicCardManager {
     if (previousSnapshot.durationTimeText !== nextSnapshot.durationTimeText) {
       return true
     }
+    if (previousSnapshot.lyricLine0 !== nextSnapshot.lyricLine0) {
+      return true
+    }
     if (previousSnapshot.lyricLine1 !== nextSnapshot.lyricLine1) {
       return true
     }

+ 17 - 2
entry/src/main/ets/common/player/MusicCardSnapshot.ets

@@ -20,6 +20,7 @@ export interface MusicCardSnapshot {
   durationMs: number
   currentTimeText: string
   durationTimeText: string
+  lyricLine0: string
   lyricLine1: string
   lyricLine2: string
   hasLyric: boolean
@@ -29,6 +30,7 @@ export interface MusicCardSnapshot {
 }
 
 export interface MusicCardLyricLines {
+  line0: string
   line1: string
   line2: string
   hasLyric: boolean
@@ -55,6 +57,7 @@ export class MusicCardBindingData {
   durationMs: number = 0
   currentTimeText: string = DEFAULT_TIME_TEXT
   durationTimeText: string = DEFAULT_TIME_TEXT
+  lyricLine0: string = ''
   lyricLine1: string = MUSIC_CARD_EMPTY_TITLE
   lyricLine2: string = MUSIC_CARD_EMPTY_ARTIST
   hasLyric: boolean = false
@@ -80,6 +83,7 @@ export function createEmptyMusicCardSnapshot(): MusicCardSnapshot {
     durationMs: 0,
     currentTimeText: DEFAULT_TIME_TEXT,
     durationTimeText: DEFAULT_TIME_TEXT,
+    lyricLine0: '',
     lyricLine1: MUSIC_CARD_EMPTY_TITLE,
     lyricLine2: MUSIC_CARD_EMPTY_ARTIST,
     hasLyric: false,
@@ -96,8 +100,11 @@ export function resolveMusicCardLyricMetaText(
 ): string {
   const safeArtist = artist?.trim() ?? ''
   const safeCurrentLyric = currentLyric?.trim() ?? ''
-  if ( hasLyric && safeCurrentLyric !== '') {
-    return `${safeCurrentLyric}`
+  if (hasLyric && safeArtist !== '' && safeCurrentLyric !== '') {
+    return `${safeArtist} - ${safeCurrentLyric}`
+  }
+  if (hasLyric && safeCurrentLyric !== '') {
+    return safeCurrentLyric
   }
   if (safeArtist !== '') {
     return safeArtist
@@ -113,6 +120,7 @@ export function resolveMusicCardLyricLines(
   const trimmedText = normalizedLyricText ? normalizedLyricText.trim() : ''
   if (trimmedText === '') {
     return {
+      line0: '',
       line1: '',
       line2: '',
       hasLyric: false
@@ -168,6 +176,7 @@ export function resolveMusicCardLyricLines(
 
   if (entries.length === 0) {
     return {
+      line0: '',
       line1: '',
       line2: '',
       hasLyric: false
@@ -190,9 +199,11 @@ export function resolveMusicCardLyricLines(
   }
 
   const currentLine = entries[currentIndex]
+  const previousLine = currentIndex > 0 ? entries[currentIndex - 1] : undefined
   const nextLine = entries[currentIndex + 1]
 
   return {
+    line0: previousLine ? previousLine.text : '',
     line1: currentLine.text,
     line2: nextLine ? nextLine.text : '',
     hasLyric: true
@@ -233,12 +244,14 @@ export function buildMusicCardBindingData(snapshot: MusicCardSnapshot): MusicCar
     data.currentTimeText = DEFAULT_TIME_TEXT
     data.durationTimeText = DEFAULT_TIME_TEXT
     data.filePath = ''
+    data.lyricLine0 = ''
     data.lyricLine1 = data.title
     data.lyricLine2 = data.artist
     data.hasLyric = false
     return data
   }
 
+  let lyricLine0 = ''
   let lyricLine1 = data.title
   let lyricLine2 = data.artist
   let hasLyric = false
@@ -246,11 +259,13 @@ export function buildMusicCardBindingData(snapshot: MusicCardSnapshot): MusicCar
   const lyricLines = resolveMusicCardLyricLines(source.lyricText, source.currentPositionMs)
 
   if (lyricLines.hasLyric) {
+    lyricLine0 = lyricLines.line0
     lyricLine1 = lyricLines.line1
     lyricLine2 = lyricLines.line2
     hasLyric = true
   }
 
+  data.lyricLine0 = lyricLine0
   data.lyricLine1 = lyricLine1
   data.lyricLine2 = lyricLine2
   data.hasLyric = hasLyric

+ 1 - 0
entry/src/main/ets/common/player/MusicCardSnapshotStore.ets

@@ -51,6 +51,7 @@ const mergeSnapshot = (parsed: MusicCardSnapshot): MusicCardSnapshot => {
   snapshot.durationMs = parsed.durationMs
   snapshot.currentTimeText = parsed.currentTimeText
   snapshot.durationTimeText = parsed.durationTimeText
+  snapshot.lyricLine0 = parsed.lyricLine0 ?? ''
   snapshot.lyricLine1 = parsed.lyricLine1
   snapshot.lyricLine2 = parsed.lyricLine2
   snapshot.hasLyric = parsed.hasLyric

+ 1 - 1
entry/src/main/ets/widget/pages/MusicPlayerWidgetCard.ets

@@ -14,7 +14,7 @@ const TAG = 'MusicPlayerWidgetCard'
 struct MusicPlayerWidgetCard {
   @LocalStorageProp('formId') formId: string = ''
   @LocalStorageProp('title') title: string = '未在播放'
-  @LocalStorageProp('artist') artist: string = '点击打开播放器'
+  @LocalStorageProp('artist') artist: string = ''
   @LocalStorageProp('coverPath') coverPath: string = ''
   @LocalStorageProp('coverImageName') coverImageName: string = ''
   @LocalStorageProp('hasCoverImage') hasCoverImage: boolean = false

+ 8 - 11
entry/src/main/ets/widget/pages/MusicPlayerWidgetLyricCard.ets

@@ -152,9 +152,9 @@ struct MusicPlayerWidgetLyricCard {
 
   private hasCoverBackground(): boolean {
     if (this.hasCoverImage && this.coverImageName.length > 0) {
-      return true;
+      return true
     }
-    return this.coverPath.length > 0;
+    return this.coverPath.length > 0
   }
 
   private resolveTitleArtistText(): string {
@@ -174,8 +174,7 @@ struct MusicPlayerWidgetLyricCard {
 
   build() {
     Stack({ alignContent: Alignment.Center }) {
-
-      if (this.hasCoverBackground()&&this.isChangeBg) {
+      if (this.hasCoverBackground() && this.isChangeBg) {
         Column()
           .width('100%')
           .height('100%')
@@ -186,19 +185,17 @@ struct MusicPlayerWidgetLyricCard {
         Column()
           .width('100%')
           .height('100%')
-          .linearGradient( { direction: GradientDirection.Right, colors:[
-            ['#00BC70',0.0],['#D81B60',1.0]]})
+          .linearGradient({ direction: GradientDirection.Right, colors: [
+            ['#00BC70', 0.0], ['#D81B60', 1.0]] })
       }
 
-
-
       Row({ space: 16 }) {
         Image(this.resolveCoverSource())
           .width(120)
           .height(120)
           .borderRadius(10)
           .objectFit(ImageFit.Cover)
-          .onClick(()=>{
+          .onClick(() => {
             this.isChangeBg = !this.isChangeBg
           })
 
@@ -268,7 +265,7 @@ struct MusicPlayerWidgetLyricCard {
 
             Button({ type: ButtonType.Circle, stateEffect: true }) {
               SymbolGlyph(this.isPlaying ? $r('sys.symbol.pause_fill') : $r('sys.symbol.play_fill'))
-                .fontSize(33)
+                .fontSize(30)
                 .fontColor([Color.White])
                 .effectStrategy(SymbolEffectStrategy.HIERARCHICAL)
             }
@@ -283,7 +280,7 @@ struct MusicPlayerWidgetLyricCard {
           .width('100%')
           .justifyContent(FlexAlign.SpaceBetween)
           .alignItems(VerticalAlign.Top)
-          .margin({bottom:10})
+          .margin({ bottom: 10 })
         }
         .width('100%')
         .justifyContent(FlexAlign.Center)

+ 282 - 0
entry/src/main/ets/widget/pages/MusicPlayerWidgetMiniCard.ets

@@ -0,0 +1,282 @@
+import { MusicCardActionConstants } from '../../common/player/MusicCardActionConstants'
+import Logger from '../../common/util/Logger'
+import {
+  clampMusicCardWidgetProgress,
+  resolveMusicCardWidgetCoverSource
+} from '../common/MusicPlayerWidgetHelper'
+
+const cardStorage: LocalStorage = new LocalStorage()
+const ENTRY_ABILITY_NAME = 'EntryAbility'
+const TAG = 'MusicPlayerWidgetMiniCard'
+
+@Entry(cardStorage)
+@Component
+struct u {
+  @LocalStorageProp('formId') formId: string = ''
+  @LocalStorageProp('title') title: string = '未在播放'
+  @LocalStorageProp('artist') artist: string = ''
+  @LocalStorageProp('coverPath') coverPath: string = ''
+  @LocalStorageProp('coverImageName') coverImageName: string = ''
+  @LocalStorageProp('hasCoverImage') hasCoverImage: boolean = false
+  @LocalStorageProp('hasSong') hasSong: boolean = false
+  @LocalStorageProp('isPlaying') isPlaying: boolean = false
+  @LocalStorageProp('currentPositionMs') @Watch('syncSliderFromPlayback') currentPositionMs: number = 0
+  @LocalStorageProp('durationMs') @Watch('syncSliderFromPlayback') durationMs: number = 0
+  @LocalStorageProp('updatedAtMs') @Watch('syncLyricDisplayFromSnapshot') updatedAtMs: number = 0
+  @LocalStorageProp('currentTimeText') currentTimeText: string = '00:00'
+  @LocalStorageProp('durationTimeText') durationTimeText: string = '00:00'
+  @LocalStorageProp('lyricLine1') lyricLine1: string = ''
+  @LocalStorageProp('lyricLine2') lyricLine2: string = ''
+  @LocalStorageProp('hasLyric') hasLyric: boolean = false
+  @State isChangeBg: boolean = true
+  @State sliderProgressMs: number = 0
+  @State displayLyricLine1: string = ''
+  @State displayLyricLine2: string = ''
+  @State lyricTranslateY: number = 0
+  @State lyricOpacity: number = 1
+
+  aboutToAppear(): void {
+    Logger.info(TAG,
+      `musicCard small aboutToAppear formId=${this.formId}, title=${this.title}, artist=${this.artist}, ` +
+      `coverImageName=${this.coverImageName}, coverPath=${this.coverPath}, hasCoverImage=${this.hasCoverImage}, ` +
+      `hasSong=${this.hasSong}, isPlaying=${this.isPlaying}, currentPositionMs=${this.currentPositionMs}, ` +
+      `durationMs=${this.durationMs}, lyricLine1=${this.lyricLine1}, lyricLine2=${this.lyricLine2}, hasLyric=${this.hasLyric}`)
+    this.syncSliderFromPlayback()
+    this.syncLyricDisplay(false)
+  }
+
+  private syncSliderFromPlayback(): void {
+    this.sliderProgressMs = clampMusicCardWidgetProgress(this.currentPositionMs, this.durationMs)
+  }
+
+  private postControlAction(action: string): void {
+    Logger.info(TAG, `musicCard small postControlAction formId=${this.formId}, action=${action}`)
+    postCardAction(this, {
+      action: 'call',
+      abilityName: ENTRY_ABILITY_NAME,
+      params: {
+        method: MusicCardActionConstants.CALL_METHOD_HANDLE_ACTION,
+        ttmusic_music_card_form_id: this.formId,
+        ttmusic_music_card_action: action,
+        ttmusic_music_card_source: MusicCardActionConstants.ACTION_SOURCE_WIDGET
+      }
+    })
+  }
+
+  private postRouterAction(action: string): void {
+    Logger.info(TAG, `musicCard small postRouterAction formId=${this.formId}, action=${action}`)
+    postCardAction(this, {
+      action: 'router',
+      abilityName: ENTRY_ABILITY_NAME,
+      params: {
+        ttmusic_music_card_form_id: this.formId,
+        ttmusic_music_card_action: action,
+        ttmusic_music_card_source: MusicCardActionConstants.ACTION_SOURCE_WIDGET
+      }
+    })
+  }
+
+  private resolveCoverSource(): string | Resource {
+    return resolveMusicCardWidgetCoverSource(this.coverImageName, this.coverPath, this.hasCoverImage)
+  }
+
+  private resolveProgressValue(): number {
+    if (this.durationMs <= 0) {
+      return 0
+    }
+    return Math.min(100, Math.max(0, Math.floor(this.sliderProgressMs * 100 / this.durationMs)))
+  }
+
+  private resolveTitleArtistText(): string {
+    const safeTitle = this.title?.trim() ?? ''
+    const safeArtist = this.artist?.trim() ?? ''
+    if (safeTitle !== '' && safeArtist !== '') {
+      return `${safeTitle} - ${safeArtist}`
+    }
+    if (safeTitle !== '') {
+      return safeTitle
+    }
+    if (safeArtist !== '') {
+      return safeArtist
+    }
+    return '未在播放'
+  }
+
+  private resolvePlayPauseIcon(): Resource {
+    return this.isPlaying ? $r('sys.symbol.pause_fill') : $r('sys.symbol.play_fill')
+  }
+
+  private resolveDisplayLyricLine1(): string {
+    if (!this.hasLyric) {
+      return ''
+    }
+    return this.lyricLine1?.trim() ?? ''
+  }
+
+  private resolveDisplayLyricLine2(): string {
+    if (!this.hasLyric) {
+      return ''
+    }
+    return this.lyricLine2?.trim() ?? ''
+  }
+
+  private syncLyricDisplay(shouldAnimate: boolean): void {
+    const nextLine1 = this.resolveDisplayLyricLine1()
+    const nextLine2 = this.resolveDisplayLyricLine2()
+    const changed = this.displayLyricLine1 !== nextLine1 || this.displayLyricLine2 !== nextLine2
+    if (!changed) {
+      return
+    }
+
+    this.displayLyricLine1 = nextLine1
+    this.displayLyricLine2 = nextLine2
+
+    if (!shouldAnimate) {
+      this.lyricTranslateY = 0
+      this.lyricOpacity = 1
+      return
+    }
+
+    this.lyricTranslateY = 10
+    this.lyricOpacity = 0.35
+    animateTo({ duration: 220, curve: Curve.EaseOut }, () => {
+      this.lyricTranslateY = 0
+      this.lyricOpacity = 1
+    })
+  }
+
+  private syncLyricDisplayFromSnapshot(): void {
+    this.syncLyricDisplay(true)
+  }
+
+  @Builder
+  private ControlButton(imageResource: Resource, action: string, buttonSize: number, symbolSize: number) {
+    Button() {
+      SymbolGlyph(imageResource)
+        .fontSize(symbolSize)
+        .fontColor([Color.Black])
+        .effectStrategy(SymbolEffectStrategy.HIERARCHICAL)
+    }
+    .width(buttonSize * 1.35)
+    .height(buttonSize * 1.35)
+    .backgroundColor(Color.Transparent)
+    .type(ButtonType.Circle)
+    .stateEffect(true)
+    .onClick(() => this.postControlAction(action))
+  }
+
+  @Builder
+  private PlayProgressButton() {
+    Stack({ alignContent: Alignment.Center }) {
+      Progress({ value: this.resolveProgressValue(), total: 100, type: ProgressType.Ring })
+        .width(34)
+        .height(34)
+        .color(Color.Black)
+        .style({ strokeWidth: 2 })
+
+      Button() {
+        SymbolGlyph(this.resolvePlayPauseIcon())
+          .fontSize(19)
+          .fontColor([Color.Black])
+          .effectStrategy(SymbolEffectStrategy.HIERARCHICAL)
+      }
+      .width(34)
+      .height(34)
+      .type(ButtonType.Circle)
+      .backgroundColor('#4DFFFFFF')
+      .stateEffect(false)
+      .onClick(() => this.postControlAction(MusicCardActionConstants.ACTION_PLAY_PAUSE))
+    }
+    .width(34)
+    .height(34)
+  }
+
+  private hasCoverBackground(): boolean {
+    if (this.hasCoverImage && this.coverImageName.length > 0) {
+      return true;
+    }
+    return this.coverPath.length > 0;
+  }
+
+  build() {
+    Stack() {
+
+      if (this.hasCoverBackground()&&this.isChangeBg) {
+        Column()
+          .width('100%')
+          .height('100%')
+          .backgroundImage(this.resolveCoverSource())
+          .backgroundImageSize({ width: '100%' })
+          .opacity(0.66)
+      } else {
+        Column()
+          .width('100%')
+          .height('100%')
+          .linearGradient( { direction: GradientDirection.Right, colors:[
+            ['#90EE90 ',0.0],['#F4D7C8',1.0]]})
+      }
+
+      Column({ space: 5 }) {
+        Text(this.title)
+          .fontSize(15)
+          .fontWeight(FontWeight.Bold)
+          .fontColor(Color.Black)
+          .maxLines(1)
+          .textAlign(TextAlign.Center)
+          .textOverflow({ overflow: TextOverflow.Ellipsis })
+
+        Text(this.artist)
+          .fontSize(14)
+          .fontWeight(FontWeight.Bold)
+          .fontColor('#B3000000')
+          .maxLines(1)
+          .textAlign(TextAlign.Center)
+          .textOverflow({ overflow: TextOverflow.Ellipsis })
+
+        Column({ space: 2 }) {
+          Text(this.displayLyricLine1)
+            .fontSize(15)
+            .fontWeight(FontWeight.Bold)
+            .fontColor('#D9000000')
+            .maxLines(1)
+            .textAlign(TextAlign.Center)
+            .textOverflow({ overflow: TextOverflow.Ellipsis })
+            .opacity(this.displayLyricLine1 === '' ? 0 : this.lyricOpacity)
+            .translate({ x: 0, y: this.lyricTranslateY })
+
+          Text(this.displayLyricLine2)
+            .fontSize(13)
+            .fontWeight(FontWeight.Medium)
+            .fontColor('#D9000000')
+            .maxLines(1)
+            .textAlign(TextAlign.Center)
+            .textOverflow({ overflow: TextOverflow.Ellipsis })
+            .opacity(this.displayLyricLine2 === '' ? 0 : this.lyricOpacity * 0.82)
+            .translate({ x: 0, y: this.lyricTranslateY + 4 })
+        }
+        .width('100%')
+        .height(28)
+        .justifyContent(FlexAlign.Center)
+
+        Row({ space: 16 }) {
+          this.ControlButton($r('sys.symbol.backward_end_fill'),
+            MusicCardActionConstants.ACTION_PREVIOUS, 18, 18)
+          this.PlayProgressButton()
+          this.ControlButton($r('sys.symbol.forward_end_fill'),
+            MusicCardActionConstants.ACTION_NEXT, 18, 18)
+        }
+        .justifyContent(FlexAlign.Center)
+        .alignItems(VerticalAlign.Center)
+      }
+      .width('100%')
+      .height('100%')
+      .alignItems(HorizontalAlign.Center)
+      .justifyContent(FlexAlign.Center)
+      .padding({ left: 16, right: 16, top: 16, bottom: 14 })
+    }
+    .width('100%')
+    .height('100%')
+    .clip(true)
+    .onClick(() => this.postRouterAction(MusicCardActionConstants.ACTION_OPEN_PLAYER))
+  }
+}

+ 3 - 3
entry/src/main/ets/widget/pages/MusicPlayerWidgetWideCard.ets

@@ -250,12 +250,12 @@ struct MusicPlayerWidgetWideCard {
 
               Button({ type: ButtonType.Circle, stateEffect: true }) {
                 SymbolGlyph(this.isPlaying ? $r('sys.symbol.pause_fill') : $r('sys.symbol.play_fill'))
-                  .fontSize(34)
+                  .fontSize(30)
                   .fontColor([Color.White])
                   .effectStrategy(SymbolEffectStrategy.HIERARCHICAL)
               }
-              .width(36)
-              .height(36)
+              .width(35)
+              .height(35)
               .backgroundColor(Color.Transparent)
               .onClick(() => this.postControlAction(MusicCardActionConstants.ACTION_PLAY_PAUSE))
 

+ 16 - 0
entry/src/main/resources/base/element/string.json

@@ -747,6 +747,14 @@
       "name": "music_card_wide_desc",
       "value": "音乐播放卡片(中等模式)"
     },
+    {
+      "name": "music_card_small_cover_display_name",
+      "value": "音乐封面卡片"
+    },
+    {
+      "name": "music_card_small_cover_desc",
+      "value": "音乐播放卡片(小型封面样式)"
+    },
     {
       "name": "music_card_lyric_display_name",
       "value": "音乐歌词卡片"
@@ -754,6 +762,14 @@
     {
       "name": "music_card_lyric_desc",
       "value": "音乐歌词卡片(两行歌词)"
+    },
+    {
+      "name": "music_card_dynamic_lyric_display_name",
+      "value": "音乐动态歌词卡片"
+    },
+    {
+      "name": "music_card_dynamic_lyric_desc",
+      "value": "音乐歌词卡片(4x4 动态歌词模式)"
     }
   ]
 }

+ 40 - 0
entry/src/main/resources/base/profile/form_config.json

@@ -40,6 +40,26 @@
         "2*4"
       ]
     },
+    {
+      "name": "music_player_widget_small_cover",
+      "displayName": "$string:music_card_small_cover_display_name",
+      "description": "$string:music_card_small_cover_desc",
+      "src": "./ets/widget/pages/MusicPlayerWidgetMiniCard.ets",
+      "uiSyntax": "arkts",
+      "window": {
+        "designWidth": 720,
+        "autoDesignWidth": true
+      },
+      "colorMode": "auto",
+      "isDynamic": true,
+      "isDefault": false,
+      "updateEnabled": false,
+      "updateDuration": 1,
+      "defaultDimension": "2*2",
+      "supportDimensions": [
+        "2*2"
+      ]
+    },
     {
       "name": "music_player_widget_lyric",
       "displayName": "$string:music_card_lyric_display_name",
@@ -59,6 +79,26 @@
       "supportDimensions": [
         "2*4"
       ]
+    },
+    {
+      "name": "music_player_widget_dynamic_lyric",
+      "displayName": "$string:music_card_dynamic_lyric_display_name",
+      "description": "$string:music_card_dynamic_lyric_desc",
+      "src": "./ets/widget/pages/MusicPlayerWidgetDynamicLyricCard.ets",
+      "uiSyntax": "arkts",
+      "window": {
+        "designWidth": 720,
+        "autoDesignWidth": true
+      },
+      "colorMode": "auto",
+      "isDynamic": true,
+      "isDefault": false,
+      "updateEnabled": false,
+      "updateDuration": 1,
+      "defaultDimension": "4*4",
+      "supportDimensions": [
+        "4*4"
+      ]
     }
   ]
 }