music列表增加封面图
This commit is contained in:
@@ -1,20 +1,50 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
|
import { useState } from 'react';
|
||||||
import { addMusicSongToPlaylist, playMusicLater, playMusicSong } from '@/lib/music/actions';
|
import { addMusicSongToPlaylist, playMusicLater, playMusicSong } from '@/lib/music/actions';
|
||||||
import { SourcePill } from '@/lib/music/shared';
|
import { SourcePill } from '@/lib/music/shared';
|
||||||
import type { Song } from '@/lib/music/types';
|
import type { Song } from '@/lib/music/types';
|
||||||
|
|
||||||
|
function SongCover({ song }: { song: Song }) {
|
||||||
|
const [failed, setFailed] = useState(false);
|
||||||
|
const cover = song.pic && !failed ? song.pic : '';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="relative h-11 w-11 shrink-0 overflow-hidden rounded-lg bg-white/10 shadow-inner">
|
||||||
|
{cover ? (
|
||||||
|
<img
|
||||||
|
src={cover}
|
||||||
|
alt={`${song.name} 封面`}
|
||||||
|
loading="lazy"
|
||||||
|
referrerPolicy="no-referrer"
|
||||||
|
onError={() => setFailed(true)}
|
||||||
|
className="h-full w-full object-cover"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div className="flex h-full w-full items-center justify-center text-zinc-500">
|
||||||
|
<svg className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.8} d="M9 19V6l12-2v13M9 19c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2Zm12-2c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2Z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export default function SongList({ songs }: { songs: Song[] }) {
|
export default function SongList({ songs }: { songs: Song[] }) {
|
||||||
return (
|
return (
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
{songs.map((song, index) => (
|
{songs.map((song, index) => (
|
||||||
<div
|
<div
|
||||||
key={`${song.platform}-${song.id}-${index}`}
|
key={`${song.platform}-${song.id}-${index}`}
|
||||||
className="grid grid-cols-[40px_1fr_auto_auto] md:grid-cols-[50px_2fr_1fr_auto_auto] gap-2 px-3 py-3 rounded-lg cursor-pointer transition-all hover:bg-white/5"
|
className="grid grid-cols-[32px_44px_1fr_auto_auto] md:grid-cols-[44px_48px_2fr_1fr_auto_auto] items-center gap-2 px-3 py-3 rounded-lg cursor-pointer transition-all hover:bg-white/5"
|
||||||
>
|
>
|
||||||
<div className="text-center text-zinc-500 dark:text-zinc-300 text-sm" onClick={() => playMusicSong(song, index)}>
|
<div className="text-center text-zinc-500 dark:text-zinc-300 text-sm" onClick={() => playMusicSong(song, index)}>
|
||||||
{index + 1}
|
{index + 1}
|
||||||
</div>
|
</div>
|
||||||
|
<div onClick={() => playMusicSong(song, index)}>
|
||||||
|
<SongCover song={song} />
|
||||||
|
</div>
|
||||||
<div className="min-w-0" onClick={() => playMusicSong(song, index)}>
|
<div className="min-w-0" onClick={() => playMusicSong(song, index)}>
|
||||||
<div className="text-sm font-medium text-white truncate">{song.name}</div>
|
<div className="text-sm font-medium text-white truncate">{song.name}</div>
|
||||||
<div className="text-xs text-zinc-500 truncate md:hidden">{song.artist}</div>
|
<div className="text-xs text-zinc-500 truncate md:hidden">{song.artist}</div>
|
||||||
|
|||||||
+28
-2
@@ -91,7 +91,23 @@ export interface LxServerSong {
|
|||||||
interval?: string;
|
interval?: string;
|
||||||
albumName?: string;
|
albumName?: string;
|
||||||
img?: string;
|
img?: string;
|
||||||
|
image?: string;
|
||||||
|
imageUrl?: string;
|
||||||
|
albumPicUrl?: string;
|
||||||
|
pic?: string;
|
||||||
|
cover?: string;
|
||||||
songmid?: string;
|
songmid?: string;
|
||||||
|
meta?: {
|
||||||
|
picUrl?: string;
|
||||||
|
albumName?: string;
|
||||||
|
};
|
||||||
|
album?: {
|
||||||
|
picUrl?: string;
|
||||||
|
pic?: string;
|
||||||
|
};
|
||||||
|
al?: {
|
||||||
|
picUrl?: string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isMusicSource(source: string | null | undefined): source is MusicSource {
|
export function isMusicSource(source: string | null | undefined): source is MusicSource {
|
||||||
@@ -163,8 +179,18 @@ export function normalizeLxSong(song: LxServerSong): MusicV2Song {
|
|||||||
songmid: song.songmid,
|
songmid: song.songmid,
|
||||||
name: song.name,
|
name: song.name,
|
||||||
artist: song.singer,
|
artist: song.singer,
|
||||||
album: song.albumName,
|
album: song.albumName || song.meta?.albumName,
|
||||||
cover: song.img,
|
cover:
|
||||||
|
song.img ||
|
||||||
|
song.pic ||
|
||||||
|
song.cover ||
|
||||||
|
song.image ||
|
||||||
|
song.imageUrl ||
|
||||||
|
song.albumPicUrl ||
|
||||||
|
song.meta?.picUrl ||
|
||||||
|
song.album?.picUrl ||
|
||||||
|
song.album?.pic ||
|
||||||
|
song.al?.picUrl,
|
||||||
durationText: song.interval,
|
durationText: song.interval,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-1
@@ -19,12 +19,24 @@ export function normalizeSource(source: string | undefined | null): MusicSource
|
|||||||
|
|
||||||
export function mapSong(song: any): Song {
|
export function mapSong(song: any): Song {
|
||||||
const rawSource = song.source || song.platform || song.vendor || song.origin;
|
const rawSource = song.source || song.platform || song.vendor || song.origin;
|
||||||
|
const pic =
|
||||||
|
song.pic ||
|
||||||
|
song.cover ||
|
||||||
|
song.img ||
|
||||||
|
song.image ||
|
||||||
|
song.imageUrl ||
|
||||||
|
song.albumPicUrl ||
|
||||||
|
song.meta?.picUrl ||
|
||||||
|
song.album?.picUrl ||
|
||||||
|
song.album?.pic ||
|
||||||
|
song.al?.picUrl;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: String(song.id ?? song.songId ?? song.rid ?? song.mid ?? ''),
|
id: String(song.id ?? song.songId ?? song.rid ?? song.mid ?? ''),
|
||||||
name: song.name || song.title || '未知歌曲',
|
name: song.name || song.title || '未知歌曲',
|
||||||
artist: song.artist || song.singer || song.artists || '未知艺术家',
|
artist: song.artist || song.singer || song.artists || '未知艺术家',
|
||||||
album: song.album || song.albumName,
|
album: song.album || song.albumName,
|
||||||
pic: song.pic || song.cover || song.img,
|
pic,
|
||||||
platform: normalizeSource(rawSource),
|
platform: normalizeSource(rawSource),
|
||||||
duration: song.durationSec || song.duration,
|
duration: song.durationSec || song.duration,
|
||||||
durationText: song.durationText || song.interval,
|
durationText: song.durationText || song.interval,
|
||||||
|
|||||||
Reference in New Issue
Block a user