浏览代码

分块上传前

xiang 2 周之前
父节点
当前提交
b05c7cf2a3
共有 83 个文件被更改,包括 1003 次插入1448 次删除
  1. 14 1
      artist/artist.sql
  2. 9 0
      artist/pom.xml
  3. 3 0
      artist/src/main/java/com/artist/ArtistApplication.java
  4. 6 10
      artist/src/main/java/com/artist/controller/ArtistController.java
  5. 22 0
      artist/src/main/java/com/artist/mapper/UserFavoriteArtistMapper.java
  6. 7 4
      artist/src/main/java/com/artist/service/IUserFavoriteArtistService.java
  7. 29 0
      artist/src/main/java/com/artist/service/impl/UserFavoriteArtistServiceImpl.java
  8. 1 1
      artist/src/main/resources/mapper/UserFavoriteArtistMapper.xml
  9. 1 13
      content/content.sql
  10. 33 0
      content/src/main/java/com/content/controller/AlbumController.java
  11. 0 20
      content/src/main/java/com/content/controller/ArtistMediaHistoryController.java
  12. 0 20
      content/src/main/java/com/content/controller/ChunkInfoController.java
  13. 0 20
      content/src/main/java/com/content/controller/MediaProcessController.java
  14. 0 20
      content/src/main/java/com/content/controller/MediaProcessHistoryController.java
  15. 0 20
      content/src/main/java/com/content/controller/MediaVideoController.java
  16. 52 16
      content/src/main/java/com/content/controller/PlaylistController.java
  17. 7 0
      content/src/main/java/com/content/controller/SongController.java
  18. 2 1
      content/src/main/java/com/content/controller/SwipperController.java
  19. 0 20
      content/src/main/java/com/content/controller/SysConfigController.java
  20. 0 20
      content/src/main/java/com/content/controller/VideoProcessQueueController.java
  21. 0 235
      content/src/main/java/com/content/domain/po/Artist.java
  22. 0 59
      content/src/main/java/com/content/domain/po/ChunkInfo.java
  23. 0 71
      content/src/main/java/com/content/domain/po/MediaProcess.java
  24. 0 65
      content/src/main/java/com/content/domain/po/MediaProcessHistory.java
  25. 0 78
      content/src/main/java/com/content/domain/po/MediaVideo.java
  26. 18 11
      content/src/main/java/com/content/domain/po/Playlist.java
  27. 0 50
      content/src/main/java/com/content/domain/po/SysConfig.java
  28. 0 78
      content/src/main/java/com/content/domain/po/UserFavoriteArtist.java
  29. 7 39
      content/src/main/java/com/content/domain/po/UserPlaylistFavorite.java
  30. 0 47
      content/src/main/java/com/content/domain/po/VideoProcessQueue.java
  31. 13 1
      content/src/main/java/com/content/mapper/AlbumMapper.java
  32. 0 18
      content/src/main/java/com/content/mapper/ArtistMapper.java
  33. 0 16
      content/src/main/java/com/content/mapper/ArtistMediaHistoryMapper.java
  34. 0 16
      content/src/main/java/com/content/mapper/ChunkInfoMapper.java
  35. 0 16
      content/src/main/java/com/content/mapper/MediaProcessHistoryMapper.java
  36. 0 16
      content/src/main/java/com/content/mapper/MediaProcessMapper.java
  37. 0 16
      content/src/main/java/com/content/mapper/MediaVideoMapper.java
  38. 0 16
      content/src/main/java/com/content/mapper/SysConfigMapper.java
  39. 0 18
      content/src/main/java/com/content/mapper/UserFavoriteArtistMapper.java
  40. 4 0
      content/src/main/java/com/content/mapper/UserPlaylistFavoriteMapper.java
  41. 0 16
      content/src/main/java/com/content/mapper/VideoProcessQueueMapper.java
  42. 7 0
      content/src/main/java/com/content/service/IAlbumService.java
  43. 0 16
      content/src/main/java/com/content/service/IArtistMediaHistoryService.java
  44. 0 17
      content/src/main/java/com/content/service/IArtistService.java
  45. 0 16
      content/src/main/java/com/content/service/IChunkInfoService.java
  46. 0 16
      content/src/main/java/com/content/service/IMediaProcessHistoryService.java
  47. 0 16
      content/src/main/java/com/content/service/IMediaProcessService.java
  48. 0 16
      content/src/main/java/com/content/service/IMediaVideoService.java
  49. 5 0
      content/src/main/java/com/content/service/IPlaylistService.java
  50. 0 16
      content/src/main/java/com/content/service/ISysConfigService.java
  51. 4 0
      content/src/main/java/com/content/service/IUserPlaylistFavoriteService.java
  52. 0 16
      content/src/main/java/com/content/service/IVideoProcessQueueService.java
  53. 18 0
      content/src/main/java/com/content/service/impl/AlbumServiceImpl.java
  54. 0 20
      content/src/main/java/com/content/service/impl/ArtistMediaHistoryServiceImpl.java
  55. 0 29
      content/src/main/java/com/content/service/impl/ArtistServiceImpl.java
  56. 0 20
      content/src/main/java/com/content/service/impl/ChunkInfoServiceImpl.java
  57. 0 20
      content/src/main/java/com/content/service/impl/MediaProcessHistoryServiceImpl.java
  58. 0 20
      content/src/main/java/com/content/service/impl/MediaProcessServiceImpl.java
  59. 0 20
      content/src/main/java/com/content/service/impl/MediaVideoServiceImpl.java
  60. 71 2
      content/src/main/java/com/content/service/impl/PlaylistServiceImpl.java
  61. 0 20
      content/src/main/java/com/content/service/impl/SysConfigServiceImpl.java
  62. 0 20
      content/src/main/java/com/content/service/impl/UserFavoriteArtistServiceImpl.java
  63. 11 1
      content/src/main/java/com/content/service/impl/UserPlaylistFavoriteServiceImpl.java
  64. 0 20
      content/src/main/java/com/content/service/impl/VideoProcessQueueServiceImpl.java
  65. 10 0
      content/src/main/resources/mapper/AlbumMapper.xml
  66. 0 5
      content/src/main/resources/mapper/ArtistMapper.xml
  67. 0 5
      content/src/main/resources/mapper/ArtistMediaHistoryMapper.xml
  68. 0 5
      content/src/main/resources/mapper/MediaProcessHistoryMapper.xml
  69. 0 5
      content/src/main/resources/mapper/MediaProcessMapper.xml
  70. 0 5
      content/src/main/resources/mapper/MediaVideoMapper.xml
  71. 0 5
      content/src/main/resources/mapper/SysConfigMapper.xml
  72. 0 5
      content/src/main/resources/mapper/UserFavoriteArtistMapper.xml
  73. 5 0
      content/src/main/resources/mapper/UserPlaylistFavoriteMapper.xml
  74. 0 5
      content/src/main/resources/mapper/VideoProcessQueueMapper.xml
  75. 121 4
      media/media.sql
  76. 5 0
      media/pom.xml
  77. 174 14
      media/src/main/java/com/media/controller/FileUploadController.java
  78. 14 0
      media/src/main/java/com/media/domain/dto/MergeChunkDTO.java
  79. 30 0
      media/src/main/java/com/media/domain/po/ChunkInfo.java
  80. 17 0
      media/src/main/java/com/media/domain/vo/UploadStatusVO.java
  81. 282 0
      media/src/main/java/com/media/service/impl/ChunkUploadService.java
  82. 1 0
      media/src/main/java/com/media/util/enums/StorageBucket.java
  83. 0 1
      media/src/main/java/com/media/util/upload/MinioFileUploader.java

+ 14 - 1
artist/artist.sql

@@ -88,4 +88,17 @@ CREATE TABLE `artist_audit_record` (
     INDEX `idx_apply_time` (`apply_time`),
     INDEX `idx_audit_status` (`audit_status`),
     INDEX `idx_audit_user_id` (`audit_user_id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='音乐人审核申请记录表';
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='音乐人审核申请记录表';
+
+-- ------------------------------
+-- 7. 我喜欢的歌手表(关联auth服务的user.id、artist服务的artist.id)
+-- ------------------------------
+CREATE TABLE `user_favorite_artist` (
+                                        `id` INT AUTO_INCREMENT PRIMARY KEY,
+                                        `user_id` INT NOT NULL COMMENT '关联auth服务的user.id',
+                                        `artist_id` INT NOT NULL COMMENT '关联artist服务的artist.id',
+                                        `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '关注时间',
+                                        UNIQUE KEY `uk_user_artist` (`user_id`, `artist_id`),
+                                        INDEX `idx_user_id` (`user_id`), -- 逻辑关联索引
+                                        INDEX `idx_artist_id` (`artist_id`) -- 逻辑关联索引
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='我喜欢的歌手表';

+ 9 - 0
artist/pom.xml

@@ -78,6 +78,15 @@
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-data-redis</artifactId>
         </dependency>
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
+        </dependency>
+        <!-- Spring Cloud 微服务远程调用 -->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-openfeign</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.springframework.cloud</groupId>
             <artifactId>spring-cloud-starter-oauth2</artifactId>

+ 3 - 0
artist/src/main/java/com/artist/ArtistApplication.java

@@ -1,7 +1,10 @@
 package com.artist;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+
 @SpringBootApplication
+@EnableFeignClients(basePackages={"com.artist.feignclient"})
 public class ArtistApplication {
     public static void main(String[] args) {
         SpringApplication.run(ArtistApplication.class, args);

+ 6 - 10
artist/src/main/java/com/artist/controller/ArtistController.java

@@ -1,6 +1,4 @@
 package com.artist.controller;
-
-
 import com.alibaba.fastjson.JSON;
 import com.artist.domain.dto.MusicianApplicationDTO;
 import com.artist.domain.dto.SingerInfoDTO;
@@ -10,6 +8,7 @@ import com.artist.domain.po.ArtistAuditRecord;
 import com.artist.domain.po.WyUser;
 import com.artist.service.IArtistAuditRecordService;
 import com.artist.service.IArtistService;
+import com.base.common.RedisConstant;
 import com.base.exception.WyMusicException;
 import com.base.utils.Result;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -67,7 +66,8 @@ public class ArtistController {
         }
 
         // 构建Redis key
-        String redisKey = "artist:status:user:" + id;
+        String redisKey = RedisConstant.ARTIST_STATUS_USER_PREFIX + id;
+
 
         // 尝试从Redis获取数据
         String cachedData = stringRedisTemplate.opsForValue().get(redisKey);
@@ -96,11 +96,7 @@ public class ArtistController {
     @PreAuthorize("hasRole('ROLE_ADMIN')")
     public Result updateArtistStatus(@RequestParam Integer id, @RequestParam Integer status, @RequestParam(required = false, defaultValue = "") String reason) {
         iArtistApplyService.updateArtistApply(id, status, reason);
-
-        // 清除该用户的艺人状态缓存
-        String redisKey = "artist:status:user:" + id;
-        stringRedisTemplate.delete(redisKey);
-
+        stringRedisTemplate.delete(RedisConstant.ARTIST_STATUS_USER_PREFIX + id);
         return Result.success("更新成功");
     }
     @GetMapping("/application-info")
@@ -124,12 +120,12 @@ public class ArtistController {
     @GetMapping("querySingerById")
     @PreAuthorize("hasRole('ROLE_USER')")
     public Result querySingerById(@RequestParam Integer id) {
-        String s = stringRedisTemplate.opsForValue().get("artist:querySingerById:" + id);
+        String s = stringRedisTemplate.opsForValue().get(RedisConstant.ARTIST_QUERY_SINGER_BY_ID_PREFIX + id);
         if (s != null) {
             return Result.success(JSON.parseObject(s, Artist.class));
         }
         Artist artist = artistService.getById(id);
-        stringRedisTemplate.opsForValue().set("artist:querySingerById:" + id, JSON.toJSONString(artist), 24, TimeUnit.HOURS);
+        stringRedisTemplate.opsForValue().set(RedisConstant.ARTIST_QUERY_SINGER_BY_ID_PREFIX+  id, JSON.toJSONString(artist), 24, TimeUnit.HOURS);
         return Result.success(artist);
     }
 }

+ 22 - 0
artist/src/main/java/com/artist/mapper/UserFavoriteArtistMapper.java

@@ -0,0 +1,22 @@
+package com.artist.mapper;
+import com.artist.domain.po.Artist;
+import com.artist.domain.po.UserFavoriteArtist;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author xiang
+ * @since 2025-11-06
+ */
+@Mapper
+public interface UserFavoriteArtistMapper extends BaseMapper<UserFavoriteArtist> {
+    @Select("SELECT * FROM artist WHERE id IN (SELECT artist_id FROM user_favorite_artist WHERE user_id = #{id})")
+    List<Artist> queryById(Integer id);
+}

+ 7 - 4
content/src/main/java/com/content/service/IUserFavoriteArtistService.java → artist/src/main/java/com/artist/service/IUserFavoriteArtistService.java

@@ -1,16 +1,19 @@
-package com.content.service;
+package com.artist.service;
 
-import com.content.domain.po.UserFavoriteArtist;
+import com.artist.domain.po.Artist;
+import com.artist.domain.po.UserFavoriteArtist;
 import com.baomidou.mybatisplus.extension.service.IService;
 
+import java.util.List;
+
 /**
  * <p>
- *  服务类
+ * 服务类
  * </p>
  *
  * @author xiang
  * @since 2025-11-06
  */
 public interface IUserFavoriteArtistService extends IService<UserFavoriteArtist> {
-
+    List<Artist> queryById(Integer id);
 }

+ 29 - 0
artist/src/main/java/com/artist/service/impl/UserFavoriteArtistServiceImpl.java

@@ -0,0 +1,29 @@
+package com.artist.service.impl;
+import com.artist.domain.po.Artist;
+import com.artist.domain.po.UserFavoriteArtist;
+import com.artist.mapper.UserFavoriteArtistMapper;
+import com.artist.service.IUserFavoriteArtistService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author xiang
+ * @since 2025-11-06
+ */
+@Service
+public class UserFavoriteArtistServiceImpl extends ServiceImpl<UserFavoriteArtistMapper, UserFavoriteArtist> implements IUserFavoriteArtistService {
+@Autowired
+private UserFavoriteArtistMapper userFavoriteArtistMapper;
+    @Override
+    public List<Artist> queryById(Integer id) {
+        List<Artist> artists = userFavoriteArtistMapper.queryById(id);
+        return artists;
+    }
+}

+ 1 - 1
content/src/main/resources/mapper/ChunkInfoMapper.xml → artist/src/main/resources/mapper/UserFavoriteArtistMapper.xml

@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.content.mapper.ChunkInfoMapper">
+<mapper namespace="com.artist.mapper.UserFavoriteArtistMapper">
 
 </mapper>

+ 1 - 13
content/content.sql

@@ -46,7 +46,6 @@ CREATE TABLE `song` (
                         `price` DECIMAL(10,2) DEFAULT 0.00 COMMENT '单曲价格',
                         `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
                         `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
-
 -- 已添加的管理字段
                         `status` TINYINT DEFAULT 0 COMMENT '歌曲状态:0-草稿,1-审核中,2-审核失败,3-发布中,4-已上架,5-已下架',
                         `audit_reason` VARCHAR(500) COMMENT '审核失败原因',
@@ -155,18 +154,7 @@ CREATE TABLE `user_favorite_song` (
                                       INDEX `idx_song_id` (`song_id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='我喜欢的音乐表';
 
--- ------------------------------
--- 7. 我喜欢的歌手表(关联auth服务的user.id、artist服务的artist.id)
--- ------------------------------
-CREATE TABLE `user_favorite_artist` (
-                                        `id` INT AUTO_INCREMENT PRIMARY KEY,
-                                        `user_id` INT NOT NULL COMMENT '关联auth服务的user.id',
-                                        `artist_id` INT NOT NULL COMMENT '关联artist服务的artist.id',
-                                        `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '关注时间',
-                                        UNIQUE KEY `uk_user_artist` (`user_id`, `artist_id`),
-                                        INDEX `idx_user_id` (`user_id`), -- 逻辑关联索引
-                                        INDEX `idx_artist_id` (`artist_id`) -- 逻辑关联索引
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='我喜欢的歌手表';
+
 
 -- ------------------------------
 -- 8. 我关注的用户表(关联auth服务的user.id)

+ 33 - 0
content/src/main/java/com/content/controller/AlbumController.java

@@ -1,5 +1,8 @@
 package com.content.controller;
+import com.base.common.RedisConstant;
 import com.base.utils.Result;
+import com.content.domain.dto.AlbumListDto;
+import com.content.domain.dto.AlbumNumDto;
 import com.content.domain.dto.ApplyDto;
 import com.content.domain.dto.PageQueryDto;
 import com.content.domain.po.Album;
@@ -7,7 +10,10 @@ import com.content.domain.po.Song;
 import com.content.service.IAlbumManageService;
 import com.content.service.IAlbumService;
 import com.content.service.ISongService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
@@ -15,8 +21,11 @@ import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.util.HashMap;
 import java.util.List;
+import java.util.concurrent.TimeUnit;
+
 @RestController
 @RequestMapping("/album")
+@Slf4j
 public class AlbumController {
     @Autowired
     private IAlbumService albumService;
@@ -25,6 +34,8 @@ public class AlbumController {
     // 新增依赖
     @Autowired
     private IAlbumManageService albumManageService;
+    @Autowired
+    private RedisTemplate redisTemplate;
     @PostMapping("/add")
     @PreAuthorize("hasRole('ROLE_USER')")
     public Result add(@RequestBody Album album) {
@@ -104,4 +115,26 @@ public class AlbumController {
         objectObjectHashMap.put("songs", songs);
         return Result.success(objectObjectHashMap);
     }
+    //查询所有专辑
+    @GetMapping("/listAllAlbum")
+    @PreAuthorize("hasRole('ROLE_USER')")
+    public Result listAllAlbum() {
+        Object cachedObj = redisTemplate.opsForValue().get(RedisConstant.PLAYLIST_ALL_ALBUM);
+        if (cachedObj != null) {
+            // 安全的类型转换
+            @SuppressWarnings("unchecked")
+            List<AlbumListDto> cachedList = (List<AlbumListDto>) cachedObj;
+            return Result.success(cachedList);
+        }
+
+        List<AlbumListDto> list = albumService.selAlbumList();
+        redisTemplate.opsForValue().set(RedisConstant.PLAYLIST_ALL_ALBUM, list, 24, TimeUnit.HOURS);
+        return Result.success(list);
+    }
+    @GetMapping("/AlbumNum")
+    public List<AlbumNumDto> AlbumNum(@RequestParam List<Integer> ids) {
+        List<AlbumNumDto> list = albumService.selAlbumNumList(ids);
+        log.info("list = " + list);
+        return list;
+    }
 }

+ 0 - 20
content/src/main/java/com/content/controller/ArtistMediaHistoryController.java

@@ -1,20 +0,0 @@
-package com.content.controller;
-
-
-import org.springframework.web.bind.annotation.RequestMapping;
-
-import org.springframework.web.bind.annotation.RestController;
-
-/**
- * <p>
- * 艺人媒体文件历史记录表 前端控制器
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-@RestController
-@RequestMapping("/artist-media-history")
-public class ArtistMediaHistoryController {
-
-}

+ 0 - 20
content/src/main/java/com/content/controller/ChunkInfoController.java

@@ -1,20 +0,0 @@
-package com.content.controller;
-
-
-import org.springframework.web.bind.annotation.RequestMapping;
-
-import org.springframework.web.bind.annotation.RestController;
-
-/**
- * <p>
- * 分块上传信息表 前端控制器
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-@RestController
-@RequestMapping("/chunk-info")
-public class ChunkInfoController {
-
-}

+ 0 - 20
content/src/main/java/com/content/controller/MediaProcessController.java

@@ -1,20 +0,0 @@
-package com.content.controller;
-
-
-import org.springframework.web.bind.annotation.RequestMapping;
-
-import org.springframework.web.bind.annotation.RestController;
-
-/**
- * <p>
- * 媒体处理任务表 前端控制器
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-@RestController
-@RequestMapping("/media-process")
-public class MediaProcessController {
-
-}

+ 0 - 20
content/src/main/java/com/content/controller/MediaProcessHistoryController.java

@@ -1,20 +0,0 @@
-package com.content.controller;
-
-
-import org.springframework.web.bind.annotation.RequestMapping;
-
-import org.springframework.web.bind.annotation.RestController;
-
-/**
- * <p>
- * 媒体处理历史表 前端控制器
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-@RestController
-@RequestMapping("/media-process-history")
-public class MediaProcessHistoryController {
-
-}

+ 0 - 20
content/src/main/java/com/content/controller/MediaVideoController.java

@@ -1,20 +0,0 @@
-package com.content.controller;
-
-
-import org.springframework.web.bind.annotation.RequestMapping;
-
-import org.springframework.web.bind.annotation.RestController;
-
-/**
- * <p>
- * 视频文件表 前端控制器
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-@RestController
-@RequestMapping("/media-video")
-public class MediaVideoController {
-
-}

+ 52 - 16
content/src/main/java/com/content/controller/PlaylistController.java

@@ -1,20 +1,25 @@
 package com.content.controller;
-
 import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.base.common.RedisConstant;
 import com.base.utils.Result;
 import com.content.config.SecurityUtil;
+import com.content.domain.dto.CollectSongDto;
+import com.content.domain.dto.PageDto;
 import com.content.domain.po.Playlist;
 import com.content.domain.po.WyUser;
+import com.content.domain.query.PageQuery;
 import com.content.service.IPlaylistService;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
-
 import java.util.List;
 import java.util.concurrent.TimeUnit;
-
 @Slf4j
 @RestController
 @RequestMapping("/playlist")
@@ -30,24 +35,19 @@ public class PlaylistController {
     public Result list() {
         WyUser user = SecurityUtil.getUser();
         Integer userId = user.getId();
-
         // 构建Redis key
-        String redisKey = "playlist:user:" + userId;
-
+        String redisKey = RedisConstant.PLAYLIST_USER_PREFIX + userId;
         // 尝试从Redis获取数据
         String cachedData = (String) redisTemplate.opsForValue().get(redisKey);
         if (cachedData != null) {
             List<Playlist> list = JSON.parseArray(cachedData, Playlist.class);
             return Result.success(list);
         }
-
         // Redis中没有数据,从数据库查询
-        List<Playlist> list = playlistService.lambdaQuery().eq(Playlist::getUserId, userId).list();
-
+        List<Playlist> list = playlistService.lambdaQuery().eq(Playlist::getUserId, userId).eq(Playlist::getStatus, 0).list();
         // 将数据存入Redis,设置过期时间(例如30分钟)
         String jsonString = JSON.toJSONString(list);
         redisTemplate.opsForValue().set(redisKey, jsonString, 30, TimeUnit.MINUTES);
-
         return Result.success(list);
     }
 
@@ -56,11 +56,7 @@ public class PlaylistController {
     public Result add(@RequestBody Playlist playlist) {
         playlist.setUserId(SecurityUtil.getUser().getId());
         playlistService.save(playlist);
-
-        // 清除该用户的歌单缓存
-        String redisKey = "playlist:user:" + playlist.getUserId();
-        redisTemplate.delete(redisKey);
-
+        redisTemplate.delete(RedisConstant.PLAYLIST_USER_PREFIX + playlist.getUserId());
         return Result.success("添加成功");
     }
 
@@ -70,4 +66,44 @@ public class PlaylistController {
         log.info("id: " + id);
         return Result.success(playlistService.payListDetail(id));
     }
-}
+
+    @PostMapping("/PageQuery")
+    @PreAuthorize("hasRole('ROLE_USER')")
+    public Result<PageDto> PageQuery(@RequestBody PageQuery pageQuery) {
+        Long pageNo = pageQuery.getPageNo() != null ? pageQuery.getPageNo() : 1;
+        long pageSize = pageQuery.getPageSize() != null ? pageQuery.getPageSize() : 10;
+        Page<Playlist> page = Page.of(pageNo, pageSize);
+
+        LambdaQueryWrapper<Playlist> queryWrapper = new LambdaQueryWrapper<>();
+
+        queryWrapper
+                .in(StringUtils.isNotBlank(pageQuery.getTag()), Playlist::getTag, pageQuery.getTag())
+                .eq(StringUtils.isNotBlank(pageQuery.getLanguage()), Playlist::getLanguage, pageQuery.getLanguage())
+                .eq(StringUtils.isNotBlank(pageQuery.getStyle()), Playlist::getStyle, pageQuery.getStyle())
+                .eq(StringUtils.isNotBlank(pageQuery.getScene()), Playlist::getScene, pageQuery.getScene())
+                .eq(StringUtils.isNotBlank(pageQuery.getEmotion()), Playlist::getEmotion, pageQuery.getEmotion())
+                .eq(StringUtils.isNotBlank(pageQuery.getTheme()), Playlist::getTheme, pageQuery.getTheme()).eq(Playlist::getStatus, 0);
+
+        IPage<Playlist> result = playlistService.page(page, queryWrapper);
+
+        PageDto<Playlist> pageDto = new PageDto<>(
+                result.getTotal(),
+                result.getRecords(),
+                result.getCurrent(),
+                result.getSize()
+        );
+        return Result.success(pageDto);
+    }
+    @PostMapping("collectSong")
+    @PreAuthorize("hasRole('ROLE_USER')")
+    public Result collectSong(@RequestBody CollectSongDto collectSongDto) {
+        playlistService.collectSong(collectSongDto);
+        return Result.success("收藏成功");
+    }
+    @PostMapping("uncollectSong")
+    @PreAuthorize("hasRole('ROLE_USER')")
+    public Result uncollectSong(@RequestBody CollectSongDto collectSongDto) {
+        playlistService.uncollectSong(collectSongDto);
+        return Result.success("取消收藏");
+    }
+}

+ 7 - 0
content/src/main/java/com/content/controller/SongController.java

@@ -78,4 +78,11 @@ public class SongController {
         iSongService.lambdaUpdate().eq(Song::getId, pageQueryDto.getId()).set(Song::getStatus, pageQueryDto.getStatus()).update();
         return Result.success("修改完成");
     }
+    //根据id查询歌曲
+    @GetMapping("/getById")
+    @PreAuthorize("hasRole('ROLE_USER')")
+    public Result getById(@RequestParam Integer id) {
+        Song song = iSongService.getById(id);
+        return Result.success(song);
+    }
 }

+ 2 - 1
content/src/main/java/com/content/controller/SwipperController.java

@@ -1,5 +1,6 @@
 package com.content.controller;
 import com.alibaba.fastjson.JSON;
+import com.base.common.RedisConstant;
 import com.base.exception.WyMusicException;
 import com.base.utils.Result;
 import com.content.domain.po.Swipper;
@@ -32,7 +33,7 @@ public class SwipperController {
     @GetMapping("/swipper")
     public Result<List<Swipper>> findRecommend(){
         // 先从Redis中获取
-        String redisKey = "swipper:list";
+        String redisKey = RedisConstant.SWIPPER_LIST;
         String cachedData = (String) redisTemplate.opsForValue().get(redisKey);
 
         if (cachedData != null) {

+ 0 - 20
content/src/main/java/com/content/controller/SysConfigController.java

@@ -1,20 +0,0 @@
-package com.content.controller;
-
-
-import org.springframework.web.bind.annotation.RequestMapping;
-
-import org.springframework.web.bind.annotation.RestController;
-
-/**
- * <p>
- * 系统配置表 前端控制器
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-@RestController
-@RequestMapping("/sys-config")
-public class SysConfigController {
-
-}

+ 0 - 20
content/src/main/java/com/content/controller/VideoProcessQueueController.java

@@ -1,20 +0,0 @@
-package com.content.controller;
-
-
-import org.springframework.web.bind.annotation.RequestMapping;
-
-import org.springframework.web.bind.annotation.RestController;
-
-/**
- * <p>
- * 视频处理队列表 前端控制器
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-@RestController
-@RequestMapping("/video-process-queue")
-public class VideoProcessQueueController {
-
-}

+ 0 - 235
content/src/main/java/com/content/domain/po/Artist.java

@@ -1,235 +0,0 @@
-package com.content.domain.po;
-
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.baomidou.mybatisplus.annotation.IdType;
-import java.time.LocalDate;
-import com.baomidou.mybatisplus.annotation.TableId;
-import java.time.LocalDateTime;
-import java.io.Serializable;
-
-/**
- * <p>
- * 艺人基础信息表
- * </p>
- *
- * @author xiang
- * @since 2025-11-18
- */
-@TableName("artist")
-public class Artist implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    @TableId(value = "id", type = IdType.AUTO)
-    private Integer id;
-
-    /**
-     * 关联平台用户ID(对应user表id)
-     */
-    private Integer userId;
-
-    /**
-     * 艺人名
-     */
-    private String artistName;
-
-    /**
-     * 艺人头像URL
-     */
-    private String avatar;
-
-    /**
-     * 艺人页头图(网页端)URL
-     */
-    private String headerImage;
-
-    /**
-     * 性别:1-男,2-女,3-团体
-     */
-    private Integer gender;
-
-    /**
-     * 生日
-     */
-    private LocalDate birthday;
-
-    /**
-     * 艺人所属地区
-     */
-    private String region;
-
-    /**
-     * 流派风格(多个用逗号分隔,如流行,摇滚)
-     */
-    private String genre;
-
-    /**
-     * 所属公司/厂牌
-     */
-    private String company;
-
-    /**
-     * 艺人介绍(10-1000字)
-     */
-    private String introduction;
-
-    /**
-     * 邀请码
-     */
-    private String invitationCode;
-
-    /**
-     * 微信号
-     */
-    private String wechat;
-
-    /**
-     * 艺人账号状态:0-待审核,1-已通过,2-已拒绝,3-已冻结
-     */
-    private Integer status;
-
-    /**
-     * 创建时间
-     */
-    private LocalDateTime createTime;
-
-    /**
-     * 更新时间
-     */
-    private LocalDateTime updateTime;
-
-    public Integer getId() {
-        return id;
-    }
-
-    public void setId(Integer id) {
-        this.id = id;
-    }
-    public Integer getUserId() {
-        return userId;
-    }
-
-    public void setUserId(Integer userId) {
-        this.userId = userId;
-    }
-    public String getArtistName() {
-        return artistName;
-    }
-
-    public void setArtistName(String artistName) {
-        this.artistName = artistName;
-    }
-    public String getAvatar() {
-        return avatar;
-    }
-
-    public void setAvatar(String avatar) {
-        this.avatar = avatar;
-    }
-    public String getHeaderImage() {
-        return headerImage;
-    }
-
-    public void setHeaderImage(String headerImage) {
-        this.headerImage = headerImage;
-    }
-    public Integer getGender() {
-        return gender;
-    }
-
-    public void setGender(Integer gender) {
-        this.gender = gender;
-    }
-    public LocalDate getBirthday() {
-        return birthday;
-    }
-
-    public void setBirthday(LocalDate birthday) {
-        this.birthday = birthday;
-    }
-    public String getRegion() {
-        return region;
-    }
-
-    public void setRegion(String region) {
-        this.region = region;
-    }
-    public String getGenre() {
-        return genre;
-    }
-
-    public void setGenre(String genre) {
-        this.genre = genre;
-    }
-    public String getCompany() {
-        return company;
-    }
-
-    public void setCompany(String company) {
-        this.company = company;
-    }
-    public String getIntroduction() {
-        return introduction;
-    }
-
-    public void setIntroduction(String introduction) {
-        this.introduction = introduction;
-    }
-    public String getInvitationCode() {
-        return invitationCode;
-    }
-
-    public void setInvitationCode(String invitationCode) {
-        this.invitationCode = invitationCode;
-    }
-    public String getWechat() {
-        return wechat;
-    }
-
-    public void setWechat(String wechat) {
-        this.wechat = wechat;
-    }
-    public Integer getStatus() {
-        return status;
-    }
-
-    public void setStatus(Integer status) {
-        this.status = status;
-    }
-    public LocalDateTime getCreateTime() {
-        return createTime;
-    }
-
-    public void setCreateTime(LocalDateTime createTime) {
-        this.createTime = createTime;
-    }
-    public LocalDateTime getUpdateTime() {
-        return updateTime;
-    }
-
-    public void setUpdateTime(LocalDateTime updateTime) {
-        this.updateTime = updateTime;
-    }
-
-    @Override
-    public String toString() {
-        return "Artist{" +
-            "id=" + id +
-            ", userId=" + userId +
-            ", artistName=" + artistName +
-            ", avatar=" + avatar +
-            ", headerImage=" + headerImage +
-            ", gender=" + gender +
-            ", birthday=" + birthday +
-            ", region=" + region +
-            ", genre=" + genre +
-            ", company=" + company +
-            ", introduction=" + introduction +
-            ", invitationCode=" + invitationCode +
-            ", wechat=" + wechat +
-            ", status=" + status +
-            ", createTime=" + createTime +
-            ", updateTime=" + updateTime +
-        "}";
-    }
-}

+ 0 - 59
content/src/main/java/com/content/domain/po/ChunkInfo.java

@@ -1,59 +0,0 @@
-package com.content.domain.po;
-
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableId;
-import java.time.LocalDateTime;
-import java.io.Serializable;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.experimental.Accessors;
-
-/**
- * <p>
- * 分块上传信息表
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-@Data
-@EqualsAndHashCode(callSuper = false)
-@Accessors(chain = true)
-@TableName("chunk_info")
-@ApiModel(value="ChunkInfo对象", description="分块上传信息表")
-public class ChunkInfo implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    @TableId(value = "id", type = IdType.AUTO)
-    private Long id;
-
-    @ApiModelProperty(value = "文件MD5")
-    private String fileMd5;
-
-    @ApiModelProperty(value = "原始文件名")
-    private String fileName;
-
-    @ApiModelProperty(value = "分块索引")
-    private Integer chunkIndex;
-
-    @ApiModelProperty(value = "总分块数")
-    private Integer totalChunks;
-
-    @ApiModelProperty(value = "分块文件URL")
-    private String chunkUrl;
-
-    @ApiModelProperty(value = "状态:0-待上传,1-已上传")
-    private Integer status;
-
-    @ApiModelProperty(value = "上传时间")
-    private LocalDateTime uploadedTime;
-
-    @ApiModelProperty(value = "创建时间")
-    private LocalDateTime createTime;
-
-
-}

+ 0 - 71
content/src/main/java/com/content/domain/po/MediaProcess.java

@@ -1,71 +0,0 @@
-package com.content.domain.po;
-
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableId;
-import java.time.LocalDateTime;
-import java.io.Serializable;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.experimental.Accessors;
-
-/**
- * <p>
- * 媒体处理任务表
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-@Data
-@EqualsAndHashCode(callSuper = false)
-@Accessors(chain = true)
-@TableName("media_process")
-@ApiModel(value="MediaProcess对象", description="媒体处理任务表")
-public class MediaProcess implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    @TableId(value = "id", type = IdType.AUTO)
-    private Long id;
-
-    @ApiModelProperty(value = "文件ID")
-    private String fileId;
-
-    @ApiModelProperty(value = "文件名")
-    private String fileName;
-
-    @ApiModelProperty(value = "存储桶")
-    private String bucket;
-
-    @ApiModelProperty(value = "文件路径")
-    private String filePath;
-
-    @ApiModelProperty(value = "任务状态: 0-待处理, 1-处理中, 2-处理成功, 3-处理失败")
-    private String status;
-
-    @ApiModelProperty(value = "失败次数")
-    private Integer failCount;
-
-    @ApiModelProperty(value = "错误信息")
-    private String errormsg;
-
-    @ApiModelProperty(value = "处理后文件URL")
-    private String url;
-
-    @ApiModelProperty(value = "完成时间")
-    private LocalDateTime finishDate;
-
-    @ApiModelProperty(value = "创建时间")
-    private LocalDateTime createDate;
-
-    @ApiModelProperty(value = "流程定义ID")
-    private String processDefinitionId;
-
-    @ApiModelProperty(value = "标签")
-    private String tag;
-
-
-}

+ 0 - 65
content/src/main/java/com/content/domain/po/MediaProcessHistory.java

@@ -1,65 +0,0 @@
-package com.content.domain.po;
-
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableId;
-import java.time.LocalDateTime;
-import java.io.Serializable;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.experimental.Accessors;
-
-/**
- * <p>
- * 媒体处理历史表
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-@Data
-@EqualsAndHashCode(callSuper = false)
-@Accessors(chain = true)
-@TableName("media_process_history")
-@ApiModel(value="MediaProcessHistory对象", description="媒体处理历史表")
-public class MediaProcessHistory implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    @TableId(value = "id", type = IdType.AUTO)
-    private Long id;
-
-    @ApiModelProperty(value = "对应的任务ID")
-    private Long processId;
-
-    @ApiModelProperty(value = "文件ID")
-    private String fileId;
-
-    @ApiModelProperty(value = "文件名")
-    private String fileName;
-
-    @ApiModelProperty(value = "存储桶")
-    private String bucket;
-
-    @ApiModelProperty(value = "文件路径")
-    private String filePath;
-
-    @ApiModelProperty(value = "处理状态")
-    private String status;
-
-    @ApiModelProperty(value = "错误信息")
-    private String errormsg;
-
-    @ApiModelProperty(value = "处理后URL")
-    private String url;
-
-    @ApiModelProperty(value = "完成时间")
-    private LocalDateTime finishDate;
-
-    @ApiModelProperty(value = "创建时间")
-    private LocalDateTime createDate;
-
-
-}

+ 0 - 78
content/src/main/java/com/content/domain/po/MediaVideo.java

@@ -1,78 +0,0 @@
-package com.content.domain.po;
-
-import java.math.BigDecimal;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableId;
-import java.time.LocalDateTime;
-import java.io.Serializable;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.experimental.Accessors;
-
-/**
- * <p>
- * 视频文件表
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-@Data
-@EqualsAndHashCode(callSuper = false)
-@Accessors(chain = true)
-@TableName("media_video")
-@ApiModel(value="MediaVideo对象", description="视频文件表")
-public class MediaVideo implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    @TableId(value = "id", type = IdType.AUTO)
-    private Long id;
-
-    @ApiModelProperty(value = "原始文件名")
-    private String originalName;
-
-    @ApiModelProperty(value = "存储文件名")
-    private String fileName;
-
-    @ApiModelProperty(value = "视频文件URL")
-    private String fileUrl;
-
-    @ApiModelProperty(value = "预览GIF URL")
-    private String previewGifUrl;
-
-    @ApiModelProperty(value = "文件大小")
-    private Long fileSize;
-
-    @ApiModelProperty(value = "视频时长")
-    private String duration;
-
-    @ApiModelProperty(value = "上传歌手")
-    private String singer;
-
-    @ApiModelProperty(value = "存储桶名")
-    private String bucketName;
-
-    @ApiModelProperty(value = "状态:0-待处理,1-处理中,2-已完成,3-处理失败")
-    private Integer status;
-
-    @ApiModelProperty(value = "处理进度(%)")
-    private BigDecimal processProgress;
-
-    @ApiModelProperty(value = "重试次数")
-    private Integer retryCount;
-
-    @ApiModelProperty(value = "创建时间")
-    private LocalDateTime createdTime;
-
-    @ApiModelProperty(value = "更新时间")
-    private LocalDateTime updatedTime;
-
-    @ApiModelProperty(value = "处理完成时间")
-    private LocalDateTime processedTime;
-
-
-}

+ 18 - 11
content/src/main/java/com/content/domain/po/Playlist.java

@@ -1,21 +1,13 @@
 package com.content.domain.po;
 
-import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
-import java.time.LocalDateTime;
 import java.io.Serializable;
+import java.time.LocalDateTime;
 
-/**
- * <p>
- * 歌单表
- * </p>
- *
- * @author xiang
- * @since 2025-11-18
- */
 @Data
 @TableName("playlist")
 public class Playlist implements Serializable {
@@ -36,8 +28,23 @@ public class Playlist implements Serializable {
 
     private String description;
 
+    // 原tag字段(若保留,可用于存储自定义标签)
     private String tag;
 
+    // 新增:语种(对应页面“语种”分类,如“华语”“欧美”)
+    private String language;
+
+    // 新增:风格(对应页面“风格”分类,如“流行”“摇滚”)
+    private String style;
+
+    // 新增:场景(对应页面“场景”分类,如“学习”“工作”)
+    private String scene;
+
+    // 新增:情感(对应页面“情感”分类,如“治愈”“放松”)
+    private String emotion;
+
+    // 新增:主题
+    private String Theme;
     /**
      * 歌单歌曲数量
      */
@@ -57,4 +64,4 @@ public class Playlist implements Serializable {
      * 0-公开,1-私密
      */
     private Boolean status;
-}
+}

+ 0 - 50
content/src/main/java/com/content/domain/po/SysConfig.java

@@ -1,50 +0,0 @@
-package com.content.domain.po;
-
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableId;
-import java.time.LocalDateTime;
-import java.io.Serializable;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.experimental.Accessors;
-
-/**
- * <p>
- * 系统配置表
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-@Data
-@EqualsAndHashCode(callSuper = false)
-@Accessors(chain = true)
-@TableName("sys_config")
-@ApiModel(value="SysConfig对象", description="系统配置表")
-public class SysConfig implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    @TableId(value = "id", type = IdType.AUTO)
-    private Long id;
-
-    @ApiModelProperty(value = "配置键")
-    private String configKey;
-
-    @ApiModelProperty(value = "配置值")
-    private String configValue;
-
-    @ApiModelProperty(value = "配置描述")
-    private String description;
-
-    @ApiModelProperty(value = "创建时间")
-    private LocalDateTime createTime;
-
-    @ApiModelProperty(value = "更新时间")
-    private LocalDateTime updateTime;
-
-
-}

+ 0 - 78
content/src/main/java/com/content/domain/po/UserFavoriteArtist.java

@@ -1,78 +0,0 @@
-package com.content.domain.po;
-
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableId;
-import java.time.LocalDateTime;
-import java.io.Serializable;
-
-/**
- * <p>
- * 我喜欢的歌手表
- * </p>
- *
- * @author xiang
- * @since 2025-11-18
- */
-@TableName("user_favorite_artist")
-public class UserFavoriteArtist implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    @TableId(value = "id", type = IdType.AUTO)
-    private Integer id;
-
-    /**
-     * 关联用户ID(对应user表id)
-     */
-    private Integer userId;
-
-    /**
-     * 关联艺人ID(对应artist表id)
-     */
-    private Integer artistId;
-
-    /**
-     * 关注时间
-     */
-    private LocalDateTime createTime;
-
-    public Integer getId() {
-        return id;
-    }
-
-    public void setId(Integer id) {
-        this.id = id;
-    }
-    public Integer getUserId() {
-        return userId;
-    }
-
-    public void setUserId(Integer userId) {
-        this.userId = userId;
-    }
-    public Integer getArtistId() {
-        return artistId;
-    }
-
-    public void setArtistId(Integer artistId) {
-        this.artistId = artistId;
-    }
-    public LocalDateTime getCreateTime() {
-        return createTime;
-    }
-
-    public void setCreateTime(LocalDateTime createTime) {
-        this.createTime = createTime;
-    }
-
-    @Override
-    public String toString() {
-        return "UserFavoriteArtist{" +
-            "id=" + id +
-            ", userId=" + userId +
-            ", artistId=" + artistId +
-            ", createTime=" + createTime +
-        "}";
-    }
-}

+ 7 - 39
content/src/main/java/com/content/domain/po/UserPlaylistFavorite.java

@@ -3,6 +3,10 @@ package com.content.domain.po;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
 import java.time.LocalDateTime;
 import java.io.Serializable;
 
@@ -15,8 +19,10 @@ import java.io.Serializable;
  * @since 2025-11-18
  */
 @TableName("user_playlist_favorite")
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
 public class UserPlaylistFavorite implements Serializable {
-
     private static final long serialVersionUID = 1L;
 
     @TableId(value = "id", type = IdType.AUTO)
@@ -37,42 +43,4 @@ public class UserPlaylistFavorite implements Serializable {
      */
     private LocalDateTime createTime;
 
-    public Integer getId() {
-        return id;
-    }
-
-    public void setId(Integer id) {
-        this.id = id;
-    }
-    public Integer getUserId() {
-        return userId;
-    }
-
-    public void setUserId(Integer userId) {
-        this.userId = userId;
-    }
-    public Integer getPlaylistId() {
-        return playlistId;
-    }
-
-    public void setPlaylistId(Integer playlistId) {
-        this.playlistId = playlistId;
-    }
-    public LocalDateTime getCreateTime() {
-        return createTime;
-    }
-
-    public void setCreateTime(LocalDateTime createTime) {
-        this.createTime = createTime;
-    }
-
-    @Override
-    public String toString() {
-        return "UserPlaylistFavorite{" +
-            "id=" + id +
-            ", userId=" + userId +
-            ", playlistId=" + playlistId +
-            ", createTime=" + createTime +
-        "}";
-    }
 }

+ 0 - 47
content/src/main/java/com/content/domain/po/VideoProcessQueue.java

@@ -1,47 +0,0 @@
-package com.content.domain.po;
-
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableId;
-import java.time.LocalDateTime;
-import java.io.Serializable;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.experimental.Accessors;
-
-/**
- * <p>
- * 视频处理队列表
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-@Data
-@EqualsAndHashCode(callSuper = false)
-@Accessors(chain = true)
-@TableName("video_process_queue")
-@ApiModel(value="VideoProcessQueue对象", description="视频处理队列表")
-public class VideoProcessQueue implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    @TableId(value = "id", type = IdType.AUTO)
-    private Long id;
-
-    @ApiModelProperty(value = "视频ID")
-    private Long videoId;
-
-    @ApiModelProperty(value = "优先级:1-普通,2-高")
-    private Integer priority;
-
-    @ApiModelProperty(value = "0-待处理,1-已调度,2-已完成")
-    private Integer status;
-
-    @ApiModelProperty(value = "调度时间")
-    private LocalDateTime scheduledTime;
-
-
-}

+ 13 - 1
content/src/main/java/com/content/mapper/AlbumMapper.java

@@ -1,12 +1,18 @@
 package com.content.mapper;
 
+import com.content.domain.dto.AlbumListDto;
+import com.content.domain.dto.AlbumNumDto;
 import com.content.domain.po.Album;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
 
 /**
  * <p>
- *  Mapper 接口
+ * Mapper 接口
  * </p>
  *
  * @author xiang
@@ -14,5 +20,11 @@ import org.apache.ibatis.annotations.Mapper;
  */
 @Mapper
 public interface AlbumMapper extends BaseMapper<Album> {
+    @Select("SELECT id, album_name as title, cover_url as src FROM album WHERE delete_flag = 0 AND status = 3")
+    List<AlbumListDto> selAlbumList();
+
+//    @Select("SELECT artist_id,COUNT(*) AS num FROM album WHERE artist_id IN ${id} GROUP BY artist_id;")
+//    List<AlbumNumDto> selAlbumNumList(@Param("id") List<Integer> id);
 
+List<AlbumNumDto> selAlbumNumList(@Param("id") List<Integer> id);
 }

+ 0 - 18
content/src/main/java/com/content/mapper/ArtistMapper.java

@@ -1,18 +0,0 @@
-package com.content.mapper;
-
-import com.content.domain.po.Artist;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import org.apache.ibatis.annotations.Mapper;
-
-/**
- * <p>
- *  Mapper 接口
- * </p>
- *
- * @author xiang
- * @since 2025-11-06
- */
-@Mapper
-public interface ArtistMapper extends BaseMapper<Artist> {
-
-}

+ 0 - 16
content/src/main/java/com/content/mapper/ArtistMediaHistoryMapper.java

@@ -1,16 +0,0 @@
-package com.content.mapper;
-
-import com.content.domain.po.ArtistMediaHistory;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-
-/**
- * <p>
- * 艺人媒体文件历史记录表 Mapper 接口
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-public interface ArtistMediaHistoryMapper extends BaseMapper<ArtistMediaHistory> {
-
-}

+ 0 - 16
content/src/main/java/com/content/mapper/ChunkInfoMapper.java

@@ -1,16 +0,0 @@
-package com.content.mapper;
-
-import com.content.domain.po.ChunkInfo;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-
-/**
- * <p>
- * 分块上传信息表 Mapper 接口
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-public interface ChunkInfoMapper extends BaseMapper<ChunkInfo> {
-
-}

+ 0 - 16
content/src/main/java/com/content/mapper/MediaProcessHistoryMapper.java

@@ -1,16 +0,0 @@
-package com.content.mapper;
-
-import com.content.domain.po.MediaProcessHistory;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-
-/**
- * <p>
- * 媒体处理历史表 Mapper 接口
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-public interface MediaProcessHistoryMapper extends BaseMapper<MediaProcessHistory> {
-
-}

+ 0 - 16
content/src/main/java/com/content/mapper/MediaProcessMapper.java

@@ -1,16 +0,0 @@
-package com.content.mapper;
-
-import com.content.domain.po.MediaProcess;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-
-/**
- * <p>
- * 媒体处理任务表 Mapper 接口
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-public interface MediaProcessMapper extends BaseMapper<MediaProcess> {
-
-}

+ 0 - 16
content/src/main/java/com/content/mapper/MediaVideoMapper.java

@@ -1,16 +0,0 @@
-package com.content.mapper;
-
-import com.content.domain.po.MediaVideo;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-
-/**
- * <p>
- * 视频文件表 Mapper 接口
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-public interface MediaVideoMapper extends BaseMapper<MediaVideo> {
-
-}

+ 0 - 16
content/src/main/java/com/content/mapper/SysConfigMapper.java

@@ -1,16 +0,0 @@
-package com.content.mapper;
-
-import com.content.domain.po.SysConfig;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-
-/**
- * <p>
- * 系统配置表 Mapper 接口
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-public interface SysConfigMapper extends BaseMapper<SysConfig> {
-
-}

+ 0 - 18
content/src/main/java/com/content/mapper/UserFavoriteArtistMapper.java

@@ -1,18 +0,0 @@
-package com.content.mapper;
-
-import com.content.domain.po.UserFavoriteArtist;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import org.apache.ibatis.annotations.Mapper;
-
-/**
- * <p>
- *  Mapper 接口
- * </p>
- *
- * @author xiang
- * @since 2025-11-06
- */
-@Mapper
-public interface UserFavoriteArtistMapper extends BaseMapper<UserFavoriteArtist> {
-
-}

+ 4 - 0
content/src/main/java/com/content/mapper/UserPlaylistFavoriteMapper.java

@@ -1,9 +1,12 @@
 package com.content.mapper;
 
+import com.content.domain.po.Playlist;
 import com.content.domain.po.UserPlaylistFavorite;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import org.apache.ibatis.annotations.Mapper;
 
+import java.util.ArrayList;
+
 /**
  * <p>
  *  Mapper 接口
@@ -15,4 +18,5 @@ import org.apache.ibatis.annotations.Mapper;
 @Mapper
 public interface UserPlaylistFavoriteMapper extends BaseMapper<UserPlaylistFavorite> {
 
+    ArrayList<Playlist> queryAll(Integer id);
 }

+ 0 - 16
content/src/main/java/com/content/mapper/VideoProcessQueueMapper.java

@@ -1,16 +0,0 @@
-package com.content.mapper;
-
-import com.content.domain.po.VideoProcessQueue;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-
-/**
- * <p>
- * 视频处理队列表 Mapper 接口
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-public interface VideoProcessQueueMapper extends BaseMapper<VideoProcessQueue> {
-
-}

+ 7 - 0
content/src/main/java/com/content/service/IAlbumService.java

@@ -1,8 +1,12 @@
 package com.content.service;
 
+import com.content.domain.dto.AlbumListDto;
+import com.content.domain.dto.AlbumNumDto;
 import com.content.domain.po.Album;
 import com.baomidou.mybatisplus.extension.service.IService;
 
+import java.util.List;
+
 /**
  * <p>
  *  服务类
@@ -13,4 +17,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
  */
 public interface IAlbumService extends IService<Album> {
 
+    List<AlbumListDto> selAlbumList();
+
+    List<AlbumNumDto> selAlbumNumList(List<Integer> id);
 }

+ 0 - 16
content/src/main/java/com/content/service/IArtistMediaHistoryService.java

@@ -1,16 +0,0 @@
-package com.content.service;
-
-import com.content.domain.po.ArtistMediaHistory;
-import com.baomidou.mybatisplus.extension.service.IService;
-
-/**
- * <p>
- * 艺人媒体文件历史记录表 服务类
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-public interface IArtistMediaHistoryService extends IService<ArtistMediaHistory> {
-
-}

+ 0 - 17
content/src/main/java/com/content/service/IArtistService.java

@@ -1,17 +0,0 @@
-package com.content.service;
-
-import com.content.domain.dto.MusicianApplicationDTO;
-import com.content.domain.po.Artist;
-import com.baomidou.mybatisplus.extension.service.IService;
-
-/**
- * <p>
- *  服务类
- * </p>
- *
- * @author xiang
- * @since 2025-11-06
- */
-public interface IArtistService extends IService<Artist> {
-
-}

+ 0 - 16
content/src/main/java/com/content/service/IChunkInfoService.java

@@ -1,16 +0,0 @@
-package com.content.service;
-
-import com.content.domain.po.ChunkInfo;
-import com.baomidou.mybatisplus.extension.service.IService;
-
-/**
- * <p>
- * 分块上传信息表 服务类
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-public interface IChunkInfoService extends IService<ChunkInfo> {
-
-}

+ 0 - 16
content/src/main/java/com/content/service/IMediaProcessHistoryService.java

@@ -1,16 +0,0 @@
-package com.content.service;
-
-import com.content.domain.po.MediaProcessHistory;
-import com.baomidou.mybatisplus.extension.service.IService;
-
-/**
- * <p>
- * 媒体处理历史表 服务类
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-public interface IMediaProcessHistoryService extends IService<MediaProcessHistory> {
-
-}

+ 0 - 16
content/src/main/java/com/content/service/IMediaProcessService.java

@@ -1,16 +0,0 @@
-package com.content.service;
-
-import com.content.domain.po.MediaProcess;
-import com.baomidou.mybatisplus.extension.service.IService;
-
-/**
- * <p>
- * 媒体处理任务表 服务类
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-public interface IMediaProcessService extends IService<MediaProcess> {
-
-}

+ 0 - 16
content/src/main/java/com/content/service/IMediaVideoService.java

@@ -1,16 +0,0 @@
-package com.content.service;
-
-import com.content.domain.po.MediaVideo;
-import com.baomidou.mybatisplus.extension.service.IService;
-
-/**
- * <p>
- * 视频文件表 服务类
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-public interface IMediaVideoService extends IService<MediaVideo> {
-
-}

+ 5 - 0
content/src/main/java/com/content/service/IPlaylistService.java

@@ -1,4 +1,5 @@
 package com.content.service;
+import com.content.domain.dto.CollectSongDto;
 import com.content.domain.dto.PlaylistWithSongsDTO;
 import com.content.domain.po.Playlist;
 import com.baomidou.mybatisplus.extension.service.IService;
@@ -16,4 +17,8 @@ import java.util.Map;
 public interface IPlaylistService extends IService<Playlist> {
 
     PlaylistWithSongsDTO payListDetail(Integer id);
+
+    void collectSong(CollectSongDto collectSongDto);
+
+    void uncollectSong(CollectSongDto collectSongDto);
 }

+ 0 - 16
content/src/main/java/com/content/service/ISysConfigService.java

@@ -1,16 +0,0 @@
-package com.content.service;
-
-import com.content.domain.po.SysConfig;
-import com.baomidou.mybatisplus.extension.service.IService;
-
-/**
- * <p>
- * 系统配置表 服务类
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-public interface ISysConfigService extends IService<SysConfig> {
-
-}

+ 4 - 0
content/src/main/java/com/content/service/IUserPlaylistFavoriteService.java

@@ -1,8 +1,11 @@
 package com.content.service;
 
+import com.content.domain.po.Playlist;
 import com.content.domain.po.UserPlaylistFavorite;
 import com.baomidou.mybatisplus.extension.service.IService;
 
+import java.util.ArrayList;
+
 /**
  * <p>
  *  服务类
@@ -13,4 +16,5 @@ import com.baomidou.mybatisplus.extension.service.IService;
  */
 public interface IUserPlaylistFavoriteService extends IService<UserPlaylistFavorite> {
 
+    ArrayList<Playlist> queryAll(Integer id);
 }

+ 0 - 16
content/src/main/java/com/content/service/IVideoProcessQueueService.java

@@ -1,16 +0,0 @@
-package com.content.service;
-
-import com.content.domain.po.VideoProcessQueue;
-import com.baomidou.mybatisplus.extension.service.IService;
-
-/**
- * <p>
- * 视频处理队列表 服务类
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-public interface IVideoProcessQueueService extends IService<VideoProcessQueue> {
-
-}

+ 18 - 0
content/src/main/java/com/content/service/impl/AlbumServiceImpl.java

@@ -1,11 +1,16 @@
 package com.content.service.impl;
 
+import com.content.domain.dto.AlbumListDto;
+import com.content.domain.dto.AlbumNumDto;
 import com.content.domain.po.Album;
 import com.content.mapper.AlbumMapper;
 import com.content.service.IAlbumService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.List;
+
 /**
  * <p>
  *  服务实现类
@@ -16,5 +21,18 @@ import org.springframework.stereotype.Service;
  */
 @Service
 public class AlbumServiceImpl extends ServiceImpl<AlbumMapper, Album> implements IAlbumService {
+    @Autowired
+    private AlbumMapper albumMapper;
+
+    @Override
+    public List<AlbumListDto> selAlbumList() {
+        return albumMapper.selAlbumList();
+    }
 
+    @Override
+    public List<AlbumNumDto> selAlbumNumList(List<Integer> id) {
+        List<AlbumNumDto> albumNumDtos = albumMapper.selAlbumNumList(id);
+        System.out.println("albumNumDtos = " + albumNumDtos);
+        return albumNumDtos;
+    }
 }

+ 0 - 20
content/src/main/java/com/content/service/impl/ArtistMediaHistoryServiceImpl.java

@@ -1,20 +0,0 @@
-package com.content.service.impl;
-
-import com.content.domain.po.ArtistMediaHistory;
-import com.content.mapper.ArtistMediaHistoryMapper;
-import com.content.service.IArtistMediaHistoryService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.stereotype.Service;
-
-/**
- * <p>
- * 艺人媒体文件历史记录表 服务实现类
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-@Service
-public class ArtistMediaHistoryServiceImpl extends ServiceImpl<ArtistMediaHistoryMapper, ArtistMediaHistory> implements IArtistMediaHistoryService {
-
-}

+ 0 - 29
content/src/main/java/com/content/service/impl/ArtistServiceImpl.java

@@ -1,29 +0,0 @@
-package com.content.service.impl;
-
-import com.alibaba.fastjson.JSON;
-import com.content.config.SecurityUtil;
-import com.content.domain.dto.MusicianApplicationDTO;
-import com.content.domain.po.Artist;
-import com.content.domain.po.ArtistRealAuth;
-import com.content.domain.po.WyUser;
-import com.content.mapper.ArtistMapper;
-import com.content.service.IArtistService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.beans.BeanUtils;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-/**
- * <p>
- *  服务实现类
- * </p>
- *
- * @author xiang
- * @since 2025-11-06
- */
-@Service
-public class ArtistServiceImpl extends ServiceImpl<ArtistMapper, Artist> implements IArtistService {
-
-
-}

+ 0 - 20
content/src/main/java/com/content/service/impl/ChunkInfoServiceImpl.java

@@ -1,20 +0,0 @@
-package com.content.service.impl;
-
-import com.content.domain.po.ChunkInfo;
-import com.content.mapper.ChunkInfoMapper;
-import com.content.service.IChunkInfoService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.stereotype.Service;
-
-/**
- * <p>
- * 分块上传信息表 服务实现类
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-@Service
-public class ChunkInfoServiceImpl extends ServiceImpl<ChunkInfoMapper, ChunkInfo> implements IChunkInfoService {
-
-}

+ 0 - 20
content/src/main/java/com/content/service/impl/MediaProcessHistoryServiceImpl.java

@@ -1,20 +0,0 @@
-package com.content.service.impl;
-
-import com.content.domain.po.MediaProcessHistory;
-import com.content.mapper.MediaProcessHistoryMapper;
-import com.content.service.IMediaProcessHistoryService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.stereotype.Service;
-
-/**
- * <p>
- * 媒体处理历史表 服务实现类
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-@Service
-public class MediaProcessHistoryServiceImpl extends ServiceImpl<MediaProcessHistoryMapper, MediaProcessHistory> implements IMediaProcessHistoryService {
-
-}

+ 0 - 20
content/src/main/java/com/content/service/impl/MediaProcessServiceImpl.java

@@ -1,20 +0,0 @@
-package com.content.service.impl;
-
-import com.content.domain.po.MediaProcess;
-import com.content.mapper.MediaProcessMapper;
-import com.content.service.IMediaProcessService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.stereotype.Service;
-
-/**
- * <p>
- * 媒体处理任务表 服务实现类
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-@Service
-public class MediaProcessServiceImpl extends ServiceImpl<MediaProcessMapper, MediaProcess> implements IMediaProcessService {
-
-}

+ 0 - 20
content/src/main/java/com/content/service/impl/MediaVideoServiceImpl.java

@@ -1,20 +0,0 @@
-package com.content.service.impl;
-
-import com.content.domain.po.MediaVideo;
-import com.content.mapper.MediaVideoMapper;
-import com.content.service.IMediaVideoService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.stereotype.Service;
-
-/**
- * <p>
- * 视频文件表 服务实现类
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-@Service
-public class MediaVideoServiceImpl extends ServiceImpl<MediaVideoMapper, MediaVideo> implements IMediaVideoService {
-
-}

+ 71 - 2
content/src/main/java/com/content/service/impl/PlaylistServiceImpl.java

@@ -1,19 +1,29 @@
 package com.content.service.impl;
+
+import com.base.common.RedisConstant;
 import com.base.exception.WyMusicException;
+import com.content.domain.dto.CollectSongDto;
 import com.content.domain.dto.PlaylistWithSongsDTO;
 import com.content.domain.po.Playlist;
+import com.content.domain.po.PlaylistSong;
+import com.content.domain.po.Song;
 import com.content.mapper.PlaylistMapper;
+import com.content.mapper.PlaylistSongMapper;
+import com.content.mapper.SongMapper;
 import com.content.service.IPlaylistService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.content.service.IPlaylistSongService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.util.Map;
 
 /**
  * <p>
- *  服务实现类
+ * 服务实现类
  * </p>
  *
  * @author xiang
@@ -24,8 +34,16 @@ import java.util.Map;
 public class PlaylistServiceImpl extends ServiceImpl<PlaylistMapper, Playlist> implements IPlaylistService {
     @Autowired
     private PlaylistMapper playlistMapper;
+    @Autowired
+    private SongMapper songMapper;
+    @Autowired
+    private IPlaylistSongService iPlaylistSongService;
+    @Autowired
+    private IPlaylistSongService playlistSongService;
+    @Autowired
+    private RedisTemplate redisTemplate;
     @Override
-    public  PlaylistWithSongsDTO  payListDetail(Integer id) {
+    public PlaylistWithSongsDTO payListDetail(Integer id) {
         log.info("id: " + id);
         if (id == null) {
             throw new WyMusicException("歌单ID不能为空");
@@ -33,4 +51,55 @@ public class PlaylistServiceImpl extends ServiceImpl<PlaylistMapper, Playlist> i
         PlaylistWithSongsDTO playlistWithSongs = playlistMapper.getPlaylistWithSongs(id);
         return playlistWithSongs;
     }
+
+    @Override
+    @Transactional
+    public void collectSong(CollectSongDto collectSongDto) {
+        Song song = songMapper.selectById(collectSongDto.getSongId());
+        if (song == null) {
+            throw new WyMusicException("歌曲不存在");
+        }
+        Playlist playlist = playlistMapper.selectById(collectSongDto.getPlaylistId());
+        if (playlist == null) {
+            throw new WyMusicException("歌单不存在");
+        }
+        PlaylistSong one = iPlaylistSongService.lambdaQuery().eq(PlaylistSong::getPlaylistId, collectSongDto.getPlaylistId())
+                .eq(PlaylistSong::getSongId, collectSongDto.getSongId()).one();
+        if (one!=null) {
+            throw new WyMusicException("歌曲已存在");
+        }
+        Long count = playlistSongService.lambdaQuery()
+                .eq(PlaylistSong::getPlaylistId, collectSongDto.getPlaylistId())
+                .eq(PlaylistSong::getSongId, collectSongDto.getSongId()).count();
+        PlaylistSong playlistSong = new PlaylistSong();
+        playlistSong.setPlaylistId(collectSongDto.getPlaylistId());
+        playlistSong.setSongId(collectSongDto.getSongId());
+        playlistSong.setOrderNum((int) (count+1));
+        iPlaylistSongService.save(playlistSong);
+        Integer songCount = playlist.getSongCount();
+        playlist.setCoverUrl(song.getCoverUrl());
+        playlist.setSongCount(songCount + 1);
+        playlistMapper.updateById(playlist);
+        redisTemplate.delete(RedisConstant.PLAYLIST_USER_PREFIX + playlist.getUserId());
+    }
+
+    @Override
+    public void uncollectSong(CollectSongDto collectSongDto) {
+        Song song = songMapper.selectById(collectSongDto.getSongId());
+        if (song == null) {
+            throw new WyMusicException("歌曲不存在");
+        }
+        Playlist playlist = playlistMapper.selectById(collectSongDto.getPlaylistId());
+        if (playlist == null) {
+            throw new WyMusicException("歌单不存在");
+        }
+        PlaylistSong one = iPlaylistSongService.lambdaQuery().eq(PlaylistSong::getId, collectSongDto.getPlaylistId()).eq(PlaylistSong::getSongId, collectSongDto.getSongId()).one();
+        System.out.println("one = " + one);
+        if (one.getId() == null) {
+            throw new WyMusicException("歌曲不存在");
+        }
+        iPlaylistSongService.removeById(one.getId());
+        playlist.setSongCount(playlist.getSongCount() - 1);
+        playlistMapper.updateById(playlist);
+    }
 }

+ 0 - 20
content/src/main/java/com/content/service/impl/SysConfigServiceImpl.java

@@ -1,20 +0,0 @@
-package com.content.service.impl;
-
-import com.content.domain.po.SysConfig;
-import com.content.mapper.SysConfigMapper;
-import com.content.service.ISysConfigService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.stereotype.Service;
-
-/**
- * <p>
- * 系统配置表 服务实现类
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-@Service
-public class SysConfigServiceImpl extends ServiceImpl<SysConfigMapper, SysConfig> implements ISysConfigService {
-
-}

+ 0 - 20
content/src/main/java/com/content/service/impl/UserFavoriteArtistServiceImpl.java

@@ -1,20 +0,0 @@
-package com.content.service.impl;
-
-import com.content.domain.po.UserFavoriteArtist;
-import com.content.mapper.UserFavoriteArtistMapper;
-import com.content.service.IUserFavoriteArtistService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.stereotype.Service;
-
-/**
- * <p>
- *  服务实现类
- * </p>
- *
- * @author xiang
- * @since 2025-11-06
- */
-@Service
-public class UserFavoriteArtistServiceImpl extends ServiceImpl<UserFavoriteArtistMapper, UserFavoriteArtist> implements IUserFavoriteArtistService {
-
-}

+ 11 - 1
content/src/main/java/com/content/service/impl/UserPlaylistFavoriteServiceImpl.java

@@ -1,14 +1,18 @@
 package com.content.service.impl;
 
+import com.content.domain.po.Playlist;
 import com.content.domain.po.UserPlaylistFavorite;
 import com.content.mapper.UserPlaylistFavoriteMapper;
 import com.content.service.IUserPlaylistFavoriteService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.ArrayList;
+
 /**
  * <p>
- *  服务实现类
+ * 服务实现类
  * </p>
  *
  * @author xiang
@@ -16,5 +20,11 @@ import org.springframework.stereotype.Service;
  */
 @Service
 public class UserPlaylistFavoriteServiceImpl extends ServiceImpl<UserPlaylistFavoriteMapper, UserPlaylistFavorite> implements IUserPlaylistFavoriteService {
+    @Autowired
+    private UserPlaylistFavoriteMapper userPlaylistFavoriteMapper;
 
+    @Override
+    public ArrayList<Playlist> queryAll(Integer id) {
+        return userPlaylistFavoriteMapper.queryAll(id);
+    }
 }

+ 0 - 20
content/src/main/java/com/content/service/impl/VideoProcessQueueServiceImpl.java

@@ -1,20 +0,0 @@
-package com.content.service.impl;
-
-import com.content.domain.po.VideoProcessQueue;
-import com.content.mapper.VideoProcessQueueMapper;
-import com.content.service.IVideoProcessQueueService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.stereotype.Service;
-
-/**
- * <p>
- * 视频处理队列表 服务实现类
- * </p>
- *
- * @author xiang
- * @since 2025-12-26
- */
-@Service
-public class VideoProcessQueueServiceImpl extends ServiceImpl<VideoProcessQueueMapper, VideoProcessQueue> implements IVideoProcessQueueService {
-
-}

+ 10 - 0
content/src/main/resources/mapper/AlbumMapper.xml

@@ -2,4 +2,14 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.content.mapper.AlbumMapper">
 
+    <select id="selAlbumNumList" resultType="com.content.domain.dto.AlbumNumDto"
+            parameterType="java.util.List">
+        SELECT artist_id AS id, COUNT(*) AS num
+        FROM album
+        WHERE artist_id IN
+        <foreach collection="id" item="artistId" open="(" separator="," close=")">
+            #{artistId}
+        </foreach>
+        GROUP BY artist_id
+    </select>
 </mapper>

+ 0 - 5
content/src/main/resources/mapper/ArtistMapper.xml

@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.content.mapper.ArtistMapper">
-
-</mapper>

+ 0 - 5
content/src/main/resources/mapper/ArtistMediaHistoryMapper.xml

@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.content.mapper.ArtistMediaHistoryMapper">
-
-</mapper>

+ 0 - 5
content/src/main/resources/mapper/MediaProcessHistoryMapper.xml

@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.content.mapper.MediaProcessHistoryMapper">
-
-</mapper>

+ 0 - 5
content/src/main/resources/mapper/MediaProcessMapper.xml

@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.content.mapper.MediaProcessMapper">
-
-</mapper>

+ 0 - 5
content/src/main/resources/mapper/MediaVideoMapper.xml

@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.content.mapper.MediaVideoMapper">
-
-</mapper>

+ 0 - 5
content/src/main/resources/mapper/SysConfigMapper.xml

@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.content.mapper.SysConfigMapper">
-
-</mapper>

+ 0 - 5
content/src/main/resources/mapper/UserFavoriteArtistMapper.xml

@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.content.mapper.UserFavoriteArtistMapper">
-
-</mapper>

+ 5 - 0
content/src/main/resources/mapper/UserPlaylistFavoriteMapper.xml

@@ -2,4 +2,9 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.content.mapper.UserPlaylistFavoriteMapper">
 
+    <select id="queryAll" resultType="com.content.domain.po.Playlist" parameterType="java.lang.Integer">
+        select a.* from playlist a
+                            inner join user_playlist_favorite b on b.playlist_id = a.id
+        where b.user_id = #{id}
+    </select>
 </mapper>

+ 0 - 5
content/src/main/resources/mapper/VideoProcessQueueMapper.xml

@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.content.mapper.VideoProcessQueueMapper">
-
-</mapper>

+ 121 - 4
media/media.sql

@@ -12,7 +12,7 @@ CREATE TABLE `media_file` (
                               `file_size` BIGINT COMMENT '文件大小(字节)',
                               `bucket_name` VARCHAR(100) NOT NULL COMMENT '存储桶名称',
                               `file_url` VARCHAR(500) NOT NULL COMMENT '文件访问URL',
-                              `storage_type` VARCHAR(20) DEFAULT 'oss' COMMENT '存储类型(oss、local、minio等)',
+                              `storage_type` VARCHAR(20) DEFAULT 'minio' COMMENT '存储类型(oss、local、minio等)',
                               `status` TINYINT DEFAULT 0 COMMENT '文件状态:0-正常,1-已删除(逻辑删除)',
                               `md5` VARCHAR(32) COMMENT '文件MD5值',
                               `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
@@ -31,9 +31,126 @@ CREATE TABLE `artist_media_history` (
                                         `artist_id` INT NOT NULL COMMENT '关联artist服务的artist.id',
                                         `media_type` VARCHAR(20) NOT NULL COMMENT '媒体类型: avatar、header_image等',
                                         `media_file_id` BIGINT NOT NULL COMMENT '关联本服务的media_file.id',
-                                        `is_current` TINYINT DEFAULT 0 COMMENT '是否为当前使用版本:0-否,1-是',
+                                        `is_current` TINYINT DEFAULT 1 COMMENT '是否为当前使用版本:0-否,1-是',
                                         `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
                                         FOREIGN KEY (`media_file_id`) REFERENCES `media_file` (`id`) ON DELETE RESTRICT,
                                         UNIQUE KEY `uk_artist_media_current` (`artist_id`, `media_type`, `is_current`),
-                                        INDEX `idx_artist_id` (`artist_id`) -- 逻辑关联索引
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='艺人媒体文件历史记录表';
+                                        INDEX `idx_artist_id` (`artist_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='艺人媒体文件历史记录表';
+
+-- ------------------------------
+-- 3. 分块上传信息表
+-- ------------------------------
+CREATE TABLE `chunk_info` (
+                              `id` BIGINT AUTO_INCREMENT PRIMARY KEY,
+                              `file_md5` VARCHAR(32) NOT NULL COMMENT '文件MD5',
+                              `file_name` VARCHAR(255) NOT NULL COMMENT '原始文件名',
+                              `chunk_index` INT NOT NULL COMMENT '分块索引',
+                              `total_chunks` INT NOT NULL COMMENT '总分块数',
+                              `chunk_url` VARCHAR(500) COMMENT '分块文件URL',
+                              `status` TINYINT DEFAULT 0 COMMENT '状态:0-待上传,1-已上传',
+                              `uploaded_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '上传时间',
+                              `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+                              INDEX `idx_file_md5` (`file_md5`),
+                              INDEX `idx_chunk_index` (`chunk_index`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='分块上传信息表';
+
+-- ------------------------------
+-- 4. 媒体处理任务表
+-- ------------------------------
+CREATE TABLE `media_process` (
+                                 `id` BIGINT AUTO_INCREMENT PRIMARY KEY,
+                                 `file_id` VARCHAR(32) NOT NULL COMMENT '文件ID',
+                                 `file_name` VARCHAR(255) NOT NULL COMMENT '文件名',
+                                 `bucket` VARCHAR(100) NOT NULL COMMENT '存储桶',
+                                 `file_path` VARCHAR(500) NOT NULL COMMENT '文件路径',
+                                 `status` VARCHAR(10) DEFAULT '0' COMMENT '任务状态: 0-待处理, 1-处理中, 2-处理成功, 3-处理失败',
+                                 `fail_count` INT DEFAULT 0 COMMENT '失败次数',
+                                 `errormsg` VARCHAR(1000) COMMENT '错误信息',
+                                 `url` VARCHAR(500) COMMENT '处理后文件URL',
+                                 `finish_date` DATETIME COMMENT '完成时间',
+                                 `create_date` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+                                 `process_definition_id` VARCHAR(50) COMMENT '流程定义ID',
+                                 `tag` VARCHAR(50) COMMENT '标签',
+                                 INDEX `idx_status` (`status`),
+                                 INDEX `idx_file_id` (`file_id`),
+                                 INDEX `idx_create_date` (`create_date`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='媒体处理任务表';
+
+-- ------------------------------
+-- 5. 媒体处理历史表
+-- ------------------------------
+CREATE TABLE `media_process_history` (
+                                         `id` BIGINT AUTO_INCREMENT PRIMARY KEY,
+                                         `process_id` BIGINT COMMENT '对应的任务ID',
+                                         `file_id` VARCHAR(32) NOT NULL COMMENT '文件ID',
+                                         `file_name` VARCHAR(255) NOT NULL COMMENT '文件名',
+                                         `bucket` VARCHAR(100) NOT NULL COMMENT '存储桶',
+                                         `file_path` VARCHAR(500) NOT NULL COMMENT '文件路径',
+                                         `status` VARCHAR(10) COMMENT '处理状态',
+                                         `errormsg` VARCHAR(1000) COMMENT '错误信息',
+                                         `url` VARCHAR(500) COMMENT '处理后URL',
+                                         `finish_date` DATETIME COMMENT '完成时间',
+                                         `create_date` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+                                         INDEX `idx_process_id` (`process_id`),
+                                         INDEX `idx_file_id` (`file_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='媒体处理历史表';
+
+-- ------------------------------
+-- 6. 视频文件表(用于存储视频相关信息)
+-- ------------------------------
+CREATE TABLE `media_video` (
+                               `id` BIGINT AUTO_INCREMENT PRIMARY KEY,
+                               `original_name` VARCHAR(255) NOT NULL COMMENT '原始文件名',
+                               `file_name` VARCHAR(255) NOT NULL COMMENT '存储文件名',
+                               `file_url` VARCHAR(500) COMMENT '视频文件URL',
+                               `preview_gif_url` VARCHAR(500) COMMENT '预览GIF URL',
+                               `file_size` BIGINT COMMENT '文件大小',
+                               `duration` VARCHAR(20) COMMENT '视频时长',
+                               `singer` VARCHAR(100) COMMENT '上传歌手',
+                               `bucket_name` VARCHAR(50) COMMENT '存储桶名',
+                               `status` TINYINT DEFAULT 0 COMMENT '状态:0-待处理,1-处理中,2-已完成,3-处理失败',
+                               `process_progress` DECIMAL(5,2) DEFAULT 0.00 COMMENT '处理进度(%)',
+                               `retry_count` TINYINT DEFAULT 0 COMMENT '重试次数',
+                               `created_time` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+                               `updated_time` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+                               `processed_time` TIMESTAMP NULL COMMENT '处理完成时间',
+                               INDEX `idx_status` (`status`),
+                               INDEX `idx_created_time` (`created_time`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='视频文件表';
+
+-- ------------------------------
+-- 7. 视频处理队列表
+-- ------------------------------
+CREATE TABLE `video_process_queue` (
+                                       `id` BIGINT AUTO_INCREMENT PRIMARY KEY,
+                                       `video_id` BIGINT NOT NULL COMMENT '视频ID',
+                                       `priority` TINYINT DEFAULT 1 COMMENT '优先级:1-普通,2-高',
+                                       `status` TINYINT DEFAULT 0 COMMENT '0-待处理,1-已调度,2-已完成',
+                                       `scheduled_time` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '调度时间',
+                                       INDEX `idx_status_priority` (`status`, `priority`, `scheduled_time`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='视频处理队列表';
+
+-- ------------------------------
+-- 8. 系统配置表
+-- ------------------------------
+CREATE TABLE `sys_config` (
+                              `id` BIGINT AUTO_INCREMENT PRIMARY KEY,
+                              `config_key` VARCHAR(100) NOT NULL UNIQUE COMMENT '配置键',
+                              `config_value` TEXT COMMENT '配置值',
+                              `description` VARCHAR(255) COMMENT '配置描述',
+                              `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+                              `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+                              INDEX `idx_config_key` (`config_key`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统配置表';
+
+-- ------------------------------
+-- 9. 初始化系统配置
+-- ------------------------------
+INSERT INTO `sys_config` (`config_key`, `config_value`, `description`) VALUES
+                                                                           ('ffmpeg.path', '/usr/local/bin/ffmpeg', 'FFmpeg可执行文件路径'),
+                                                                           ('video.max_size', '104857600', '视频最大上传大小(字节),100MB'),
+                                                                           ('chunk.size', '2097152', '分块大小(字节),2MB'),
+                                                                           ('max.concurrent.tasks', '5', '最大并发处理任务数'),
+                                                                           ('max.retry.count', '3', '最大重试次数'),
+                                                                           ('temp.dir', '/tmp/media_temp', '临时文件目录');

+ 5 - 0
media/pom.xml

@@ -57,6 +57,11 @@
             <artifactId>okhttp</artifactId>
             <version>4.8.1</version>
         </dependency>
+<!--        swagger         -->
+        <dependency>
+            <groupId>com.spring4all</groupId>
+            <artifactId>swagger-spring-boot-starter</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-validation</artifactId>

+ 174 - 14
media/src/main/java/com/media/controller/FileUploadController.java

@@ -1,54 +1,214 @@
 package com.media.controller;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.base.utils.Result;
+import com.media.domain.dto.MergeChunkDTO;
+import com.media.domain.po.MediaFile;
+import com.media.domain.vo.UploadStatusVO;
 import com.media.service.FileUploadService;
 import com.media.service.IMediaFileService;
-import com.media.util.upload.MinioFileUploader;
-import com.media.util.Vo.FileUploadVO;
+import com.media.service.impl.ChunkUploadService;
 import com.media.util.enums.StorageBucket;
+import com.media.util.upload.MinioFileUploader;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 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.io.InputStream;
-import java.security.MessageDigest;
-
+/**
+ * 媒体文件上传控制器
+ * 提供文件上传、分块上传、状态查询等接口
+ */
 @RestController
 @RequestMapping("/media")
 @CrossOrigin(origins = "*")
+@Slf4j
 public class FileUploadController {
+
     @Autowired
     private FileUploadService fileUploadService;
 
+    @Autowired
+    private IMediaFileService mediaFileService;
+
+    @Autowired
+    private ChunkUploadService chunkUploadService;
+
+    @Autowired
+    private MinioFileUploader minioFileUploader;
 
     /**
-     * 文件上传接口(适用于3M以内文件)
+     * 普通文件上传接口(适用于3M以内文件)
      *
-     * @param file       上传的文件
-     * @param bucket     存储桶名称
+     * @param file 上传的文件
+     * @param bucket 存储桶名称
      * @param objectName 对象名称(可选)
+     * @param md5 文件MD5值(可选,用于校验)
      * @return 上传结果
      */
     @PostMapping("/upload")
-    public Result uploadFile(
+    public Result<String> uploadFile(
             @RequestParam("file") MultipartFile file,
             @RequestParam("bucket") StorageBucket bucket,
             @RequestParam(value = "objectName", required = false) String objectName,
-            @RequestParam(value = "md5", required = false) String md5) throws Exception {
-        String s = fileUploadService.uploadFile(file, bucket, objectName, md5);
-        return Result.success(s);
+            @RequestParam(value = "md5", required = false) String md5) {
+
+        try {
+            String fileUrl = fileUploadService.uploadFile(file, bucket, objectName, md5);
+            return Result.success(fileUrl);
+        } catch (Exception e) {
+            log.error("文件上传失败", e);
+            return Result.fail("文件上传失败: " + e.getMessage());
+        }
     }
 
+    /**
+     * 分块上传接口 - 上传单个分块
+     *
+     * @param chunk 分块文件
+     * @param fileMd5 文件MD5
+     * @param chunkIndex 分块索引
+     * @param totalChunks 总分块数
+     * @param fileName 原始文件名
+     * @return 上传结果
+     */
+    @PostMapping("/chunk/upload")
+    public Result<String> uploadChunk(
+            @RequestParam("chunk") MultipartFile chunk,
+            @RequestParam("fileMd5") String fileMd5,
+            @RequestParam("chunkIndex") int chunkIndex,
+            @RequestParam("totalChunks") int totalChunks,
+            @RequestParam("fileName") String fileName) {
+
+        try {
+            String chunkUrl = chunkUploadService.uploadChunk(
+                    fileMd5, fileName, chunk, chunkIndex, totalChunks);
+            return Result.success(chunkUrl);
+        } catch (Exception e) {
+            log.error("分块上传失败", e);
+            return Result.fail("分块上传失败: " + e.getMessage());
+        }
+    }
 
+    /**
+     * 分块上传合并接口
+     *
+     * @param mergeDTO 合并参数
+     * @return 合并结果
+     */
+    @PostMapping("/chunk/merge")
+    public Result<String> mergeChunks(@RequestBody MergeChunkDTO mergeDTO) {
+        try {
+            String finalUrl = chunkUploadService.mergeChunks(
+                    mergeDTO.getFileMd5(),
+                    mergeDTO.getFileName(),
+                    mergeDTO.getBucket()
+            );
+            return Result.success(finalUrl);
+        } catch (Exception e) {
+            log.error("分块合并失败", e);
+            return Result.fail("分块合并失败: " + e.getMessage());
+        }
+    }
+
+    /**
+     * 查询分块上传状态
+     *
+     * @param fileMd5 文件MD5
+     * @return 上传状态信息
+     */
+    @GetMapping("/chunk/status")
+    public Result<UploadStatusVO> getUploadStatus(@RequestParam String fileMd5) {
+        try {
+            UploadStatusVO status = chunkUploadService.getUploadStatus(fileMd5);
+            return Result.success(status);
+        } catch (Exception e) {
+            log.error("查询上传状态失败", e);
+            return Result.fail("查询状态失败: " + e.getMessage());
+        }
+    }
 
     /**
      * 获取支持的存储桶列表
+     *
+     * @return 存储桶列表
      */
     @GetMapping("/buckets")
     public ResponseEntity<Result<StorageBucket[]>> getSupportedBuckets() {
         return ResponseEntity.ok(Result.success(StorageBucket.values()));
     }
+
+    /**
+     * 查询媒体文件列表
+     *
+     * @param current 页码
+     * @param size 页大小
+     * @param fileType 文件类型
+     * @return 文件列表
+     */
+    @GetMapping("/files")
+    public Result<IPage<MediaFile>> getFileList(
+            @RequestParam(defaultValue = "1") Long current,
+            @RequestParam(defaultValue = "10") Long size,
+            @RequestParam(required = false) String fileType) {
+
+        IPage<MediaFile> page = new Page<>(current, size);
+        LambdaQueryWrapper<MediaFile> queryWrapper = new LambdaQueryWrapper<>();
+
+        if (StringUtils.isNotBlank(fileType)) {
+            queryWrapper.eq(MediaFile::getFileType, fileType);
+        }
+
+        queryWrapper.eq(MediaFile::getStatus, 0) // 只查询正常状态的文件
+                .orderByDesc(MediaFile::getCreateTime);
+
+        IPage<MediaFile> result = mediaFileService.page(page, queryWrapper);
+        return Result.success(result);
+    }
+
+    /**
+     * 根据ID查询文件信息
+     *
+     * @param id 文件ID
+     * @return 文件信息
+     */
+    @GetMapping("/files/{id}")
+    public Result<MediaFile> getFileById(@PathVariable Long id) {
+        MediaFile file = mediaFileService.getById(id);
+        if (file == null) {
+            return Result.fail("文件不存在");
+        }
+        return Result.success(file);
+    }
+
+    /**
+     * 删除文件(逻辑删除)
+     *
+     * @param id 文件ID
+     * @return 删除结果
+     */
+    @DeleteMapping("/files/{id}")
+    public Result<String> deleteFile(@PathVariable Long id) {
+        try {
+            MediaFile file = mediaFileService.getById(id);
+            if (file == null) {
+                return Result.fail("文件不存在");
+            }
+
+            // 逻辑删除
+            MediaFile updateFile = new MediaFile();
+            updateFile.setId(id);
+            updateFile.setStatus(1); // 已删除状态
+            mediaFileService.updateById(updateFile);
+
+            return Result.success("删除成功");
+        } catch (Exception e) {
+            log.error("删除文件失败", e);
+            return Result.fail("删除失败: " + e.getMessage());
+        }
+    }
 }

+ 14 - 0
media/src/main/java/com/media/domain/dto/MergeChunkDTO.java

@@ -0,0 +1,14 @@
+package com.media.domain.dto;
+
+import com.media.util.enums.StorageBucket;
+import lombok.Data;
+
+/**
+ * 分块合并参数DTO
+ */
+@Data
+public class MergeChunkDTO {
+    private String fileMd5;     // 文件MD5
+    private String fileName;    // 原始文件名
+    private StorageBucket bucket; // 存储桶
+}

+ 30 - 0
media/src/main/java/com/media/domain/po/ChunkInfo.java

@@ -0,0 +1,30 @@
+package com.media.domain.po;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * 分块信息实体类
+ */
+@Data
+@TableName("chunk_info")
+public class ChunkInfo implements Serializable {
+    private static final long serialVersionUID = 1L;
+    
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    
+    private String fileMd5;             // 文件MD5
+    private String fileName;            // 原始文件名
+    private Integer chunkIndex;         // 分块索引
+    private Integer totalChunks;        // 总分块数
+    private String chunkUrl;            // 分块文件URL
+    private Integer status;             // 状态:0-待上传,1-已上传
+    private LocalDateTime uploadedTime; // 上传时间
+    private LocalDateTime createTime;   // 创建时间
+}

+ 17 - 0
media/src/main/java/com/media/domain/vo/UploadStatusVO.java

@@ -0,0 +1,17 @@
+package com.media.domain.vo;
+
+import lombok.Data;
+
+/**
+ * 上传状态返回VO
+ */
+@Data
+public class UploadStatusVO {
+    private String fileMd5;         // 文件MD5
+    private String fileName;        // 文件名
+    private Integer totalChunks;    // 总分块数
+    private Integer uploadedChunks; // 已上传分块数
+    private String status;          // 状态:uploading, merged, failed
+    private String progress;        // 进度百分比
+    private String message;         // 状态消息
+}

+ 282 - 0
media/src/main/java/com/media/service/impl/ChunkUploadService.java

@@ -0,0 +1,282 @@
+package com.media.service.impl;
+import com.media.domain.po.ChunkInfo;
+import com.media.domain.po.MediaFile;
+import com.media.domain.vo.UploadStatusVO;
+import com.media.service.IChunkInfoService;
+import com.media.service.IMediaFileService;
+import com.media.util.enums.StorageBucket;
+import com.media.util.upload.MinioFileUploader;
+import io.minio.ComposeObjectArgs;
+import io.minio.ComposeSource;
+import io.minio.RemoveObjectArgs;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * 分块上传服务实现
+ */
+@Service
+@Slf4j
+public class ChunkUploadService {
+    
+    @Autowired
+    private MinioFileUploader minioFileUploader;
+    
+    @Autowired
+    private IChunkInfoService chunkInfoService;
+    
+    @Autowired
+    private IMediaFileService mediaFileService;
+    
+    private static final String TEMP_CHUNK_DIR = "temp_chunks/";
+    
+    /**
+     * 上传单个分块
+     */
+    public String uploadChunk(String fileMd5, String fileName,
+                              MultipartFile chunk, int chunkIndex, int totalChunks) {
+        try {
+            // 验证分块索引
+            if (chunkIndex >= totalChunks) {
+                throw new RuntimeException("分块索引超出范围");
+            }
+            
+            // 上传分块到MinIO临时目录
+            String chunkObjectName = TEMP_CHUNK_DIR + fileMd5 + "/" + chunkIndex;
+            String chunkUrl = minioFileUploader.uploadFile(
+                StorageBucket.VIDEO_FILES, // 或其他合适的存储桶
+                chunkObjectName,
+                chunk.getInputStream(),
+                chunk.getContentType()
+            );
+            
+            // 记录分块信息到数据库
+            ChunkInfo chunkInfo = new ChunkInfo();
+            chunkInfo.setFileMd5(fileMd5);
+            chunkInfo.setFileName(fileName);
+            chunkInfo.setChunkIndex(chunkIndex);
+            chunkInfo.setTotalChunks(totalChunks);
+            chunkInfo.setChunkUrl(chunkUrl);
+            chunkInfo.setStatus(1); // 已上传
+            chunkInfo.setUploadedTime(LocalDateTime.now());
+            chunkInfoService.save(chunkInfo);
+            
+            log.info("分块上传成功: fileMd5={}, chunkIndex={}", fileMd5, chunkIndex);
+            return chunkUrl;
+            
+        } catch (Exception e) {
+            log.error("分块上传失败: fileMd5={}, chunkIndex={}", fileMd5, chunkIndex, e);
+            throw new RuntimeException("分块上传失败: " + e.getMessage());
+        }
+    }
+    
+    /**
+     * 合并分块
+     */
+    @Transactional
+    public String mergeChunks(String fileMd5, String fileName, StorageBucket bucket) {
+        try {
+            log.info("开始合并分块: fileMd5={}", fileMd5);
+            
+            // 查询所有分块信息
+            List<ChunkInfo> chunks = chunkInfoService.lambdaQuery()
+                .eq(ChunkInfo::getFileMd5, fileMd5)
+                .orderByAsc(ChunkInfo::getChunkIndex)
+                .list();
+            
+            if (chunks.isEmpty()) {
+                throw new RuntimeException("未找到分块信息");
+            }
+            
+            // 验证分块完整性
+            int expectedChunks = chunks.get(0).getTotalChunks();
+            Set<Integer> uploadedIndices = chunks.stream()
+                .map(ChunkInfo::getChunkIndex)
+                .collect(Collectors.toSet());
+            
+            for (int i = 0; i < expectedChunks; i++) {
+                if (!uploadedIndices.contains(i)) {
+                    throw new RuntimeException("分块不完整,缺少第" + i + "块");
+                }
+            }
+            
+            // 构建合并源
+            List<ComposeSource> sources = new ArrayList<>();
+            for (ChunkInfo chunk : chunks) {
+                String objectName = extractObjectNameFromUrl(chunk.getChunkUrl());
+                sources.add(ComposeSource.builder()
+                    .bucket(extractBucketName(chunk.getChunkUrl()))
+                    .object(objectName)
+                    .build());
+            }
+            
+            // 合并文件
+            String finalObjectName = "files/" + fileMd5 + "_" + System.currentTimeMillis() + "_" + fileName;
+            minioClient.composeObject(ComposeObjectArgs.builder()
+                .bucket(bucket.getBucketName())
+                .object(finalObjectName)
+                .sources(sources)
+                .build());
+            
+            // 生成最终文件URL
+            String finalUrl = minioFileUploader.generateFileUrl(bucket, finalObjectName);
+            
+            // 保存到媒体文件表
+            MediaFile mediaFile = new MediaFile();
+            mediaFile.setOriginalName(fileName);
+            mediaFile.setFileName(finalObjectName);
+            mediaFile.setFileType(getFileTypeFromName(fileName));
+            mediaFile.setFileSize(calculateTotalSize(chunks));
+            mediaFile.setBucketName(bucket.getBucketName());
+            mediaFile.setFileUrl(finalUrl);
+            mediaFile.setStatus(0); // 正常状态
+            mediaFile.setStorageType("minio");
+            mediaFile.setMd5(fileMd5);
+            mediaFile.setCreateTime(LocalDateTime.now());
+            mediaFile.setUpdateTime(LocalDateTime.now());
+            mediaFileService.save(mediaFile);
+            
+            // 删除临时分块文件
+            deleteTempChunks(fileMd5);
+            
+            // 删除分块记录
+            chunkInfoService.lambdaQuery()
+                .eq(ChunkInfo::getFileMd5, fileMd5)
+                .remove();
+            
+            log.info("分块合并完成: fileMd5={}, finalUrl={}", fileMd5, finalUrl);
+            return finalUrl;
+            
+        } catch (Exception e) {
+            log.error("分块合并失败: fileMd5={}", fileMd5, e);
+            // 清理临时文件
+            deleteTempChunks(fileMd5);
+            throw new RuntimeException("分块合并失败: " + e.getMessage());
+        }
+    }
+    
+    /**
+     * 查询上传状态
+     */
+    public UploadStatusVO getUploadStatus(String fileMd5) {
+        List<ChunkInfo> chunks = chunkInfoService.lambdaQuery()
+            .eq(ChunkInfo::getFileMd5, fileMd5)
+            .list();
+        
+        UploadStatusVO status = new UploadStatusVO();
+        status.setFileMd5(fileMd5);
+        
+        if (chunks.isEmpty()) {
+            status.setStatus("not_found");
+            status.setMessage("未找到上传记录");
+            return status;
+        }
+        
+        ChunkInfo firstChunk = chunks.get(0);
+        int totalChunks = firstChunk.getTotalChunks();
+        int uploadedChunks = chunks.size();
+        
+        status.setFileName(firstChunk.getFileName());
+        status.setTotalChunks(totalChunks);
+        status.setUploadedChunks(uploadedChunks);
+        
+        if (uploadedChunks == totalChunks) {
+            status.setStatus("merged");
+            status.setProgress("100%");
+            status.setMessage("上传完成");
+        } else {
+            status.setStatus("uploading");
+            String progress = String.format("%.2f", (uploadedChunks * 100.0 / totalChunks));
+            status.setProgress(progress + "%");
+            status.setMessage("上传中: " + uploadedChunks + "/" + totalChunks);
+        }
+        
+        return status;
+    }
+    
+    /**
+     * 提取对象名称
+     */
+    private String extractObjectNameFromUrl(String url) {
+        // 从URL中提取对象名称部分
+        int lastSlash = url.lastIndexOf('/');
+        return lastSlash > 0 ? url.substring(lastSlash + 1) : url;
+    }
+    
+    /**
+     * 提取存储桶名称
+     */
+    private String extractBucketName(String url) {
+        // 从URL中提取存储桶名称
+        String[] parts = url.split("/");
+        return parts.length > 3 ? parts[3] : "default";
+    }
+    
+    /**
+     * 根据文件名获取文件类型
+     */
+    private String getFileTypeFromName(String fileName) {
+        String ext = getFileExtension(fileName).toLowerCase();
+        if (Arrays.asList("jpg", "jpeg", "png", "gif", "bmp").contains(ext)) {
+            return "image";
+        } else if (Arrays.asList("mp3", "wav", "flac", "aac").contains(ext)) {
+            return "audio";
+        } else if (Arrays.asList("mp4", "avi", "mov", "mkv", "flv").contains(ext)) {
+            return "video";
+        } else {
+            return "other";
+        }
+    }
+    
+    /**
+     * 获取文件扩展名
+     */
+    private String getFileExtension(String fileName) {
+        int dotIndex = fileName.lastIndexOf('.');
+        return dotIndex > 0 ? fileName.substring(dotIndex + 1) : "";
+    }
+    
+    /**
+     * 计算总文件大小
+     */
+    private Long calculateTotalSize(List<ChunkInfo> chunks) {
+        return chunks.stream()
+            .mapToLong(chunk -> {
+                // 这里需要根据实际存储的大小信息计算
+                return 0L; // 需要从MinIO获取实际大小
+            })
+            .sum();
+    }
+    
+    /**
+     * 删除临时分块文件
+     */
+    private void deleteTempChunks(String fileMd5) {
+        try {
+            List<ChunkInfo> chunks = chunkInfoService.lambdaQuery()
+                .eq(ChunkInfo::getFileMd5, fileMd5)
+                .list();
+            
+            for (ChunkInfo chunk : chunks) {
+                String objectName = extractObjectNameFromUrl(chunk.getChunkUrl());
+                String bucketName = extractBucketName(chunk.getChunkUrl());
+                
+                minioClient.removeObject(RemoveObjectArgs.builder()
+                    .bucket(bucketName)
+                    .object(objectName)
+                    .build());
+            }
+        } catch (Exception e) {
+            log.error("删除临时分块文件失败", e);
+        }
+    }
+}

+ 1 - 0
media/src/main/java/com/media/util/enums/StorageBucket.java

@@ -4,6 +4,7 @@ public enum StorageBucket {
     ARTIST_COVERS("artist-covers"),//    ARTIST_COVERS: 艺人封面存储桶
     USER_AVATARS("user-avatars"),//    USER_AVATARS: 用户头像存储桶
     VIDEO_HOME("video-home"),//    VIDEO_HOME: 视频首页存储桶
+    VIDEO_FILES("video-files"),//    VIDEO_FILES: 视频文件存储桶
     ALBUM_HOME("album-home"),//    ALBUM_HOME: 专辑首页存储桶
     BANNER_HOME("banner-home"),//    BANNER_HOME: 轮播图首页存储桶
     ALBUM_SHOP("album-shop"),//    ALBUM_SHOP: 专辑商城存储桶

+ 0 - 1
media/src/main/java/com/media/util/upload/MinioFileUploader.java

@@ -51,7 +51,6 @@ private void checkAndCreateBucket(String bucketName) {
                     .bucket(bucketName)
                     .build()
             );
-
             // 设置存储桶策略为公开读取
             setBucketPolicy(bucketName);
         }