feat(music-list): 添加音乐到用户歌单功能
- 新增"添加到我的歌单"选项,仅在用户登录时显示- 实现用户歌单获取和音乐添加到歌单的功能 - 添加相关API调用和错误处理 - 优化分页配置,使用本地状态管理
This commit is contained in:
@@ -100,7 +100,8 @@
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item command="addToPlaylist">添加到播放列表</el-dropdown-item>
|
||||
<el-dropdown-item command="playNext">下一首播放</el-dropdown-item>
|
||||
<el-dropdown-item command="downloadMusic">下载音乐</el-dropdown-item>
|
||||
<el-dropdown-item v-if="userStore.isLoggedIn" command="showAddToPlaylistDialog" divided>添加到我的歌单</el-dropdown-item>
|
||||
<el-dropdown-item command="downloadMusic" :divided="!userStore.isLoggedIn">下载音乐</el-dropdown-item>
|
||||
<el-dropdown-item command="downloadLyric">下载歌词</el-dropdown-item>
|
||||
<el-dropdown-item v-if="detailInMore" command="goToMusicDetail">音乐详情</el-dropdown-item>
|
||||
<el-dropdown-item command="share" v-if="false">分享</el-dropdown-item>
|
||||
@@ -115,13 +116,30 @@
|
||||
<el-pagination
|
||||
v-model:current-page="localCurrentPage"
|
||||
v-model:page-size="localPageSize"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
:page-sizes="pageSizes"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="total"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 添加到歌单弹窗 -->
|
||||
<el-dialog v-model="isAddToPlaylistDialogVisible" title="添加到歌单" width="300px">
|
||||
<div v-loading="loadingUserPlaylists" class="dialog-playlist-container">
|
||||
<ul v-if="userPlaylists.length > 0" class="dialog-playlist-list">
|
||||
<li
|
||||
v-for="playlist in userPlaylists"
|
||||
:key="playlist.id"
|
||||
class="dialog-playlist-item"
|
||||
@click="handleAddToPlaylist(currentMusicToAdd, playlist.id)"
|
||||
>
|
||||
{{ playlist.name }}
|
||||
</li>
|
||||
</ul>
|
||||
<el-empty v-else-if="!loadingUserPlaylists" description="您还没有创建过歌单" />
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -130,7 +148,9 @@ import { ref, computed, watch } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { VideoPlay, VideoPause, Star, More, InfoFilled, Pointer } from '@element-plus/icons-vue'
|
||||
import { usePlayerStore } from '../stores/player'
|
||||
import { useUserStore } from '../stores/user'
|
||||
import { toggleCollectMusic, toggleLikeMusic } from '../api/music'
|
||||
import { getUserPlaylist, addMusicToPlaylist } from '../api/playlist'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
|
||||
const props = defineProps({
|
||||
@@ -171,6 +191,7 @@ const router = useRouter()
|
||||
// 使用本地状态来代替直接绑定到props
|
||||
const localCurrentPage = ref(props.currentPage)
|
||||
const localPageSize = ref(props.pageSize)
|
||||
const pageSizes = [10, 20, 50, 100] // 添加分页大小选项
|
||||
|
||||
// 监听props变化,更新本地状态
|
||||
watch(() => props.currentPage, (newVal) => {
|
||||
@@ -182,6 +203,52 @@ watch(() => props.pageSize, (newVal) => {
|
||||
})
|
||||
|
||||
const playerStore = usePlayerStore()
|
||||
const userStore = useUserStore()
|
||||
|
||||
const userPlaylists = ref([])
|
||||
const loadingUserPlaylists = ref(false)
|
||||
const isAddToPlaylistDialogVisible = ref(false)
|
||||
const currentMusicToAdd = ref(null)
|
||||
|
||||
// 获取用户创建的歌单
|
||||
const fetchUserPlaylists = async () => {
|
||||
if (!userStore.isLoggedIn) {
|
||||
userPlaylists.value = []
|
||||
return
|
||||
}
|
||||
loadingUserPlaylists.value = true
|
||||
try {
|
||||
// 获取用户所有歌单,这里设置一个比较大的size
|
||||
const res = await getUserPlaylist(1, 200)
|
||||
if (res.code === 200) {
|
||||
userPlaylists.value = res.data.records || res.data.list || []
|
||||
} else {
|
||||
ElMessage.error(res.message || '获取您的歌单失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取用户歌单失败:', error)
|
||||
ElMessage.error('获取您的歌单失败')
|
||||
} finally {
|
||||
loadingUserPlaylists.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 将音乐添加到歌单
|
||||
const handleAddToPlaylist = async (music, playlistId) => {
|
||||
if (!music || !playlistId) return
|
||||
try {
|
||||
const res = await addMusicToPlaylist(playlistId, music.id)
|
||||
if (res.code === 200 && res.data) {
|
||||
ElMessage.success(`已将《${music.name}》添加到歌单`)
|
||||
isAddToPlaylistDialogVisible.value = false
|
||||
} else {
|
||||
ElMessage.error(res.message || '添加失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('添加到歌单失败:', error)
|
||||
ElMessage.error('添加失败,请稍后重试')
|
||||
}
|
||||
}
|
||||
|
||||
// 跳转到音乐详情页
|
||||
const goToMusicDetail = (id) => {
|
||||
@@ -262,6 +329,11 @@ const handleCommand = (command, music) => {
|
||||
ElMessage.success('已添加到播放列表')
|
||||
}
|
||||
break
|
||||
case 'showAddToPlaylistDialog':
|
||||
currentMusicToAdd.value = music
|
||||
fetchUserPlaylists()
|
||||
isAddToPlaylistDialogVisible.value = true
|
||||
break
|
||||
case 'share':
|
||||
ElMessage.info('分享功能开发中')
|
||||
break
|
||||
@@ -318,6 +390,29 @@ const handleCurrentChange = (page) => {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.dialog-playlist-container {
|
||||
min-height: 150px;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.dialog-playlist-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.dialog-playlist-item {
|
||||
padding: 10px 15px;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.dialog-playlist-item:hover {
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
|
||||
.music-list {
|
||||
width: 100%;
|
||||
border-radius: 8px;
|
||||
|
||||
Reference in New Issue
Block a user