feat(playlist): 添加歌单编辑功能
- 在前端 PlaylistDetail组件中添加编辑歌单的对话框和相关逻辑 - 在后端 PlaylistServiceImpl 中实现更新歌单信息和封面的方法 - 优化封面上传逻辑,将物理路径转换为相对路径
This commit is contained in:
@@ -36,6 +36,7 @@ import org.springframework.util.StringUtils;
|
|||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import jakarta.persistence.criteria.Predicate;
|
import jakarta.persistence.criteria.Predicate;
|
||||||
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -237,7 +238,8 @@ public class PlaylistServiceImpl implements PlaylistService {
|
|||||||
// 上传封面
|
// 上传封面
|
||||||
String coverUrl = null;
|
String coverUrl = null;
|
||||||
if (cover != null && !cover.isEmpty()) {
|
if (cover != null && !cover.isEmpty()) {
|
||||||
coverUrl = fileService.uploadImage(cover);
|
String coverPhysicalPath = fileService.uploadImage(cover);
|
||||||
|
coverUrl = coverPhysicalPath.replace(System.getProperty("user.dir") + File.separator + "music-houduan", "").replace(File.separator, "/");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建歌单实体
|
// 创建歌单实体
|
||||||
@@ -286,7 +288,8 @@ public class PlaylistServiceImpl implements PlaylistService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 上传新封面
|
// 上传新封面
|
||||||
String coverUrl = fileService.uploadImage(cover);
|
String coverPhysicalPath = fileService.uploadImage(cover);
|
||||||
|
String coverUrl = coverPhysicalPath.replace(System.getProperty("user.dir") + File.separator + "music-houduan", "").replace(File.separator, "/");
|
||||||
playlist.setCover(coverUrl);
|
playlist.setCover(coverUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { useRoute, useRouter } from 'vue-router'
|
|||||||
import { usePlayerStore } from '../stores/player'
|
import { usePlayerStore } from '../stores/player'
|
||||||
import { useUserStore } from '../stores/user'
|
import { useUserStore } from '../stores/user'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import { getPlaylistById, toggleCollectPlaylist, deletePlaylist as apiDeletePlaylist, isPlaylistCollected } from '../api/playlist'
|
import { getPlaylistById, toggleCollectPlaylist, deletePlaylist as apiDeletePlaylist, isPlaylistCollected, updatePlaylist } from '../api/playlist'
|
||||||
import { getMusicStatus } from '../api/music'
|
import { getMusicStatus } from '../api/music'
|
||||||
import { getCommentList, addComment, deleteComment as apiDeleteComment } from '../api/comment'
|
import { getCommentList, addComment, deleteComment as apiDeleteComment } from '../api/comment'
|
||||||
import { connect, subscribe, unsubscribe, disconnect } from '../utils/websocket' // 导入 WebSocket 工具
|
import { connect, subscribe, unsubscribe, disconnect } from '../utils/websocket' // 导入 WebSocket 工具
|
||||||
@@ -49,6 +49,20 @@ const isCollected = ref(false)
|
|||||||
// 是否是创建者
|
// 是否是创建者
|
||||||
const isCreator = ref(false)
|
const isCreator = ref(false)
|
||||||
|
|
||||||
|
// 编辑模态框可见性
|
||||||
|
const editDialogVisible = ref(false)
|
||||||
|
|
||||||
|
// 编辑表单数据
|
||||||
|
const editForm = ref({
|
||||||
|
id: null,
|
||||||
|
name: '',
|
||||||
|
description: '',
|
||||||
|
cover: null
|
||||||
|
})
|
||||||
|
|
||||||
|
// 封面预览 URL
|
||||||
|
const coverPreview = ref('')
|
||||||
|
|
||||||
// 获取歌单详情
|
// 获取歌单详情
|
||||||
const fetchPlaylistDetail = async () => {
|
const fetchPlaylistDetail = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
@@ -297,8 +311,42 @@ const editPlaylist = () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 实际应用中,这里应该跳转到编辑页面或打开编辑对话框
|
// 初始化编辑表单
|
||||||
ElMessage.info('编辑歌单功能开发中')
|
editForm.value = {
|
||||||
|
id: playlist.value.id,
|
||||||
|
name: playlist.value.name,
|
||||||
|
description: playlist.value.description,
|
||||||
|
cover: null
|
||||||
|
}
|
||||||
|
coverPreview.value = playlist.value.cover
|
||||||
|
editDialogVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理封面选择
|
||||||
|
const handleCoverChange = (file) => {
|
||||||
|
editForm.value.cover = file.raw
|
||||||
|
coverPreview.value = URL.createObjectURL(file.raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交编辑
|
||||||
|
const submitEdit = async () => {
|
||||||
|
try {
|
||||||
|
const res = await updatePlaylist(editForm.value.id, {
|
||||||
|
name: editForm.value.name,
|
||||||
|
description: editForm.value.description
|
||||||
|
}, editForm.value.cover)
|
||||||
|
|
||||||
|
if (res.code === 200) {
|
||||||
|
ElMessage.success('歌单更新成功')
|
||||||
|
editDialogVisible.value = false
|
||||||
|
fetchPlaylistDetail()
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res.message || '更新失败')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('更新歌单失败:', error)
|
||||||
|
ElMessage.error('更新失败,请稍后重试')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除歌单
|
// 删除歌单
|
||||||
@@ -599,10 +647,52 @@ onUnmounted(() => {
|
|||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<!-- 编辑歌单对话框 -->
|
||||||
|
<el-dialog v-model="editDialogVisible" title="编辑歌单" width="500px">
|
||||||
|
<el-form :model="editForm" label-width="80px">
|
||||||
|
<el-form-item label="歌单名称">
|
||||||
|
<el-input v-model="editForm.name" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="歌单描述">
|
||||||
|
<el-input v-model="editForm.description" type="textarea" :rows="3" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="封面">
|
||||||
|
<el-upload
|
||||||
|
class="cover-uploader"
|
||||||
|
action="#"
|
||||||
|
:show-file-list="false"
|
||||||
|
:auto-upload="false"
|
||||||
|
@change="handleCoverChange"
|
||||||
|
>
|
||||||
|
<img v-if="coverPreview" :src="coverPreview" class="cover" />
|
||||||
|
<el-icon v-else class="cover-uploader-icon"><plus /></el-icon>
|
||||||
|
</el-upload>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="editDialogVisible = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="submitEdit">确定</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.cover-uploader .cover {
|
||||||
|
width: 178px;
|
||||||
|
height: 178px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.cover-uploader-icon {
|
||||||
|
font-size: 28px;
|
||||||
|
color: #8c939d;
|
||||||
|
width: 178px;
|
||||||
|
height: 178px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
.playlist-detail-container {
|
.playlist-detail-container {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
min-height: calc(100vh - 140px);
|
min-height: calc(100vh - 140px);
|
||||||
|
|||||||
Reference in New Issue
Block a user