mirror of
https://github.com/imsyy/SPlayer.git
synced 2025-11-25 03:14:57 +08:00
@@ -1,9 +1,18 @@
|
|||||||
|
# 根配置文件
|
||||||
|
## 编辑器在查找配置时会停止查找更高层次的配置文件
|
||||||
root = true
|
root = true
|
||||||
|
|
||||||
|
# 通配符,匹配所有文件
|
||||||
[*]
|
[*]
|
||||||
|
# 设置字符集为 UTF-8,确保文件中的文本使用 UTF-8 编码
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
|
# 使用空格作为缩进风格
|
||||||
indent_style = space
|
indent_style = space
|
||||||
|
# 设置每个缩进级别的空格数量为 2
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
# 设置行尾换行符为LF(Line Feed)
|
||||||
end_of_line = lf
|
end_of_line = lf
|
||||||
|
# 在文件的末尾插入一个新行
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
trim_trailing_whitespace = true
|
# 删除每一行末尾的尾随空格
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|||||||
@@ -229,7 +229,6 @@ docker run -d --name SPlayer -p 7899:7899 imsyy/splayer:latest
|
|||||||
- [NeteaseCloudMusicApi](https://github.com/Binaryify/NeteaseCloudMusicApi)
|
- [NeteaseCloudMusicApi](https://github.com/Binaryify/NeteaseCloudMusicApi)
|
||||||
- [YesPlayMusic](https://github.com/qier222/YesPlayMusic)
|
- [YesPlayMusic](https://github.com/qier222/YesPlayMusic)
|
||||||
- [UnblockNeteaseMusic](https://github.com/UnblockNeteaseMusic/server)
|
- [UnblockNeteaseMusic](https://github.com/UnblockNeteaseMusic/server)
|
||||||
- [BlurLyric](https://github.com/Project-And-Factory/BlurLyric)
|
|
||||||
- [Vue-mmPlayer](https://github.com/maomao1996/Vue-mmPlayer)
|
- [Vue-mmPlayer](https://github.com/maomao1996/Vue-mmPlayer)
|
||||||
|
|
||||||
## 📢 免责声明
|
## 📢 免责声明
|
||||||
|
|||||||
1
components.d.ts
vendored
1
components.d.ts
vendored
@@ -77,7 +77,6 @@ declare module 'vue' {
|
|||||||
NSelect: typeof import('naive-ui')['NSelect']
|
NSelect: typeof import('naive-ui')['NSelect']
|
||||||
NSkeleton: typeof import('naive-ui')['NSkeleton']
|
NSkeleton: typeof import('naive-ui')['NSkeleton']
|
||||||
NSlider: typeof import('naive-ui')['NSlider']
|
NSlider: typeof import('naive-ui')['NSlider']
|
||||||
NSpace: typeof import('naive-ui')['NSpace']
|
|
||||||
NSpin: typeof import('naive-ui')['NSpin']
|
NSpin: typeof import('naive-ui')['NSpin']
|
||||||
NSwitch: typeof import('naive-ui')['NSwitch']
|
NSwitch: typeof import('naive-ui')['NSwitch']
|
||||||
NTab: typeof import('naive-ui')['NTab']
|
NTab: typeof import('naive-ui')['NTab']
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { ipcMain, dialog, app, clipboard, shell } from "electron";
|
import { ipcMain, dialog, app, clipboard, shell } from "electron";
|
||||||
import { readDirAsync } from "@main/utils/readDirAsync";
|
import { readDirAsync } from "@main/utils/readDirAsync";
|
||||||
import { parseFile } from "music-metadata";
|
import { parseFile } from "music-metadata";
|
||||||
import { write } from "node-id3";
|
|
||||||
import { download } from "electron-dl";
|
import { download } from "electron-dl";
|
||||||
import getNeteaseMusicUrl from "@main/utils/getNeteaseMusicUrl";
|
import getNeteaseMusicUrl from "@main/utils/getNeteaseMusicUrl";
|
||||||
|
import NodeID3 from "node-id3";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import fs from "fs/promises";
|
import fs from "fs/promises";
|
||||||
|
|
||||||
@@ -203,6 +203,8 @@ const mainIpcMain = (win) => {
|
|||||||
directory: path,
|
directory: path,
|
||||||
filename: `${songName}.${songType}`,
|
filename: `${songName}.${songType}`,
|
||||||
});
|
});
|
||||||
|
// 若不为 mp3,则不进行元信息写入
|
||||||
|
if (songType !== "mp3") return true;
|
||||||
// 下载封面
|
// 下载封面
|
||||||
const coverDownload = await download(win, songData.cover, {
|
const coverDownload = await download(win, songData.cover, {
|
||||||
directory: path,
|
directory: path,
|
||||||
@@ -218,10 +220,10 @@ const mainIpcMain = (win) => {
|
|||||||
image: coverDownload.getSavePath(),
|
image: coverDownload.getSavePath(),
|
||||||
};
|
};
|
||||||
// 保存修改后的元数据
|
// 保存修改后的元数据
|
||||||
write(songTag, songDownload.getSavePath());
|
const isSuccess = NodeID3.write(songTag, songDownload.getSavePath());
|
||||||
// 删除封面
|
// 删除封面
|
||||||
await fs.unlink(coverDownload.getSavePath());
|
await fs.unlink(coverDownload.getSavePath());
|
||||||
return true;
|
return isSuccess;
|
||||||
} else {
|
} else {
|
||||||
console.log(`目录不存在:${path}`);
|
console.log(`目录不存在:${path}`);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { dialog, shell } from "electron";
|
import { dialog, shell } from "electron";
|
||||||
import { is } from "@electron-toolkit/utils";
|
import { is } from "@electron-toolkit/utils";
|
||||||
import { autoUpdater } from "electron-updater";
|
import pkg from "electron-updater";
|
||||||
|
|
||||||
|
const { autoUpdater } = pkg;
|
||||||
|
|
||||||
// 更新弹窗
|
// 更新弹窗
|
||||||
const hasNewVersion = (info) => {
|
const hasNewVersion = (info) => {
|
||||||
|
|||||||
29
package.json
29
package.json
@@ -8,9 +8,10 @@
|
|||||||
"github": "https://github.com/imsyy/SPlayer",
|
"github": "https://github.com/imsyy/SPlayer",
|
||||||
"repository": "github:imsyy/SPlayer",
|
"repository": "github:imsyy/SPlayer",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.16.0"
|
"node": ">=18.16.0",
|
||||||
|
"npm": ">=9.6.7",
|
||||||
|
"pnpm": ">=8.14.0"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@8.12.0",
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"format": "prettier --write .",
|
"format": "prettier --write .",
|
||||||
"lint": "eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts,.vue --fix",
|
"lint": "eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts,.vue --fix",
|
||||||
@@ -23,8 +24,8 @@
|
|||||||
"build:linux": "npm run build && electron-builder --linux --config"
|
"build:linux": "npm run build && electron-builder --linux --config"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@electron-toolkit/preload": "^2.0.0",
|
"@electron-toolkit/preload": "^3.0.0",
|
||||||
"@electron-toolkit/utils": "^2.0.1",
|
"@electron-toolkit/utils": "^3.0.0",
|
||||||
"@material/material-color-utilities": "^0.2.7",
|
"@material/material-color-utilities": "^0.2.7",
|
||||||
"NeteaseCloudMusicApi": "^4.14.0",
|
"NeteaseCloudMusicApi": "^4.14.0",
|
||||||
"axios": "^1.6.5",
|
"axios": "^1.6.5",
|
||||||
@@ -33,11 +34,11 @@
|
|||||||
"electron-store": "^8.1.0",
|
"electron-store": "^8.1.0",
|
||||||
"electron-updater": "^6.1.7",
|
"electron-updater": "^6.1.7",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"express-http-proxy": "^1.6.3",
|
"express-http-proxy": "^2.0.0",
|
||||||
"howler": "^2.2.4",
|
"howler": "^2.2.4",
|
||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
"localforage": "^1.10.0",
|
"localforage": "^1.10.0",
|
||||||
"music-metadata": "7.13.4",
|
"music-metadata": "7.14.0",
|
||||||
"node-id3": "^0.2.6",
|
"node-id3": "^0.2.6",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
"pinia-plugin-persistedstate": "^3.2.1",
|
"pinia-plugin-persistedstate": "^3.2.1",
|
||||||
@@ -49,22 +50,22 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@electron-toolkit/eslint-config": "^1.0.2",
|
"@electron-toolkit/eslint-config": "^1.0.2",
|
||||||
"@rushstack/eslint-patch": "^1.6.1",
|
"@rushstack/eslint-patch": "^1.6.1",
|
||||||
"@vitejs/plugin-vue": "^4.6.2",
|
"@vitejs/plugin-vue": "^5.0.2",
|
||||||
"@vue/eslint-config-prettier": "^8.0.0",
|
"@vue/eslint-config-prettier": "^9.0.0",
|
||||||
"ajv": "^8.12.0",
|
"ajv": "^8.12.0",
|
||||||
"electron": "^27.2.1",
|
"electron": "^28.1.2",
|
||||||
"electron-builder": "^24.9.1",
|
"electron-builder": "^24.9.1",
|
||||||
"electron-log": "^5.0.3",
|
"electron-log": "^5.0.3",
|
||||||
"electron-vite": "^1.0.29",
|
"electron-vite": "^2.0.0",
|
||||||
"eslint": "^8.56.0",
|
"eslint": "^8.56.0",
|
||||||
"eslint-plugin-vue": "^9.19.2",
|
"eslint-plugin-vue": "^9.19.2",
|
||||||
"naive-ui": "^2.37.0",
|
"naive-ui": "^2.37.3",
|
||||||
"prettier": "^3.1.1",
|
"prettier": "^3.1.1",
|
||||||
"sass": "^1.69.7",
|
"sass": "^1.69.7",
|
||||||
"terser": "^5.26.0",
|
"terser": "^5.26.0",
|
||||||
"unplugin-auto-import": "^0.16.7",
|
"unplugin-auto-import": "^0.17.3",
|
||||||
"unplugin-vue-components": "^0.25.2",
|
"unplugin-vue-components": "^0.26.0",
|
||||||
"vite": "^4.5.1",
|
"vite": "^5.0.11",
|
||||||
"vite-plugin-compression": "^0.5.1",
|
"vite-plugin-compression": "^0.5.1",
|
||||||
"vite-plugin-pwa": "^0.17.4",
|
"vite-plugin-pwa": "^0.17.4",
|
||||||
"vue": "3.4.4"
|
"vue": "3.4.4"
|
||||||
|
|||||||
492
pnpm-lock.yaml
generated
492
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -90,5 +90,6 @@
|
|||||||
"password": "M2 17h20v2H2v-2zm1.15-4.05L4 11.47l.85 1.48l1.3-.75l-.85-1.48H7v-1.5H5.3l.85-1.47L4.85 7L4 8.47L3.15 7l-1.3.75l.85 1.47H1v1.5h1.7l-.85 1.48l1.3.75zm6.7-.75l1.3.75l.85-1.48l.85 1.48l1.3-.75l-.85-1.48H15v-1.5h-1.7l.85-1.47l-1.3-.75L12 8.47L11.15 7l-1.3.75l.85 1.47H9v1.5h1.7l-.85 1.48zM23 9.22h-1.7l.85-1.47l-1.3-.75L20 8.47L19.15 7l-1.3.75l.85 1.47H17v1.5h1.7l-.85 1.48l1.3.75l.85-1.48l.85 1.48l1.3-.75l-.85-1.48H23v-1.5z",
|
"password": "M2 17h20v2H2v-2zm1.15-4.05L4 11.47l.85 1.48l1.3-.75l-.85-1.48H7v-1.5H5.3l.85-1.47L4.85 7L4 8.47L3.15 7l-1.3.75l.85 1.47H1v1.5h1.7l-.85 1.48l1.3.75zm6.7-.75l1.3.75l.85-1.48l.85 1.48l1.3-.75l-.85-1.48H15v-1.5h-1.7l.85-1.47l-1.3-.75L12 8.47L11.15 7l-1.3.75l.85 1.47H9v1.5h1.7l-.85 1.48zM23 9.22h-1.7l.85-1.47l-1.3-.75L20 8.47L19.15 7l-1.3.75l.85 1.47H17v1.5h1.7l-.85 1.48l1.3.75l.85-1.48l.85 1.48l1.3-.75l-.85-1.48H23v-1.5z",
|
||||||
"star": "m12 17.27l4.15 2.51c.76.46 1.69-.22 1.49-1.08l-1.1-4.72l3.67-3.18c.67-.58.31-1.68-.57-1.75l-4.83-.41l-1.89-4.46c-.34-.81-1.5-.81-1.84 0L9.19 8.63l-4.83.41c-.88.07-1.24 1.17-.57 1.75l3.67 3.18l-1.1 4.72c-.2.86.73 1.54 1.49 1.08l4.15-2.5z",
|
"star": "m12 17.27l4.15 2.51c.76.46 1.69-.22 1.49-1.08l-1.1-4.72l3.67-3.18c.67-.58.31-1.68-.57-1.75l-4.83-.41l-1.89-4.46c-.34-.81-1.5-.81-1.84 0L9.19 8.63l-4.83.41c-.88.07-1.24 1.17-.57 1.75l3.67 3.18l-1.1 4.72c-.2.86.73 1.54 1.49 1.08l4.15-2.5z",
|
||||||
"record": "M17 18.25v3.25H7v-3.25c0-1.38 2.24-2.5 5-2.5s5 1.12 5 2.5M12 5.5a6.5 6.5 0 0 1 6.5 6.5c0 1.25-.35 2.42-.96 3.41L16 14.04c.32-.61.5-1.31.5-2.04c0-2.5-2-4.5-4.5-4.5s-4.5 2-4.5 4.5c0 .73.18 1.43.5 2.04l-1.54 1.37c-.61-.99-.96-2.16-.96-3.41A6.5 6.5 0 0 1 12 5.5m0-4A10.5 10.5 0 0 1 22.5 12c0 2.28-.73 4.39-1.96 6.11l-1.5-1.35c.92-1.36 1.46-3 1.46-4.76A8.5 8.5 0 0 0 12 3.5A8.5 8.5 0 0 0 3.5 12c0 1.76.54 3.4 1.46 4.76l-1.5 1.35A10.473 10.473 0 0 1 1.5 12A10.5 10.5 0 0 1 12 1.5m0 8a2.5 2.5 0 0 1 2.5 2.5a2.5 2.5 0 0 1-2.5 2.5A2.5 2.5 0 0 1 9.5 12A2.5 2.5 0 0 1 12 9.5Z",
|
"record": "M17 18.25v3.25H7v-3.25c0-1.38 2.24-2.5 5-2.5s5 1.12 5 2.5M12 5.5a6.5 6.5 0 0 1 6.5 6.5c0 1.25-.35 2.42-.96 3.41L16 14.04c.32-.61.5-1.31.5-2.04c0-2.5-2-4.5-4.5-4.5s-4.5 2-4.5 4.5c0 .73.18 1.43.5 2.04l-1.54 1.37c-.61-.99-.96-2.16-.96-3.41A6.5 6.5 0 0 1 12 5.5m0-4A10.5 10.5 0 0 1 22.5 12c0 2.28-.73 4.39-1.96 6.11l-1.5-1.35c.92-1.36 1.46-3 1.46-4.76A8.5 8.5 0 0 0 12 3.5A8.5 8.5 0 0 0 3.5 12c0 1.76.54 3.4 1.46 4.76l-1.5 1.35A10.473 10.473 0 0 1 1.5 12A10.5 10.5 0 0 1 12 1.5m0 8a2.5 2.5 0 0 1 2.5 2.5a2.5 2.5 0 0 1-2.5 2.5A2.5 2.5 0 0 1 9.5 12A2.5 2.5 0 0 1 12 9.5Z",
|
||||||
"storage": "M4 20h16c1.1 0 2-.9 2-2s-.9-2-2-2H4c-1.1 0-2 .9-2 2s.9 2 2 2m0-3h2v2H4zM2 6c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2s-.9-2-2-2H4c-1.1 0-2 .9-2 2m4 1H4V5h2zm-2 7h16c1.1 0 2-.9 2-2s-.9-2-2-2H4c-1.1 0-2 .9-2 2s.9 2 2 2m0-3h2v2H4z"
|
"storage": "M4 20h16c1.1 0 2-.9 2-2s-.9-2-2-2H4c-1.1 0-2 .9-2 2s.9 2 2 2m0-3h2v2H4zM2 6c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2s-.9-2-2-2H4c-1.1 0-2 .9-2 2m4 1H4V5h2zm-2 7h16c1.1 0 2-.9 2-2s-.9-2-2-2H4c-1.1 0-2 .9-2 2s.9 2 2 2m0-3h2v2H4z",
|
||||||
|
"lrc-text": "M13.8 22H5c-1.7 0-3-1.3-3-3v-1h11.1c-.1.3-.1.7-.1 1c0 1.1.3 2.1.8 3m0-6H5V5c0-1.7 1.3-3 3-3h11c1.7 0 3 1.3 3 3v1h-2V5c0-.6-.4-1-1-1s-1 .4-1 1v8.1c-1.8.3-3.3 1.4-4.2 2.9M8 8h7V6H8zm0 4h6v-2H8zm9 4v6l5-3z"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,9 +49,14 @@
|
|||||||
<div v-show="playerControlShow" class="menu">
|
<div v-show="playerControlShow" class="menu">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<!-- 歌词模式 -->
|
<!-- 歌词模式 -->
|
||||||
<div v-if="isHasLrc" class="n-icon" @click="pureLyricMode = !pureLyricMode">
|
<n-icon
|
||||||
<n-text>词</n-text>
|
v-if="isHasLrc"
|
||||||
</div>
|
:class="['lrc-open', { open: pureLyricMode }]"
|
||||||
|
size="28"
|
||||||
|
@click="pureLyricMode = !pureLyricMode"
|
||||||
|
>
|
||||||
|
<SvgIcon icon="lrc-text" />
|
||||||
|
</n-icon>
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<!-- 全屏切换 -->
|
<!-- 全屏切换 -->
|
||||||
@@ -406,17 +411,6 @@ onUnmounted(() => {
|
|||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
.left {
|
|
||||||
justify-content: flex-start;
|
|
||||||
.n-icon {
|
|
||||||
margin-left: 0;
|
|
||||||
margin-right: 12px;
|
|
||||||
.n-text {
|
|
||||||
font-size: 26px;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.n-icon {
|
.n-icon {
|
||||||
margin-left: 12px;
|
margin-left: 12px;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
@@ -441,6 +435,17 @@ onUnmounted(() => {
|
|||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.left {
|
||||||
|
justify-content: flex-start;
|
||||||
|
.n-icon {
|
||||||
|
margin-left: 0;
|
||||||
|
&.lrc-open {
|
||||||
|
&.open {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.main-player {
|
.main-player {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -779,6 +779,41 @@ const getPlaySongName = () => {
|
|||||||
return songName + " - " + songArtist;
|
return songName + " - " + songArtist;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const playAllSongs = async (playlist, mode = "normal") => {
|
||||||
|
try {
|
||||||
|
// pinia
|
||||||
|
const music = musicData();
|
||||||
|
const status = siteStatus();
|
||||||
|
if (!playlist) return false;
|
||||||
|
// 关闭心动模式
|
||||||
|
status.playHeartbeatMode = false;
|
||||||
|
// 更改模式和歌单
|
||||||
|
status.playMode = mode;
|
||||||
|
music.playList = playlist.slice();
|
||||||
|
// 是否处于歌单内
|
||||||
|
const songId = music.getPlaySongData?.id;
|
||||||
|
const existingIndex = playlist.findIndex((song) => song.id === songId);
|
||||||
|
// 若不处于
|
||||||
|
if (existingIndex === -1 || !songId) {
|
||||||
|
console.log("不在歌单内");
|
||||||
|
music.playSongData = playlist[0];
|
||||||
|
status.playIndex = 0;
|
||||||
|
// 初始化播放器
|
||||||
|
await initPlayer(true);
|
||||||
|
} else {
|
||||||
|
console.log("处于歌单内");
|
||||||
|
music.playSongData = playlist[existingIndex];
|
||||||
|
status.playIndex = existingIndex;
|
||||||
|
// 播放
|
||||||
|
fadePlayOrPause();
|
||||||
|
}
|
||||||
|
$message.info("已开始播放", { showIcon: false });
|
||||||
|
} catch (error) {
|
||||||
|
console.error("播放全部歌曲出错:", error);
|
||||||
|
$message.error("播放全部歌曲出现错误");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 清除定时器
|
* 清除定时器
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -17,7 +17,17 @@
|
|||||||
<!-- 功能区 -->
|
<!-- 功能区 -->
|
||||||
<n-flex class="menu" justify="space-between">
|
<n-flex class="menu" justify="space-between">
|
||||||
<n-flex class="left">
|
<n-flex class="left">
|
||||||
<n-button type="primary" class="play" circle strong secondary @click="playAllSongs">
|
<n-button
|
||||||
|
:disabled="userCloudData?.length === 0"
|
||||||
|
:focusable="false"
|
||||||
|
type="primary"
|
||||||
|
class="play"
|
||||||
|
tag="div"
|
||||||
|
circle
|
||||||
|
strong
|
||||||
|
secondary
|
||||||
|
@click="playAllSongs(userCloudData)"
|
||||||
|
>
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<n-icon size="32">
|
<n-icon size="32">
|
||||||
<SvgIcon icon="play-arrow-rounded" />
|
<SvgIcon icon="play-arrow-rounded" />
|
||||||
@@ -82,19 +92,14 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { storeToRefs } from "pinia";
|
import { indexedDBData } from "@/stores";
|
||||||
import { musicData, siteStatus, indexedDBData } from "@/stores";
|
|
||||||
import { getUserCloud } from "@/api/cloud";
|
import { getUserCloud } from "@/api/cloud";
|
||||||
import { fuzzySearch } from "@/utils/helper";
|
import { fuzzySearch } from "@/utils/helper";
|
||||||
import { fadePlayOrPause, initPlayer } from "@/utils/Player";
|
import { playAllSongs } from "@/utils/Player";
|
||||||
import debounce from "@/utils/debounce";
|
import debounce from "@/utils/debounce";
|
||||||
import formatData from "@/utils/formatData";
|
import formatData from "@/utils/formatData";
|
||||||
|
|
||||||
const music = musicData();
|
|
||||||
const status = siteStatus();
|
|
||||||
const indexedDB = indexedDBData();
|
const indexedDB = indexedDBData();
|
||||||
const { playList, playSongData } = storeToRefs(music);
|
|
||||||
const { playIndex, playMode, playHeartbeatMode } = storeToRefs(status);
|
|
||||||
|
|
||||||
// 云盘数据
|
// 云盘数据
|
||||||
const userCloudSpace = ref([]);
|
const userCloudSpace = ref([]);
|
||||||
@@ -160,31 +165,6 @@ const localSearch = debounce((val) => {
|
|||||||
searchData.value = result;
|
searchData.value = result;
|
||||||
}, 300);
|
}, 300);
|
||||||
|
|
||||||
// 播放歌单全部歌曲
|
|
||||||
const playAllSongs = async () => {
|
|
||||||
if (!userCloudData.value || !Object.keys(userCloudData.value).length) return false;
|
|
||||||
// 关闭心动模式
|
|
||||||
playHeartbeatMode.value = false;
|
|
||||||
// 更改模式和歌单
|
|
||||||
playMode.value = "normal";
|
|
||||||
playList.value = userCloudData.value.slice();
|
|
||||||
// 是否处于歌单内
|
|
||||||
const songId = playSongData.value?.id;
|
|
||||||
const existingIndex = userCloudData.value.findIndex((song) => song.id === songId);
|
|
||||||
// 若不处于
|
|
||||||
if (existingIndex === -1 || !songId) {
|
|
||||||
playSongData.value = userCloudData.value[0];
|
|
||||||
playIndex.value = 0;
|
|
||||||
// 初始化播放器
|
|
||||||
await initPlayer(true);
|
|
||||||
} else {
|
|
||||||
playSongData.value = userCloudData.value[existingIndex];
|
|
||||||
playIndex.value = existingIndex;
|
|
||||||
fadePlayOrPause();
|
|
||||||
}
|
|
||||||
$message.info("已开始播放", { showIcon: false });
|
|
||||||
};
|
|
||||||
|
|
||||||
// 云盘扩容
|
// 云盘扩容
|
||||||
const goBuy = () => {
|
const goBuy = () => {
|
||||||
window.open("https://music.163.com/#/store/product/detail?id=34001");
|
window.open("https://music.163.com/#/store/product/detail?id=34001");
|
||||||
|
|||||||
@@ -13,7 +13,16 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- 操作 -->
|
<!-- 操作 -->
|
||||||
<n-flex class="control">
|
<n-flex class="control">
|
||||||
<n-button size="large" tag="div" round strong secondary @click="playAllSongs">
|
<n-button
|
||||||
|
:disabled="dailySongsData.data?.length === 0"
|
||||||
|
:focusable="false"
|
||||||
|
size="large"
|
||||||
|
tag="div"
|
||||||
|
round
|
||||||
|
strong
|
||||||
|
secondary
|
||||||
|
@click="playAllSongs(dailySongsData.data)"
|
||||||
|
>
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<n-icon>
|
<n-icon>
|
||||||
<SvgIcon icon="play-arrow-rounded" />
|
<SvgIcon icon="play-arrow-rounded" />
|
||||||
@@ -40,16 +49,12 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { NIcon } from "naive-ui";
|
import { NIcon } from "naive-ui";
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
import { musicData, siteData, siteStatus } from "@/stores";
|
import { siteData } from "@/stores";
|
||||||
import { fadePlayOrPause, initPlayer } from "@/utils/Player";
|
import { playAllSongs } from "@/utils/Player";
|
||||||
import SvgIcon from "@/components/Global/SvgIcon";
|
import SvgIcon from "@/components/Global/SvgIcon";
|
||||||
|
|
||||||
const data = siteData();
|
const data = siteData();
|
||||||
const music = musicData();
|
|
||||||
const status = siteStatus();
|
|
||||||
const { dailySongsData } = storeToRefs(data);
|
const { dailySongsData } = storeToRefs(data);
|
||||||
const { playList, playSongData } = storeToRefs(music);
|
|
||||||
const { playIndex, playMode, playHeartbeatMode } = storeToRefs(status);
|
|
||||||
|
|
||||||
const showTime = ref(false);
|
const showTime = ref(false);
|
||||||
const showTimeOut = ref(null);
|
const showTimeOut = ref(null);
|
||||||
@@ -85,34 +90,6 @@ const moreOptions = computed(() => [
|
|||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// 播放歌单全部歌曲
|
|
||||||
const playAllSongs = async () => {
|
|
||||||
if (!dailySongsData.value.data) return false;
|
|
||||||
// 关闭心动模式
|
|
||||||
playHeartbeatMode.value = false;
|
|
||||||
// 更改模式和歌单
|
|
||||||
playMode.value = "normal";
|
|
||||||
playList.value = dailySongsData.value.data.slice();
|
|
||||||
// 是否处于歌单内
|
|
||||||
const songId = music.getPlaySongData?.id;
|
|
||||||
const existingIndex = dailySongsData.value.data.findIndex((song) => song.id === songId);
|
|
||||||
// 若不处于
|
|
||||||
if (existingIndex === -1 || !songId) {
|
|
||||||
console.log("不在歌单内");
|
|
||||||
playSongData.value = dailySongsData.value.data[0];
|
|
||||||
playIndex.value = 0;
|
|
||||||
// 初始化播放器
|
|
||||||
await initPlayer(true);
|
|
||||||
} else {
|
|
||||||
console.log("处于歌单内");
|
|
||||||
playSongData.value = dailySongsData.value.data[existingIndex];
|
|
||||||
playIndex.value = existingIndex;
|
|
||||||
// 播放
|
|
||||||
fadePlayOrPause();
|
|
||||||
}
|
|
||||||
$message.info("已开始播放", { showIcon: false });
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
showTimeOut.value = setTimeout(() => {
|
showTimeOut.value = setTimeout(() => {
|
||||||
showTime.value = true;
|
showTime.value = true;
|
||||||
|
|||||||
@@ -105,13 +105,14 @@
|
|||||||
<n-flex class="left">
|
<n-flex class="left">
|
||||||
<n-button
|
<n-button
|
||||||
:disabled="albumData === 'empty'"
|
:disabled="albumData === 'empty'"
|
||||||
|
:focusable="false"
|
||||||
type="primary"
|
type="primary"
|
||||||
class="play"
|
class="play"
|
||||||
tag="div"
|
tag="div"
|
||||||
circle
|
circle
|
||||||
strong
|
strong
|
||||||
secondary
|
secondary
|
||||||
@click="playAllSongs"
|
@click="playAllSongs(albumData)"
|
||||||
>
|
>
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<n-icon size="32">
|
<n-icon size="32">
|
||||||
@@ -120,6 +121,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</n-button>
|
</n-button>
|
||||||
<n-button
|
<n-button
|
||||||
|
:focusable="false"
|
||||||
class="like"
|
class="like"
|
||||||
size="large"
|
size="large"
|
||||||
tag="div"
|
tag="div"
|
||||||
@@ -138,7 +140,7 @@
|
|||||||
{{ isLikeOrDislike(albumId) ? "收藏专辑" : "取消收藏" }}
|
{{ isLikeOrDislike(albumId) ? "收藏专辑" : "取消收藏" }}
|
||||||
</n-button>
|
</n-button>
|
||||||
<n-dropdown :options="moreOptions" trigger="hover" placement="bottom-start">
|
<n-dropdown :options="moreOptions" trigger="hover" placement="bottom-start">
|
||||||
<n-button class="more" size="large" tag="div" circle strong secondary>
|
<n-button :focusable="false" class="more" size="large" tag="div" circle strong secondary>
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<n-icon>
|
<n-icon>
|
||||||
<SvgIcon icon="format-list-bulleted" />
|
<SvgIcon icon="format-list-bulleted" />
|
||||||
@@ -193,7 +195,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-else class="title">
|
<div v-else class="title">
|
||||||
<n-text class="key">参数不完整</n-text>
|
<n-text class="key">参数不完整</n-text>
|
||||||
<n-button class="back" strong secondary @click="router.go(-1)"> 返回上一页 </n-button>
|
<n-button :focusable="false" class="back" strong secondary @click="router.go(-1)">
|
||||||
|
返回上一页
|
||||||
|
</n-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -201,12 +205,12 @@
|
|||||||
import { NIcon } from "naive-ui";
|
import { NIcon } from "naive-ui";
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
import { musicData, siteData, siteStatus } from "@/stores";
|
import { siteData } from "@/stores";
|
||||||
import { getSongDetail } from "@/api/song";
|
import { getSongDetail } from "@/api/song";
|
||||||
import { getAlbumDetail, likeAlbum } from "@/api/album";
|
import { getAlbumDetail, likeAlbum } from "@/api/album";
|
||||||
import { formatNumber, fuzzySearch } from "@/utils/helper";
|
import { formatNumber, fuzzySearch } from "@/utils/helper";
|
||||||
import { getTimestampTime } from "@/utils/timeTools";
|
import { getTimestampTime } from "@/utils/timeTools";
|
||||||
import { fadePlayOrPause, initPlayer } from "@/utils/Player";
|
import { playAllSongs } from "@/utils/Player";
|
||||||
import { isLogin } from "@/utils/auth";
|
import { isLogin } from "@/utils/auth";
|
||||||
import debounce from "@/utils/debounce";
|
import debounce from "@/utils/debounce";
|
||||||
import formatData from "@/utils/formatData";
|
import formatData from "@/utils/formatData";
|
||||||
@@ -214,11 +218,7 @@ import SvgIcon from "@/components/Global/SvgIcon";
|
|||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const data = siteData();
|
const data = siteData();
|
||||||
const music = musicData();
|
|
||||||
const status = siteStatus();
|
|
||||||
const { userLikeData } = storeToRefs(data);
|
const { userLikeData } = storeToRefs(data);
|
||||||
const { playList, playSongData } = storeToRefs(music);
|
|
||||||
const { playIndex, playMode, playHeartbeatMode } = storeToRefs(status);
|
|
||||||
|
|
||||||
// 专辑 ID
|
// 专辑 ID
|
||||||
const albumId = ref(router.currentRoute.value.query.id || null);
|
const albumId = ref(router.currentRoute.value.query.id || null);
|
||||||
@@ -269,34 +269,6 @@ const getAlbumAllData = async (id, justDetail = false) => {
|
|||||||
albumData.value = formatData(songsDetail.songs, "song");
|
albumData.value = formatData(songsDetail.songs, "song");
|
||||||
};
|
};
|
||||||
|
|
||||||
// 播放专辑全部歌曲
|
|
||||||
const playAllSongs = async () => {
|
|
||||||
if (!albumData.value) return false;
|
|
||||||
// 关闭心动模式
|
|
||||||
playHeartbeatMode.value = false;
|
|
||||||
// 更改模式和歌单
|
|
||||||
playMode.value = "normal";
|
|
||||||
playList.value = albumData.value.slice();
|
|
||||||
// 是否处于专辑内
|
|
||||||
const songId = playSongData.value?.id;
|
|
||||||
const existingIndex = albumData.value.findIndex((song) => song.id === songId);
|
|
||||||
// 若不处于
|
|
||||||
if (existingIndex === -1 || !songId) {
|
|
||||||
console.log("不在专辑内");
|
|
||||||
playSongData.value = albumData.value[0];
|
|
||||||
playIndex.value = 0;
|
|
||||||
// 初始化播放器
|
|
||||||
await initPlayer(true);
|
|
||||||
} else {
|
|
||||||
console.log("处于专辑内");
|
|
||||||
playSongData.value = albumData.value[existingIndex];
|
|
||||||
playIndex.value = existingIndex;
|
|
||||||
// 播放
|
|
||||||
fadePlayOrPause();
|
|
||||||
}
|
|
||||||
$message.info("已开始播放", { showIcon: false });
|
|
||||||
};
|
|
||||||
|
|
||||||
// 歌曲模糊搜索
|
// 歌曲模糊搜索
|
||||||
const localSearch = debounce((val) => {
|
const localSearch = debounce((val) => {
|
||||||
const searchValue = val?.trim();
|
const searchValue = val?.trim();
|
||||||
|
|||||||
@@ -100,13 +100,14 @@
|
|||||||
<n-flex class="left">
|
<n-flex class="left">
|
||||||
<n-button
|
<n-button
|
||||||
:disabled="djData === 'empty'"
|
:disabled="djData === 'empty'"
|
||||||
|
:focusable="false"
|
||||||
type="primary"
|
type="primary"
|
||||||
class="play"
|
class="play"
|
||||||
tag="div"
|
tag="div"
|
||||||
circle
|
circle
|
||||||
strong
|
strong
|
||||||
secondary
|
secondary
|
||||||
@click="playAllSongs"
|
@click="playAllSongs(djData, 'dj')"
|
||||||
>
|
>
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<n-icon size="32">
|
<n-icon size="32">
|
||||||
@@ -115,6 +116,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</n-button>
|
</n-button>
|
||||||
<n-button
|
<n-button
|
||||||
|
:focusable="false"
|
||||||
class="like"
|
class="like"
|
||||||
size="large"
|
size="large"
|
||||||
tag="div"
|
tag="div"
|
||||||
@@ -133,7 +135,7 @@
|
|||||||
{{ isLikeOrDislike(djId) ? "订阅电台" : "取消订阅" }}
|
{{ isLikeOrDislike(djId) ? "订阅电台" : "取消订阅" }}
|
||||||
</n-button>
|
</n-button>
|
||||||
<n-dropdown :options="moreOptions" trigger="hover" placement="bottom-start">
|
<n-dropdown :options="moreOptions" trigger="hover" placement="bottom-start">
|
||||||
<n-button class="more" size="large" tag="div" circle strong secondary>
|
<n-button :focusable="false" class="more" size="large" tag="div" circle strong secondary>
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<n-icon>
|
<n-icon>
|
||||||
<SvgIcon icon="format-list-bulleted" />
|
<SvgIcon icon="format-list-bulleted" />
|
||||||
@@ -197,7 +199,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-else class="title">
|
<div v-else class="title">
|
||||||
<n-text class="key">参数不完整</n-text>
|
<n-text class="key">参数不完整</n-text>
|
||||||
<n-button class="back" strong secondary @click="router.go(-1)"> 返回上一页 </n-button>
|
<n-button :focusable="false" class="back" strong secondary @click="router.go(-1)">
|
||||||
|
返回上一页
|
||||||
|
</n-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -205,25 +209,21 @@
|
|||||||
import { NIcon } from "naive-ui";
|
import { NIcon } from "naive-ui";
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
import { musicData, siteData, siteSettings, siteStatus } from "@/stores";
|
import { siteData, siteSettings } from "@/stores";
|
||||||
import { getDjDetail, getDjProgram, likeDj } from "@/api/dj";
|
import { getDjDetail, getDjProgram, likeDj } from "@/api/dj";
|
||||||
import { fuzzySearch } from "@/utils/helper";
|
import { fuzzySearch } from "@/utils/helper";
|
||||||
import { isLogin } from "@/utils/auth";
|
import { isLogin } from "@/utils/auth";
|
||||||
import { getTimestampTime } from "@/utils/timeTools";
|
import { getTimestampTime } from "@/utils/timeTools";
|
||||||
import { fadePlayOrPause, initPlayer } from "@/utils/Player";
|
import { playAllSongs } from "@/utils/Player";
|
||||||
import debounce from "@/utils/debounce";
|
import debounce from "@/utils/debounce";
|
||||||
import formatData from "@/utils/formatData";
|
import formatData from "@/utils/formatData";
|
||||||
import SvgIcon from "@/components/Global/SvgIcon";
|
import SvgIcon from "@/components/Global/SvgIcon";
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const data = siteData();
|
const data = siteData();
|
||||||
const music = musicData();
|
|
||||||
const status = siteStatus();
|
|
||||||
const settings = siteSettings();
|
const settings = siteSettings();
|
||||||
const { userLikeData } = storeToRefs(data);
|
const { userLikeData } = storeToRefs(data);
|
||||||
const { loadSize } = storeToRefs(settings);
|
const { loadSize } = storeToRefs(settings);
|
||||||
const { playList, playSongData } = storeToRefs(music);
|
|
||||||
const { playIndex, playMode, playHeartbeatMode } = storeToRefs(status);
|
|
||||||
|
|
||||||
// 电台数据
|
// 电台数据
|
||||||
const djId = ref(router.currentRoute.value.query.id);
|
const djId = ref(router.currentRoute.value.query.id);
|
||||||
@@ -290,34 +290,6 @@ const getDjProgramData = async (id, limit = loadSize.value, offset = 0) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 播放电台全部节目
|
|
||||||
const playAllSongs = async () => {
|
|
||||||
if (!djData.value) return false;
|
|
||||||
// 关闭心动模式
|
|
||||||
playHeartbeatMode.value = false;
|
|
||||||
// 更改模式和电台
|
|
||||||
playMode.value = "dj";
|
|
||||||
playList.value = djData.value.slice();
|
|
||||||
// 是否处于电台内
|
|
||||||
const songId = music.getPlaySongData?.id;
|
|
||||||
const existingIndex = djData.value.findIndex((song) => song.id === songId);
|
|
||||||
// 若不处于
|
|
||||||
if (existingIndex === -1 || !songId) {
|
|
||||||
console.log("不在电台内");
|
|
||||||
playSongData.value = djData.value[0];
|
|
||||||
playIndex.value = 0;
|
|
||||||
// 初始化播放器
|
|
||||||
await initPlayer(true);
|
|
||||||
} else {
|
|
||||||
console.log("处于电台内");
|
|
||||||
playSongData.value = djData.value[existingIndex];
|
|
||||||
playIndex.value = existingIndex;
|
|
||||||
// 播放
|
|
||||||
fadePlayOrPause();
|
|
||||||
}
|
|
||||||
$message.info("已开始播放", { showIcon: false });
|
|
||||||
};
|
|
||||||
|
|
||||||
// 节目模糊搜索
|
// 节目模糊搜索
|
||||||
const localSearch = debounce((val) => {
|
const localSearch = debounce((val) => {
|
||||||
const searchValue = val?.trim();
|
const searchValue = val?.trim();
|
||||||
|
|||||||
@@ -112,13 +112,14 @@
|
|||||||
<n-flex class="left">
|
<n-flex class="left">
|
||||||
<n-button
|
<n-button
|
||||||
:disabled="playListData === null || playListData === 'empty' || loadingMsg !== null"
|
:disabled="playListData === null || playListData === 'empty' || loadingMsg !== null"
|
||||||
|
:focusable="false"
|
||||||
type="primary"
|
type="primary"
|
||||||
class="play"
|
class="play"
|
||||||
tag="div"
|
tag="div"
|
||||||
circle
|
circle
|
||||||
strong
|
strong
|
||||||
secondary
|
secondary
|
||||||
@click="playAllSongs"
|
@click="playAllSongs(playListData)"
|
||||||
>
|
>
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<n-icon size="32">
|
<n-icon size="32">
|
||||||
@@ -128,6 +129,7 @@
|
|||||||
</n-button>
|
</n-button>
|
||||||
<n-button
|
<n-button
|
||||||
v-if="!isUserPLayList"
|
v-if="!isUserPLayList"
|
||||||
|
:focusable="false"
|
||||||
class="like"
|
class="like"
|
||||||
size="large"
|
size="large"
|
||||||
tag="div"
|
tag="div"
|
||||||
@@ -149,6 +151,7 @@
|
|||||||
</n-button>
|
</n-button>
|
||||||
<n-button
|
<n-button
|
||||||
v-else
|
v-else
|
||||||
|
:focusable="false"
|
||||||
class="like"
|
class="like"
|
||||||
size="large"
|
size="large"
|
||||||
tag="div"
|
tag="div"
|
||||||
@@ -165,7 +168,15 @@
|
|||||||
编辑歌单
|
编辑歌单
|
||||||
</n-button>
|
</n-button>
|
||||||
<n-dropdown :options="moreOptions" trigger="hover" placement="bottom-start">
|
<n-dropdown :options="moreOptions" trigger="hover" placement="bottom-start">
|
||||||
<n-button class="more" size="large" tag="div" circle strong secondary>
|
<n-button
|
||||||
|
:focusable="false"
|
||||||
|
class="more"
|
||||||
|
size="large"
|
||||||
|
tag="div"
|
||||||
|
circle
|
||||||
|
strong
|
||||||
|
secondary
|
||||||
|
>
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<n-icon>
|
<n-icon>
|
||||||
<SvgIcon icon="format-list-bulleted" />
|
<SvgIcon icon="format-list-bulleted" />
|
||||||
@@ -218,7 +229,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-else class="title">
|
<div v-else class="title">
|
||||||
<n-text class="key">参数不完整</n-text>
|
<n-text class="key">参数不完整</n-text>
|
||||||
<n-button class="back" strong secondary @click="router.go(-1)"> 返回上一页 </n-button>
|
<n-button :focusable="false" class="back" strong secondary @click="router.go(-1)">
|
||||||
|
返回上一页
|
||||||
|
</n-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -226,7 +239,7 @@
|
|||||||
import { NIcon } from "naive-ui";
|
import { NIcon } from "naive-ui";
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
import { musicData, siteData, siteStatus } from "@/stores";
|
import { siteData } from "@/stores";
|
||||||
import {
|
import {
|
||||||
getPlayListDetail,
|
getPlayListDetail,
|
||||||
getAllPlayList,
|
getAllPlayList,
|
||||||
@@ -238,18 +251,14 @@ import { getSongDetail } from "@/api/song";
|
|||||||
import { formatNumber, fuzzySearch } from "@/utils/helper";
|
import { formatNumber, fuzzySearch } from "@/utils/helper";
|
||||||
import { isLogin } from "@/utils/auth";
|
import { isLogin } from "@/utils/auth";
|
||||||
import { getTimestampTime } from "@/utils/timeTools";
|
import { getTimestampTime } from "@/utils/timeTools";
|
||||||
import { fadePlayOrPause, initPlayer } from "@/utils/Player";
|
import { playAllSongs } from "@/utils/Player";
|
||||||
import debounce from "@/utils/debounce";
|
import debounce from "@/utils/debounce";
|
||||||
import formatData from "@/utils/formatData";
|
import formatData from "@/utils/formatData";
|
||||||
import SvgIcon from "@/components/Global/SvgIcon";
|
import SvgIcon from "@/components/Global/SvgIcon";
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const data = siteData();
|
const data = siteData();
|
||||||
const music = musicData();
|
|
||||||
const status = siteStatus();
|
|
||||||
const { userLikeData, userData } = storeToRefs(data);
|
const { userLikeData, userData } = storeToRefs(data);
|
||||||
const { playList, playSongData } = storeToRefs(music);
|
|
||||||
const { playIndex, playMode, playHeartbeatMode } = storeToRefs(status);
|
|
||||||
|
|
||||||
// 歌单 ID
|
// 歌单 ID
|
||||||
const playlistId = ref(
|
const playlistId = ref(
|
||||||
@@ -385,34 +394,6 @@ const getBigPlayListData = async (id, count) => {
|
|||||||
loadingMsg.value = null;
|
loadingMsg.value = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 播放歌单全部歌曲
|
|
||||||
const playAllSongs = async () => {
|
|
||||||
if (!playListData.value) return false;
|
|
||||||
// 关闭心动模式
|
|
||||||
playHeartbeatMode.value = false;
|
|
||||||
// 更改模式和歌单
|
|
||||||
playMode.value = "normal";
|
|
||||||
playList.value = playListData.value.slice();
|
|
||||||
// 是否处于歌单内
|
|
||||||
const songId = music.getPlaySongData?.id;
|
|
||||||
const existingIndex = playListData.value.findIndex((song) => song.id === songId);
|
|
||||||
// 若不处于
|
|
||||||
if (existingIndex === -1 || !songId) {
|
|
||||||
console.log("不在歌单内");
|
|
||||||
playSongData.value = playListData.value[0];
|
|
||||||
playIndex.value = 0;
|
|
||||||
// 初始化播放器
|
|
||||||
await initPlayer(true);
|
|
||||||
} else {
|
|
||||||
console.log("处于歌单内");
|
|
||||||
playSongData.value = playListData.value[existingIndex];
|
|
||||||
playIndex.value = existingIndex;
|
|
||||||
// 播放
|
|
||||||
fadePlayOrPause();
|
|
||||||
}
|
|
||||||
$message.info("已开始播放", { showIcon: false });
|
|
||||||
};
|
|
||||||
|
|
||||||
// 歌曲模糊搜索
|
// 歌曲模糊搜索
|
||||||
const localSearch = debounce((val) => {
|
const localSearch = debounce((val) => {
|
||||||
const searchValue = val?.trim();
|
const searchValue = val?.trim();
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
v-if="allAlbumData"
|
v-if="allAlbumData"
|
||||||
:style="{
|
:style="{
|
||||||
height: `calc(100vh - ${
|
height: `calc(100vh - ${
|
||||||
Object.keys(music.playSongData)?.length && status.showPlayBar ? 380 : 300
|
Object.keys(music.playSongData)?.length && status.showPlayBar ? 445 : 365
|
||||||
}px)`,
|
}px)`,
|
||||||
}"
|
}"
|
||||||
class="local-album"
|
class="local-album"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
class="local-artists"
|
class="local-artists"
|
||||||
:style="{
|
:style="{
|
||||||
height: `calc(100vh - ${
|
height: `calc(100vh - ${
|
||||||
Object.keys(music.playSongData)?.length && status.showPlayBar ? 380 : 300
|
Object.keys(music.playSongData)?.length && status.showPlayBar ? 445 : 365
|
||||||
}px)`,
|
}px)`,
|
||||||
}"
|
}"
|
||||||
type="card"
|
type="card"
|
||||||
|
|||||||
@@ -26,41 +26,68 @@
|
|||||||
GB
|
GB
|
||||||
</div>
|
</div>
|
||||||
</n-flex>
|
</n-flex>
|
||||||
|
<!-- 功能区 -->
|
||||||
|
<n-flex class="menu" justify="space-between">
|
||||||
|
<n-flex class="left">
|
||||||
|
<n-button
|
||||||
|
:disabled="!localSongList?.length"
|
||||||
|
:focusable="false"
|
||||||
|
type="primary"
|
||||||
|
class="play"
|
||||||
|
tag="div"
|
||||||
|
circle
|
||||||
|
strong
|
||||||
|
secondary
|
||||||
|
@click="playAllSongs(localSongList)"
|
||||||
|
>
|
||||||
|
<template #icon>
|
||||||
|
<n-icon size="32">
|
||||||
|
<SvgIcon icon="play-arrow-rounded" />
|
||||||
|
</n-icon>
|
||||||
|
</template>
|
||||||
|
</n-button>
|
||||||
|
<!-- 目录管理 -->
|
||||||
|
<n-button
|
||||||
|
:focusable="false"
|
||||||
|
class="local-path"
|
||||||
|
tag="div"
|
||||||
|
round
|
||||||
|
strong
|
||||||
|
secondary
|
||||||
|
@click="localPathShow = true"
|
||||||
|
>
|
||||||
|
<template #icon>
|
||||||
|
<n-icon>
|
||||||
|
<SvgIcon icon="folder-cog" />
|
||||||
|
</n-icon>
|
||||||
|
</template>
|
||||||
|
目录管理
|
||||||
|
</n-button>
|
||||||
|
</n-flex>
|
||||||
|
<n-flex class="right">
|
||||||
|
<!-- 模糊搜索 -->
|
||||||
|
<n-input
|
||||||
|
v-if="localSongList?.length"
|
||||||
|
v-model:value="searchValue"
|
||||||
|
:input-props="{ autoComplete: false }"
|
||||||
|
class="search"
|
||||||
|
placeholder="搜索"
|
||||||
|
clearable
|
||||||
|
@input="localSearch"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<n-icon size="18">
|
||||||
|
<SvgIcon icon="search-rounded" />
|
||||||
|
</n-icon>
|
||||||
|
</template>
|
||||||
|
</n-input>
|
||||||
|
</n-flex>
|
||||||
|
</n-flex>
|
||||||
<!-- 标签页 -->
|
<!-- 标签页 -->
|
||||||
<n-tabs v-model:value="tabValue" class="tabs" type="segment" @update:value="tabChange">
|
<n-tabs v-model:value="tabValue" class="tabs" type="segment" @update:value="tabChange">
|
||||||
<n-tab name="local-songs"> 歌曲 </n-tab>
|
<n-tab name="local-songs"> 歌曲 </n-tab>
|
||||||
<n-tab name="local-artists"> 歌手 </n-tab>
|
<n-tab name="local-artists"> 歌手 </n-tab>
|
||||||
<n-tab name="local-albums"> 专辑 </n-tab>
|
<n-tab name="local-albums"> 专辑 </n-tab>
|
||||||
<template #suffix>
|
|
||||||
<!-- 模糊搜索 -->
|
|
||||||
<div v-if="localSongList?.length" class="search">
|
|
||||||
<n-input
|
|
||||||
v-model:value="searchValue"
|
|
||||||
:input-props="{ autoComplete: false }"
|
|
||||||
class="local-search"
|
|
||||||
placeholder="搜索"
|
|
||||||
clearable
|
|
||||||
@input="localSearch"
|
|
||||||
>
|
|
||||||
<template #prefix>
|
|
||||||
<n-icon size="18">
|
|
||||||
<SvgIcon icon="search-rounded" />
|
|
||||||
</n-icon>
|
|
||||||
</template>
|
|
||||||
</n-input>
|
|
||||||
</div>
|
|
||||||
<!-- 目录管理 -->
|
|
||||||
<div class="local-path">
|
|
||||||
<n-button strong secondary @click="localPathShow = true">
|
|
||||||
<template #icon>
|
|
||||||
<n-icon>
|
|
||||||
<SvgIcon icon="folder-cog" />
|
|
||||||
</n-icon>
|
|
||||||
</template>
|
|
||||||
目录管理
|
|
||||||
</n-button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</n-tabs>
|
</n-tabs>
|
||||||
<!-- 路由页面 -->
|
<!-- 路由页面 -->
|
||||||
<Transition name="fade" mode="out-in">
|
<Transition name="fade" mode="out-in">
|
||||||
@@ -172,6 +199,7 @@
|
|||||||
import { musicData, indexedDBData } from "@/stores";
|
import { musicData, indexedDBData } from "@/stores";
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
import { fuzzySearch } from "@/utils/helper";
|
import { fuzzySearch } from "@/utils/helper";
|
||||||
|
import { playAllSongs } from "@/utils/Player";
|
||||||
import debounce from "@/utils/debounce";
|
import debounce from "@/utils/debounce";
|
||||||
|
|
||||||
const indexedDB = indexedDBData();
|
const indexedDB = indexedDBData();
|
||||||
@@ -335,26 +363,41 @@ onBeforeMount(async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.tabs {
|
.menu {
|
||||||
margin-bottom: 20px;
|
flex-wrap: nowrap;
|
||||||
.search {
|
align-items: center;
|
||||||
height: 100%;
|
margin: 20px 0;
|
||||||
margin-right: 16px;
|
.left {
|
||||||
.local-search {
|
flex-wrap: nowrap;
|
||||||
|
align-items: center;
|
||||||
|
.play {
|
||||||
|
--n-width: 46px;
|
||||||
|
--n-height: 46px;
|
||||||
|
}
|
||||||
|
.local-path {
|
||||||
|
--n-height: 100%;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.right {
|
||||||
|
.search {
|
||||||
|
height: 40px;
|
||||||
|
width: 130px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: 100%;
|
border-radius: 40px;
|
||||||
border-radius: 6px;
|
transition:
|
||||||
}
|
width 0.3s,
|
||||||
}
|
background-color 0.3s;
|
||||||
.local-path {
|
&.n-input--focus {
|
||||||
height: 100%;
|
width: 200px;
|
||||||
:deep(.n-button) {
|
}
|
||||||
--n-height: 100%;
|
|
||||||
--n-border-radius: 6px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.tabs {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.local-list {
|
.local-list {
|
||||||
:deep(.n-list-item__prefix) {
|
:deep(.n-list-item__prefix) {
|
||||||
|
|||||||
Reference in New Issue
Block a user