(baseUrl: string)
| 295 | |
| 296 | // 获取节点总览信息 |
| 297 | async function getNodesOverview(baseUrl: string): Promise<string> { |
| 298 | try { |
| 299 | // 获取公开信息 |
| 300 | const publicData = await makeRequest(baseUrl, "/api/public"); |
| 301 | |
| 302 | // 获取节点列表 |
| 303 | const nodesData = await makeRequest(baseUrl, "/api/nodes"); |
| 304 | |
| 305 | if (publicData.status !== "success" || nodesData.status !== "success") { |
| 306 | throw new Error("API 返回状态异常"); |
| 307 | } |
| 308 | |
| 309 | const siteName = publicData.data.sitename || "未知站点"; |
| 310 | const nodes = nodesData.data; |
| 311 | |
| 312 | // 尝试通过 WebSocket 获取实时数据 |
| 313 | let onlineNodes: string[] = []; |
| 314 | let realtimeData: { [key: string]: any } = {}; |
| 315 | |
| 316 | try { |
| 317 | // 这里我们通过 /api/recent/ 接口来获取每个节点的最新数据 |
| 318 | // 作为 WebSocket 的替代方案 |
| 319 | for (const node of nodes) { |
| 320 | try { |
| 321 | const recentData = await makeRequest( |
| 322 | baseUrl, |
| 323 | `/api/recent/${node.uuid}` |
| 324 | ); |
| 325 | if (recentData.status === "success" && recentData.data.length > 0) { |
| 326 | onlineNodes.push(node.uuid); |
| 327 | realtimeData[node.uuid] = recentData.data[0]; |
| 328 | } |
| 329 | } catch { |
| 330 | // 节点可能离线,忽略错误 |
| 331 | } |
| 332 | } |
| 333 | } catch { |
| 334 | // 如果获取实时数据失败,使用节点列表数据 |
| 335 | } |
| 336 | |
| 337 | const totalNodes = nodes.length; |
| 338 | const onlineCount = onlineNodes.length; |
| 339 | const onlinePercent = |
| 340 | totalNodes > 0 ? ((onlineCount / totalNodes) * 100).toFixed(2) : "0.00"; |
| 341 | |
| 342 | // 计算平均值 |
| 343 | let totalCores = 0; |
| 344 | let avgCpu = 0; |
| 345 | let avgLoad1 = 0; |
| 346 | let avgLoad5 = 0; |
| 347 | let avgLoad15 = 0; |
| 348 | let totalMemUsed = 0; |
| 349 | let totalMemTotal = 0; |
| 350 | let totalSwapUsed = 0; |
| 351 | let totalSwapTotal = 0; |
| 352 | let totalDiskUsed = 0; |
| 353 | let totalDiskTotal = 0; |
| 354 | let totalDownload = 0; |
no test coverage detected