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
|
||||
- 部署:Vercel(静态构建 + Serverless Functions)
|
||||
|
||||
## 致谢
|
||||
|
||||
排名不分先后
|
||||
|
||||
- [`Netease Mini Player`](https://github.com/numakkiyu/NeteaseMiniPlayer): 迷你网易云播放器组件,为本项目的音乐播放功能提供支持。
|
||||
|
||||
感谢以上开源项目原作者与维护者的贡献。
|
||||
|
||||
## 配置指南
|
||||
|
||||
### 站点配置文件 (`src/config/siteConfig.ts`)
|
||||
@@ -61,6 +69,28 @@ const siteConfig: SiteConfig = {
|
||||
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: {
|
||||
enable: true, // 是否启用 Umami 分析
|
||||
url: "https://cloud.umami.is/script.js", // Umami 分析脚本 URL,一般无需修改
|
||||
|
||||
@@ -6,11 +6,15 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Cloud Home</title>
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<!-- NeteaseMiniPlayer v2 CSS -->
|
||||
<link rel="stylesheet" href="https://api.hypcvgm.top/NeteaseMiniPlayer/netease-mini-player-v2.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
<!-- NeteaseMiniPlayer v2 JS -->
|
||||
<script src="/js/netease-mini-player-v2.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -10,6 +10,7 @@
|
||||
"dependencies": {
|
||||
"@jaseeey/vue-umami-plugin": "^1.4.0",
|
||||
"@vercel/node": "^5.5.15",
|
||||
"cros": "^1.1.0",
|
||||
"express": "^5.2.1",
|
||||
"he": "^1.2.0",
|
||||
"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">
|
||||
<FooterSection v-if="!hideComponents" :contact="contact" key="footer" />
|
||||
</Transition>
|
||||
<!-- 音乐播放器 -->
|
||||
<MusicPlayer />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -28,6 +30,7 @@
|
||||
import { onMounted, computed, ref } from "vue";
|
||||
import PageSwitcher from "./components/PageSwitcher.vue";
|
||||
import FooterSection from "./components/FooterSection.vue";
|
||||
import MusicPlayer from "./components/MusicPlayer.vue";
|
||||
import siteConfig from "./config/siteConfig";
|
||||
|
||||
const contact = siteConfig.footer;
|
||||
@@ -53,7 +56,7 @@ const getBackgroundImage = () => {
|
||||
|
||||
if (!image) return undefined;
|
||||
|
||||
return image.startsWith("http") ? image : `/public/${image}`;
|
||||
return image.startsWith("http") ? image : `/${image}`;
|
||||
};
|
||||
|
||||
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: {
|
||||
enable: true,
|
||||
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(router).mount("#app");
|
||||
|
||||
101
src/styles.css
101
src/styles.css
@@ -1,3 +1,7 @@
|
||||
html {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
font-family: "Inter", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||
@@ -7,7 +11,7 @@
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
min-height: 100vh;
|
||||
min-height: 100%;
|
||||
background: radial-gradient(circle at 20% 20%, #1b2b4b, #0f1629);
|
||||
}
|
||||
|
||||
@@ -90,3 +94,98 @@ p {
|
||||
text-align: center;
|
||||
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