/** * 日志管理界面JavaScript * * 处理日志页面的交互功能 */ (function($) { 'use strict'; /** * 日志管理器 */ var LogManager = { /** * 初始化 */ init: function() { this.bindEvents(); this.setupAutoRefresh(); }, /** * 绑定事件 */ bindEvents: function() { // 刷新日志 $('#refresh-logs').on('click', this.refreshLogs.bind(this)); // 清空日志 $('#clear-logs').on('click', this.clearLogs.bind(this)); // 下载日志 $('#download-logs').on('click', this.downloadLogs.bind(this)); // 日志行点击展开详情 $(document).on('click', '.log-table tbody tr', this.toggleLogDetails.bind(this)); // 实时搜索 $('input[name="search"]').on('input', this.debounce(this.performSearch.bind(this), 500)); }, /** * 刷新日志 */ refreshLogs: function() { location.reload(); }, /** * 清空日志 */ clearLogs: function() { if (!confirm(yoone_logs_params.i18n.confirm_clear)) { return; } var $button = $('#clear-logs'); var originalText = $button.text(); $button.text(yoone_logs_params.i18n.clearing).prop('disabled', true); $.ajax({ url: yoone_logs_params.ajax_url, type: 'POST', data: { action: 'yoone_clear_logs', nonce: yoone_logs_params.nonce }, success: function(response) { if (response.success) { location.reload(); } else { alert(response.data.message || '清空失败'); } }, error: function() { alert('请求失败,请重试'); }, complete: function() { $button.text(originalText).prop('disabled', false); } }); }, /** * 下载日志 */ downloadLogs: function() { var $button = $('#download-logs'); var originalText = $button.text(); $button.text(yoone_logs_params.i18n.downloading).prop('disabled', true); // 创建隐藏的下载链接 var downloadUrl = yoone_logs_params.ajax_url + '?action=yoone_download_logs&nonce=' + yoone_logs_params.nonce; var $link = $('').attr({ href: downloadUrl, download: 'yoone-subscriptions-' + new Date().toISOString().split('T')[0] + '.log' }).appendTo('body'); $link[0].click(); $link.remove(); setTimeout(function() { $button.text(originalText).prop('disabled', false); }, 2000); }, /** * 切换日志详情显示 */ toggleLogDetails: function(e) { var $row = $(e.currentTarget); var $detailRow = $row.next('.log-detail-row'); if ($detailRow.length) { $detailRow.toggle(); return; } // 创建详情行 var context = $row.find('.log-context').text(); if (!context) { return; } var $newDetailRow = $('').html( '
' + '

详细信息:

' + '
' + this.formatJSON(context) + '
' + '
' ); $row.after($newDetailRow); }, /** * 格式化JSON */ formatJSON: function(jsonString) { try { var obj = JSON.parse(jsonString); return JSON.stringify(obj, null, 2); } catch (e) { return jsonString; } }, /** * 执行搜索 */ performSearch: function() { var searchTerm = $('input[name="search"]').val(); var $rows = $('.log-table tbody tr:not(.log-detail-row)'); if (!searchTerm) { $rows.show(); return; } $rows.each(function() { var $row = $(this); var text = $row.text().toLowerCase(); var match = text.indexOf(searchTerm.toLowerCase()) !== -1; $row.toggle(match); // 隐藏对应的详情行 var $detailRow = $row.next('.log-detail-row'); if ($detailRow.length) { $detailRow.toggle(match); } }); }, /** * 设置自动刷新 */ setupAutoRefresh: function() { // 每30秒自动刷新一次(仅在错误标签页) if (this.getCurrentTab() === 'error') { setInterval(function() { if (document.visibilityState === 'visible') { location.reload(); } }, 30000); } }, /** * 获取当前标签页 */ getCurrentTab: function() { var urlParams = new URLSearchParams(window.location.search); return urlParams.get('tab') || 'recent'; }, /** * 防抖函数 */ debounce: function(func, wait) { var timeout; return function executedFunction() { var context = this; var args = arguments; var later = function() { timeout = null; func.apply(context, args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; } }; /** * 日志统计图表 */ var LogChart = { /** * 初始化图表 */ init: function() { this.createLevelChart(); this.createTimelineChart(); }, /** * 创建级别分布图表 */ createLevelChart: function() { var $container = $('#log-level-chart'); if (!$container.length) { return; } // 统计各级别日志数量 var levels = { error: 0, warning: 0, info: 0, debug: 0 }; $('.log-level').each(function() { var level = $(this).text().toLowerCase(); if (levels.hasOwnProperty(level)) { levels[level]++; } }); // 创建简单的条形图 var total = Object.values(levels).reduce((a, b) => a + b, 0); var html = '
日志级别分布
'; Object.keys(levels).forEach(function(level) { var count = levels[level]; var percentage = total > 0 ? (count / total * 100).toFixed(1) : 0; html += '
' + '' + level + '' + '
' + '
' + '
' + '' + count + ' (' + percentage + '%)' + '
'; }); $container.html(html); }, /** * 创建时间线图表 */ createTimelineChart: function() { var $container = $('#log-timeline-chart'); if (!$container.length) { return; } // 按小时统计日志数量 var hourlyStats = {}; var now = new Date(); // 初始化最近24小时 for (var i = 23; i >= 0; i--) { var hour = new Date(now.getTime() - i * 60 * 60 * 1000); var key = hour.getHours().toString().padStart(2, '0') + ':00'; hourlyStats[key] = 0; } // 统计实际日志 $('.log-table tbody tr:not(.log-detail-row)').each(function() { var timestamp = $(this).find('td:first').text(); var date = new Date(timestamp); var hour = date.getHours().toString().padStart(2, '0') + ':00'; if (hourlyStats.hasOwnProperty(hour)) { hourlyStats[hour]++; } }); // 创建时间线图表 var maxCount = Math.max(...Object.values(hourlyStats)); var html = '
24小时日志趋势
'; Object.keys(hourlyStats).forEach(function(hour) { var count = hourlyStats[hour]; var height = maxCount > 0 ? (count / maxCount * 100) : 0; html += '
' + '
' + '' + hour + '' + '
'; }); html += '
'; $container.html(html); } }; /** * 日志导出功能 */ var LogExporter = { /** * 导出为CSV */ exportCSV: function() { var csv = 'Timestamp,Level,Message,Context\n'; $('.log-table tbody tr:not(.log-detail-row)').each(function() { var $row = $(this); var cells = $row.find('td').map(function() { return '"' + $(this).text().replace(/"/g, '""') + '"'; }).get(); csv += cells.join(',') + '\n'; }); this.downloadFile(csv, 'yoone-logs-' + new Date().toISOString().split('T')[0] + '.csv', 'text/csv'); }, /** * 导出为JSON */ exportJSON: function() { var logs = []; $('.log-table tbody tr:not(.log-detail-row)').each(function() { var $row = $(this); var $cells = $row.find('td'); logs.push({ timestamp: $cells.eq(0).text(), level: $cells.eq(1).text(), message: $cells.eq(2).text(), context: $cells.eq(3).text() }); }); var json = JSON.stringify(logs, null, 2); this.downloadFile(json, 'yoone-logs-' + new Date().toISOString().split('T')[0] + '.json', 'application/json'); }, /** * 下载文件 */ downloadFile: function(content, filename, contentType) { var blob = new Blob([content], { type: contentType }); var url = window.URL.createObjectURL(blob); var $link = $('
').attr({ href: url, download: filename }).appendTo('body'); $link[0].click(); $link.remove(); window.URL.revokeObjectURL(url); } }; // 文档就绪时初始化 $(document).ready(function() { LogManager.init(); LogChart.init(); // 添加导出按钮事件 $(document).on('click', '#export-csv', LogExporter.exportCSV.bind(LogExporter)); $(document).on('click', '#export-json', LogExporter.exportJSON.bind(LogExporter)); }); // 添加样式 $('