networkTest.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. // 网络测试相关功能
  2. // 创建networkTest对象
  3. const networkTest = {
  4. // 初始化函数
  5. init: function() {
  6. // console.log('初始化网络测试模块...');
  7. this.initNetworkTestControls(); // Renamed for clarity
  8. this.displayInitialResultsMessage();
  9. return Promise.resolve(); // Keep if other inits expect a Promise
  10. },
  11. displayInitialResultsMessage: function() {
  12. const resultsDiv = document.getElementById('testResults');
  13. if (resultsDiv) {
  14. resultsDiv.innerHTML = '<p class="text-muted text-center p-3">请选择参数并开始测试。</p>';
  15. }
  16. },
  17. // 初始化网络测试界面控件和事件
  18. initNetworkTestControls: function() {
  19. const domainSelect = document.getElementById('domainSelect');
  20. const testTypeSelect = document.getElementById('testType'); // Corrected ID reference
  21. const startTestButton = document.getElementById('startTestBtn'); // Use ID
  22. const clearResultsButton = document.getElementById('clearTestResultsBtn');
  23. const resultsDiv = document.getElementById('testResults');
  24. // 填充域名选择器
  25. if (domainSelect) {
  26. domainSelect.innerHTML = `
  27. <option value="">选择预定义域名</option>
  28. <option value="gcr.io">gcr.io</option>
  29. <option value="ghcr.io">ghcr.io</option>
  30. <option value="quay.io">quay.io</option>
  31. <option value="k8s.gcr.io">k8s.gcr.io</option>
  32. <option value="registry.k8s.io">registry.k8s.io</option>
  33. <option value="mcr.microsoft.com">mcr.microsoft.com</option>
  34. <option value="docker.elastic.co">docker.elastic.co</option>
  35. <option value="registry-1.docker.io">registry-1.docker.io</option>
  36. <option value="google.com">google.com (测试用)</option>
  37. <option value="cloudflare.com">cloudflare.com (测试用)</option>
  38. <option value="custom">自定义域名</option>
  39. `;
  40. // 添加选择变化事件,显示/隐藏自定义域名输入框
  41. domainSelect.addEventListener('change', () => {
  42. const customDomainContainer = document.getElementById('customDomainContainer');
  43. if (customDomainContainer) {
  44. customDomainContainer.style.display = domainSelect.value === 'custom' ? 'block' : 'none';
  45. }
  46. });
  47. }
  48. // 填充测试类型选择器
  49. if (testTypeSelect) {
  50. testTypeSelect.innerHTML = `
  51. <option value="ping">Ping (ICMP)</option>
  52. <option value="traceroute">Traceroute</option>
  53. `;
  54. }
  55. // 绑定开始测试按钮点击事件
  56. if (startTestButton) {
  57. // Bind the function correctly, preserving 'this' context if necessary,
  58. // or ensure runNetworkTest doesn't rely on 'this' from the event handler.
  59. // Using an arrow function or .bind(this) if runNetworkTest uses 'this.someOtherMethod'
  60. startTestButton.addEventListener('click', () => this.runNetworkTest());
  61. } else {
  62. // console.error('未找到开始测试按钮 (ID: startTestBtn)');
  63. }
  64. // 绑定清空结果按钮点击事件
  65. if (clearResultsButton && resultsDiv) {
  66. clearResultsButton.addEventListener('click', () => {
  67. resultsDiv.innerHTML = '<p class="text-muted text-center p-3">结果已清空。</p>';
  68. // Optionally, remove loading class if it was somehow stuck
  69. resultsDiv.classList.remove('loading');
  70. });
  71. } else {
  72. if (!clearResultsButton) { /* console.error('未找到清空结果按钮 (ID: clearTestResultsBtn)'); */ }
  73. if (!resultsDiv) { /* console.error('未找到测试结果区域 (ID: testResults)'); */ }
  74. }
  75. },
  76. // 运行网络测试
  77. runNetworkTest: async function() { // Changed to async for await
  78. let domain = document.getElementById('domainSelect').value;
  79. const testType = document.getElementById('testType').value;
  80. const resultsDiv = document.getElementById('testResults');
  81. const startTestButton = document.getElementById('startTestBtn');
  82. // 处理自定义域名
  83. if (domain === 'custom') {
  84. const customDomain = document.getElementById('customDomain')?.value?.trim();
  85. if (!customDomain) {
  86. core.showAlert('请输入自定义域名进行测试。', 'warning');
  87. return;
  88. }
  89. domain = customDomain;
  90. } else if (!domain) {
  91. core.showAlert('请选择目标域名进行测试。', 'warning');
  92. return;
  93. }
  94. if (!testType) {
  95. core.showAlert('请选择测试类型。', 'warning');
  96. return;
  97. }
  98. resultsDiv.innerHTML = ''; // Clear previous content before adding loading class
  99. resultsDiv.classList.add('loading');
  100. if(startTestButton) startTestButton.disabled = true; // Disable button during test
  101. const controller = new AbortController();
  102. const timeoutId = setTimeout(() => {
  103. controller.abort();
  104. // logger.warn('Network test aborted due to timeout.');
  105. }, 60000); // 60秒超时
  106. try {
  107. const response = await fetch('/api/network-test', {
  108. method: 'POST',
  109. headers: {
  110. 'Content-Type': 'application/json',
  111. // Add any necessary auth headers if your API requires them
  112. // 'Authorization': 'Bearer ' + localStorage.getItem('authToken'),
  113. },
  114. body: JSON.stringify({ domain, type: testType }),
  115. signal: controller.signal
  116. });
  117. clearTimeout(timeoutId);
  118. if (!response.ok) {
  119. const errorText = await response.text();
  120. let detail = errorText;
  121. try {
  122. const errorJson = JSON.parse(errorText);
  123. detail = errorJson.message || errorJson.error || errorText;
  124. } catch (e) { /* ignore parsing error, use raw text */ }
  125. throw new Error(`网络连接正常,但测试执行失败 (状态: ${response.status}): ${detail}`);
  126. }
  127. const result = await response.text();
  128. // Format the plain text result in a <pre> tag for better display
  129. resultsDiv.innerHTML = `<pre>${result}</pre>`;
  130. } catch (error) {
  131. clearTimeout(timeoutId); // Ensure timeout is cleared on any error
  132. // console.error('网络测试出错:', error);
  133. let errorMessage = '测试失败: ' + error.message;
  134. if (error.name === 'AbortError') {
  135. errorMessage = '测试请求超时 (60秒)。请检查网络连接或目标主机状态。';
  136. }
  137. resultsDiv.innerHTML = `<pre class="text-danger">${errorMessage}</pre>`;
  138. } finally {
  139. resultsDiv.classList.remove('loading');
  140. if(startTestButton) startTestButton.disabled = false; // Re-enable button
  141. }
  142. }
  143. };
  144. // 全局公开网络测试模块 (或者 integrate with app.js module system if you have one)
  145. // Ensure this is called after the DOM is ready, e.g., in app.js or a DOMContentLoaded listener
  146. // For now, let's assume app.js handles calling networkTest.init()
  147. window.networkTest = networkTest;