@@ -40,6 +40,17 @@ class Player {
4040 // 初始化媒体会话
4141 this . initMediaSession ( ) ;
4242 }
43+ /**
44+ * 洗牌数组(Fisher-Yates)
45+ */
46+ private shuffleArray < T > ( arr : T [ ] ) : T [ ] {
47+ const copy = arr . slice ( ) ;
48+ for ( let i = copy . length - 1 ; i > 0 ; i -- ) {
49+ const j = Math . floor ( Math . random ( ) * ( i + 1 ) ) ;
50+ [ copy [ i ] , copy [ j ] ] = [ copy [ j ] , copy [ i ] ] ;
51+ }
52+ return copy ;
53+ }
4354 /**
4455 * 重置状态
4556 */
@@ -667,19 +678,15 @@ class Player {
667678 this . setSeek ( 0 ) ;
668679 await this . play ( ) ;
669680 }
670- // 列表循环或处于心动模式
671- if ( playSongMode === "repeat" || playHeartbeatMode || playSong . type === "radio" ) {
681+ // 列表循环或处于心动模式或随机模式
682+ if (
683+ playSongMode === "repeat" ||
684+ playSongMode === "shuffle" ||
685+ playHeartbeatMode ||
686+ playSong . type === "radio"
687+ ) {
672688 statusStore . playIndex += type === "next" ? 1 : - 1 ;
673689 }
674- // 随机播放
675- else if ( playSongMode === "shuffle" ) {
676- let newIndex : number ;
677- // 确保不会随机到同一首
678- do {
679- newIndex = Math . floor ( Math . random ( ) * playListLength ) ;
680- } while ( newIndex === statusStore . playIndex ) ;
681- statusStore . playIndex = newIndex ;
682- }
683690 // 单曲循环
684691 else if ( playSongMode === "repeat-once" ) {
685692 statusStore . lyricIndex = - 1 ;
@@ -708,28 +715,65 @@ class Player {
708715 * 切换播放模式
709716 * @param mode 播放模式 repeat / repeat-once / shuffle
710717 */
711- togglePlayMode ( mode : PlayModeType | false ) {
718+ async togglePlayMode ( mode : PlayModeType | false ) {
712719 const statusStore = useStatusStore ( ) ;
720+ const dataStore = useDataStore ( ) ;
721+ const musicStore = useMusicStore ( ) ;
713722 // 退出心动模式
714723 if ( statusStore . playHeartbeatMode ) this . toggleHeartMode ( false ) ;
715- // 若传入了指定模式
724+ // 计算目标模式
725+ let targetMode : PlayModeType ;
716726 if ( mode ) {
717- statusStore . playSongMode = mode ;
727+ targetMode = mode ;
718728 } else {
719729 switch ( statusStore . playSongMode ) {
720730 case "repeat" :
721- statusStore . playSongMode = "repeat-once" ;
731+ targetMode = "repeat-once" ;
722732 break ;
723733 case "shuffle" :
724- statusStore . playSongMode = "repeat" ;
734+ targetMode = "repeat" ;
725735 break ;
726736 case "repeat-once" :
727- statusStore . playSongMode = "shuffle" ;
737+ targetMode = "shuffle" ;
728738 break ;
729739 default :
730- statusStore . playSongMode = "repeat" ;
740+ targetMode = "repeat" ;
741+ }
742+ }
743+ // 进入随机模式:保存原顺序并打乱当前歌单
744+ if ( targetMode === "shuffle" && statusStore . playSongMode !== "shuffle" ) {
745+ const currentList = dataStore . playList ;
746+ if ( currentList && currentList . length > 1 ) {
747+ const currentSongId = musicStore . playSong ?. id ;
748+ await dataStore . setOriginalPlayList ( currentList ) ;
749+ const shuffled = this . shuffleArray ( currentList ) ;
750+ await dataStore . setPlayList ( shuffled ) ;
751+ if ( currentSongId ) {
752+ const newIndex = shuffled . findIndex ( ( s : any ) => s ?. id === currentSongId ) ;
753+ if ( newIndex !== - 1 ) useStatusStore ( ) . playIndex = newIndex ;
754+ }
755+ }
756+ }
757+ // 离开随机模式:恢复到原顺序
758+ if (
759+ statusStore . playSongMode === "shuffle" &&
760+ ( targetMode === "repeat" || targetMode === "repeat-once" )
761+ ) {
762+ const original = await dataStore . getOriginalPlayList ( ) ;
763+ if ( original && original . length ) {
764+ const currentSongId = musicStore . playSong ?. id ;
765+ await dataStore . setPlayList ( original ) ;
766+ if ( currentSongId ) {
767+ const origIndex = original . findIndex ( ( s : any ) => s ?. id === currentSongId ) ;
768+ useStatusStore ( ) . playIndex = origIndex !== - 1 ? origIndex : 0 ;
769+ } else {
770+ useStatusStore ( ) . playIndex = 0 ;
771+ }
772+ await dataStore . clearOriginalPlayList ( ) ;
731773 }
732774 }
775+ // 应用模式
776+ statusStore . playSongMode = targetMode ;
733777 this . playModeSyncIpc ( ) ;
734778 }
735779 /**
0 commit comments