mirror of
https://github.com/imsyy/SPlayer.git
synced 2025-11-25 19:37:35 +08:00
✨ feat: 卡片播放按钮可直接播放 #111
This commit is contained in:
7
components.d.ts
vendored
7
components.d.ts
vendored
@@ -12,6 +12,7 @@ declare module 'vue' {
|
|||||||
CommentList: typeof import('./src/components/List/CommentList.vue')['default']
|
CommentList: typeof import('./src/components/List/CommentList.vue')['default']
|
||||||
CountDown: typeof import('./src/components/Player/CountDown.vue')['default']
|
CountDown: typeof import('./src/components/Player/CountDown.vue')['default']
|
||||||
CoverDropdown: typeof import('./src/components/Cover/CoverDropdown.vue')['default']
|
CoverDropdown: typeof import('./src/components/Cover/CoverDropdown.vue')['default']
|
||||||
|
CoverPlayBtn: typeof import('./src/components/Cover/CoverPlayBtn.vue')['default']
|
||||||
CreatePlaylist: typeof import('./src/components/Modal/CreatePlaylist.vue')['default']
|
CreatePlaylist: typeof import('./src/components/Modal/CreatePlaylist.vue')['default']
|
||||||
DownloadSong: typeof import('./src/components/Modal/DownloadSong.vue')['default']
|
DownloadSong: typeof import('./src/components/Modal/DownloadSong.vue')['default']
|
||||||
FullPlayer: typeof import('./src/components/Player/FullPlayer.vue')['default']
|
FullPlayer: typeof import('./src/components/Player/FullPlayer.vue')['default']
|
||||||
@@ -46,7 +47,7 @@ declare module 'vue' {
|
|||||||
NGrid: typeof import('naive-ui')['NGrid']
|
NGrid: typeof import('naive-ui')['NGrid']
|
||||||
NH1: typeof import('naive-ui')['NH1']
|
NH1: typeof import('naive-ui')['NH1']
|
||||||
NH3: typeof import('naive-ui')['NH3']
|
NH3: typeof import('naive-ui')['NH3']
|
||||||
NH4: (typeof import("naive-ui"))["NH4"]
|
NH4: typeof import('naive-ui')['NH4']
|
||||||
NH6: typeof import('naive-ui')['NH6']
|
NH6: typeof import('naive-ui')['NH6']
|
||||||
NIcon: typeof import('naive-ui')['NIcon']
|
NIcon: typeof import('naive-ui')['NIcon']
|
||||||
NImage: typeof import('naive-ui')['NImage']
|
NImage: typeof import('naive-ui')['NImage']
|
||||||
@@ -63,14 +64,12 @@ declare module 'vue' {
|
|||||||
NMessageProvider: typeof import('naive-ui')['NMessageProvider']
|
NMessageProvider: typeof import('naive-ui')['NMessageProvider']
|
||||||
NModal: typeof import('naive-ui')['NModal']
|
NModal: typeof import('naive-ui')['NModal']
|
||||||
NNotificationProvider: typeof import('naive-ui')['NNotificationProvider']
|
NNotificationProvider: typeof import('naive-ui')['NNotificationProvider']
|
||||||
NNumberAnimation: (typeof import("naive-ui"))["NNumberAnimation"]
|
NNumberAnimation: typeof import('naive-ui')['NNumberAnimation']
|
||||||
NPagination: typeof import('naive-ui')['NPagination']
|
NPagination: typeof import('naive-ui')['NPagination']
|
||||||
NPopover: typeof import('naive-ui')['NPopover']
|
NPopover: typeof import('naive-ui')['NPopover']
|
||||||
NProgress: typeof import('naive-ui')['NProgress']
|
|
||||||
NQrCode: typeof import('naive-ui')['NQrCode']
|
NQrCode: typeof import('naive-ui')['NQrCode']
|
||||||
NRadio: typeof import('naive-ui')['NRadio']
|
NRadio: typeof import('naive-ui')['NRadio']
|
||||||
NRadioGroup: typeof import('naive-ui')['NRadioGroup']
|
NRadioGroup: typeof import('naive-ui')['NRadioGroup']
|
||||||
NResult: (typeof import("naive-ui"))["NResult"]
|
|
||||||
NScrollbar: typeof import('naive-ui')['NScrollbar']
|
NScrollbar: typeof import('naive-ui')['NScrollbar']
|
||||||
NSelect: typeof import('naive-ui')['NSelect']
|
NSelect: typeof import('naive-ui')['NSelect']
|
||||||
NSkeleton: typeof import('naive-ui')['NSkeleton']
|
NSkeleton: typeof import('naive-ui')['NSkeleton']
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
"chevron-down": "M7.41 8.58L12 13.17l4.59-4.59L18 10l-6 6l-6-6z",
|
"chevron-down": "M7.41 8.58L12 13.17l4.59-4.59L18 10l-6 6l-6-6z",
|
||||||
"play": "M9.525 18.025q-.5.325-1.012.038T8 17.175V6.825q0-.6.513-.888t1.012.038l8.15 5.175q.45.3.45.85t-.45.85l-8.15 5.175Z",
|
"play": "M9.525 18.025q-.5.325-1.012.038T8 17.175V6.825q0-.6.513-.888t1.012.038l8.15 5.175q.45.3.45.85t-.45.85l-8.15 5.175Z",
|
||||||
"play-circle": "M10 16.5v-9l6 4.5M12 2A10 10 0 0 0 2 12a10 10 0 0 0 10 10a10 10 0 0 0 10-10A10 10 0 0 0 12 2Z",
|
"play-circle": "M10 16.5v-9l6 4.5M12 2A10 10 0 0 0 2 12a10 10 0 0 0 10 10a10 10 0 0 0 10-10A10 10 0 0 0 12 2Z",
|
||||||
|
"pause-circle": "M15 16h-2V8h2m-4 8H9V8h2m1-6A10 10 0 0 0 2 12a10 10 0 0 0 10 10a10 10 0 0 0 10-10A10 10 0 0 0 12 2",
|
||||||
"play-next": "m10 16.5l6-4.5l-6-4.5M22 12c0-5.54-4.46-10-10-10c-1.17 0-2.3.19-3.38.56l.7 1.94c.85-.34 1.74-.53 2.68-.53c4.41 0 8.03 3.62 8.03 8.03c0 4.41-3.62 8.03-8.03 8.03c-4.41 0-8.03-3.62-8.03-8.03c0-.94.19-1.88.53-2.72l-1.94-.66C2.19 9.7 2 10.83 2 12c0 5.54 4.46 10 10 10s10-4.46 10-10M5.47 3.97c.85 0 1.53.71 1.53 1.5C7 6.32 6.32 7 5.47 7c-.79 0-1.5-.68-1.5-1.53c0-.79.71-1.5 1.5-1.5Z",
|
"play-next": "m10 16.5l6-4.5l-6-4.5M22 12c0-5.54-4.46-10-10-10c-1.17 0-2.3.19-3.38.56l.7 1.94c.85-.34 1.74-.53 2.68-.53c4.41 0 8.03 3.62 8.03 8.03c0 4.41-3.62 8.03-8.03 8.03c-4.41 0-8.03-3.62-8.03-8.03c0-.94.19-1.88.53-2.72l-1.94-.66C2.19 9.7 2 10.83 2 12c0 5.54 4.46 10 10 10s10-4.46 10-10M5.47 3.97c.85 0 1.53.71 1.53 1.5C7 6.32 6.32 7 5.47 7c-.79 0-1.5-.68-1.5-1.53c0-.79.71-1.5 1.5-1.5Z",
|
||||||
"playlist-add": "M4 16q-.425 0-.713-.288T3 15q0-.425.288-.713T4 14h5q.425 0 .713.288T10 15q0 .425-.288.713T9 16H4Zm0-4q-.425 0-.713-.288T3 11q0-.425.288-.713T4 10h9q.425 0 .713.288T14 11q0 .425-.288.713T13 12H4Zm0-4q-.425 0-.713-.288T3 7q0-.425.288-.713T4 6h9q.425 0 .713.288T14 7q0 .425-.288.713T13 8H4Zm13 12q-.425 0-.713-.288T16 19v-3h-3q-.425 0-.713-.288T12 15q0-.425.288-.713T13 14h3v-3q0-.425.288-.713T17 10q.425 0 .713.288T18 11v3h3q.425 0 .713.288T22 15q0 .425-.288.713T21 16h-3v3q0 .425-.288.713T17 20Z",
|
"playlist-add": "M4 16q-.425 0-.713-.288T3 15q0-.425.288-.713T4 14h5q.425 0 .713.288T10 15q0 .425-.288.713T9 16H4Zm0-4q-.425 0-.713-.288T3 11q0-.425.288-.713T4 10h9q.425 0 .713.288T14 11q0 .425-.288.713T13 12H4Zm0-4q-.425 0-.713-.288T3 7q0-.425.288-.713T4 6h9q.425 0 .713.288T14 7q0 .425-.288.713T13 8H4Zm13 12q-.425 0-.713-.288T16 19v-3h-3q-.425 0-.713-.288T12 15q0-.425.288-.713T13 14h3v-3q0-.425.288-.713T17 10q.425 0 .713.288T18 11v3h3q.425 0 .713.288T22 15q0 .425-.288.713T21 16h-3v3q0 .425-.288.713T17 20Z",
|
||||||
"account-music": "M11 14c1 0 2.05.16 3.2.44c-.81.87-1.2 1.89-1.2 3.06c0 .89.25 1.73.78 2.5H3v-2c0-1.19.91-2.15 2.74-2.88C7.57 14.38 9.33 14 11 14m0-2c-1.08 0-2-.39-2.82-1.17C7.38 10.05 7 9.11 7 8c0-1.08.38-2 1.18-2.82C9 4.38 9.92 4 11 4c1.11 0 2.05.38 2.83 1.18C14.61 6 15 6.92 15 8c0 1.11-.39 2.05-1.17 2.83c-.78.78-1.72 1.17-2.83 1.17m7.5-2H22v2h-2v5.5a2.5 2.5 0 0 1-2.5 2.5a2.5 2.5 0 0 1-2.5-2.5a2.5 2.5 0 0 1 2.5-2.5c.36 0 .69.07 1 .21V10Z",
|
"account-music": "M11 14c1 0 2.05.16 3.2.44c-.81.87-1.2 1.89-1.2 3.06c0 .89.25 1.73.78 2.5H3v-2c0-1.19.91-2.15 2.74-2.88C7.57 14.38 9.33 14 11 14m0-2c-1.08 0-2-.39-2.82-1.17C7.38 10.05 7 9.11 7 8c0-1.08.38-2 1.18-2.82C9 4.38 9.92 4 11 4c1.11 0 2.05.38 2.83 1.18C14.61 6 15 6.92 15 8c0 1.11-.39 2.05-1.17 2.83c-.78.78-1.72 1.17-2.83 1.17m7.5-2H22v2h-2v5.5a2.5 2.5 0 0 1-2.5 2.5a2.5 2.5 0 0 1-2.5-2.5a2.5 2.5 0 0 1 2.5-2.5c.36 0 .69.07 1 .21V10Z",
|
||||||
|
|||||||
146
src/components/Cover/CoverPlayBtn.vue
Normal file
146
src/components/Cover/CoverPlayBtn.vue
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
<!-- 封面列表 - 播放按钮 -->
|
||||||
|
<template>
|
||||||
|
<div class="play-btn" @click.stop>
|
||||||
|
<n-button
|
||||||
|
:loading="playLoading"
|
||||||
|
color="#efefefde"
|
||||||
|
tag="div"
|
||||||
|
type="primary"
|
||||||
|
class="play"
|
||||||
|
size="large"
|
||||||
|
strong
|
||||||
|
secondary
|
||||||
|
circle
|
||||||
|
@click.stop="playAllSongs"
|
||||||
|
>
|
||||||
|
<template #icon>
|
||||||
|
<Transition name="fade" mode="out-in">
|
||||||
|
<n-icon :key="`${isHasSongs}-${playState}`" size="50">
|
||||||
|
<SvgIcon :icon="isHasSongs !== -1 && playState ? 'pause-circle' : 'play-circle'" />
|
||||||
|
</n-icon>
|
||||||
|
</Transition>
|
||||||
|
</template>
|
||||||
|
</n-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { storeToRefs } from "pinia";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import { getAllPlayList } from "@/api/playlist";
|
||||||
|
import { getAlbumDetail } from "@/api/album";
|
||||||
|
import { getDjProgram } from "@/api/dj";
|
||||||
|
import { musicData, siteStatus } from "@/stores";
|
||||||
|
import { playOrPause, initPlayer } from "@/utils/Player";
|
||||||
|
import formatData from "@/utils/formatData";
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const music = musicData();
|
||||||
|
const status = siteStatus();
|
||||||
|
const { playList, playSongData } = storeToRefs(music);
|
||||||
|
const { playIndex, playMode, playHeartbeatMode, playState } = storeToRefs(status);
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
// id
|
||||||
|
id: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
// 歌单类型
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: "playlist",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// 播放按钮数据
|
||||||
|
const playLoading = ref(false);
|
||||||
|
const playListData = ref(null);
|
||||||
|
|
||||||
|
// 是否处于当前歌单
|
||||||
|
const isHasSongs = computed(() => {
|
||||||
|
if (!playListData.value) return -1;
|
||||||
|
const songId = music.getPlaySongData?.id;
|
||||||
|
const existingIndex = playListData.value.findIndex((song) => song.id === songId);
|
||||||
|
return existingIndex;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取歌单数据
|
||||||
|
const getPlaylistData = async () => {
|
||||||
|
// 为了播放速度,仅加载列表前 500 首
|
||||||
|
console.log(props.type, props.id);
|
||||||
|
// 按列表类别获取数据
|
||||||
|
switch (props.type) {
|
||||||
|
case "playlist": {
|
||||||
|
const result = await getAllPlayList(props.id, 500);
|
||||||
|
return formatData(result.songs, "song");
|
||||||
|
}
|
||||||
|
case "album": {
|
||||||
|
const result = await getAlbumDetail(props.id);
|
||||||
|
return formatData(result.songs, "song");
|
||||||
|
}
|
||||||
|
case "dj": {
|
||||||
|
const result = await getDjProgram(props.id, 500);
|
||||||
|
return formatData(result.programs, "dj");
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 播放歌单
|
||||||
|
const playAllSongs = async () => {
|
||||||
|
try {
|
||||||
|
if (!props.id) return false;
|
||||||
|
// 开启加载状态
|
||||||
|
if (props.type !== "mv") {
|
||||||
|
// 若不处于歌单内
|
||||||
|
if (isHasSongs.value === -1) {
|
||||||
|
playLoading.value = true;
|
||||||
|
// 获取歌单数据
|
||||||
|
playListData.value = await getPlaylistData();
|
||||||
|
console.log(playListData.value);
|
||||||
|
if (!playListData.value) {
|
||||||
|
playLoading.value = false;
|
||||||
|
return $message.error("获取播放列表时出现错误");
|
||||||
|
}
|
||||||
|
console.log("不在歌单内");
|
||||||
|
// 更改模式和歌单
|
||||||
|
playHeartbeatMode.value = false;
|
||||||
|
playMode.value = props.type === "dj" ? "dj" : "normal";
|
||||||
|
playList.value = playListData.value.slice();
|
||||||
|
playSongData.value = playListData.value[0];
|
||||||
|
playIndex.value = 0;
|
||||||
|
// 初始化播放器
|
||||||
|
await initPlayer(true);
|
||||||
|
playLoading.value = false;
|
||||||
|
$message.info("已开始播放", { showIcon: false });
|
||||||
|
}
|
||||||
|
// 若处于歌单内
|
||||||
|
else {
|
||||||
|
console.log("处于歌单内");
|
||||||
|
playSongData.value = playListData.value[isHasSongs.value];
|
||||||
|
playIndex.value = isHasSongs.value;
|
||||||
|
// 播放
|
||||||
|
playOrPause();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 跳转播放器
|
||||||
|
router.push({
|
||||||
|
path: "/videos-player",
|
||||||
|
query: {
|
||||||
|
id: props.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("获取播放列表时出现错误:", error);
|
||||||
|
$message.error("获取播放列表时出现错误");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.play-btn {
|
||||||
|
backdrop-filter: blur(20px);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -56,8 +56,9 @@
|
|||||||
<n-text class="add-desc">{{ item.desc }}</n-text>
|
<n-text class="add-desc">{{ item.desc }}</n-text>
|
||||||
</div>
|
</div>
|
||||||
<!-- 播放按钮 -->
|
<!-- 播放按钮 -->
|
||||||
<n-icon class="play">
|
<CoverPlayBtn v-if="type !== 'artist'" :id="item.id" :type="type" />
|
||||||
<SvgIcon :icon="type !== 'artist' ? 'play-circle' : 'account-music'" />
|
<n-icon v-else class="play-btn">
|
||||||
|
<SvgIcon icon="account-music" />
|
||||||
</n-icon>
|
</n-icon>
|
||||||
</div>
|
</div>
|
||||||
<!-- 信息 -->
|
<!-- 信息 -->
|
||||||
@@ -286,14 +287,18 @@ const jumpLink = (data, type) => {
|
|||||||
-webkit-line-clamp: 2;
|
-webkit-line-clamp: 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.play {
|
.play-btn {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
right: 8px;
|
right: 8px;
|
||||||
bottom: 8px;
|
bottom: 8px;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
color: #efefefde;
|
color: #efefefde;
|
||||||
transform: translateY(6px);
|
transform: translateY(6px);
|
||||||
font-size: 50px;
|
border-radius: 50%;
|
||||||
|
overflow: hidden;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
transition:
|
transition:
|
||||||
opacity 0.3s,
|
opacity 0.3s,
|
||||||
@@ -356,7 +361,7 @@ const jumpLink = (data, type) => {
|
|||||||
top: 0;
|
top: 0;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
.play {
|
.play-btn {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
&:hover {
|
&:hover {
|
||||||
@@ -385,8 +390,8 @@ const jumpLink = (data, type) => {
|
|||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.play {
|
.play-btn {
|
||||||
// display: none;
|
font-size: 50px;
|
||||||
right: auto;
|
right: auto;
|
||||||
bottom: auto;
|
bottom: auto;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user