style: 更新主题配色方案为蓝紫调

将全局渐变色从暖红/粉橙主题调整为蓝紫/粉色调,统一卡片、导航栏、页面背景及装饰元素的视觉风格,并重构音乐播放器组件的初始化逻辑
This commit is contained in:
2026-08-07 17:43:34 +08:00
parent 88999c4961
commit 28612006a6
9 changed files with 223 additions and 136 deletions
+105 -67
View File
@@ -1,6 +1,6 @@
<template>
<!-- 准备一个容器用来存放音乐播放器 -->
<div id="aplayer"></div>
<div ref="containerRef" id="aplayer"></div>
</template>
<script setup lang="ts">
@@ -8,81 +8,119 @@
import APlayer from "aplayer"; // 引入音乐插件
import "aplayer/dist/APlayer.min.css"; // 引入音乐插件的样式
// window.Hls = Hls;
const data: any = reactive({
audio: [],
info: {
fixed: true, // 开启吸底模式
// mini: false, // 开启迷你模式
// autoplay: true, // 自动播放(已经没用了)
// theme: '#000', // 主题色
loop: "all", // 音频循环播放, 可选值: 'all', 'one', 'none'
order: "list", // 音频循环顺序, 可选值: 'list', 'random'
preload: "metadata", //预加载,可选值: 'none', 'metadata', 'auto'
volume: 0.5, // 默认音量,可选值: 0-1
mutex: true, // 互斥,默认为true,即不允许多个音频同时播放,当前播放的音频会暂停其他音频
lrcType: 3, // 歌词类型,可选值: 1, 2, 3
},
});
/** 歌单接口 */
interface MusicItem {
title: string;
author: string;
url: string;
pic: string;
lrc: string;
}
/** 歌单来源配置 */
const PLAYLIST_SERVER = "tencent";
const PLAYLIST_ID = "7681108669";
/** 歌单拉取接口(公共 meting API */
const METING_API = `https://meting.mikus.ink/api?server=${PLAYLIST_SERVER}&type=playlist&id=${PLAYLIST_ID}`;
/** APlayer 基础配置 */
const APLAYER_INFO = {
fixed: true, // 开启吸底模式
loop: "all", // 音频循环播放, 可选值: 'all', 'one', 'none'
order: "list", // 音频循环顺序, 可选值: 'list', 'random'
preload: "metadata", // 预加载,可选值: 'none', 'metadata', 'auto'
volume: 0.5, // 默认音量,可选值: 0-1
mutex: true, // 互斥,默认为true,即不允许多个音频同时播放,当前播放的音频会暂停其他音频
lrcType: 3, // 歌词类型,可选值: 1, 2, 3
};
const containerRef = ref<HTMLDivElement | null>(null);
let ap: InstanceType<typeof APlayer> | null = null;
let miniswitcherEl: HTMLElement | null = null;
let listScrollEl: HTMLElement | null = null;
let onClickMiniswitcher: (() => void) | null = null;
let onListWheel: ((e: Event) => void) | null = null;
/** 拉取歌单并解析为 MusicItem[] */
async function fetchPlaylist(): Promise<MusicItem[]> {
const res = await fetch(METING_API);
if (!res.ok) throw new Error(`歌单请求失败: ${res.status}`);
const mlist: MusicItem[] = await res.json();
return mlist;
}
/** 初始化迷你切换按钮的显隐动画(自定义展开/收起效果) */
function setupMiniswitcher() {
miniswitcherEl = document.querySelector("#aplayer > div.aplayer-body > div.aplayer-miniswitcher > button");
const app = document.querySelector<HTMLElement>("#aplayer > div.aplayer-lrc");
const apic = document.querySelector<HTMLElement>("#aplayer div.aplayer-body");
if (!miniswitcherEl || !app || !apic) return;
let expanded = false;
app.style.display = "block";
app.style.transform = "translateY(50px)";
apic.style.transform = "translateX(-66px)";
onClickMiniswitcher = () => {
if (expanded) {
app.style.transform = "translateY(50px)";
ap.lrc?.hide();
ap.list.hide();
apic.style.transform = "translateX(-66px)";
expanded = false;
} else {
app.style.transform = "translateY(0)";
ap.lrc?.show();
apic.style.transform = "translateX(0)";
expanded = true;
}
};
miniswitcherEl.addEventListener("click", onClickMiniswitcher);
}
/** 阻止歌单列表滚轮事件冒泡,避免联动外层滚动 */
function setupListWheelGuard() {
listScrollEl = document.querySelector(".aplayer-list > ol");
if (!listScrollEl) return;
onListWheel = (e: Event) => e.stopPropagation();
listScrollEl.addEventListener("mousewheel", onListWheel);
}
/** 移动端(宽度 < 767)自动收起播放器为迷你模式 */
function applyMobileCollapse() {
const width = document.documentElement.clientWidth;
if (width < 767) miniswitcherEl?.click();
}
onMounted(async () => {
try {
const server = 'tencent'
const gdid = '7681108669'
const res = await fetch(`https://meting.mikus.ink/api?server=${server}&type=playlist&id=${gdid}`)
const mlist: any = await res.json()
data.audio = []
mlist.forEach((i: any) => {
data.audio.push({
title: i.title,
author: i.author,
url: i.url,
pic: i.pic,
lrc: i.lrc,
});
const audio = await fetchPlaylist();
ap = new APlayer({
container: containerRef.value ?? undefined,
audio, // 音乐信息
...APLAYER_INFO, // 其他配置信息
});
// 创建一个音乐播放器实例,并挂载到DOM上,同时进行相关配置
const ap = new APlayer({
container: document.getElementById("aplayer"),
audio: data.audio, // 音乐信息
...data.info, // 其他配置信息
});
const d: HTMLElement | null = document.querySelector("#aplayer > div.aplayer-body > div.aplayer-miniswitcher > button");
let flag = true;
const app: HTMLElement | null = document.querySelector("#aplayer > div.aplayer-lrc");
const apic: HTMLElement | null = document.querySelector("#aplayer div.aplayer-body");
if (!d || !app || !apic) return;
app.style.display = "block";
app.style.transform = "translateY(50px)";
apic.style.transform = "translateX(-66px)";
d.addEventListener("click", () => {
if (flag) {
app.style.transform = "translateY(0)";
ap.lrc.show();
apic.style.transform = "translateX(0)";
flag = false;
} else {
app.style.transform = "translateY(50px)";
ap.lrc.hide();
ap.list.hide();
apic.style.transform = "translateX(-66px)";
flag = true;
}
});
document.querySelector(".aplayer-list > ol")?.addEventListener("mousewheel", (e) => {
e.stopPropagation();
})
// 获取当前屏幕宽度
const width = document.documentElement.clientWidth; // 获取屏幕宽度
if (width < 767) d.click();
setupMiniswitcher();
setupListWheelGuard();
applyMobileCollapse();
} catch (error) {
console.error('音乐列表加载失败:', error)
console.error("音乐列表加载失败:", error);
}
});
onUnmounted(() => {
// 清理事件监听,避免内存泄漏
if (miniswitcherEl && onClickMiniswitcher) {
miniswitcherEl.removeEventListener("click", onClickMiniswitcher);
}
if (listScrollEl && onListWheel) {
listScrollEl.removeEventListener("mousewheel", onListWheel);
}
// 销毁 APlayer 实例
ap?.destroy();
ap = null;
});
</script>
<style lang="less" scoped>
#aplayer {