feat: 新增副歌时间展示

This commit is contained in:
imsyy
2024-12-10 17:45:12 +08:00
parent fbf261f80b
commit 3b07f7346f
7 changed files with 73 additions and 16 deletions

14
electron/server/port.ts Normal file
View File

@@ -0,0 +1,14 @@
import getPort from "get-port";
// 默认端口
let webPort: number;
let servePort: number;
const getSafePort = async () => {
if (webPort && servePort) return { webPort, servePort };
webPort = await getPort({ port: 14558 });
servePort = await getPort({ port: 25884 });
return { webPort, servePort };
};
export default getSafePort;

View File

@@ -57,6 +57,7 @@
"electron-updater": "^6.3.9",
"file-saver": "^2.0.5",
"font-list": "^1.5.1",
"get-port": "^7.1.0",
"github-markdown-css": "^5.8.1",
"howler": "^2.2.4",
"js-cookie": "^3.0.5",
@@ -101,6 +102,7 @@
"prettier": "^3.4.1",
"sass": "^1.81.0",
"terser": "^5.36.0",
"typescript": "5.6.2",
"unplugin-auto-import": "^0.18.6",
"unplugin-vue-components": "^0.27.5",
"vite": "^5.4.11",
@@ -108,7 +110,6 @@
"vite-plugin-wasm": "^3.3.0",
"vue": "^3.5.13",
"vue-router": "^4.5.0",
"typescript": "5.6.2",
"vue-tsc": "2.0.29"
},
"pnpm": {

9
pnpm-lock.yaml generated
View File

@@ -84,6 +84,9 @@ importers:
font-list:
specifier: ^1.5.1
version: 1.5.1
get-port:
specifier: ^7.1.0
version: 7.1.0
github-markdown-css:
specifier: ^5.8.1
version: 5.8.1
@@ -2337,6 +2340,10 @@ packages:
resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==}
engines: {node: '>= 0.4'}
get-port@7.1.0:
resolution: {integrity: sha512-QB9NKEeDg3xxVwCCwJQ9+xycaz6pBB6iQ76wiWMl1927n0Kir6alPiP+yuiICLLU4jpMe08dXfpebuQppFA2zw==}
engines: {node: '>=16'}
get-stream@4.1.0:
resolution: {integrity: sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==}
engines: {node: '>=6'}
@@ -6478,6 +6485,8 @@ snapshots:
has-symbols: 1.0.3
hasown: 2.0.2
get-port@7.1.0: {}
get-stream@4.1.0:
dependencies:
pump: 3.0.2

View File

@@ -114,10 +114,20 @@ export const matchSong = (
* 歌曲动态封面
* @param {number} id - 歌曲 id
*/
export const songDynamicCover = (id: number) => {
return request({
url: "/song/dynamic/cover",
params: { id },
});
};
/**
* 副歌时间
* @param {number} id - 歌曲 id
*/
export const songChorus = (id: number) => {
return request({
url: "/song/chorus",
params: { id },
});
};

View File

@@ -15,6 +15,11 @@
:max="100"
:tooltip="false"
:keyboard="false"
:marks="
statusStore.chorus && statusStore.progress <= statusStore.chorus
? { [statusStore.chorus]: '' }
: undefined
"
class="player-slider"
@dragstart="player.pause(false)"
@dragend="sliderDragend"
@@ -380,6 +385,7 @@ const changeVolume = (e: WheelEvent) => {
height: 16px;
top: -8px;
left: 0;
margin: 0;
--n-rail-height: 3px;
--n-handle-size: 14px;
}

View File

@@ -29,6 +29,7 @@ interface StatusState {
lyricIndex: number;
currentTime: number;
duration: number;
chorus: number;
progress: number;
currentTimeOffset: number;
playUblock: boolean;
@@ -65,6 +66,8 @@ export const useStatusStore = defineStore({
currentTime: 0,
duration: 0,
progress: 0,
// 副歌时间
chorus: 0,
// 进度偏移
currentTimeOffset: 0,
// 封面主题

View File

@@ -4,7 +4,7 @@ import { Howl, Howler } from "howler";
import { cloneDeep } from "lodash-es";
import { useMusicStore, useStatusStore, useDataStore, useSettingStore } from "@/stores";
import { parsedLyricsData, resetSongLyric, parseLocalLyric } from "./lyric";
import { songUrl, unlockSongUrl, songLyric } from "@/api/song";
import { songUrl, unlockSongUrl, songLyric, songChorus } from "@/api/song";
import { getCoverColorData } from "@/utils/color";
import { calculateProgress } from "./time";
import { isElectron, isDev } from "./helper";
@@ -52,6 +52,7 @@ class Player {
currentTime: 0,
duration: 0,
progress: 0,
chorus: 0,
currentTimeOffset: 0,
lyricIndex: -1,
playStatus: false,
@@ -113,12 +114,7 @@ class Player {
// 歌词跨界处理
const lyricIndex = index === -1 ? lyrics.length - 1 : index - 1;
// 更新状态
statusStore.$patch({
currentTime,
duration,
progress,
lyricIndex,
});
statusStore.$patch({ currentTime, duration, progress, lyricIndex });
// 客户端事件
if (isElectron) {
// 歌词变化
@@ -217,9 +213,11 @@ class Player {
if (!settingStore.showSpectrums) this.toggleOutputDevice();
// 自动播放
if (autoPlay) this.play();
// 获取歌词数据 - 非电台和本地
if (type !== "radio" && !path) this.getLyricData(id);
else resetSongLyric();
// 获取歌曲附加信息 - 非电台和本地
if (type !== "radio" && !path) {
this.getLyricData(id);
this.getChorus(id);
} else resetSongLyric();
// 定时获取状态
if (!this.playerInterval) this.handlePlayStatus();
// 新增播放历史
@@ -402,6 +400,22 @@ class Player {
const lyricRes = await songLyric(id);
parsedLyricsData(lyricRes);
}
/**
* 获取副歌时间
* @param id 歌曲id
*/
private async getChorus(id: number) {
const statusStore = useStatusStore();
const result = await songChorus(id);
if (result?.code !== 200 || result?.chorus?.length === 0) {
statusStore.chorus = 0;
return;
}
// 计算并保存
const chorus = result?.chorus?.[0]?.startTime;
const time = ((chorus / 1000 / statusStore.duration) * 100).toFixed(2);
statusStore.chorus = Number(time);
}
/**
* 播放错误
* 在播放错误时,播放下一首
@@ -590,8 +604,8 @@ class Player {
const statusStore = useStatusStore();
// 播放器未加载完成
if (this.player.state() !== "loaded"){
return
if (this.player.state() !== "loaded") {
return;
}
// 淡出
@@ -880,7 +894,7 @@ class Player {
const songIndex = await dataStore.setNextPlaySong(song, statusStore.playIndex);
// 播放歌曲
if (songIndex < 0) return;
if (play) this.togglePlayIndex(songIndex,true);
if (play) this.togglePlayIndex(songIndex, true);
else window.$message.success("已添加至下一首播放");
}
/**
@@ -888,7 +902,7 @@ class Player {
* @param index 播放索引
* @param play 是否立即播放
*/
async togglePlayIndex(index: number,play:boolean = false) {
async togglePlayIndex(index: number, play: boolean = false) {
const dataStore = useDataStore();
const statusStore = useStatusStore();
// 获取数据