Skip to main content
Glama
export.js9.74 kB
/** * 导出管理页面JavaScript */ class ExportManager { constructor() { this.plans = []; this.init(); } init() { this.loadPlans(); this.bindEvents(); } bindEvents() { // 计划选择变化事件 document.getElementById('exportPlanSelect').addEventListener('change', (e) => { this.onPlanSelectChange(e.target.value); }); } async loadPlans() { try { const response = await fetch('/api/plans'); if (response.ok) { this.plans = await response.json(); this.renderPlanOptions(); } else { Utils.showNotification('加载测试计划失败', 'error'); } } catch (error) { console.error('加载测试计划错误:', error); Utils.showNotification('加载测试计划失败', 'error'); } } renderPlanOptions() { const planSelect = document.getElementById('exportPlanSelect'); planSelect.innerHTML = '<option value="">请选择要导出的测试计划</option>'; this.plans.forEach(plan => { const option = document.createElement('option'); option.value = plan.id; option.textContent = `${plan.name} (${plan.tasks ? plan.tasks.length : 0}个任务)`; planSelect.appendChild(option); }); } onPlanSelectChange(planId) { const exportBtn = document.getElementById('exportBtn'); const previewBtn = document.getElementById('previewBtn'); exportBtn.disabled = !planId; previewBtn.disabled = !planId; } async exportToExcel() { const planId = document.getElementById('exportPlanSelect').value; if (!planId) { Utils.showNotification('请选择要导出的测试计划', 'error'); return; } const options = this.getExportOptions(); try { this.showExportStatus('正在生成Excel文件...'); Utils.setLoading(true); const response = await fetch(`/api/export/${planId}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(options) }); if (response.ok) { // 获取文件名 const contentDisposition = response.headers.get('Content-Disposition'); let filename = 'test-results.xlsx'; if (contentDisposition) { const filenameMatch = contentDisposition.match(/filename="(.+)"/); if (filenameMatch) { filename = filenameMatch[1]; } } // 下载文件 const blob = await response.blob(); const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = filename; document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url); document.body.removeChild(a); this.showExportStatus('导出成功!文件已下载。', 'success'); Utils.showNotification('Excel文件导出成功', 'success'); } else { const result = await response.json(); this.showExportStatus(result.message || '导出失败', 'error'); Utils.showNotification(result.message || '导出Excel文件失败', 'error'); } } catch (error) { console.error('导出Excel错误:', error); this.showExportStatus('导出失败: ' + error.message, 'error'); Utils.showNotification('导出Excel文件失败', 'error'); } finally { Utils.setLoading(false); } } async previewExport() { const planId = document.getElementById('exportPlanSelect').value; if (!planId) { Utils.showNotification('请选择要导出的测试计划', 'error'); return; } try { Utils.setLoading(true); // 获取计划详情和任务数据 const [planResponse, tasksResponse] = await Promise.all([ fetch(`/api/plans/${planId}`), fetch(`/api/tasks?plan_id=${planId}`) ]); if (planResponse.ok && tasksResponse.ok) { const plan = await planResponse.json(); const tasks = await tasksResponse.json(); this.showPreview(plan, tasks); } else { Utils.showNotification('获取预览数据失败', 'error'); } } catch (error) { console.error('预览导出错误:', error); Utils.showNotification('预览导出失败', 'error'); } finally { Utils.setLoading(false); } } getExportOptions() { return { includeDetails: document.getElementById('includeDetails').checked, includeSummary: document.getElementById('includeSummary').checked, includeTimestamp: document.getElementById('includeTimestamp').checked }; } showExportStatus(message, type = 'info') { const statusDiv = document.getElementById('exportStatus'); statusDiv.className = `export-status ${type}`; statusDiv.innerHTML = ` <div class="status-message"> <span class="status-icon">${this.getStatusIcon(type)}</span> <span class="status-text">${message}</span> </div> `; statusDiv.style.display = 'block'; // 自动隐藏成功消息 if (type === 'success') { setTimeout(() => { statusDiv.style.display = 'none'; }, 3000); } } getStatusIcon(type) { switch (type) { case 'success': return '✓'; case 'error': return '✗'; case 'info': default: return 'ℹ'; } } showPreview(plan, tasks) { const options = this.getExportOptions(); const previewContent = document.getElementById('previewContent'); // 生成预览表格 let tableHtml = ` <div class="preview-info"> <h4>计划信息</h4> <p><strong>计划名称:</strong> ${plan.name}</p> <p><strong>任务数量:</strong> ${tasks.length}</p> ${options.includeTimestamp ? `<p><strong>导出时间:</strong> ${Utils.formatTimestamp(new Date().toISOString())}</p>` : ''} </div> <div class="preview-table"> <table class="export-preview-table"> <thead> <tr> <th>序号</th> <th>任务名称</th> <th>URL</th> <th>方法</th> <th>状态</th> ${options.includeDetails ? '<th>状态码</th><th>响应时间</th>' : ''} ${options.includeSummary ? '<th>测试总结</th><th>改进建议</th>' : ''} ${options.includeTimestamp ? '<th>执行时间</th>' : ''} </tr> </thead> <tbody> `; tasks.forEach((task, index) => { const statusText = this.getStatusText(task.status); tableHtml += ` <tr> <td>${index + 1}</td> <td>${task.name || 'N/A'}</td> <td>${task.url || 'N/A'}</td> <td>${task.method || 'N/A'}</td> <td><span class="status-badge ${task.status}">${statusText}</span></td> ${options.includeDetails ? ` <td>${task.response?.status || 'N/A'}</td> <td>${task.response?.responseTime || 'N/A'}ms</td> ` : ''} ${options.includeSummary ? ` <td>${task.summary || 'N/A'}</td> <td>${task.suggest || 'N/A'}</td> ` : ''} ${options.includeTimestamp ? ` <td>${Utils.formatTimestamp(task.executed_at)}</td> ` : ''} </tr> `; }); tableHtml += ` </tbody> </table> </div> `; previewContent.innerHTML = tableHtml; document.getElementById('exportPreview').style.display = 'block'; } getStatusText(status) { switch (status) { case 'success': return '成功'; case 'error': return '失败'; case 'pending': return '待处理'; default: return '未知'; } } } // 全局函数 function exportToExcel() { exportManager.exportToExcel(); } function previewExport() { exportManager.previewExport(); } // 初始化 let exportManager; document.addEventListener('DOMContentLoaded', () => { exportManager = new ExportManager(); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/FactrueSolin/api-test-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server