增加了悬赏,标签查看,评论页面,标签上传后端有问题,评论还没跟后端连,优化了一些小界面
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