种子,促销
Change-Id: I0ce919ce4228dcefec26ef636bacd3298c0dc77a
diff --git a/src/main/java/com/example/myproject/controller/TorrentController.java b/src/main/java/com/example/myproject/controller/TorrentController.java
new file mode 100644
index 0000000..cea2ccf
--- /dev/null
+++ b/src/main/java/com/example/myproject/controller/TorrentController.java
@@ -0,0 +1,293 @@
+package com.example.myproject.controller;
+
+import com.example.myproject.common.base.PageUtil;
+import com.example.myproject.entity.TorrentEntity;
+import com.example.myproject.service.TorrentService;
+import com.example.myproject.service.PromotionService;
+import com.example.myproject.dto.param.TorrentParam;
+import com.example.myproject.dto.vo.TorrentVO;
+import com.example.myproject.common.base.Result;
+import com.example.myproject.dto.param.TorrentUploadParam;
+import com.example.myproject.dto.TorrentUpdateDTO;
+import com.example.myproject.dto.PromotionCreateDTO;
+import com.example.myproject.entity.Promotion;
+import com.example.myproject.service.UserService;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.List;
+
+import cn.dev33.satoken.annotation.SaCheckLogin;
+import cn.dev33.satoken.stp.StpUtil;
+
+@RestController
+@RequestMapping("/seeds")
+public class TorrentController {
+
+ @Autowired
+ private TorrentService torrentService;
+
+ @Autowired
+ private PromotionService promotionService;
+
+ @Autowired
+ private UserService userService;
+
+
+ @SaCheckLogin
+ @Operation(summary = "种子列表查询", description = "种子列表条件查询-分页-排序")
+ @ApiResponse(responseCode = "0", description = "操作成功",
+ content = {@Content(mediaType = "application/json",
+ schema = @Schema(implementation = TorrentVO.class))
+ })
+ @PostMapping("/list")
+ public Result list(@RequestBody TorrentParam param) {
+ // 构建排序和模糊查询条件
+ param.validOrder(param.getOrderKey(TorrentEntity.class));
+ param.buildLike();
+
+ PageUtil.startPage(param);
+
+ // 查询数据
+ List<TorrentEntity> list = torrentService.search(param);
+
+ // 返回分页结果
+ return Result.ok(list, PageUtil.getPage(list));
+ }
+
+ @SaCheckLogin
+ @Operation(summary = "种子详情查询")
+ @ApiResponse(responseCode = "0", description = "操作成功", content = {
+ @Content(mediaType = "application/json", schema = @Schema(implementation =
+ TorrentEntity.class))
+ })
+ @PostMapping("/info/{id}")
+ public Result info(@PathVariable("id")Long id) {
+
+ TorrentEntity entity = torrentService.selectBySeedId(id);
+ return Result.ok(entity);
+ }
+
+@Operation(summary = "上传种子")
+
+ @PostMapping("/upload")
+ public Result uploadTorrent(
+ @RequestParam("file") MultipartFile file,
+ @ModelAttribute @Validated TorrentUploadParam param) throws IOException {
+ try {
+ // 验证用户权限
+ // Long userId = StpUtil.getLoginIdAsLong();
+ String userId = String.valueOf(param.getUploader());
+ param.setUploader(userId);
+
+ // 验证文件大小和类型
+ if (file.isEmpty() || file.getSize() > 10 * 1024 * 1024) { // 10MB限制
+ return Result.error("文件大小不符合要求");
+ }
+
+ if (!file.getOriginalFilename().toLowerCase().endsWith(".torrent")) {
+ return Result.error("只支持.torrent文件");
+ }
+
+ torrentService.uploadTorrent(file, param);
+ return Result.ok();
+ } catch (Exception e) {
+ return Result.error("种子上传失败: " + e.getMessage());
+ }
+ }
+
+ /**
+ * 获取种子文件
+ */
+ @GetMapping("/{seed_id}/download")
+ public void downloadTorrent(
+ @PathVariable("seed_id") Long seedId,
+ @RequestParam("passkey") String passkey,
+ HttpServletResponse response) throws IOException {
+
+ // 获取种子实体
+ TorrentEntity entity = torrentService.selectBySeedId(seedId);
+ if (entity == null) {
+ response.sendError(HttpServletResponse.SC_NOT_FOUND, "种子不存在");
+ return;
+ }
+
+ // 获取并处理种子文件内容(需在service中实现passkey注入)
+ byte[] torrentBytes = torrentService.fetch(seedId, passkey);
+
+ // 设置下载文件名
+ String filename = entity.getFileName();
+ if (filename == null || filename.isBlank()) {
+ filename = seedId + ".torrent";
+ }
+ if (!filename.toLowerCase().endsWith(".torrent")) {
+ filename = filename + ".torrent";
+ }
+ filename = java.net.URLEncoder.encode(filename, java.nio.charset.StandardCharsets.UTF_8).replaceAll("\\+",
+ "%20");
+
+ // 设置响应头
+ response.setCharacterEncoding(java.nio.charset.StandardCharsets.UTF_8.name());
+ response.setContentLength(torrentBytes.length);
+ response.setContentType("application/x-bittorrent");
+ response.setHeader("Content-Disposition", "attachment;filename=" + filename);
+
+ // 写入文件内容
+ response.getOutputStream().write(torrentBytes);
+ response.getOutputStream().flush();
+ }
+
+ /**
+ * 收藏或者取消收藏
+ */
+ @PostMapping("/{seed_id}/favorite-toggle")
+ public Result favorite(
+ @PathVariable("seed_id") Long seedId,
+ @RequestParam("user_id") Long userId) {
+ try {
+
+ return torrentService.favorite(seedId, userId);
+ } catch (Exception e) {
+ return Result.error("失败: ");
+ }
+ }
+
+ @SaCheckLogin
+ @Operation(summary = "删除种子")
+ @DeleteMapping("/{torrentId}")
+ public Result deleteTorrent(@PathVariable Long torrentId) {
+ try {
+ // 验证用户权限
+ Long userId = StpUtil.getLoginIdAsLong();
+ if (!torrentService.canUserDeleteTorrent(torrentId, userId)) {
+ return Result.error("没有权限删除此种子");
+ }
+
+ torrentService.deleteTorrent(torrentId);
+ return Result.ok();
+ } catch (Exception e) {
+ return Result.error("删除失败: " + e.getMessage());
+ }
+ }
+
+ @SaCheckLogin
+ @Operation(summary = "修改种子信息")
+ @PutMapping("/{torrentId}")
+ public Result updateTorrent(
+ @PathVariable Long torrentId,
+ @RequestBody @Validated TorrentUpdateDTO updateDTO) {
+ try {
+ // 验证用户权限
+ Long userId = StpUtil.getLoginIdAsLong();
+ if (!torrentService.canUserUpdateTorrent(torrentId, userId)) {
+ return Result.error("没有权限修改此种子");
+ }
+
+ torrentService.updateTorrent(torrentId, updateDTO);
+ return Result.ok();
+ } catch (Exception e) {
+ return Result.error("更新失败: " + e.getMessage());
+ }
+ }
+
+ @SaCheckLogin
+ @Operation(summary = "创建促销活动")
+ @PostMapping("/promotions")
+ public Result createPromotion(@RequestBody @Validated PromotionCreateDTO promotionDTO) {
+ try {
+ // 验证用户权限(只有管理员可以创建促销)
+// if (!StpUtil.hasRole("admin")) {
+// return Result.error("没有权限创建促销活动");
+// }
+//
+ Promotion promotion = promotionService.createPromotion(promotionDTO);
+ return Result.ok(promotion);
+ } catch (Exception e) {
+ return Result.error("创建促销失败: " + e.getMessage());
+ }
+ }
+
+ @SaCheckLogin
+ @Operation(summary = "获取促销活动列表")
+ @GetMapping("/promotions")
+ public Result getPromotions() {
+ try {
+ List<Promotion> promotions = promotionService.getAllActivePromotions();
+ return Result.ok(promotions);
+ } catch (Exception e) {
+ return Result.error("获取促销列表失败: " + e.getMessage());
+ }
+ }
+
+ @SaCheckLogin
+ @Operation(summary = "获取促销详情")
+ @GetMapping("/promotions/{promotionId}")
+ public Result getPromotionDetails(@PathVariable Long promotionId) {
+ try {
+ Promotion promotion = promotionService.getPromotionById(promotionId);
+ if (promotion == null) {
+ return Result.error("促销活动不存在");
+ }
+ return Result.ok(promotion);
+ } catch (Exception e) {
+ return Result.error("获取促销详情失败: " + e.getMessage());
+ }
+ }
+
+ @SaCheckLogin
+ @Operation(summary = "删除促销活动")
+ @DeleteMapping("/promotions/{promotionId}")
+ public Result deletePromotion(@PathVariable Long promotionId) {
+ try {
+ // 验证用户权限(只有管理员可以删除促销)
+ if (!StpUtil.hasRole("admin")) {
+ return Result.error("没有权限删除促销活动");
+ }
+
+ promotionService.deletePromotion(promotionId);
+ return Result.ok();
+ } catch (Exception e) {
+ return Result.error("删除促销失败: " + e.getMessage());
+ }
+ }
+
+ // 下载种子(包含反作弊机制)
+ @PostMapping("/{torrentId}/download")
+ public ResponseEntity<?> downloadTorrent(@PathVariable Long torrentId,
+ @RequestParam Long userId) {
+// // 验证用户身份和权限
+// if (!userService.validateUser(userId)) {
+// return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
+// }
+
+ // 检查用户上传量是否足够
+ if (!torrentService.checkUserUploadRatio(userId)) {
+ return ResponseEntity.status(HttpStatus.FORBIDDEN)
+ .body("上传量不足,无法下载");
+ }
+
+ // 应用促销折扣(如果有)
+ double downloadSize = torrentService.calculateDownloadSize(torrentId, userId);
+
+ // 记录下载
+ torrentService.recordDownload(torrentId, userId, downloadSize);
+
+ return ResponseEntity.ok().build();
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/example/myproject/controller/UserController.java b/src/main/java/com/example/myproject/controller/UserController.java
index 4bf6adf..acda403 100644
--- a/src/main/java/com/example/myproject/controller/UserController.java
+++ b/src/main/java/com/example/myproject/controller/UserController.java
@@ -1,16 +1,25 @@
package com.example.myproject.controller;
+import cn.dev33.satoken.annotation.SaCheckLogin;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.example.myproject.common.base.PageUtil;
+import com.example.myproject.dto.param.TorrentParam;
+import com.example.myproject.dto.vo.TorrentVO;
+import com.example.myproject.entity.TorrentEntity;
import com.example.myproject.mapper.UserMapper;
import com.example.myproject.mapper.VerificationTokenMapper;
import com.example.myproject.entity.User;
import com.example.myproject.entity.VerificationToken;
import com.example.myproject.service.EmailService;
import com.example.myproject.service.UserService;
-import com.example.myproject.utils.Result;
+import com.example.myproject.common.base.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
import org.apache.commons.lang3.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -27,6 +36,7 @@
import javax.annotation.Resource;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
+import java.util.List;
@RestController
@RequestMapping("/user")
@@ -61,9 +71,9 @@
User user = userMapper.selectOne(new QueryWrapper<User>().eq("username", username));
System.out.println("Login successful for user: " + username);
- return Result.success(user);
+ return Result.ok(user);
} catch (AuthenticationException e) {
- return Result.error("401", "登录失败:" + e.getMessage());
+ return Result.error("登录失败");
}
}
@@ -71,15 +81,15 @@
@ApiOperation(value = "用户注册", notes = "使用用户信息进行注册")
public Result registerController(@RequestBody @ApiParam(value = "新用户信息", required = true) User newUser) {
if (userService.checkEmailExists(newUser.getEmail())) {
- return Result.error("邮箱冲突", "邮箱已被使用,请使用其他邮箱注册或找回密码!");
+ return Result.error( "邮箱已被使用,请使用其他邮箱注册或找回密码!");
}
boolean success = userService.preRegisterUser(newUser);
if (success) {
User responseUser = new User();
responseUser.setEmail(newUser.getEmail());
- return Result.success(responseUser, "验证邮件已发送,请检查您的邮箱。");
+ return Result.ok();
} else {
- return Result.error("注册失败", "账号已存在或注册失败!");
+ return Result.error("账号已存在或注册失败!");
}
}
@@ -100,9 +110,9 @@
String code = verificationRequest.getCode();
boolean isVerified = userService.verifyEmail(email, code);
if (isVerified) {
- return Result.success(null, "邮箱验证成功!");
+ return Result.ok();
} else {
- return Result.error("验证失败", "验证码错误或已过期!");
+ return Result.error( "验证码错误或已过期!");
}
}
@@ -123,7 +133,7 @@
if (user == null) {
logger.error("未找到与该邮箱地址相关联的用户: {}", email);
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
- .body(Result.error("1","未找到与该邮箱地址相关联的用户"));
+ .body(Result.error("未找到与该邮箱地址相关联的用户"));
}
// 生成验证码
@@ -139,15 +149,42 @@
logger.info("验证令牌已保存,用户: {}", user.getUsername());
emailService.sendVerificationEmail(email, token);
- return ResponseEntity.ok(Result.success(200, "验证邮件已发送!"));
+ return ResponseEntity.ok(Result.ok());
}
@PostMapping("/checkPassword")
public Result<String> checkPassword(@RequestParam Long userId, @RequestParam String password) {
boolean isPasswordCorrect = userService.checkPassword(userId, password);
if (isPasswordCorrect) {
- return Result.success("200","原始密码输入正确");
+ return Result.ok();
} else {
- return Result.error("305","原始密码输入错误");
+ return Result.error("原始密码输入错误");
}
}
+
+
+// @SaCheckLogin
+// @Operation(summary = "用户收藏列表", description = "获取用户收藏的种子列表-分页-排序")
+// @ApiResponse(responseCode = "0", description = "操作成功",
+// content = {@Content(mediaType = "application/json",
+// schema = @Schema(implementation = TorrentVO.class))
+// })
+// @PostMapping("/favorite/list")
+// public Result listFavorites(@RequestBody FavoriteParam param) {
+// if (param.getUserId() == null) {
+// return Result.error("缺少 userId");
+// }
+//
+// // 校验排序字段是否合理(可选)
+// param.validOrder(param.getOrderKey(TorrentEntity.class));
+//
+// PageUtil.startPage(param);
+//
+// List<TorrentEntity> list = favoriteService.getUserFavoritesPaged(param.getUserId());
+//
+// return Result.ok(list, PageUtil.getPage(list));
+// }
+//
+
+
+
}