增加付费片单,修复种子列表搜索排序
Change-Id: Ib645906c0f240f954676790daf2ff0e5f16f6e0a
diff --git a/src/main/java/com/example/myproject/controller/FileController.java b/src/main/java/com/example/myproject/controller/FileController.java
new file mode 100644
index 0000000..169d8e8
--- /dev/null
+++ b/src/main/java/com/example/myproject/controller/FileController.java
@@ -0,0 +1,34 @@
+package com.example.myproject.controller;
+
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.lang.UUID;
+import com.example.myproject.common.base.Result;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+@RestController
+@RequestMapping("/file")
+public class FileController {
+ @PostMapping
+ public Result upload(MultipartFile file){
+ try{
+ String originalFilename = file.getOriginalFilename();
+ String fileName = FileUtil.mainName(originalFilename) + UUID.fastUUID().toString() + "." + FileUtil.getSuffix(originalFilename); // 以用户ID作为文件名
+ Path path = Paths.get("uploads/" + fileName);
+ Files.createDirectories(path.getParent());
+ Files.write(path, file.getBytes());
+ String filepath = "/uploads/" + fileName;
+ return Result.ok(filepath); // 返回相对URL路径
+
+ }catch (Exception ignore){
+ return Result.failure("文件上传失败");
+ }
+
+ }
+}
diff --git a/src/main/java/com/example/myproject/controller/GroupController.java b/src/main/java/com/example/myproject/controller/GroupController.java
index a0830b6..c9b0ea7 100644
--- a/src/main/java/com/example/myproject/controller/GroupController.java
+++ b/src/main/java/com/example/myproject/controller/GroupController.java
@@ -1,5 +1,8 @@
package com.example.myproject.controller;
+import cn.dev33.satoken.annotation.SaCheckLogin;
+import cn.dev33.satoken.annotation.SaCheckRole;
+import cn.dev33.satoken.annotation.SaMode;
import com.example.myproject.entity.Group;
import com.example.myproject.entity.GroupComments;
import com.example.myproject.service.GroupService;
@@ -19,6 +22,8 @@
private GroupService groupService;
@PostMapping("/createGroup")
+ @SaCheckLogin
+ @SaCheckRole(value = { "chocolate", "ice-cream"}, mode = SaMode.OR)
public ResponseEntity<Map<String, Object>> createGroup(@RequestBody Group groupRequest) {
// 调用服务层方法创建小组
System.out.println("Received group name: " + groupRequest.getGroupName());
@@ -28,6 +33,8 @@
// 加入小组接口
@PostMapping("/{group_id}/join")
+ @SaCheckLogin
+ @SaCheckRole(value = {"chocolate", "ice-cream"}, mode = SaMode.OR)
public ResponseEntity<Map<String, Object>> joinGroup(@PathVariable("group_id") Long groupId,
@RequestBody Map<String, Long> requestBody) {
Long userId = requestBody.get("user_id");
@@ -36,6 +43,8 @@
// 退出小组接口
@PostMapping("/{group_id}/leave")
+ @SaCheckLogin
+ @SaCheckRole(value = { "chocolate", "ice-cream"}, mode = SaMode.OR)
public ResponseEntity<Map<String, Object>> leaveGroup(@PathVariable("group_id") Long groupId,
@RequestBody Map<String, Long> requestBody) {
Long userId = requestBody.get("user_id");
@@ -50,6 +59,8 @@
//发布帖子
@PostMapping("/{group_id}/createPost")
+ @SaCheckLogin
+ @SaCheckRole(value = { "chocolate", "ice-cream"}, mode = SaMode.OR)
public ResponseEntity<Map<String, Object>> createPost(
@PathVariable("group_id") Long groupId,
@RequestParam("user_id") Long userId,
@@ -77,6 +88,8 @@
// 点赞帖子
@PostMapping("/{group_post_id}/like")
+ @SaCheckLogin
+ @SaCheckRole(value = { "chocolate", "ice-cream"}, mode = SaMode.OR)
public ResponseEntity<Map<String, Object>> likePost(
@PathVariable("group_post_id") Long groupPostId) {
Map<String, Object> response = groupService.likePost(groupPostId);
@@ -85,6 +98,8 @@
// 取消点赞
@PostMapping("/{group_post_id}/unlike")
+ @SaCheckLogin
+ @SaCheckRole(value = {"chocolate", "ice-cream"}, mode = SaMode.OR)
public ResponseEntity<Map<String, Object>> unlikePost(
@PathVariable("group_post_id") Long groupPostId) {
Map<String, Object> response = groupService.unlikePost(groupPostId);
@@ -93,6 +108,8 @@
// 添加评论接口
@PostMapping("/{group_post_id}/comment")
+ @SaCheckLogin
+ @SaCheckRole(value = { "chocolate", "ice-cream"}, mode = SaMode.OR)
public ResponseEntity<Map<String, Object>> addComment(
@PathVariable("group_post_id") Long postId,
diff --git a/src/main/java/com/example/myproject/controller/PlaylistController.java b/src/main/java/com/example/myproject/controller/PlaylistController.java
new file mode 100644
index 0000000..240eeeb
--- /dev/null
+++ b/src/main/java/com/example/myproject/controller/PlaylistController.java
@@ -0,0 +1,97 @@
+package com.example.myproject.controller;
+
+import java.util.List;
+
+import javax.validation.Valid;
+
+import cn.dev33.satoken.annotation.SaCheckRole;
+import cn.dev33.satoken.annotation.SaMode;
+import org.springframework.data.domain.Page;
+import org.springframework.web.bind.annotation.*;
+
+import com.example.myproject.common.base.ResPage;
+import com.example.myproject.common.base.Result;
+import com.example.myproject.dto.CreatePlaylistRequest;
+import com.example.myproject.dto.PagePlaylistDto;
+import com.example.myproject.dto.PlaylistDetail;
+import com.example.myproject.dto.QueryPlaylistRequest;
+import com.example.myproject.dto.UpdatedPlaylistRequest;
+import com.example.myproject.entity.PaidPlaylistEntity;
+import com.example.myproject.service.PlaylistService;
+
+import cn.dev33.satoken.annotation.SaCheckLogin;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+
+@RestController
+@Slf4j
+@RequiredArgsConstructor
+@RequestMapping("/playlist")
+@SaCheckLogin
+@Api(tags = "片单管理")
+public class PlaylistController {
+ private final PlaylistService playlistService;
+
+ // 创建片单
+ @PostMapping
+ @ApiOperation("创建片单")
+ public Result<PaidPlaylistEntity> createPlayList(
+ @RequestBody @Valid @ApiParam("创建片单请求") CreatePlaylistRequest request) {
+ return Result.ok(playlistService.createPlaylist(request));
+ }
+
+ // 修改片单
+ @PutMapping
+ @ApiOperation("修改片单")
+ public Result<PaidPlaylistEntity> updatePlayList(
+ @RequestBody @Valid @ApiParam("更新片单请求") UpdatedPlaylistRequest request) {
+ return Result.ok(playlistService.updatePlaylist(request));
+ }
+
+ // 删除片单
+ @DeleteMapping
+ @ApiOperation("删除片单")
+ public Result<Void> removePlaylists(@RequestParam @ApiParam("片单ID列表") List<Long> ids) {
+ playlistService.removePlaylists(ids);
+ return Result.ok();
+ }
+
+ // 片单分页
+ @GetMapping("/page")
+ @ApiOperation("片单分页")
+ public Result getPlaylists(@Valid @ModelAttribute QueryPlaylistRequest request) {
+ try {
+ Page<PagePlaylistDto> playlists = playlistService.getPlaylists(request);
+ List<PagePlaylistDto> list = playlists.get().toList();
+ return Result.ok(list, new ResPage(playlists.getTotalElements(), request.getPage(), request.getSize()));
+ } catch (Exception e) {
+ e.printStackTrace();
+ return Result.error("服务器异常:" + e.getMessage());
+
+ }
+ }
+
+
+ // 支付片单
+ // 扣除用户余额就行
+ @PostMapping("/{id:\\d+}/pay")
+ @ApiOperation("支付片单")
+ @SaCheckLogin
+ @SaCheckRole(value = {"cookie", "chocolate", "ice-cream"}, mode = SaMode.OR)
+ public Result<Void> payPlaylist(@PathVariable @ApiParam("片单ID") Long id) {
+ playlistService.payPlaylist(id);
+ return Result.ok();
+ }
+
+ // 片单详情
+ // 购买过后才能查看片单
+ @GetMapping("/{id:\\d+}")
+ @ApiOperation("获取片单详情")
+ public Result<PlaylistDetail> getDetail(@PathVariable @ApiParam("片单ID") Long id) {
+ return Result.ok(playlistService.getDetail(id));
+ }
+
+}
diff --git a/src/main/java/com/example/myproject/controller/SeedRatingController.java b/src/main/java/com/example/myproject/controller/SeedRatingController.java
index 16e0b22..879b4a3 100644
--- a/src/main/java/com/example/myproject/controller/SeedRatingController.java
+++ b/src/main/java/com/example/myproject/controller/SeedRatingController.java
@@ -1,5 +1,8 @@
package com.example.myproject.controller;
+import cn.dev33.satoken.annotation.SaCheckLogin;
+import cn.dev33.satoken.annotation.SaCheckRole;
+import cn.dev33.satoken.annotation.SaMode;
import com.example.myproject.service.SeedRatingService;
import org.springframework.web.bind.annotation.*;
@@ -7,6 +10,8 @@
@RestController
@RequestMapping("/echo/ratings")
+@SaCheckLogin
+@SaCheckRole(value = {"cookie", "chocolate", "ice-cream"}, mode = SaMode.OR)
public class SeedRatingController {
private final SeedRatingService ratingService;
diff --git a/src/main/java/com/example/myproject/controller/TorrentController.java b/src/main/java/com/example/myproject/controller/TorrentController.java
index c0e4e86..99573a3 100644
--- a/src/main/java/com/example/myproject/controller/TorrentController.java
+++ b/src/main/java/com/example/myproject/controller/TorrentController.java
@@ -1,12 +1,16 @@
package com.example.myproject.controller;
+import cn.dev33.satoken.annotation.SaCheckRole;
+import cn.dev33.satoken.annotation.SaMode;
import cn.hutool.core.util.StrUtil;
import com.example.myproject.common.base.PageUtil;
import com.example.myproject.dto.TrackerProtocol;
import com.example.myproject.entity.TorrentEntity;
import com.example.myproject.entity.TorrentReport;
+import com.example.myproject.exception.BusinessException;
import com.example.myproject.mapper.UserMapper;
import com.example.myproject.repository.TorrentReportRepository;
+import com.example.myproject.service.LevelService;
import com.example.myproject.service.TorrentService;
import com.example.myproject.service.PromotionService;
import com.example.myproject.dto.param.TorrentParam;
@@ -76,6 +80,9 @@
@Autowired
private UserRepository userRepository;
+ @Autowired
+ private LevelService levelService;
+
@SaCheckLogin
@Operation(summary = "种子列表查询", description = "种子列表条件查询-分页-排序")
@ApiResponse(responseCode = "0", description = "操作成功",
@@ -83,11 +90,15 @@
schema = @Schema(implementation = TorrentVO.class))
})
@GetMapping("/list")
- public Result list( TorrentParam param) {
- // 构建排序和模糊查询条件
- param.validOrder(param.getOrderKey(TorrentEntity.class));
+ @SaCheckRole(value = {"candy", "cookie", "chocolate", "ice-cream"}, mode = SaMode.OR)
+ public Result list(TorrentParam param) {
+ // 校验排序字段和规则
+ param.validOrder();
+
+ // 构建模糊查询条件
param.buildLike();
+ // 启动分页
PageUtil.startPage(param);
// 查询数据
@@ -115,12 +126,15 @@
@Operation(summary = "上传种子")
@PostMapping("/upload")
+// @SaCheckRole(value = {"cookie", "chocolate", "ice-cream"}, mode = SaMode.OR)
public Result uploadTorrent(
@RequestParam("file") MultipartFile file,
@RequestParam("coverImage") MultipartFile coverImage,
@ModelAttribute @Validated TorrentUploadParam param,
HttpServletRequest request
- ) throws IOException {
+ ) {
+ // 代码形式替换
+ StpUtil.checkRoleOr("cookie", "chocolate", "ice-cream");
try {
// 验证用户权限
// Long userId = StpUtil.getLoginIdAsLong();
@@ -144,7 +158,6 @@
return Result.error("仅支持 JPG/PNG 格式的封面图片");
}
-
// 项目根目录下的 /uploads/torrents/
String uploadDir = System.getProperty("user.dir") + "/uploads/torrents/";
File dir = new File(uploadDir);
@@ -155,13 +168,17 @@
String imageUrl = request.getScheme() + "://" + request.getServerName() + ":" +
request.getServerPort() + "/uploads/torrents/" + fileName;
-// String imageUrl ="/uploads/torrents/" + fileName;
+
+
+
param.setImageUrl(imageUrl);
}
torrentService.uploadTorrent(file, param);
- return Result.ok();
- } catch (Exception e) {
+ Map<String, Object> result = levelService.updateExperience(Long.valueOf(userId), 20, "upload_torrent");
+ return Result.ok(result);
+// return Result.ok();
+ } catch (IOException e) {
return Result.error("种子上传失败: " + e.getMessage());
}
}
@@ -183,6 +200,15 @@
return;
}
+ // 判断该种子是否付费,然后再调用 StpUtil.checkRoleOr("chocolate", "ice-cream") 判断是否有权限
+ if(torrentService.needPay(entity.getId()) ){
+ StpUtil.checkRoleOr("chocolate", "ice-cream");// 这里没有权限就会报错
+ // 检查用户是否购买该种子
+ if (!torrentService.isPaid(entity.getId())) {
+ throw new BusinessException("您还未购买该种子");
+ }
+ }
+
// 获取并处理种子文件内容(需在service中实现passkey注入)
byte[] torrentBytes = torrentService.fetch(seedId, passkey);