feat: 完成 Tracker 项目与 Torrent 种子模块的前后端接口与页面开发

- 实现 Tracker 项目、任务、任务日志、项目用户关联等模块的接口封装与 ProTable 页面
- 实现 Torrent 种子主表、文件列表、Tracker 服务器、标签模块的前后端接口封装
- 支持新增、编辑、删除、详情查看等完整 CRUD 功能
- 页面基于 Ant Design Pro,支持分页、筛选、Drawer + Modal 表单展示

Change-Id: If8ead64a0bf6c177545f1c3c348ee09cad221a85
diff --git a/react-ui/src/pages/Torrent/service.ts b/react-ui/src/pages/Torrent/service.ts
new file mode 100644
index 0000000..c1d8e26
--- /dev/null
+++ b/react-ui/src/pages/Torrent/service.ts
@@ -0,0 +1,175 @@
+import { request } from '@umijs/max';
+import type {
+  BtTorrent,
+  BtTorrentFile,
+  BtTorrentAnnounce,
+  BtTorrentTag,
+} from '@/pages/Torrent/data'; // 假设你把 data.d.ts 放这里
+
+// ================================
+// 种子主表(bt_torrent)接口
+// ================================
+
+/** 查询种子列表 */
+export async function listBtTorrent(params?: Partial<BtTorrent>) {
+  const queryString = params ? `?${new URLSearchParams(params as any)}` : '';
+  return request(`/api/system/torrent/list${queryString}`, {
+    method: 'get',
+  });
+}
+
+/** 获取种子详情 */
+export async function getBtTorrent(torrentId: number) {
+  return request<BtTorrent>(`/api/system/torrent/${torrentId}`, {
+    method: 'get',
+  });
+}
+
+/** 新增种子 */
+export async function addBtTorrent(data: BtTorrent) {
+  return request('/api/system/torrent', {
+    method: 'post',
+    data,
+  });
+}
+
+/** 修改种子 */
+export async function updateBtTorrent(data: BtTorrent) {
+  return request('/api/system/torrent', {
+    method: 'put',
+    data,
+  });
+}
+
+/** 删除种子(支持批量) */
+export async function removeBtTorrent(torrentIds: number[]) {
+  return request(`/api/system/torrent/${torrentIds.join(',')}`, {
+    method: 'delete',
+  });
+}
+
+// ================================
+// 种子文件(bt_torrent_file)接口
+// ================================
+
+/** 查询种子文件列表 */
+export async function listBtTorrentFile(params?: Partial<BtTorrentFile>) {
+  const queryString = params ? `?${new URLSearchParams(params as any)}` : '';
+  return request(`/api/system/file/list${queryString}`, {
+    method: 'get',
+  });
+}
+
+/** 获取文件详情 */
+export async function getBtTorrentFile(id: number) {
+  return request<BtTorrentFile>(`/api/system/file/${id}`, {
+    method: 'get',
+  });
+}
+
+/** 新增文件 */
+export async function addBtTorrentFile(data: BtTorrentFile) {
+  return request('/api/system/file', {
+    method: 'post',
+    data,
+  });
+}
+
+/** 修改文件 */
+export async function updateBtTorrentFile(data: BtTorrentFile) {
+  return request('/api/system/file', {
+    method: 'put',
+    data,
+  });
+}
+
+/** 删除文件(支持批量) */
+export async function removeBtTorrentFile(ids: number[]) {
+  return request(`/api/system/file/${ids.join(',')}`, {
+    method: 'delete',
+  });
+}
+
+// ================================
+// Tracker 列表(bt_torrent_announce)接口
+// ================================
+
+/** 查询 Tracker 列表 */
+export async function listBtTorrentAnnounce(params?: Partial<BtTorrentAnnounce>) {
+  const queryString = params ? `?${new URLSearchParams(params as any)}` : '';
+  return request(`/api/system/announce/list${queryString}`, {
+    method: 'get',
+  });
+}
+
+/** 获取单个 Tracker */
+export async function getBtTorrentAnnounce(id: number) {
+  return request<BtTorrentAnnounce>(`/api/system/announce/${id}`, {
+    method: 'get',
+  });
+}
+
+/** 新增 Tracker */
+export async function addBtTorrentAnnounce(data: BtTorrentAnnounce) {
+  return request('/api/system/announce', {
+    method: 'post',
+    data,
+  });
+}
+
+/** 修改 Tracker */
+export async function updateBtTorrentAnnounce(data: BtTorrentAnnounce) {
+  return request('/api/system/announce', {
+    method: 'put',
+    data,
+  });
+}
+
+/** 删除 Tracker(支持批量) */
+export async function removeBtTorrentAnnounce(ids: number[]) {
+  return request(`/api/system/announce/${ids.join(',')}`, {
+    method: 'delete',
+  });
+}
+
+// ================================
+// 种子标签(bt_torrent_tags)接口
+// ================================
+
+/** 查询标签列表 */
+export async function listBtTorrentTags(params?: Partial<BtTorrentTag>) {
+  const queryString = params ? `?${new URLSearchParams(params as any)}` : '';
+  return request(`/api/system/tags/list${queryString}`, {
+    method: 'get',
+  });
+}
+
+/** 获取标签详情 */
+export async function getBtTorrentTag(id: number) {
+  return request<BtTorrentTag>(`/api/system/tags/${id}`, {
+    method: 'get',
+  });
+}
+
+/** 新增标签 */
+export async function addBtTorrentTag(data: BtTorrentTag) {
+  return request('/api/system/tags', {
+    method: 'post',
+    data,
+  });
+}
+
+/** 修改标签 */
+export async function updateBtTorrentTag(data: BtTorrentTag) {
+  return request('/api/system/tags', {
+    method: 'put',
+    data,
+  });
+}
+
+/** 删除标签(支持批量) */
+export async function removeBtTorrentTag(ids: number[]) {
+  return request(`/api/system/tags/${ids.join(',')}`, {
+    method: 'delete',
+  });
+}