diff --git a/functions.php b/functions.php index 60072b5..1fc8c88 100644 --- a/functions.php +++ b/functions.php @@ -13101,3 +13101,118 @@ function argon_ajax_clear_keyword_optimization_log() { wp_send_json_success(['message' => '关键字优化日志已清除']); } add_action('wp_ajax_argon_clear_keyword_optimization_log', 'argon_ajax_clear_keyword_optimization_log'); + +/** + * AJAX: 全站扫描垃圾评论 + */ +function argon_ajax_spam_scan_comments() { + check_ajax_referer('argon_spam_scan_comments', 'nonce'); + + if (!current_user_can('manage_options')) { + wp_send_json_error(['message' => '权限不足']); + } + + $scan_type = isset($_POST['scan_type']) ? sanitize_text_field($_POST['scan_type']) : 'all'; + $offset = isset($_POST['offset']) ? intval($_POST['offset']) : 0; + $batch_size = isset($_POST['batch_size']) ? intval($_POST['batch_size']) : 10; + + // 构建查询参数 + $args = [ + 'number' => $batch_size, + 'offset' => $offset, + 'orderby' => 'comment_date', + 'order' => 'DESC' + ]; + + // 如果只扫描待审核评论 + if ($scan_type === 'pending') { + $args['status'] = 'hold'; + } + + // 获取评论 + $comments = get_comments($args); + + // 获取总数(用于计算进度) + $total_args = $args; + unset($total_args['number']); + unset($total_args['offset']); + $total_args['count'] = true; + $total_comments = get_comments($total_args); + + $scanned = 0; + $skipped = 0; + $spam_found = 0; + $spam_comments = []; + + foreach ($comments as $comment) { + // 检查是否已经过 AI 审核 + $existing_result = get_comment_meta($comment->comment_ID, '_argon_spam_detection_result', true); + + if (!empty($existing_result)) { + // 已审核,跳过 + $skipped++; + continue; + } + + // 使用 AI 检测 + $detection_result = argon_detect_spam_with_ai($comment->comment_content, $comment->comment_author, $comment->comment_author_email); + + if ($detection_result && isset($detection_result['is_spam'])) { + // 保存检测结果 + update_comment_meta($comment->comment_ID, '_argon_spam_detection_result', $detection_result); + + $scanned++; + + if ($detection_result['is_spam']) { + $spam_found++; + + // 添加到垃圾评论列表 + $spam_comments[] = [ + 'id' => $comment->comment_ID, + 'author' => esc_html($comment->comment_author), + 'content' => esc_html(mb_substr($comment->comment_content, 0, 200)), + 'date' => get_comment_date('Y-m-d H:i', $comment->comment_ID), + 'confidence' => isset($detection_result['confidence']) ? intval($detection_result['confidence']) : 0, + 'reason' => isset($detection_result['reason']) ? esc_html($detection_result['reason']) : '', + 'edit_link' => admin_url('comment.php?action=editcomment&c=' . $comment->comment_ID) + ]; + + // 根据设置自动处理 + $auto_action = get_option('argon_comment_spam_detection_auto_action', 'trash'); + $confidence_threshold = intval(get_option('argon_comment_spam_detection_confidence_threshold', 85)); + $confidence = isset($detection_result['confidence']) ? intval($detection_result['confidence']) : 0; + + if ($confidence >= $confidence_threshold) { + if ($auto_action === 'trash') { + wp_trash_comment($comment->comment_ID); + } elseif ($auto_action === 'hold') { + wp_set_comment_status($comment->comment_ID, 'hold'); + } + // 'mark' 选项只标记不处理 + } + } + } else { + $scanned++; + } + } + + // 计算进度 + $progress = 0; + if ($total_comments > 0) { + $progress = min(100, round((($offset + count($comments)) / $total_comments) * 100)); + } + + // 判断是否完成 + $completed = (count($comments) < $batch_size) || (($offset + $batch_size) >= $total_comments); + + wp_send_json_success([ + 'scanned' => $scanned, + 'skipped' => $skipped, + 'spam_found' => $spam_found, + 'spam_comments' => $spam_comments, + 'progress' => $progress, + 'completed' => $completed, + 'total' => $total_comments + ]); +} +add_action('wp_ajax_argon_spam_scan_comments', 'argon_ajax_spam_scan_comments'); diff --git a/settings.php b/settings.php index 9f90040..675a26b 100644 --- a/settings.php +++ b/settings.php @@ -2521,26 +2521,34 @@ function themeoptions_page(){

- - -

- -

- - - - + + - + + + + + + + +

- +
+

@@ -2868,6 +2876,156 @@ function themeoptions_page(){ $('.argon-custom-prompt-row').slideUp(); } }); + + // ========== 全站扫描 ========== + let scanInProgress = false; + + function startSpamScan(scanType) { + if (scanInProgress) { + alert(''); + return; + } + + if (!confirm('')) { + return; + } + + scanInProgress = true; + + // 禁用按钮 + $('#argon-spam-scan-all, #argon-spam-scan-pending').prop('disabled', true); + + // 显示进度条 + $('#argon-spam-scan-progress').show(); + $('#argon-spam-scan-progress-bar').css('width', '0%'); + $('#argon-spam-scan-progress-text').text('0%'); + $('#argon-spam-scan-status').text(''); + + // 隐藏之前的结果 + $('#argon-spam-scan-results').hide(); + + // 开始扫描 + scanBatch(scanType, 0, 0, 0, 0, []); + } + + function scanBatch(scanType, offset, totalScanned, totalSkipped, totalSpam, spamComments) { + $.post(ajaxurl, { + action: 'argon_spam_scan_comments', + nonce: '', + scan_type: scanType, + offset: offset, + batch_size: 10 + }, function(response) { + if (response.success) { + let data = response.data; + totalScanned += data.scanned; + totalSkipped += data.skipped; + totalSpam += data.spam_found; + + // 合并垃圾评论列表 + if (data.spam_comments && data.spam_comments.length > 0) { + spamComments = spamComments.concat(data.spam_comments); + } + + // 更新进度 + let progress = data.progress || 0; + $('#argon-spam-scan-progress-bar').css('width', progress + '%'); + $('#argon-spam-scan-progress-text').text(progress + '%'); + $('#argon-spam-scan-status').text(' ' + totalScanned + ' ' + totalSkipped + ' ' + totalSpam + ' '); + + // 检查是否完成 + if (data.completed) { + // 扫描完成 + scanInProgress = false; + $('#argon-spam-scan-all, #argon-spam-scan-pending').prop('disabled', false); + $('#argon-spam-scan-status').html(''); + + // 显示结果 + displayScanResults(totalScanned, totalSkipped, totalSpam, spamComments); + } else { + // 继续下一批 + scanBatch(scanType, offset + 10, totalScanned, totalSkipped, totalSpam, spamComments); + } + } else { + // 错误处理 + scanInProgress = false; + $('#argon-spam-scan-all, #argon-spam-scan-pending').prop('disabled', false); + let errorMsg = (response.data && response.data.message) ? response.data.message : ''; + $('#argon-spam-scan-status').html(' ' + errorMsg + ''); + } + }).fail(function(xhr, status, error) { + scanInProgress = false; + $('#argon-spam-scan-all, #argon-spam-scan-pending').prop('disabled', false); + $('#argon-spam-scan-status').html(' ' + error + ''); + }); + } + + function displayScanResults(totalScanned, totalSkipped, totalSpam, spamComments) { + let html = '

'; + html += '
'; + html += '
'; + html += '
' + totalScanned + '
'; + html += '
'; + html += '
'; + html += '
'; + html += '
' + totalSkipped + '
'; + html += '
'; + html += '
'; + html += '
'; + html += '
' + totalSpam + '
'; + html += '
'; + html += '
'; + html += '
'; + + if (totalSpam > 0 && spamComments.length > 0) { + html += '

'; + html += '
'; + spamComments.forEach(function(comment) { + let confidenceColor = comment.confidence >= 90 ? '#d32f2f' : (comment.confidence >= 70 ? '#f57c00' : '#fbc02d'); + html += '
'; + html += '
'; + html += '
'; + html += '' + comment.author + ''; + html += '' + comment.date + ''; + html += '
'; + html += '
'; + html += ' ' + comment.confidence + '%'; + html += '
'; + html += '
'; + html += '
' + comment.content + '
'; + if (comment.reason) { + html += '
'; + html += ' ' + comment.reason; + html += '
'; + } + html += '
'; + html += ''; + html += '
'; + html += '
'; + }); + html += '
'; + html += '

'; + html += ''; + html += '

'; + } else if (totalScanned > 0) { + html += '
'; + html += ''; + html += '

'; + html += '
'; + } + + $('#argon-spam-scan-results-content').html(html); + $('#argon-spam-scan-results').slideDown(); + } + + // 绑定扫描按钮事件 + $('#argon-spam-scan-all').on('click', function() { + startSpamScan('all'); + }); + + $('#argon-spam-scan-pending').on('click', function() { + startSpamScan('pending'); + }); });