Merge pull request #229 from first19326/dev
feat: 替换 vue3-aplayer 插件,并添加播放器设置选项
This commit is contained in:
commit
e2290042f7
@ -14,6 +14,7 @@
|
|||||||
"lint": "eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts,.vue --fix"
|
"lint": "eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts,.vue --fix"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@worstone/vue-aplayer": "^1.0.4",
|
||||||
"aplayer": "^1.10.1",
|
"aplayer": "^1.10.1",
|
||||||
"axios": "^1.1.3",
|
"axios": "^1.1.3",
|
||||||
"element-plus": "^2.2.18",
|
"element-plus": "^2.2.18",
|
||||||
@ -21,8 +22,7 @@
|
|||||||
"pinia": "^2.0.23",
|
"pinia": "^2.0.23",
|
||||||
"pinia-plugin-persistedstate": "^3.0.0",
|
"pinia-plugin-persistedstate": "^3.0.0",
|
||||||
"swiper": "^9.3.2",
|
"swiper": "^9.3.2",
|
||||||
"vue": "^3.3.4",
|
"vue": "^3.3.4"
|
||||||
"vue3-aplayer": "^1.7.3"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@icon-park/vue-next": "^1.4.2",
|
"@icon-park/vue-next": "^1.4.2",
|
||||||
|
544
pnpm-lock.yaml
544
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
@ -22,18 +22,18 @@ export const getPlayerList = async (server, type, id) => {
|
|||||||
).replace("http://", "https://");
|
).replace("http://", "https://");
|
||||||
|
|
||||||
return data.map((v, i) => ({
|
return data.map((v, i) => ({
|
||||||
title: v.name || v.title,
|
name: v.name || v.title,
|
||||||
artist: v.artist || v.author,
|
artist: v.artist || v.author,
|
||||||
src: domain + jsonpData.req_0.data.midurlinfo[i].purl,
|
url: domain + jsonpData.req_0.data.midurlinfo[i].purl,
|
||||||
pic: v.pic,
|
cover: v.cover || v.pic,
|
||||||
lrc: v.lrc,
|
lrc: v.lrc,
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
return data.map((v) => ({
|
return data.map((v) => ({
|
||||||
title: v.name || v.title,
|
name: v.name || v.title,
|
||||||
artist: v.artist || v.author,
|
artist: v.artist || v.author,
|
||||||
src: v.url,
|
url: v.url,
|
||||||
pic: v.pic,
|
cover: v.cover || v.pic,
|
||||||
lrc: v.lrc,
|
lrc: v.lrc,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- 音乐列表弹窗 -->
|
<!-- 音乐列表弹窗 -->
|
||||||
<Transition name="fade" mode="out-in">
|
<Transition name="fade" mode="out-in">
|
||||||
<div class="music-list" v-show="musicListShow" @click="musicListShow = false">
|
<div class="music-list" v-show="musicListShow" @click="closeMusicList()">
|
||||||
<Transition name="zoom">
|
<Transition name="zoom">
|
||||||
<div class="list" v-show="musicListShow" @click.stop>
|
<div class="list" v-show="musicListShow" @click.stop>
|
||||||
<close-one
|
<close-one
|
||||||
@ -51,7 +51,7 @@
|
|||||||
theme="filled"
|
theme="filled"
|
||||||
size="28"
|
size="28"
|
||||||
fill="#ffffff60"
|
fill="#ffffff60"
|
||||||
@click="musicListShow = false"
|
@click="closeMusicList()"
|
||||||
/>
|
/>
|
||||||
<Player
|
<Player
|
||||||
ref="playerRef"
|
ref="playerRef"
|
||||||
@ -59,7 +59,6 @@
|
|||||||
:songType="playerData.type"
|
:songType="playerData.type"
|
||||||
:songId="playerData.id"
|
:songId="playerData.id"
|
||||||
:volume="volumeNum"
|
:volume="volumeNum"
|
||||||
:shuffle="false"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Transition>
|
</Transition>
|
||||||
@ -98,6 +97,13 @@ const playerData = reactive({
|
|||||||
// 开启播放列表
|
// 开启播放列表
|
||||||
const openMusicList = () => {
|
const openMusicList = () => {
|
||||||
musicListShow.value = true;
|
musicListShow.value = true;
|
||||||
|
playerRef.value.toggleList();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 关闭播放列表
|
||||||
|
const closeMusicList = () => {
|
||||||
|
musicListShow.value = false;
|
||||||
|
playerRef.value.toggleList();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 音乐播放暂停
|
// 音乐播放暂停
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
<template>
|
<template>
|
||||||
<aplayer
|
<APlayer
|
||||||
showLrc
|
|
||||||
ref="player"
|
|
||||||
v-if="playList[0]"
|
v-if="playList[0]"
|
||||||
:music="playList[playIndex]"
|
ref="player"
|
||||||
:list="playList"
|
:audio="playList"
|
||||||
:autoplay="autoplay"
|
:autoplay="store.playerAutoplay"
|
||||||
:theme="theme"
|
:theme="theme"
|
||||||
:repeat="repeat"
|
:autoSwitch="false"
|
||||||
:shuffle="shuffle"
|
:loop="store.playerLoop"
|
||||||
:listMaxHeight="listMaxHeight"
|
:order="store.playerOrder"
|
||||||
:listFolded="listFolded"
|
|
||||||
:volume="volume"
|
:volume="volume"
|
||||||
|
:showLrc="true"
|
||||||
|
:listFolded="listFolded"
|
||||||
|
:listMaxHeight="listMaxHeight"
|
||||||
|
:noticeSwitch="false"
|
||||||
@play="onPlay"
|
@play="onPlay"
|
||||||
@pause="onPause"
|
@pause="onPause"
|
||||||
@timeupdate="onTimeUp"
|
@timeupdate="onTimeUp"
|
||||||
@onSelectSong="onSelectSong"
|
|
||||||
@error="loadMusicError"
|
@error="loadMusicError"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
@ -24,7 +24,7 @@
|
|||||||
import { MusicOne, PlayWrong } from "@icon-park/vue-next";
|
import { MusicOne, PlayWrong } from "@icon-park/vue-next";
|
||||||
import { getPlayerList } from "@/api";
|
import { getPlayerList } from "@/api";
|
||||||
import { mainStore } from "@/store";
|
import { mainStore } from "@/store";
|
||||||
import aplayer from "vue3-aplayer";
|
import APlayer from "@worstone/vue-aplayer";
|
||||||
|
|
||||||
const store = mainStore();
|
const store = mainStore();
|
||||||
|
|
||||||
@ -36,32 +36,14 @@ const playList = ref([]);
|
|||||||
|
|
||||||
// 歌曲播放项
|
// 歌曲播放项
|
||||||
const playIndex = ref(0);
|
const playIndex = ref(0);
|
||||||
const playListCount = ref(0);
|
|
||||||
|
|
||||||
const skipTimeout = ref(null);
|
|
||||||
|
|
||||||
// 配置项
|
// 配置项
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
// 音频自动播放
|
|
||||||
autoplay: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
// 主题色
|
// 主题色
|
||||||
theme: {
|
theme: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "#efefef",
|
default: "#efefef",
|
||||||
},
|
},
|
||||||
// 音频循环播放
|
|
||||||
repeat: {
|
|
||||||
type: String,
|
|
||||||
default: "list", //'list' | 'music' | 'none'
|
|
||||||
},
|
|
||||||
// 随机播放
|
|
||||||
shuffle: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
// 默认音量
|
// 默认音量
|
||||||
volume: {
|
volume: {
|
||||||
type: Number,
|
type: Number,
|
||||||
@ -92,39 +74,28 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
// 列表最大高度
|
// 列表最大高度
|
||||||
listMaxHeight: {
|
listMaxHeight: {
|
||||||
type: String,
|
type: Number,
|
||||||
default: "420px",
|
default: 420,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const listHeight = computed(() => {
|
||||||
|
return props.listMaxHeight + "px";
|
||||||
|
});
|
||||||
|
|
||||||
// 初始化播放器
|
// 初始化播放器
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
try {
|
try {
|
||||||
getPlayerList(props.songServer, props.songType, props.songId).then((res) => {
|
getPlayerList(props.songServer, props.songType, props.songId).then((res) => {
|
||||||
console.log(res);
|
console.log(res);
|
||||||
// 生成歌单信息
|
|
||||||
playIndex.value = Math.floor(Math.random() * res.length);
|
|
||||||
playListCount.value = res.length;
|
|
||||||
// 更改播放器加载状态
|
// 更改播放器加载状态
|
||||||
store.musicIsOk = true;
|
store.musicIsOk = true;
|
||||||
// 生成歌单
|
// 生成歌单
|
||||||
res.forEach((v) => {
|
playList.value = res;
|
||||||
playList.value.push({
|
console.log("音乐加载完成");
|
||||||
title: v.name || v.title,
|
console.log(playList.value);
|
||||||
artist: v.artist || v.author,
|
console.log(playIndex.value, playList.value.length, props.volume);
|
||||||
src: v.url || v.src,
|
|
||||||
pic: v.pic,
|
|
||||||
lrc: v.lrc,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
console.log(
|
|
||||||
"音乐加载完成",
|
|
||||||
playList.value,
|
|
||||||
playIndex.value,
|
|
||||||
playListCount.value,
|
|
||||||
props.volume,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
@ -144,10 +115,11 @@ onMounted(() => {
|
|||||||
// 播放
|
// 播放
|
||||||
const onPlay = () => {
|
const onPlay = () => {
|
||||||
console.log("播放");
|
console.log("播放");
|
||||||
|
playIndex.value = player.value.aplayer.index;
|
||||||
// 播放状态
|
// 播放状态
|
||||||
store.setPlayerState(player.value.audio.paused);
|
store.setPlayerState(player.value.audioRef.paused);
|
||||||
// 储存播放器信息
|
// 储存播放器信息
|
||||||
store.setPlayerData(player.value.currentMusic.title, player.value.currentMusic.artist);
|
store.setPlayerData(playList.value[playIndex.value].name, playList.value[playIndex.value].artist);
|
||||||
ElMessage({
|
ElMessage({
|
||||||
message: store.getPlayerData.name + " - " + store.getPlayerData.artist,
|
message: store.getPlayerData.name + " - " + store.getPlayerData.artist,
|
||||||
grouping: true,
|
grouping: true,
|
||||||
@ -160,19 +132,23 @@ const onPlay = () => {
|
|||||||
|
|
||||||
// 暂停
|
// 暂停
|
||||||
const onPause = () => {
|
const onPause = () => {
|
||||||
store.setPlayerState(player.value.audio.paused);
|
store.setPlayerState(player.value.audioRef.paused);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 音频时间更新事件
|
// 音频时间更新事件
|
||||||
const onTimeUp = () => {
|
const onTimeUp = () => {
|
||||||
let playerRef = player.value.$.vnode.el;
|
let lyrics = player.value.aplayer.lyrics[playIndex.value];
|
||||||
if (playerRef) {
|
let lyricIndex = player.value.aplayer.lyricIndex;
|
||||||
const currentLrcElement = playerRef.querySelector(".aplayer-lrc-current");
|
if (!lyrics || !lyrics[lyricIndex]) {
|
||||||
const previousLrcElement = currentLrcElement?.previousElementSibling;
|
return;
|
||||||
const lrcContent =
|
|
||||||
currentLrcElement?.innerHTML || previousLrcElement?.innerHTML || "这句没有歌词";
|
|
||||||
store.setPlayerLrc(lrcContent);
|
|
||||||
}
|
}
|
||||||
|
let lrc = lyrics[lyricIndex][1];
|
||||||
|
if (lrc === "Loading") {
|
||||||
|
lrc = "歌词加载中";
|
||||||
|
} else if (lrc === "Not available") {
|
||||||
|
lrc = "歌词加载失败";
|
||||||
|
}
|
||||||
|
store.setPlayerLrc(lrc);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 切换播放暂停事件
|
// 切换播放暂停事件
|
||||||
@ -182,41 +158,27 @@ const playToggle = () => {
|
|||||||
|
|
||||||
// 切换音量事件
|
// 切换音量事件
|
||||||
const changeVolume = (value) => {
|
const changeVolume = (value) => {
|
||||||
player.value.audio.volume = value;
|
player.value.setVolume(value, false);
|
||||||
};
|
|
||||||
|
|
||||||
const onSelectSong = (val) => {
|
|
||||||
console.log(val);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 切换上下曲
|
// 切换上下曲
|
||||||
const changeSong = (type) => {
|
const changeSong = (type) => {
|
||||||
playIndex.value = player.value.playIndex;
|
type === 0 ? player.value.skipBack() : player.value.skipForward();
|
||||||
playIndex.value += type ? 1 : -1;
|
|
||||||
// 判断是否处于最后/第一首
|
|
||||||
if (playIndex.value < 0) {
|
|
||||||
playIndex.value = playListCount.value - 1;
|
|
||||||
} else if (playIndex.value >= playListCount.value) {
|
|
||||||
playIndex.value = 0;
|
|
||||||
}
|
|
||||||
// console.log(playIndex.value, playList.value[playIndex.value]);
|
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
player.value.play();
|
player.value.play();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 切换歌曲列表状态
|
||||||
|
const toggleList = () => {
|
||||||
|
player.value.toggleList();
|
||||||
|
};
|
||||||
|
|
||||||
// 加载音频错误
|
// 加载音频错误
|
||||||
const loadMusicError = () => {
|
const loadMusicError = () => {
|
||||||
let notice = "";
|
let notice = "";
|
||||||
if (playList.value.length > 1) {
|
if (playList.value.length > 1) {
|
||||||
notice = "播放歌曲出现错误,播放器将在 2s 后进行下一首";
|
notice = "播放歌曲出现错误,播放器将在 2s 后进行下一首";
|
||||||
// 播放下一首
|
|
||||||
skipTimeout.value = setTimeout(() => {
|
|
||||||
changeSong(1);
|
|
||||||
if (!player.value.audio.paused) {
|
|
||||||
onPlay();
|
|
||||||
}
|
|
||||||
}, 2000);
|
|
||||||
} else {
|
} else {
|
||||||
notice = "播放歌曲出现错误";
|
notice = "播放歌曲出现错误";
|
||||||
}
|
}
|
||||||
@ -229,24 +191,22 @@ const loadMusicError = () => {
|
|||||||
duration: 2000,
|
duration: 2000,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
console.error("播放歌曲: " + player.value.currentMusic.title + " 出现错误");
|
console.error(
|
||||||
|
"播放歌曲: " + player.value.aplayer.audio[player.value.aplayer.index].name + " 出现错误",
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 暴露子组件方法
|
// 暴露子组件方法
|
||||||
defineExpose({ playToggle, changeVolume, changeSong });
|
defineExpose({ playToggle, changeVolume, changeSong, toggleList });
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
clearTimeout(skipTimeout.value);
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.aplayer {
|
.aplayer {
|
||||||
width: 80%;
|
width: 80%;
|
||||||
background: transparent;
|
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
font-family: "HarmonyOS_Regular", sans-serif !important;
|
font-family: "HarmonyOS_Regular", sans-serif !important;
|
||||||
:deep(.aplayer-body) {
|
:deep(.aplayer-body) {
|
||||||
|
background-color: transparent;
|
||||||
.aplayer-pic {
|
.aplayer-pic {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@ -268,8 +228,8 @@ onBeforeUnmount(() => {
|
|||||||
}
|
}
|
||||||
.aplayer-lrc {
|
.aplayer-lrc {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
margin: 4px 0 6px 6px;
|
margin: 7px 0 6px 6px;
|
||||||
height: 100%;
|
height: 44px;
|
||||||
mask: linear-gradient(
|
mask: linear-gradient(
|
||||||
#fff 15%,
|
#fff 15%,
|
||||||
#fff 85%,
|
#fff 85%,
|
||||||
@ -301,6 +261,8 @@ onBeforeUnmount(() => {
|
|||||||
}
|
}
|
||||||
:deep(.aplayer-list) {
|
:deep(.aplayer-list) {
|
||||||
margin-top: 6px;
|
margin-top: 6px;
|
||||||
|
height: v-bind(listHeight);
|
||||||
|
background-color: transparent;
|
||||||
ol {
|
ol {
|
||||||
&::-webkit-scrollbar-track {
|
&::-webkit-scrollbar-track {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
@ -50,7 +50,34 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-collapse-item>
|
</el-collapse-item>
|
||||||
<el-collapse-item title="播放器配置" name="3">
|
<el-collapse-item title="播放器配置" name="3">
|
||||||
<div>设置内容待增加</div>
|
<div class="item">
|
||||||
|
<span class="text">自动播放</span>
|
||||||
|
<el-switch
|
||||||
|
v-model="playerAutoplay"
|
||||||
|
inline-prompt
|
||||||
|
:active-icon="CheckSmall"
|
||||||
|
:inactive-icon="CloseSmall"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<span class="text">随机播放</span>
|
||||||
|
<el-switch
|
||||||
|
v-model="playerOrder"
|
||||||
|
inline-prompt
|
||||||
|
:active-icon="CheckSmall"
|
||||||
|
:inactive-icon="CloseSmall"
|
||||||
|
active-value="random"
|
||||||
|
inactive-value="list"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<span class="text">循环模式</span>
|
||||||
|
<el-radio-group v-model="playerLoop" size="small" text-color="#FFFFFF">
|
||||||
|
<el-radio label="all" border>列表</el-radio>
|
||||||
|
<el-radio label="one" border>单曲</el-radio>
|
||||||
|
<el-radio label="none" border>不循环</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</div>
|
||||||
</el-collapse-item>
|
</el-collapse-item>
|
||||||
<el-collapse-item title="其他设置" name="4">
|
<el-collapse-item title="其他设置" name="4">
|
||||||
<div>设置内容待增加</div>
|
<div>设置内容待增加</div>
|
||||||
@ -65,7 +92,16 @@ import { mainStore } from "@/store";
|
|||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
|
|
||||||
const store = mainStore();
|
const store = mainStore();
|
||||||
const { coverType, siteStartShow, musicClick, playerLrcShow, footerBlur } = storeToRefs(store);
|
const {
|
||||||
|
coverType,
|
||||||
|
siteStartShow,
|
||||||
|
musicClick,
|
||||||
|
playerLrcShow,
|
||||||
|
footerBlur,
|
||||||
|
playerAutoplay,
|
||||||
|
playerOrder,
|
||||||
|
playerLoop,
|
||||||
|
} = storeToRefs(store);
|
||||||
|
|
||||||
// 默认选中项
|
// 默认选中项
|
||||||
const activeName = ref("1");
|
const activeName = ref("1");
|
||||||
@ -107,13 +143,23 @@ const radioChange = () => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
flex-wrap: wrap;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
.el-switch__core {
|
.el-switch__core {
|
||||||
border-color: transparent;
|
border-color: transparent;
|
||||||
background-color: #ffffff30;
|
background-color: #ffffff30;
|
||||||
}
|
}
|
||||||
|
.el-radio-group {
|
||||||
|
.el-radio {
|
||||||
|
margin: 2px 10px 2px 0;
|
||||||
|
border-radius: 5px;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.bg-set {
|
|
||||||
.el-radio-group {
|
.el-radio-group {
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
@ -152,6 +198,5 @@ const radioChange = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -22,6 +22,9 @@ export const mainStore = defineStore("main", {
|
|||||||
playerLrc: "歌词加载中", // 当前播放歌词
|
playerLrc: "歌词加载中", // 当前播放歌词
|
||||||
playerLrcShow: true, // 是否显示底栏歌词
|
playerLrcShow: true, // 是否显示底栏歌词
|
||||||
footerBlur: true, // 底栏模糊
|
footerBlur: true, // 底栏模糊
|
||||||
|
playerAutoplay: false, // 是否自动播放
|
||||||
|
playerLoop: "all", // 循环播放 "all", "one", "none"
|
||||||
|
playerOrder: "list", // 循环顺序 "list", "random"
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
@ -82,6 +85,9 @@ export const mainStore = defineStore("main", {
|
|||||||
"musicClick",
|
"musicClick",
|
||||||
"playerLrcShow",
|
"playerLrcShow",
|
||||||
"footerBlur",
|
"footerBlur",
|
||||||
|
"playerAutoplay",
|
||||||
|
"playerLoop",
|
||||||
|
"playerOrder",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user