music列表增加封面图

This commit is contained in:
mtvpls
2026-05-27 11:42:01 +08:00
parent c08a5974b4
commit 84e74231d4
3 changed files with 72 additions and 4 deletions
+31 -1
View File
@@ -1,20 +1,50 @@
'use client';
import { useState } from 'react';
import { addMusicSongToPlaylist, playMusicLater, playMusicSong } from '@/lib/music/actions';
import { SourcePill } from '@/lib/music/shared';
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[] }) {
return (
<div className="space-y-1">
{songs.map((song, index) => (
<div
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)}>
{index + 1}
</div>
<div onClick={() => playMusicSong(song, index)}>
<SongCover song={song} />
</div>
<div className="min-w-0" onClick={() => playMusicSong(song, index)}>
<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>
+28 -2
View File
@@ -91,7 +91,23 @@ export interface LxServerSong {
interval?: string;
albumName?: string;
img?: string;
image?: string;
imageUrl?: string;
albumPicUrl?: string;
pic?: string;
cover?: 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 {
@@ -163,8 +179,18 @@ export function normalizeLxSong(song: LxServerSong): MusicV2Song {
songmid: song.songmid,
name: song.name,
artist: song.singer,
album: song.albumName,
cover: song.img,
album: song.albumName || song.meta?.albumName,
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,
});
}
+13 -1
View File
@@ -19,12 +19,24 @@ export function normalizeSource(source: string | undefined | null): MusicSource
export function mapSong(song: any): Song {
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 {
id: String(song.id ?? song.songId ?? song.rid ?? song.mid ?? ''),
name: song.name || song.title || '未知歌曲',
artist: song.artist || song.singer || song.artists || '未知艺术家',
album: song.album || song.albumName,
pic: song.pic || song.cover || song.img,
pic,
platform: normalizeSource(rawSource),
duration: song.durationSec || song.duration,
durationText: song.durationText || song.interval,