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

@@ -1,12 +1,27 @@
package com.test.musichouduan.controller;
import cn.dev33.satoken.annotation.SaCheckLogin;
import com.test.musichouduan.entity.Music;
import com.test.musichouduan.service.MusicService;
import com.test.musichouduan.dto.Result;
import com.test.musichouduan.service.FileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
/**
* 文件控制器
*/
@@ -16,7 +31,8 @@ public class FileController {
@Autowired
private FileService fileService;
@Autowired
private MusicService musicService;
/**
* 上传图片
*
@@ -68,4 +84,73 @@ public class FileController {
boolean result = fileService.deleteFile(url);
return Result.success("删除成功", result);
}
/**
* 下载音乐
*
* @param musicId 音乐ID
* @return 响应实体
*/
@GetMapping("/download/music/{musicId}")
public ResponseEntity<Resource> downloadMusic(@PathVariable Integer musicId) throws IOException {
// 1. 根据 musicId 获取音乐信息
Music music = musicService.findMusicById(musicId);
if (music == null || music.getUrl() == null || music.getUrl().isEmpty()) {
return ResponseEntity.notFound().build();
}
// 2. 获取文件路径
String fileUrl = music.getUrl(); // 格式: /upload/musics/xxxxxxxx.mp3
String filePath = "music-houduan" + fileUrl; // 转换为相对项目路径
Path path = Paths.get(filePath);
Resource resource = new InputStreamResource(Files.newInputStream(path));
// 3. 设置响应头
HttpHeaders headers = new HttpHeaders();
String filename = music.getName() + ".mp3"; // 使用音乐名作为文件名
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + URLEncoder.encode(filename, StandardCharsets.UTF_8.name()));
headers.add(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, must-revalidate");
headers.add(HttpHeaders.PRAGMA, "no-cache");
headers.add(HttpHeaders.EXPIRES, "0");
return ResponseEntity.ok()
.headers(headers)
.contentLength(Files.size(path))
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(resource);
}
/**
* 下载歌词
*
* @param musicId 音乐ID
* @return 响应实体
*/
@GetMapping("/download/lyric/{musicId}")
public ResponseEntity<Resource> downloadLyric(@PathVariable Integer musicId) throws IOException {
// 1. 根据 musicId 获取音乐信息
Music music = musicService.findMusicById(musicId);
if (music == null || music.getLyric() == null || music.getLyric().isEmpty()) {
return ResponseEntity.notFound().build();
}
// 2. 将歌词文本转换为输入流
String lyricContent = music.getLyric();
byte[] lyricBytes = lyricContent.getBytes(StandardCharsets.UTF_8);
Resource resource = new InputStreamResource(new ByteArrayInputStream(lyricBytes));
// 3. 设置响应头
HttpHeaders headers = new HttpHeaders();
String filename = music.getName() + ".lrc"; // 使用音乐名作为文件名
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + URLEncoder.encode(filename, StandardCharsets.UTF_8.name()));
headers.add(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, must-revalidate");
headers.add(HttpHeaders.PRAGMA, "no-cache");
headers.add(HttpHeaders.EXPIRES, "0");
return ResponseEntity.ok()
.headers(headers)
.contentLength(lyricBytes.length)
.contentType(MediaType.TEXT_PLAIN)
.body(resource);
}
}

View File

@@ -161,4 +161,12 @@ public interface MusicService {
* @return 音乐状态DTO
*/
MusicStatusDTO getMusicStatus(Long musicId, Long userId);
/**
* 根据ID查找音乐实体
*
* @param musicId 音乐ID
* @return 音乐实体
*/
Music findMusicById(Integer musicId);
}

View File

@@ -615,6 +615,11 @@ public class MusicServiceImpl implements MusicService {
return new MusicStatusDTO(isCollected, isLiked);
}
@Override
public Music findMusicById(Integer musicId) {
return musicRepository.findById(musicId.longValue()).orElse(null);
}
/**
* 将实体转换为DTO
*