Files
PC-official/static/js/index.js
DESKTOP-RQ919RC\Pc 5a957acf3f no message
2025-09-12 16:57:43 +08:00

520 lines
19 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: "./static/img/headset-icon.png",
title: "音乐创作",
text: "朴见潮音2024 年成立于广州,是专注 AI 音乐领域的创新工作室。短短一年便跻身于AI音乐浪潮先锋品牌",
},
{
icon: "./static/img/mv-icon.png",
title: "MV创作",
text: "以 AI 技术为核心整合音乐创作、MV 制作、教学培训、发行级重制等业务,为创作者和爱好者打造一站式平台。",
},
{
icon: "./static/img/train-icon.png",
title: "教学培训",
text: "工作室运用多种 AI 工具,突破传统创作局限,支持流行、摇滚等多元风格创作,满足个性化需求。",
},
{
icon: "./static/img/remake-icon.png",
title: "发行级重制",
text: "构建全流程服务体系,从 AI 音乐创作、MV 视觉呈现,到零基础教学,再到发行级重制提升品质,实现作品价值最大化。",
},
];
const audioPlayer = ref(null);
const progress = ref(0); // 播放进度百分比
// 响应式变量存储当前播放时间和总时长
const currentTimeFormatted = ref("00:00");
const durationFormatted = ref("00:00");
// 格式化时间函数:将秒数转换为 MM:SS 格式
const formatTime = (seconds) => {
const mins = Math.floor(seconds / 60);
const secs = Math.floor(seconds % 60);
return `${mins.toString().padStart(2, "0")}:${secs.toString().padStart(2, "0")}`;
};
// 更新进度的函数
const getProgress = () => {
if (!audioPlayer.value) return;
const currentTime = audioPlayer.value.currentTime || 0;
const duration = audioPlayer.value.duration || 0;
const p = duration > 0 ? (currentTime / duration) * 100 : 0;
setProgress(p, audioPlayer.value.src);
progress.value = p;
// 更新时间显示
currentTimeFormatted.value = formatTime(currentTime);
durationFormatted.value = formatTime(duration);
};
const setProgress = (val, src) => {
awardAudioList.value.forEach((item) => {
if (item.playurl == src) item.progress = val;
});
customList.value.forEach((item) => {
if (item.playurl == src) item.progress = val;
});
studentList.value.forEach((item) => {
if (item.playurl == src) item.progress = val;
});
if (zeroOrderStudents.value?.playurl == src) zeroOrderStudents.value["progress"] = val;
};
const introduceRef = ref(null);
const worksRef = ref(null);
const customRef = ref(null);
const studentRef = ref(null);
let pointerIndex = ref(0);
const albumBoxRef = ref(null);
// 点击侧边栏
const changePointer = (index) => {
albumBoxRef.value.scrollTo({ top: 448 * index, behavior: "smooth" });
pointerIndex.value = index;
};
// 向上滚动到上一页
const scrollToPrevious = () => {
let index = pointerIndex.value - 1;
if (index < 0) return;
changePointer(index);
};
// 向下滚动到下一页
const scrollToNext = () => {
let index = pointerIndex.value + 1;
if (index > bannerList.value.length) return;
changePointer(index);
};
// 获取当前在可视窗口中的元素ref
const visibleRef = computed(() => {
const visibleElement = elements.value.find((el) => el.isVisible);
return visibleElement ? visibleElement.ref : null;
});
let bannerList = ref([]);
let awardMVList = ref([]);
let awardAudioList = ref([]);
const init = () => {
ajax("https://pujianchaoyin.com/api/getHomeData").then((res) => {
if (res.code != 200) return;
const data = res.data;
console.log("data", data);
bannerList.value = data.banner;
awardMVList.value = data.awardMVList;
data.awardAudioList.forEach((item, index) => {
item["playurl"] = `https://app.gter.net/image/miniApp/mp3/${index + 1}.mp3`;
});
awardAudioList.value = data.awardAudioList;
customList.value = data.customAudioList;
studentList.value = data.studentList || [];
studentList.value.forEach((item, index) => {
item["order"] = index;
});
zeroOrderStudents.value = studentList.value[0];
nextTick(() => bannerSwiper());
});
};
let bannerSwiperTimer = null;
const bannerSwiper = () => {
bannerSwiperTimer = setTimeout(() => {
let index = pointerIndex.value + 1;
if (index > bannerList.value.length - 1) index = 0;
changePointer(index);
bannerSwiper();
}, 3000);
};
const changeInterval = (type) => {
if (type) clearTimeout(bannerSwiperTimer);
else bannerSwiper();
};
onMounted(() => {
init();
// 添加进度更新事件监听器
if (audioPlayer.value) {
volume.value = audioPlayer.value.volume * 100;
audioPlayer.value.addEventListener("timeupdate", getProgress);
audioPlayer.value.addEventListener("loadedmetadata", getProgress);
}
});
// 组件卸载时清理事件监听器
onUnmounted(() => {
audioPlayer?.value?.removeEventListener("timeupdate", getProgress);
audioPlayer?.value?.removeEventListener("loadedmetadata", getProgress);
});
// 播放 组件状态
let previewState = ref(false);
let art = null;
// 开启播放 MV
const openPreview = (id, poster = "") => {
ajax("https://pujianchaoyin.com/api/getMvDetail", {
id,
}).then((res) => {
if (res.code != 200) return;
const data = res.data;
previewState.value = true;
nextTick(() => {
art = new Artplayer({
container: ".artplayer-app",
url: data.playurl,
autoplay: true,
poster,
fullscreen: true,
});
art.play();
});
});
};
// 关闭播放 MV
const closePreview = () => {
previewState.value = false;
art?.destroy();
art = null;
};
// 快进 和 后退 10秒
const fastForward = (type = "fast") => {
if (!audioPlayer.value) return;
const src = playData.value?.playurl || "";
const area = playData.value?.area || "";
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();
};
let playData = ref(null);
const manageAudio = (src, area) => {
const audio = audioPlayer.value;
closeAll();
nextTick(() => {
if (audio?.src != src) audio.src = src;
audio.play().then(() => {
if (area == "works") {
awardAudioList.value.forEach((item) => {
if (item.playurl == src) {
item["state"] = true;
playData.value = { ...item, area };
}
});
}
if (area == "custom") {
customList.value.forEach((item) => {
if (item.playurl == src) {
item["state"] = true;
playData.value = { ...item, area };
}
});
}
if (area == "student") {
zeroOrderStudents.value["state"] = true;
playData.value = { ...zeroOrderStudents.value, area };
}
});
});
};
// 重新播放
const rePlay = () => {
if (!playData.value) return;
const { playurl, area } = playData.value;
manageAudio(playurl, area);
};
const closeAll = () => {
audioPlayer.value.pause();
awardAudioList.value.forEach((item) => {
item["state"] = false;
});
customList.value.forEach((item) => {
item["state"] = false;
});
zeroOrderStudents.value["state"] = false;
console.log("playData", playData);
playData.value && (playData.value.state = false);
};
let customList = ref([]);
let studentIndex = ref(0);
let zeroOrderStudents = ref({});
let studentList = ref([]);
const cutStudent = (order) => {
// 找到目标元素和第一个元素
const [target, first] = [studentList.value.find((item) => item.order == order), studentList.value.find((item) => item.order == 0)];
// 交换order值
if (target && first && target !== first) [target.order, first.order] = [first.order, target.order];
console.log("studentList.value", studentList.value);
zeroOrderStudents.value = target;
target.playurl ? manageAudio(target.playurl, "student") : getPlayUrl(0, "student");
};
// 响应式数据:音量值、是否静音
const volume = ref(84);
const isMuted = ref(false);
// 切换静音状态的方法
const toggleMute = () => {
isMuted.value = !isMuted.value;
if (audioPlayer.value) {
audioPlayer.value.muted = isMuted.value;
}
};
// 计算并设置音量百分比
const setVolumePercentage = (percentage) => {
// 确保百分比在0-100之间
const volumePercent = Math.max(0, Math.min(100, percentage));
volume.value = Math.abs(~~volumePercent);
// 设置音频元素的音量范围是0-1
if (audioPlayer.value) audioPlayer.value.volume = volume.value / 100;
};
// 处理音量进度条点击
const handleVolumeClick = (event) => {
// 获取进度条元素
const progressBar = event.currentTarget;
const rect = progressBar.getBoundingClientRect();
// 计算点击位置相对于进度条的比例
// 因为是垂直进度条所以用clientY
const clickPosition = rect.bottom - event.clientY;
const percentage = (clickPosition / rect.height) * 100;
console.log("percentage", percentage);
setVolumePercentage(percentage);
};
let volumeShow = ref(false);
// 处理音量进度条拖拽
let isDragging = false;
const startDrag = (event) => {
isDragging = true;
handleVolumeDrag(event);
// 添加事件监听器
document.addEventListener("mousemove", handleVolumeDrag);
document.addEventListener("mouseup", stopDrag);
};
const handleVolumeDrag = (event) => {
if (!isDragging) return;
// 获取音量进度条元素
const progressBar = document.querySelector(".sound-control .progress");
if (!progressBar) return;
const rect = progressBar.getBoundingClientRect();
// 计算拖拽位置相对于进度条的比例
let dragPosition = rect.bottom - event.clientY;
// 限制在进度条范围内
dragPosition = Math.max(0, Math.min(dragPosition, rect.height));
const percentage = (dragPosition / rect.height) * 100;
setVolumePercentage(percentage);
};
const stopDrag = () => {
isDragging = false;
document.removeEventListener("mousemove", handleVolumeDrag);
document.removeEventListener("mouseup", stopDrag);
};
const handleVolumeShow = () => (volumeShow.value = true);
const handleVolumeHide = () => (volumeShow.value = false);
onUnmounted(() => {
// 确保移除所有拖拽相关事件
document.removeEventListener("mousemove", handleVolumeDrag);
document.removeEventListener("mouseup", stopDrag);
document.removeEventListener("mousemove", handleBarDragBottomDrag);
document.removeEventListener("mouseup", stopBarDragBottom);
});
const ajax = (url, data = {}) => {
if (["localhost", "127.0.0.1"].includes(location.hostname)) data["authorization"] = "3338bf6a2e53dda872da3664a2560b25";
return new Promise(function (resolve, reject) {
axios
.post(url, data, {
emulateJSON: true,
withCredentials: true,
})
.then(function (res) {
var data = typeof res.data == "string" ? JSON.parse(res.data) : res.data;
resolve(data);
});
});
};
const ajaxget = (url, data) => {
if (!data) data = {};
if (["localhost", "127.0.0.1"].includes(location.hostname)) data["authorization"] = "3338bf6a2e53dda872da3664a2560b25";
return new Promise((resolve, reject) => {
axios
.get(url, {
emulateJSON: true,
withCredentials: true,
})
.then((res) => {
var data = typeof res.data == "string" ? JSON.parse(res.data) : res.data;
resolve(data);
});
});
};
// 处理音量进度条拖拽
let isBarBottomDragging = false;
const startBarDragBottom = (event) => {
isBarBottomDragging = true;
handleBarDragBottomDrag(event);
// 添加事件监听器
document.addEventListener("mousemove", handleBarDragBottomDrag);
document.addEventListener("mouseup", stopBarDragBottom);
};
const stopBarDragBottom = () => {
isBarBottomDragging = false;
document.removeEventListener("mousemove", handleBarDragBottomDrag);
document.removeEventListener("mouseup", stopBarDragBottom);
};
const handleBarDragBottomClick = (event) => {
// 获取进度条元素
const progressBar = event.currentTarget;
const rect = progressBar.getBoundingClientRect();
const clickPosition = event.clientX - rect.left;
const percentage = clickPosition / rect.width;
// 限制百分比在0-100之间
const clampedPercentage = Math.max(0, Math.min(100, percentage));
updatePlay(clampedPercentage);
};
const handleBarDragBottomDrag = (event) => {
if (!isBarBottomDragging) return;
// 获取音量进度条元素
const progressBar = document.querySelector(".bottom-play .middle .progress-bar");
if (!progressBar) return;
const rect = progressBar.getBoundingClientRect();
// 计算拖拽位置相对于进度条的比例
let dragPosition = event.clientX - rect.left;
// 限制在进度条范围内
dragPosition = Math.max(0, Math.min(dragPosition, rect.width));
const percentage = dragPosition / rect.width;
updatePlay(percentage);
};
const updatePlay = (percentage) => {
if (!audioPlayer.value) return;
const duration = audioPlayer.value.duration || 0;
let newTime = duration * percentage;
newTime = Math.max(0, Math.min(duration, newTime));
audioPlayer.value.currentTime = newTime;
getProgress();
};
const getPlayUrl = (index, area) => {
console.log("index", index);
let id = null;
if (area == "student") {
const item = zeroOrderStudents.value;
console.log("item", item.id);
id = item.id;
}
ajax("https://pujianchaoyin.com/api/getMusicDetail", {
id,
}).then((res) => {
if (res.code != 200) return;
const data = res.data;
console.log("data", data);
zeroOrderStudents.value = { ...data, ...zeroOrderStudents.value };
manageAudio(data.playurl, area);
console.log(zeroOrderStudents.value, "zeroOrderStudents");
});
};
const cutSong = (type, order) => {
const listLength = studentList.value.length;
let newOrder = 0;
if (type === "up") {
// 上一首order减1如果小于0则设置为列表最后一个元素的order
newOrder = order - 1 < 0 ? listLength - 1 : order - 1;
} else if (type === "down") {
// 下一首order加1如果大于等于列表长度则设置为0
newOrder = order + 1 >= listLength ? 0 : order + 1;
}
cutStudent(newOrder);
};
return { cutSong, getPlayUrl, handleBarDragBottomClick, startBarDragBottom, volumeShow, handleVolumeHide, handleVolumeShow, zeroOrderStudents, rePlay, playData, awardAudioList, changeInterval, awardMVList, bannerList, albumBoxRef, volume, handleVolumeClick, handleVolumeDrag, startDrag, stopDrag, toggleMute, isMuted, volume, cutStudent, studentList, studentIndex, scrollToPrevious, scrollToNext, changePointer, pointerIndex, visibleRef, studentRef, customRef, formatTime, currentTimeFormatted, durationFormatted, worksRef, introduceRef, customList, closeAll, manageAudio, progress, closePreview, openPreview, previewState, audioPlayer, trait, fastForward };
},
}).mount("#appIndex");