feat(user): 为收藏音乐页面添加更多操作功能

- 添加下拉菜单,支持多种操作
- 实现添加到播放列表、下一首播放、下载音乐、下载歌词等功能
- 优化用户交互,增加确认对话框和提示消息
This commit is contained in:
ikmkj
2025-07-26 12:07:45 +08:00
parent 4b4aaedeef
commit 258215a4e6
7 changed files with 310 additions and 34 deletions

View File

@@ -99,8 +99,9 @@
<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 command="downloadLyric">下载歌词</el-dropdown-item>
<el-dropdown-item command="share" v-if="false">分享</el-dropdown-item>
<el-dropdown-item command="download" v-if="false">下载</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
@@ -128,7 +129,7 @@ import { useRouter } from 'vue-router'
import { VideoPlay, VideoPause, Star, More, InfoFilled, Pointer } from '@element-plus/icons-vue'
import { usePlayerStore } from '../stores/player'
import { toggleCollectMusic, toggleLikeMusic } from '../api/music'
import { ElMessage } from 'element-plus'
import { ElMessage, ElMessageBox } from 'element-plus'
const props = defineProps({
list: {
@@ -258,12 +259,31 @@ const handleCommand = (command, music) => {
case 'share':
ElMessage.info('分享功能开发中')
break
case 'download':
ElMessage.info('下载功能开发中')
case 'downloadMusic':
downloadFile('music', music)
break
case 'downloadLyric':
downloadFile('lyric', music)
break
}
}
// 下载文件
const downloadFile = (type, music) => {
const typeName = type === 'music' ? '音乐' : '歌词'
ElMessageBox.confirm(`确定要下载《${music.name}》的${typeName}吗?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'info'
}).then(() => {
const url = `/api/file/download/${type}/${music.id}`
window.open(url, '_blank')
ElMessage.success(`${typeName}开始下载...`)
}).catch(() => {
ElMessage.info(`已取消下载${typeName}`)
})
}
// 格式化时长
const formatDuration = (seconds) => {
if (!seconds) return '00:00'

View File

@@ -331,6 +331,54 @@ const formatPlayCount = (count) => {
}
}
// 处理下拉菜单命令
const handleCommand = (command, music) => {
switch (command) {
case 'addToPlaylist':
playerStore.addToPlaylist(music)
ElMessage.success('已添加到播放列表')
break
case 'playNext':
const currentIndex = playerStore.getCurrentIndex
if (currentIndex !== -1) {
const playlist = [...playerStore.getPlaylist]
const existingIndex = playlist.findIndex(item => item.id === music.id)
if (existingIndex !== -1) {
playlist.splice(existingIndex, 1)
}
playlist.splice(currentIndex + 1, 0, music)
playerStore.$patch({ playlist })
ElMessage.success('已添加到下一首播放')
} else {
playerStore.addToPlaylist(music)
ElMessage.success('已添加到播放列表')
}
break
case 'downloadMusic':
downloadFile('music', music)
break
case 'downloadLyric':
downloadFile('lyric', music)
break
}
}
// 下载文件
const downloadFile = (type, music) => {
const typeName = type === 'music' ? '音乐' : '歌词'
ElMessageBox.confirm(`确定要下载《${music.name}》的${typeName}吗?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'info'
}).then(() => {
const url = `/api/file/download/${type}/${music.id}`
window.open(url, '_blank')
ElMessage.success(`${typeName}开始下载...`)
}).catch(() => {
ElMessage.info(`已取消下载${typeName}`)
})
}
// WebSocket 订阅实例
let commentSubscription = null;
@@ -484,14 +532,21 @@ onUnmounted(() => {
</template>
</el-table-column>
<el-table-column label="操作" width="100" align="center">
<el-table-column label="操作" width="120" align="center">
<template #default="scope">
<el-button
icon="Plus"
circle
size="small"
@click.stop="addToPlaylist(scope.row)"
></el-button>
<el-dropdown trigger="click" @command="handleCommand($event, scope.row)">
<el-button circle size="small">
<el-icon><More /></el-icon>
</el-button>
<template #dropdown>
<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 command="downloadLyric">下载歌词</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
</el-table-column>
</el-table>

View File

@@ -147,7 +147,7 @@ const playAll = () => {
// 播放第一首
playerStore.setCurrentMusic({
...songs.value[0],
...songs.value,
singer: singer.value.name
})
@@ -317,6 +317,52 @@ const deleteComment = async (commentId) => {
}
}
// 处理下拉菜单命令
const handleCommand = (command, music) => {
switch (command) {
case 'addToPlaylist':
addToPlaylist(music)
break
case 'playNext':
const currentIndex = playerStore.getCurrentIndex
if (currentIndex !== -1) {
const playlist = [...playerStore.getPlaylist]
const existingIndex = playlist.findIndex(item => item.id === music.id)
if (existingIndex !== -1) {
playlist.splice(existingIndex, 1)
}
playlist.splice(currentIndex + 1, 0, music)
playerStore.$patch({ playlist })
ElMessage.success('已添加到下一首播放')
} else {
playerStore.addToPlaylist(music)
ElMessage.success('已添加到播放列表')
}
break
case 'downloadMusic':
downloadFile('music', music)
break
case 'downloadLyric':
downloadFile('lyric', music)
break
}
}
// 下载文件
const downloadFile = (type, music) => {
const typeName = type === 'music' ? '音乐' : '歌词'
ElMessageBox.confirm(`确定要下载《${music.name}》的${typeName}吗?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'info'
}).then(() => {
const url = `/api/file/download/${type}/${music.id}`
window.open(url, '_blank')
ElMessage.success(`${typeName}开始下载...`)
}).catch(() => {
ElMessage.info(`已取消下载${typeName}`)
})
}
// 格式化时间
@@ -497,14 +543,21 @@ onUnmounted(() => {
</template>
</el-table-column>
<el-table-column label="操作" width="100" align="center">
<el-table-column label="操作" width="120" align="center">
<template #default="scope">
<el-button
icon="Plus"
circle
size="small"
@click.stop="addToPlaylist(scope.row)"
></el-button>
<el-dropdown trigger="click" @command="handleCommand($event, scope.row)">
<el-button circle size="small">
<el-icon><More /></el-icon>
</el-button>
<template #dropdown>
<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 command="downloadLyric">下载歌词</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
</el-table-column>
</el-table>

View File

@@ -99,6 +99,56 @@ const playAll = () => {
ElMessage.success('开始播放全部收藏音乐')
}
// 处理下拉菜单命令
const handleCommand = (command, music) => {
switch (command) {
case 'addToPlaylist':
addToPlaylist(music)
break
case 'playNext':
const currentIndex = playerStore.getCurrentIndex
if (currentIndex !== -1) {
const playlist = [...playerStore.getPlaylist]
const existingIndex = playlist.findIndex(item => item.id === music.id)
if (existingIndex !== -1) {
playlist.splice(existingIndex, 1)
}
playlist.splice(currentIndex + 1, 0, music)
playerStore.$patch({ playlist })
ElMessage.success('已添加到下一首播放')
} else {
playerStore.addToPlaylist(music)
ElMessage.success('已添加到播放列表')
}
break
case 'downloadMusic':
downloadFile('music', music)
break
case 'downloadLyric':
downloadFile('lyric', music)
break
case 'cancelCollect':
cancelCollect(music.id)
break
}
}
// 下载文件
const downloadFile = (type, music) => {
const typeName = type === 'music' ? '音乐' : '歌词'
ElMessageBox.confirm(`确定要下载《${music.name}》的${typeName}吗?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'info'
}).then(() => {
const url = `/api/file/download/${type}/${music.id}`
window.open(url, '_blank')
ElMessage.success(`${typeName}开始下载...`)
}).catch(() => {
ElMessage.info(`已取消下载${typeName}`)
})
}
// 格式化时间
const formatTime = (seconds) => {
const mins = Math.floor(seconds / 60)
@@ -167,20 +217,20 @@ onMounted(() => {
<el-table-column label="操作" width="150" align="center">
<template #default="scope">
<el-button
icon="Delete"
circle
size="small"
type="danger"
@click="cancelCollect(scope.row.id)"
></el-button>
<el-button
icon="Plus"
circle
size="small"
@click="addToPlaylist(scope.row)"
></el-button>
<el-dropdown trigger="click" @command="handleCommand($event, scope.row)">
<el-button circle size="small">
<el-icon><More /></el-icon>
</el-button>
<template #dropdown>
<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 command="downloadLyric">下载歌词</el-dropdown-item>
<el-dropdown-item command="cancelCollect" divided>取消收藏</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
</el-table-column>
</el-table>