当前播放开发中...

This commit is contained in:
zilong 2021-10-23 00:42:08 +08:00
parent 4ade4395d4
commit 8b42649ba1
7 changed files with 272 additions and 89 deletions

View File

@ -34,9 +34,10 @@ const store = useStore();
//localstorage //localstorage
store.commit("loadSettings"); store.commit("loadSettings");
store.state.settings.playing = false; //
store.commit("loadCaches"); store.commit("loadCaches");
router.replace('/discover/recommend') // router.replace('/discover/recommend')
const showPlaying = ref(false); // const showPlaying = ref(false); //

View File

@ -3,15 +3,15 @@ import pubsub from 'pubsub-js'
import Home from "../views/Home.vue"; import Home from "../views/Home.vue";
const routes = [ const routes = [
// { {
// path: "/", path: "/",
// redirect: "/discover/recommend", redirect: "/discover/recommend",
// name: "index", name: "index",
// // component: ()=> import('@/views/Home.vue'), // component: ()=> import('@/views/Home.vue'),
// // meta:{ // meta:{
// // title:'zmusic', // title:'zmusic',
// // } // }
// }, },
{ {
path: "/discover", path: "/discover",
name: "discover", name: "discover",

View File

@ -7,6 +7,8 @@ export default createStore({
settings: { settings: {
currentRoute: "/discover/recommend", //当前路由 currentRoute: "/discover/recommend", //当前路由
songId: 0, //歌曲id songId: 0, //歌曲id
playing: false, //是否播放
playMode: 0, //播放模式0-3顺序循环单曲随机。
lastPlayed: [], //最近播放 lastPlayed: [], //最近播放
playingList: [], //当前播放 playingList: [], //当前播放
}, },
@ -53,7 +55,7 @@ export default createStore({
//载入settings设置 //载入settings设置
loadSettings(state) { loadSettings(state) {
const l = localStorage.getItem("zmusic.settings"); const l = localStorage.getItem("zmusic.settings");
if (l) state.settings = JSON.parse(l); if (l) state.settings ={...state.settings, ...JSON.parse(l)};
}, },
//保存settings设置 //保存settings设置
saveSettings(state, settings) { saveSettings(state, settings) {
@ -64,7 +66,7 @@ export default createStore({
//载入caches设置 //载入caches设置
loadCaches(state) { loadCaches(state) {
const l = localStorage.getItem("zmusic.caches"); const l = localStorage.getItem("zmusic.caches");
if (l) state.caches = JSON.parse(l); if (l) state.caches = {...state.caches, ...JSON.parse(l)}
}, },
//保存caches设置 //保存caches设置
saveCaches(state, caches) { saveCaches(state, caches) {
@ -81,7 +83,7 @@ export default createStore({
//载入theme设置 //载入theme设置
loadTheme(state) { loadTheme(state) {
const l = localStorage.getItem("zmusic.theme"); const l = localStorage.getItem("zmusic.theme");
if (l) state.theme = JSON.parse(l); if (l) state.theme = {...state.theme, ...JSON.parse(l)};
}, },
//保存theme设置 //保存theme设置
saveTheme(state, theme) { saveTheme(state, theme) {
@ -98,6 +100,20 @@ export default createStore({
state.settings.lastPlayed = p; state.settings.lastPlayed = p;
saveLoaclSettings(state.settings); saveLoaclSettings(state.settings);
}, },
addToPlayingList(state, song) {
//如果没有,设置为[]
if (!state.settings.playingList)
state.settings.playingList = [];
let f = state.settings.playingList.find((item) => {
return item.id === song.id;
});
if (!f) {
// console.log("add to playingList");
state.settings.playingList.unshift(song)
saveLoaclSettings(state.settings);
}
},
}, },
actions: {}, actions: {},
modules: {}, modules: {},

View File

@ -1,10 +1,15 @@
<script setup> <script setup>
import { ref, reactive, h, watch, toRaw } from "vue";
import { import {
RouterLink, ref,
useRoute, reactive,
useRouter, h,
} from "vue-router"; watch,
toRaw,
onMounted,
onUnmounted,
nextTick,
} from "vue";
import { RouterLink, useRoute, useRouter } from "vue-router";
import { useStore } from "vuex"; import { useStore } from "vuex";
import { import {
NButton, NButton,
@ -22,48 +27,110 @@ import {
useMessage, useMessage,
} from "naive-ui"; } from "naive-ui";
import Play from "@/assets/svgs/Play_.svg"; import Play from "@/assets/svgs/Play_.svg";
import Add from "@/assets/svgs/Add.svg"; import Pause from "@/assets/svgs/Pause.svg";
import dayjs from "dayjs"; import dayjs from "dayjs";
import "dayjs/locale/zh-cn"; import "dayjs/locale/zh-cn";
import duration from "dayjs/plugin/duration";
import pubsub from "pubsub-js"; import pubsub from "pubsub-js";
const store = useStore(); const store = useStore();
const playingList = ref([]) const router = useRouter();
dayjs.extend(duration);
const playingList = ref([]);
const wpTable = ref("");
const listHeight = ref(0);
const createColumns = ({ play ,singerInfo }) => { onMounted(() => {
window.addEventListener("resize", onResize);
// console.log(wpTable.value.clientHeight);
listHeight.value = wpTable.value.clientHeight;
});
const onResize = () => {
if (wpTable.value) {
listHeight.value = wpTable.value.clientHeight - 40;
// console.log(wpTable.value.clientHeight)
}
};
const token = pubsub.subscribe("zp", (msg, data) => {
switch (msg) {
case "zp.togglePlaying":
nextTick(() => {
onResize();
});
break;
}
});
//
onUnmounted(() => {
pubsub.unsubscribe(token);
});
const createColumns = ({ play, singerInfo }) => {
return [ return [
{ {
title: "", title: "",
key: "index", key: "index",
align: "right", align: "right",
width: 20 width: 20,
render(row) {
if (row.id === store.state.settings.songId) {
const icon = h(store.state.settings.playing ? Play : Pause);
return h(
NButton,
{
text: true,
type: "primary",
circle: true,
size: "tiny",
},
{
default: () =>
h(
NIcon,
{
style: {
bottom: "-2px",
left: "-2px",
position: "absolute",
},
},
// [h(store.state.settings.playing ? Play : Pause,{},[])]
{ default: () => icon }
),
}
);
} else return "";
},
}, },
{ {
title: "音乐标题", title: "音乐标题",
key: "name", key: "name",
align: "left", align: "left",
ellipsis: true, ellipsis: true,
render(row){ render(row) {
return h( return h(
NButton, NButton,
{ {
style: { style: {
marginRight: "6px", marginRight: "6px",
},
text: true,
size: "small",
onClick: () => play(row.id),
}, },
{ text: true,
default: () => row.name, size: "small",
} onClick: () => play(row.id),
); },
} {
default: () => row.name,
}
);
},
}, },
{ {
title: "歌手", title: "歌手",
key: "artists", key: "artists",
ellipsis: true, ellipsis: true,
width: 120,
render(row) { render(row) {
const ars = row.artists.map((ar, idx) => { const ars = row.artists.map((ar, idx) => {
let r = h( let r = h(
@ -87,62 +154,81 @@ const createColumns = ({ play ,singerInfo }) => {
}, },
}, },
{ {
title: "播放时间", title: "专辑",
key: "date", key: "album.name",
width: 100, width: 100,
render(row){ ellipsis: true,
return h('span', [dayjs(row.date).format('YYYY-MM-DD')])
}
}, },
{
title: "时长",
key: "duration",
width: 60,
render(row) {
return h("span", [
dayjs.duration(row.duration).format("mm:ss"),
]);
},
},
// {
// title: "",
// key: "date",
// width: 100,
// render(row) {
// return h("span", [
// dayjs(row.date).format("YYYY-MM-DD"),
// ]);
// },
// },
]; ];
}; };
const columns = createColumns({ const columns = createColumns({
play(id){ play(id) {
pubsub.publish('zp.play', {id, im:true}) pubsub.publish("zp.play", { id, im: true });
}, },
singerInfo(id) { singerInfo(id) {
// console.log("");
router.push("/singer/" + id); router.push("/singer/" + id);
}, },
}); });
// watch( watch(
// () => store.state.settings.playingList, () => store.state.settings.playingList,
// (val, oldVal) => { (val, oldVal) => {
// playingList.value = toRaw(store.state.settings.playingList) playingList.value = toRaw(store.state.settings.playingList);
// }, },
// { {
// immediate: true, immediate: true,
// deep: true, deep: true,
// } }
// ); );
</script> </script>
<template> <template>
<n-layout> <n-layout>
<n-layout-header <n-layout-header
style="padding: 6px 12px 0px 12px; font-size: 24px" style="padding: 10px 12px 0px 12px; font-size: 24px"
>当前播放 >当前播放
</n-layout-header> </n-layout-header>
<n-layout has-sider> <n-layout has-sider>
<n-layout-content <n-layout-content style="padding: 6px 12px; font-size: 12px">
style="padding: 6px 12px; font-size: 12px" {{ playingList.length }}
>
{{ playingList }}
</n-layout-content> </n-layout-content>
<n-layout-sider width="100" style="padding: 0 12px 6px 12px"> <n-layout-sider width="100" style="padding: 0 12px 6px 12px">
<n-button size="tiny">清除列表</n-button> <n-button size="tiny">清除列表</n-button>
</n-layout-sider> </n-layout-sider>
</n-layout> </n-layout>
</n-layout> </n-layout>
<n-data-table <div class="wp-table" ref="wpTable">
:bordered="false" <n-data-table
:single-line="true" :bordered="false"
:columns="columns" :single-line="true"
:data="playingList" :columns="columns"
size="tiny" :data="playingList"
/> size="small"
:max-height="listHeight"
/>
</div>
</template> </template>
<script> <script>
@ -150,6 +236,17 @@ export default {};
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.wp-table {
position: absolute;
bottom: 0px;
top: 76px;
overflow: hidden;
}
thead {
display: none;
}
.n-layout-header, .n-layout-header,
.n-layout-content, .n-layout-content,
.n-layout-side { .n-layout-side {

View File

@ -33,7 +33,7 @@ onMounted(() => {
}); });
onUnmounted(() => { onUnmounted(() => {
console.log("另外一个Unmounted"); // console.log("Unmounted");
// audioEl.value.removeEventListener("play", onPlay); // audioEl.value.removeEventListener("play", onPlay);
// audioEl.value.removeEventListener("pause", onPause); // audioEl.value.removeEventListener("pause", onPause);
// audioEl.value.removeEventListener("ended", onEnd); // audioEl.value.removeEventListener("ended", onEnd);
@ -46,12 +46,46 @@ const onPause = () => {
console.log("onPause"); console.log("onPause");
}; };
const onEnd = () => { const onEnd = () => {
playing.value = false; playNext(1)
// playing.value = false;
currentTime = 0; currentTime = 0;
console.log("onEnd"); console.log("下一首...");
}; };
const play = async (id, name, im = true) => { const playNext = async (step) => {
let { songId, playingList, playMode , playing} = store.state.settings;
let idx = playingList.findIndex((item) => item.id == songId);
console.log(idx);
switch (playMode) {
case 0:
idx += step;
if (idx > playingList.length - 1) return;
if (idx < 0) return
break;
case 1:
idx += step;
if (idx > playingList.length - 1) idx = 0;
if (idx < 0) idx = playingList.length - 1;
break;
case 2:
break;
case 3:
break;
}
console.log(idx);
play(playingList[idx].id, playing)
};
const playPrev = async (id, im = true) => {};
const previous = async () => {
playNext(-1);
};
const forward = async () => {
playNext(1);
};
const play = async (id, im = true) => {
console.log(id); console.log(id);
await getSongUrl(id) await getSongUrl(id)
.then((res) => { .then((res) => {
@ -60,13 +94,16 @@ const play = async (id, name, im = true) => {
store.commit("saveSettings", { store.commit("saveSettings", {
songId: id, songId: id,
}); });
pubsub.publish('zp.getSongInfo', {id: store.state.settings.songId, im}) // console.log(audioEl.value.duration);
pubsub.publish("zp.getSongInfo", {
id: store.state.settings.songId,
im,
});
if (im) { if (im) {
audioEl.value.play(); audioEl.value.play();
playing.value = true; playing.value = true;
} }
} }
}) })
.catch((err) => { .catch((err) => {
@ -90,7 +127,10 @@ const resume = async () => {
} }
audioEl.value.play(); audioEl.value.play();
playing.value = true; playing.value = true;
pubsub.publish('zp.getSongInfo', {id: store.state.settings.songId, im: true}) pubsub.publish("zp.getSongInfo", {
id: store.state.settings.songId,
im: true,
});
} }
}; };
@ -108,9 +148,10 @@ const favorite = () => {
let interval; let interval;
watch(playing, (val, old) => { watch(playing, (val, old) => {
store.state.settings.playing = val;
if (val === true) { if (val === true) {
interval = setInterval(() => { interval = setInterval(() => {
// console.log(audioEl.value.currentTime); // console.log(audioEl.value.duration);
currentTime = audioEl.value.currentTime; currentTime = audioEl.value.currentTime;
pubsub.publish("zp.progress", { pubsub.publish("zp.progress", {
progress: audioEl.value.currentTime, progress: audioEl.value.currentTime,
@ -127,7 +168,7 @@ watch(playing, (val, old) => {
const psToken = pubsub.subscribe("zp", (msg, data) => { const psToken = pubsub.subscribe("zp", (msg, data) => {
switch (msg) { switch (msg) {
case "zp.play": case "zp.play":
play(data.id, data.name, data.im); play(data.id, data.im);
break; break;
case "zp.setProgressScale": case "zp.setProgressScale":
setProgressScale(data.scale); setProgressScale(data.scale);
@ -149,7 +190,7 @@ onUnmounted(() => {
id="songCtrl" id="songCtrl"
align="center" align="center"
:size="[6]" :size="[6]"
style="padding-top: 2px;margin: 0 4px" style="padding-top: 2px; margin: 0 4px"
> >
<n-button circle @click="favorite"> <n-button circle @click="favorite">
<template #icon> <template #icon>
@ -158,7 +199,7 @@ onUnmounted(() => {
</n-icon> </n-icon>
</template> </template>
</n-button> </n-button>
<n-button circle> <n-button circle @click="previous">
<template #icon> <template #icon>
<n-icon> <n-icon>
<PlaySkipBack /> <PlaySkipBack />
@ -194,7 +235,7 @@ onUnmounted(() => {
<!-- </template> --> <!-- </template> -->
</n-button> </n-button>
<!-- <n-button circle color="#18a058"> --> <!-- <n-button circle color="#18a058"> -->
<n-button circle> <n-button circle @click="forward">
<template #icon> <template #icon>
<n-icon> <n-icon>
<PlaySkipForward /> <PlaySkipForward />

View File

@ -21,7 +21,9 @@ const showInfo = ref(false);
const info = reactive({ const info = reactive({
name: "", name: "",
artists: "", artists: "",
albumPicUrl: "", album: {},
duration: 0,
mv: 0,
}); });
//#region //#region
@ -31,12 +33,19 @@ const songInfo = (id, im) => {
showInfo.value = true; showInfo.value = true;
info.name = res.data.songs[0].name; info.name = res.data.songs[0].name;
info.artists = res.data.songs[0].ar; info.artists = res.data.songs[0].ar;
info.albumPicUrl = res.data.songs[0].al.picUrl; info.album = res.data.songs[0].al;
info.duration = res.data.songs[0].dt;
info.mv = res.data.songs[0].mv;
currTime.value = '00:00'
totalTime.value = zpTime(info.duration)
if(im){ if(im){
store.commit('savePlayed', {...{ const p = {...{
id, id,
date: Date.now(), date: Date.now(),
}, ...toRaw(info)}) }, ...toRaw(info)}
store.commit('savePlayed', p)
store.commit('addToPlayingList', p)
console.log('savePlayed'); console.log('savePlayed');
} }
}) })
@ -76,7 +85,7 @@ onUnmounted(() => {
<NAvatar <NAvatar
:size="40" :size="40"
v-show="showInfo" v-show="showInfo"
:src="info.albumPicUrl" :src="info.album.picUrl"
></NAvatar> ></NAvatar>
<div class="song" v-show="showInfo"> <div class="song" v-show="showInfo">
<div class="w-song"> <div class="w-song">

View File

@ -1,5 +1,6 @@
<script setup> <script setup>
import { ref } from "vue"; import { ref, watch, toRaw } from "vue";
import {useStore} from 'vuex';
import { NButton, NIcon, NSpace } from "naive-ui"; import { NButton, NIcon, NSpace } from "naive-ui";
import PlaylistMusic from "@/assets/svgs/PlaylistMusic.svg"; import PlaylistMusic from "@/assets/svgs/PlaylistMusic.svg";
import VolumeOffOutline from "@/assets/svgs/VolumeOffOutline.svg"; import VolumeOffOutline from "@/assets/svgs/VolumeOffOutline.svg";
@ -9,9 +10,27 @@ import Playlist from "@/assets/svgs/Playlist.svg";
import Random from "@/assets/svgs/Random.svg"; import Random from "@/assets/svgs/Random.svg";
import pubsub from 'pubsub-js'; import pubsub from 'pubsub-js';
const store = useStore()
//0-3 //0-3
const playMode = ref(0) let playMode = ref(0)
const chPlayMode = (mode) => {
store.commit('saveSettings', {
playMode: mode
})
}
watch(
() => store.state.settings.playMode,
(val, oldVal) => {
playMode.value = toRaw(store.state.settings.playMode);
},
{
immediate: true,
deep: true,
}
);
</script> </script>
@ -24,28 +43,28 @@ const playMode = ref(0)
:size="[6]" :size="[6]"
style="padding-top: 2px; padding-right: 8px" style="padding-top: 2px; padding-right: 8px"
> >
<n-button circle v-if="playMode==1"> <n-button circle v-if="playMode==1" @click="chPlayMode(2)">
<template #icon> <template #icon>
<n-icon> <n-icon>
<RepeatOutline /> <RepeatOutline />
</n-icon> </n-icon>
</template> </template>
</n-button> </n-button>
<n-button circle v-if="playMode==2"> <n-button circle v-if="playMode==2" @click="chPlayMode(3)">
<template #icon> <template #icon>
<n-icon> <n-icon>
<RepeatOne /> <RepeatOne />
</n-icon> </n-icon>
</template> </template>
</n-button> </n-button>
<n-button circle v-if="playMode==0"> <n-button circle v-if="playMode==0" @click="chPlayMode(1)">
<template #icon> <template #icon>
<n-icon> <n-icon>
<Playlist /> <Playlist />
</n-icon> </n-icon>
</template> </template>
</n-button> </n-button>
<n-button circle v-if="playMode==3"> <n-button circle v-if="playMode==3" @click="chPlayMode(0)">
<template #icon> <template #icon>
<n-icon> <n-icon>
<Random /> <Random />