Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ declare module 'vue' {
copy: typeof import('./src/components/Global/Provider copy.vue')['default']
CopyLyrics: typeof import('./src/components/Modal/CopyLyrics.vue')['default']
CoverList: typeof import('./src/components/List/CoverList.vue')['default']
CoverManager: typeof import('./src/components/Modal/Setting/CoverManager.vue')['default']
CoverMenu: typeof import('./src/components/Menu/CoverMenu.vue')['default']
CreatePlaylist: typeof import('./src/components/Modal/CreatePlaylist.vue')['default']
CustomCode: typeof import('./src/components/Modal/Setting/CustomCode.vue')['default']
Expand Down Expand Up @@ -161,6 +162,7 @@ declare module 'vue' {
PlayerSlider: typeof import('./src/components/Player/PlayerComponents/PlayerSlider.vue')['default']
PlayerSpectrum: typeof import('./src/components/Player/PlayerComponents/PlayerSpectrum.vue')['default']
PlaylistAdd: typeof import('./src/components/Modal/PlaylistAdd.vue')['default']
PlaylistPageManager: typeof import('./src/components/Modal/Setting/PlaylistPageManager.vue')['default']
PlaySetting: typeof import('./src/components/Setting/old/PlaySetting.vue')['default']
Provider: typeof import('./src/components/Global/Provider.vue')['default']
ProxyConfig: typeof import('./src/components/Setting/components/ProxyConfig.vue')['default']
Expand Down
35 changes: 32 additions & 3 deletions electron/main/ipc/ipc-file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,12 @@ const initFileIpc = (): void => {
size: (size / (1024 * 1024)).toFixed(2),
path: fullPath,
quality: format.bitrate ?? 0,
replayGain: {
trackGain: common.replaygain_track_gain?.ratio,
trackPeak: common.replaygain_track_peak?.ratio,
albumGain: common.replaygain_album_gain?.ratio,
albumPeak: common.replaygain_album_peak?.ratio,
},
};
} catch (err) {
ipcLog.warn(`⚠️ Failed to parse file: ${fullPath}`, err);
Expand Down Expand Up @@ -193,6 +199,12 @@ const initFileIpc = (): void => {
format,
// md5
md5: await getFileMD5(filePath),
replayGain: {
trackGain: common.replaygain_track_gain?.ratio,
trackPeak: common.replaygain_track_peak?.ratio,
albumGain: common.replaygain_album_gain?.ratio,
albumPeak: common.replaygain_album_peak?.ratio,
},
};
} catch (error) {
ipcLog.error("❌ Error fetching music metadata:", error);
Expand Down Expand Up @@ -636,9 +648,26 @@ const initFileIpc = (): void => {
Id3v2Settings.defaultVersion = 3;

songFile.tag.title = songData?.name || "未知曲目";
songFile.tag.album = songData?.album?.name || "未知专辑";
songFile.tag.performers = songData?.artists?.map((ar: any) => ar.name) || ["未知艺术家"];
songFile.tag.albumArtists = songData?.artists?.map((ar: any) => ar.name) || ["未知艺术家"];
songFile.tag.album =
(typeof songData?.album === "string" ? songData.album : songData?.album?.name) || "未知专辑";
// 处理歌手信息(兼容字符串和数组格式)
const getArtistNames = (artists: any): string[] => {
if (Array.isArray(artists)) {
return artists
.map((ar: any) => (typeof ar === "string" ? ar : ar?.name || ""))
.filter((name) => name && name.trim().length > 0);
}
if (typeof artists === "string" && artists.trim().length > 0) {
return [artists];
}
return [];
};

const artistNames = getArtistNames(songData?.artists);
const finalArtists = artistNames.length > 0 ? artistNames : ["未知艺术家"];

songFile.tag.performers = finalArtists;
songFile.tag.albumArtists = finalArtists;
if (lyric && downloadLyric) songFile.tag.lyrics = lyric;
if (songCover && downloadCover) songFile.tag.pictures = [songCover];
// 保存元信息
Expand Down
18 changes: 13 additions & 5 deletions src/components/Card/SongCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@
class="name-text"
>
{{
settingStore.hideLyricBrackets
settingStore.hideBracketedContent
? removeBrackets(song?.name)
: song?.name || "未知曲目"
}}
<n-text
v-if="song.alia?.length && !settingStore.hideLyricBrackets"
v-if="song.alia?.length && !settingStore.hideBracketedContent"
class="alia"
depth="3"
>
Expand Down Expand Up @@ -120,14 +120,22 @@
class="ar"
@click="openJumpArtist(song.artists, ar.id)"
>
{{ ar.name }}
{{
settingStore.hideBracketedContent ? removeBrackets(ar.name) : ar.name
}}
</n-text>
</div>
<div v-else-if="song.type === 'radio'" class="artists">
<n-text class="ar"> 电台节目 </n-text>
</div>
<div v-else class="artists" @click="openJumpArtist(song.artists)">
<n-text class="ar"> {{ song.artists || "未知艺术家" }} </n-text>
<n-text class="ar">
{{
settingStore.hideBracketedContent
? removeBrackets(song.artists)
: song.artists || "未知艺术家"
}}
</n-text>
</div>
</n-flex>
</n-flex>
Expand Down Expand Up @@ -236,7 +244,7 @@ const qualityColor = computed(() => {
const albumName = computed(() => {
const album = song.value.album;
const name = isObject(album) ? album.name : album;
return (settingStore.hideLyricBrackets ? removeBrackets(name) : name) || "未知专辑";
return (settingStore.hideBracketedContent ? removeBrackets(name) : name) || "未知专辑";
});

// 加载本地歌曲封面
Expand Down
16 changes: 14 additions & 2 deletions src/components/Card/SongDataCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,20 @@
<div v-if="Array.isArray(data.artists)" class="artists text-hidden">
<SvgIcon name="Artist" :depth="3" />
<n-text v-for="ar in data.artists" :key="ar.id" class="ar">
{{ ar.name }}
{{
settingStore.hideBracketedContent ? removeBrackets(ar.name) : ar.name
}}
</n-text>
</div>
<div v-else class="artists text-hidden">
<SvgIcon name="Artist" :depth="3" />
<n-text class="ar"> {{ data.artists || "未知艺术家" }} </n-text>
<n-text class="ar">
{{
settingStore.hideBracketedContent
? removeBrackets(data.artists)
: data.artists || "未知艺术家"
}}
</n-text>
</div>
<div class="album text-hidden">
<SvgIcon name="Album" :depth="3" />
Expand All @@ -47,6 +55,10 @@
import type { SongType } from "@/types/main";
import { coverLoaded } from "@/utils/helper";
import { isObject } from "lodash-es";
import { removeBrackets } from "@/utils/format";
import { useSettingStore } from "@/stores";

const settingStore = useSettingStore();

defineProps<{
data: SongType | null;
Expand Down
3 changes: 2 additions & 1 deletion src/components/Card/SongListCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
</n-flex>
<div class="content">
<!-- 封面 -->
<div class="cover">
<div v-if="!hiddenCover" class="cover">
<n-image v-if="cover" :src="cover" preview-disabled lazy @load="coverLoaded">
<template #placeholder>
<div class="cover-loading">
Expand Down Expand Up @@ -65,6 +65,7 @@ const props = defineProps<{
loading?: boolean;
height?: number;
cover?: string;
hiddenCover?: boolean;
}>();

// 列表前三首
Expand Down
31 changes: 26 additions & 5 deletions src/components/List/ArtistList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<div
v-for="(item, index) in data"
:key="index"
class="artist-item"
:class="['artist-item', { 'no-cover': hiddenCover }]"
@click="
router.push({
name: 'artist',
Expand All @@ -14,7 +14,7 @@
"
>
<!-- 封面 -->
<div class="cover">
<div v-if="!hiddenCover" class="cover">
<s-image
:src="item.coverSize?.m || item.cover"
default-src="/images/artist.jpg?asset"
Expand All @@ -31,7 +31,9 @@
</div>
<!-- 信息 -->
<div class="cover-data">
<n-text class="name text-hidden">{{ item.name }}</n-text>
<n-text class="name text-hidden">{{
settingStore.hideBracketedContent ? removeBrackets(item.name) : item.name
}}</n-text>
<!-- 数量 -->
<div v-if="item.musicSize" class="num">
<SvgIcon name="Music" :depth="3" />
Expand All @@ -49,8 +51,8 @@
</div>
<div v-else-if="loading" class="artist-list">
<div class="artist-grid">
<div v-for="item in 50" :key="item" class="artist-item">
<div class="cover">
<div v-for="item in 50" :key="item" :class="['artist-item', { 'no-cover': hiddenCover }]">
<div v-if="!hiddenCover" class="cover">
<n-skeleton class="cover-img" />
</div>
<div class="cover-data">
Expand All @@ -66,13 +68,16 @@

<script setup lang="ts">
import type { ArtistType } from "@/types/main";
import { removeBrackets } from "@/utils/format";
import { useSettingStore } from "@/stores";

defineProps<{
data: ArtistType[];
type?: "playlist" | "album" | "video";
loadMore?: boolean;
loading?: boolean;
loadingText?: string;
hiddenCover?: boolean;
}>();

const emit = defineEmits<{
Expand All @@ -81,6 +86,7 @@ const emit = defineEmits<{
}>();

const router = useRouter();
const settingStore = useSettingStore();
</script>

<style lang="scss" scoped>
Expand Down Expand Up @@ -191,6 +197,21 @@ const router = useRouter();
&:active {
transform: scale(0.98);
}
&.no-cover {
background-color: var(--surface-container-hex);
border: 2px solid rgba(var(--primary), 0.12);
padding: 12px 0;
&:hover {
border-color: rgba(var(--primary), 0.58);
}
.cover-data {
height: 100%;
justify-content: center;
.name {
font-weight: bold;
}
}
}
}
.load-more {
margin: 20px 0;
Expand Down
16 changes: 9 additions & 7 deletions src/components/List/CommentList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
<Transition name="fade" mode="out-in">
<n-flex v-if="data.length > 0" :size="20" :class="['comment-list', { transparent }]" vertical>
<n-flex
v-for="(item, index) in data"
:key="index"
:size="20"
class="comments"
@dblclick="handleDoubleClick(item)"
>
<div v-if="!transparent" class="user">
v-for="(item, index) in data"
:key="index"
:size="0"
class="comments"
@dblclick="handleDoubleClick(item)"
>
<div v-if="!transparent && !hiddenCover" class="user">
<div class="avatar">
<n-image
:src="
Expand Down Expand Up @@ -116,6 +116,7 @@ const props = defineProps<{
transparent?: boolean;
// 资源 ID
resId: number;
hiddenCover?: boolean;
}>();

const emit = defineEmits<{
Expand Down Expand Up @@ -228,6 +229,7 @@ const handleDoubleClick = debounce(async (item: CommentType) => {
align-items: center;
min-width: 60px;
width: 60px;
margin-right: 12px;
.avatar {
position: relative;
display: flex;
Expand Down
Loading