我是人,我提交了悬赏功能哦!悬赏功能是:1.人可以发布悬赏 2.人可以回复悬赏 3.只有回复人和悬赏发布者可以下载回复的附件

Change-Id: I269fb69c6ee4dd695a38fa0c91fa8fbe72fc5322
diff --git a/ruoyi-system/src/main/java/bounty/controller/BountyController.java b/ruoyi-system/src/main/java/bounty/controller/BountyController.java
new file mode 100644
index 0000000..7c47e1b
--- /dev/null
+++ b/ruoyi-system/src/main/java/bounty/controller/BountyController.java
@@ -0,0 +1,52 @@
+package bounty.controller;
+
+import bounty.domain.Bounty;
+import bounty.domain.BountySubmission;
+import bounty.service.BountyService;
+import bounty.service.BountySubmissionService;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+import java.util.List;
+
+// 悬赏 Controller 类
+@RestController
+@RequestMapping("/bounties")
+public class BountyController {
+    @Autowired
+    private BountyService bountyService;
+
+    @PostMapping
+    public ResponseEntity<?> saveBounty(@RequestBody Bounty bounty) {
+        boolean result = bountyService.saveBounty(bounty);
+        if (result) {
+            return ResponseEntity.ok().build();
+        } else {
+            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
+        }
+    }
+    @GetMapping
+    // 导入 List 类
+    public List<Bounty> getBounties() {  // 移除分页参数,返回 List 而非 IPage
+        return bountyService.getBounties();  // 调用无分页的 Service 方法
+    }
+
+    @GetMapping("/{id}")
+    public ResponseEntity<Bounty> getBountyById(@PathVariable Long id) {
+        Bounty bounty = bountyService.getBountyById(id);
+        if (bounty == null) {
+            return ResponseEntity.notFound().build();
+        } else {
+            return ResponseEntity.ok(bounty);
+        }
+    }
+    // 新增:发布悬赏接口
+    @PostMapping("/publish")
+    public boolean publishBounty(@RequestBody Bounty bounty) {
+        return bountyService.publishBounty(bounty);
+    }
+}
+
diff --git a/ruoyi-system/src/main/java/bounty/controller/BountySubmissionController.java b/ruoyi-system/src/main/java/bounty/controller/BountySubmissionController.java
new file mode 100644
index 0000000..c8098f1
--- /dev/null
+++ b/ruoyi-system/src/main/java/bounty/controller/BountySubmissionController.java
@@ -0,0 +1,142 @@
+package bounty.controller;
+
+import bounty.domain.BountySubmission;
+import bounty.service.BountySubmissionService;
+import bounty.service.FileStorageService;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import jakarta.validation.Valid;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.UrlResource;
+import org.springframework.http.*;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.net.MalformedURLException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.Map;
+
+// 悬赏提交 Controller 类
+@RestController
+@RequestMapping("/bounty-submissions")
+public class BountySubmissionController {
+
+    @Autowired
+    private FileStorageService fileStorageService;
+
+
+
+    // BountySubmission.java
+    private String attachment; // 存储文件路径(如 /uploads/filename.ext)
+
+
+    @Autowired
+    private BountySubmissionService bountySubmissionService;
+
+
+    @PostMapping
+    public ResponseEntity<?> saveBountySubmission(
+            @RequestPart("submission") @Valid BountySubmission submission,
+            @RequestPart("file") MultipartFile file) {
+
+        try {
+            String filePath = fileStorageService.saveFile(file);
+            submission.setAttachment(filePath);
+            boolean saveResult = bountySubmissionService.saveBountySubmission(submission);
+
+            if (saveResult) {
+                return ResponseEntity.ok().body(Map.of("code", 200, "message", "提交成功", "data", submission));
+            } else {
+                return ResponseEntity.status(500).body(Map.of("code", 500, "message", "提交失败"));
+            }
+        } catch (Exception e) {
+            return ResponseEntity.status(500).body(Map.of("code", 500, "message", e.getMessage()));
+        }
+    }
+
+    @GetMapping
+    public IPage<BountySubmission> getBountySubmissions(
+            @RequestParam(defaultValue = "1") long current,
+            @RequestParam(defaultValue = "10") long size,
+            @RequestParam Long bountyId) {
+        Page<BountySubmission> page = new Page<>(current, size);
+        IPage<BountySubmission> result = bountySubmissionService.getBountySubmissionsByPage(page, bountyId);
+
+        // 👇 新增:打印分页数据
+        System.out.println("【分页数据】bountyId=" + bountyId + ", 数据量=" + result.getRecords().size());
+        result.getRecords().forEach(submission -> {
+            System.out.println("【附件路径】" + submission.getAttachment());
+        });
+
+        return result;
+    }
+
+    // ✅ 仅处理文件上传(保持原逻辑)
+    @PostMapping("/upload")
+    public String uploadAttachment(@RequestParam("file") MultipartFile file) {
+        return fileStorageService.saveFile(file);
+    }
+
+    @GetMapping("/download")
+    public ResponseEntity<Resource> downloadAttachment(@RequestParam String filename) {
+        try {
+            // ✅ 只使用文件名(避免重复拼接)
+            Path uploadDir = Paths.get("uploads/");
+            Path filePath = uploadDir.resolve(filename).normalize();
+
+            if (!filePath.startsWith(uploadDir)) {
+                return ResponseEntity.status(HttpStatus.FORBIDDEN).body(null);
+            }
+
+            Resource resource = new UrlResource(filePath.toUri());
+
+            if (resource.exists() && resource.isReadable()) {
+                HttpHeaders headers = new HttpHeaders();
+                headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
+                headers.setContentDisposition(ContentDisposition.builder("attachment")
+                        .filename(filename, StandardCharsets.UTF_8)
+                        .build());
+                return ResponseEntity.ok()
+                        .headers(headers)
+                        .body(resource);
+            } else {
+                return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
+            }
+        } catch (MalformedURLException e) {
+            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
+        }
+    }
+
+    @PutMapping("/{id}/adopt")
+    public ResponseEntity<?> adoptSubmission(@PathVariable Long id) {
+        try {
+            boolean result = bountySubmissionService.adoptSubmission(id);
+
+            // 使用 HashMap 替代 Map.of()
+            Map<String, Object> response = new HashMap<>();
+            if (result) {
+                response.put("code", 200);
+                response.put("message", "采纳成功");
+                return ResponseEntity.ok(response);
+            } else {
+                response.put("code", 500);
+                response.put("message", "采纳失败");
+                return ResponseEntity.status(500).body(response);
+            }
+        } catch (Exception e) {
+            Map<String, Object> errorResponse = new HashMap<>();
+            errorResponse.put("code", 500);
+            errorResponse.put("message", e.getMessage() != null ? e.getMessage() : "未知错误");
+
+            return ResponseEntity.status(500).body(errorResponse);
+        }
+    }
+
+
+    // BountySubmissionController.java
+
+}