|
|
@@ -1,205 +1,17 @@
|
|
|
-import React, { useState, useEffect } from 'react';
|
|
|
import { useParams } from 'react-router-dom';
|
|
|
import './index.css';
|
|
|
-import { getPayListDetail } from '@/apis/payList';
|
|
|
-import { Image, Spin } from 'antd';
|
|
|
-import { LoadingOutlined } from '@ant-design/icons';
|
|
|
-
|
|
|
-// 定义API返回的数据结构
|
|
|
-interface Playlist {
|
|
|
- id: number;
|
|
|
- userId: number;
|
|
|
- playlistName: string;
|
|
|
- coverUrl: string | null;
|
|
|
- description: string | null;
|
|
|
- tag: string | null;
|
|
|
- songCount: number;
|
|
|
- playCount: number;
|
|
|
- createTime: string;
|
|
|
- updateTime: string;
|
|
|
- status: boolean;
|
|
|
-}
|
|
|
-
|
|
|
-interface Song {
|
|
|
- id: number;
|
|
|
- songName: string;
|
|
|
- artistId: number;
|
|
|
- albumId: number | null;
|
|
|
- duration: number;
|
|
|
- fileUrl: string;
|
|
|
- coverUrl: string;
|
|
|
- releaseTime: string;
|
|
|
- lyrics: string;
|
|
|
- playCount: number;
|
|
|
- isPaid: number;
|
|
|
- price: number;
|
|
|
- createTime: string;
|
|
|
- updateTime: string;
|
|
|
- status: number;
|
|
|
- auditReason: string | null;
|
|
|
- auditTime: string | null;
|
|
|
- publishTime: string | null;
|
|
|
- shelfTime: string | null;
|
|
|
- offShelfTime: string | null;
|
|
|
- deleteFlag: number;
|
|
|
- deleteTime: string | null;
|
|
|
- songType: string | null;
|
|
|
- version: string | null;
|
|
|
- workType: string | null;
|
|
|
- genre: string | null;
|
|
|
- language: string | null;
|
|
|
- lyricist: string | null;
|
|
|
- composer: string | null;
|
|
|
- arranger: string | null;
|
|
|
- singerName: string | null;
|
|
|
-}
|
|
|
-
|
|
|
-interface PlaylistData {
|
|
|
- playlist: Playlist;
|
|
|
- songs: Song[];
|
|
|
-}
|
|
|
+import PlaylistDetail from '../components/PlaylistDetail';
|
|
|
|
|
|
const Mine_Playlist = () => {
|
|
|
const { id } = useParams<{ id: string }>();
|
|
|
- const [playlistData, setPlaylistData] = useState<PlaylistData | null>(null);
|
|
|
- const [loading, setLoading] = useState(true);
|
|
|
- const [error, setError] = useState<string | null>(null);
|
|
|
-
|
|
|
- // 格式化时间为 YYYY-MM-DD 格式
|
|
|
- const formatDate = (dateString: string) => {
|
|
|
- const date = new Date(dateString);
|
|
|
- return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
|
|
|
- };
|
|
|
-
|
|
|
- // 将秒数转换为 mm:ss 格式
|
|
|
- const formatDuration = (seconds: number) => {
|
|
|
- const mins = Math.floor(seconds / 60);
|
|
|
- const secs = seconds % 60;
|
|
|
- return `${mins}:${secs.toString().padStart(2, '0')}`;
|
|
|
- };
|
|
|
-
|
|
|
- // 请求歌单详情
|
|
|
- useEffect(() => {
|
|
|
- const fetchPlaylistDetails = async () => {
|
|
|
- try {
|
|
|
- setLoading(true);
|
|
|
- setError(null);
|
|
|
-
|
|
|
- if (!id) {
|
|
|
- throw new Error('缺少歌单ID');
|
|
|
- }
|
|
|
-
|
|
|
- // 调用API获取真实数据
|
|
|
- const response = await getPayListDetail(Number(id));
|
|
|
-
|
|
|
- if (response.code === 200) {
|
|
|
- // 直接使用返回的数据,不再需要解析JSON字符串
|
|
|
- setPlaylistData(response.data);
|
|
|
- } else {
|
|
|
- throw new Error(response.message || '获取歌单失败');
|
|
|
- }
|
|
|
- } catch (err: any) {
|
|
|
- console.error('获取歌单失败:', err);
|
|
|
- setError(err.message || '获取歌单失败');
|
|
|
- } finally {
|
|
|
- setLoading(false);
|
|
|
- }
|
|
|
- };
|
|
|
|
|
|
- if (id) {
|
|
|
- fetchPlaylistDetails();
|
|
|
- }
|
|
|
- }, [id]);
|
|
|
-
|
|
|
- if (loading) {
|
|
|
- return (
|
|
|
- <div className="loading" style={{
|
|
|
- display: 'flex',
|
|
|
- justifyContent: 'center',
|
|
|
- alignItems: 'center',
|
|
|
- height: '100vh',
|
|
|
- width: '100vw',
|
|
|
- position: 'fixed',
|
|
|
- top: 0,
|
|
|
- left: 0,
|
|
|
- backgroundColor: 'rgba(255, 255, 255, 0.8)',
|
|
|
- zIndex: 9999
|
|
|
- }}>
|
|
|
- <Spin indicator={<LoadingOutlined style={{ fontSize: 48 }} spin />} />
|
|
|
- </div>
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- if (error) {
|
|
|
- return <div className="error">错误: {error}</div>;
|
|
|
- }
|
|
|
-
|
|
|
- if (!playlistData || !playlistData.playlist) {
|
|
|
- return <div className="not-found">歌单不存在</div>;
|
|
|
+ if (!id) {
|
|
|
+ return <div className="not-found">缺少歌单ID</div>;
|
|
|
}
|
|
|
|
|
|
- const { playlist, songs } = playlistData;
|
|
|
-
|
|
|
- // 确保 songs 是数组,如果不是则默认为空数组
|
|
|
- const validSongs = Array.isArray(songs) ? songs : [];
|
|
|
-
|
|
|
return (
|
|
|
- <div className="playlist-page">
|
|
|
- {/* 歌单头部 */}
|
|
|
- <div className="playlist-header">
|
|
|
- <img
|
|
|
- src={playlist.coverUrl || 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png'}
|
|
|
- alt={playlist.playlistName}
|
|
|
- className="cover-img"
|
|
|
- />
|
|
|
- <div className="playlist-info">
|
|
|
- <h1>{playlist.playlistName}</h1>
|
|
|
- <div className="meta">
|
|
|
- <span className="create-time"> {formatDate(playlist.createTime)} 创建</span>
|
|
|
- </div>
|
|
|
- <div className="actions">
|
|
|
- <button className="play-btn">播放</button>
|
|
|
- <button className="add-btn">+</button>
|
|
|
- <button className="collect-btn">收藏</button>
|
|
|
- <button className="share-btn">分享</button>
|
|
|
- <button className="download-btn">下载</button>
|
|
|
- <button className="comment-btn">评论</button>
|
|
|
- </div>
|
|
|
- <div className="play-count">
|
|
|
- 播放:<strong>{playlist.playCount}</strong>次
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- {/* 歌曲列表 */}
|
|
|
- {validSongs.length > 0 ? (
|
|
|
- <div className="song-list-container">
|
|
|
- <div className="song-list-header">
|
|
|
- <div className="song-number">序号</div>
|
|
|
- <div className="song-title">歌曲标题</div>
|
|
|
- <div className="song-duration">时长</div>
|
|
|
- <div className="song-artist">歌手</div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <ul className="song-list">
|
|
|
- {validSongs.map((song, index) => (
|
|
|
- <li key={song.id} className="song-item">
|
|
|
- <div className="song-number">{index + 1}</div>
|
|
|
- <div className="song-title">
|
|
|
- <span className="play-icon">▶</span>
|
|
|
- {song.songName}
|
|
|
- </div>
|
|
|
- <div className="song-duration">{formatDuration(song.duration)}</div>
|
|
|
- <div className="song-artist">{song.singerName || '未知歌手'}</div>
|
|
|
- </li>
|
|
|
- ))}
|
|
|
- </ul>
|
|
|
- </div>
|
|
|
- ) : (
|
|
|
- <div>
|
|
|
- <Image preview={false} src="http://117.72.120.45:9000/public/musician/playlist/songNull.png" />
|
|
|
- </div>
|
|
|
- )}
|
|
|
+ <div>
|
|
|
+ <PlaylistDetail id={Number(id)} showCollect={false} />
|
|
|
</div>
|
|
|
);
|
|
|
};
|