| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- import React, { useState } from 'react';
- import AudioPlayer from 'react-h5-audio-player';
- import 'react-h5-audio-player/lib/styles.css';
- interface Song {
- id: number;
- title: string;
- artist: string;
- url: string;
- cover: string;
- duration: string;
- }
- const MusicPlayer: React.FC = () => {
- const playlist: Song[] = [
- {
- id: 1,
- title: '放生',
- artist: '陈旧',
- url: 'http://117.72.120.45:9000/testbucket/1232e131.mp3',
- cover: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
- duration: '04:24'
- },
- {
- id: 2,
- title: '夜曲',
- artist: '周杰伦',
- url: 'http://music.163.com/song/media/outer/url?id=123456.mp3',
- cover: 'https://p1.music.126.net/6y-UleORITEDbvrOLV0Q8A==/5639395138885805.jpg',
- duration: '03:45'
- },
- {
- id: 3,
- title: '青花瓷',
- artist: '周杰伦',
- url: 'http://music.163.com/song/media/outer/url?id=789012.mp3',
- cover: 'https://p1.music.126.net/6y-UleORITEDbvrOLV0Q8A==/5639395138885805.jpg',
- duration: '03:58'
- }
- ];
- const [currentTrackIndex, setCurrentTrackIndex] = useState(0);
- const [isPlaying, setIsPlaying] = useState(false);
- const [audioError, setAudioError] = useState<string | null>(null);
- const currentTrack = playlist[currentTrackIndex];
- // 上一首逻辑
- const handlePrevious = () => {
- setCurrentTrackIndex(prev => (prev === 0 ? playlist.length - 1 : prev - 1));
- setAudioError(null);
- if (isPlaying) setIsPlaying(true); // 切换后继续播放
- };
- // 下一首逻辑
- const handleNext = () => {
- setCurrentTrackIndex(prev => (prev === playlist.length - 1 ? 0 : prev + 1));
- setAudioError(null);
- if (isPlaying) setIsPlaying(true); // 切换后继续播放
- };
- // 播放列表项点击
- const handleTrackSelect = (index: number) => {
- setCurrentTrackIndex(index);
- setIsPlaying(true);
- setAudioError(null);
- };
- return (
- <div style={{ padding: '20px' }}>
- {/* 错误提示 */}
- {audioError && (
- <div style={{ color: 'red', padding: '10px', backgroundColor: '#ffe6e6', borderRadius: '4px', marginBottom: '10px' }}>
- {audioError}
- </div>
- )}
- {/* 播放器:适配 3.10.1 版本的核心 Props */}
- <AudioPlayer
- key={currentTrackIndex} // 切换歌曲时强制刷新组件
- src={currentTrack.url}
- onPlay={() => setIsPlaying(true)}
- onPause={() => setIsPlaying(false)}
- onClickPrevious={handlePrevious} // 绑定上一首(3.10.1 支持)
- onClickNext={handleNext} // 绑定下一首(3.10.1 支持)
- onEnded={handleNext} // 播放结束自动下一首
- onError={(e) => setAudioError('音频加载失败,请检查网络')}
- showSkipControls={true} // 显示上一首/下一首按钮
- header={
- // 手动渲染封面图和歌曲信息(替代 3.10.1 不支持的 cover 属性)
- <div style={{ textAlign: 'center', marginBottom: '10px' }}>
- <img
- src={currentTrack.cover}
- alt={currentTrack.title}
- style={{ width: '80px', height: '80px', borderRadius: '8px', marginBottom: '8px' }}
- />
- <h3 style={{ margin: '0', fontSize: '16px' }}>{currentTrack.title}</h3>
- <p style={{ margin: '0', fontSize: '14px', color: '#666' }}>{currentTrack.artist}</p>
- </div>
- }
- autoPlay={false}
- style={{
- // 自定义播放器样式(适配深色/浅色主题)
- backgroundColor: '#f5f5f5',
- padding: '10px',
- borderRadius: '8px'
- }}
- />
- {/* 播放列表 */}
- <div style={{ marginTop: '20px' }}>
- <h3 style={{ fontSize: '16px' }}>播放列表</h3>
- <ul style={{ listStyle: 'none', padding: '0', border: '1px solid #eee', borderRadius: '8px' }}>
- {playlist.map((song, index) => (
- <li
- key={song.id}
- onClick={() => handleTrackSelect(index)}
- style={{
- padding: '12px',
- backgroundColor: index === currentTrackIndex ? '#e6f7ff' : '#fff',
- borderBottom: index !== playlist.length - 1 ? '1px solid #eee' : 'none',
- cursor: 'pointer',
- display: 'flex',
- alignItems: 'center'
- }}
- >
- {/* 播放状态指示器 */}
- {index === currentTrackIndex && isPlaying && (
- <span style={{ marginRight: '10px', color: '#1890ff' }}>▶</span>
- )}
- {/* 列表项封面图 */}
- <img
- src={song.cover}
- alt={song.title}
- style={{ width: '36px', height: '36px', borderRadius: '4px', marginRight: '10px' }}
- />
- {/* 歌曲信息 */}
- <div style={{ flex: 1 }}>
- <div style={{ fontSize: '14px', fontWeight: index === currentTrackIndex ? 'bold' : 'normal' }}>
- {song.title}
- </div>
- <div style={{ fontSize: '12px', color: '#666' }}>
- {song.artist} · {song.duration}
- </div>
- </div>
- </li>
- ))}
- </ul>
- </div>
- </div>
- );
- };
- export default MusicPlayer;
|