refactor(播放器): 优化音频播放逻辑和学生切换功能

- 重构音频播放管理逻辑,简化播放状态控制
- 改进学生切换功能,使用索引代替顺序号
- 移除冗余代码,优化音量控制实现
- 调整CSS布局样式,增强页面展示效果
This commit is contained in:
DESKTOP-RQ919RC\Pc
2025-09-12 18:59:47 +08:00
parent 5a957acf3f
commit 35e3a11427
4 changed files with 51 additions and 62 deletions

View File

@@ -57,7 +57,7 @@
<img class="bj bj1" src="./static/img/album-bj1.svg" />
<img class="bj bj2" src="./static/img/album-bj2.svg" />
<div class="album-box" ref="albumBoxRef">
<div class="item" v-for="(item, index) in bannerList" :key="index" @click="openPreview(item.id, item.img)">
<div class="item" v-for="(item, index) in bannerList" :key="index" @click="openPreview(item.id)">
<img class="img" :src="item.img" />
<img class="bj bj3" src="./static/img/album-bj3.svg" />
<img class="bj bj4" src="./static/img/album-bj4.png" />
@@ -68,7 +68,7 @@
</div>
</div>
<div class="trait flexflex mar1200">
<div class="item flexflex flex1" v-for="(item, index) in trait" :key="index">
<div class="item flexflex" v-for="(item, index) in trait" :key="index">
<img class="icon" :src="item.icon" />
<div class="title">{{ item.title }}</div>
<div class="text">{{ item.text }}</div>
@@ -99,7 +99,7 @@
<div class="time">{{ item.date }}</div>
</div>
<div class="media" @click="openPreview(item.id, item.img)">
<div class="media" @click="openPreview(item.id)">
<img class="img" :src="item.img" />
<img class="play" src="./static/img/play-white-icon.svg" />
</div>
@@ -119,7 +119,7 @@
<div class="name">{{ item.title }}</div>
<div class="subtitle">{{ item.desc }}</div>
<div class="time">{{ item.date }}</div>
<div class="progress-bar flexacenter">
<div class="progress-bar flexacenter" @click="handleBarDragBottomClick">
<div class="bar white" :style="{ width: item.progress + '%' }"></div>
<div class="bar black flex1"></div>
</div>
@@ -145,7 +145,7 @@
<div class="info flexflex">
<div class="name">{{ item.title }}</div>
<div class="lyric">{{ item.desc }}</div>
<div class="progress-bar flexacenter">
<div class="progress-bar flexacenter" @click="handleBarDragBottomClick">
<div class="bar white" :style="{ width: item.progress + '%' }"></div>
<div class="bar black flex1"></div>
</div>
@@ -172,7 +172,7 @@
<div class="student-box flexflex">
<img class="title" src="./static/img/student-title.png" alt="" />
<div class="list flexacenter">
<img class="img" :class="[`img${ item.order }`]" v-for="(item, index) in studentList" :src="item.img" :key="index" @click="cutStudent(item.order)" />
<img class="img" :class="[`img${ item.order }`]" v-for="(item, index) in studentList" :src="item.img" :key="index" @click="cutStudent(index, item.order)" />
</div>
<div class="name">《{{ zeroOrderStudents.title }}》</div>
<div class="info flexacenter">
@@ -180,7 +180,7 @@
{{ zeroOrderStudents.name }} | {{ zeroOrderStudents.age }}岁 | {{ zeroOrderStudents.city }}
</div>
<div class="progress-bar flexacenter">
<div class="progress-bar flexacenter" @click="handleBarDragBottomClick">
<div class="bar white" :style="{ width: zeroOrderStudents.progress + '%' }"></div>
<div class="bar black flex1"></div>
</div>

View File

@@ -224,6 +224,7 @@
.content .introduce .trait {
background-color: #ffffff;
height: 420px;
justify-content: space-between;
}
.content .introduce .trait .item {
padding-top: 98px;
@@ -244,7 +245,7 @@
margin-bottom: 42px;
}
.content .introduce .trait .item .text {
width: 266px;
width: 270px;
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
font-weight: 400;
font-style: normal;

View File

@@ -255,7 +255,7 @@
.trait {
background-color: #ffffff;
height: 420px;
justify-content: space-between;
.item {
padding-top: 98px;
flex-direction: column;
@@ -276,7 +276,7 @@
}
.text {
width: 266px;
width: 270px;
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
font-weight: 400;
font-style: normal;

View File

@@ -64,7 +64,9 @@ const search = createApp({
if (item.playurl == src) item.progress = val;
});
if (zeroOrderStudents.value?.playurl == src) zeroOrderStudents.value["progress"] = val;
if (zeroOrderStudents.value?.playurl == src) {
zeroOrderStudents.value["progress"] = val;
}
};
const introduceRef = ref(null);
@@ -108,6 +110,7 @@ const search = createApp({
const init = () => {
ajax("https://pujianchaoyin.com/api/getHomeData").then((res) => {
// ajax("https://pujianchaoyin.com/index/api").then((res) => {
if (res.code != 200) return;
const data = res.data;
console.log("data", data);
@@ -136,7 +139,9 @@ const search = createApp({
};
let bannerSwiperTimer = null;
// 头部轮播图 定时器
const bannerSwiper = () => {
clearTimeout(bannerSwiperTimer);
bannerSwiperTimer = setTimeout(() => {
let index = pointerIndex.value + 1;
if (index > bannerList.value.length - 1) index = 0;
@@ -145,6 +150,7 @@ const search = createApp({
}, 3000);
};
// 头部轮播图 - 切换 定时器
const changeInterval = (type) => {
if (type) clearTimeout(bannerSwiperTimer);
else bannerSwiper();
@@ -172,7 +178,7 @@ const search = createApp({
let art = null;
// 开启播放 MV
const openPreview = (id, poster = "") => {
const openPreview = (id) => {
ajax("https://pujianchaoyin.com/api/getMvDetail", {
id,
}).then((res) => {
@@ -180,12 +186,13 @@ const search = createApp({
const data = res.data;
previewState.value = true;
nextTick(() => {
art = new Artplayer({
container: ".artplayer-app",
url: data.playurl,
autoplay: true,
poster,
poster: data.img || "",
fullscreen: true,
});
art.play();
@@ -220,13 +227,16 @@ const search = createApp({
getProgress();
};
// 播放 组件数据
let playData = ref(null);
// 管理音频播放
const manageAudio = (src, area) => {
const audio = audioPlayer.value;
closeAll();
nextTick(() => {
if (audio?.src != src) audio.src = src;
console.log("audio", audio);
audio.play().then(() => {
if (area == "works") {
@@ -262,6 +272,7 @@ const search = createApp({
manageAudio(playurl, area);
};
// 关闭所有播放
const closeAll = () => {
audioPlayer.value.pause();
@@ -275,46 +286,44 @@ const search = createApp({
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([]); // 学生数据
let studentIndex = ref(0); // 学生下标
let zeroOrderStudents = ref({}); // 学生 选中播放 数据
let studentList = ref([]);
const cutStudent = (order) => {
// 切换学生 播放
const cutStudent = (index) => {
// 找到目标元素和第一个元素
const [target, first] = [studentList.value.find((item) => item.order == order), studentList.value.find((item) => item.order == 0)];
const [target, first] = [studentList.value[index], 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;
studentIndex.value = index;
target.playurl ? manageAudio(target.playurl, "student") : getPlayUrl(0, "student");
};
// 响应式数据:音量值、是否静音
const volume = ref(84);
const isMuted = ref(false);
// 切换学生 歌曲 上\下一首
const cutSong = (type) => {
const listLength = studentList.value.length;
const index = studentIndex.value;
let newIndex = 0;
// 切换静音状态的方法
const toggleMute = () => {
isMuted.value = !isMuted.value;
if (audioPlayer.value) {
audioPlayer.value.muted = isMuted.value;
}
if (type === "up") newIndex = index - 1 < 0 ? listLength - 1 : index - 1;
else if (type === "down") newIndex = index + 1 >= listLength ? 0 : index + 1;
cutStudent(newIndex);
};
// 响应式数据:音量值、是否静音
let volume = ref(100);
// 计算并设置音量百分比
const setVolumePercentage = (percentage) => {
// 确保百分比在0-100之间
const volumePercent = Math.max(0, Math.min(100, percentage));
volume.value = Math.abs(~~volumePercent);
@@ -328,11 +337,8 @@ const search = createApp({
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);
};
@@ -436,6 +442,7 @@ const search = createApp({
document.removeEventListener("mouseup", stopBarDragBottom);
};
// 直接点击进度条 跳转
const handleBarDragBottomClick = (event) => {
// 获取进度条元素
const progressBar = event.currentTarget;
@@ -476,11 +483,9 @@ const search = createApp({
};
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;
}
@@ -489,31 +494,14 @@ const search = createApp({
}).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");
if (area == "student") {
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 };
return { cutSong, getPlayUrl, handleBarDragBottomClick, startBarDragBottom, volumeShow, handleVolumeHide, handleVolumeShow, zeroOrderStudents, rePlay, playData, awardAudioList, changeInterval, awardMVList, bannerList, albumBoxRef, volume, handleVolumeClick, handleVolumeDrag, startDrag, stopDrag, 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");