Files
pit-router/app/templates/test/index.html

160 lines
7.4 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base.html" %}
{% block title %}连接测试 - 智队中枢{% endblock %}
{% block content %}
<div class="space-y-6">
{# 页面标题 #}
<div class="flex items-center justify-between">
<h1 class="text-2xl font-bold dark:text-white">连接测试</h1>
</div>
{# 测试控制面板 #}
<div class="card">
<div class="card-body">
<div class="flex flex-wrap items-end gap-4">
<div class="flex-1 min-w-[200px]">
<label class="block text-sm font-medium mb-1 dark:text-gray-300">选择频道</label>
<select id="test-channel" class="select">
<option value="">请选择频道...</option>
{% for config in configs %}
<option value="{{ config.id }}">{{ config.name }} ({{ config.gateway_url }})</option>
{% endfor %}
</select>
</div>
<button onclick="startTest()" class="btn btn-primary flex items-center gap-2">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
开始测试
</button>
</div>
</div>
</div>
{# 测试结果 #}
<div id="test-result" class="card hidden">
<div class="card-header">
<h2 class="text-lg font-semibold dark:text-white">测试结果</h2>
</div>
<div class="card-body space-y-4">
{# 结果概览 #}
<div class="flex items-center justify-between p-4 bg-gray-50 dark:bg-gray-700/50 rounded-lg">
<div class="flex items-center gap-3">
<div id="result-icon" class="w-10 h-10 rounded-full flex items-center justify-center">
{# JS 将填充 #}
</div>
<div>
<div id="result-status" class="font-semibold text-lg">-</div>
<div id="result-time" class="text-sm text-gray-500 dark:text-gray-400">-</div>
</div>
</div>
<button onclick="startTest()" class="btn btn-secondary text-sm">
重新测试
</button>
</div>
{# 详细日志 #}
<div>
<h3 class="text-sm font-medium mb-2 dark:text-gray-300">测试日志</h3>
<div id="test-logs" class="log-area">
{# JS 将填充 #}
</div>
</div>
</div>
</div>
{# 测试说明 #}
<div class="card">
<div class="card-body">
<h3 class="font-semibold mb-3 dark:text-white">测试说明</h3>
<ul class="space-y-2 text-sm text-gray-600 dark:text-gray-400">
<li class="flex items-start gap-2">
<svg class="w-5 h-5 text-primary-500 flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
<span>测试将依次验证WebSocket 连接、认证、心跳、消息收发</span>
</li>
<li class="flex items-start gap-2">
<svg class="w-5 h-5 text-primary-500 flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
<span>请确保频道配置正确且目标服务正在运行</span>
</li>
<li class="flex items-start gap-2">
<svg class="w-5 h-5 text-primary-500 flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
<span>测试日志将实时显示每一步的详细结果</span>
</li>
</ul>
</div>
</div>
</div>
<script>
let eventSource = null;
function startTest() {
const channelId = document.getElementById('test-channel').value;
if (!channelId) {
showToast('请选择频道', 'warning');
return;
}
// 显示结果区域
document.getElementById('test-result').classList.remove('hidden');
// 清空日志
document.getElementById('test-logs').innerHTML = '<div class="log-info">[INFO] 开始测试...</div>';
// 使用 SSE 接收实时日志
eventSource = new EventSource(`/api/web/channels/${channelId}/test/stream`);
eventSource.onmessage = function(event) {
const data = JSON.parse(event.data);
addLog(data.level, data.message);
if (data.complete) {
eventSource.close();
showResult(data.success, data.response_time);
}
};
eventSource.onerror = function() {
addLog('error', '连接中断');
eventSource.close();
};
}
function addLog(level, message) {
const logArea = document.getElementById('test-logs');
const time = new Date().toLocaleTimeString();
const entry = `<div class="log-entry log-${level}">[${time}] ${message}</div>`;
logArea.innerHTML += entry;
logArea.scrollTop = logArea.scrollHeight;
}
function showResult(success, responseTime) {
const icon = document.getElementById('result-icon');
const status = document.getElementById('result-status');
const time = document.getElementById('result-time');
if (success) {
icon.innerHTML = '<svg class="w-6 h-6 text-green-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>';
icon.className = 'w-10 h-10 rounded-full bg-green-100 dark:bg-green-900/30 flex items-center justify-center';
status.textContent = '测试通过';
status.className = 'font-semibold text-lg text-green-600 dark:text-green-400';
} else {
icon.innerHTML = '<svg class="w-6 h-6 text-red-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg>';
icon.className = 'w-10 h-10 rounded-full bg-red-100 dark:bg-red-900/30 flex items-center justify-center';
status.textContent = '测试失败';
status.className = 'font-semibold text-lg text-red-600 dark:text-red-400';
}
time.textContent = `响应时间: ${responseTime}ms | 测试时间: ${new Date().toLocaleString()}`;
}
</script>
{% endblock %}