|
@@ -149,14 +149,6 @@ function updateRecentResults(results) {
|
|
|
<i class="bi bi-speedometer2"></i>
|
|
|
延迟: ${result.latency}ms
|
|
|
</div>
|
|
|
- <div class="result-detail">
|
|
|
- <i class="bi bi-download"></i>
|
|
|
- 下载: ${formatSpeed(result.downloadSpeed)}
|
|
|
- </div>
|
|
|
- <div class="result-detail">
|
|
|
- <i class="bi bi-upload"></i>
|
|
|
- 上传: ${formatSpeed(result.uploadSpeed)}
|
|
|
- </div>
|
|
|
` : `
|
|
|
<div class="result-detail">
|
|
|
<i class="bi bi-exclamation-triangle"></i>
|
|
@@ -171,19 +163,16 @@ function updateRecentResults(results) {
|
|
|
}
|
|
|
|
|
|
// 加载节点列表
|
|
|
-async function loadNodes(page = 1) {
|
|
|
+async function loadNodes() {
|
|
|
try {
|
|
|
showLoading();
|
|
|
|
|
|
const search = document.getElementById('node-search')?.value || '';
|
|
|
- const group = document.getElementById('group-filter')?.value || '';
|
|
|
const status = document.getElementById('status-filter')?.value || '';
|
|
|
|
|
|
const params = new URLSearchParams({
|
|
|
- page: page,
|
|
|
- limit: 20,
|
|
|
+ limit: 1000, // 设置一个很大的限制,获取所有节点
|
|
|
...(search && { search }),
|
|
|
- ...(group && { group }),
|
|
|
...(status && { status })
|
|
|
});
|
|
|
|
|
@@ -192,7 +181,6 @@ async function loadNodes(page = 1) {
|
|
|
|
|
|
if (data.success) {
|
|
|
updateNodesList(data.data);
|
|
|
- currentNodesPage = page;
|
|
|
}
|
|
|
|
|
|
hideLoading();
|
|
@@ -209,59 +197,60 @@ function updateNodesList(data) {
|
|
|
const { nodes, pagination } = data;
|
|
|
|
|
|
if (nodes.length === 0) {
|
|
|
- container.innerHTML = '<div class="text-center text-muted">暂无节点</div>';
|
|
|
+ container.innerHTML = '<div class="row"><div class="col-12"><div class="text-center text-muted">暂无节点</div></div></div>';
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- const html = nodes.map(node => `
|
|
|
- <div class="node-item">
|
|
|
- <div class="node-header">
|
|
|
- <div class="node-name">${node.name}</div>
|
|
|
- <div class="node-status ${node.status}">${node.status === 'online' ? '在线' : '离线'}</div>
|
|
|
- </div>
|
|
|
- <div class="node-info">
|
|
|
- <div class="node-info-item">
|
|
|
- <i class="bi bi-hdd-network"></i>
|
|
|
- 类型: ${node.type}
|
|
|
- </div>
|
|
|
- <div class="node-info-item">
|
|
|
- <i class="bi bi-geo-alt"></i>
|
|
|
- 服务器: ${node.server}
|
|
|
+ const html = '<div class="row">' + nodes.map((node, index) => `
|
|
|
+ <div class="col-md-6 mb-3">
|
|
|
+ <div class="node-item">
|
|
|
+ <div class="node-header">
|
|
|
+ <div class="node-name">${node.name}</div>
|
|
|
+ <div class="node-status ${node.status}">${node.status === 'online' ? '在线' : '离线'}</div>
|
|
|
</div>
|
|
|
- <div class="node-info-item">
|
|
|
- <i class="bi bi-arrow-left-right"></i>
|
|
|
- 端口: ${node.port}
|
|
|
- </div>
|
|
|
- <div class="node-info-item">
|
|
|
- <i class="bi bi-tags"></i>
|
|
|
- 分组: ${node.group || '默认'}
|
|
|
- </div>
|
|
|
- ${node.testResults && node.testResults.length > 0 ? `
|
|
|
+ <div class="node-info">
|
|
|
<div class="node-info-item">
|
|
|
- <i class="bi bi-clock"></i>
|
|
|
- 最后测速: ${formatTime(node.testResults[0].testTime)}
|
|
|
+ <i class="bi bi-hdd-network"></i>
|
|
|
+ 类型: ${node.type}
|
|
|
</div>
|
|
|
- ` : ''}
|
|
|
- </div>
|
|
|
- <div class="mt-2">
|
|
|
- <button class="btn btn-sm btn-outline-primary" onclick="viewNodeDetail(${node.id})">
|
|
|
- <i class="bi bi-eye"></i> 详情
|
|
|
- </button>
|
|
|
- <button class="btn btn-sm btn-outline-success" onclick="testSingleNode(${node.id})">
|
|
|
- <i class="bi bi-speedometer"></i> 测速
|
|
|
- </button>
|
|
|
+ <div class="node-info-item">
|
|
|
+ <i class="bi bi-geo-alt"></i>
|
|
|
+ 服务器: ${node.server}
|
|
|
+ </div>
|
|
|
+ <div class="node-info-item">
|
|
|
+ <i class="bi bi-arrow-left-right"></i>
|
|
|
+ 端口: ${node.port}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ ${node.testResults && node.testResults.length > 0 ? `
|
|
|
+ <div class="node-info-item last-test">
|
|
|
+ <i class="bi bi-clock"></i>
|
|
|
+ 最后测速: ${formatTime(node.testResults[0].testTime)}
|
|
|
+ ${node.testResults[0].isSuccess ? `
|
|
|
+ <span class="latency-separator">|</span>
|
|
|
+ <i class="bi bi-speedometer2"></i>
|
|
|
+ 延迟: <span class="latency-value">${node.testResults[0].latency}ms</span>
|
|
|
+ ` : ''}
|
|
|
+ </div>
|
|
|
+ ` : ''}
|
|
|
+ </div>
|
|
|
+ <div class="mt-2">
|
|
|
+ <button class="btn btn-sm btn-outline-primary" onclick="viewNodeDetail(${node.id})">
|
|
|
+ <i class="bi bi-eye"></i> 详情
|
|
|
+ </button>
|
|
|
+ <button class="btn btn-sm btn-outline-success" onclick="testSingleNode(${node.id})">
|
|
|
+ <i class="bi bi-speedometer"></i> 测速
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- `).join('');
|
|
|
+ `).join('') + '</div>';
|
|
|
|
|
|
container.innerHTML = html;
|
|
|
-
|
|
|
- // 更新分页
|
|
|
- updatePagination('nodes-pagination', pagination, loadNodes);
|
|
|
}
|
|
|
|
|
|
// 加载测速结果
|
|
|
-async function loadTestResults(page = 1) {
|
|
|
+async function loadTestResults() {
|
|
|
try {
|
|
|
showLoading();
|
|
|
|
|
@@ -271,8 +260,7 @@ async function loadTestResults(page = 1) {
|
|
|
const endDate = document.getElementById('end-date')?.value || '';
|
|
|
|
|
|
const params = new URLSearchParams({
|
|
|
- page: page,
|
|
|
- limit: 20,
|
|
|
+ limit: 1000, // 设置一个很大的限制,获取所有结果
|
|
|
...(nodeId && { nodeId }),
|
|
|
...(isSuccess && { isSuccess }),
|
|
|
...(startDate && { startDate }),
|
|
@@ -284,7 +272,6 @@ async function loadTestResults(page = 1) {
|
|
|
|
|
|
if (data.success) {
|
|
|
updateTestResults(data.data);
|
|
|
- currentResultsPage = page;
|
|
|
}
|
|
|
|
|
|
hideLoading();
|
|
@@ -301,48 +288,39 @@ function updateTestResults(data) {
|
|
|
const { results, pagination } = data;
|
|
|
|
|
|
if (results.length === 0) {
|
|
|
- container.innerHTML = '<div class="text-center text-muted">暂无测速结果</div>';
|
|
|
+ container.innerHTML = '<div class="row"><div class="col-12"><div class="text-center text-muted">暂无测速结果</div></div></div>';
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- const html = results.map(result => `
|
|
|
- <div class="result-item ${result.isSuccess ? 'result-success' : 'result-failure'}">
|
|
|
- <div class="result-header">
|
|
|
- <div class="result-node">${result.node ? result.node.name : '未知节点'}</div>
|
|
|
- <div class="result-time">${formatTime(result.testTime)}</div>
|
|
|
- </div>
|
|
|
- <div class="result-details">
|
|
|
- <div class="result-detail">
|
|
|
- <i class="bi ${result.isSuccess ? 'bi-check-circle text-success' : 'bi-x-circle text-danger'}"></i>
|
|
|
- 状态: ${result.isSuccess ? '成功' : '失败'}
|
|
|
+ const html = '<div class="row">' + results.map((result, index) => `
|
|
|
+ <div class="col-md-6 mb-3">
|
|
|
+ <div class="result-item ${result.isSuccess ? 'result-success' : 'result-failure'}">
|
|
|
+ <div class="result-header">
|
|
|
+ <div class="result-node">${result.node ? result.node.name : '未知节点'}</div>
|
|
|
+ <div class="result-time">${formatTime(result.testTime)}</div>
|
|
|
</div>
|
|
|
- ${result.isSuccess ? `
|
|
|
- <div class="result-detail">
|
|
|
- <i class="bi bi-speedometer2"></i>
|
|
|
- 延迟: ${result.latency}ms
|
|
|
- </div>
|
|
|
- <div class="result-detail">
|
|
|
- <i class="bi bi-download"></i>
|
|
|
- 下载: ${formatSpeed(result.downloadSpeed)}
|
|
|
- </div>
|
|
|
- <div class="result-detail">
|
|
|
- <i class="bi bi-upload"></i>
|
|
|
- 上传: ${formatSpeed(result.uploadSpeed)}
|
|
|
- </div>
|
|
|
- ` : `
|
|
|
+ <div class="result-details">
|
|
|
<div class="result-detail">
|
|
|
- <i class="bi bi-exclamation-triangle"></i>
|
|
|
- 错误: ${result.error || '未知错误'}
|
|
|
+ <i class="bi ${result.isSuccess ? 'bi-check-circle text-success' : 'bi-x-circle text-danger'}"></i>
|
|
|
+ 状态: ${result.isSuccess ? '成功' : '失败'}
|
|
|
</div>
|
|
|
- `}
|
|
|
+ ${result.isSuccess ? `
|
|
|
+ <div class="result-detail">
|
|
|
+ <i class="bi bi-speedometer2"></i>
|
|
|
+ 延迟: ${result.latency}ms
|
|
|
+ </div>
|
|
|
+ ` : `
|
|
|
+ <div class="result-detail">
|
|
|
+ <i class="bi bi-exclamation-triangle"></i>
|
|
|
+ 错误: ${result.error || '未知错误'}
|
|
|
+ </div>
|
|
|
+ `}
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- `).join('');
|
|
|
+ `).join('') + '</div>';
|
|
|
|
|
|
container.innerHTML = html;
|
|
|
-
|
|
|
- // 更新分页
|
|
|
- updatePagination('results-pagination', pagination, loadTestResults);
|
|
|
}
|
|
|
|
|
|
// 加载通知记录
|
|
@@ -576,12 +554,12 @@ async function showSystemStatus() {
|
|
|
|
|
|
// 搜索节点
|
|
|
function searchNodes() {
|
|
|
- loadNodes(1);
|
|
|
+ loadNodes();
|
|
|
}
|
|
|
|
|
|
// 搜索结果
|
|
|
function searchResults() {
|
|
|
- loadTestResults(1);
|
|
|
+ loadTestResults();
|
|
|
}
|
|
|
|
|
|
// 导入节点
|
|
@@ -679,7 +657,7 @@ async function viewNodeDetail(nodeId) {
|
|
|
<tr><td>类型:</td><td>${node.type}</td></tr>
|
|
|
<tr><td>服务器:</td><td>${node.server}</td></tr>
|
|
|
<tr><td>端口:</td><td>${node.port}</td></tr>
|
|
|
- <tr><td>分组:</td><td>${node.group || '默认'}</td></tr>
|
|
|
+
|
|
|
<tr><td>状态:</td><td><span class="badge ${node.status === 'online' ? 'bg-success' : 'bg-danger'}">${node.status === 'online' ? '在线' : '离线'}</span></td></tr>
|
|
|
</table>
|
|
|
</div>
|
|
@@ -700,14 +678,6 @@ async function viewNodeDetail(nodeId) {
|
|
|
<i class="bi bi-speedometer2"></i>
|
|
|
延迟: ${node.testResults[0].latency}ms
|
|
|
</div>
|
|
|
- <div class="result-detail">
|
|
|
- <i class="bi bi-download"></i>
|
|
|
- 下载: ${formatSpeed(node.testResults[0].downloadSpeed)}
|
|
|
- </div>
|
|
|
- <div class="result-detail">
|
|
|
- <i class="bi bi-upload"></i>
|
|
|
- 上传: ${formatSpeed(node.testResults[0].uploadSpeed)}
|
|
|
- </div>
|
|
|
` : `
|
|
|
<div class="result-detail">
|
|
|
<i class="bi bi-exclamation-triangle"></i>
|