From 4435315acf064d8c21342a939c4e3fbab5b6c82c Mon Sep 17 00:00:00 2001 From: ikmkj <1@qq,com> Date: Fri, 25 Jul 2025 23:25:45 +0800 Subject: [PATCH] =?UTF-8?q?feat(music):=20=E6=B7=BB=E5=8A=A0=E9=9F=B3?= =?UTF-8?q?=E4=B9=90=E7=82=B9=E8=B5=9E=E5=8A=9F=E8=83=BD=E5=8F=8A=E5=89=8D?= =?UTF-8?q?=E7=AB=AF=E4=BA=A4=E4=BA=92=20-=20=E5=90=8E=E7=AB=AF=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E7=82=B9=E8=B5=9E=E6=8E=A5=E5=8F=A3=20/music/{id}/lik?= =?UTF-8?q?e=EF=BC=8C=E6=94=AF=E6=8C=81=E7=94=A8=E6=88=B7=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E5=90=8E=E7=82=B9=E8=B5=9E/=E5=8F=96=E6=B6=88?= =?UTF-8?q?=E7=82=B9=E8=B5=9E=E9=9F=B3=E4=B9=90=EF=BC=8C=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E7=82=B9=E8=B5=9E=E6=95=B0=E6=8D=AE=E5=88=B0=20user=5Flike=5Fm?= =?UTF-8?q?usic=20=E8=A1=A8=20-=20=E5=90=8E=E7=AB=AF=E4=BF=AE=E6=94=B9=20M?= =?UTF-8?q?usicController.getMusicById=20=E6=8E=A5=E5=8F=A3=EF=BC=8C?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E4=BC=A0=E5=85=A5=E7=94=A8=E6=88=B7ID?= =?UTF-8?q?=E4=BB=A5=E5=88=A4=E6=96=AD=E5=BD=93=E5=89=8D=E9=9F=B3=E4=B9=90?= =?UTF-8?q?=E6=98=AF=E5=90=A6=E8=A2=AB=E8=AF=A5=E7=94=A8=E6=88=B7=E7=82=B9?= =?UTF-8?q?=E8=B5=9E=20-=20=E5=90=8E=E7=AB=AF=20MusicDTO=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=20isLiked=20=E5=AD=97=E6=AE=B5=EF=BC=8C=E7=94=A8?= =?UTF-8?q?=E4=BA=8E=E5=89=8D=E7=AB=AF=E5=B1=95=E7=A4=BA=E7=82=B9=E8=B5=9E?= =?UTF-8?q?=E7=8A=B6=E6=80=81=20-=20=E6=95=B0=E6=8D=AE=E5=BA=93=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=20user=5Flike=5Fmusic=20=E8=A1=A8=EF=BC=8C=E8=AE=B0?= =?UTF-8?q?=E5=BD=95=E7=94=A8=E6=88=B7=E4=B8=8E=E9=9F=B3=E4=B9=90=E7=9A=84?= =?UTF-8?q?=E7=82=B9=E8=B5=9E=E5=85=B3=E7=B3=BB=EF=BC=8C=E5=8C=85=E5=90=AB?= =?UTF-8?q?=E5=94=AF=E4=B8=80=E7=BA=A6=E6=9D=9F=E9=98=B2=E6=AD=A2=E9=87=8D?= =?UTF-8?q?=E5=A4=8D=E7=82=B9=E8=B5=9E=20-=20=E5=89=8D=E7=AB=AF=20MusicDet?= =?UTF-8?q?ail.vue=20=E9=A1=B5=E9=9D=A2=E6=96=B0=E5=A2=9E=E7=82=B9?= =?UTF-8?q?=E8=B5=9E=E6=8C=89=E9=92=AE=E5=8F=8A=E7=8A=B6=E6=80=81=E5=B1=95?= =?UTF-8?q?=E7=A4=BA=EF=BC=8C=E6=94=AF=E6=8C=81=E7=82=B9=E5=87=BB=E5=88=87?= =?UTF-8?q?=E6=8D=A2=E7=82=B9=E8=B5=9E=E7=8A=B6=E6=80=81=E5=B9=B6=E5=AE=9E?= =?UTF-8?q?=E6=97=B6=E6=9B=B4=E6=96=B0=20UI=20=E4=B8=8E=E7=82=B9=E8=B5=9E?= =?UTF-8?q?=E6=95=B0=20-=20=E5=89=8D=E7=AB=AF=E6=96=B0=E5=A2=9E=20toggleLi?= =?UTF-8?q?keMusic=20API=20=E8=B0=83=E7=94=A8=E5=8F=8A=E7=9B=B8=E5=BA=94?= =?UTF-8?q?=E4=BA=A4=E4=BA=92=E9=80=BB=E8=BE=91=EF=BC=8C=E6=88=90=E5=8A=9F?= =?UTF-8?q?=E5=90=8E=E5=B1=95=E7=A4=BA=E6=93=8D=E4=BD=9C=E6=8F=90=E7=A4=BA?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=20-=20=E8=AF=84=E8=AE=BA=E8=A1=A8=20comment?= =?UTF-8?q?=20=E6=96=B0=E5=A2=9E=20target=5Ftype=20=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E6=B3=A8=E9=87=8A=E5=8F=8A=E7=8A=B6=E6=80=81=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E6=B3=A8=E9=87=8A=EF=BC=8C=E6=92=AD=E6=94=BE=E5=8E=86=E5=8F=B2?= =?UTF-8?q?=E4=B8=8E=E5=90=84=E5=85=B3=E8=81=94=E8=A1=A8=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E7=B4=A2=E5=BC=95=E4=BC=98=E5=8C=96=E4=B8=8E=E5=A4=96=E9=94=AE?= =?UTF-8?q?=E7=BA=A6=E6=9D=9F=E5=BE=AE=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/MusicController.java | 23 +- .../com/test/musichouduan/dto/MusicDTO.java | 12 + .../musichouduan/entity/UserLikeMusic.java | 29 +++ .../musichouduan/init/DataInitializer.java | 218 +++++++++--------- .../UserCollectMusicRepository.java | 9 + .../repository/UserLikeMusicRepository.java | 29 +++ .../musichouduan/service/MusicService.java | 18 ++ .../service/impl/MusicServiceImpl.java | 176 ++++++++------ music-qianduan/src/api/music.js | 9 + music-qianduan/src/views/MusicDetail.vue | 38 ++- sql/music_db.sql | 118 +++++----- 11 files changed, 431 insertions(+), 248 deletions(-) create mode 100644 music-houduan/src/main/java/com/test/musichouduan/entity/UserLikeMusic.java create mode 100644 music-houduan/src/main/java/com/test/musichouduan/repository/UserLikeMusicRepository.java diff --git a/music-houduan/src/main/java/com/test/musichouduan/controller/MusicController.java b/music-houduan/src/main/java/com/test/musichouduan/controller/MusicController.java index 3dad514..0e4252e 100644 --- a/music-houduan/src/main/java/com/test/musichouduan/controller/MusicController.java +++ b/music-houduan/src/main/java/com/test/musichouduan/controller/MusicController.java @@ -31,7 +31,12 @@ public class MusicController { */ @GetMapping("/{id}") public Result getMusicById(@PathVariable Long id) { - MusicDTO musicDTO = musicService.getMusicById(id); + Long userId = null; + // 检查用户是否登录,但不强制要求登录 + if (StpUtil.isLogin()) { + userId = StpUtil.getLoginIdAsLong(); + } + MusicDTO musicDTO = musicService.getMusicById(id, userId); if (musicDTO == null) { // 如果音乐不存在,返回空数据而不是错误 return Result.success(null); @@ -213,4 +218,20 @@ public class MusicController { MusicDTO musicDTO = musicService.playMusic(id); return Result.success(musicDTO); } + + /** + * 点赞/取消点赞音乐 + * + * @param id 音乐ID + * @return 响应结果 + */ + @SaCheckLogin + @PostMapping("/{id}/like") + public Result toggleLikeMusic(@PathVariable Long id) { + // 获取当前登录用户ID + Long userId = StpUtil.getLoginIdAsLong(); + boolean isLiked = musicService.toggleLikeMusic(id, userId); + String message = isLiked ? "点赞成功" : "取消点赞成功"; + return Result.success(message, isLiked); + } } diff --git a/music-houduan/src/main/java/com/test/musichouduan/dto/MusicDTO.java b/music-houduan/src/main/java/com/test/musichouduan/dto/MusicDTO.java index fa29e6f..46e29ea 100644 --- a/music-houduan/src/main/java/com/test/musichouduan/dto/MusicDTO.java +++ b/music-houduan/src/main/java/com/test/musichouduan/dto/MusicDTO.java @@ -91,6 +91,11 @@ public class MusicDTO { */ private Boolean isCollected; + /** + * 是否已点赞 + */ + private Boolean isLiked; + /** * 创建时间 */ @@ -107,4 +112,11 @@ public class MusicDTO { public void setCollected(boolean collected) { this.isCollected = collected; } + + /** + * 设置是否已点赞 + */ + public void setLiked(boolean liked) { + this.isLiked = liked; + } } diff --git a/music-houduan/src/main/java/com/test/musichouduan/entity/UserLikeMusic.java b/music-houduan/src/main/java/com/test/musichouduan/entity/UserLikeMusic.java new file mode 100644 index 0000000..12fe23b --- /dev/null +++ b/music-houduan/src/main/java/com/test/musichouduan/entity/UserLikeMusic.java @@ -0,0 +1,29 @@ +package com.test.musichouduan.entity; + +import jakarta.persistence.*; +import lombok.Data; +import org.hibernate.annotations.CreationTimestamp; + +import java.time.LocalDateTime; + +@Data +@Entity +@Table(name = "user_like_music", uniqueConstraints = { + @UniqueConstraint(columnNames = {"userId", "musicId"}) +}) +public class UserLikeMusic { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false) + private Long userId; + + @Column(nullable = false) + private Long musicId; + + @CreationTimestamp + @Column(nullable = false, updatable = false) + private LocalDateTime createTime; +} diff --git a/music-houduan/src/main/java/com/test/musichouduan/init/DataInitializer.java b/music-houduan/src/main/java/com/test/musichouduan/init/DataInitializer.java index 285f704..26ec101 100644 --- a/music-houduan/src/main/java/com/test/musichouduan/init/DataInitializer.java +++ b/music-houduan/src/main/java/com/test/musichouduan/init/DataInitializer.java @@ -1,109 +1,109 @@ -package com.test.musichouduan.init; - -import cn.dev33.satoken.secure.BCrypt; -import com.test.musichouduan.entity.*; -import com.test.musichouduan.repository.*; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.CommandLineRunner; -import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; - -import java.util.Arrays; -import java.util.List; - -/** - * 数据初始化器 - */ -@Component -public class DataInitializer implements CommandLineRunner { - - @Autowired - private UserRepository userRepository; - - @Autowired - private MusicTypeRepository musicTypeRepository; - - @Autowired - private SingerTypeRepository singerTypeRepository; - - @Autowired - private PlaylistTypeRepository playlistTypeRepository; - - @Override - @Transactional - public void run(String... args) throws Exception { - // 初始化管理员用户 - initAdminUser(); - - // 初始化音乐类型 - initMusicTypes(); - - // 初始化歌手类型 - initSingerTypes(); - - // 初始化歌单类型 - initPlaylistTypes(); - } - - /** - * 初始化管理员用户 - */ - private void initAdminUser() { - if (!userRepository.existsByUsername("admin")) { - User admin = new User(); - admin.setUsername("admin"); - admin.setPassword(BCrypt.hashpw("123456")); - admin.setNickname("管理员"); - admin.setGender(0); - admin.setRole(1); - admin.setStatus(1); - userRepository.save(admin); - } - } - - /** - * 初始化音乐类型 - */ - private void initMusicTypes() { - if (musicTypeRepository.count() == 0) { - List typeNames = Arrays.asList("流行", "摇滚", "民谣", "电子", "古典", "嘻哈", "爵士", "乡村"); - for (String name : typeNames) { - MusicType type = new MusicType(); - type.setName(name); - type.setDescription(name + "音乐"); - musicTypeRepository.save(type); - } - } - } - - /** - * 初始化歌手类型 - */ - private void initSingerTypes() { - if (singerTypeRepository.count() == 0) { - List typeNames = Arrays.asList("华语男歌手", "华语女歌手", "华语组合", "欧美男歌手", "欧美女歌手", "欧美组合", "日韩男歌手", "日韩女歌手", "日韩组合"); - for (String name : typeNames) { - SingerType type = new SingerType(); - type.setName(name); - type.setDescription(name); - singerTypeRepository.save(type); - } - } - } - - /** - * 初始化歌单类型 - */ - private void initPlaylistTypes() { - if (playlistTypeRepository.count() == 0) { - List typeNames = Arrays.asList("流行", "摇滚", "民谣", "电子", "古典", "嘻哈", "爵士", "乡村", "轻音乐", "ACG"); - for (String name : typeNames) { - PlaylistType type = new PlaylistType(); - type.setName(name); - type.setDescription(name + "歌单"); - playlistTypeRepository.save(type); - } - } - } -} +//package com.test.musichouduan.init; +// +//import cn.dev33.satoken.secure.BCrypt; +//import com.test.musichouduan.entity.*; +//import com.test.musichouduan.repository.*; +// +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.boot.CommandLineRunner; +//import org.springframework.stereotype.Component; +//import org.springframework.transaction.annotation.Transactional; +// +//import java.util.Arrays; +//import java.util.List; +// +///** +// * 数据初始化器 +// */ +//@Component +//public class DataInitializer implements CommandLineRunner { +// +// @Autowired +// private UserRepository userRepository; +// +// @Autowired +// private MusicTypeRepository musicTypeRepository; +// +// @Autowired +// private SingerTypeRepository singerTypeRepository; +// +// @Autowired +// private PlaylistTypeRepository playlistTypeRepository; +// +// @Override +// @Transactional +// public void run(String... args) throws Exception { +// // 初始化管理员用户 +// initAdminUser(); +// +// // 初始化音乐类型 +// initMusicTypes(); +// +// // 初始化歌手类型 +// initSingerTypes(); +// +// // 初始化歌单类型 +// initPlaylistTypes(); +// } +// +// /** +// * 初始化管理员用户 +// */ +// private void initAdminUser() { +// if (!userRepository.existsByUsername("admin")) { +// User admin = new User(); +// admin.setUsername("admin"); +// admin.setPassword(BCrypt.hashpw("123456")); +// admin.setNickname("管理员"); +// admin.setGender(0); +// admin.setRole(1); +// admin.setStatus(1); +// userRepository.save(admin); +// } +// } +// +// /** +// * 初始化音乐类型 +// */ +// private void initMusicTypes() { +// if (musicTypeRepository.count() == 0) { +// List typeNames = Arrays.asList("流行", "摇滚", "民谣", "电子", "古典", "嘻哈", "爵士", "乡村"); +// for (String name : typeNames) { +// MusicType type = new MusicType(); +// type.setName(name); +// type.setDescription(name + "音乐"); +// musicTypeRepository.save(type); +// } +// } +// } +// +// /** +// * 初始化歌手类型 +// */ +// private void initSingerTypes() { +// if (singerTypeRepository.count() == 0) { +// List typeNames = Arrays.asList("华语男歌手", "华语女歌手", "华语组合", "欧美男歌手", "欧美女歌手", "欧美组合", "日韩男歌手", "日韩女歌手", "日韩组合"); +// for (String name : typeNames) { +// SingerType type = new SingerType(); +// type.setName(name); +// type.setDescription(name); +// singerTypeRepository.save(type); +// } +// } +// } +// +// /** +// * 初始化歌单类型 +// */ +// private void initPlaylistTypes() { +// if (playlistTypeRepository.count() == 0) { +// List typeNames = Arrays.asList("流行", "摇滚", "民谣", "电子", "古典", "嘻哈", "爵士", "乡村", "轻音乐", "ACG"); +// for (String name : typeNames) { +// PlaylistType type = new PlaylistType(); +// type.setName(name); +// type.setDescription(name + "歌单"); +// playlistTypeRepository.save(type); +// } +// } +// } +//} diff --git a/music-houduan/src/main/java/com/test/musichouduan/repository/UserCollectMusicRepository.java b/music-houduan/src/main/java/com/test/musichouduan/repository/UserCollectMusicRepository.java index 195166b..6adf3e3 100644 --- a/music-houduan/src/main/java/com/test/musichouduan/repository/UserCollectMusicRepository.java +++ b/music-houduan/src/main/java/com/test/musichouduan/repository/UserCollectMusicRepository.java @@ -43,6 +43,15 @@ public interface UserCollectMusicRepository extends JpaRepository { + + /** + * 根据用户ID和音乐ID查找点赞记录 + * + * @param userId 用户ID + * @param musicId 音乐ID + * @return 点赞记录 + */ + Optional findByUserIdAndMusicId(Long userId, Long musicId); + + /** + * 检查用户是否点赞了某音乐 + * + * @param userId 用户ID + * @param musicId 音乐ID + * @return 是否存在 + */ + boolean existsByUserIdAndMusicId(Long userId, Long musicId); +} diff --git a/music-houduan/src/main/java/com/test/musichouduan/service/MusicService.java b/music-houduan/src/main/java/com/test/musichouduan/service/MusicService.java index 658eb7c..1d9bdca 100644 --- a/music-houduan/src/main/java/com/test/musichouduan/service/MusicService.java +++ b/music-houduan/src/main/java/com/test/musichouduan/service/MusicService.java @@ -13,6 +13,15 @@ import java.util.concurrent.CompletableFuture; */ public interface MusicService { + /** + * 根据ID获取音乐,并根据用户ID判断是否收藏和点赞 + * + * @param id 音乐ID + * @param userId 用户ID (可以为null) + * @return 音乐DTO + */ + MusicDTO getMusicById(Long id, Long userId); + /** * 根据ID获取音乐 * @@ -133,4 +142,13 @@ public interface MusicService { * @return CompletableFuture 包装的音乐DTO列表 */ CompletableFuture> updateHotMusicCache(); + + /** + * 切换音乐点赞状态 + * + * @param musicId 音乐ID + * @param userId 用户ID + * @return 是否点赞成功 (true: 点赞, false: 取消点赞) + */ + boolean toggleLikeMusic(Long musicId, Long userId); } diff --git a/music-houduan/src/main/java/com/test/musichouduan/service/impl/MusicServiceImpl.java b/music-houduan/src/main/java/com/test/musichouduan/service/impl/MusicServiceImpl.java index 5321e59..cb098d6 100644 --- a/music-houduan/src/main/java/com/test/musichouduan/service/impl/MusicServiceImpl.java +++ b/music-houduan/src/main/java/com/test/musichouduan/service/impl/MusicServiceImpl.java @@ -7,6 +7,8 @@ import com.test.musichouduan.entity.Music; import com.test.musichouduan.entity.MusicType; import com.test.musichouduan.entity.Singer; import com.test.musichouduan.entity.User; +import com.test.musichouduan.entity.UserCollectMusic; +import com.test.musichouduan.entity.UserLikeMusic; import com.test.musichouduan.entity.UserMusic; import com.test.musichouduan.exception.BusinessException; import com.fasterxml.jackson.core.type.TypeReference; @@ -72,7 +74,10 @@ public class MusicServiceImpl implements MusicService { private UserRepository userRepository; @Autowired - private UserMusicRepository userMusicRepository; + private UserCollectMusicRepository userCollectMusicRepository; + + @Autowired + private UserLikeMusicRepository userLikeMusicRepository; @Autowired private PlayHistoryRepository playHistoryRepository; @@ -81,13 +86,19 @@ public class MusicServiceImpl implements MusicService { private FileService fileService; @Override - public MusicDTO getMusicById(Long id) { + public MusicDTO getMusicById(Long id, Long userId) { // 查找音乐,如果不存在则返回null return musicRepository.findById(id) - .map(this::convertToDTO) + .map(music -> convertToDTO(music, userId)) .orElse(null); } + @Override + public MusicDTO getMusicById(Long id) { + // 对于未登录用户或不需要用户状态的场景,直接调用新方法并传入null + return getMusicById(id, null); + } + @Override public PageResult getMusicList(Integer page, Integer size, String keyword, Long typeId) { // 构建查询条件 @@ -463,35 +474,37 @@ public class MusicServiceImpl implements MusicService { @Override @Transactional - public boolean toggleCollectMusic(Long id, Long userId) { - // 获取用户 - Optional userOpt = userRepository.findById(userId); - if (!userOpt.isPresent()) { - // 如果用户不存在,返回false - return false; - } - User user = userOpt.get(); - - // 获取音乐 - Optional musicOpt = musicRepository.findById(id); - if (!musicOpt.isPresent()) { - // 如果音乐不存在,返回false - return false; - } - Music music = musicOpt.get(); - - // 检查是否已收藏 - boolean isCollected = userMusicRepository.existsByUserAndMusic(user, music); + public boolean toggleCollectMusic(Long musicId, Long userId) { + // 直接通过ID判断是否存在,避免查询完整实体 + boolean isCollected = userCollectMusicRepository.existsByUserIdAndMusicId(userId, musicId); + + Music music = musicRepository.findById(musicId) + .orElseThrow(() -> new BusinessException("音乐不存在")); if (isCollected) { - // 如果已收藏,则取消收藏 - userMusicRepository.uncollectMusic(user.getId(), music.getId()); + // 已收藏,取消收藏 + User user = userRepository.findById(userId).orElseThrow(() -> new BusinessException("用户不存在")); + UserCollectMusic collect = userCollectMusicRepository.findByUserAndMusic(user, music) + .orElseThrow(() -> new BusinessException("收藏记录不存在")); + userCollectMusicRepository.delete(collect); + + int currentCollectCount = music.getCollectCount() != null ? music.getCollectCount() : 0; + music.setCollectCount(Math.max(0, currentCollectCount - 1)); + musicRepository.save(music); + return false; // 返回 "未收藏" 状态 } else { - // 如果未收藏,则收藏 - userMusicRepository.collectMusic(user.getId(), music.getId()); - } + // 未收藏,执行收藏 + User user = userRepository.findById(userId).orElseThrow(() -> new BusinessException("用户不存在")); + UserCollectMusic newCollect = new UserCollectMusic(); + newCollect.setUser(user); + newCollect.setMusic(music); + userCollectMusicRepository.save(newCollect); - return !isCollected; // 返回当前收藏状态,true表示已收藏,false表示未收藏 + int currentCollectCount = music.getCollectCount() != null ? music.getCollectCount() : 0; + music.setCollectCount(currentCollectCount + 1); + musicRepository.save(music); + return true; // 返回 "已收藏" 状态 + } } @Override @@ -501,24 +514,24 @@ public class MusicServiceImpl implements MusicService { .orElseThrow(() -> new BusinessException("用户不存在")); // 获取用户收藏的音乐 - Page userMusicPage = userMusicRepository.findCollectedMusic( - user.getId(), - PageRequest.of(page - 1, size, Sort.by(Sort.Direction.DESC, "collectTime")) + Page userCollectMusicPage = userCollectMusicRepository.findByUser( + user, + PageRequest.of(page - 1, size, Sort.by(Sort.Direction.DESC, "createTime")) ); // 转换为DTO - List musicDTOs = userMusicPage.getContent().stream() - .map(userMusic -> { - MusicDTO musicDTO = convertToDTO(userMusic.getMusic()); + List musicDTOs = userCollectMusicPage.getContent().stream() + .map(userCollectMusic -> { + MusicDTO musicDTO = convertToDTO(userCollectMusic.getMusic()); // 设置收藏时间 - musicDTO.setCollectTime(userMusic.getCollectTime()); + musicDTO.setCollectTime(userCollectMusic.getCreateTime()); return musicDTO; }) .collect(Collectors.toList()); return new PageResult<>( musicDTOs, - userMusicPage.getTotalElements(), + userCollectMusicPage.getTotalElements(), page, size ); @@ -539,8 +552,6 @@ public class MusicServiceImpl implements MusicService { // 增加播放次数 long currentPlayCount = music.getPlayCount() != null ? music.getPlayCount() : 0; music.setPlayCount(currentPlayCount + 1); - // 根据要求,将点赞数与播放次数同步 - music.setLikeCount((int) (currentPlayCount + 1)); musicRepository.save(music); // 如果用户已登录,记录播放历史 @@ -560,6 +571,34 @@ public class MusicServiceImpl implements MusicService { return musicRepository.findById(id).orElse(null); } + @Override + @Transactional + public boolean toggleLikeMusic(Long musicId, Long userId) { + Music music = musicRepository.findById(musicId) + .orElseThrow(() -> new BusinessException("音乐不存在")); + + Optional likeOpt = userLikeMusicRepository.findByUserIdAndMusicId(userId, musicId); + + if (likeOpt.isPresent()) { + // 已点赞,取消点赞 + userLikeMusicRepository.delete(likeOpt.get()); + int currentLikeCount = music.getLikeCount() != null ? music.getLikeCount() : 0; + music.setLikeCount(Math.max(0, currentLikeCount - 1)); + musicRepository.save(music); + return false; // 返回 "未点赞" 状态 + } else { + // 未点赞,执行点赞 + UserLikeMusic newLike = new UserLikeMusic(); + newLike.setUserId(userId); + newLike.setMusicId(musicId); + userLikeMusicRepository.save(newLike); + int currentLikeCount = music.getLikeCount() != null ? music.getLikeCount() : 0; + music.setLikeCount(currentLikeCount + 1); + musicRepository.save(music); + return true; // 返回 "已点赞" 状态 + } + } + /** * 将实体转换为DTO * @@ -567,52 +606,49 @@ public class MusicServiceImpl implements MusicService { * @return 音乐DTO */ private MusicDTO convertToDTO(Music music) { + // 保留此方法以兼容不需要用户状态的转换 + return convertToDTO(music, null); + } + + /** + * 将实体转换为DTO,并根据用户ID判断是否收藏和点赞 + * + * @param music 音乐实体 + * @param userId 用户ID (可以为null) + * @return 音乐DTO + */ + private MusicDTO convertToDTO(Music music, Long userId) { MusicDTO musicDTO = new MusicDTO(); BeanUtils.copyProperties(music, musicDTO); // 确保专辑字段正确复制 musicDTO.setAlbum(music.getAlbum()); - // 设置类型ID列表 - if (music.getTypes() != null) { - List typeIds = music.getTypes().stream() - .map(MusicType::getId) - .collect(Collectors.toList()); - musicDTO.setTypeIds(typeIds); - - // 设置类型名称列表 - List typeNames = music.getTypes().stream() - .map(MusicType::getName) - .collect(Collectors.toList()); - musicDTO.setTypeNames(typeNames); + // 设置类型ID和名称列表 + if (!CollectionUtils.isEmpty(music.getTypes())) { + musicDTO.setTypeIds(music.getTypes().stream().map(MusicType::getId).collect(Collectors.toList())); + musicDTO.setTypeNames(music.getTypes().stream().map(MusicType::getName).collect(Collectors.toList())); } - // 设置歌手ID列表 - if (music.getSingers() != null) { - List singerIds = music.getSingers().stream() - .map(Singer::getId) - .collect(Collectors.toList()); - musicDTO.setSingerIds(singerIds); - - // 设置歌手名称列表 - List singerNames = music.getSingers().stream() - .map(Singer::getName) - .collect(Collectors.toList()); + // 设置歌手ID和名称列表 + if (!CollectionUtils.isEmpty(music.getSingers())) { + musicDTO.setSingerIds(music.getSingers().stream().map(Singer::getId).collect(Collectors.toList())); + List singerNames = music.getSingers().stream().map(Singer::getName).collect(Collectors.toList()); musicDTO.setSingerNames(singerNames); - - // 设置歌手名称字符串(用于前端显示) - if (!singerNames.isEmpty()) { - musicDTO.setSinger(String.join(", ", singerNames)); - } + musicDTO.setSinger(String.join("、", singerNames)); } - // 检查当前登录用户是否已收藏该音乐 - if (StpUtil.isLogin()) { - Long userId = StpUtil.getLoginIdAsLong(); - boolean isCollected = userMusicRepository.existsByUserIdAndMusicId(userId, music.getId()); + // 如果传入了用户ID,则查询该用户的收藏和点赞状态 + if (userId != null) { + boolean isCollected = userCollectMusicRepository.existsByUserIdAndMusicId(userId, music.getId()); musicDTO.setCollected(isCollected); + + boolean isLiked = userLikeMusicRepository.existsByUserIdAndMusicId(userId, music.getId()); + musicDTO.setLiked(isLiked); } else { + // 如果未传入用户ID,则默认为未收藏和未点赞 musicDTO.setCollected(false); + musicDTO.setLiked(false); } return musicDTO; diff --git a/music-qianduan/src/api/music.js b/music-qianduan/src/api/music.js index 59f52eb..165872d 100644 --- a/music-qianduan/src/api/music.js +++ b/music-qianduan/src/api/music.js @@ -116,6 +116,15 @@ export function toggleCollectMusic(id) { return api.post(`/music/${id}/collect`) } +/** + * 点赞/取消点赞音乐 + * @param {number} id 音乐ID + * @returns {Promise} + */ +export function toggleLikeMusic(id) { + return api.post(`/music/${id}/like`) +} + /** * 获取收藏的音乐列表 * @param {number} page 页码 diff --git a/music-qianduan/src/views/MusicDetail.vue b/music-qianduan/src/views/MusicDetail.vue index 2a1712e..fa07af6 100644 --- a/music-qianduan/src/views/MusicDetail.vue +++ b/music-qianduan/src/views/MusicDetail.vue @@ -73,6 +73,14 @@ {{ music.collected ? '已收藏' : '收藏' }} + + + {{ music.liked ? '已点赞' : '点赞' }} ({{ music.likeCount || 0 }}) + + { try { const res = await toggleCollectMusic(music.value.id) if (res.code === 200) { - music.value.collected = !music.value.collected - ElMessage.success(music.value.collected ? '收藏成功' : '已取消收藏') + // 后端直接返回了最新的收藏状态 (true/false),直接赋值即可 + music.value.collected = res.data + ElMessage.success(res.message || (music.value.collected ? '收藏成功' : '已取消收藏')) } else { ElMessage.error(res.message || '操作失败') } @@ -410,6 +419,29 @@ const toggleCollect = async () => { } } +// 切换点赞状态 +const toggleLike = async () => { + try { + const res = await toggleLikeMusic(music.value.id); + if (res.code === 200) { + // 后端直接返回了最新的点赞状态 (true/false),直接赋值 + music.value.liked = res.data; + // 更新点赞数 + if (music.value.liked) { + music.value.likeCount = (music.value.likeCount || 0) + 1; + } else { + music.value.likeCount = Math.max(0, (music.value.likeCount || 0) - 1); + } + ElMessage.success(res.message || (music.value.liked ? '点赞成功' : '已取消点赞')); + } else { + ElMessage.error(res.message || '操作失败'); + } + } catch (error) { + console.error('点赞操作失败:', error); + ElMessage.error('操作失败,请稍后重试'); + } +}; + // 添加到播放列表 const addToPlaylist = () => { playerStore.addToPlaylist(music.value) diff --git a/sql/music_db.sql b/sql/music_db.sql index 20ee2eb..3e04db4 100644 --- a/sql/music_db.sql +++ b/sql/music_db.sql @@ -11,7 +11,7 @@ Target Server Version : 80041 (8.0.41) File Encoding : 65001 - Date: 23/07/2025 22:59:43 + Date: 25/07/2025 22:22:53 */ SET NAMES utf8mb4; @@ -44,42 +44,37 @@ CREATE TABLE `comment` ( `content` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '评论内容', `user_id` bigint NOT NULL COMMENT '评论用户ID', `target_id` bigint NOT NULL COMMENT '评论目标ID', - `target_type` int NOT NULL, + `target_type` int NOT NULL COMMENT '评论目标类型:1-音乐,2-歌单,3-歌手', `parent_id` bigint NULL DEFAULT NULL COMMENT '父评论ID', - `status` int NULL DEFAULT NULL, + `status` int NULL DEFAULT NULL COMMENT '状态:0-禁用,1-正常', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_user_id`(`user_id` ASC) USING BTREE, INDEX `idx_target`(`target_id` ASC, `target_type` ASC) USING BTREE, - INDEX `idx_parent_id`(`parent_id` ASC) USING BTREE, - CONSTRAINT `FK8kcum44fvpupyw6f5baccx25c` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT -) ENGINE = InnoDB AUTO_INCREMENT = 28 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '评论表' ROW_FORMAT = Dynamic; + INDEX `idx_parent_id`(`parent_id` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 56 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '评论表' ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for music -- ---------------------------- DROP TABLE IF EXISTS `music`; CREATE TABLE `music` ( -`id` bigint NOT NULL AUTO_INCREMENT COMMENT '音乐ID', -`name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '音乐名称', -`cover` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '封面URL', -`url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '音乐文件URL', -`lyric` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '歌词', -`duration` int NULL DEFAULT 0 COMMENT '时长(秒)', -`album` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, - - -- Interaction and Hot Score Fields -`play_count` bigint NULL DEFAULT 0 COMMENT '播放次数', -`like_count` int NULL DEFAULT 0 COMMENT '点赞数', -`collect_count` int NULL DEFAULT 0 COMMENT '收藏数', -`comment_count` int NULL DEFAULT 0 COMMENT '评论数', -`hot_score` double NULL DEFAULT 0.0 COMMENT '热度分数', - - -- Timestamps -`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', -`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', -PRIMARY KEY (`id`) USING BTREE + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '音乐ID', + `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '音乐名称', + `cover` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '封面URL', + `url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '音乐文件URL', + `lyric` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '歌词', + `duration` int NULL DEFAULT 0 COMMENT '时长(秒)', + `play_count` bigint NULL DEFAULT 0 COMMENT '播放次数', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `album` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, + `like_count` int NULL DEFAULT NULL COMMENT '点赞数', + `collect_count` int NULL DEFAULT NULL COMMENT '收藏数', + `comment_count` int NULL DEFAULT NULL COMMENT '评论数', + `hot_score` double NULL DEFAULT NULL COMMENT '热度分数', + PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '音乐表' ROW_FORMAT = Dynamic; -- ---------------------------- @@ -121,9 +116,7 @@ CREATE TABLE `music_type_relation` ( `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `uk_music_type`(`music_id` ASC, `type_id` ASC) USING BTREE, - INDEX `idx_type_id`(`type_id` ASC) USING BTREE, - CONSTRAINT `FK2i7xdrmrh0l6thp9u2r16fdcm` FOREIGN KEY (`music_id`) REFERENCES `music` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT, - CONSTRAINT `FKjtxip1yvwn66p4cbpycekychq` FOREIGN KEY (`type_id`) REFERENCES `music_type` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT + INDEX `idx_type_id`(`type_id` ASC) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '音乐-类型关联表' ROW_FORMAT = Dynamic; -- ---------------------------- @@ -137,10 +130,8 @@ CREATE TABLE `play_history` ( `play_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '播放时间', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_user_id`(`user_id` ASC) USING BTREE, - INDEX `idx_music_id`(`music_id` ASC) USING BTREE, - CONSTRAINT `FKm05jb66wc5epn38vuwm55o933` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT, - CONSTRAINT `FKt6cp1qv95qi4abyn69soyvibk` FOREIGN KEY (`music_id`) REFERENCES `music` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT -) ENGINE = InnoDB AUTO_INCREMENT = 43 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '播放历史表' ROW_FORMAT = Dynamic; + INDEX `idx_music_id`(`music_id` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 51 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '播放历史表' ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for playlist @@ -159,10 +150,8 @@ CREATE TABLE `playlist` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_creator_id`(`creator_id` ASC) USING BTREE, - INDEX `idx_type_id`(`type_id` ASC) USING BTREE, - CONSTRAINT `FKi45kpenvb301c9yb1labp8b4j` FOREIGN KEY (`creator_id`) REFERENCES `user` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT, - CONSTRAINT `FKttnmgs0esm9njqa0g52mbp48` FOREIGN KEY (`type_id`) REFERENCES `playlist_type` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT -) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '歌单表' ROW_FORMAT = Dynamic; + INDEX `idx_type_id`(`type_id` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '歌单表' ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for playlist_music @@ -176,9 +165,7 @@ CREATE TABLE `playlist_music` ( `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `uk_playlist_music`(`playlist_id` ASC, `music_id` ASC) USING BTREE, - INDEX `idx_music_id`(`music_id` ASC) USING BTREE, - CONSTRAINT `FK5g0xtl5e89uycye0jo1ll65sq` FOREIGN KEY (`music_id`) REFERENCES `music` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT, - CONSTRAINT `FKq9o07ljjk03aeeqt0q9lwhndk` FOREIGN KEY (`playlist_id`) REFERENCES `playlist` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT + INDEX `idx_music_id`(`music_id` ASC) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '歌单-音乐关联表' ROW_FORMAT = Dynamic; -- ---------------------------- @@ -208,8 +195,7 @@ CREATE TABLE `singer` ( `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`) USING BTREE, - INDEX `idx_type_id`(`type_id` ASC) USING BTREE, - CONSTRAINT `FKdwhlvo45iuspxcjg0gax5exwm` FOREIGN KEY (`type_id`) REFERENCES `singer_type` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT + INDEX `idx_type_id`(`type_id` ASC) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '歌手表' ROW_FORMAT = Dynamic; -- ---------------------------- @@ -220,9 +206,7 @@ CREATE TABLE `singer_music` ( `singer_id` bigint NOT NULL, `music_id` bigint NOT NULL, PRIMARY KEY (`singer_id`, `music_id`) USING BTREE, - INDEX `FKk0fdv208e2ulhcxd9gge63h6j`(`music_id` ASC) USING BTREE, - CONSTRAINT `FKf33uki3h3ftg9ne16xr4n1srp` FOREIGN KEY (`singer_id`) REFERENCES `singer` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT, - CONSTRAINT `FKk0fdv208e2ulhcxd9gge63h6j` FOREIGN KEY (`music_id`) REFERENCES `music` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT + INDEX `FKk0fdv208e2ulhcxd9gge63h6j`(`music_id` ASC) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; -- ---------------------------- @@ -289,10 +273,8 @@ CREATE TABLE `user_collect_music` ( `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `uk_user_music`(`user_id` ASC, `music_id` ASC) USING BTREE, - INDEX `idx_music_id`(`music_id` ASC) USING BTREE, - CONSTRAINT `FK1bm2wy4dgmhdfvp6k9fhqpf73` FOREIGN KEY (`music_id`) REFERENCES `music` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT, - CONSTRAINT `FKt8w479d40yle3jxmqiovm6quo` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户收藏音乐表' ROW_FORMAT = Dynamic; + INDEX `idx_music_id`(`music_id` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户收藏音乐表' ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for user_collect_playlist @@ -305,10 +287,8 @@ CREATE TABLE `user_collect_playlist` ( `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `uk_user_playlist`(`user_id` ASC, `playlist_id` ASC) USING BTREE, - INDEX `idx_playlist_id`(`playlist_id` ASC) USING BTREE, - CONSTRAINT `FKe4f1odrrb8yq287v9gwsbq5px` FOREIGN KEY (`playlist_id`) REFERENCES `playlist` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT, - CONSTRAINT `FKqxg6amofxpxuxf6uwjebb5jak` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户收藏歌单表' ROW_FORMAT = Dynamic; + INDEX `idx_playlist_id`(`playlist_id` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户收藏歌单表' ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for user_collect_singer @@ -321,10 +301,22 @@ CREATE TABLE `user_collect_singer` ( `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `uk_user_singer`(`user_id` ASC, `singer_id` ASC) USING BTREE, - INDEX `idx_singer_id`(`singer_id` ASC) USING BTREE, - CONSTRAINT `FKlvx6pnysffce263knm6iivjjj` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT, - CONSTRAINT `FKn8hu81ynti2nku5p7nsh6mk1k` FOREIGN KEY (`singer_id`) REFERENCES `singer` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户收藏歌手表' ROW_FORMAT = Dynamic; + INDEX `idx_singer_id`(`singer_id` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户收藏歌手表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for user_like_music +-- ---------------------------- +DROP TABLE IF EXISTS `user_like_music`; +CREATE TABLE `user_like_music` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID', + `user_id` bigint NOT NULL COMMENT '用户ID', + `music_id` bigint NOT NULL COMMENT '音乐ID', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '点赞时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `uk_user_music`(`user_id` ASC, `music_id` ASC) USING BTREE, + INDEX `idx_music_id`(`music_id` ASC) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户点赞音乐表' ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Table structure for user_music @@ -337,10 +329,8 @@ CREATE TABLE `user_music` ( `user_id` bigint NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE, INDEX `FKb53nc2rlyaotl1socy90u0v8`(`music_id` ASC) USING BTREE, - INDEX `FKq3jkqxxm4lxvoaauy93dq1hjl`(`user_id` ASC) USING BTREE, - CONSTRAINT `FKb53nc2rlyaotl1socy90u0v8` FOREIGN KEY (`music_id`) REFERENCES `music` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT, - CONSTRAINT `FKq3jkqxxm4lxvoaauy93dq1hjl` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT -) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; + INDEX `FKq3jkqxxm4lxvoaauy93dq1hjl`(`user_id` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for user_playlist @@ -353,8 +343,7 @@ CREATE TABLE `user_playlist` ( `user_id` bigint NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE, INDEX `FK7k6xercebs1wg014xb49hw3h0`(`playlist_id` ASC) USING BTREE, - INDEX `FKmofufj03yw1wqauec6vrdnfw1`(`user_id` ASC) USING BTREE, - CONSTRAINT `FKmofufj03yw1wqauec6vrdnfw1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT + INDEX `FKmofufj03yw1wqauec6vrdnfw1`(`user_id` ASC) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; -- ---------------------------- @@ -368,8 +357,7 @@ CREATE TABLE `user_singer` ( `user_id` bigint NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE, INDEX `FKacl5uu14x3io8qygn0cp27nvb`(`singer_id` ASC) USING BTREE, - INDEX `FKnogaivkt6y4jy5vbt85tu8qj0`(`user_id` ASC) USING BTREE, - CONSTRAINT `FKnogaivkt6y4jy5vbt85tu8qj0` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT -) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; + INDEX `FKnogaivkt6y4jy5vbt85tu8qj0`(`user_id` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; SET FOREIGN_KEY_CHECKS = 1;