Files
PC-official/js/index.js
DESKTOP-RQ919RC\Pc 3d380d82de feat: 新增音频播放器功能及MV预览组件
style: 优化页面布局及样式细节

refactor: 重构音频播放逻辑与进度条控制

docs: 更新README说明音频播放功能

test: 添加音频播放器交互测试用例
2025-09-10 19:00:23 +08:00

193 lines
7.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const { createApp, ref, onMounted, nextTick, onUnmounted, computed } = Vue;
const search = createApp({
setup() {
const trait = [
{
icon: "./img/headset-icon.png",
title: "音乐创作",
text: "朴见潮音2024 年成立于广州,是专注 AI 音乐领域的创新工作室。短短一年便跻身于AI音乐浪潮先锋品牌",
},
{
icon: "./img/mv-icon.png",
title: "MV创作",
text: "以 AI 技术为核心整合音乐创作、MV 制作、教学培训、发行级重制等业务,为创作者和爱好者打造一站式平台。",
},
{
icon: "./img/train-icon.png",
title: "教学培训",
text: "工作室运用多种 AI 工具,突破传统创作局限,支持流行、摇滚等多元风格创作,满足个性化需求。",
},
{
icon: "./img/remake-icon.png",
title: "发行级重制",
text: "构建全流程服务体系,从 AI 音乐创作、MV 视觉呈现,到零基础教学,再到发行级重制提升品质,实现作品价值最大化。",
},
];
const text = `中国AIGC产业联盟AIGCxChina
温州市社科联
温州市新闻媒体中心
第一届AI音乐春晚 正选节目`;
const audioPlayer = ref(null);
const progress = ref(20); // 播放进度百分比
// 更新进度的函数
const getProgress = () => {
if (!audioPlayer.value) return;
const currentTime = audioPlayer.value.currentTime || 0;
const duration = audioPlayer.value.duration || 0;
const progress = duration > 0 ? (currentTime / duration) * 100 : 0;
setProgress(progress, audioPlayer.value.src);
};
const setProgress = (val, src) => {
audioList.value.forEach((item) => {
if (item.url === src) item.progress = val;
});
};
onMounted(() => {
// 添加进度更新事件监听器
if (audioPlayer.value) {
audioPlayer.value.addEventListener("timeupdate", getProgress);
audioPlayer.value.addEventListener("loadedmetadata", getProgress);
}
});
// 组件卸载时清理事件监听器
onUnmounted(() => {
audioPlayer?.value?.removeEventListener("timeupdate", getProgress);
audioPlayer?.value?.removeEventListener("loadedmetadata", getProgress);
});
// 头部播放状态
let audioHeadState = ref(false);
// 头部播放 - 开启
const playHead = () => {
closeAll();
nextTick(() => {
audioPlayer.value.src = "./mp3/1.MP3";
audioPlayer.value.play().then(() => (audioHeadState.value = true));
});
};
// 头部播放 - 暂停
const pauseHead = () => {
audioPlayer.value.pause();
audioHeadState.value = false;
};
// 播放 组件状态
let previewState = ref(false);
let art = null;
// 开启播放 MV
const openPreview = () => {
previewState.value = true;
nextTick(() => {
art = new Artplayer({
container: ".artplayer-app",
url: "https://o.x-php.com/Zvt57TuJSUvkyhw-xG7Y2l-c-JoqdX_qqsgFptxhcq_cQnrlc6Z1CwMUBq_D-81qNDQyOQ~~",
autoplay: true,
poster: "https://o.x-php.com/thumb/UHkZOgUVDvP9z7rPV2rT1kE22Zf1QEiLggt9OPnf5hC7a-QU5l8VTqiP5awMLv2DMEUiOUl03dK1PW0Yzf8ZPfpa7ZTTgV-PZGNjZQ~~",
});
art.play();
});
};
// 关闭播放 MV
const closePreview = () => {
previewState.value = false;
art?.destroy();
art = null;
};
let audioList = ref([
{
url: "https://app.gter.net/image/miniApp/mp3/1.mp3",
},
{
url: "https://app.gter.net/image/miniApp/mp3/2.mp3",
},
{
url: "https://app.gter.net/image/miniApp/mp3/3.mp3",
},
{
url: "https://app.gter.net/image/miniApp/mp3/4.mp3",
},
]);
const playAudio = (index) => {
closeAll();
nextTick(() => {
let target = audioList.value[index];
const url = target.url;
if (audioPlayer.value?.src != url) audioPlayer.value.src = url;
audioPlayer.value.play().then(() => {
target["state"] = true;
});
});
};
const pauseAudio = (index) => {
let target = audioList.value[index];
target["state"] = false;
audioPlayer.value.pause();
};
// 快进 和 后退 10秒
const fastForward = (type = "fast", src, area) => {
if (!audioPlayer.value) return;
console.log("src", src, "audioPlayer", audioPlayer.value);
if (audioPlayer.value.src != src) {
manageAudio(src, area);
return;
}
let currentTime = audioPlayer.value.currentTime || 0;
const duration = audioPlayer.value.duration || 0;
let newTime = 0;
if (type == "fast") newTime = Math.min(currentTime + 10, duration);
else newTime = Math.max(currentTime - 10, 0);
audioPlayer.value.currentTime = newTime;
getProgress();
};
const manageAudio = (src, area) => {
console.log("src", src, "area", area);
const audio = audioPlayer.value;
console.log("audio", audio.paused);
closeAll();
if (area == "head") {
nextTick(() => {
if (audio?.src != src) audio.src = src;
audio.play().then(() => (audioHeadState.value = true));
});
}
if (area == "works") {
nextTick(() => {
if (audio?.src != src) audio.src = src;
audio.play().then(() => {
audioList.value.forEach((item) => {
if (item.url == src) item["state"] = true;
});
});
});
}
};
const closeAll = () => {
audioPlayer.value.pause();
audioHeadState.value = false;
audioList.value.forEach((item) => {
item["state"] = false;
});
};
return { closeAll, manageAudio, progress, pauseAudio, playAudio, audioList, closePreview, openPreview, previewState, audioHeadState, pauseHead, playHead, audioPlayer, text, trait, fastForward };
},
}).mount("#appIndex");