惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Cloudbric
Cloudbric
Schneier on Security
Schneier on Security
V2EX - 技术
V2EX - 技术
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
O
OpenAI News
S
Security @ Cisco Blogs
Scott Helme
Scott Helme
Security Archives - TechRepublic
Security Archives - TechRepublic
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
WordPress大学
WordPress大学
云风的 BLOG
云风的 BLOG
T
Threatpost
Hacker News: Ask HN
Hacker News: Ask HN
Microsoft Azure Blog
Microsoft Azure Blog
Know Your Adversary
Know Your Adversary
博客园 - 三生石上(FineUI控件)
A
About on SuperTechFans
Forbes - Security
Forbes - Security
NISL@THU
NISL@THU
Security Latest
Security Latest
G
Google Developers Blog
D
Docker
T
Threat Research - Cisco Blogs
N
Netflix TechBlog - Medium
C
CERT Recently Published Vulnerability Notes
H
Help Net Security
B
Blog
Martin Fowler
Martin Fowler
N
News and Events Feed by Topic
Simon Willison's Weblog
Simon Willison's Weblog
Hacker News - Newest:
Hacker News - Newest: "LLM"
L
Lohrmann on Cybersecurity
Y
Y Combinator Blog
PCI Perspectives
PCI Perspectives
F
Fortinet All Blogs
MyScale Blog
MyScale Blog
Project Zero
Project Zero
爱范儿
爱范儿
Cisco Talos Blog
Cisco Talos Blog
博客园 - 聂微东
Hugging Face - Blog
Hugging Face - Blog
人人都是产品经理
人人都是产品经理
V
Vulnerabilities – Threatpost
P
Proofpoint News Feed
Cyberwarzone
Cyberwarzone
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
TaoSecurity Blog
TaoSecurity Blog
N
News | PayPal Newsroom
Recorded Future
Recorded Future

Hyde Blog

Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog 关于我 关于我 Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog
Hyde Blog
Hyde · 2026-04-04 · via Hyde Blog

vue

<!-- 网易云迷你播放器 -->
<template>
  <!-- 创建播放器容器 -->
  <div class="netease-mini-player" data-playlist-id="14273792576" data-embed="false" data-position="bottom-left"
    data-lyric="true" data-theme="auto" data-default-minimized="true"></div>
</template>

<script setup>
import { onMounted, onUnmounted } from 'vue';

// 动态引入播放器的 CSS 和 JS 文件
onMounted(() => {
  // 引入 CSS
  const cssLink = document.createElement('link');
  cssLink.rel = 'stylesheet';
  // cssLink.href = 'https://api.hypcvgm.top/NeteaseMiniPlayer/netease-mini-player-v2.css';
  // document.head.appendChild(cssLink);

  // 引入 JS 并确保加载完成后初始化
  const script = document.createElement('script');
  script.src = 'https://api.hypcvgm.top/NeteaseMiniPlayer/netease-mini-player-v2.js';
  script.async = true;
  script.onload = () => {
    console.log('网易云迷你播放器资源加载完成');
  };
  script.onerror = () => {
    console.error('网易云迷你播放器资源加载失败');
  };
  document.body.appendChild(script);
});

// 组件卸载时清理动态引入的资源
onUnmounted(() => {
  // 移除 CSS
  // const cssLinks = document.head.querySelectorAll('link[href*="netease-mini-player-v2.css"]');
  // cssLinks.forEach(link => document.head.removeChild(link));

  // 移除 JS
  const scripts = document.body.querySelectorAll('script[src*="netease-mini-player-v2.js"]');
  scripts.forEach(script => document.body.removeChild(script));

  // 清理播放器实例(如果播放器提供了销毁方法)
  if (window.neteaseMiniPlayer?.destroy) {
    window.neteaseMiniPlayer.destroy();
  }
});
</script>

<style>
/**
 * [NMPv2] NeteaseMiniPlayer v2 CSS 
 * Lightweight Player Component Based on NetEase Cloud Music API
 * 
 * Copyright 2025 BHCN STUDIO & 北海的佰川(ImBHCN[numakkiyu])
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
:root {
  --primary-bg: #fafafa;
  --secondary-bg: #f0f0f0;
  --bg-color: #fafafa;
  --accent-color: #FF6B35;
  --accent-color-2: #7A66FF;
  --accent-color-3: #00C2FF;
  --accent-gradient: linear-gradient(135deg, var(--accent-color) 0%, var(--accent-color-2) 50%, var(--accent-color-3) 100%);
  --text-primary: #333333;
  --text-secondary: #666666;
  --text-muted: #999999;
  --shadow-light: rgba(255, 255, 255, 0.9);
  --shadow-dark: rgba(0, 0, 0, 0.1);
  --shadow-inset: inset 3px 3px 6px var(--shadow-dark), inset -3px -3px 6px var(--shadow-light);
  --shadow-outset: 6px 6px 12px var(--shadow-dark), -6px -6px 12px var(--shadow-light);
  --border-radius: 12px;
  --transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  --theme-transition: background-color 0.3s ease, color 0.3s ease, box-shadow 0.3s ease, border-color 0.3s ease;

  --flow-color-1: rgba(255, 107, 53, 0.32);
  --flow-color-2: rgba(86, 151, 227, 0.26);
  --flow-color-3: rgba(255, 209, 102, 0.26);
  --flow-color-4: rgba(122, 102, 255, 0.28);
  --flow-color-5: rgba(0, 194, 255, 0.22);
  --flow-opacity: 0.45;
  --flow-speed: 10s;
  --volume-total-width: 60px;
  --playlist-flow-opacity: 0.25;
}

.netease-mini-player[data-theme="dark"] {
  --primary-bg: #1e1e1e;
  --secondary-bg: #2a2a2a;
  --bg-color: #1e1e1e;
  --accent-color: #FF8A50;
  --accent-color-2: #6C63FF;
  --accent-color-3: #00D4FF;
  --accent-gradient: linear-gradient(135deg, var(--accent-color) 0%, var(--accent-color-2) 50%, var(--accent-color-3) 100%);
  --text-primary: #e0e0e0;
  --text-secondary: #b0b0b0;
  --text-muted: #808080;
  --shadow-light: rgba(255, 255, 255, 0.05);
  --shadow-dark: rgba(0, 0, 0, 0.4);
  --shadow-inset: inset 3px 3px 6px var(--shadow-dark), inset -3px -3px 6px var(--shadow-light);
  --shadow-outset: 6px 6px 12px var(--shadow-dark), -6px -6px 12px var(--shadow-light);

  --flow-color-1: rgba(255, 138, 80, 0.28);
  --flow-color-2: rgba(86, 151, 227, 0.24);
  --flow-color-3: rgba(140, 100, 255, 0.26);
  --flow-color-4: rgba(124, 110, 255, 0.24);
  --flow-color-5: rgba(0, 212, 255, 0.22);
  --flow-opacity: 0.36;
  --flow-speed: 12s;
}

@media (prefers-color-scheme: dark) {
  .netease-mini-player[data-theme="auto"] {
    --primary-bg: #1e1e1e;
    --secondary-bg: #2a2a2a;
    --bg-color: #1e1e1e;
    --accent-color: #FF8A50;
    --accent-color-2: #6C63FF;
    --accent-color-3: #00D4FF;
    --accent-gradient: linear-gradient(135deg, var(--accent-color) 0%, var(--accent-color-2) 50%, var(--accent-color-3) 100%);
    --text-primary: #e0e0e0;
    --text-secondary: #b0b0b0;
    --text-muted: #808080;
    --shadow-light: rgba(255, 255, 255, 0.05);
    --shadow-dark: rgba(0, 0, 0, 0.4);
    --shadow-inset: inset 3px 3px 6px var(--shadow-dark), inset -3px -3px 6px var(--shadow-light);
    --shadow-outset: 6px 6px 12px var(--shadow-dark), -6px -6px 12px var(--shadow-light);

    --flow-color-1: rgba(255, 138, 80, 0.28);
    --flow-color-2: rgba(86, 151, 227, 0.24);
    --flow-color-3: rgba(140, 100, 255, 0.26);
    --flow-color-4: rgba(124, 110, 255, 0.24);
    --flow-color-5: rgba(0, 212, 255, 0.22);
    --flow-opacity: 0.36;
    --flow-speed: 12s;
  }
}

@media (prefers-color-scheme: light) {
  .netease-mini-player[data-theme="auto"] {
    --primary-bg: #fafafa;
    --secondary-bg: #f0f0f0;
    --bg-color: #fafafa;
    --accent-color: #FF6B35;
    --accent-color-2: #7A66FF;
    --accent-color-3: #00C2FF;
    --accent-gradient: linear-gradient(135deg, var(--accent-color) 0%, var(--accent-color-2) 50%, var(--accent-color-3) 100%);
    --text-primary: #333333;
    --text-secondary: #666666;
    --text-muted: #999999;
    --shadow-light: rgba(255, 255, 255, 0.9);
    --shadow-dark: rgba(0, 0, 0, 0.1);
    --shadow-inset: inset 3px 3px 6px var(--shadow-dark), inset -3px -3px 6px var(--shadow-light);
    --shadow-outset: 6px 6px 12px var(--shadow-dark), -6px -6px 12px var(--shadow-light);

    --flow-color-1: rgba(255, 107, 53, 0.32);
    --flow-color-2: rgba(86, 151, 227, 0.26);
    --flow-color-3: rgba(255, 209, 102, 0.26);
    --flow-color-4: rgba(122, 102, 255, 0.28);
    --flow-color-5: rgba(0, 194, 255, 0.22);
    --flow-opacity: 0.45;
    --flow-speed: 10s;
  }
}

.netease-mini-player {
  width: 400px;
  height: 120px;
  background: var(--bg-color);
  border-radius: 16px;
  padding: 12px;
  box-shadow: var(--shadow-outset);
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  position: relative;
  overflow: visible;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: 8px;
  transition:
    width 0.5s cubic-bezier(0.4, 0, 0.2, 1),
    height 0.5s cubic-bezier(0.4, 0, 0.2, 1),
    border-radius 0.5s cubic-bezier(0.4, 0, 0.2, 1),
    padding 0.5s cubic-bezier(0.4, 0, 0.2, 1),
    var(--theme-transition);
  background: 0.5s cubic-bezier(0.4, 0, 0.2, 1),
    box-shadow 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}

.netease-mini-player::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background:
    radial-gradient(circle at 15% 20%, var(--flow-color-1) 0%, transparent 60%),
    radial-gradient(circle at 80% 25%, var(--flow-color-2) 0%, transparent 60%),
    radial-gradient(circle at 30% 85%, var(--flow-color-3) 0%, transparent 60%),
    radial-gradient(circle at 10% 75%, var(--flow-color-4) 0%, transparent 55%),
    radial-gradient(circle at 85% 80%, var(--flow-color-5) 0%, transparent 55%);
  opacity: var(--flow-opacity);
  background-size: 220% 220%, 220% 220%, 220% 220%, 220% 220%, 220% 220%;
  background-position: 0% 0%, 100% 0%, 0% 100%, 20% 80%, 80% 20%;
  filter: saturate(1.02) brightness(1.01);
  transform: scale(1);
  animation: flow-breathe var(--flow-speed) ease-in-out infinite;
  animation-play-state: paused;
}

.netease-mini-player.player-playing::before {
  animation-play-state: running;
}

@keyframes flow-breathe {
  0% {
    background-position: 0% 0%, 100% 0%, 0% 100%, 20% 80%, 80% 20%;
    transform: scale(1);
    filter: saturate(1.02) brightness(1.01);
  }

  50% {
    background-position: 100% 50%, 0% 100%, 50% 0%, 35% 65%, 65% 35%;
    transform: scale(1.03);
    filter: saturate(1.15) brightness(1.06);
  }

  100% {
    background-position: 0% 100%, 100% 50%, 100% 0%, 20% 80%, 80% 20%;
    transform: scale(1);
    filter: saturate(1.02) brightness(1.01);
  }
}

.netease-mini-player.minimized {
  width: 80px;
  height: 80px;
  border-radius: 50%;
  padding: 0;
  background: radial-gradient(120px 120px at 30% 30%, rgba(255, 138, 80, 0.25), transparent 60%),
    radial-gradient(120px 120px at 70% 70%, rgba(0, 210, 255, 0.22), transparent 60%),
    linear-gradient(135deg, #151515, #1e1e1e);
  box-shadow:
    4px 4px 12px rgba(0, 0, 0, 0.4),
    -2px -2px 8px rgba(255, 255, 255, 0.1),
    inset 0 0 20px rgba(0, 0, 0, 0.3);
}

.netease-mini-player.minimized .song-content,
.netease-mini-player.minimized .controls,
.netease-mini-player.minimized .playlist-container {
  opacity: 0;
  visibility: hidden;
  transition:
    opacity 0.3s ease,
    visibility 0.3s ease;
}

.netease-mini-player.minimized .player-bottom {
  opacity: 0;
  visibility: hidden;
  transition:
    opacity 0.3s ease,
    visibility 0.3s ease;
}

.netease-mini-player.minimized .minimize-btn {
  opacity: 1 !important;
  visibility: visible !important;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 1000;
  background: rgba(0, 0, 0, 0.7);
  border-radius: 50%;
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  transition: all 0.3s ease;
}

.netease-mini-player.minimized .minimize-btn:hover {
  background: rgba(0, 0, 0, 0.9);
  transform: translate(-50%, -50%) scale(1.1);
}

.netease-mini-player .song-content,
.netease-mini-player .controls,
.netease-mini-player .player-bottom {
  opacity: 1;
  visibility: visible;
  transition:
    opacity 0.3s ease 0.2s,
    visibility 0.3s ease 0.2s;
}

.netease-mini-player.minimized .album-cover-container {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  border-radius: 50%;
  box-shadow: none;
  transition:
    width 0.5s cubic-bezier(0.4, 0, 0.2, 1),
    height 0.5s cubic-bezier(0.4, 0, 0.2, 1),
    top 0.5s cubic-bezier(0.4, 0, 0.2, 1),
    left 0.5s cubic-bezier(0.4, 0, 0.2, 1),
    box-shadow 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}

.netease-mini-player.minimized .album-cover {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  filter: brightness(0.8) contrast(1.1);
  transition:
    width 0.5s cubic-bezier(0.4, 0, 0.2, 1),
    height 0.5s cubic-bezier(0.4, 0, 0.2, 1),
    filter 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}

.netease-mini-player.minimized .vinyl-overlay {
  background: radial-gradient(circle at center,
      transparent 15%,
      rgba(0, 0, 0, 0.1) 15%,
      rgba(0, 0, 0, 0.1) 16%,
      transparent 16%,
      transparent 25%,
      rgba(0, 0, 0, 0.15) 25%,
      rgba(0, 0, 0, 0.15) 26%,
      transparent 26%,
      transparent 35%,
      rgba(0, 0, 0, 0.1) 35%,
      rgba(0, 0, 0, 0.1) 36%,
      transparent 36%,
      transparent 45%,
      rgba(0, 0, 0, 0.15) 45%,
      rgba(0, 0, 0, 0.15) 46%,
      transparent 46%);
  box-shadow:
    inset 0 0 15px rgba(0, 0, 0, 0.5),
    inset 0 0 5px rgba(0, 0, 0, 0.8);
  transition:
    background 0.5s cubic-bezier(0.4, 0, 0.2, 1),
    box-shadow 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}

.netease-mini-player.minimized .vinyl-center {
  width: 16px;
  height: 16px;
  background: radial-gradient(circle at 30% 30%,
      #666 0%,
      #333 50%,
      #111 100%);
  box-shadow:
    0 0 3px rgba(0, 0, 0, 0.8),
    inset 1px 1px 2px rgba(255, 255, 255, 0.2);
  border: 1px solid #000;
  transition:
    width 0.5s cubic-bezier(0.4, 0, 0.2, 1),
    height 0.5s cubic-bezier(0.4, 0, 0.2, 1),
    background 0.5s cubic-bezier(0.4, 0, 0.2, 1),
    box-shadow 0.5s cubic-bezier(0.4, 0, 0.2, 1),
    border 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}


.netease-mini-player[data-position="top-left"] {
  position: fixed;
  top: 20px;
  left: 20px;
  z-index: 1000;
}

.netease-mini-player[data-position="top-right"] {
  position: fixed;
  top: 20px;
  right: 20px;
  z-index: 1000;
}

.netease-mini-player[data-position="bottom-left"] {
  position: fixed;
  bottom: 20px;
  left: 20px;
  z-index: 1000;
}

.netease-mini-player[data-position="bottom-right"] {
  position: fixed;
  bottom: 20px;
  right: 20px;
  z-index: 1000;
}

.netease-mini-player[data-position="static"] {
  position: relative;
}

.player-main {
  display: flex;
  align-items: center;
  gap: 12px;
  flex: 1;
}

.album-cover-container {
  width: 60px;
  height: 60px;
  border-radius: 50%;
  position: relative;
  flex-shrink: 0;
  background: var(--secondary-bg);
  box-shadow:
    inset 2px 2px 4px var(--shadow-dark),
    inset -2px -2px 4px var(--shadow-light),
    2px 2px 6px rgba(0, 0, 0, 0.2),
    -1px -1px 3px rgba(255, 255, 255, 0.1);
  overflow: hidden;
  cursor: pointer;
  border: 2px solid rgba(0, 0, 0, 0.1);
}

.album-cover-container::after {
  content: '';
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  pointer-events: none;
  background: conic-gradient(from 0deg, var(--accent-color), var(--accent-color-2), var(--accent-color-3), var(--accent-color));
  opacity: 0.18;
  filter: blur(6px) saturate(1.05);
}

.album-cover {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  transition: var(--transition);
  filter: brightness(0.9) contrast(1.1);
}

.vinyl-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: radial-gradient(circle at center,
      transparent 12%,
      rgba(0, 0, 0, 0.8) 12%,
      rgba(0, 0, 0, 0.8) 15%,
      transparent 15%,
      transparent 20%,
      rgba(0, 0, 0, 0.15) 20%,
      rgba(0, 0, 0, 0.15) 20.5%,
      transparent 20.5%,
      transparent 25%,
      rgba(0, 0, 0, 0.1) 25%,
      rgba(0, 0, 0, 0.1) 25.5%,
      transparent 25.5%,
      transparent 30%,
      rgba(0, 0, 0, 0.08) 30%,
      rgba(0, 0, 0, 0.08) 30.5%,
      transparent 30.5%,
      transparent 35%,
      rgba(0, 0, 0, 0.06) 35%,
      rgba(0, 0, 0, 0.06) 35.5%,
      transparent 35.5%,
      transparent 40%,
      rgba(0, 0, 0, 0.05) 40%,
      rgba(0, 0, 0, 0.05) 40.5%,
      transparent 40.5%,
      transparent 85%,
      rgba(0, 0, 0, 0.1) 85%,
      rgba(0, 0, 0, 0.2) 100%);
  pointer-events: none;
  box-shadow:
    inset 0 0 10px rgba(0, 0, 0, 0.3),
    inset 0 0 20px rgba(0, 0, 0, 0.1);
}

.vinyl-center {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 12px;
  height: 12px;
  background: radial-gradient(circle at center,
      #1a1a1a 0%,
      #333 50%,
      #1a1a1a 100%);
  border-radius: 50%;
  transform: translate(-50%, -50%);
  box-shadow:
    0 0 4px rgba(0, 0, 0, 0.5),
    inset 0 0 3px rgba(0, 0, 0, 0.8),
    inset 0 0 1px rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.1);
}

@keyframes vinyl-spin {
  from {
    transform: rotate(0deg);
  }

  to {
    transform: rotate(360deg);
  }
}

.album-cover {
  animation: vinyl-spin 6s linear infinite;
  animation-play-state: paused;
}

.album-cover.playing {
  animation-play-state: running;
}

.vinyl-overlay {
  animation: vinyl-spin 3s linear infinite;
  animation-play-state: paused;
}

.album-cover.playing+.vinyl-overlay {
  animation-play-state: running;
}

.song-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.song-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.song-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.2;
  transition: var(--theme-transition);
}

.song-artist {
  font-size: 12px;
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.2;
  transition: var(--theme-transition);
}

.lyrics-container {
  min-height: 20px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.lyrics-container.hidden {
  display: none;
}

.lyric-line {
  font-size: 11px;
  color: #5697e3;
  line-height: 1.4;
  transition: var(--transition);
  opacity: 0.8;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  width: 100%;
  transition: opacity 0.2s ease-in-out, transform 0.2s ease-in-out;
}

.lyric-line.current {
  color: #5697e3;
  font-weight: 600;
  opacity: 1;
  text-shadow: 0 0 8px rgba(86, 151, 227, 0.3);
  animation: lyric-glow 2s ease-in-out infinite alternate;

  animation: none;
  opacity: 0;
  transform: translateY(10px);
  animation: lyric-fade-in 0.2s ease-out forwards;
}

.lyric-line.translation {
  font-size: 10px;
  color: var(--text-muted);
  opacity: 0.7;
  margin-top: 1px;
  transition: var(--theme-transition);
}

.lyric-line.translation.current {
  color: var(--text-secondary);
  opacity: 0.9;
  font-weight: 500;
  transition: var(--theme-transition);
}

@keyframes lyric-fade-in {
  from {
    opacity: 0;
    transform: translateY(10px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes lyric-glow {
  0% {
    text-shadow: 0 0 8px rgba(86, 151, 227, 0.3);
  }

  100% {
    text-shadow: 0 0 12px rgba(86, 151, 227, 0.5);
  }
}

.lyric-line.word-lyric {
  position: relative;
  display: inline-block;
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
}

.lyric-word-line {
  position: relative;
  display: inline-block;
  transition: transform 0.1s ease-out;
}

.lyric-line.word-lyric-active {
  -webkit-mask: linear-gradient(90deg, #000 0%, #000 var(--line-progress, 0%), transparent var(--line-progress, 0%));
  mask: linear-gradient(90deg, #000 0%, #000 var(--line-progress, 0%), transparent var(--line-progress, 0%));
}

.netease-mini-player[data-theme="dark"] .lyric-line.word-lyric-active {
  text-shadow: 0 0 8px rgba(255, 165, 0, 0.7);
}

.lyric-line.word-lyric::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  width: var(--line-progress, 0%);
  height: 2px;
  background: var(--accent-gradient);
  border-radius: 1px;
  transition: width 0.1s ease;
}

.controls {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}

.control-btn {
  width: 32px;
  height: 32px;
  border: none;
  background: var(--primary-bg);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: var(--transition);
  box-shadow:
    2px 2px 4px var(--shadow-dark),
    -2px -2px 4px var(--shadow-light);
  font-size: 12px;
  color: var(--text-primary);
  position: relative;
}

.control-btn:hover {
  box-shadow:
    inset 1px 1px 2px var(--shadow-dark),
    inset -1px -1px 2px var(--shadow-light);
  background: var(--secondary-bg);
}

.play-btn {
  width: 30px;
  height: 30px;
  font-size: 14px;
  background: var(--primary-bg);
  box-shadow:
    2px 2px 4px var(--shadow-dark),
    -2px -2px 4px var(--shadow-light);
}

.play-icon,
.pause-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  color: var(--text-primary);
  transition: var(--transition);
}

.play-btn:hover {
  background: var(--secondary-bg);
  box-shadow:
    inset 1px 1px 2px var(--shadow-dark),
    inset -1px -1px 2px var(--shadow-light);
}

.control-btn:active {
  box-shadow:
    inset 2px 2px 4px var(--shadow-dark),
    inset -2px -2px 4px var(--shadow-light);
  background: var(--accent-gradient);
  color: white;
}

.control-btn:active span {
  color: white;
}

.play-icon {
  margin-left: 2px;
}

.volume-icon {
  font-size: 10px;
  color: var(--text-secondary);
  margin-right: 2px;
  flex-shrink: 0;
}

.player-bottom {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 8px;
  width: 100%;
}

.progress-container {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 1;
  max-width: var(--progress-max, 60%);
}

.netease-mini-player[data-embed="true"] .progress-container {
  max-width: calc(100% - 60px);
  flex: 1;
}

.time-display {
  font-size: 10px;
  color: var(--text-muted);
  white-space: nowrap;
  min-width: 35px;
  text-align: center;
}

.progress-bar-container {
  flex: 1;
  height: 4px;
  background: var(--secondary-bg);
  border-radius: 2px;
  position: relative;
  cursor: pointer;
  box-shadow:
    inset 1px 1px 2px var(--shadow-dark),
    inset -1px -1px 2px var(--shadow-light);
}

.progress-bar {
  height: 100%;
  background: var(--accent-gradient);
  border-radius: 2px;
  width: 0%;
  transition: width 0.1s ease;
  position: relative;
}

.progress-bar::after {
  content: '';
  position: absolute;
  right: -2px;
  top: 50%;
  width: 8px;
  /* 和顶部滚动样式冲突 ,暂时注释 */
  /* height: 8px;
  background: var(--accent-color-3); */
  border-radius: 50%;
  transform: translateY(-50%);
  box-shadow:
    0 0 8px rgba(0, 210, 255, 0.6),
    1px 1px 2px var(--shadow-dark),
    -1px -1px 2px var(--shadow-light);
}

.bottom-controls {
  display: flex;
  align-items: center;
  gap: 8px;
  justify-content: flex-end;
  flex-shrink: 0;
  min-width: 0;
}

.volume-container {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-shrink: 0;
}

.volume-slider-container {
  display: flex;
  align-items: center;
  width: 40px;
}

.volume-slider {
  flex: 1;
  height: 3px;
  background: var(--secondary-bg);
  border-radius: 2px;
  position: relative;
  cursor: pointer;
  box-shadow:
    inset 1px 1px 2px var(--shadow-dark),
    inset -1px -1px 2px var(--shadow-light);
}

.volume-bar {
  height: 100%;
  background: var(--accent-color);
  border-radius: 2px;
  width: 70%;
  transition: width 0.1s ease;
}

.netease-mini-player svg {
  width: 100%;
  height: 100%;
  fill: currentColor;
  display: block;
}

.control-btn svg {
  width: 18px;
  height: 18px;
}

.feature-btn svg {
  width: 16px;
  height: 16px;
}

.volume-icon svg {
  width: 14px;
  height: 14px;
}

.play-btn svg {
  width: 22px;
  height: 22px;
  margin-left: 2px;
}

.play-btn .pause-icon svg {
  margin-left: 0;
}

.control-btn,
.feature-btn {
  font-size: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.minimize-btn svg {
  width: 18px;
  height: 18px;
}

.sr-visually-hidden {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0 0 0 0) !important;
  clip-path: inset(50%) !important;
  white-space: nowrap !important;
  border: 0 !important;
  padding: 0 !important;
}

.netease-mini-player.mobile-env .volume-container {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
  padding: 0;
  opacity: 0;
  pointer-events: none;
}

.netease-mini-player.mobile-env .progress-container {
  --progress-max: calc(60% + var(--volume-total-width, 60px));
}

.netease-mini-player.mobile-env[data-embed="true"] .progress-container {
  max-width: calc(100% - 60px + var(--volume-total-width, 60px));
}

@media (hover: none) and (pointer: coarse) {
  .netease-mini-player.mobile-env .bottom-controls {
    gap: 10px;
  }
}

.feature-btn {
  width: 20px;
  height: 20px;
  border: none;
  background: transparent;
  cursor: pointer;
  color: var(--text-muted);
  transition: var(--transition);
  font-size: 11px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.feature-btn:hover {
  color: var(--accent-color);
}

.feature-btn.active {
  color: var(--accent-color);
}

.netease-mini-player[data-embed="true"] .list-btn {
  display: none !important;
}

.netease-mini-player[data-embed="true"] .minimize-btn {
  display: none !important;
}

.netease-mini-player[data-position="static"] .minimize-btn {
  display: none !important;
}

.netease-mini-player[data-embed="true"] .prev-btn,
.netease-mini-player[data-embed="true"] .next-btn {
  display: none !important;
}

.netease-mini-player[data-embed="true"] .playlist-container {
  display: none !important;
}

.netease-mini-player-embed .list-btn,
.netease-mini-player-embed .minimize-btn,
.netease-mini-player-embed .prev-btn,
.netease-mini-player-embed .next-btn {
  display: none !important;
}

.netease-mini-player-embed .playlist-container {
  display: none !important;
}

.playlist-container {
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  background: var(--primary-bg);
  border-radius: var(--border-radius);
  box-shadow:
    4px 4px 8px var(--shadow-dark),
    -4px -4px 8px var(--shadow-light);
  max-height: 200px;
  overflow: hidden;
  z-index: 1001;
  opacity: 0;
  transform: translateY(-10px);
  visibility: hidden;
  transition: all 0.3s ease;
  margin-top: 8px;
}

.playlist-container::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background:
    radial-gradient(circle at 20% 15%, var(--flow-color-1) 0%, transparent 60%),
    radial-gradient(circle at 75% 30%, var(--flow-color-2) 0%, transparent 55%),
    radial-gradient(circle at 35% 85%, var(--flow-color-3) 0%, transparent 55%),
    radial-gradient(circle at 25% 70%, var(--flow-color-4) 0%, transparent 50%),
    radial-gradient(circle at 85% 75%, var(--flow-color-5) 0%, transparent 50%);
  opacity: var(--playlist-flow-opacity);
  background-size: 220% 220%, 220% 220%, 220% 220%, 220% 220%, 220% 220%;
  background-position: 0% 0%, 100% 0%, 0% 100%, 20% 80%, 80% 20%;
  filter: saturate(1.02) brightness(1.01);
  transform: scale(1);
  animation: flow-breathe var(--flow-speed) ease-in-out infinite;
  animation-play-state: paused;
}

.netease-mini-player.player-playing .playlist-container::before {
  animation-play-state: running;
}

.playlist-container.expand-up {
  top: auto;
  bottom: 100%;
  margin-top: 0;
  margin-bottom: 8px;
  transform: translateY(10px);
}

.playlist-container.expand-up.show {
  transform: translateY(0);
}

.playlist-container.show {
  opacity: 1;
  transform: translateY(0);
  visibility: visible;
}

.playlist-content {
  max-height: 200px;
  overflow-y: auto;

  &::-webkit-scrollbar {
    display: none;
  }

  scrollbar-width: none;
}


.playlist-item {
  padding: 8px 12px;
  border-bottom: 1px solid rgba(0, 0, 0, 0.05);
  cursor: pointer;
  transition: var(--transition);
  display: flex;
  align-items: center;
  gap: 8px;
}

.playlist-item:last-child {
  border-bottom: none;
}

.playlist-item:hover {
  background: rgba(255, 107, 53, 0.08);
  box-shadow:
    inset 1px 1px 2px var(--shadow-dark),
    inset -1px -1px 2px var(--shadow-light);
  transform: translateX(2px);
  transition: all 0.2s ease;
}

.playlist-item.active {
  background: rgba(255, 107, 53, 0.15);
  color: var(--accent-color);
  font-weight: 600;
}

.playlist-item-index {
  font-size: 10px;
  color: var(--text-muted);
  min-width: 16px;
  text-align: center;
}

.playlist-item.active .playlist-item-index {
  color: var(--accent-color);
}

.playlist-item-info {
  flex: 1;
  min-width: 0;
}

.playlist-item-name {
  font-size: 11px;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.2;
}

.playlist-item-artist {
  font-size: 10px;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-top: 1px;
}

.playlist-item.active .playlist-item-name,
.playlist-item.active .playlist-item-artist {
  color: var(--accent-color);
}

.loading {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
  font-size: 12px;
}

.loading::after {
  content: '';
  width: 12px;
  height: 12px;
  border: 2px solid var(--secondary-bg);
  border-top: 2px solid var(--accent-color);
  border-radius: 50%;
  animation: spin 1s linear infinite;
  margin-left: 8px;
}

.playlist-item-cover {
  width: 36px;
  height: 36px;
  border-radius: 8px;
  object-fit: cover;
  flex-shrink: 0;
  background: var(--secondary-bg);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}

@keyframes spin {
  0% {
    transform: rotate(0deg);
  }

  100% {
    transform: rotate(360deg);
  }
}

.error {
  color: #ff4757;
  font-size: 12px;
  text-align: center;
}

@media (max-width: 480px) {
  .netease-mini-player {
    width: 100%;
    max-width: 360px;
    height: 100px;
    padding: 8px;
    margin: 0 auto;
  }

  .album-cover-container {
    width: 50px;
    height: 50px;
  }

  .song-title {
    font-size: 12px;
  }

  .song-artist {
    font-size: 10px;
  }

  .lyric-line {
    font-size: 10px;
  }

  .control-btn {
    width: 28px;
    height: 28px;
    font-size: 10px;
  }

  .play-btn {
    width: 32px;
    height: 32px;
    font-size: 12px;
  }

  .time-display {
    font-size: 9px;
  }

  .feature-btn {
    width: 20px;
    height: 20px;
    font-size: 10px;
  }

  .volume-slider-container {
    width: 50px;
  }
}

.netease-mini-player.dragging {
  cursor: grabbing;
  -webkit-user-select: none;
  user-select: none;
  pointer-events: none;
  opacity: 0.8;
  transform: scale(0.95);
  z-index: 9999;
  transition: none;
}

.netease-mini-player {
  opacity: 1;
}

.netease-mini-player.minimized.idle {
  opacity: 0.7;
}

.netease-mini-player.minimized.fading-out {
  animation: player-fade-out var(--opacity-duration-down, 0.6s) var(--opacity-ease-out, cubic-bezier(0.22, 1, 0.36, 1)) forwards;
}

.netease-mini-player.minimized.fading-in {
  animation: player-fade-in var(--opacity-duration-up, 0.25s) var(--opacity-ease-in, cubic-bezier(0.4, 0, 0.2, 1)) forwards;
}

@keyframes player-fade-out {
  from {
    opacity: 1;
  }

  to {
    opacity: 0.7;
  }
}

@keyframes player-fade-in {
  from {
    opacity: 0.7;
  }

  to {
    opacity: 1;
  }
}

.netease-mini-player.minimized.docked-right {
  transform: translateX(calc(50% + var(--dock-gap, 20px)));
}

.netease-mini-player.minimized.docked-left {
  transform: translateX(calc(-50% - var(--dock-gap, 20px)));
}

.netease-mini-player.minimized.fading-out.docked-right {
  animation:
    player-fade-out var(--opacity-duration-down, 0.6s) var(--opacity-ease-out, cubic-bezier(0.22, 1, 0.36, 1)) forwards,
    player-dock-right var(--dock-duration, 0.45s) var(--dock-ease-out, cubic-bezier(0.18, 0.9, 0.2, 1.0)) forwards;
}

.netease-mini-player.minimized.fading-out.docked-left {
  animation:
    player-fade-out var(--opacity-duration-down, 0.6s) var(--opacity-ease-out, cubic-bezier(0.22, 1, 0.36, 1)) forwards,
    player-dock-left var(--dock-duration, 0.45s) var(--dock-ease-out, cubic-bezier(0.18, 0.9, 0.2, 1.0)) forwards;
}

.netease-mini-player.minimized.popping-right {
  animation: player-popout-right var(--popout-duration, 0.28s) var(--popout-ease, cubic-bezier(0.4, 0, 0.2, 1)) forwards;
}

.netease-mini-player.minimized.popping-left {
  animation: player-popout-left var(--popout-duration, 0.28s) var(--popout-ease, cubic-bezier(0.4, 0, 0.2, 1)) forwards;
}

@keyframes player-dock-right {
  from {
    transform: translateX(0);
  }

  to {
    transform: translateX(calc(50% + var(--dock-gap, 20px)));
  }
}

@keyframes player-dock-left {
  from {
    transform: translateX(0);
  }

  to {
    transform: translateX(calc(-50% - var(--dock-gap, 20px)));
  }
}

@keyframes player-popout-right {
  from {
    transform: translateX(calc(50% + var(--dock-gap, 20px)));
  }

  to {
    transform: translateX(0);
  }
}

@keyframes player-popout-left {
  from {
    transform: translateX(calc(-50% - var(--dock-gap, 20px)));
  }

  to {
    transform: translateX(0);
  }
}

.netease-mini-player .feature-btn,
.netease-mini-player .control-btn {
  font-size: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.netease-mini-player .bottom-controls .feature-btn,
.netease-mini-player .volume-icon {
  color: var(--text-primary);
}

.netease-mini-player .control-btn svg {
  width: 18px;
  height: 18px;
  display: block;
  fill: currentColor;
}

.netease-mini-player .play-btn svg {
  width: 20px;
  height: 20px;
}

.netease-mini-player .play-icon {
  margin-left: 0;
}

.netease-mini-player .bottom-controls .feature-btn svg,
.netease-mini-player .volume-icon svg {
  width: 16px;
  height: 16px;
  display: block;
  fill: currentColor;
}

.netease-mini-player .volume-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  font-size: 0;
}

.netease-mini-player .feature-btn {
  width: auto;
  height: auto;
}

.netease-mini-player .bottom-controls {
  gap: 6px;
}

.netease-mini-player .volume-icon svg {
  width: 18px;
  height: 18px;
}

.netease-mini-player.minimized .minimize-btn {
  font-size: 0;
}
</style>

vue

<script setup>
import NeteaseMusicPlayer from "./NeteaseMusicPlayer.vue";
</script>

<template>
  <Teek.Layout>
    <template #layout-top>
      <!-- 全局网易云音乐播放器组件 -->
        <template #layout-bottom>
            <NeteaseMusicPlayer />
        </template>
    </template>
  </Teek.Layout>
</template>