Skip to content

Commit af55159

Browse files
committed
feat(lyric): 增强桌面歌词功能并添加预载下一首选项
- 新增始终显示播放信息选项及界面元素 - 重构歌词数据获取逻辑,支持歌手信息显示 - 添加预载下一首歌曲的开关选项 - 优化URL验证逻辑,确保包含%s占位符 - 修复窗口首次显示置顶问题 - 改进歌词索引计算和显示逻辑
1 parent abbf423 commit af55159

15 files changed

Lines changed: 225 additions & 82 deletions

File tree

electron/main/ipc/ipc-lyric.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,6 @@ const initLyricIpc = (): void => {
8080
lyricWin.webContents.send("update-desktop-lyric-data", { playStatus: status });
8181
});
8282

83-
// 音乐名称更改
84-
ipcMain.on("play-song-change", (_, title) => {
85-
if (!isWinAlive(lyricWin)) return;
86-
lyricWin.webContents.send("update-desktop-lyric-data", { playName: title });
87-
});
88-
8983
// 音乐歌词更改
9084
ipcMain.on("play-lyric-change", (_, lyricData) => {
9185
if (!lyricData || !isWinAlive(lyricWin)) return;

electron/main/ipc/ipc-window.ts

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ import mainWindow from "../windows/main-window";
77
import loadWindow from "../windows/load-window";
88
import loginWindow from "../windows/login-window";
99

10-
// 记录是否已处理启动协议
10+
/** 是否已首次启动 */
11+
let isFirstLaunch = false;
12+
/** 是否已处理协议 */
1113
let isProtocolProcessed = false;
1214

1315
/**
@@ -35,16 +37,19 @@ const initWindowsIpc = (): void => {
3537
if (!mainWin) return;
3638
mainWin?.show();
3739
mainWin?.focus();
38-
// 解决窗口不立即显示
39-
mainWin?.setAlwaysOnTop(true);
40-
// 100ms 后取消置顶
41-
const timer = setTimeout(() => {
42-
if (mainWin && !mainWin.isDestroyed()) {
43-
mainWin.setAlwaysOnTop(false);
44-
mainWin.focus();
45-
clearTimeout(timer);
46-
}
47-
}, 100);
40+
if (!isFirstLaunch) {
41+
// 解决窗口不立即显示
42+
mainWin?.setAlwaysOnTop(true);
43+
// 100ms 后取消置顶
44+
const timer = setTimeout(() => {
45+
if (mainWin && !mainWin.isDestroyed()) {
46+
mainWin.setAlwaysOnTop(false);
47+
mainWin.focus();
48+
clearTimeout(timer);
49+
}
50+
}, 100);
51+
isFirstLaunch = true;
52+
}
4853
// 初始化缩略图工具栏
4954
if (mainWin) {
5055
initThumbar(mainWin);

electron/main/store/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export const useStore = () => {
4949
config: defaultLyricConfig,
5050
},
5151
proxy: "",
52-
amllDbServer: "https://amll-ttml-db.stevexmh.net",
52+
amllDbServer: "https://amll-ttml-db.stevexmh.net/ncm/%s",
5353
},
5454
});
5555
};

electron/server/netease/index.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,8 @@ export const initNcmAPI = async (fastify: FastifyInstance) => {
7070
return reply.status(400).send({ error: "id is required" });
7171
}
7272
const store = useStore();
73-
const server = store.get("amllDbServer") ?? "https://amll-ttml-db.stevexmh.net";
74-
// 净化网址
75-
const cleanServer = server.replace(/\/$/, "");
76-
const url = `${cleanServer}/ncm/${id}`;
73+
const server = store.get("amllDbServer") ?? "https://amll-ttml-db.stevexmh.net/ncm/%s";
74+
const url = server.replace("%s", String(id));
7775
try {
7876
const response = await fetch(url);
7977
if (response.status !== 200) {

src/api/song.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { isElectron } from "@/utils/env";
22
import { songLevelData } from "@/utils/meta";
33
import { SongUnlockServer } from "@/utils/songManager";
4-
import request from "@/utils/request";
54
import { useSettingStore } from "@/stores";
5+
import request from "@/utils/request";
66

77
// 获取歌曲详情
88
export const songDetail = (ids: number | number[]) => {
@@ -78,8 +78,8 @@ export const songLyricTTML = async (id: number) => {
7878
return request({ url: "/lyric/ttml", params: { id, noCookie: true } });
7979
} else {
8080
const settingStore = useSettingStore();
81-
const server = settingStore.amllDbServer || "https://amll-ttml-db.stevexmh.net";
82-
const url = `${server}/ncm/${id}`;
81+
const server = settingStore.amllDbServer || "https://amll-ttml-db.stevexmh.net/ncm/%s";
82+
const url = server.replace("%s", String(id));
8383
try {
8484
const response = await fetch(url);
8585
if (response === null || response.status !== 200) {

src/assets/data/lyricConfig.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const config: LyricConfig = {
1414
position: "both",
1515
limitBounds: false,
1616
textBackgroundMask: false,
17+
alwaysShowPlayInfo: false,
1718
};
1819

1920
export default config;

src/components/Setting/LyricsSetting.vue

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@
444444
/>
445445
</n-flex>
446446
</n-card>
447-
<!-- <n-card class="set-item">
447+
<n-card class="set-item">
448448
<div class="label">
449449
<n-text class="name">显示逐字歌词</n-text>
450450
<n-text class="tip" :depth="3">是否显示桌面歌词逐字效果</n-text>
@@ -455,7 +455,7 @@
455455
class="set"
456456
@update:value="saveDesktopLyricConfig"
457457
/>
458-
</n-card> -->
458+
</n-card>
459459
<n-card class="set-item">
460460
<div class="label">
461461
<n-text class="name">显示翻译</n-text>
@@ -549,6 +549,18 @@
549549
@update:value="saveDesktopLyricConfig"
550550
/>
551551
</n-card>
552+
<n-card class="set-item">
553+
<div class="label">
554+
<n-text class="name">始终展示播放信息</n-text>
555+
<n-text class="tip" :depth="3">是否始终展示当前歌曲名及歌手</n-text>
556+
</div>
557+
<n-switch
558+
v-model:value="desktopLyricConfig.alwaysShowPlayInfo"
559+
:round="false"
560+
class="set"
561+
@update:value="saveDesktopLyricConfig"
562+
/>
563+
</n-card>
552564
<n-card class="set-item">
553565
<div class="label">
554566
<n-text class="name">恢复默认配置</n-text>
@@ -580,7 +592,7 @@ const settingStore = useSettingStore();
580592
const allFontsData = ref<SelectOption[]>([]);
581593
582594
// AMLL TTML DB 地址
583-
const amllDbServer = ref("https://amll-ttml-db.stevexmh.net");
595+
const amllDbServer = ref("https://amll-ttml-db.stevexmh.net/ncm/%s");
584596
585597
// 桌面歌词配置
586598
const desktopLyricConfig = reactive<LyricConfig>({ ...defaultDesktopLyricConfig });
@@ -681,26 +693,27 @@ const changeAMLLDBServer = () => {
681693
{ depth: 3, type: "warning" },
682694
{ default: () => "如果你不清楚这里是做什么的,请不要修改" },
683695
),
696+
h(NText, null, { default: () => "请确保地址正确,并且包含 %s( 用于替换歌曲 ID )" }),
684697
h(NInput, {
685698
value: amllDbServer.value,
686699
onUpdateValue: (val) => (amllDbServer.value = val),
687700
placeholder: "请输入 AMLL TTML DB 地址",
688701
}),
689-
h(NText, { depth: 3 }, { default: () => "请确保地址正确,否则将导致歌词获取失败" }),
690702
],
691703
},
692704
),
693705
positiveText: "确认",
694706
negativeText: "取消",
695707
onPositiveClick: async () => {
696708
const urlValue = amllDbServer.value.trim();
697-
if (isValidURL(urlValue)) {
709+
// 验证 URL 格式和 %s
710+
if (isValidURL(urlValue) && urlValue.includes("%s")) {
698711
await window.api.store.set("amllDbServer", urlValue);
699712
settingStore.amllDbServer = urlValue;
700713
window.$message.success("AMLL TTML DB 地址已更新");
701714
return true;
702715
} else {
703-
window.$message.error("请输入正确的网址格式");
716+
window.$message.error("请输入正确的网址格式,需包含 %s");
704717
return false;
705718
}
706719
},

src/components/Setting/PlaySetting.vue

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@
1616
:disabled="!isElectron"
1717
/>
1818
</n-card>
19+
<n-card class="set-item">
20+
<div class="label">
21+
<n-text class="name">下一首歌曲预载</n-text>
22+
<n-text class="tip" :depth="3">提前预加载下一首歌曲的播放地址,提升切换速度</n-text>
23+
</div>
24+
<n-switch v-model:value="settingStore.useNextPrefetch" class="set" :round="false" />
25+
</n-card>
1926
<n-card class="set-item">
2027
<div class="label">
2128
<n-text class="name">记忆上次播放位置</n-text>

src/stores/setting.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ export interface SettingState {
100100
playDevice: "default" | string;
101101
/** 自动播放 */
102102
autoPlay: boolean;
103+
/** 预载下一首 */
104+
useNextPrefetch: boolean;
103105
/** 渐入渐出 */
104106
songVolumeFade: boolean;
105107
/** 渐入渐出时间 */
@@ -254,6 +256,7 @@ export const useSettingStore = defineStore("setting", {
254256
songLevel: "exhigh",
255257
playDevice: "default",
256258
autoPlay: false,
259+
useNextPrefetch: true,
257260
songVolumeFade: true,
258261
songVolumeFadeTime: 300,
259262
useSongUnlock: true,
@@ -282,7 +285,7 @@ export const useSettingStore = defineStore("setting", {
282285
useAMLyrics: false,
283286
useAMSpring: false,
284287
enableTTMLLyric: true,
285-
amllDbServer: "https://amll-ttml-db.stevexmh.net",
288+
amllDbServer: "https://amll-ttml-db.stevexmh.net/ncm/%s",
286289
showYrc: true,
287290
showYrcAnimation: true,
288291
showYrcLongEffect: true,

src/types/desktop-lyric.d.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ import { type LyricLine } from "@applemusic-like-lyrics/lyric";
22

33
/** 桌面歌词数据 */
44
export interface LyricData {
5-
/** 播放歌曲名称 */
5+
/** 歌曲名称 */
66
playName?: string;
7+
/** 歌手名称 */
8+
artistName?: string;
79
/** 播放状态 */
810
playStatus?: boolean;
911
/** 当前播放进度 */
@@ -49,6 +51,8 @@ export interface LyricConfig {
4951
limitBounds: boolean;
5052
/** 文本背景遮罩 */
5153
textBackgroundMask: boolean;
54+
/** 始终展示播放信息 */
55+
alwaysShowPlayInfo: boolean;
5256
}
5357

5458
/**

0 commit comments

Comments
 (0)