mirror of
https://github.com/RhenCloud/Cloud-Home.git
synced 2026-01-22 17:39:07 +08:00
feat: 通过 NeteaseMiniPlayer 支持播放来自网易云音乐的音乐
This commit is contained in:
30
README.md
30
README.md
@@ -15,6 +15,14 @@
|
|||||||
- 构建:Vite
|
- 构建:Vite
|
||||||
- 部署:Vercel(静态构建 + Serverless Functions)
|
- 部署:Vercel(静态构建 + Serverless Functions)
|
||||||
|
|
||||||
|
## 致谢
|
||||||
|
|
||||||
|
排名不分先后
|
||||||
|
|
||||||
|
- [`Netease Mini Player`](https://github.com/numakkiyu/NeteaseMiniPlayer): 迷你网易云播放器组件,为本项目的音乐播放功能提供支持。
|
||||||
|
|
||||||
|
感谢以上开源项目原作者与维护者的贡献。
|
||||||
|
|
||||||
## 配置指南
|
## 配置指南
|
||||||
|
|
||||||
### 站点配置文件 (`src/config/siteConfig.ts`)
|
### 站点配置文件 (`src/config/siteConfig.ts`)
|
||||||
@@ -61,6 +69,28 @@ const siteConfig: SiteConfig = {
|
|||||||
startDate:"xxxx-xx-xx", // 网站创建日期
|
startDate:"xxxx-xx-xx", // 网站创建日期
|
||||||
},
|
},
|
||||||
|
|
||||||
|
music: {
|
||||||
|
// 是否启用音乐播放器
|
||||||
|
enable: true,
|
||||||
|
// floating - 浮动模式播放器(推荐)- 用于播放网易云歌单
|
||||||
|
// embed - 嵌入模式播放器 - 用于播放网易云单曲
|
||||||
|
mode: "floating", // "floating" 或 "embed"
|
||||||
|
// 歌单ID:从网易云音乐链接获取,如 https://music.163.com/#/playlist?id=14273792576
|
||||||
|
playlistId: undefined, // 例如: "14273792576"
|
||||||
|
// 歌曲ID:仅在嵌入模式下使用
|
||||||
|
songId: undefined, // 例如: "554242291"
|
||||||
|
// 播放器位置(浮动模式): "bottom-left" | "bottom-right" | "top-left" | "top-right"
|
||||||
|
position: "bottom-left",
|
||||||
|
// 是否显示歌词
|
||||||
|
lyric: true,
|
||||||
|
// 主题: "light" | "dark" | "auto"
|
||||||
|
theme: "dark",
|
||||||
|
// 是否自动播放
|
||||||
|
autoplay: false,
|
||||||
|
// 是否默认以黑胶唱片状态启动(仅浮动模式)
|
||||||
|
defaultMinimized: true,
|
||||||
|
},
|
||||||
|
|
||||||
umami: {
|
umami: {
|
||||||
enable: true, // 是否启用 Umami 分析
|
enable: true, // 是否启用 Umami 分析
|
||||||
url: "https://cloud.umami.is/script.js", // Umami 分析脚本 URL,一般无需修改
|
url: "https://cloud.umami.is/script.js", // Umami 分析脚本 URL,一般无需修改
|
||||||
|
|||||||
@@ -6,11 +6,15 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Cloud Home</title>
|
<title>Cloud Home</title>
|
||||||
<link rel="icon" href="/favicon.ico" />
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
<!-- NeteaseMiniPlayer v2 CSS -->
|
||||||
|
<link rel="stylesheet" href="https://api.hypcvgm.top/NeteaseMiniPlayer/netease-mini-player-v2.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<script type="module" src="/src/main.ts"></script>
|
<script type="module" src="/src/main.ts"></script>
|
||||||
|
<!-- NeteaseMiniPlayer v2 JS -->
|
||||||
|
<script src="/js/netease-mini-player-v2.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jaseeey/vue-umami-plugin": "^1.4.0",
|
"@jaseeey/vue-umami-plugin": "^1.4.0",
|
||||||
"@vercel/node": "^5.5.15",
|
"@vercel/node": "^5.5.15",
|
||||||
|
"cros": "^1.1.0",
|
||||||
"express": "^5.2.1",
|
"express": "^5.2.1",
|
||||||
"he": "^1.2.0",
|
"he": "^1.2.0",
|
||||||
"nodemailer": "^7.0.11",
|
"nodemailer": "^7.0.11",
|
||||||
|
|||||||
1585
public/js/netease-mini-player-v2.js
Normal file
1585
public/js/netease-mini-player-v2.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -21,6 +21,8 @@
|
|||||||
<Transition name="fade-down">
|
<Transition name="fade-down">
|
||||||
<FooterSection v-if="!hideComponents" :contact="contact" key="footer" />
|
<FooterSection v-if="!hideComponents" :contact="contact" key="footer" />
|
||||||
</Transition>
|
</Transition>
|
||||||
|
<!-- 音乐播放器 -->
|
||||||
|
<MusicPlayer />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -28,6 +30,7 @@
|
|||||||
import { onMounted, computed, ref } from "vue";
|
import { onMounted, computed, ref } from "vue";
|
||||||
import PageSwitcher from "./components/PageSwitcher.vue";
|
import PageSwitcher from "./components/PageSwitcher.vue";
|
||||||
import FooterSection from "./components/FooterSection.vue";
|
import FooterSection from "./components/FooterSection.vue";
|
||||||
|
import MusicPlayer from "./components/MusicPlayer.vue";
|
||||||
import siteConfig from "./config/siteConfig";
|
import siteConfig from "./config/siteConfig";
|
||||||
|
|
||||||
const contact = siteConfig.footer;
|
const contact = siteConfig.footer;
|
||||||
@@ -53,7 +56,7 @@ const getBackgroundImage = () => {
|
|||||||
|
|
||||||
if (!image) return undefined;
|
if (!image) return undefined;
|
||||||
|
|
||||||
return image.startsWith("http") ? image : `/public/${image}`;
|
return image.startsWith("http") ? image : `/${image}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const backgroundStyle = computed(() => {
|
const backgroundStyle = computed(() => {
|
||||||
|
|||||||
30
src/components/MusicPlayer.vue
Normal file
30
src/components/MusicPlayer.vue
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
v-if="music.enable && (music.playlistId || music.songId)"
|
||||||
|
class="netease-mini-player"
|
||||||
|
:data-playlist-id="music.mode === 'floating' ? music.playlistId : undefined"
|
||||||
|
:data-song-id="music.mode === 'embed' ? music.songId : undefined"
|
||||||
|
:data-embed="music.mode === 'embed'"
|
||||||
|
:data-position="music.position"
|
||||||
|
:data-lyric="music.lyric"
|
||||||
|
:data-theme="music.theme"
|
||||||
|
:data-autoplay="music.autoplay"
|
||||||
|
:data-default-minimized="music.defaultMinimized"
|
||||||
|
></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import siteConfig from "../config/siteConfig";
|
||||||
|
|
||||||
|
const music = siteConfig.music;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- <style scoped>
|
||||||
|
/* 音乐播放器样式由 NeteaseMiniPlayer 提供 */
|
||||||
|
/* 使用 display: contents 使外层容器不占用空间 */
|
||||||
|
/* 确保播放器浮动定位,不影响页面布局 */
|
||||||
|
:deep(.netease-mini-player) {
|
||||||
|
position: fixed !important;
|
||||||
|
z-index: 999 !important;
|
||||||
|
}
|
||||||
|
</style> -->
|
||||||
@@ -47,6 +47,26 @@ const siteConfig = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
music: {
|
||||||
|
enable: true,
|
||||||
|
// 浮动模式播放器(推荐)- 用于播放网易云歌单
|
||||||
|
mode: "floating", // "floating" 或 "embed"
|
||||||
|
// 歌单ID:从网易云音乐链接获取,如 https://music.163.com/#/playlist?id=14273792576
|
||||||
|
playlistId: "14366453940", // 例如: "14273792576"
|
||||||
|
// 歌曲ID:仅在嵌入模式下使用
|
||||||
|
songId: undefined, // 例如: "554242291"
|
||||||
|
// 播放器位置(浮动模式): "bottom-left" | "bottom-right" | "top-left" | "top-right"
|
||||||
|
position: "bottom-left",
|
||||||
|
// 是否显示歌词
|
||||||
|
lyric: true,
|
||||||
|
// 主题: "light" | "dark" | "auto"
|
||||||
|
theme: "dark",
|
||||||
|
// 是否自动播放
|
||||||
|
autoplay: false,
|
||||||
|
// 是否默认以黑胶唱片状态启动(仅浮动模式)
|
||||||
|
defaultMinimized: true,
|
||||||
|
},
|
||||||
|
|
||||||
umami: {
|
umami: {
|
||||||
enable: true,
|
enable: true,
|
||||||
url: "https://cloud.umami.is/script.js",
|
url: "https://cloud.umami.is/script.js",
|
||||||
|
|||||||
@@ -12,4 +12,5 @@ if (process.env.NODE_ENV !== "development") {
|
|||||||
app.use(VueUmamiPlugin({ websiteID: siteConfig.umami.websiteId, scriptSrc: siteConfig.umami.url, router }));
|
app.use(VueUmamiPlugin({ websiteID: siteConfig.umami.websiteId, scriptSrc: siteConfig.umami.url, router }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
app.use(router).mount("#app");
|
app.use(router).mount("#app");
|
||||||
|
|||||||
101
src/styles.css
101
src/styles.css
@@ -1,3 +1,7 @@
|
|||||||
|
html {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
color-scheme: light dark;
|
color-scheme: light dark;
|
||||||
font-family: "Inter", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
font-family: "Inter", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||||
@@ -7,7 +11,7 @@
|
|||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
min-height: 100vh;
|
min-height: 100%;
|
||||||
background: radial-gradient(circle at 20% 20%, #1b2b4b, #0f1629);
|
background: radial-gradient(circle at 20% 20%, #1b2b4b, #0f1629);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,3 +94,98 @@ p {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Ensure the Netease mini player doesn't occupy page layout space
|
||||||
|
and stays fixed above content. Use !important to override
|
||||||
|
styles injected by third-party scripts. */
|
||||||
|
.netease-mini-player {
|
||||||
|
position: fixed !important;
|
||||||
|
bottom: 20px !important;
|
||||||
|
left: 20px !important;
|
||||||
|
right: auto !important;
|
||||||
|
/* do not force width here — let the player's own minimized/expanded
|
||||||
|
styles control sizing. Only constrain max width as a safety net. */
|
||||||
|
max-width: calc(100% - 40px) !important;
|
||||||
|
z-index: 9999 !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
transform: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the player injects a full-width bar, make sure it won't
|
||||||
|
push page content by forcing it out of the normal flow. */
|
||||||
|
.netease-mini-player > * {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Defensive: hide any accidental full-width injected container from the player
|
||||||
|
that might occupy vertical space. This targets common helper classes used
|
||||||
|
by the player script. */
|
||||||
|
.netease-mini-player-embed,
|
||||||
|
.nmpv2-player,
|
||||||
|
.nmpv2-root {
|
||||||
|
position: fixed !important;
|
||||||
|
bottom: 20px !important;
|
||||||
|
left: 20px !important;
|
||||||
|
right: auto !important;
|
||||||
|
z-index: 9999 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fix: prevent playlist dropdown from increasing document height
|
||||||
|
by forcing the playlist container to be fixed and clipped to viewport. */
|
||||||
|
.netease-mini-player[data-position="bottom-left"] .playlist-container,
|
||||||
|
.netease-mini-player[data-position="bottom-right"] .playlist-container {
|
||||||
|
position: fixed !important;
|
||||||
|
bottom: calc(20px + 80px) !important;
|
||||||
|
left: 20px !important;
|
||||||
|
right: auto !important;
|
||||||
|
width: 290px !important;
|
||||||
|
max-height: 50vh !important;
|
||||||
|
overflow: auto !important;
|
||||||
|
z-index: 10001 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.netease-mini-player[data-position="top-left"] .playlist-container,
|
||||||
|
.netease-mini-player[data-position="top-right"] .playlist-container {
|
||||||
|
position: fixed !important;
|
||||||
|
top: calc(20px + 80px) !important;
|
||||||
|
left: 20px !important;
|
||||||
|
right: auto !important;
|
||||||
|
width: 290px !important;
|
||||||
|
max-height: 50vh !important;
|
||||||
|
overflow: auto !important;
|
||||||
|
z-index: 10001 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If player is docked to the right, align playlist to right edge */
|
||||||
|
.netease-mini-player[data-position="bottom-right"] .playlist-container,
|
||||||
|
.netease-mini-player[data-position="top-right"] .playlist-container {
|
||||||
|
left: auto !important;
|
||||||
|
right: 20px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure minimized player displays as a circle and its album cover fits */
|
||||||
|
.netease-mini-player.minimized {
|
||||||
|
width: 80px !important;
|
||||||
|
height: 80px !important;
|
||||||
|
border-radius: 50% !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
overflow: hidden !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.netease-mini-player.minimized .album-cover-container {
|
||||||
|
width: 100% !important;
|
||||||
|
height: 100% !important;
|
||||||
|
position: absolute !important;
|
||||||
|
top: 0 !important;
|
||||||
|
left: 0 !important;
|
||||||
|
border-radius: 50% !important;
|
||||||
|
overflow: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.netease-mini-player.minimized .album-cover {
|
||||||
|
width: 100% !important;
|
||||||
|
height: 100% !important;
|
||||||
|
object-fit: cover !important;
|
||||||
|
border-radius: 50% !important;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user