From b275ffab5a9d8721a5c6be2f5e92170693c23803 Mon Sep 17 00:00:00 2001
From: ikmkj <1@qq,com>
Date: Sat, 26 Apr 2025 19:32:45 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E5=88=9D=E5=A7=8B=E5=8C=96=E9=9F=B3?=
=?UTF-8?q?=E4=B9=90=E9=A1=B9=E7=9B=AE=E5=90=8E=E5=8F=B0=E7=AE=A1=E7=90=86?=
=?UTF-8?q?=E7=B3=BB=E7=BB=9F-=20=E6=96=B0=E5=A2=9E=E5=90=8E=E5=8F=B0?=
=?UTF-8?q?=E7=AE=A1=E7=90=86=E7=9B=B8=E5=85=B3=E9=A1=B5=E9=9D=A2=E5=92=8C?=
=?UTF-8?q?=E5=8A=9F=E8=83=BD=E7=BB=84=E4=BB=B6=20-=20=E5=AE=9E=E7=8E=B0?=
=?UTF-8?q?=E7=AE=A1=E7=90=86=E5=91=98=E8=AF=84=E8=AE=BA=E7=AE=A1=E7=90=86?=
=?UTF-8?q?=E3=80=81=E6=95=B0=E6=8D=AE=E7=BB=9F=E8=AE=A1=E7=AD=89=E5=8A=9F?=
=?UTF-8?q?=E8=83=BD=20-=20=E6=B7=BB=E5=8A=A0=E5=90=8E=E5=8F=B0=E5=B8=83?=
=?UTF-8?q?=E5=B1=80=E5=92=8C=E8=B7=AF=E7=94=B1=E7=AE=A1=E7=90=86=20-?=
=?UTF-8?q?=E9=85=8D=E7=BD=AE=E6=95=B0=E6=8D=AE=E5=BA=93=E5=92=8CRedis?=
=?UTF-8?q?=E8=BF=9E=E6=8E=A5=20-=20=E5=AE=9E=E7=8E=B0=E6=96=87=E4=BB=B6?=
=?UTF-8?q?=E4=B8=8A=E4=BC=A0=E5=92=8C=E8=AE=BF=E9=97=AE=E8=B7=AF=E5=BE=84?=
=?UTF-8?q?=E9=85=8D=E7=BD=AE=20-=20=E6=B7=BB=E5=8A=A0Sa-Token=E5=AE=89?=
=?UTF-8?q?=E5=85=A8=E9=85=8D=E7=BD=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.gitignore | 79 +
README.md | 219 ++
doc/音乐下载.txt | 2 +
music-houduan/.gitattributes | 64 +
music-houduan/.gitignore | 39 +
music-houduan/pom.xml | 145 ++
.../musichouduan/MusicHouduanApplication.java | 21 +
.../test/musichouduan/config/CorsConfig.java | 33 +
.../musichouduan/config/Knife4jConfig.java | 24 +
.../test/musichouduan/config/RedisConfig.java | 34 +
.../musichouduan/config/SaTokenConfig.java | 55 +
.../musichouduan/config/StpInterfaceImpl.java | 55 +
.../musichouduan/config/SwaggerConfig.java | 119 +
.../test/musichouduan/config/WebConfig.java | 25 +
.../musichouduan/config/WebMvcConfig.java | 28 +
.../musichouduan/config/WebSocketConfig.java | 33 +
.../controller/BannerController.java | 153 ++
.../controller/BasicTestController.java | 29 +
.../controller/CommentController.java | 97 +
.../controller/FallbackController.java | 36 +
.../controller/FileController.java | 71 +
.../controller/HelloController.java | 42 +
.../controller/MusicController.java | 216 ++
.../controller/PlaylistController.java | 256 ++
.../controller/SingerController.java | 215 ++
.../controller/StatController.java | 94 +
.../controller/TypeController.java | 227 ++
.../controller/UserController.java | 227 ++
.../admin/AdminCommentController.java | 76 +
.../admin/AdminDashboardController.java | 240 ++
.../com/test/musichouduan/dto/BannerDTO.java | 57 +
.../com/test/musichouduan/dto/CommentDTO.java | 53 +
.../test/musichouduan/dto/LoginRequest.java | 23 +
.../test/musichouduan/dto/LoginResultDTO.java | 30 +
.../com/test/musichouduan/dto/MusicDTO.java | 110 +
.../test/musichouduan/dto/MusicTypeDTO.java | 25 +
.../com/test/musichouduan/dto/PageResult.java | 55 +
.../dto/PasswordUpdateRequest.java | 31 +
.../test/musichouduan/dto/PlaylistDTO.java | 73 +
.../musichouduan/dto/PlaylistTypeDTO.java | 25 +
.../musichouduan/dto/RegisterRequest.java | 45 +
.../com/test/musichouduan/dto/Result.java | 84 +
.../com/test/musichouduan/dto/SingerDTO.java | 63 +
.../test/musichouduan/dto/SingerTypeDTO.java | 25 +
.../com/test/musichouduan/dto/UserDTO.java | 87 +
.../musichouduan/dto/UserUpdateRequest.java | 46 +
.../dto/admin/DashboardDataDTO.java | 63 +
.../musichouduan/dto/admin/MusicAdminDTO.java | 69 +
.../musichouduan/dto/admin/StatItemDTO.java | 26 +
.../musichouduan/dto/admin/UserAdminDTO.java | 88 +
.../com/test/musichouduan/entity/Banner.java | 77 +
.../com/test/musichouduan/entity/Comment.java | 72 +
.../com/test/musichouduan/entity/Music.java | 97 +
.../test/musichouduan/entity/MusicType.java | 47 +
.../test/musichouduan/entity/PlayHistory.java | 41 +
.../test/musichouduan/entity/Playlist.java | 92 +
.../musichouduan/entity/PlaylistType.java | 47 +
.../com/test/musichouduan/entity/Singer.java | 75 +
.../test/musichouduan/entity/SingerType.java | 47 +
.../com/test/musichouduan/entity/User.java | 95 +
.../musichouduan/entity/UserCollectMusic.java | 41 +
.../entity/UserCollectPlaylist.java | 41 +
.../entity/UserCollectSinger.java | 41 +
.../test/musichouduan/entity/UserMusic.java | 44 +
.../musichouduan/entity/UserPlaylist.java | 44 +
.../test/musichouduan/entity/UserSinger.java | 44 +
.../exception/BusinessException.java | 59 +
.../exception/GlobalExceptionHandler.java | 132 ++
.../musichouduan/init/DataInitializer.java | 109 +
.../repository/BannerRepository.java | 22 +
.../repository/CommentRepository.java | 54 +
.../repository/MusicRepository.java | 116 +
.../repository/MusicTypeRepository.java | 31 +
.../repository/PlayHistoryRepository.java | 79 +
.../repository/PlaylistRepository.java | 100 +
.../repository/PlaylistTypeRepository.java | 31 +
.../repository/SingerRepository.java | 83 +
.../repository/SingerTypeRepository.java | 31 +
.../UserCollectMusicRepository.java | 69 +
.../UserCollectPlaylistRepository.java | 69 +
.../UserCollectSingerRepository.java | 69 +
.../repository/UserMusicRepository.java | 69 +
.../repository/UserPlaylistRepository.java | 69 +
.../repository/UserRepository.java | 71 +
.../repository/UserSingerRepository.java | 69 +
.../musichouduan/service/BannerService.java | 82 +
.../musichouduan/service/CommentService.java | 84 +
.../musichouduan/service/FileService.java | 41 +
.../musichouduan/service/MusicService.java | 124 +
.../musichouduan/service/PlaylistService.java | 153 ++
.../musichouduan/service/SingerService.java | 125 +
.../musichouduan/service/StatService.java | 55 +
.../musichouduan/service/TypeService.java | 140 ++
.../musichouduan/service/UserService.java | 117 +
.../service/impl/BannerServiceImpl.java | 186 ++
.../service/impl/CommentServiceImpl.java | 268 +++
.../service/impl/FileServiceImpl.java | 168 ++
.../service/impl/MusicServiceImpl.java | 504 ++++
.../service/impl/PlaylistServiceImpl.java | 479 ++++
.../service/impl/SingerServiceImpl.java | 389 +++
.../service/impl/StatServiceImpl.java | 175 ++
.../service/impl/TypeServiceImpl.java | 395 ++++
.../service/impl/UserServiceImpl.java | 355 +++
.../util/SwaggerAnnotationGenerator.java | 57 +
.../src/main/resources/application.properties | 25 +
.../src/main/resources/application.yml | 141 ++
.../362d1d68-fcc2-4a74-a0f1-44bd38e9cb6d.jpg | Bin 0 -> 1001210 bytes
.../3efa486a-610d-4745-a54c-61f55ab3f1d5.jpg | Bin 0 -> 62169 bytes
.../569f8ce5-09d2-4151-a6b1-f56a4d0b2c84.png | Bin 0 -> 1104033 bytes
.../68fa60bd-710e-443d-95f7-cb117a1a3b73.jpg | Bin 0 -> 113691 bytes
.../6c8c8d04-e583-4f12-8c56-d618b2bb06f4.jpg | Bin 0 -> 7062 bytes
.../7886a646-721a-4999-bb0c-0404768fe744.jpg | Bin 0 -> 62169 bytes
.../69c2c485-080f-4dd7-a541-c961652a2b8e.mp3 | Bin 0 -> 3796450 bytes
music-qianduan/.gitignore | 80 +
music-qianduan/index.html | 13 +
music-qianduan/package-lock.json | 2075 +++++++++++++++++
music-qianduan/package.json | 26 +
music-qianduan/public/vite.svg | 1 +
music-qianduan/src/App.vue | 66 +
music-qianduan/src/api/admin/comment.js | 43 +
music-qianduan/src/api/admin/dashboard.js | 9 +
music-qianduan/src/api/admin/type.js | 106 +
music-qianduan/src/api/admin/user.js | 69 +
music-qianduan/src/api/banner.js | 162 ++
music-qianduan/src/api/comment.js | 57 +
music-qianduan/src/api/index.js | 123 +
music-qianduan/src/api/music.js | 242 ++
music-qianduan/src/api/musicType.js | 63 +
music-qianduan/src/api/playlist.js | 362 +++
music-qianduan/src/api/playlistType.js | 63 +
music-qianduan/src/api/singer.js | 244 ++
music-qianduan/src/api/singerType.js | 63 +
music-qianduan/src/api/user.js | 121 +
music-qianduan/src/assets/css/global.css | 76 +
music-qianduan/src/assets/vue.svg | 1 +
music-qianduan/src/components/HelloWorld.vue | 43 +
music-qianduan/src/components/HomeBanner.vue | 122 +
.../src/components/ImagePreview.vue | 98 +
music-qianduan/src/components/MusicList.vue | 384 +++
music-qianduan/src/components/MusicPlayer.vue | 1195 ++++++++++
music-qianduan/src/layouts/AdminLayout.vue | 336 +++
music-qianduan/src/layouts/MainLayout.vue | 384 +++
music-qianduan/src/main.js | 27 +
music-qianduan/src/router/index.js | 312 +++
music-qianduan/src/stores/index.js | 5 +
music-qianduan/src/stores/player.js | 285 +++
music-qianduan/src/stores/user.js | 145 ++
music-qianduan/src/style.css | 84 +
music-qianduan/src/utils/clearStorage.js | 12 +
music-qianduan/src/utils/imageUtils.js | 42 +
music-qianduan/src/utils/websocket.js | 95 +
music-qianduan/src/views/About.vue | 80 +
music-qianduan/src/views/Home.vue | 502 ++++
music-qianduan/src/views/ImageTest.vue | 212 ++
music-qianduan/src/views/Login.vue | 227 ++
music-qianduan/src/views/Music.vue | 336 +++
music-qianduan/src/views/MusicDetail.vue | 448 ++++
music-qianduan/src/views/NotFound.vue | 32 +
music-qianduan/src/views/Playlist.vue | 547 +++++
music-qianduan/src/views/PlaylistDetail.vue | 659 ++++++
music-qianduan/src/views/Register.vue | 207 ++
music-qianduan/src/views/Search.vue | 692 ++++++
music-qianduan/src/views/Singer.vue | 499 ++++
music-qianduan/src/views/SingerDetail.vue | 576 +++++
music-qianduan/src/views/UserCenter.vue | 493 ++++
music-qianduan/src/views/admin/Banner.vue | 414 ++++
.../src/views/admin/BannerManagement.vue | 673 ++++++
.../src/views/admin/CommentManagement.vue | 440 ++++
music-qianduan/src/views/admin/Dashboard.vue | 707 ++++++
music-qianduan/src/views/admin/Index.vue | 257 ++
music-qianduan/src/views/admin/Music.vue | 788 +++++++
music-qianduan/src/views/admin/Playlist.vue | 1064 +++++++++
.../src/views/admin/PlaylistType.vue | 333 +++
music-qianduan/src/views/admin/Singer.vue | 852 +++++++
music-qianduan/src/views/admin/Type.vue | 357 +++
.../src/views/admin/TypeManagement.vue | 780 +++++++
music-qianduan/src/views/admin/User.vue | 294 +++
.../src/views/admin/UserManagement.vue | 513 ++++
.../src/views/user/CollectMusic.vue | 226 ++
.../src/views/user/CollectPlaylist.vue | 271 +++
.../src/views/user/CollectSinger.vue | 243 ++
music-qianduan/src/views/user/Password.vue | 199 ++
music-qianduan/src/views/user/Playlist.vue | 562 +++++
music-qianduan/vite.config.js | 37 +
sql/music.sql | 237 ++
185 files changed, 32763 insertions(+)
create mode 100644 .gitignore
create mode 100644 README.md
create mode 100644 doc/音乐下载.txt
create mode 100644 music-houduan/.gitattributes
create mode 100644 music-houduan/.gitignore
create mode 100644 music-houduan/pom.xml
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/MusicHouduanApplication.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/config/CorsConfig.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/config/Knife4jConfig.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/config/RedisConfig.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/config/SaTokenConfig.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/config/StpInterfaceImpl.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/config/SwaggerConfig.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/config/WebConfig.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/config/WebMvcConfig.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/config/WebSocketConfig.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/controller/BannerController.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/controller/BasicTestController.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/controller/CommentController.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/controller/FallbackController.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/controller/FileController.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/controller/HelloController.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/controller/MusicController.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/controller/PlaylistController.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/controller/SingerController.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/controller/StatController.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/controller/TypeController.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/controller/UserController.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/controller/admin/AdminCommentController.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/controller/admin/AdminDashboardController.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/dto/BannerDTO.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/dto/CommentDTO.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/dto/LoginRequest.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/dto/LoginResultDTO.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/dto/MusicDTO.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/dto/MusicTypeDTO.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/dto/PageResult.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/dto/PasswordUpdateRequest.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/dto/PlaylistDTO.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/dto/PlaylistTypeDTO.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/dto/RegisterRequest.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/dto/Result.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/dto/SingerDTO.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/dto/SingerTypeDTO.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/dto/UserDTO.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/dto/UserUpdateRequest.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/dto/admin/DashboardDataDTO.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/dto/admin/MusicAdminDTO.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/dto/admin/StatItemDTO.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/dto/admin/UserAdminDTO.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/entity/Banner.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/entity/Comment.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/entity/Music.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/entity/MusicType.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/entity/PlayHistory.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/entity/Playlist.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/entity/PlaylistType.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/entity/Singer.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/entity/SingerType.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/entity/User.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/entity/UserCollectMusic.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/entity/UserCollectPlaylist.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/entity/UserCollectSinger.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/entity/UserMusic.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/entity/UserPlaylist.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/entity/UserSinger.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/exception/BusinessException.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/exception/GlobalExceptionHandler.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/init/DataInitializer.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/repository/BannerRepository.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/repository/CommentRepository.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/repository/MusicRepository.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/repository/MusicTypeRepository.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/repository/PlayHistoryRepository.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/repository/PlaylistRepository.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/repository/PlaylistTypeRepository.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/repository/SingerRepository.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/repository/SingerTypeRepository.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/repository/UserCollectMusicRepository.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/repository/UserCollectPlaylistRepository.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/repository/UserCollectSingerRepository.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/repository/UserMusicRepository.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/repository/UserPlaylistRepository.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/repository/UserRepository.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/repository/UserSingerRepository.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/service/BannerService.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/service/CommentService.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/service/FileService.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/service/MusicService.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/service/PlaylistService.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/service/SingerService.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/service/StatService.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/service/TypeService.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/service/UserService.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/service/impl/BannerServiceImpl.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/service/impl/CommentServiceImpl.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/service/impl/FileServiceImpl.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/service/impl/MusicServiceImpl.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/service/impl/PlaylistServiceImpl.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/service/impl/SingerServiceImpl.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/service/impl/StatServiceImpl.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/service/impl/TypeServiceImpl.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/service/impl/UserServiceImpl.java
create mode 100644 music-houduan/src/main/java/com/test/musichouduan/util/SwaggerAnnotationGenerator.java
create mode 100644 music-houduan/src/main/resources/application.properties
create mode 100644 music-houduan/src/main/resources/application.yml
create mode 100644 music-houduan/upload/images/362d1d68-fcc2-4a74-a0f1-44bd38e9cb6d.jpg
create mode 100644 music-houduan/upload/images/3efa486a-610d-4745-a54c-61f55ab3f1d5.jpg
create mode 100644 music-houduan/upload/images/569f8ce5-09d2-4151-a6b1-f56a4d0b2c84.png
create mode 100644 music-houduan/upload/images/68fa60bd-710e-443d-95f7-cb117a1a3b73.jpg
create mode 100644 music-houduan/upload/images/6c8c8d04-e583-4f12-8c56-d618b2bb06f4.jpg
create mode 100644 music-houduan/upload/images/7886a646-721a-4999-bb0c-0404768fe744.jpg
create mode 100644 music-houduan/upload/musics/69c2c485-080f-4dd7-a541-c961652a2b8e.mp3
create mode 100644 music-qianduan/.gitignore
create mode 100644 music-qianduan/index.html
create mode 100644 music-qianduan/package-lock.json
create mode 100644 music-qianduan/package.json
create mode 100644 music-qianduan/public/vite.svg
create mode 100644 music-qianduan/src/App.vue
create mode 100644 music-qianduan/src/api/admin/comment.js
create mode 100644 music-qianduan/src/api/admin/dashboard.js
create mode 100644 music-qianduan/src/api/admin/type.js
create mode 100644 music-qianduan/src/api/admin/user.js
create mode 100644 music-qianduan/src/api/banner.js
create mode 100644 music-qianduan/src/api/comment.js
create mode 100644 music-qianduan/src/api/index.js
create mode 100644 music-qianduan/src/api/music.js
create mode 100644 music-qianduan/src/api/musicType.js
create mode 100644 music-qianduan/src/api/playlist.js
create mode 100644 music-qianduan/src/api/playlistType.js
create mode 100644 music-qianduan/src/api/singer.js
create mode 100644 music-qianduan/src/api/singerType.js
create mode 100644 music-qianduan/src/api/user.js
create mode 100644 music-qianduan/src/assets/css/global.css
create mode 100644 music-qianduan/src/assets/vue.svg
create mode 100644 music-qianduan/src/components/HelloWorld.vue
create mode 100644 music-qianduan/src/components/HomeBanner.vue
create mode 100644 music-qianduan/src/components/ImagePreview.vue
create mode 100644 music-qianduan/src/components/MusicList.vue
create mode 100644 music-qianduan/src/components/MusicPlayer.vue
create mode 100644 music-qianduan/src/layouts/AdminLayout.vue
create mode 100644 music-qianduan/src/layouts/MainLayout.vue
create mode 100644 music-qianduan/src/main.js
create mode 100644 music-qianduan/src/router/index.js
create mode 100644 music-qianduan/src/stores/index.js
create mode 100644 music-qianduan/src/stores/player.js
create mode 100644 music-qianduan/src/stores/user.js
create mode 100644 music-qianduan/src/style.css
create mode 100644 music-qianduan/src/utils/clearStorage.js
create mode 100644 music-qianduan/src/utils/imageUtils.js
create mode 100644 music-qianduan/src/utils/websocket.js
create mode 100644 music-qianduan/src/views/About.vue
create mode 100644 music-qianduan/src/views/Home.vue
create mode 100644 music-qianduan/src/views/ImageTest.vue
create mode 100644 music-qianduan/src/views/Login.vue
create mode 100644 music-qianduan/src/views/Music.vue
create mode 100644 music-qianduan/src/views/MusicDetail.vue
create mode 100644 music-qianduan/src/views/NotFound.vue
create mode 100644 music-qianduan/src/views/Playlist.vue
create mode 100644 music-qianduan/src/views/PlaylistDetail.vue
create mode 100644 music-qianduan/src/views/Register.vue
create mode 100644 music-qianduan/src/views/Search.vue
create mode 100644 music-qianduan/src/views/Singer.vue
create mode 100644 music-qianduan/src/views/SingerDetail.vue
create mode 100644 music-qianduan/src/views/UserCenter.vue
create mode 100644 music-qianduan/src/views/admin/Banner.vue
create mode 100644 music-qianduan/src/views/admin/BannerManagement.vue
create mode 100644 music-qianduan/src/views/admin/CommentManagement.vue
create mode 100644 music-qianduan/src/views/admin/Dashboard.vue
create mode 100644 music-qianduan/src/views/admin/Index.vue
create mode 100644 music-qianduan/src/views/admin/Music.vue
create mode 100644 music-qianduan/src/views/admin/Playlist.vue
create mode 100644 music-qianduan/src/views/admin/PlaylistType.vue
create mode 100644 music-qianduan/src/views/admin/Singer.vue
create mode 100644 music-qianduan/src/views/admin/Type.vue
create mode 100644 music-qianduan/src/views/admin/TypeManagement.vue
create mode 100644 music-qianduan/src/views/admin/User.vue
create mode 100644 music-qianduan/src/views/admin/UserManagement.vue
create mode 100644 music-qianduan/src/views/user/CollectMusic.vue
create mode 100644 music-qianduan/src/views/user/CollectPlaylist.vue
create mode 100644 music-qianduan/src/views/user/CollectSinger.vue
create mode 100644 music-qianduan/src/views/user/Password.vue
create mode 100644 music-qianduan/src/views/user/Playlist.vue
create mode 100644 music-qianduan/vite.config.js
create mode 100644 sql/music.sql
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..843870d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,79 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
+### Example user template template
+### Example user template
+
+# IntelliJ project files
+.log
+*.gz
+.gz
+*/.gz
+*/.log
+target
+*.iml
+out
+gen
+*/.vscode
+.vscode
+#忽略所有.svn目录
+.svn/
+#忽略所有target目录
+target/
+#忽略所有.idea目录及其内容
+.idea/
+.idea/*
+#忽略所有.ipr文件
+*.ipr
+#忽略所有.iws文件
+*.iws
+#忽略所有.gradle目录
+.gradle/
+#忽略所有.settings目录
+.settings/
+#忽略所有.classpath文件
+.classpath
+#忽略所有.project文件
+.project
+#忽略所有.pydevproject文件
+.pydevproject
+#忽略所有.DS_Store文件
+
+#忽略所有.class文件
+*.class
+#忽略所有.log文件
+
+#忽略所有.tmp文件
+*.tmp
+#忽略所有.swp文件
+*.swp
+node_modules/
+/dist/
+
+.git
+
+# Editor directories and files
+dist/
+npm-debug.log
+.vscode/
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..9b497b1
--- /dev/null
+++ b/README.md
@@ -0,0 +1,219 @@
+# 音乐播放应用系统
+
+## 项目概述
+
+这是一个功能完整的音乐播放应用系统,包含前后端两部分。系统支持用户注册登录、音乐播放、歌单管理、歌手管理、评论互动等功能,为用户提供全面的音乐体验。
+
+### 系统架构
+
+本项目采用前后端分离架构:
+- 前端:基于Vue 3的单页面应用
+- 后端:基于Spring Boot的RESTful API服务
+- 数据库:MySQL关系型数据库
+- 缓存:Redis缓存服务
+
+## 技术栈
+
+### 后端技术栈
+
+- **核心框架**:Spring Boot 3.x
+- **ORM框架**:Spring Data JPA + Hibernate
+- **安全认证**:Sa-Token
+- **数据库**:MySQL 8.x
+- **缓存**:Redis
+- **API文档**:Knife4j/Swagger
+- **文件处理**:自定义文件上传服务
+
+### 前端技术栈
+
+- **核心框架**:Vue 3 (组合式API)
+- **构建工具**:Vite
+- **状态管理**:Pinia
+- **UI组件**:Element Plus
+- **路由管理**:Vue Router
+- **HTTP请求**:Axios
+- **音频处理**:Web Audio API
+
+## 功能模块
+
+### 1. 用户系统
+
+- 用户注册与登录
+- 个人信息管理
+- 收藏管理(音乐、歌单、歌手)
+- 播放历史记录
+- 权限控制(普通用户/管理员)
+
+### 2. 音乐播放系统
+
+- 音乐播放、暂停、上一首、下一首
+- 播放列表管理
+- 播放模式(顺序播放、单曲循环、列表循环)
+- 歌词同步显示
+- 进度控制与音量调节
+- 播放统计
+
+### 3. 音乐管理系统
+
+- 音乐上传与编辑
+- 音乐分类管理
+- 音乐搜索
+- 热门音乐推荐
+- 最新音乐展示
+
+### 4. 歌手管理系统
+
+- 歌手信息管理
+- 歌手分类
+- 歌手音乐关联
+- 歌手搜索
+
+### 5. 歌单管理系统
+
+- 歌单创建与编辑
+- 歌单分类
+- 歌单音乐管理
+- 歌单收藏
+- 官方推荐歌单
+
+### 6. 评论系统
+
+- 发表评论
+- 回复评论
+- 评论管理
+
+### 7. 首页推荐系统
+
+- 轮播图展示
+- 热门音乐推荐
+- 最新音乐展示
+- 推荐歌单
+- 热门歌手
+
+## 数据模型
+
+### 核心实体
+
+1. **用户(User)**:用户基本信息
+2. **音乐(Music)**:音乐信息、文件路径、歌词
+3. **歌手(Singer)**:歌手信息
+4. **歌单(Playlist)**:歌单信息
+5. **评论(Comment)**:评论内容
+6. **类型(Type)**:音乐类型、歌手类型、歌单类型
+7. **轮播图(Banner)**:首页轮播图
+
+### 核心关系
+
+1. **用户-音乐**:收藏关系、播放历史
+2. **用户-歌单**:创建关系、收藏关系
+3. **用户-歌手**:收藏关系
+4. **音乐-歌手**:多对多关系
+5. **音乐-类型**:多对多关系
+6. **歌单-音乐**:多对多关系
+7. **歌手-类型**:多对一关系
+8. **歌单-类型**:多对一关系
+
+## 部署指南
+
+### 环境要求
+
+- JDK 17+
+- Node.js 16+
+- MySQL 8.x
+- Redis 6.x
+
+### 后端部署
+
+1. 配置数据库
+ ```sql
+ CREATE DATABASE music_db CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
+ ```
+
+2. 修改配置文件
+ - 编辑 `music-houduan/src/main/resources/application.yml`
+ - 配置数据库连接信息
+ - 配置Redis连接信息
+ - 配置文件上传路径
+
+3. 构建项目
+ ```bash
+ cd music-houduan
+ mvn clean package -DskipTests
+ ```
+
+4. 运行项目
+ ```bash
+ java -jar target/music-houduan-1.0.0.jar
+ ```
+
+### 前端部署
+
+1. 安装依赖
+ ```bash
+ cd music-qianduan
+ npm install
+ ```
+
+2. 修改配置
+ - 编辑 `.env` 文件,配置API地址
+
+3. 构建项目
+ ```bash
+ npm run build
+ ```
+
+4. 部署静态资源
+ - 将 `dist` 目录下的文件部署到Web服务器
+
+## 使用说明
+
+### 管理员账号
+
+- 用户名:admin
+- 密码:123456
+
+### 普通用户
+
+- 可以自行注册或使用以下测试账号:
+ - 用户名:test
+ - 密码:123456
+
+### 基本操作流程
+
+1. **音乐播放**
+ - 在首页或音乐列表页选择音乐
+ - 点击播放按钮开始播放
+ - 使用播放器控制播放进度、音量等
+
+2. **歌单管理**
+ - 登录后可创建个人歌单
+ - 添加音乐到歌单
+ - 收藏其他用户的歌单
+
+3. **音乐上传(管理员)**
+ - 登录管理员账号
+ - 进入后台管理
+ - 上传音乐文件和封面
+
+4. **评论互动**
+ - 在音乐、歌单、歌手详情页发表评论
+ - 回复其他用户的评论
+
+## 系统截图
+
+(此处可添加系统主要页面的截图)
+
+## 开发团队
+
+- 前端开发:XXX
+- 后端开发:XXX
+- 产品设计:XXX
+- 测试:XXX
+
+## 版权声明
+
+本项目仅用于学习和演示目的,不得用于商业用途。音乐文件版权归原作者所有。
+
+## 联系方式
+
+如有问题或建议,请联系:example@example.com
diff --git a/doc/音乐下载.txt b/doc/音乐下载.txt
new file mode 100644
index 0000000..3579140
--- /dev/null
+++ b/doc/音乐下载.txt
@@ -0,0 +1,2 @@
+https://www.gequbao.com/
+https://www.gequhai.com/
\ No newline at end of file
diff --git a/music-houduan/.gitattributes b/music-houduan/.gitattributes
new file mode 100644
index 0000000..22a3c0b
--- /dev/null
+++ b/music-houduan/.gitattributes
@@ -0,0 +1,64 @@
+### Example user template template
+### Example user template
+
+# IntelliJ project files
+.idea
+target
+*.gz
+*.log
+.log
+*.logs
+.logs
+*.zip
+*.iml
+out
+gen
+*/.vscode
+.vscode
+#忽略所有.svn目录
+.svn/
+#忽略所有target目录
+target/
+#忽略所有.idea目录及其内容
+.idea/
+.idea/*
+#忽略所有.ipr文件
+*.ipr
+#忽略所有.iws文件
+*.iws
+#忽略所有.gradle目录
+.gradle/
+#忽略所有.settings目录
+.settings/
+#忽略所有.classpath文件
+.classpath
+#忽略所有.project文件
+.project
+#忽略所有.pydevproject文件
+.pydevproject
+#忽略所有.DS_Store文件
+.DS_Store
+#忽略所有.class文件
+*.class
+#忽略所有.log文件
+*.log
+#忽略所有.tmp文件
+*.tmp
+#忽略所有.swp文件
+*.swp
+node_modules/
+/dist/
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+.git
+
+# Editor directories and files
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+dist/
+npm-debug.log
+.vscode/
+README.md
\ No newline at end of file
diff --git a/music-houduan/.gitignore b/music-houduan/.gitignore
new file mode 100644
index 0000000..8b1cf61
--- /dev/null
+++ b/music-houduan/.gitignore
@@ -0,0 +1,39 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+*.log
+*.logs
+*/*.log
+*/.log
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+logs
+node_modules
\ No newline at end of file
diff --git a/music-houduan/pom.xml b/music-houduan/pom.xml
new file mode 100644
index 0000000..16ae858
--- /dev/null
+++ b/music-houduan/pom.xml
@@ -0,0 +1,145 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.2.5
+
+
+ com.test
+ music-houduan
+ 0.0.1-SNAPSHOT
+ music-houduan
+ 音乐应用后端
+
+
+ 17
+ 1.38.0
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ runtime
+ true
+
+
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+
+
+ com.mysql
+ mysql-connector-j
+ runtime
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+
+
+ org.apache.commons
+ commons-pool2
+
+
+
+
+ cn.dev33
+ sa-token-spring-boot3-starter
+ ${sa-token.version}
+
+
+
+
+ cn.dev33
+ sa-token-redis-jackson
+ ${sa-token.version}
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+
+ org.springframework.boot
+ spring-boot-starter-websocket
+
+
+
+
+ org.apache.commons
+ commons-lang3
+
+
+
+
+ commons-fileupload
+ commons-fileupload
+ 1.5
+
+
+
+
+ net.coobird
+ thumbnailator
+ 0.4.20
+
+
+
+
+ com.github.xiaoymin
+ knife4j-openapi3-jakarta-spring-boot-starter
+ 4.5.0
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+
+
+
diff --git a/music-houduan/src/main/java/com/test/musichouduan/MusicHouduanApplication.java b/music-houduan/src/main/java/com/test/musichouduan/MusicHouduanApplication.java
new file mode 100644
index 0000000..668ac50
--- /dev/null
+++ b/music-houduan/src/main/java/com/test/musichouduan/MusicHouduanApplication.java
@@ -0,0 +1,21 @@
+package com.test.musichouduan;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+/**
+ * 音乐应用后端启动类
+ */
+@SpringBootApplication
+@EnableTransactionManagement
+@EnableScheduling
+public class MusicHouduanApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(MusicHouduanApplication.class, args);
+ System.out.println("\n---------- 音乐应用后端启动成功 ----------\n");
+ }
+
+}
diff --git a/music-houduan/src/main/java/com/test/musichouduan/config/CorsConfig.java b/music-houduan/src/main/java/com/test/musichouduan/config/CorsConfig.java
new file mode 100644
index 0000000..e3783d6
--- /dev/null
+++ b/music-houduan/src/main/java/com/test/musichouduan/config/CorsConfig.java
@@ -0,0 +1,33 @@
+package com.test.musichouduan.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * 跨域配置
+ */
+@Configuration
+public class CorsConfig {
+
+ @Bean
+ public CorsFilter corsFilter() {
+ CorsConfiguration config = new CorsConfiguration();
+ // 允许指定域名跨域调用
+ config.addAllowedOrigin("http://localhost:5173");
+ config.addAllowedOrigin("http://localhost:5174");
+ config.addAllowedOrigin("https://your-production-domain.com");
+ // 允许跨域发送cookie
+ config.setAllowCredentials(true);
+ // 放行全部原始头信息
+ config.addAllowedHeader("*");
+ // 允许所有请求方法跨域调用
+ config.addAllowedMethod("*");
+
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", config);
+ return new CorsFilter(source);
+ }
+}
diff --git a/music-houduan/src/main/java/com/test/musichouduan/config/Knife4jConfig.java b/music-houduan/src/main/java/com/test/musichouduan/config/Knife4jConfig.java
new file mode 100644
index 0000000..621ef43
--- /dev/null
+++ b/music-houduan/src/main/java/com/test/musichouduan/config/Knife4jConfig.java
@@ -0,0 +1,24 @@
+package com.test.musichouduan.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+/**
+ * Knife4j 配置类
+ */
+@Configuration
+public class Knife4jConfig implements WebMvcConfigurer {
+
+ @Override
+ public void addResourceHandlers(ResourceHandlerRegistry registry) {
+ // 配置 Knife4j 的静态资源
+ registry.addResourceHandler("doc.html")
+ .addResourceLocations("classpath:/META-INF/resources/")
+ .resourceChain(false); // 使用默认的资源解析器
+ registry.addResourceHandler("/webjars/**")
+ .addResourceLocations("classpath:/META-INF/resources/webjars/")
+ .resourceChain(false); // 使用默认的资源解析器
+ }
+}
diff --git a/music-houduan/src/main/java/com/test/musichouduan/config/RedisConfig.java b/music-houduan/src/main/java/com/test/musichouduan/config/RedisConfig.java
new file mode 100644
index 0000000..8cbcb66
--- /dev/null
+++ b/music-houduan/src/main/java/com/test/musichouduan/config/RedisConfig.java
@@ -0,0 +1,34 @@
+package com.test.musichouduan.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+/**
+ * Redis配置
+ */
+@Configuration
+public class RedisConfig {
+
+ @Bean
+ public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) {
+ RedisTemplate template = new RedisTemplate<>();
+ template.setConnectionFactory(connectionFactory);
+
+ // 使用StringRedisSerializer来序列化和反序列化redis的key值
+ template.setKeySerializer(new StringRedisSerializer());
+ // 使用GenericJackson2JsonRedisSerializer来序列化和反序列化redis的value值
+ template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
+
+ // Hash的key也采用StringRedisSerializer的序列化方式
+ template.setHashKeySerializer(new StringRedisSerializer());
+ // Hash的value也采用GenericJackson2JsonRedisSerializer的序列化方式
+ template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
+
+ template.afterPropertiesSet();
+ return template;
+ }
+}
diff --git a/music-houduan/src/main/java/com/test/musichouduan/config/SaTokenConfig.java b/music-houduan/src/main/java/com/test/musichouduan/config/SaTokenConfig.java
new file mode 100644
index 0000000..782c369
--- /dev/null
+++ b/music-houduan/src/main/java/com/test/musichouduan/config/SaTokenConfig.java
@@ -0,0 +1,55 @@
+package com.test.musichouduan.config;
+
+import cn.dev33.satoken.interceptor.SaInterceptor;
+import cn.dev33.satoken.stp.StpUtil;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import java.util.List;
+
+/**
+ * Sa-Token配置
+ */
+@Configuration
+public class SaTokenConfig implements WebMvcConfigurer {
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 注册Sa-Token拦截器,打开注解式鉴权功能
+ registry.addInterceptor(new SaInterceptor(handle -> {
+ // 打印调试信息
+ System.out.println("\n=== Sa-Token 拦截器检查登录状态 ===\n");
+
+ // 获取当前登录用户ID
+ Object loginId = StpUtil.getLoginIdDefaultNull();
+ System.out.println("当前登录用户ID: " + loginId);
+
+ // 获取当前用户角色
+ List roleList = StpUtil.getRoleList();
+ System.out.println("当前用户角色: " + roleList);
+
+ // 检查登录状态
+ StpUtil.checkLogin();
+ }))
+ .addPathPatterns("/api/**")
+ .excludePathPatterns(
+ "/api/user/login",
+ "/api/user/register",
+ "/api/music/list",
+ "/api/music/latest",
+ "/api/music/hot",
+ "/api/music/*/play",
+ "/api/playlist/list",
+ "/api/playlist/latest",
+ "/api/playlist/hot",
+ "/api/playlist/official",
+ "/api/playlist/*/play",
+ "/api/singer/list",
+ "/api/singer/latest",
+ "/api/type/**",
+ "/api/banner/list",
+ "/api/comment/list"
+ );
+ }
+}
diff --git a/music-houduan/src/main/java/com/test/musichouduan/config/StpInterfaceImpl.java b/music-houduan/src/main/java/com/test/musichouduan/config/StpInterfaceImpl.java
new file mode 100644
index 0000000..44d3b7c
--- /dev/null
+++ b/music-houduan/src/main/java/com/test/musichouduan/config/StpInterfaceImpl.java
@@ -0,0 +1,55 @@
+package com.test.musichouduan.config;
+
+import cn.dev33.satoken.stp.StpInterface;
+import com.test.musichouduan.entity.User;
+import com.test.musichouduan.repository.UserRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 自定义权限验证接口扩展
+ */
+@Component
+public class StpInterfaceImpl implements StpInterface {
+
+ @Autowired
+ private UserRepository userRepository;
+
+ /**
+ * 返回一个账号所拥有的权限码集合
+ */
+ @Override
+ public List getPermissionList(Object loginId, String loginType) {
+ // 暂时不需要权限码
+ return new ArrayList<>();
+ }
+
+ /**
+ * 返回一个账号所拥有的角色标识集合
+ */
+ @Override
+ public List getRoleList(Object loginId, String loginType) {
+ List roles = new ArrayList<>();
+
+ // 获取用户ID
+ Long userId = Long.parseLong(loginId.toString());
+
+ // 查询用户
+ userRepository.findById(userId).ifPresent(user -> {
+ // 根据用户的role字段设置角色
+ if (user.getRole() == 1) {
+ roles.add("admin");
+ } else {
+ roles.add("user");
+ }
+
+ // 打印调试信息
+ System.out.println("用户ID: " + userId + ", 角色: " + roles);
+ });
+
+ return roles;
+ }
+}
diff --git a/music-houduan/src/main/java/com/test/musichouduan/config/SwaggerConfig.java b/music-houduan/src/main/java/com/test/musichouduan/config/SwaggerConfig.java
new file mode 100644
index 0000000..78ebb5b
--- /dev/null
+++ b/music-houduan/src/main/java/com/test/musichouduan/config/SwaggerConfig.java
@@ -0,0 +1,119 @@
+package com.test.musichouduan.config;
+
+import io.swagger.v3.oas.models.Components;
+import io.swagger.v3.oas.models.ExternalDocumentation;
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.info.Contact;
+import io.swagger.v3.oas.models.info.Info;
+import io.swagger.v3.oas.models.info.License;
+import io.swagger.v3.oas.models.security.SecurityRequirement;
+import io.swagger.v3.oas.models.security.SecurityScheme;
+import io.swagger.v3.oas.models.servers.Server;
+import org.springdoc.core.models.GroupedOpenApi;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Knife4j配置
+ */
+@Configuration
+public class SwaggerConfig {
+
+ @Bean
+ public OpenAPI openAPI() {
+ // 添加服务器信息
+ List servers = new ArrayList<>();
+ servers.add(new Server().url("/").description("本地服务"));
+
+ return new OpenAPI()
+ .info(new Info()
+ .title("音乐应用API文档")
+ .description("音乐应用后端API接口文档")
+ .version("v1.0.0")
+ .contact(new Contact()
+ .name("Admin")
+ .email("admin@example.com")
+ .url("https://example.com"))
+ .license(new License()
+ .name("Apache 2.0")
+ .url("https://www.apache.org/licenses/LICENSE-2.0.html")))
+ .externalDocs(new ExternalDocumentation()
+ .description("项目文档")
+ .url("https://example.com/docs"))
+ .servers(servers)
+ .addSecurityItem(new SecurityRequirement().addList("bearerAuth"))
+ .components(new Components()
+ .addSecuritySchemes("bearerAuth", new SecurityScheme()
+ .name("bearerAuth")
+ .type(SecurityScheme.Type.HTTP)
+ .scheme("bearer")
+ .bearerFormat("JWT")));
+ }
+
+ @Bean
+ public GroupedOpenApi userApi() {
+ return GroupedOpenApi.builder()
+ .group("用户接口")
+ .pathsToMatch("/api/user/**")
+ .build();
+ }
+
+ @Bean
+ public GroupedOpenApi musicApi() {
+ return GroupedOpenApi.builder()
+ .group("音乐接口")
+ .pathsToMatch("/api/music/**")
+ .build();
+ }
+
+ @Bean
+ public GroupedOpenApi singerApi() {
+ return GroupedOpenApi.builder()
+ .group("歌手接口")
+ .pathsToMatch("/api/singer/**")
+ .build();
+ }
+
+ @Bean
+ public GroupedOpenApi playlistApi() {
+ return GroupedOpenApi.builder()
+ .group("歌单接口")
+ .pathsToMatch("/api/playlist/**")
+ .build();
+ }
+
+ @Bean
+ public GroupedOpenApi commentApi() {
+ return GroupedOpenApi.builder()
+ .group("评论接口")
+ .pathsToMatch("/api/comment/**")
+ .build();
+ }
+
+ @Bean
+ public GroupedOpenApi typeApi() {
+ return GroupedOpenApi.builder()
+ .group("类型接口")
+ .pathsToMatch("/api/type/**")
+ .build();
+ }
+
+ @Bean
+ public GroupedOpenApi bannerApi() {
+ return GroupedOpenApi.builder()
+ .group("轮播图接口")
+ .pathsToMatch("/api/banner/**")
+ .build();
+ }
+
+ @Bean
+ public GroupedOpenApi adminApi() {
+ return GroupedOpenApi.builder()
+ .group("管理员接口")
+ .pathsToMatch("/api/admin/**")
+ .build();
+ }
+}
diff --git a/music-houduan/src/main/java/com/test/musichouduan/config/WebConfig.java b/music-houduan/src/main/java/com/test/musichouduan/config/WebConfig.java
new file mode 100644
index 0000000..8ed84b1
--- /dev/null
+++ b/music-houduan/src/main/java/com/test/musichouduan/config/WebConfig.java
@@ -0,0 +1,25 @@
+package com.test.musichouduan.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+/**
+ * Web配置类
+ */
+@Configuration
+public class WebConfig implements WebMvcConfigurer {
+
+ /**
+ * 跨域配置
+ */
+ @Override
+ public void addCorsMappings(CorsRegistry registry) {
+ registry.addMapping("/**")
+ .allowedOriginPatterns("*")
+ .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
+ .allowedHeaders("*")
+ .allowCredentials(true)
+ .maxAge(3600);
+ }
+}
diff --git a/music-houduan/src/main/java/com/test/musichouduan/config/WebMvcConfig.java b/music-houduan/src/main/java/com/test/musichouduan/config/WebMvcConfig.java
new file mode 100644
index 0000000..47476b4
--- /dev/null
+++ b/music-houduan/src/main/java/com/test/musichouduan/config/WebMvcConfig.java
@@ -0,0 +1,28 @@
+package com.test.musichouduan.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+/**
+ * Web MVC 配置
+ */
+@Configuration
+public class WebMvcConfig implements WebMvcConfigurer {
+
+ @Value("${file.upload-path}")
+ private String uploadPath;
+
+ @Value("${file.access-path}")
+ private String accessPath;
+
+ @Override
+ public void addResourceHandlers(ResourceHandlerRegistry registry) {
+ // 配置上传文件资源映射
+ registry.addResourceHandler(accessPath + "**")
+ .addResourceLocations("file:" + uploadPath);
+
+ // 注意:前后端分离项目,不需要配置静态资源映射
+ }
+}
diff --git a/music-houduan/src/main/java/com/test/musichouduan/config/WebSocketConfig.java b/music-houduan/src/main/java/com/test/musichouduan/config/WebSocketConfig.java
new file mode 100644
index 0000000..3edab79
--- /dev/null
+++ b/music-houduan/src/main/java/com/test/musichouduan/config/WebSocketConfig.java
@@ -0,0 +1,33 @@
+package com.test.musichouduan.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.messaging.simp.config.MessageBrokerRegistry;
+import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
+import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
+import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
+
+@Configuration
+@EnableWebSocketMessageBroker
+public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
+
+ @Override
+ public void configureMessageBroker(MessageBrokerRegistry config) {
+ // 配置消息代理,用于广播式消息(例如,/topic/ 前缀)
+ // 客户端订阅 "/topic/comments/{targetType}/{targetId}" 来接收特定目标的评论更新
+ config.enableSimpleBroker("/topic");
+ // 配置应用程序目标前缀,客户端发送消息到服务器的目标前缀(例如,/app/ 前缀)
+ // 这个项目我们主要用服务器主动推送,所以 /app 可能用不到,但先配置上
+ config.setApplicationDestinationPrefixes("/app");
+ }
+
+ @Override
+ public void registerStompEndpoints(StompEndpointRegistry registry) {
+ // 注册一个 STOMP 端点,客户端将使用它连接到 WebSocket 服务器
+ // "/ws" 是连接的端点路径
+ // withSockJS() 启用 SockJS 后备选项,以便在 WebSocket 不可用时使用其他传输方式
+ // setAllowedOrigins("*") 允许所有来源的跨域连接,在生产环境中应配置为具体的来源
+ registry.addEndpoint("/ws")
+ .setAllowedOrigins("http://localhost:5173", "http://localhost:5174", "https://your-production-domain.com")
+ .withSockJS(); // 启用 SockJS 支持
+ }
+}
diff --git a/music-houduan/src/main/java/com/test/musichouduan/controller/BannerController.java b/music-houduan/src/main/java/com/test/musichouduan/controller/BannerController.java
new file mode 100644
index 0000000..bee199a
--- /dev/null
+++ b/music-houduan/src/main/java/com/test/musichouduan/controller/BannerController.java
@@ -0,0 +1,153 @@
+package com.test.musichouduan.controller;
+
+import cn.dev33.satoken.annotation.SaCheckRole;
+import com.test.musichouduan.dto.BannerDTO;
+import com.test.musichouduan.dto.PageResult;
+import com.test.musichouduan.dto.Result;
+import com.test.musichouduan.service.BannerService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.List;
+
+/**
+ * 轮播图控制器
+ */
+@Tag(name = "轮播图接口", description = "轮播图的增删改查操作")
+@RestController
+@RequestMapping("/api/banner")
+public class BannerController {
+
+ @Autowired
+ private BannerService bannerService;
+
+ /**
+ * 根据ID获取轮播图
+ *
+ * @param id 轮播图ID
+ * @return 响应结果
+ */
+ @Operation(summary = "根据ID获取轮播图", description = "根据轮播图ID获取轮播图详情")
+ @GetMapping("/{id}")
+ public Result getBannerById(@Parameter(description = "轮播图ID") @PathVariable Long id) {
+ BannerDTO bannerDTO = bannerService.getBannerById(id);
+ return Result.success(bannerDTO);
+ }
+
+ /**
+ * 获取轮播图列表
+ *
+ * @return 响应结果
+ */
+ @Operation(summary = "获取轮播图列表", description = "获取所有启用状态的轮播图列表")
+ @GetMapping("/list")
+ public Result> getBannerList() {
+ List bannerList = bannerService.getBannerList();
+ return Result.success(bannerList);
+ }
+
+ /**
+ * 分页获取轮播图列表
+ *
+ * @param page 页码
+ * @param size 每页大小
+ * @return 响应结果
+ */
+ @Operation(summary = "分页获取轮播图列表", description = "分页获取轮播图列表,需要管理员权限")
+ @SaCheckRole("admin")
+ @GetMapping("/page")
+ public Result> getBannerPage(
+ @Parameter(description = "页码", example = "1") @RequestParam(defaultValue = "1") Integer page,
+ @Parameter(description = "每页大小", example = "10") @RequestParam(defaultValue = "10") Integer size) {
+ PageResult pageResult = bannerService.getBannerPage(page, size);
+ return Result.success(pageResult);
+ }
+
+ /**
+ * 添加轮播图
+ *
+ * @param bannerDTO 轮播图DTO
+ * @param image 图片文件
+ * @return 响应结果
+ */
+ @Operation(summary = "添加轮播图", description = "添加轮播图,需要管理员权限")
+ @SaCheckRole("admin")
+ @PostMapping("/add")
+ public Result addBanner(
+ @Parameter(description = "轮播图信息") @RequestPart("banner") BannerDTO bannerDTO,
+ @Parameter(description = "轮播图图片文件") @RequestPart("image") MultipartFile image) {
+ BannerDTO result = bannerService.addBanner(bannerDTO, image);
+ return Result.success("添加成功", result);
+ }
+
+ /**
+ * 更新轮播图
+ *
+ * @param id 轮播图ID
+ * @param bannerDTO 轮播图DTO
+ * @param image 图片文件
+ * @return 响应结果
+ */
+ @Operation(summary = "更新轮播图", description = "更新轮播图信息,需要管理员权限")
+ @SaCheckRole("admin")
+ @PutMapping("/{id}")
+ public Result updateBanner(
+ @Parameter(description = "轮播图ID") @PathVariable Long id,
+ @Parameter(description = "轮播图信息") @RequestPart("banner") BannerDTO bannerDTO,
+ @Parameter(description = "轮播图图片文件,可选") @RequestPart(value = "image", required = false) MultipartFile image) {
+ BannerDTO result = bannerService.updateBanner(id, bannerDTO, image);
+ return Result.success("更新成功", result);
+ }
+
+ /**
+ * 删除轮播图
+ *
+ * @param id 轮播图ID
+ * @return 响应结果
+ */
+ @Operation(summary = "删除轮播图", description = "删除轮播图,需要管理员权限")
+ @SaCheckRole("admin")
+ @DeleteMapping("/{id}")
+ public Result deleteBanner(@Parameter(description = "轮播图ID") @PathVariable Long id) {
+ boolean result = bannerService.deleteBanner(id);
+ return Result.success("删除成功", result);
+ }
+
+ /**
+ * 更新轮播图状态
+ *
+ * @param id 轮播图ID
+ * @param status 状态
+ * @return 响应结果
+ */
+ @Operation(summary = "更新轮播图状态", description = "更新轮播图状态,0-禁用,1-启用,需要管理员权限")
+ @SaCheckRole("admin")
+ @PutMapping("/{id}/status")
+ public Result updateBannerStatus(
+ @Parameter(description = "轮播图ID") @PathVariable Long id,
+ @Parameter(description = "状态,0-禁用,1-启用", example = "1") @RequestParam Integer status) {
+ boolean result = bannerService.updateBannerStatus(id, status);
+ return Result.success("更新成功", result);
+ }
+
+ /**
+ * 更新轮播图排序
+ *
+ * @param id 轮播图ID
+ * @param orderNum 排序号
+ * @return 响应结果
+ */
+ @Operation(summary = "更新轮播图排序", description = "更新轮播图排序号,数字越小越靠前,需要管理员权限")
+ @SaCheckRole("admin")
+ @PutMapping("/{id}/order")
+ public Result updateBannerOrder(
+ @Parameter(description = "轮播图ID") @PathVariable Long id,
+ @Parameter(description = "排序号,数字越小越靠前", example = "1") @RequestParam Integer orderNum) {
+ boolean result = bannerService.updateBannerOrder(id, orderNum);
+ return Result.success("更新成功", result);
+ }
+}
diff --git a/music-houduan/src/main/java/com/test/musichouduan/controller/BasicTestController.java b/music-houduan/src/main/java/com/test/musichouduan/controller/BasicTestController.java
new file mode 100644
index 0000000..589418b
--- /dev/null
+++ b/music-houduan/src/main/java/com/test/musichouduan/controller/BasicTestController.java
@@ -0,0 +1,29 @@
+package com.test.musichouduan.controller;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 基本测试控制器
+ */
+@RestController
+@RequestMapping("/basic-test")
+public class BasicTestController {
+
+ /**
+ * 基本测试接口
+ */
+ @GetMapping
+ public Map test() {
+ Map result = new HashMap<>();
+ result.put("code", 200);
+ result.put("message", "基本测试成功");
+ result.put("data", "Hello, Basic Test!");
+ result.put("time", System.currentTimeMillis());
+ return result;
+ }
+}
diff --git a/music-houduan/src/main/java/com/test/musichouduan/controller/CommentController.java b/music-houduan/src/main/java/com/test/musichouduan/controller/CommentController.java
new file mode 100644
index 0000000..6a986cc
--- /dev/null
+++ b/music-houduan/src/main/java/com/test/musichouduan/controller/CommentController.java
@@ -0,0 +1,97 @@
+package com.test.musichouduan.controller;
+
+import cn.dev33.satoken.annotation.SaCheckLogin;
+import cn.dev33.satoken.annotation.SaCheckRole;
+import cn.dev33.satoken.stp.StpUtil;
+import com.test.musichouduan.dto.CommentDTO;
+import com.test.musichouduan.dto.PageResult;
+import com.test.musichouduan.dto.Result;
+import com.test.musichouduan.service.CommentService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * 评论控制器
+ */
+@RestController
+@RequestMapping("/api/comment")
+public class CommentController {
+
+ @Autowired
+ private CommentService commentService;
+
+ /**
+ * 根据ID获取评论
+ *
+ * @param id 评论ID
+ * @return 响应结果
+ */
+ @GetMapping("/{id}")
+ public Result getCommentById(@PathVariable Long id) {
+ CommentDTO commentDTO = commentService.getCommentById(id);
+ return Result.success(commentDTO);
+ }
+
+ /**
+ * 分页获取评论列表
+ *
+ * @param targetId 目标ID
+ * @param targetType 目标类型
+ * @param page 页码
+ * @param size 每页大小
+ * @return 响应结果
+ */
+ @GetMapping("/list")
+ public Result> getCommentList(
+ @RequestParam Long targetId,
+ @RequestParam Integer targetType,
+ @RequestParam(defaultValue = "1") Integer page,
+ @RequestParam(defaultValue = "10") Integer size) {
+ PageResult pageResult = commentService.getCommentList(targetId, targetType, page, size);
+ return Result.success(pageResult);
+ }
+
+ /**
+ * 添加评论
+ *
+ * @param commentDTO 评论DTO
+ * @return 响应结果
+ */
+ @SaCheckLogin
+ @PostMapping("/add")
+ public Result addComment(@RequestBody CommentDTO commentDTO) {
+ CommentDTO result = commentService.addComment(commentDTO);
+ return Result.success("评论成功", result);
+ }
+
+ /**
+ * 删除评论
+ *
+ * @param id 评论ID
+ * @return 响应结果
+ */
+ @SaCheckLogin
+ @DeleteMapping("/{id}")
+ public Result deleteComment(@PathVariable Long id) {
+ boolean result = commentService.deleteComment(id);
+ return Result.success("删除成功", result);
+ }
+
+ /**
+ * 获取用户的评论列表
+ *
+ * @param page 页码
+ * @param size 每页大小
+ * @return 响应结果
+ */
+ @SaCheckLogin
+ @GetMapping("/user")
+ public Result> getUserCommentList(
+ @RequestParam(defaultValue = "1") Integer page,
+ @RequestParam(defaultValue = "10") Integer size) {
+ // 获取当前登录用户ID
+ Long userId = StpUtil.getLoginIdAsLong();
+ PageResult pageResult = commentService.getUserCommentList(userId, page, size);
+ return Result.success(pageResult);
+ }
+}
diff --git a/music-houduan/src/main/java/com/test/musichouduan/controller/FallbackController.java b/music-houduan/src/main/java/com/test/musichouduan/controller/FallbackController.java
new file mode 100644
index 0000000..23e2024
--- /dev/null
+++ b/music-houduan/src/main/java/com/test/musichouduan/controller/FallbackController.java
@@ -0,0 +1,36 @@
+package com.test.musichouduan.controller;
+
+import com.test.musichouduan.dto.Result;
+import org.springframework.core.annotation.Order;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+
+/**
+ * 回退控制器
+ * 处理所有未匹配的请求
+ * 使用Order注解指定优先级,数值越大优先级越低
+ */
+@RestController
+@Order(Integer.MAX_VALUE)
+public class FallbackController {
+
+ /**
+ * 处理所有非API请求
+ *
+ * @param request HTTP请求
+ * @param response HTTP响应
+ * @return 响应结果
+ */
+ @RequestMapping({"/1", "/2", "/3", "/4", "/5", "/6", "/7", "/8", "/9"})
+ public Result handleFallback(HttpServletRequest request, HttpServletResponse response) {
+ // 设置HTTP状态码为404
+ response.setStatus(HttpStatus.NOT_FOUND.value());
+
+ // 返回错误信息
+ return Result.error(HttpStatus.NOT_FOUND.value(), "资源不存在: " + request.getRequestURI());
+ }
+}
diff --git a/music-houduan/src/main/java/com/test/musichouduan/controller/FileController.java b/music-houduan/src/main/java/com/test/musichouduan/controller/FileController.java
new file mode 100644
index 0000000..920e1f8
--- /dev/null
+++ b/music-houduan/src/main/java/com/test/musichouduan/controller/FileController.java
@@ -0,0 +1,71 @@
+package com.test.musichouduan.controller;
+
+import cn.dev33.satoken.annotation.SaCheckLogin;
+import com.test.musichouduan.dto.Result;
+import com.test.musichouduan.service.FileService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * 文件控制器
+ */
+@RestController
+@RequestMapping("/api/file")
+public class FileController {
+
+ @Autowired
+ private FileService fileService;
+
+ /**
+ * 上传图片
+ *
+ * @param file 图片文件
+ * @return 响应结果
+ */
+ @SaCheckLogin
+ @PostMapping("/upload/image")
+ public Result uploadImage(@RequestParam("file") MultipartFile file) {
+ String url = fileService.uploadImage(file);
+ return Result.success("上传成功", url);
+ }
+
+ /**
+ * 上传音乐
+ *
+ * @param file 音乐文件
+ * @return 响应结果
+ */
+ @SaCheckLogin
+ @PostMapping("/upload/music")
+ public Result uploadMusic(@RequestParam("file") MultipartFile file) {
+ String url = fileService.uploadMusic(file);
+ return Result.success("上传成功", url);
+ }
+
+ /**
+ * 上传歌词
+ *
+ * @param file 歌词文件
+ * @return 响应结果
+ */
+ @SaCheckLogin
+ @PostMapping("/upload/lyric")
+ public Result uploadLyric(@RequestParam("file") MultipartFile file) {
+ String lyric = fileService.uploadLyric(file);
+ return Result.success("上传成功", lyric);
+ }
+
+ /**
+ * 删除文件
+ *
+ * @param url 文件URL
+ * @return 响应结果
+ */
+ @SaCheckLogin
+ @DeleteMapping("/delete")
+ public Result deleteFile(@RequestParam String url) {
+ boolean result = fileService.deleteFile(url);
+ return Result.success("删除成功", result);
+ }
+}
diff --git a/music-houduan/src/main/java/com/test/musichouduan/controller/HelloController.java b/music-houduan/src/main/java/com/test/musichouduan/controller/HelloController.java
new file mode 100644
index 0000000..ed69835
--- /dev/null
+++ b/music-houduan/src/main/java/com/test/musichouduan/controller/HelloController.java
@@ -0,0 +1,42 @@
+package com.test.musichouduan.controller;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 简单的Hello控制器
+ */
+@RestController
+@RequestMapping("/api")
+public class HelloController {
+
+ /**
+ * 欢迎接口
+ */
+ @GetMapping("/hello")
+ public Map hello() {
+ Map result = new HashMap<>();
+ result.put("code", 200);
+ result.put("message", "Hello, Music API!");
+ result.put("data", "欢迎使用音乐应用API");
+ result.put("timestamp", System.currentTimeMillis());
+ return result;
+ }
+
+ /**
+ * 测试热部署接口
+ */
+ @GetMapping("/test")
+ public Map test() {
+ Map result = new HashMap<>();
+ result.put("code", 200);
+ result.put("message", "测试成功");
+ result.put("data", "这是一个测试接口,可以修改此处来测试热部署");
+ result.put("timestamp", System.currentTimeMillis());
+ return result;
+ }
+}
diff --git a/music-houduan/src/main/java/com/test/musichouduan/controller/MusicController.java b/music-houduan/src/main/java/com/test/musichouduan/controller/MusicController.java
new file mode 100644
index 0000000..3dad514
--- /dev/null
+++ b/music-houduan/src/main/java/com/test/musichouduan/controller/MusicController.java
@@ -0,0 +1,216 @@
+package com.test.musichouduan.controller;
+
+import cn.dev33.satoken.annotation.SaCheckLogin;
+import cn.dev33.satoken.annotation.SaCheckRole;
+import cn.dev33.satoken.stp.StpUtil;
+import com.test.musichouduan.dto.MusicDTO;
+import com.test.musichouduan.dto.PageResult;
+import com.test.musichouduan.dto.Result;
+import com.test.musichouduan.service.MusicService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.List;
+
+/**
+ * 音乐控制器
+ */
+@RestController
+@RequestMapping("/api/music")
+public class MusicController {
+
+ @Autowired
+ private MusicService musicService;
+
+ /**
+ * 根据ID获取音乐
+ *
+ * @param id 音乐ID
+ * @return 响应结果
+ */
+ @GetMapping("/{id}")
+ public Result getMusicById(@PathVariable Long id) {
+ MusicDTO musicDTO = musicService.getMusicById(id);
+ if (musicDTO == null) {
+ // 如果音乐不存在,返回空数据而不是错误
+ return Result.success(null);
+ }
+ return Result.success(musicDTO);
+ }
+
+ /**
+ * 分页获取音乐列表
+ *
+ * @param page 页码
+ * @param size 每页大小
+ * @param keyword 关键字
+ * @param typeId 类型ID
+ * @return 响应结果
+ */
+ @GetMapping("/list")
+ public Result> getMusicList(
+ @RequestParam(defaultValue = "1") Integer page,
+ @RequestParam(defaultValue = "10") Integer size,
+ @RequestParam(required = false) String keyword,
+ @RequestParam(required = false) Long typeId) {
+ PageResult pageResult = musicService.getMusicList(page, size, keyword, typeId);
+ return Result.success(pageResult);
+ }
+
+ /**
+ * 根据歌手ID获取音乐列表
+ *
+ * @param singerId 歌手ID
+ * @param page 页码
+ * @param size 每页大小
+ * @return 响应结果
+ */
+ @GetMapping("/singer/{singerId}")
+ public Result> getMusicListBySinger(
+ @PathVariable Long singerId,
+ @RequestParam(defaultValue = "1") Integer page,
+ @RequestParam(defaultValue = "10") Integer size) {
+ PageResult pageResult = musicService.getMusicListBySinger(singerId, page, size);
+ return Result.success(pageResult);
+ }
+
+ /**
+ * 获取最新音乐列表
+ *
+ * @param limit 限制数量
+ * @return 响应结果
+ */
+ @GetMapping("/latest")
+ public Result> getLatestMusic(@RequestParam(defaultValue = "10") Integer limit) {
+ List musicList = musicService.getLatestMusic(limit);
+ return Result.success(musicList);
+ }
+
+ /**
+ * 获取热门音乐列表
+ *
+ * @param limit 限制数量
+ * @return 响应结果
+ */
+ @GetMapping("/hot")
+ public Result> getHotMusic(@RequestParam(defaultValue = "10") Integer limit) {
+ List musicList = musicService.getHotMusic(limit);
+ return Result.success(musicList);
+ }
+
+ /**
+ * 搜索音乐
+ *
+ * @param keyword 关键字
+ * @param page 页码
+ * @param size 每页大小
+ * @return 响应结果
+ */
+ @GetMapping("/search")
+ public Result> searchMusic(
+ @RequestParam String keyword,
+ @RequestParam(defaultValue = "1") Integer page,
+ @RequestParam(defaultValue = "10") Integer size) {
+ PageResult pageResult = musicService.getMusicList(page, size, keyword, null);
+ return Result.success(pageResult);
+ }
+
+ /**
+ * 添加音乐
+ *
+ * @param musicDTO 音乐DTO
+ * @param file 音乐文件
+ * @param cover 封面文件
+ * @return 响应结果
+ */
+ @SaCheckRole("admin")
+ @PostMapping("/add")
+ public Result addMusic(
+ @RequestPart("music") MusicDTO musicDTO,
+ @RequestPart(value = "file", required = false) MultipartFile file,
+ @RequestPart(value = "cover", required = false) MultipartFile cover) {
+ MusicDTO result = musicService.addMusic(musicDTO, file, cover);
+ return Result.success("添加成功", result);
+ }
+
+ /**
+ * 更新音乐
+ *
+ * @param id 音乐ID
+ * @param musicDTO 音乐DTO
+ * @param file 音乐文件
+ * @param cover 封面文件
+ * @return 响应结果
+ */
+ @SaCheckRole("admin")
+ @PutMapping("/{id}")
+ public Result updateMusic(
+ @PathVariable Long id,
+ @RequestPart("music") MusicDTO musicDTO,
+ @RequestPart(value = "file", required = false) MultipartFile file,
+ @RequestPart(value = "cover", required = false) MultipartFile cover,
+ @RequestPart(value = "lyric", required = false) MultipartFile lyric) {
+ MusicDTO result = musicService.updateMusic(id, musicDTO, file, cover, lyric);
+ return Result.success("更新成功", result);
+ }
+
+ /**
+ * 删除音乐
+ *
+ * @param id 音乐ID
+ * @return 响应结果
+ */
+ @SaCheckRole("admin")
+ @DeleteMapping("/{id}")
+ public Result deleteMusic(@PathVariable Long id) {
+ boolean result = musicService.deleteMusic(id);
+ return Result.success("删除成功", result);
+ }
+
+ /**
+ * 收藏/取消收藏音乐
+ *
+ * @param id 音乐ID
+ * @return 响应结果
+ */
+ @SaCheckLogin
+ @PostMapping("/{id}/collect")
+ public Result toggleCollectMusic(@PathVariable Long id) {
+ // 获取当前登录用户ID
+ Long userId = StpUtil.getLoginIdAsLong();
+ boolean isCollected = musicService.toggleCollectMusic(id, userId);
+ String message = isCollected ? "收藏成功" : "取消收藏成功";
+ return Result.success(message, isCollected);
+ }
+
+ /**
+ * 获取用户收藏的音乐列表
+ *
+ * @param page 页码
+ * @param size 每页大小
+ * @return 响应结果
+ */
+ @SaCheckLogin
+ @GetMapping("/collect")
+ public Result> getCollectedMusic(
+ @RequestParam(defaultValue = "1") Integer page,
+ @RequestParam(defaultValue = "10") Integer size) {
+ // 获取当前登录用户ID
+ Long userId = StpUtil.getLoginIdAsLong();
+ PageResult pageResult = musicService.getCollectedMusic(userId, page, size);
+ return Result.success(pageResult);
+ }
+
+ /**
+ * 播放音乐
+ *
+ * @param id 音乐ID
+ * @return 响应结果
+ */
+ @PostMapping("/{id}/play")
+ public Result playMusic(@PathVariable Long id) {
+ MusicDTO musicDTO = musicService.playMusic(id);
+ return Result.success(musicDTO);
+ }
+}
diff --git a/music-houduan/src/main/java/com/test/musichouduan/controller/PlaylistController.java b/music-houduan/src/main/java/com/test/musichouduan/controller/PlaylistController.java
new file mode 100644
index 0000000..b80a6ed
--- /dev/null
+++ b/music-houduan/src/main/java/com/test/musichouduan/controller/PlaylistController.java
@@ -0,0 +1,256 @@
+package com.test.musichouduan.controller;
+
+import cn.dev33.satoken.annotation.SaCheckLogin;
+import cn.dev33.satoken.annotation.SaCheckRole;
+import com.test.musichouduan.dto.PageResult;
+import com.test.musichouduan.dto.PlaylistDTO;
+import com.test.musichouduan.dto.Result;
+import com.test.musichouduan.service.PlaylistService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.List;
+
+/**
+ * 歌单控制器
+ */
+@RestController
+@RequestMapping("/api/playlist")
+public class PlaylistController {
+
+ @Autowired
+ private PlaylistService playlistService;
+
+ /**
+ * 根据ID获取歌单
+ *
+ * @param id 歌单ID
+ * @return 响应结果
+ */
+ @GetMapping("/{id}")
+ public Result getPlaylistById(@PathVariable Long id) {
+ PlaylistDTO playlistDTO = playlistService.getPlaylistById(id);
+ return Result.success(playlistDTO);
+ }
+
+ /**
+ * 分页获取歌单列表
+ *
+ * @param page 页码
+ * @param size 每页大小
+ * @param keyword 关键字
+ * @param typeId 类型ID
+ * @return 响应结果
+ */
+ @GetMapping("/list")
+ public Result> getPlaylistList(
+ @RequestParam(defaultValue = "1") Integer page,
+ @RequestParam(defaultValue = "10") Integer size,
+ @RequestParam(required = false) String keyword,
+ @RequestParam(required = false) Long typeId) {
+ PageResult pageResult = playlistService.getPlaylistList(page, size, keyword, typeId);
+ return Result.success(pageResult);
+ }
+
+ /**
+ * 获取最新歌单列表
+ *
+ * @param limit 限制数量
+ * @return 响应结果
+ */
+ @GetMapping("/latest")
+ public Result> getLatestPlaylist(@RequestParam(defaultValue = "10") Integer limit) {
+ List playlistList = playlistService.getLatestPlaylist(limit);
+ return Result.success(playlistList);
+ }
+
+ /**
+ * 获取热门歌单列表
+ *
+ * @param limit 限制数量
+ * @return 响应结果
+ */
+ @GetMapping("/hot")
+ public Result> getHotPlaylist(@RequestParam(defaultValue = "10") Integer limit) {
+ List playlistList = playlistService.getHotPlaylist(limit);
+ return Result.success(playlistList);
+ }
+
+ /**
+ * 搜索歌单
+ *
+ * @param keyword 关键字
+ * @param page 页码
+ * @param size 每页大小
+ * @return 响应结果
+ */
+ @GetMapping("/search")
+ public Result> searchPlaylist(
+ @RequestParam String keyword,
+ @RequestParam(defaultValue = "1") Integer page,
+ @RequestParam(defaultValue = "10") Integer size) {
+ PageResult pageResult = playlistService.getPlaylistList(page, size, keyword, null);
+ return Result.success(pageResult);
+ }
+
+ /**
+ * 获取官方歌单列表
+ *
+ * @param page 页码
+ * @param size 每页大小
+ * @return 响应结果
+ */
+ @GetMapping("/official")
+ public Result> getOfficialPlaylist(
+ @RequestParam(defaultValue = "1") Integer page,
+ @RequestParam(defaultValue = "10") Integer size) {
+ PageResult pageResult = playlistService.getOfficialPlaylist(page, size);
+ return Result.success(pageResult);
+ }
+
+ /**
+ * 添加歌单
+ *
+ * @param playlistDTO 歌单DTO
+ * @param cover 封面文件
+ * @return 响应结果
+ */
+ @SaCheckLogin
+ @PostMapping("/add")
+ public Result addPlaylist(
+ @RequestPart("playlist") PlaylistDTO playlistDTO,
+ @RequestPart(value = "cover", required = false) MultipartFile cover) {
+ PlaylistDTO result = playlistService.addPlaylist(playlistDTO, cover);
+ return Result.success("添加成功", result);
+ }
+
+ /**
+ * 更新歌单
+ *
+ * @param id 歌单ID
+ * @param playlistDTO 歌单DTO
+ * @param cover 封面文件
+ * @return 响应结果
+ */
+ @SaCheckLogin
+ @PutMapping("/{id}")
+ public Result updatePlaylist(
+ @PathVariable Long id,
+ @RequestPart("playlist") PlaylistDTO playlistDTO,
+ @RequestPart(value = "cover", required = false) MultipartFile cover) {
+ PlaylistDTO result = playlistService.updatePlaylist(id, playlistDTO, cover);
+ return Result.success("更新成功", result);
+ }
+
+ /**
+ * 删除歌单
+ *
+ * @param id 歌单ID
+ * @return 响应结果
+ */
+ @SaCheckLogin
+ @DeleteMapping("/{id}")
+ public Result deletePlaylist(@PathVariable Long id) {
+ boolean result = playlistService.deletePlaylist(id);
+ return Result.success("删除成功", result);
+ }
+
+ /**
+ * 收藏歌单
+ *
+ * @param id 歌单ID
+ * @return 响应结果
+ */
+ @SaCheckLogin
+ @PostMapping("/{id}/collect")
+ public Result collectPlaylist(@PathVariable Long id) {
+ boolean result = playlistService.collectPlaylist(id);
+ return Result.success("收藏成功", result);
+ }
+
+ /**
+ * 取消收藏歌单
+ *
+ * @param id 歌单ID
+ * @return 响应结果
+ */
+ @SaCheckLogin
+ @DeleteMapping("/{id}/collect")
+ public Result uncollectPlaylist(@PathVariable Long id) {
+ boolean result = playlistService.uncollectPlaylist(id);
+ return Result.success("取消收藏成功", result);
+ }
+
+ /**
+ * 获取用户收藏的歌单列表
+ *
+ * @param page 页码
+ * @param size 每页大小
+ * @return 响应结果
+ */
+ @SaCheckLogin
+ @GetMapping("/collect")
+ public Result> getCollectedPlaylist(
+ @RequestParam(defaultValue = "1") Integer page,
+ @RequestParam(defaultValue = "10") Integer size) {
+ PageResult pageResult = playlistService.getCollectedPlaylist(page, size);
+ return Result.success(pageResult);
+ }
+
+ /**
+ * 获取用户创建的歌单列表
+ *
+ * @param page 页码
+ * @param size 每页大小
+ * @return 响应结果
+ */
+ @SaCheckLogin
+ @GetMapping("/user")
+ public Result> getUserPlaylist(
+ @RequestParam(defaultValue = "1") Integer page,
+ @RequestParam(defaultValue = "10") Integer size) {
+ PageResult pageResult = playlistService.getUserPlaylist(page, size);
+ return Result.success(pageResult);
+ }
+
+ /**
+ * 向歌单添加音乐
+ *
+ * @param id 歌单ID
+ * @param musicId 音乐ID
+ * @return 响应结果
+ */
+ @SaCheckLogin
+ @PostMapping("/{id}/music/{musicId}")
+ public Result addMusicToPlaylist(@PathVariable Long id, @PathVariable Long musicId) {
+ boolean result = playlistService.addMusicToPlaylist(id, musicId);
+ return Result.success("添加成功", result);
+ }
+
+ /**
+ * 从歌单移除音乐
+ *
+ * @param id 歌单ID
+ * @param musicId 音乐ID
+ * @return 响应结果
+ */
+ @SaCheckLogin
+ @DeleteMapping("/{id}/music/{musicId}")
+ public Result removeMusicFromPlaylist(@PathVariable Long id, @PathVariable Long musicId) {
+ boolean result = playlistService.removeMusicFromPlaylist(id, musicId);
+ return Result.success("移除成功", result);
+ }
+
+ /**
+ * 播放歌单
+ *
+ * @param id 歌单ID
+ * @return 响应结果
+ */
+ @PostMapping("/{id}/play")
+ public Result playPlaylist(@PathVariable Long id) {
+ PlaylistDTO playlistDTO = playlistService.playPlaylist(id);
+ return Result.success(playlistDTO);
+ }
+}
diff --git a/music-houduan/src/main/java/com/test/musichouduan/controller/SingerController.java b/music-houduan/src/main/java/com/test/musichouduan/controller/SingerController.java
new file mode 100644
index 0000000..fd09ece
--- /dev/null
+++ b/music-houduan/src/main/java/com/test/musichouduan/controller/SingerController.java
@@ -0,0 +1,215 @@
+package com.test.musichouduan.controller;
+
+import cn.dev33.satoken.annotation.SaCheckLogin;
+import cn.dev33.satoken.annotation.SaCheckRole;
+import com.test.musichouduan.dto.PageResult;
+import com.test.musichouduan.dto.Result;
+import com.test.musichouduan.dto.SingerDTO;
+import com.test.musichouduan.service.SingerService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.List;
+
+/**
+ * 歌手控制器
+ */
+@RestController
+@RequestMapping("/api/singer")
+public class SingerController {
+
+ @Autowired
+ private SingerService singerService;
+
+ /**
+ * 根据ID获取歌手
+ *
+ * @param id 歌手ID
+ * @return 响应结果
+ */
+ @GetMapping("/{id}")
+ public Result getSingerById(@PathVariable Long id) {
+ SingerDTO singerDTO = singerService.getSingerById(id);
+ return Result.success(singerDTO);
+ }
+
+ /**
+ * 分页获取歌手列表
+ *
+ * @param page 页码
+ * @param size 每页大小
+ * @param keyword 关键字
+ * @param typeId 类型ID
+ * @return 响应结果
+ */
+ @GetMapping("/list")
+ public Result> getSingerList(
+ @RequestParam(defaultValue = "1") Integer page,
+ @RequestParam(defaultValue = "10") Integer size,
+ @RequestParam(required = false) String keyword,
+ @RequestParam(required = false) Long typeId) {
+ PageResult pageResult = singerService.getSingerList(page, size, keyword, typeId);
+ return Result.success(pageResult);
+ }
+
+ /**
+ * 搜索歌手
+ *
+ * @param keyword 关键字
+ * @param page 页码
+ * @param size 每页大小
+ * @return 响应结果
+ */
+ @GetMapping("/search")
+ public Result> searchSinger(
+ @RequestParam String keyword,
+ @RequestParam(defaultValue = "1") Integer page,
+ @RequestParam(defaultValue = "10") Integer size) {
+ PageResult pageResult = singerService.getSingerList(page, size, keyword, null);
+ return Result.success(pageResult);
+ }
+
+ /**
+ * 获取最新歌手列表
+ *
+ * @param limit 限制数量
+ * @return 响应结果
+ */
+ @GetMapping("/latest")
+ public Result> getLatestSinger(@RequestParam(defaultValue = "10") Integer limit) {
+ List singerList = singerService.getLatestSinger(limit);
+ return Result.success(singerList);
+ }
+
+ /**
+ * 获取热门歌手列表
+ *
+ * @param limit 限制数量
+ * @return 响应结果
+ */
+ @GetMapping("/hot-list")
+ public Result> getHotSinger(@RequestParam(defaultValue = "10") Integer limit) {
+ List singerList = singerService.getHotSinger(limit);
+ return Result.success(singerList);
+ }
+
+ /**
+ * 添加歌手
+ *
+ * @param singerDTO 歌手DTO
+ * @param avatar 头像文件
+ * @return 响应结果
+ */
+ @SaCheckRole("admin")
+ @PostMapping("/add")
+ public Result addSinger(
+ @RequestPart("singer") SingerDTO singerDTO,
+ @RequestPart(value = "avatar", required = false) MultipartFile avatar) {
+ SingerDTO result = singerService.addSinger(singerDTO, avatar);
+ return Result.success("添加成功", result);
+ }
+
+ /**
+ * 更新歌手
+ *
+ * @param id 歌手ID
+ * @param singerDTO 歌手DTO
+ * @param avatar 头像文件
+ * @return 响应结果
+ */
+ @SaCheckRole("admin")
+ @PutMapping("/{id}")
+ public Result updateSinger(
+ @PathVariable Long id,
+ @RequestPart("singer") SingerDTO singerDTO,
+ @RequestPart(value = "avatar", required = false) MultipartFile avatar) {
+ SingerDTO result = singerService.updateSinger(id, singerDTO, avatar);
+ return Result.success("更新成功", result);
+ }
+
+ /**
+ * 删除歌手
+ *
+ * @param id 歌手ID
+ * @return 响应结果
+ */
+ @SaCheckRole("admin")
+ @DeleteMapping("/{id}")
+ public Result deleteSinger(@PathVariable Long id) {
+ boolean result = singerService.deleteSinger(id);
+ return Result.success("删除成功", result);
+ }
+
+ /**
+ * 收藏歌手
+ *
+ * @param id 歌手ID
+ * @return 响应结果
+ */
+ @SaCheckLogin
+ @PostMapping("/{id}/collect")
+ public Result collectSinger(@PathVariable Long id) {
+ boolean result = singerService.collectSinger(id);
+ return Result.success("收藏成功", result);
+ }
+
+ /**
+ * 取消收藏歌手
+ *
+ * @param id 歌手ID
+ * @return 响应结果
+ */
+ @SaCheckLogin
+ @DeleteMapping("/{id}/collect")
+ public Result uncollectSinger(@PathVariable Long id) {
+ boolean result = singerService.uncollectSinger(id);
+ return Result.success("取消收藏成功", result);
+ }
+
+ /**
+ * 获取用户收藏的歌手列表
+ *
+ * @param page 页码
+ * @param size 每页大小
+ * @return 响应结果
+ */
+ @SaCheckLogin
+ @GetMapping("/collect")
+ public Result> getCollectedSinger(
+ @RequestParam(defaultValue = "1") Integer page,
+ @RequestParam(defaultValue = "10") Integer size) {
+ PageResult pageResult = singerService.getCollectedSinger(page, size);
+ return Result.success(pageResult);
+ }
+
+ /**
+ * 添加音乐到歌手
+ * @param singerId 歌手ID
+ * @param musicId 音乐ID
+ * @return 响应结果
+ */
+ @SaCheckRole("admin")
+ @PostMapping("/{singerId}/music/{musicId}")
+ public Result addMusicToSinger(
+ @PathVariable Long singerId,
+ @PathVariable Long musicId) {
+ boolean result = singerService.addMusicToSinger(singerId, musicId);
+ return Result.success("添加成功", result);
+ }
+
+ /**
+ * 从歌手移除音乐
+ * @param singerId 歌手ID
+ * @param musicId 音乐ID
+ * @return 响应结果
+ */
+ @SaCheckRole("admin")
+ @DeleteMapping("/{singerId}/music/{musicId}")
+ public Result removeMusicFromSinger(
+ @PathVariable Long singerId,
+ @PathVariable Long musicId) {
+ boolean result = singerService.removeMusicFromSinger(singerId, musicId);
+ return Result.success("移除成功", result);
+ }
+}
diff --git a/music-houduan/src/main/java/com/test/musichouduan/controller/StatController.java b/music-houduan/src/main/java/com/test/musichouduan/controller/StatController.java
new file mode 100644
index 0000000..cf0842e
--- /dev/null
+++ b/music-houduan/src/main/java/com/test/musichouduan/controller/StatController.java
@@ -0,0 +1,94 @@
+package com.test.musichouduan.controller;
+
+import cn.dev33.satoken.annotation.SaCheckRole;
+import com.test.musichouduan.dto.Result;
+import com.test.musichouduan.service.StatService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Map;
+
+/**
+ * 统计控制器
+ */
+@RestController
+@RequestMapping("/api/stat")
+@SaCheckRole("admin")
+public class StatController {
+
+ @Autowired
+ private StatService statService;
+
+ /**
+ * 获取总体统计数据
+ *
+ * @return 响应结果
+ */
+ @GetMapping("/total")
+ public Result