Skip to content

Commit 6caf99d

Browse files
committed
feat(player): 添加播放状态信息显示功能
- 在设置中新增开关控制是否显示播放状态信息 - 在播放器界面添加当前歌曲及歌词状态信息显示 - 优化歌词管理器逻辑,改进TTML歌词处理 - 调整播放器数据组件布局,支持精简显示模式
1 parent ad27d1e commit 6caf99d

5 files changed

Lines changed: 169 additions & 98 deletions

File tree

src/components/Player/FullPlayer.vue

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,7 @@
3737
@mousemove="playerMove"
3838
>
3939
<Transition name="zoom">
40-
<div
41-
v-if="
42-
!(statusStore.pureLyricMode && musicStore.isHasLrc) ||
43-
musicStore.playSong.type === 'radio'
44-
"
45-
:key="musicStore.playSong.id"
46-
class="content-left"
47-
>
40+
<div v-if="!pureLyricMode" :key="musicStore.playSong.id" class="content-left">
4841
<!-- 封面 -->
4942
<PlayerCover />
5043
<!-- 数据 -->
@@ -58,6 +51,7 @@
5851
v-if="statusStore.pureLyricMode && musicStore.isHasLrc"
5952
:center="statusStore.pureLyricMode"
6053
:theme="statusStore.mainColor"
54+
:light="pureLyricMode"
6155
/>
6256
<!-- 歌词 -->
6357
<MainAMLyric v-if="settingStore.useAMLyrics" />
@@ -100,11 +94,16 @@ const isShowComment = computed<boolean>(
10094
const noLrc = computed<boolean>(() => {
10195
const noNormalLrc = !musicStore.isHasLrc;
10296
const noYrcAvailable = !musicStore.isHasYrc || !settingStore.showYrc;
103-
const notLoading = !statusStore.lyricLoading;
97+
// const notLoading = !statusStore.lyricLoading;
10498
105-
return noNormalLrc && noYrcAvailable && notLoading;
99+
return noNormalLrc && noYrcAvailable;
106100
});
107101
102+
/** 是否处于纯净模式 */
103+
const pureLyricMode = computed<boolean>(
104+
() => (statusStore.pureLyricMode && musicStore.isHasLrc) || musicStore.playSong.type === "radio",
105+
);
106+
108107
// 主内容 key
109108
const playerContentKey = computed(() => `${statusStore.pureLyricMode}`);
110109

src/components/Player/PlayerData.vue

Lines changed: 100 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
<template>
2-
<div :class="['player-data', settingStore.playerType, { center }]">
2+
<div :class="['player-data', settingStore.playerType, { center, light }]">
33
<!-- 名称 -->
44
<div class="name">
55
<span class="name-text text-hidden">{{ musicStore.playSong.name || "未知曲目" }}</span>
66
<!-- 额外信息 -->
7-
<div v-if="statusStore.playUblock || musicStore.playSong.pc" class="extra-info">
7+
<n-flex
8+
v-if="statusStore.playUblock || musicStore.playSong.pc"
9+
class="extra-info"
10+
align="center"
11+
>
812
<n-popover :show-arrow="false" placement="right" raw>
913
<template #trigger>
1014
<SvgIcon
@@ -21,58 +25,74 @@
2125
}}
2226
</div>
2327
</n-popover>
24-
</div>
28+
</n-flex>
2529
</div>
2630
<!-- 别名 -->
2731
<span v-if="musicStore.playSong.alia" class="alia text-hidden">
2832
{{ musicStore.playSong.alia }}
2933
</span>
30-
<!-- 歌手 -->
31-
<div v-if="musicStore.playSong.type !== 'radio'" class="artists">
32-
<SvgIcon :depth="3" name="Artist" size="20" />
33-
<div v-if="Array.isArray(musicStore.playSong.artists)" class="ar-list">
34-
<span
35-
v-for="ar in musicStore.playSong.artists"
36-
:key="ar.id"
37-
class="ar"
38-
@click="jumpPage({ name: 'artist', query: { id: ar.id } })"
39-
>
40-
{{ ar.name }}
34+
<n-flex :align="center ? 'center' : undefined" size="small" vertical>
35+
<!-- 播放状态 -->
36+
<n-flex
37+
v-if="settingStore.showPlayMeta && !light"
38+
class="play-meta"
39+
size="small"
40+
align="center"
41+
>
42+
<!-- 歌词模式 -->
43+
<span class="meta-item">{{ lyricMode }}</span>
44+
<!-- 是否在线 -->
45+
<span class="meta-item">
46+
{{ musicStore.playSong.path ? "LOCAL" : "ONLINE" }}
4147
</span>
48+
</n-flex>
49+
<!-- 歌手 -->
50+
<div v-if="musicStore.playSong.type !== 'radio'" class="artists">
51+
<SvgIcon :depth="3" name="Artist" size="20" />
52+
<div v-if="Array.isArray(musicStore.playSong.artists)" class="ar-list">
53+
<span
54+
v-for="ar in musicStore.playSong.artists"
55+
:key="ar.id"
56+
class="ar"
57+
@click="jumpPage({ name: 'artist', query: { id: ar.id } })"
58+
>
59+
{{ ar.name }}
60+
</span>
61+
</div>
62+
<div v-else class="ar-list">
63+
<span class="ar">{{ musicStore.playSong.artists || "未知艺术家" }}</span>
64+
</div>
4265
</div>
43-
<div v-else class="ar-list">
44-
<span class="ar">{{ musicStore.playSong.artists || "未知艺术家" }}</span>
66+
<div v-else class="artists">
67+
<SvgIcon :depth="3" name="Artist" size="20" />
68+
<div class="ar-list">
69+
<span class="ar">{{ musicStore.playSong.dj?.creator || "未知艺术家" }}</span>
70+
</div>
4571
</div>
46-
</div>
47-
<div v-else class="artists">
48-
<SvgIcon :depth="3" name="Artist" size="20" />
49-
<div class="ar-list">
50-
<span class="ar">{{ musicStore.playSong.dj?.creator || "未知艺术家" }}</span>
72+
<!-- 专辑 -->
73+
<div v-if="musicStore.playSong.type !== 'radio'" class="album">
74+
<SvgIcon :depth="3" name="Album" size="20" />
75+
<span
76+
v-if="isObject(musicStore.playSong.album)"
77+
class="name-text text-hidden"
78+
@click="jumpPage({ name: 'album', query: { id: musicStore.playSong.album.id } })"
79+
>
80+
{{ musicStore.playSong.album?.name || "未知专辑" }}
81+
</span>
82+
<span v-else class="name-text text-hidden">
83+
{{ musicStore.playSong.album || "未知专辑" }}
84+
</span>
5185
</div>
52-
</div>
53-
<!-- 专辑 -->
54-
<div v-if="musicStore.playSong.type !== 'radio'" class="album">
55-
<SvgIcon :depth="3" name="Album" size="20" />
56-
<span
57-
v-if="isObject(musicStore.playSong.album)"
58-
class="name-text text-hidden"
59-
@click="jumpPage({ name: 'album', query: { id: musicStore.playSong.album.id } })"
86+
<!-- 电台 -->
87+
<div
88+
v-if="musicStore.playSong.type === 'radio'"
89+
class="dj"
90+
@click="jumpPage({ name: 'dj', query: { id: musicStore.playSong.dj?.id } })"
6091
>
61-
{{ musicStore.playSong.album?.name || "未知专辑" }}
62-
</span>
63-
<span v-else class="name-text text-hidden">
64-
{{ musicStore.playSong.album || "未知专辑" }}
65-
</span>
66-
</div>
67-
<!-- 电台 -->
68-
<div
69-
v-if="musicStore.playSong.type === 'radio'"
70-
class="dj"
71-
@click="jumpPage({ name: 'dj', query: { id: musicStore.playSong.dj?.id } })"
72-
>
73-
<SvgIcon :depth="3" name="Podcast" size="20" />
74-
<span class="name-text text-hidden">{{ musicStore.playSong.dj?.name || "播客电台" }}</span>
75-
</div>
92+
<SvgIcon :depth="3" name="Podcast" size="20" />
93+
<span class="name-text text-hidden">{{ musicStore.playSong.dj?.name || "播客电台" }}</span>
94+
</div>
95+
</n-flex>
7696
</div>
7797
</template>
7898

@@ -84,13 +104,24 @@ import { debounce, isObject } from "lodash-es";
84104
defineProps<{
85105
center?: boolean;
86106
theme?: string;
107+
// 少量数据模式
108+
light?: boolean;
87109
}>();
88110
89111
const router = useRouter();
90112
const musicStore = useMusicStore();
91113
const statusStore = useStatusStore();
92114
const settingStore = useSettingStore();
93115
116+
// 当前歌词模式
117+
const lyricMode = computed(() => {
118+
if (settingStore.showYrc) {
119+
if (statusStore.usingTTMLLyric) return "TTML";
120+
if (musicStore.isHasYrc) return "YRC";
121+
}
122+
return musicStore.isHasLrc ? "LRC" : "NO-LRC";
123+
});
124+
94125
const jumpPage = debounce(
95126
(go: RouteLocationRaw) => {
96127
if (!go) return;
@@ -134,14 +165,13 @@ const jumpPage = debounce(
134165
}
135166
}
136167
.alia {
137-
margin: 6px 0 6px 2px;
168+
margin: 6px 0 6px 4px;
138169
opacity: 0.6;
139170
font-size: 18px;
140171
line-clamp: 1;
141172
-webkit-line-clamp: 1;
142173
}
143174
.artists {
144-
margin-top: 2px;
145175
display: flex;
146176
align-items: center;
147177
.n-icon {
@@ -178,7 +208,6 @@ const jumpPage = debounce(
178208
}
179209
.album,
180210
.dj {
181-
margin-top: 2px;
182211
font-size: 16px;
183212
display: flex;
184213
align-items: center;
@@ -196,6 +225,16 @@ const jumpPage = debounce(
196225
}
197226
}
198227
}
228+
.play-meta {
229+
padding: 4px 4px;
230+
opacity: 0.6;
231+
.meta-item {
232+
font-size: 12px;
233+
border-radius: 8px;
234+
padding: 2px 6px;
235+
border: 1px solid rgba(var(--main-color), 0.6);
236+
}
237+
}
199238
&.record {
200239
width: 100%;
201240
padding: 0 80px 0 24px;
@@ -219,6 +258,20 @@ const jumpPage = debounce(
219258
text-align: center;
220259
}
221260
}
261+
&.light {
262+
.name {
263+
.name-text {
264+
line-clamp: 1;
265+
-webkit-line-clamp: 1;
266+
}
267+
.extra-info {
268+
display: none;
269+
}
270+
}
271+
.alia {
272+
display: none;
273+
}
274+
}
222275
}
223276
.player-tip {
224277
max-width: 240px;

src/components/Setting/PlaySetting.vue

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,13 @@
155155
</div>
156156
<n-switch v-model:value="settingStore.barLyricShow" class="set" :round="false" />
157157
</n-card>
158+
<n-card class="set-item">
159+
<div class="label">
160+
<n-text class="name">展示播放状态信息</n-text>
161+
<n-text class="tip" :depth="3">展示当前歌曲及歌词的状态信息</n-text>
162+
</div>
163+
<n-switch v-model:value="settingStore.showPlayMeta" class="set" :round="false" />
164+
</n-card>
158165
<n-card class="set-item">
159166
<div class="label">
160167
<n-text class="name">播放列表歌曲数量</n-text>

src/stores/setting.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,8 @@ export interface SettingState {
169169
excludeRegexes: string[];
170170
/** 显示默认本地路径 */
171171
showDefaultLocalPath: boolean;
172+
/** 展示当前歌曲歌词状态信息 */
173+
showPlayMeta: boolean;
172174
}
173175

174176
export const useSettingStore = defineStore("setting", {
@@ -247,6 +249,7 @@ export const useSettingStore = defineStore("setting", {
247249
proxyPort: 80,
248250
useRealIP: false,
249251
realIP: "",
252+
showPlayMeta: false,
250253
}),
251254
getters: {
252255
/**

0 commit comments

Comments
 (0)