增加了悬赏,标签查看,评论页面,标签上传后端有问题,评论还没跟后端连,优化了一些小界面

Change-Id: I44f5ef2eb0a8ebd91a4b3b3b446f897bea41435f
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/announce/controller/AnnounceController.java b/ruoyi-admin/src/main/java/com/ruoyi/announce/controller/AnnounceController.java
index 8fbb688..f3bd624 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/announce/controller/AnnounceController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/announce/controller/AnnounceController.java
@@ -1,10 +1,7 @@
 package com.ruoyi.announce.controller;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.announce.service.IAnnounceService;
-import org.apache.commons.codec.DecoderException;
-import org.apache.commons.codec.net.URLCodec;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestParam;
@@ -13,116 +10,52 @@
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
 
-import java.io.ByteArrayOutputStream;
-import java.io.UnsupportedEncodingException;
 import java.net.URLDecoder;
 import java.nio.charset.StandardCharsets;
-import java.util.Base64;
 import java.util.Map;
-import java.util.stream.Collectors;
 
 @RestController
 public class AnnounceController extends BaseController {
-    // 在你的 Controller 中:
 
     @Autowired
     private IAnnounceService announceService;
 
-
-    private byte[] decodeInfoHashAndPeerId(String param) {
-        ByteArrayOutputStream bos = new ByteArrayOutputStream();
-        for (int i = 0; i < param.length(); ) {
-            char c = param.charAt(i);
-            if (c == '%' && i + 2 < param.length()) {
-                char hi = param.charAt(i + 1);
-                char lo = param.charAt(i + 2);
-                if (isHexDigit(hi) && isHexDigit(lo)) {
-                    int value = Character.digit(hi, 16) << 4 | Character.digit(lo, 16);
-                    bos.write(value);
-                    i += 3;
-                    continue;
-                }
-            }
-            // 不是合法的 %xx,直接跳过或处理为异常字符
-            bos.write((byte) c); // 或者 throw new IllegalArgumentException(...)
-            i++;
-        }
-        return bos.toByteArray();
-    }
-
-    private boolean isHexDigit(char c) {
-        return (c >= '0' && c <= '9') ||
-                (c >= 'A' && c <= 'F') ||
-                (c >= 'a' && c <= 'f');
-    }
-
-
     /**
      * BT Tracker /announce 接口
      * 接收客户端(qBittorrent 等)发来的 announce 请求,返回 bencoded peers 列表
      */
-
     @GetMapping(value = "/announce", produces = "application/x-bittorrent")
-    public void announce(HttpServletRequest request, HttpServletResponse response) throws Exception {
+    public void announce(
+            HttpServletRequest request,
+            HttpServletResponse response,
+            @RequestParam("info_hash") String infoHashParam,
+            @RequestParam("peer_id")   String peerIdParam,
+            @RequestParam("port")      int port,
+            @RequestParam("uploaded")  long uploaded,
+            @RequestParam("downloaded") long downloaded,
+            @RequestParam("left")      long left,
+            @RequestParam(value = "event",    required = false) String event,
+            @RequestParam("passkey")   String passkey
+    ) throws Exception {
+        // 1. URL Decode 得到原始二进制
+        byte[] infoHash = URLDecoder.decode(infoHashParam, StandardCharsets.ISO_8859_1.name())
+                .getBytes(StandardCharsets.ISO_8859_1);
+        byte[] peerId   = URLDecoder.decode(peerIdParam,   StandardCharsets.ISO_8859_1.name())
+                .getBytes(StandardCharsets.ISO_8859_1);
 
-        // —— 4. 获取参数(不使用 @RequestParam) ——
-        String infoHashParam = request.getParameter("info_hash");
-        String peerIdParam   = request.getParameter("peer_id");
-        String portStr       = request.getParameter("port");
-        String uploadedStr   = request.getParameter("uploaded");
-        String downloadedStr = request.getParameter("downloaded");
-        String leftStr       = request.getParameter("left");
-        String event         = request.getParameter("event");
-        String passkey       = request.getParameter("passkey");
-        // 打印接收到的参数
-        System.out.println("Received announce request:");
-        System.out.println("  info_hash: " + infoHashParam);
-        System.out.println("  peer_id:   " + peerIdParam);
-        System.out.println("  port:      " + portStr);
-        System.out.println("  uploaded:  " + uploadedStr);
-        System.out.println("  downloaded:" + downloadedStr);
-        System.out.println("  left:      " + leftStr);
-        System.out.println("  event:     " + event);
-        System.out.println("  passkey:   " + passkey);
-        System.out.println("  IP:        " + request.getRemoteAddr());
-        // —— 校验是否有必要参数为空 ——
-        if (infoHashParam == null || peerIdParam == null || portStr == null ||
-                uploadedStr == null || downloadedStr == null || leftStr == null) {
-            System.out.println("参数缺失,终止处理。");
-            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
-            response.setContentType("text/plain");
-            response.getWriter().write("Missing required announce parameters.");
-            return;
-        }
-
-
-
-        // —— 5. 转换参数类型 ——
-        int port = Integer.parseInt(portStr);
-        long uploaded = Long.parseLong(uploadedStr);
-        long downloaded = Long.parseLong(downloadedStr);
-        long left = Long.parseLong(leftStr);
-
-        // 确保 URL 解码不会失败,使用更健壮的方法
-        byte[] infoHash = decodeInfoHashAndPeerId(infoHashParam);
-        byte[] peerId   = decodeInfoHashAndPeerId(peerIdParam);
-
-        // —— 7. 调用业务逻辑处理 ——
+        // 2. 处理 announce 请求(验证 passkey,更新 peer 列表,获取 peers 信息)
         Map<String, Object> reply = announceService.handleAnnounce(
                 infoHash, peerId, port, uploaded, downloaded, left, event, passkey,
                 request.getRemoteAddr()
         );
 
-        // —— 8. 返回 Bencode 编码的 tracker 响应 ——
+        // 3. bencode 编码并返回给客户端
         response.setStatus(HttpServletResponse.SC_OK);
         response.setHeader("Content-Type", "application/x-bittorrent");
         try (var out = response.getOutputStream()) {
             byte[] bencoded = announceService.encodeBencode(reply);
-            System.out.println(bencoded);
-
             out.write(bencoded);
             out.flush();
         }
     }
-
 }
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/announce/service/impl/AnnounceServiceImpl.java b/ruoyi-admin/src/main/java/com/ruoyi/announce/service/impl/AnnounceServiceImpl.java
index 4408fa1..f80050f 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/announce/service/impl/AnnounceServiceImpl.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/announce/service/impl/AnnounceServiceImpl.java
@@ -6,7 +6,6 @@
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.net.InetAddress;
 import java.nio.ByteBuffer;
@@ -36,72 +35,46 @@
     ) throws Exception {
         // 1. 转 hex 作为 Redis key 前缀
         String infoHashHex = bytesToHex(infoHash);
-        String peerIdStr = new String(peerId, StandardCharsets.ISO_8859_1);
+        String peerIdStr   = new String(peerId, StandardCharsets.ISO_8859_1);
 
         // 2. 校验 passkey(可根据业务到 MySQL 查 userId,此处略过)
 
-        // 3. 在 Redis 中记录/刷新此 peer 的信息(TTL 120 秒)
+        // 3. 在 Redis 中记录/刷新此 peer 的信息
+        //    使用 Hash 存储详情,TTL 120 秒
         String peerKey = "peer:" + infoHashHex + ":" + peerIdStr;
         Map<String, Object> peerData = new HashMap<>();
-        peerData.put("ip", ip);
-        peerData.put("port", port);
-        peerData.put("uploaded", uploaded);
+        peerData.put("ip",         ip);
+        peerData.put("port",       port);
+        peerData.put("uploaded",   uploaded);
         peerData.put("downloaded", downloaded);
-        peerData.put("left", left);
-        peerData.put("lastSeen", System.currentTimeMillis());
+        peerData.put("left",       left);
+        peerData.put("lastSeen",   System.currentTimeMillis());
         redisCache.setCacheMap(peerKey, peerData);
-        redisCache.expire(peerKey, 1200, TimeUnit.SECONDS);
+        redisCache.expire(peerKey, 120, TimeUnit.SECONDS);
 
-        // 4. 收集 peers,根据自身状态区分返回哪些 peer
-        boolean isSeeder = left == 0;
+        // 4. 从 Redis 中扫描所有同 info_hash 的 peer
         Collection<String> keys = redisCache.keys("peer:" + infoHashHex + ":*");
         List<byte[]> peersBin = new ArrayList<>(keys.size());
-
         for (String key : keys) {
             @SuppressWarnings("unchecked")
             Map<String, Object> data = (Map<String, Object>) redisCache.getCacheMap(key);
-            if (data == null) continue;
-
-            String otherPeerId = key.substring(key.lastIndexOf(":") + 1);
-            if (otherPeerId.equals(peerIdStr)) continue; // 忽略自己
-
             String peerIp = (String) data.get("ip");
-            int peerPort = ((Number) data.get("port")).intValue();
-            long otherLeft = ((Number) data.get("left")).longValue();
-
-            if (peerIp.contains(":")) continue; // 跳过 IPv6
-
-            // 按条件过滤
-            if (isSeeder && otherLeft > 0) {
-                peersBin.add(encodePeer(peerIp, peerPort));
-            } else if (!isSeeder) {
-                peersBin.add(encodePeer(peerIp, peerPort));
-            }
-
-            if (peersBin.size() >= 50) break;
+            int    peerPort = ((Number) data.get("port")).intValue();
+            peersBin.add(encodePeer(peerIp, peerPort));
+            if (peersBin.size() >= 50) break;  // 最多返回 50 个 peers
         }
 
-        // 4.5 合并 peers 到 compact 格式
-        ByteArrayOutputStream peerStream = new ByteArrayOutputStream();
-        for (byte[] peer : peersBin) {
-            if (peer != null && peer.length == 6) {
-                peerStream.write(peer);
-            }
-        }
-        byte[] compactPeers = peerStream.toByteArray();
-
-        // 5. 构造返回 Map
+        // 5. 构造返回数据 Map(有序)
         Map<String, Object> reply = new LinkedHashMap<>();
         reply.put("interval", ANNOUNCE_INTERVAL);
         reply.put("min interval", ANNOUNCE_INTERVAL / 2);
-        reply.put("complete", countSeeders(infoHashHex));
+        reply.put("complete",   countSeeders(infoHashHex));
         reply.put("incomplete", countLeechers(infoHashHex));
-        reply.put("peers", compactPeers);
+        reply.put("peers",      peersBin);
 
         return reply;
     }
 
-
     @Override
     public byte[] encodeBencode(Map<String, Object> reply) throws IOException {
         BencodeEncoder encoder = new BencodeEncoder();
@@ -134,22 +107,17 @@
         return count;
     }
 
+    /** 将 IPv4 + port 编码成 6 字节:4 字节 IP + 2 字节 port */
     private byte[] encodePeer(String ip, int port) throws Exception {
-        if (ip.contains(":")) return null; // 跳过 IPv6
-
         String[] parts = ip.split("\\.");
-        if (parts.length != 4) throw new IllegalArgumentException("无效的 IPv4 地址: " + ip);
-
         ByteBuffer buf = ByteBuffer.allocate(6);
-        for (String part : parts) {
-            buf.put((byte) Integer.parseInt(part));
+        for (int i = 0; i < 4; i++) {
+            buf.put((byte) Integer.parseInt(parts[i]));
         }
         buf.putShort((short) port);
         return buf.array();
     }
 
-
-
     /** 将字节数组转成十六进制字符串 */
     private static final char[] HEX = "0123456789abcdef".toCharArray();
     private String bytesToHex(byte[] bytes) {
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/announce/util/BencodeEncoder.java b/ruoyi-admin/src/main/java/com/ruoyi/announce/util/BencodeEncoder.java
index c937042..a2cdb30 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/announce/util/BencodeEncoder.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/announce/util/BencodeEncoder.java
@@ -2,7 +2,6 @@
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
-import java.nio.charset.StandardCharsets;
 import java.util.Map;
 
 public class BencodeEncoder {
@@ -33,20 +32,11 @@
             encodeMap((Map<String, Object>) obj, outputStream);
         } else if (obj instanceof Iterable) {
             encodeList((Iterable<Object>) obj, outputStream);
-        } else if (obj instanceof byte[]) {
-            encodeByteArray((byte[]) obj, outputStream);
         } else {
             throw new IllegalArgumentException("Unsupported object type: " + obj.getClass());
         }
     }
 
-    private void encodeByteArray(byte[] bytes, ByteArrayOutputStream outputStream) throws IOException {
-        outputStream.write(Integer.toString(bytes.length).getBytes());
-        outputStream.write(':');
-        outputStream.write(bytes);
-    }
-
-
     private void encodeInteger(Integer value, ByteArrayOutputStream outputStream) throws IOException {
         outputStream.write('i');
         outputStream.write(value.toString().getBytes());
@@ -54,13 +44,11 @@
     }
 
     private void encodeString(String value, ByteArrayOutputStream outputStream) throws IOException {
-        byte[] bytes = value.getBytes(StandardCharsets.UTF_8); // Assuming UTF-8 encoding
-        outputStream.write(Integer.toString(bytes.length).getBytes());
+        outputStream.write(Integer.toString(value.length()).getBytes());
         outputStream.write(':');
-        outputStream.write(bytes);
+        outputStream.write(value.getBytes());
     }
 
-
     private void encodeList(Iterable<Object> list, ByteArrayOutputStream outputStream) throws IOException {
         outputStream.write('l'); // Start of a list
 
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/reward/controller/RewardTasksController.java b/ruoyi-admin/src/main/java/com/ruoyi/reward/controller/RewardTasksController.java
new file mode 100644
index 0000000..bae499a
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/reward/controller/RewardTasksController.java
@@ -0,0 +1,104 @@
+package com.ruoyi.reward.controller;
+
+import java.util.List;
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.reward.domain.RewardTasks;
+import com.ruoyi.reward.service.IRewardTasksService;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * 【请填写功能名称】Controller
+ * 
+ * @author ruoyi
+ * @date 2025-05-17
+ */
+@RestController
+@RequestMapping("/reward")
+public class RewardTasksController extends BaseController
+{
+    @Autowired
+    private IRewardTasksService rewardTasksService;
+
+    /**
+     * 查询【请填写功能名称】列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:tasks:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(RewardTasks rewardTasks)
+    {
+        startPage();
+        List<RewardTasks> list = rewardTasksService.selectRewardTasksList(rewardTasks);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出【请填写功能名称】列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:tasks:export')")
+    @Log(title = "【请填写功能名称】", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, RewardTasks rewardTasks)
+    {
+        List<RewardTasks> list = rewardTasksService.selectRewardTasksList(rewardTasks);
+        ExcelUtil<RewardTasks> util = new ExcelUtil<RewardTasks>(RewardTasks.class);
+        util.exportExcel(response, list, "【请填写功能名称】数据");
+    }
+
+    /**
+     * 获取【请填写功能名称】详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:tasks:query')")
+    @GetMapping(value = "/{rewardId}")
+    public AjaxResult getInfo(@PathVariable("rewardId") Long rewardId)
+    {
+        return success(rewardTasksService.selectRewardTasksByRewardId(rewardId));
+    }
+
+    /**
+     * 新增【请填写功能名称】
+     */
+    @PreAuthorize("@ss.hasPermi('system:tasks:add')")
+    @Log(title = "【请填写功能名称】", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody RewardTasks rewardTasks)
+    {
+        return toAjax(rewardTasksService.insertRewardTasks(rewardTasks));
+    }
+
+    /**
+     * 修改【请填写功能名称】
+     */
+    @PreAuthorize("@ss.hasPermi('system:tasks:edit')")
+    @Log(title = "【请填写功能名称】", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody RewardTasks rewardTasks)
+    {
+        return toAjax(rewardTasksService.updateRewardTasks(rewardTasks));
+    }
+
+    /**
+     * 删除【请填写功能名称】
+     */
+    @PreAuthorize("@ss.hasPermi('system:tasks:remove')")
+    @Log(title = "【请填写功能名称】", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{rewardIds}")
+    public AjaxResult remove(@PathVariable Long[] rewardIds)
+    {
+        return toAjax(rewardTasksService.deleteRewardTasksByRewardIds(rewardIds));
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/reward/domain/RewardTasks.java b/ruoyi-admin/src/main/java/com/ruoyi/reward/domain/RewardTasks.java
new file mode 100644
index 0000000..50e5c8f
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/reward/domain/RewardTasks.java
@@ -0,0 +1,125 @@
+package com.ruoyi.reward.domain;
+
+import java.math.BigDecimal;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 【请填写功能名称】对象 reward_tasks
+ * 
+ * @author ruoyi
+ * @date 2025-05-17
+ */
+public class RewardTasks extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** $column.columnComment */
+    private Long rewardId;
+
+    /** $column.columnComment */
+    @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+    private String title;
+
+    /** $column.columnComment */
+    @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+    private String description;
+
+    /** $column.columnComment */
+    @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+    private BigDecimal amount;
+
+    /** $column.columnComment */
+    @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+    private String status;
+
+    /** $column.columnComment */
+    @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+    private Long publisherId;
+
+    /** $column.columnComment */
+    @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+    private Long accepterId;
+
+    public void setRewardId(Long rewardId) 
+    {
+        this.rewardId = rewardId;
+    }
+
+    public Long getRewardId() 
+    {
+        return rewardId;
+    }
+    public void setTitle(String title) 
+    {
+        this.title = title;
+    }
+
+    public String getTitle() 
+    {
+        return title;
+    }
+    public void setDescription(String description) 
+    {
+        this.description = description;
+    }
+
+    public String getDescription() 
+    {
+        return description;
+    }
+    public void setAmount(BigDecimal amount) 
+    {
+        this.amount = amount;
+    }
+
+    public BigDecimal getAmount() 
+    {
+        return amount;
+    }
+    public void setStatus(String status) 
+    {
+        this.status = status;
+    }
+
+    public String getStatus() 
+    {
+        return status;
+    }
+    public void setPublisherId(Long publisherId) 
+    {
+        this.publisherId = publisherId;
+    }
+
+    public Long getPublisherId() 
+    {
+        return publisherId;
+    }
+    public void setAccepterId(Long accepterId) 
+    {
+        this.accepterId = accepterId;
+    }
+
+    public Long getAccepterId() 
+    {
+        return accepterId;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("rewardId", getRewardId())
+            .append("title", getTitle())
+            .append("description", getDescription())
+            .append("amount", getAmount())
+            .append("status", getStatus())
+            .append("publisherId", getPublisherId())
+            .append("accepterId", getAccepterId())
+            .append("createTime", getCreateTime())
+            .append("updateTime", getUpdateTime())
+            .append("remark", getRemark())
+            .toString();
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/reward/mapper/RewardTasksMapper.java b/ruoyi-admin/src/main/java/com/ruoyi/reward/mapper/RewardTasksMapper.java
new file mode 100644
index 0000000..92520b8
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/reward/mapper/RewardTasksMapper.java
@@ -0,0 +1,61 @@
+package com.ruoyi.reward.mapper;
+
+import java.util.List;
+import com.ruoyi.reward.domain.RewardTasks;
+
+/**
+ * 【请填写功能名称】Mapper接口
+ * 
+ * @author ruoyi
+ * @date 2025-05-17
+ */
+public interface RewardTasksMapper 
+{
+    /**
+     * 查询【请填写功能名称】
+     * 
+     * @param rewardId 【请填写功能名称】主键
+     * @return 【请填写功能名称】
+     */
+    public RewardTasks selectRewardTasksByRewardId(Long rewardId);
+
+    /**
+     * 查询【请填写功能名称】列表
+     * 
+     * @param rewardTasks 【请填写功能名称】
+     * @return 【请填写功能名称】集合
+     */
+    public List<RewardTasks> selectRewardTasksList(RewardTasks rewardTasks);
+
+    /**
+     * 新增【请填写功能名称】
+     * 
+     * @param rewardTasks 【请填写功能名称】
+     * @return 结果
+     */
+    public int insertRewardTasks(RewardTasks rewardTasks);
+
+    /**
+     * 修改【请填写功能名称】
+     * 
+     * @param rewardTasks 【请填写功能名称】
+     * @return 结果
+     */
+    public int updateRewardTasks(RewardTasks rewardTasks);
+
+    /**
+     * 删除【请填写功能名称】
+     * 
+     * @param rewardId 【请填写功能名称】主键
+     * @return 结果
+     */
+    public int deleteRewardTasksByRewardId(Long rewardId);
+
+    /**
+     * 批量删除【请填写功能名称】
+     * 
+     * @param rewardIds 需要删除的数据主键集合
+     * @return 结果
+     */
+    public int deleteRewardTasksByRewardIds(Long[] rewardIds);
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/reward/service/IRewardTasksService.java b/ruoyi-admin/src/main/java/com/ruoyi/reward/service/IRewardTasksService.java
new file mode 100644
index 0000000..5b8bd13
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/reward/service/IRewardTasksService.java
@@ -0,0 +1,61 @@
+package com.ruoyi.reward.service;
+
+import java.util.List;
+import com.ruoyi.reward.domain.RewardTasks;
+
+/**
+ * 【请填写功能名称】Service接口
+ * 
+ * @author ruoyi
+ * @date 2025-05-17
+ */
+public interface IRewardTasksService 
+{
+    /**
+     * 查询【请填写功能名称】
+     * 
+     * @param rewardId 【请填写功能名称】主键
+     * @return 【请填写功能名称】
+     */
+    public RewardTasks selectRewardTasksByRewardId(Long rewardId);
+
+    /**
+     * 查询【请填写功能名称】列表
+     * 
+     * @param rewardTasks 【请填写功能名称】
+     * @return 【请填写功能名称】集合
+     */
+    public List<RewardTasks> selectRewardTasksList(RewardTasks rewardTasks);
+
+    /**
+     * 新增【请填写功能名称】
+     * 
+     * @param rewardTasks 【请填写功能名称】
+     * @return 结果
+     */
+    public int insertRewardTasks(RewardTasks rewardTasks);
+
+    /**
+     * 修改【请填写功能名称】
+     * 
+     * @param rewardTasks 【请填写功能名称】
+     * @return 结果
+     */
+    public int updateRewardTasks(RewardTasks rewardTasks);
+
+    /**
+     * 批量删除【请填写功能名称】
+     * 
+     * @param rewardIds 需要删除的【请填写功能名称】主键集合
+     * @return 结果
+     */
+    public int deleteRewardTasksByRewardIds(Long[] rewardIds);
+
+    /**
+     * 删除【请填写功能名称】信息
+     * 
+     * @param rewardId 【请填写功能名称】主键
+     * @return 结果
+     */
+    public int deleteRewardTasksByRewardId(Long rewardId);
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/reward/service/impl/RewardTasksServiceImpl.java b/ruoyi-admin/src/main/java/com/ruoyi/reward/service/impl/RewardTasksServiceImpl.java
new file mode 100644
index 0000000..b80f3f3
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/reward/service/impl/RewardTasksServiceImpl.java
@@ -0,0 +1,96 @@
+package com.ruoyi.reward.service.impl;
+
+import java.util.List;
+import com.ruoyi.common.utils.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.reward.mapper.RewardTasksMapper;
+import com.ruoyi.reward.domain.RewardTasks;
+import com.ruoyi.reward.service.IRewardTasksService;
+
+/**
+ * 【请填写功能名称】Service业务层处理
+ * 
+ * @author ruoyi
+ * @date 2025-05-17
+ */
+@Service
+public class RewardTasksServiceImpl implements IRewardTasksService 
+{
+    @Autowired
+    private RewardTasksMapper rewardTasksMapper;
+
+    /**
+     * 查询【请填写功能名称】
+     * 
+     * @param rewardId 【请填写功能名称】主键
+     * @return 【请填写功能名称】
+     */
+    @Override
+    public RewardTasks selectRewardTasksByRewardId(Long rewardId)
+    {
+        return rewardTasksMapper.selectRewardTasksByRewardId(rewardId);
+    }
+
+    /**
+     * 查询【请填写功能名称】列表
+     * 
+     * @param rewardTasks 【请填写功能名称】
+     * @return 【请填写功能名称】
+     */
+    @Override
+    public List<RewardTasks> selectRewardTasksList(RewardTasks rewardTasks)
+    {
+        return rewardTasksMapper.selectRewardTasksList(rewardTasks);
+    }
+
+    /**
+     * 新增【请填写功能名称】
+     * 
+     * @param rewardTasks 【请填写功能名称】
+     * @return 结果
+     */
+    @Override
+    public int insertRewardTasks(RewardTasks rewardTasks)
+    {
+        rewardTasks.setCreateTime(DateUtils.getNowDate());
+        return rewardTasksMapper.insertRewardTasks(rewardTasks);
+    }
+
+    /**
+     * 修改【请填写功能名称】
+     * 
+     * @param rewardTasks 【请填写功能名称】
+     * @return 结果
+     */
+    @Override
+    public int updateRewardTasks(RewardTasks rewardTasks)
+    {
+        rewardTasks.setUpdateTime(DateUtils.getNowDate());
+        return rewardTasksMapper.updateRewardTasks(rewardTasks);
+    }
+
+    /**
+     * 批量删除【请填写功能名称】
+     * 
+     * @param rewardIds 需要删除的【请填写功能名称】主键
+     * @return 结果
+     */
+    @Override
+    public int deleteRewardTasksByRewardIds(Long[] rewardIds)
+    {
+        return rewardTasksMapper.deleteRewardTasksByRewardIds(rewardIds);
+    }
+
+    /**
+     * 删除【请填写功能名称】信息
+     * 
+     * @param rewardId 【请填写功能名称】主键
+     * @return 结果
+     */
+    @Override
+    public int deleteRewardTasksByRewardId(Long rewardId)
+    {
+        return rewardTasksMapper.deleteRewardTasksByRewardId(rewardId);
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/torrent/controller/BtTorrentController.java b/ruoyi-admin/src/main/java/com/ruoyi/torrent/controller/BtTorrentController.java
index 6d7626b..46345c7 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/torrent/controller/BtTorrentController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/torrent/controller/BtTorrentController.java
@@ -68,7 +68,6 @@
     @PostMapping("/uploadTorrent")
     public AjaxResult uploadTorrent(@RequestParam("file") MultipartFile file) {
         try {
-
             // Create URL connection to Flask server
             String flaskUrl = "http://localhost:5000/parse_torrent"; // Flask server URL
             HttpURLConnection connection = (HttpURLConnection) new URL(flaskUrl).openConnection();
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
index c86c6b3..cb1a87c 100644
--- a/ruoyi-admin/src/main/resources/application.yml
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -9,7 +9,7 @@
   # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
   profile: D:/ruoyi/uploadPath
   # 获取ip地址开关
-  addressEnabled: true
+  addressEnabled: false
   # 验证码类型 math 数字计算 char 字符验证
   captchaType: math
 
diff --git a/ruoyi-admin/src/main/resources/mapper/system/BtTorrentMapper.xml b/ruoyi-admin/src/main/resources/mapper/system/BtTorrentMapper.xml
index afb29d7..e19128a 100644
--- a/ruoyi-admin/src/main/resources/mapper/system/BtTorrentMapper.xml
+++ b/ruoyi-admin/src/main/resources/mapper/system/BtTorrentMapper.xml
@@ -24,7 +24,9 @@
 
     <select id="selectBtTorrentList" parameterType="BtTorrent" resultMap="BtTorrentResult">
         <include refid="selectBtTorrentVo"/>
-        <where>  
+        <where>
+            <if test="torrentId != null  and torrentId != ''"> and torrent_id = #{torrentId}</if>
+
             <if test="infoHash != null  and infoHash != ''"> and info_hash = #{infoHash}</if>
             <if test="name != null  and name != ''"> and name like concat('%', #{name}, '%')</if>
             <if test="length != null "> and length = #{length}</if>
diff --git a/ruoyi-admin/src/main/resources/mapper/system/RewardTasksMapper.xml b/ruoyi-admin/src/main/resources/mapper/system/RewardTasksMapper.xml
new file mode 100644
index 0000000..bae8185
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/mapper/system/RewardTasksMapper.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.reward.mapper.RewardTasksMapper">
+    
+    <resultMap type="RewardTasks" id="RewardTasksResult">
+        <result property="rewardId"    column="reward_id"    />
+        <result property="title"    column="title"    />
+        <result property="description"    column="description"    />
+        <result property="amount"    column="amount"    />
+        <result property="status"    column="status"    />
+        <result property="publisherId"    column="publisher_id"    />
+        <result property="accepterId"    column="accepter_id"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="remark"    column="remark"    />
+    </resultMap>
+
+    <sql id="selectRewardTasksVo">
+        select reward_id, title, description, amount, status, publisher_id, accepter_id, create_time, update_time, remark from reward_tasks
+    </sql>
+
+    <select id="selectRewardTasksList" parameterType="RewardTasks" resultMap="RewardTasksResult">
+        <include refid="selectRewardTasksVo"/>
+        <where>  
+            <if test="title != null  and title != ''"> and title = #{title}</if>
+            <if test="description != null  and description != ''"> and description = #{description}</if>
+            <if test="amount != null "> and amount = #{amount}</if>
+            <if test="status != null  and status != ''"> and status = #{status}</if>
+            <if test="publisherId != null "> and publisher_id = #{publisherId}</if>
+            <if test="accepterId != null "> and accepter_id = #{accepterId}</if>
+        </where>
+    </select>
+    
+    <select id="selectRewardTasksByRewardId" parameterType="Long" resultMap="RewardTasksResult">
+        <include refid="selectRewardTasksVo"/>
+        where reward_id = #{rewardId}
+    </select>
+
+    <insert id="insertRewardTasks" parameterType="RewardTasks" useGeneratedKeys="true" keyProperty="rewardId">
+        insert into reward_tasks
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="title != null and title != ''">title,</if>
+            <if test="description != null and description != ''">description,</if>
+            <if test="amount != null">amount,</if>
+            <if test="status != null">status,</if>
+            <if test="publisherId != null">publisher_id,</if>
+            <if test="accepterId != null">accepter_id,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="remark != null">remark,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="title != null and title != ''">#{title},</if>
+            <if test="description != null and description != ''">#{description},</if>
+            <if test="amount != null">#{amount},</if>
+            <if test="status != null">#{status},</if>
+            <if test="publisherId != null">#{publisherId},</if>
+            <if test="accepterId != null">#{accepterId},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="remark != null">#{remark},</if>
+         </trim>
+    </insert>
+
+    <update id="updateRewardTasks" parameterType="RewardTasks">
+        update reward_tasks
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="title != null and title != ''">title = #{title},</if>
+            <if test="description != null and description != ''">description = #{description},</if>
+            <if test="amount != null">amount = #{amount},</if>
+            <if test="status != null">status = #{status},</if>
+            <if test="publisherId != null">publisher_id = #{publisherId},</if>
+            <if test="accepterId != null">accepter_id = #{accepterId},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="remark != null">remark = #{remark},</if>
+        </trim>
+        where reward_id = #{rewardId}
+    </update>
+
+    <delete id="deleteRewardTasksByRewardId" parameterType="Long">
+        delete from reward_tasks where reward_id = #{rewardId}
+    </delete>
+
+    <delete id="deleteRewardTasksByRewardIds" parameterType="String">
+        delete from reward_tasks where reward_id in 
+        <foreach item="rewardId" collection="array" open="(" separator="," close=")">
+            #{rewardId}
+        </foreach>
+    </delete>
+</mapper>
\ No newline at end of file