feat(core): 实现用户积分计算逻辑
- 新增积分规则处理模块
- 集成积分计算到相关业务流程中
fix(file): 修复上传工具中路径乱码和非法字符问题
- 使用 UTF-8 编码统一路径解析
- 增加路径合法性校验
fix(user): 修正用户 Passkey 生成与验证流程
- 修复部分场景下 Passkey 未生成的问题
- 调整 Passkey 校验逻辑,确保唯一性和安全性
Change-Id: Id5eacb20f354a07de01413474095c2b2b9b49231
diff --git a/react-ui/src/pages/Peer/data.d.ts b/react-ui/src/pages/Peer/data.d.ts
new file mode 100644
index 0000000..f6f711c
--- /dev/null
+++ b/react-ui/src/pages/Peer/data.d.ts
@@ -0,0 +1,17 @@
+/** Peer 信息 */
+export interface BtTorrentPeer {
+ /** Peer Key */
+ peerKey: string;
+ /** IP 地址 */
+ ip: string;
+ /** 端口号 */
+ port: string;
+ /** 已上传量 */
+ uploaded: string;
+ /** 已下载量 */
+ downloaded: string;
+ /** 剩余量 */
+ left: string;
+ /** 最后活跃时间戳 */
+ lastSeen: string;
+}
diff --git a/react-ui/src/pages/Peer/index.tsx b/react-ui/src/pages/Peer/index.tsx
new file mode 100644
index 0000000..dec06ca
--- /dev/null
+++ b/react-ui/src/pages/Peer/index.tsx
@@ -0,0 +1,60 @@
+import React, { useEffect, useState } from 'react';
+import { Table, Spin, Alert } from 'antd';
+import {listBtTorrentPeers} from "@/pages/Peer/service";
+import {BtTorrentPeer} from "@/pages/Peer/data";
+
+
+interface PeerTableProps {
+ torrentId: number;
+}
+
+const PeerTable: React.FC<PeerTableProps> = ({ torrentId }) => {
+ const [loading, setLoading] = useState<boolean>(false);
+ const [peers, setPeers] = useState<BtTorrentPeer[]>([]);
+ const [error, setError] = useState<string | null>(null);
+
+ useEffect(() => {
+ const fetchPeers = async () => {
+ setLoading(true);
+ try {
+ const data = await listBtTorrentPeers();
+
+ setPeers(data.rows);
+ } catch (err) {
+ setError('Failed to load peer data.');
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ fetchPeers();
+ }, [torrentId]);
+
+ const columns = [
+ { title: 'Peer Key', dataIndex: 'peerKey', key: 'peerKey' },
+ { title: 'IP Address', dataIndex: 'ip', key: 'ip' },
+ { title: 'Port', dataIndex: 'port', key: 'port' },
+ { title: 'Uploaded', dataIndex: 'uploaded', key: 'uploaded' },
+ { title: 'Downloaded', dataIndex: 'downloaded', key: 'downloaded' },
+ { title: 'Left', dataIndex: 'left', key: 'left' },
+ { title: 'Last Seen', dataIndex: 'lastSeen', key: 'lastSeen' },
+ ];
+
+ return (
+ <div>
+ {error && <Alert message={error} type="error" />}
+ {loading ? (
+ <Spin size="large" />
+ ) : (
+ <Table<BtTorrentPeer>
+ columns={columns}
+ dataSource={peers}
+ rowKey="peerKey"
+ pagination={false}
+ />
+ )}
+ </div>
+ );
+};
+
+export default PeerTable;
diff --git a/react-ui/src/pages/Peer/service.ts b/react-ui/src/pages/Peer/service.ts
new file mode 100644
index 0000000..27f09a3
--- /dev/null
+++ b/react-ui/src/pages/Peer/service.ts
@@ -0,0 +1,9 @@
+import {BtTorrentPeer} from "@/pages/Peer/data";
+import {request} from "@umijs/max";
+
+/** 查询种子的 Peer 列表 */
+export async function listBtTorrentPeers() {
+ return request<BtTorrentPeer[]>(`/api/peers`, {
+ method: 'get',
+ });
+}