From 8dab1503320862ef3fe1f2e68f46fe98241a4854 Mon Sep 17 00:00:00 2001 From: ikmkj <1@qq,com> Date: Tue, 29 Jul 2025 21:18:51 +0800 Subject: [PATCH] =?UTF-8?q?feat(playlist):=20=E6=B7=BB=E5=8A=A0=E6=AD=8C?= =?UTF-8?q?=E5=8D=95=E5=86=85=E5=88=A0=E9=99=A4=E6=AD=8C=E6=9B=B2=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 MusicList 组件中添加删除歌曲选项- 在 PlaylistDetail 组件中实现删除歌曲逻辑 - 优化用户交互,增加删除确认提示和删除成功提示 - 更新歌单歌曲数量和列表显示 --- music-qianduan/src/components/MusicList.vue | 16 ++++++- music-qianduan/src/views/PlaylistDetail.vue | 47 ++++++++++++++++++++- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/music-qianduan/src/components/MusicList.vue b/music-qianduan/src/components/MusicList.vue index 8eef1ca..544003f 100644 --- a/music-qianduan/src/components/MusicList.vue +++ b/music-qianduan/src/components/MusicList.vue @@ -105,6 +105,10 @@ 下载歌词 音乐详情 分享 + + + 从歌单中删除 + @@ -181,10 +185,14 @@ const props = defineProps({ detailInMore: { type: Boolean, default: false + }, + isCreator: { + type: Boolean, + default: false } }) -const emit = defineEmits(['update:currentPage', 'update:pageSize', 'page-change', 'collect-change', 'like-change']) +const emit = defineEmits(['update:currentPage', 'update:pageSize', 'page-change', 'collect-change', 'like-change', 'command']) const router = useRouter() @@ -307,6 +315,12 @@ const toggleLike = async (music) => { // 处理下拉菜单命令 const handleCommand = (command, music) => { + // 对于某些命令,直接 emit 出去给父组件处理 + if (['deleteFromPlaylist'].includes(command)) { + emit('command', command, music) + return + } + switch (command) { case 'addToPlaylist': playerStore.addToPlaylist(music) diff --git a/music-qianduan/src/views/PlaylistDetail.vue b/music-qianduan/src/views/PlaylistDetail.vue index cbc9574..4ed2157 100644 --- a/music-qianduan/src/views/PlaylistDetail.vue +++ b/music-qianduan/src/views/PlaylistDetail.vue @@ -4,7 +4,7 @@ import { useRoute, useRouter } from 'vue-router' import { usePlayerStore } from '../stores/player' import { useUserStore } from '../stores/user' import { ElMessage, ElMessageBox } from 'element-plus' -import { getPlaylistById, toggleCollectPlaylist, deletePlaylist as apiDeletePlaylist, isPlaylistCollected, updatePlaylist, playPlaylist } from '../api/playlist' +import { getPlaylistById, toggleCollectPlaylist, deletePlaylist as apiDeletePlaylist, isPlaylistCollected, updatePlaylist, playPlaylist, removeMusicFromPlaylist } from '../api/playlist' import { getMusicStatus } from '../api/music' import { getCommentList, addComment, deleteComment as apiDeleteComment } from '../api/comment' import { connect, subscribe, unsubscribe, disconnect } from '../utils/websocket' // 导入 WebSocket 工具 @@ -453,6 +453,9 @@ const handleCommand = (command, music) => { case 'downloadLyric': downloadFile('lyric', music) break + case 'deleteFromPlaylist': + deleteFromPlaylist(music) + break } } @@ -472,6 +475,46 @@ const downloadFile = (type, music) => { }) } +// 从歌单中删除歌曲 +const deleteFromPlaylist = async (music) => { + if (!isCreator.value) { + ElMessage.warning('只有创建者才能删除歌曲') + return + } + + try { + await ElMessageBox.confirm(`确定要从歌单中移除歌曲《${music.name}》吗?`, '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning' + }) + + const res = await removeMusicFromPlaylist(playlistId.value, music.id) + if (res.code === 200) { + ElMessage.success('歌曲已移除') + // 从 UI 中移除歌曲 + const index = playlist.value.songs.findIndex(s => s.id === music.id) + if (index !== -1) { + playlist.value.songs.splice(index, 1) + } + // 更新歌曲数量 + if (playlist.value.musicCount > 0) { + playlist.value.musicCount-- + } + if (playlist.value.songCount > 0) { + playlist.value.songCount-- + } + } else { + ElMessage.error(res.message || '移除失败') + } + } catch (error) { + if (error !== 'cancel') { + console.error('移除歌曲失败:', error) + ElMessage.error('移除失败,请稍后重试') + } + } +} + // WebSocket 订阅实例 let commentSubscription = null; @@ -582,6 +625,8 @@ onUnmounted(() => { :loading="loading" :show-pagination="false" :detail-in-more="true" + :is-creator="isCreator" + @command="handleCommand" />