当前播放开发中...

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
store.commit("loadSettings");
store.state.settings.playing = false; //
store.commit("loadCaches");
router.replace('/discover/recommend')
// router.replace('/discover/recommend')
const showPlaying = ref(false); //

View File

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

View File

@ -7,6 +7,8 @@ export default createStore({
settings: {
currentRoute: "/discover/recommend", //当前路由
songId: 0, //歌曲id
playing: false, //是否播放
playMode: 0, //播放模式0-3顺序循环单曲随机。
lastPlayed: [], //最近播放
playingList: [], //当前播放
},
@ -53,7 +55,7 @@ export default createStore({
//载入settings设置
loadSettings(state) {
const l = localStorage.getItem("zmusic.settings");
if (l) state.settings = JSON.parse(l);
if (l) state.settings ={...state.settings, ...JSON.parse(l)};
},
//保存settings设置
saveSettings(state, settings) {
@ -64,7 +66,7 @@ export default createStore({
//载入caches设置
loadCaches(state) {
const l = localStorage.getItem("zmusic.caches");
if (l) state.caches = JSON.parse(l);
if (l) state.caches = {...state.caches, ...JSON.parse(l)}
},
//保存caches设置
saveCaches(state, caches) {
@ -81,7 +83,7 @@ export default createStore({
//载入theme设置
loadTheme(state) {
const l = localStorage.getItem("zmusic.theme");
if (l) state.theme = JSON.parse(l);
if (l) state.theme = {...state.theme, ...JSON.parse(l)};
},
//保存theme设置
saveTheme(state, theme) {
@ -98,6 +100,20 @@ export default createStore({
state.settings.lastPlayed = p;
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: {},
modules: {},

View File

@ -1,10 +1,15 @@
<script setup>
import { ref, reactive, h, watch, toRaw } from "vue";
import {
RouterLink,
useRoute,
useRouter,
} from "vue-router";
ref,
reactive,
h,
watch,
toRaw,
onMounted,
onUnmounted,
nextTick,
} from "vue";
import { RouterLink, useRoute, useRouter } from "vue-router";
import { useStore } from "vuex";
import {
NButton,
@ -22,28 +27,89 @@ import {
useMessage,
} from "naive-ui";
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/locale/zh-cn";
import duration from "dayjs/plugin/duration";
import pubsub from "pubsub-js";
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 [
{
title: "",
key: "index",
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: "音乐标题",
key: "name",
align: "left",
ellipsis: true,
render(row){
render(row) {
return h(
NButton,
{
@ -58,12 +124,13 @@ const createColumns = ({ play ,singerInfo }) => {
default: () => row.name,
}
);
}
},
},
{
title: "歌手",
key: "artists",
ellipsis: true,
width: 120,
render(row) {
const ars = row.artists.map((ar, idx) => {
let r = h(
@ -87,62 +154,81 @@ const createColumns = ({ play ,singerInfo }) => {
},
},
{
title: "播放时间",
key: "date",
title: "专辑",
key: "album.name",
width: 100,
render(row){
return h('span', [dayjs(row.date).format('YYYY-MM-DD')])
}
ellipsis: true,
},
{
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({
play(id){
pubsub.publish('zp.play', {id, im:true})
play(id) {
pubsub.publish("zp.play", { id, im: true });
},
singerInfo(id) {
// console.log("");
router.push("/singer/" + id);
},
});
// watch(
// () => store.state.settings.playingList,
// (val, oldVal) => {
// playingList.value = toRaw(store.state.settings.playingList)
// },
// {
// immediate: true,
// deep: true,
// }
// );
watch(
() => store.state.settings.playingList,
(val, oldVal) => {
playingList.value = toRaw(store.state.settings.playingList);
},
{
immediate: true,
deep: true,
}
);
</script>
<template>
<n-layout>
<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 has-sider>
<n-layout-content
style="padding: 6px 12px; font-size: 12px"
>
{{ playingList }}
<n-layout-content style="padding: 6px 12px; font-size: 12px">
{{ playingList.length }}
</n-layout-content>
<n-layout-sider width="100" style="padding: 0 12px 6px 12px">
<n-button size="tiny">清除列表</n-button>
</n-layout-sider>
</n-layout>
</n-layout>
<div class="wp-table" ref="wpTable">
<n-data-table
:bordered="false"
:single-line="true"
:columns="columns"
:data="playingList"
size="tiny"
size="small"
:max-height="listHeight"
/>
</div>
</template>
<script>
@ -150,6 +236,17 @@ export default {};
</script>
<style lang="less" scoped>
.wp-table {
position: absolute;
bottom: 0px;
top: 76px;
overflow: hidden;
}
thead {
display: none;
}
.n-layout-header,
.n-layout-content,
.n-layout-side {

View File

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

View File

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

View File

@ -1,5 +1,6 @@
<script setup>
import { ref } from "vue";
import { ref, watch, toRaw } from "vue";
import {useStore} from 'vuex';
import { NButton, NIcon, NSpace } from "naive-ui";
import PlaylistMusic from "@/assets/svgs/PlaylistMusic.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 pubsub from 'pubsub-js';
const store = useStore()
//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>
@ -24,28 +43,28 @@ const playMode = ref(0)
:size="[6]"
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>
<n-icon>
<RepeatOutline />
</n-icon>
</template>
</n-button>
<n-button circle v-if="playMode==2">
<n-button circle v-if="playMode==2" @click="chPlayMode(3)">
<template #icon>
<n-icon>
<RepeatOne />
</n-icon>
</template>
</n-button>
<n-button circle v-if="playMode==0">
<n-button circle v-if="playMode==0" @click="chPlayMode(1)">
<template #icon>
<n-icon>
<Playlist />
</n-icon>
</template>
</n-button>
<n-button circle v-if="playMode==3">
<n-button circle v-if="playMode==3" @click="chPlayMode(0)">
<template #icon>
<n-icon>
<Random />