// 全局变量存储 JWT 令牌 let authToken = localStorage.getItem('auth_token'); $(document).ready(function() { // 检查认证状态 if (!authToken) { window.location.href = '/login'; return; } // 设置 AJAX 默认配置 $.ajaxSetup({ beforeSend: function(xhr, settings) { // 不为登录请求添加认证头 if (settings.url === '/api/auth/login') { return; } if (authToken) { xhr.setRequestHeader('Authorization', 'Bearer ' + authToken); } }, error: function(xhr, status, error) { // 如果收到 401,重定向到登录页 if (xhr.status === 401) { localStorage.removeItem('auth_token'); window.location.href = '/login'; return; } handleAjaxError(xhr, status, error); } }); // 初始化工具提示 $('[data-bs-toggle="tooltip"]').tooltip(); // 加载初始数据 loadProjects(); loadAPIKeys(); loadLogs(); checkHealth(); loadHealthDetails(); loadStatsDetails(); // 设置定期健康检查 setInterval(checkHealth, 30000); // 项目管理 $('#addProjectForm').on('submit', function(e) { e.preventDefault(); const projectData = { name: $('#projectName').val(), jenkinsJob: $('#jenkinsJob').val(), giteaRepo: $('#giteaRepo').val() }; $.ajax({ url: '/api/projects/', method: 'POST', contentType: 'application/json', data: JSON.stringify(projectData), success: function() { $('#addProjectModal').modal('hide'); $('#addProjectForm')[0].reset(); loadProjects(); showSuccess('项目添加成功'); }, error: handleAjaxError }); }); // API 密钥管理 $('#generateKeyForm').on('submit', function(e) { e.preventDefault(); $.ajax({ url: '/api/keys', method: 'POST', contentType: 'application/json', data: JSON.stringify({ description: $('#keyDescription').val() }), success: function(response) { $('#generateKeyModal').modal('hide'); $('#generateKeyForm')[0].reset(); loadAPIKeys(); showSuccess('API 密钥生成成功'); // 显示新生成的密钥 showApiKeyModal(response.key); }, error: handleAjaxError }); }); // 日志查询 $('#logQueryForm').on('submit', function(e) { e.preventDefault(); loadLogs({ startTime: $('#startTime').val(), endTime: $('#endTime').val(), level: $('#logLevel').val(), query: $('#logQuery').val() }); }); // 标签页切换 $('.nav-link').on('click', function() { $('.nav-link').removeClass('active'); $(this).addClass('active'); }); }); function loadProjects() { $.get('/api/projects/') .done(function(data) { const tbody = $('#projectsTable tbody'); tbody.empty(); data.projects.forEach(function(project) { tbody.append(` ${escapeHtml(project.name)} ${escapeHtml(project.jenkinsJob)} ${escapeHtml(project.giteaRepo)} `); }); }) .fail(handleAjaxError); } function loadAPIKeys() { $.get('/api/keys') .done(function(data) { const tbody = $('#apiKeysTable tbody'); tbody.empty(); data.keys.forEach(function(key) { tbody.append(` ${escapeHtml(key.description || '无描述')} ${escapeHtml(key.key)} ${new Date(key.created_at).toLocaleString('zh-CN')} `); }); }) .fail(handleAjaxError); } function loadLogs(query = {}) { $.get('/api/logs', query) .done(function(data) { const logContainer = $('#logEntries'); logContainer.empty(); if (data.logs && data.logs.length > 0) { data.logs.forEach(function(log) { const levelClass = { 'error': 'error', 'warn': 'warn', 'info': 'info', 'debug': 'debug' }[log.level] || ''; logContainer.append(`
${new Date(log.timestamp).toLocaleString('zh-CN')} [${escapeHtml(log.level.toUpperCase())}] ${escapeHtml(log.message)}
`); }); } else { logContainer.append('
暂无日志记录
'); } }) .fail(handleAjaxError); } function checkHealth() { $.get('/health') .done(function(data) { const indicator = $('.health-indicator'); indicator.removeClass('healthy unhealthy') .addClass(data.status === 'healthy' ? 'healthy' : 'unhealthy'); $('#healthStatus').text(data.status === 'healthy' ? '健康' : '异常'); }) .fail(function() { const indicator = $('.health-indicator'); indicator.removeClass('healthy').addClass('unhealthy'); $('#healthStatus').text('异常'); }); } function loadHealthDetails() { $.get('/health') .done(function(data) { const healthDetails = $('#healthDetails'); healthDetails.html(`
状态: ${data.status === 'healthy' ? '健康' : '异常'}
版本: ${data.version || '未知'}
启动时间: ${data.uptime || '未知'}
内存使用: ${data.memory || '未知'}
`); }) .fail(function() { $('#healthDetails').html('
无法获取健康状态
'); }); } function loadStatsDetails() { $.get('/api/stats') .done(function(data) { const statsDetails = $('#statsDetails'); statsDetails.html(`
总项目数: ${data.total_projects || 0}
API 密钥数: ${data.total_api_keys || 0}
今日触发次数: ${data.today_triggers || 0}
成功触发次数: ${data.successful_triggers || 0}
`); }) .fail(function() { $('#statsDetails').html('
无法获取统计信息
'); }); } function deleteProject(id) { if (!confirm('确定要删除这个项目吗?')) return; $.ajax({ url: `/api/projects/${id}`, method: 'DELETE', success: function() { loadProjects(); showSuccess('项目删除成功'); }, error: handleAjaxError }); } function revokeKey(id) { if (!confirm('确定要撤销这个 API 密钥吗?')) return; $.ajax({ url: `/api/keys/${id}`, method: 'DELETE', success: function() { loadAPIKeys(); showSuccess('API 密钥撤销成功'); }, error: handleAjaxError }); } function showApiKeyModal(key) { // 创建模态框显示新生成的密钥 const modal = $(` `); $('body').append(modal); modal.modal('show'); modal.on('hidden.bs.modal', function() { modal.remove(); }); } function copyToClipboard(text) { navigator.clipboard.writeText(text).then(function() { showSuccess('已复制到剪贴板'); }, function() { showError('复制失败'); }); } function handleAjaxError(jqXHR, textStatus, errorThrown) { const message = jqXHR.responseJSON?.detail || errorThrown || '发生错误'; showError(`错误: ${message}`); } function showSuccess(message) { // 创建成功提示 const alert = $(` `); $('.main-content').prepend(alert); // 3秒后自动消失 setTimeout(function() { alert.alert('close'); }, 3000); } function showError(message) { // 创建错误提示 const alert = $(` `); $('.main-content').prepend(alert); // 5秒后自动消失 setTimeout(function() { alert.alert('close'); }, 5000); } function escapeHtml(unsafe) { return unsafe .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, '''); }