首页 / 应用软件 / 实战教程,为网站集成智能化的内容相似度检测与防抄袭系统

实战教程,为网站集成智能化的内容相似度检测与防抄袭系统

实战教程:为WordPress网站集成智能化的内容相似度检测与防抄袭系统

引言:内容原创性在数字时代的重要性

在当今信息爆炸的互联网环境中,内容创作已成为网站运营的核心。然而,随着内容数量的急剧增加,抄袭和内容重复问题也日益严重。对于WordPress网站管理员和内容创作者而言,保护原创内容不仅是维护品牌声誉的需要,更是提升搜索引擎排名、吸引忠实读者的关键。

传统的防抄袭方法主要依赖人工检查或基础文本比对,效率低下且难以应对海量内容。本教程将指导您通过WordPress代码二次开发,集成智能化的内容相似度检测与防抄袭系统,将您的网站提升到一个新的智能化水平。

第一部分:系统架构设计与技术选型

1.1 系统核心功能需求分析

在开始开发之前,我们需要明确系统应具备的核心功能:

  1. 实时内容检测:在文章发布时自动检测内容相似度
  2. 批量历史内容扫描:对网站现有内容进行全面检查
  3. 智能相似度算法:采用先进的文本相似度计算方法
  4. 外部资源比对:能够与互联网上的公开内容进行比对
  5. 可视化报告系统:直观展示检测结果和相似度分析
  6. 自动化处理机制:根据预设规则自动处理疑似抄袭内容

1.2 技术栈选择与原理

我们将采用以下技术方案:

  • WordPress钩子机制:利用save_postpublish_post等动作钩子实现自动化检测
  • PHP文本处理库:使用PHP内置函数和扩展进行文本预处理
  • 相似度算法:实现余弦相似度、Jaccard相似系数和编辑距离算法
  • 外部API集成:通过第三方原创检测API增强检测能力
  • 数据库优化:合理设计数据表结构,确保系统性能
  • 前端展示:使用AJAX和Chart.js实现交互式报告界面

1.3 系统架构图

用户发布内容 → WordPress钩子触发 → 文本预处理 → 特征提取 → 
相似度计算 → 结果评估 → 数据库存储 → 报告生成 → 用户通知

第二部分:开发环境搭建与基础配置

2.1 开发环境准备

首先,确保您的开发环境满足以下要求:

  • WordPress 5.0或更高版本
  • PHP 7.3或更高版本(支持mbstring、curl扩展)
  • MySQL 5.6或更高版本
  • 至少100MB的可用磁盘空间(用于存储文本指纹和缓存)

2.2 创建自定义插件

我们将创建一个独立的WordPress插件来实现所有功能:

  1. wp-content/plugins/目录下创建新文件夹smart-content-checker
  2. 创建主插件文件smart-content-checker.php
<?php
/**
 * Plugin Name: 智能内容相似度检测与防抄袭系统
 * Plugin URI: https://yourwebsite.com/
 * Description: 为WordPress网站提供智能化的内容相似度检测与防抄袭功能
 * Version: 1.0.0
 * Author: 您的名称
 * License: GPL v2 or later
 * Text Domain: smart-content-checker
 */

// 防止直接访问
if (!defined('ABSPATH')) {
    exit;
}

// 定义插件常量
define('SCC_VERSION', '1.0.0');
define('SCC_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('SCC_PLUGIN_URL', plugin_dir_url(__FILE__));
define('SCC_CACHE_TIME', 3600); // 缓存时间1小时

// 初始化插件
require_once SCC_PLUGIN_DIR . 'includes/class-core.php';
require_once SCC_PLUGIN_DIR . 'includes/class-text-processor.php';
require_once SCC_PLUGIN_DIR . 'includes/class-similarity-checker.php';
require_once SCC_PLUGIN_DIR . 'includes/class-database.php';
require_once SCC_PLUGIN_DIR . 'includes/class-admin-interface.php';

// 启动插件
function scc_init_plugin() {
    $core = new SCC_Core();
    $core->init();
}
add_action('plugins_loaded', 'scc_init_plugin');

第三部分:核心文本处理与特征提取模块

3.1 文本预处理类实现

创建includes/class-text-processor.php文件:

<?php
class SCC_Text_Processor {
    
    /**
     * 文本清洗和标准化
     */
    public function clean_text($text) {
        // 移除HTML标签
        $text = strip_tags($text);
        
        // 转换所有字符为小写
        $text = mb_strtolower($text, 'UTF-8');
        
        // 移除特殊字符和标点符号,保留中文、英文和数字
        $text = preg_replace('/[^p{L}p{N}s]/u', ' ', $text);
        
        // 移除多余空格
        $text = preg_replace('/s+/', ' ', $text);
        
        return trim($text);
    }
    
    /**
     * 中文文本分词
     * 注意:需要服务器安装中文分词扩展,这里提供简单实现
     */
    public function chinese_segmentation($text) {
        // 如果服务器安装了scws或jieba分词,可以调用相关函数
        // 这里提供一个简单的按字符分割的方法(适用于基础需求)
        if (function_exists('scws_new')) {
            // 使用scws分词
            $so = scws_new();
            $so->set_charset('utf8');
            $so->send_text($text);
            $words = array();
            while ($tmp = $so->get_result()) {
                foreach ($tmp as $word) {
                    if (strlen($word['word']) > 1) {
                        $words[] = $word['word'];
                    }
                }
            }
            $so->close();
            return $words;
        } else {
            // 简单分词:按空格和标点分割
            return preg_split('/s+/', $text);
        }
    }
    
    /**
     * 提取文本特征(词频向量)
     */
    public function extract_features($text, $max_features = 100) {
        $cleaned_text = $this->clean_text($text);
        
        // 分词
        $words = $this->chinese_segmentation($cleaned_text);
        
        // 计算词频
        $word_freq = array_count_values($words);
        
        // 移除停用词
        $word_freq = $this->remove_stopwords($word_freq);
        
        // 按词频排序并取前N个特征
        arsort($word_freq);
        $features = array_slice($word_freq, 0, $max_features, true);
        
        return $features;
    }
    
    /**
     * 移除停用词
     */
    private function remove_stopwords($word_freq) {
        // 中文停用词列表(部分示例)
        $stopwords = array(
            '的', '了', '在', '是', '我', '有', '和', '就',
            '不', '人', '都', '一', '一个', '上', '也', '很',
            '到', '说', '要', '去', '你', '会', '着', '没有',
            '看', '好', '自己', '这', '那', '他', '她', '它'
        );
        
        // 英文停用词
        $english_stopwords = array(
            'a', 'an', 'the', 'and', 'or', 'but', 'in', 'on', 
            'at', 'to', 'for', 'of', 'with', 'by', 'is', 'are',
            'was', 'were', 'be', 'been', 'being', 'have', 'has',
            'had', 'having', 'do', 'does', 'did', 'doing'
        );
        
        $all_stopwords = array_merge($stopwords, $english_stopwords);
        
        foreach ($all_stopwords as $stopword) {
            if (isset($word_freq[$stopword])) {
                unset($word_freq[$stopword]);
            }
        }
        
        return $word_freq;
    }
    
    /**
     * 生成文本指纹(Simhash算法简化版)
     */
    public function generate_simhash($text) {
        $features = $this->extract_features($text, 64);
        
        $vector = array_fill(0, 64, 0);
        
        foreach ($features as $word => $weight) {
            $hash = crc32($word);
            
            for ($i = 0; $i < 64; $i++) {
                $bit = ($hash >> $i) & 1;
                if ($bit == 1) {
                    $vector[$i] += $weight;
                } else {
                    $vector[$i] -= $weight;
                }
            }
        }
        
        // 生成64位指纹
        $fingerprint = 0;
        for ($i = 0; $i < 64; $i++) {
            if ($vector[$i] > 0) {
                $fingerprint |= (1 << $i);
            }
        }
        
        return $fingerprint;
    }
}

3.2 相似度计算算法实现

创建includes/class-similarity-checker.php文件:

<?php
class SCC_Similarity_Checker {
    
    private $text_processor;
    
    public function __construct() {
        $this->text_processor = new SCC_Text_Processor();
    }
    
    /**
     * 计算余弦相似度
     */
    public function cosine_similarity($text1, $text2) {
        $features1 = $this->text_processor->extract_features($text1);
        $features2 = $this->text_processor->extract_features($text2);
        
        // 获取所有特征的并集
        $all_features = array_unique(array_merge(
            array_keys($features1),
            array_keys($features2)
        ));
        
        // 创建向量
        $vector1 = array();
        $vector2 = array();
        
        foreach ($all_features as $feature) {
            $vector1[] = isset($features1[$feature]) ? $features1[$feature] : 0;
            $vector2[] = isset($features2[$feature]) ? $features2[$feature] : 0;
        }
        
        // 计算点积
        $dot_product = 0;
        for ($i = 0; $i < count($vector1); $i++) {
            $dot_product += $vector1[$i] * $vector2[$i];
        }
        
        // 计算模长
        $magnitude1 = sqrt(array_sum(array_map(function($x) {
            return $x * $x;
        }, $vector1)));
        
        $magnitude2 = sqrt(array_sum(array_map(function($x) {
            return $x * $x;
        }, $vector2)));
        
        // 避免除以零
        if ($magnitude1 == 0 || $magnitude2 == 0) {
            return 0;
        }
        
        return $dot_product / ($magnitude1 * $magnitude2);
    }
    
    /**
     * 计算Jaccard相似系数
     */
    public function jaccard_similarity($text1, $text2) {
        $features1 = $this->text_processor->extract_features($text1);
        $features2 = $this->text_processor->extract_features($text2);
        
        $set1 = array_keys($features1);
        $set2 = array_keys($features2);
        
        $intersection = array_intersect($set1, $set2);
        $union = array_unique(array_merge($set1, $set2));
        
        if (count($union) == 0) {
            return 0;
        }
        
        return count($intersection) / count($union);
    }
    
    /**
     * 计算Simhash海明距离
     */
    public function simhash_distance($text1, $text2) {
        $hash1 = $this->text_processor->generate_simhash($text1);
        $hash2 = $this->text_processor->generate_simhash($text2);
        
        // 计算海明距离
        $xor = $hash1 ^ $hash2;
        $distance = 0;
        
        while ($xor) {
            $distance += $xor & 1;
            $xor >>= 1;
        }
        
        return $distance;
    }
    
    /**
     * 综合相似度评估
     */
    public function comprehensive_similarity($text1, $text2) {
        $cosine = $this->cosine_similarity($text1, $text2);
        $jaccard = $this->jaccard_similarity($text1, $text2);
        $simhash_distance = $this->simhash_distance($text1, $text2);
        
        // 将Simhash距离转换为相似度(距离越小,相似度越高)
        $simhash_similarity = max(0, 1 - ($simhash_distance / 64));
        
        // 加权平均
        $weights = array(
            'cosine' => 0.5,
            'jaccard' => 0.3,
            'simhash' => 0.2
        );
        
        $similarity = ($cosine * $weights['cosine']) + 
                     ($jaccard * $weights['jaccard']) + 
                     ($simhash_similarity * $weights['simhash']);
        
        return round($similarity, 4);
    }
    
    /**
     * 与外部API集成进行深度检测
     */
    public function external_api_check($text, $api_type = 'copyscape') {
        // 这里以Copyscape API为例
        $api_key = get_option('scc_copyscape_api_key', '');
        
        if (empty($api_key)) {
            return array(
                'success' => false,
                'message' => 'API密钥未配置'
            );
        }
        
        $encoded_text = urlencode($text);
        $url = "https://www.copyscape.com/api/?o=search&k={$api_key}&t={$encoded_text}&f=xml";
        
        $response = wp_remote_get($url, array(
            'timeout' => 30,
            'sslverify' => false
        ));
        
        if (is_wp_error($response)) {
            return array(
                'success' => false,
                'message' => $response->get_error_message()
            );
        }
        
        $body = wp_remote_retrieve_body($response);
        
        // 解析XML响应
        $xml = simplexml_load_string($body);
        
        if (!$xml) {
            return array(
                'success' => false,
                'message' => 'API响应解析失败'
            );
        }
        
        $results = array();
        
        if (isset($xml->result)) {
            foreach ($xml->result as $result) {
                $results[] = array(
                    'url' => (string)$result->url,
                    'title' => (string)$result->title,
                    'similarity' => (float)$result->minwordsmatched / 100
                );
            }
        }
        
        return array(
            'success' => true,
            'results' => $results
        );
    }
}

第四部分:数据库设计与数据管理

4.1 数据库表结构设计

创建includes/class-database.php文件:

<?php
class SCC_Database {
    
    /**
     * 创建必要的数据库表
     */
    public function create_tables() {
        global $wpdb;
        
        $charset_collate = $wpdb->get_charset_collate();
        $table_name = $wpdb->prefix . 'scc_content_fingerprints';
        $results_table = $wpdb->prefix . 'scc_scan_results';
        
        // 内容指纹表
        $sql1 = "CREATE TABLE IF NOT EXISTS $table_name (
            id bigint(20) NOT NULL AUTO_INCREMENT,
            post_id bigint(20) NOT NULL,
            fingerprint_64 bigint(20) UNSIGNED NOT NULL,
            fingerprint_128 varchar(255) DEFAULT NULL,
            content_hash varchar(64) NOT NULL,
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
            PRIMARY KEY (id),
            KEY post_id (post_id),
            KEY fingerprint_64 (fingerprint_64),
            KEY content_hash (content_hash)
        ) $charset_collate;";
        
        // 扫描结果表
        $sql2 = "CREATE TABLE IF NOT EXISTS $results_table (
            id bigint(20) NOT NULL AUTO_INCREMENT,
            post_id bigint(20) NOT NULL,
            scan_type varchar(50) NOT NULL,
            similarity_score float NOT NULL,
            matched_urls text,
            details text,
            scan_date datetime DEFAULT CURRENT_TIMESTAMP,
            status varchar(20) DEFAULT 'pending',
            PRIMARY KEY (id),
            KEY post_id (post_id),
            KEY scan_date (scan_date),
            KEY status (status)
        ) $charset_collate;";
        
        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
        dbDelta($sql1);
        dbDelta($sql2);
    }
    
    /**
     * 保存内容指纹
     */
    public function save_fingerprint($post_id, $fingerprint_64, $content_hash, $fingerprint_128 = null) {
        global $wpdb;
        
        $table_name = $wpdb->prefix . 'scc_content_fingerprints';
        
        // 检查是否已存在
        $existing = $wpdb->get_var($wpdb->prepare(
            "SELECT id FROM $table_name WHERE post_id = %d",
            $post_id
        ));
        
        if ($existing) {
            // 更新现有记录
            $wpdb->update(
                $table_name,
                array(
                    'fingerprint_64' => $fingerprint_64,
                    'fingerprint_128' => $fingerprint_128,
                    'content_hash' => $content_hash,
                    'updated_at' => current_time('mysql')
                ),
                ),
                array('%d', '%s', '%s', '%s'),
                array('%d')
            );
        } else {
            // 插入新记录
            $wpdb->insert(
                $table_name,
                array(
                    'post_id' => $post_id,
                    'fingerprint_64' => $fingerprint_64,
                    'fingerprint_128' => $fingerprint_128,
                    'content_hash' => $content_hash
                ),
                array('%d', '%d', '%s', '%s')
            );
        }
        
        return $wpdb->insert_id;
    }
    
    /**
     * 查找相似内容
     */
    public function find_similar_content($fingerprint_64, $threshold = 5, $exclude_post_id = 0) {
        global $wpdb;
        
        $table_name = $wpdb->prefix . 'scc_content_fingerprints';
        
        // 查找海明距离小于阈值的指纹
        $query = $wpdb->prepare(
            "SELECT p1.post_id, 
                    BIT_COUNT(p1.fingerprint_64 ^ %d) as hamming_distance,
                    p.post_title,
                    p.post_date
             FROM $table_name p1
             INNER JOIN {$wpdb->posts} p ON p1.post_id = p.ID
             WHERE BIT_COUNT(p1.fingerprint_64 ^ %d) <= %d
             AND p1.post_id != %d
             AND p.post_status = 'publish'
             ORDER BY hamming_distance ASC
             LIMIT 10",
            $fingerprint_64,
            $fingerprint_64,
            $threshold,
            $exclude_post_id
        );
        
        return $wpdb->get_results($query, ARRAY_A);
    }
    
    /**
     * 保存扫描结果
     */
    public function save_scan_result($post_id, $scan_type, $similarity_score, $matched_urls = '', $details = '') {
        global $wpdb;
        
        $table_name = $wpdb->prefix . 'scc_scan_results';
        
        $wpdb->insert(
            $table_name,
            array(
                'post_id' => $post_id,
                'scan_type' => $scan_type,
                'similarity_score' => $similarity_score,
                'matched_urls' => is_array($matched_urls) ? json_encode($matched_urls) : $matched_urls,
                'details' => is_array($details) ? json_encode($details) : $details,
                'status' => $similarity_score > 0.7 ? 'high_risk' : ($similarity_score > 0.3 ? 'medium_risk' : 'low_risk')
            ),
            array('%d', '%s', '%f', '%s', '%s', '%s')
        );
        
        return $wpdb->insert_id;
    }
    
    /**
     * 获取文章的扫描历史
     */
    public function get_scan_history($post_id, $limit = 10) {
        global $wpdb;
        
        $table_name = $wpdb->prefix . 'scc_scan_results';
        
        return $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM $table_name 
             WHERE post_id = %d 
             ORDER BY scan_date DESC 
             LIMIT %d",
            $post_id,
            $limit
        ), ARRAY_A);
    }
    
    /**
     * 获取高风险内容统计
     */
    public function get_risk_statistics($days = 30) {
        global $wpdb;
        
        $table_name = $wpdb->prefix . 'scc_scan_results';
        
        $query = $wpdb->prepare(
            "SELECT 
                COUNT(CASE WHEN status = 'high_risk' THEN 1 END) as high_risk_count,
                COUNT(CASE WHEN status = 'medium_risk' THEN 1 END) as medium_risk_count,
                COUNT(CASE WHEN status = 'low_risk' THEN 1 END) as low_risk_count,
                DATE(scan_date) as scan_date
             FROM $table_name
             WHERE scan_date >= DATE_SUB(NOW(), INTERVAL %d DAY)
             GROUP BY DATE(scan_date)
             ORDER BY scan_date DESC",
            $days
        );
        
        return $wpdb->get_results($query, ARRAY_A);
    }
}

第五部分:WordPress集成与自动化检测

5.1 核心插件类实现

创建includes/class-core.php文件:

<?php
class SCC_Core {
    
    private $db;
    private $text_processor;
    private $similarity_checker;
    
    public function __construct() {
        $this->db = new SCC_Database();
        $this->text_processor = new SCC_Text_Processor();
        $this->similarity_checker = new SCC_Similarity_Checker();
    }
    
    /**
     * 初始化插件
     */
    public function init() {
        // 创建数据库表
        register_activation_hook(__FILE__, array($this->db, 'create_tables'));
        
        // 添加WordPress钩子
        add_action('save_post', array($this, 'on_post_save'), 10, 3);
        add_action('publish_post', array($this, 'on_post_publish'), 10, 2);
        
        // 添加管理菜单
        add_action('admin_menu', array($this, 'add_admin_menu'));
        
        // 添加AJAX处理
        add_action('wp_ajax_scc_manual_scan', array($this, 'ajax_manual_scan'));
        add_action('wp_ajax_scc_bulk_scan', array($this, 'ajax_bulk_scan'));
        
        // 添加文章列表列
        add_filter('manage_posts_columns', array($this, 'add_post_columns'));
        add_action('manage_posts_custom_column', array($this, 'render_post_columns'), 10, 2);
        
        // 添加文章编辑页面元框
        add_action('add_meta_boxes', array($this, 'add_meta_boxes'));
    }
    
    /**
     * 文章保存时触发
     */
    public function on_post_save($post_id, $post, $update) {
        // 跳过自动保存和修订
        if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
            return;
        }
        
        if (wp_is_post_revision($post_id)) {
            return;
        }
        
        // 只处理特定文章类型
        $allowed_types = array('post', 'page');
        if (!in_array($post->post_type, $allowed_types)) {
            return;
        }
        
        // 获取文章内容
        $content = $post->post_content;
        
        // 生成内容哈希
        $content_hash = md5($content);
        
        // 生成指纹
        $fingerprint_64 = $this->text_processor->generate_simhash($content);
        
        // 保存指纹
        $this->db->save_fingerprint($post_id, $fingerprint_64, $content_hash);
        
        // 如果是更新操作,检查与历史版本的相似度
        if ($update) {
            $this->check_self_similarity($post_id, $content);
        }
    }
    
    /**
     * 文章发布时触发
     */
    public function on_post_publish($post_id, $post) {
        // 执行相似度检测
        $this->perform_similarity_check($post_id, $post->post_content);
    }
    
    /**
     * 执行相似度检测
     */
    private function perform_similarity_check($post_id, $content) {
        // 1. 内部相似度检测
        $fingerprint_64 = $this->text_processor->generate_simhash($content);
        $similar_posts = $this->db->find_similar_content($fingerprint_64, 5, $post_id);
        
        $internal_similarity = 0;
        $matched_posts = array();
        
        if (!empty($similar_posts)) {
            foreach ($similar_posts as $similar_post) {
                $similar_post_content = get_post_field('post_content', $similar_post['post_id']);
                $similarity = $this->similarity_checker->comprehensive_similarity($content, $similar_post_content);
                
                if ($similarity > $internal_similarity) {
                    $internal_similarity = $similarity;
                }
                
                if ($similarity > 0.3) {
                    $matched_posts[] = array(
                        'post_id' => $similar_post['post_id'],
                        'title' => $similar_post['post_title'],
                        'similarity' => $similarity,
                        'url' => get_permalink($similar_post['post_id'])
                    );
                }
            }
        }
        
        // 2. 外部API检测(可选)
        $external_results = array();
        if (get_option('scc_enable_external_check', false)) {
            $external_check = $this->similarity_checker->external_api_check($content);
            if ($external_check['success']) {
                $external_results = $external_check['results'];
            }
        }
        
        // 计算综合相似度
        $total_similarity = $internal_similarity;
        if (!empty($external_results)) {
            $external_similarity = max(array_column($external_results, 'similarity'));
            $total_similarity = max($total_similarity, $external_similarity);
        }
        
        // 保存结果
        $this->db->save_scan_result(
            $post_id,
            'auto',
            $total_similarity,
            array_merge($matched_posts, $external_results),
            array(
                'internal_similarity' => $internal_similarity,
                'matched_posts' => $matched_posts,
                'external_results' => $external_results
            )
        );
        
        // 发送通知
        if ($total_similarity > get_option('scc_notification_threshold', 0.7)) {
            $this->send_notification($post_id, $total_similarity);
        }
        
        return $total_similarity;
    }
    
    /**
     * 检查与历史版本的相似度
     */
    private function check_self_similarity($post_id, $current_content) {
        $revisions = wp_get_post_revisions($post_id);
        
        if (empty($revisions)) {
            return;
        }
        
        // 获取最新修订版
        $latest_revision = reset($revisions);
        $revision_content = $latest_revision->post_content;
        
        $similarity = $this->similarity_checker->comprehensive_similarity($current_content, $revision_content);
        
        // 如果相似度低于阈值,记录重大修改
        if ($similarity < 0.5) {
            $this->db->save_scan_result(
                $post_id,
                'revision_check',
                $similarity,
                array(),
                array(
                    'message' => '检测到文章内容发生重大修改',
                    'revision_id' => $latest_revision->ID,
                    'similarity_with_revision' => $similarity
                )
            );
        }
    }
    
    /**
     * 发送通知
     */
    private function send_notification($post_id, $similarity) {
        $post = get_post($post_id);
        $author = get_userdata($post->post_author);
        $admin_email = get_option('admin_email');
        
        $subject = sprintf('【内容相似度警报】文章 "%s" 检测到高相似度内容', $post->post_title);
        
        $message = sprintf(
            "文章标题:%sn" .
            "文章ID:%dn" .
            "作者:%sn" .
            "检测相似度:%.2f%%n" .
            "文章链接:%sn" .
            "编辑链接:%snn" .
            "请及时审核该文章内容。",
            $post->post_title,
            $post_id,
            $author->display_name,
            $similarity * 100,
            get_permalink($post_id),
            admin_url('post.php?post=' . $post_id . '&action=edit')
        );
        
        // 发送给管理员
        wp_mail($admin_email, $subject, $message);
        
        // 如果设置了作者通知,也发送给作者
        if (get_option('scc_notify_author', false)) {
            wp_mail($author->user_email, $subject, $message);
        }
    }
}

5.2 管理界面实现

创建includes/class-admin-interface.php文件:

<?php
class SCC_Admin_Interface {
    
    private $db;
    
    public function __construct() {
        $this->db = new SCC_Database();
    }
    
    /**
     * 添加管理菜单
     */
    public function add_admin_menu() {
        // 主菜单
        add_menu_page(
            '内容相似度检测',
            '内容检测',
            'manage_options',
            'scc-dashboard',
            array($this, 'render_dashboard_page'),
            'dashicons-search',
            30
        );
        
        // 子菜单
        add_submenu_page(
            'scc-dashboard',
            '批量检测',
            '批量检测',
            'manage_options',
            'scc-bulk-scan',
            array($this, 'render_bulk_scan_page')
        );
        
        add_submenu_page(
            'scc-dashboard',
            '检测设置',
            '设置',
            'manage_options',
            'scc-settings',
            array($this, 'render_settings_page')
        );
        
        add_submenu_page(
            'scc-dashboard',
            '检测报告',
            '报告统计',
            'manage_options',
            'scc-reports',
            array($this, 'render_reports_page')
        );
    }
    
    /**
     * 渲染仪表盘页面
     */
    public function render_dashboard_page() {
        ?>
        <div class="wrap scc-dashboard">
            <h1><?php echo esc_html(get_admin_page_title()); ?></h1>
            
            <div class="scc-stats-container">
                <div class="scc-stat-card">
                    <h3>今日检测</h3>
                    <div class="stat-number"><?php echo $this->get_today_scan_count(); ?></div>
                </div>
                
                <div class="scc-stat-card">
                    <h3>高风险内容</h3>
                    <div class="stat-number" style="color: #dc3232;"><?php echo $this->get_high_risk_count(); ?></div>
                </div>
                
                <div class="scc-stat-card">
                    <h3>平均相似度</h3>
                    <div class="stat-number"><?php echo $this->get_average_similarity(); ?>%</div>
                </div>
                
                <div class="scc-stat-card">
                    <h3>已保护文章</h3>
                    <div class="stat-number"><?php echo $this->get_protected_post_count(); ?></div>
                </div>
            </div>
            
            <div class="scc-quick-actions">
                <h2>快速操作</h2>
                <button class="button button-primary" onclick="sccQuickScan()">快速扫描最新文章</button>
                <button class="button" onclick="window.location.href='?page=scc-bulk-scan'">批量检测</button>
                <button class="button" onclick="window.location.href='?page=scc-reports'">查看完整报告</button>
            </div>
            
            <div class="scc-recent-scans">
                <h2>最近检测记录</h2>
                <?php $this->render_recent_scans_table(); ?>
            </div>
            
            <script>
            function sccQuickScan() {
                jQuery.post(ajaxurl, {
                    action: 'scc_manual_scan',
                    post_ids: 'recent',
                    nonce: '<?php echo wp_create_nonce('scc_manual_scan'); ?>'
                }, function(response) {
                    if (response.success) {
                        alert('扫描完成!检测到 ' + response.data.high_risk + ' 篇高风险文章');
                        location.reload();
                    } else {
                        alert('扫描失败:' + response.data);
                    }
                });
            }
            </script>
            
            <style>
            .scc-stats-container {
                display: grid;
                grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
                gap: 20px;
                margin: 20px 0;
            }
            
            .scc-stat-card {
                background: white;
                padding: 20px;
                border-radius: 8px;
                box-shadow: 0 2px 4px rgba(0,0,0,0.1);
                text-align: center;
            }
            
            .scc-stat-card h3 {
                margin-top: 0;
                color: #666;
            }
            
            .scc-stat-card .stat-number {
                font-size: 2.5em;
                font-weight: bold;
                color: #0073aa;
            }
            
            .scc-quick-actions {
                background: white;
                padding: 20px;
                border-radius: 8px;
                box-shadow: 0 2px 4px rgba(0,0,0,0.1);
                margin: 20px 0;
            }
            
            .scc-quick-actions button {
                margin-right: 10px;
                margin-bottom: 10px;
            }
            </style>
        </div>
        <?php
    }
    
    /**
     * 渲染批量检测页面
     */
    public function render_bulk_scan_page() {
        ?>
        <div class="wrap">
            <h1>批量内容检测</h1>
            
            <div class="card">
                <h2>选择检测范围</h2>
                <form id="scc-bulk-scan-form">
                    <table class="form-table">
                        <tr>
                            <th scope="row">文章类型</th>
                            <td>
                                <select name="post_type" id="post_type">
                                    <option value="post">文章</option>
                                    <option value="page">页面</option>
                                    <option value="all">所有内容</option>
本文来自网络,不代表柔性供应链服务中心立场,转载请注明出处:https://mall.org.cn/5218.html

EXCHANGES®作者

上一篇
下一篇

为您推荐

发表回复

联系我们

联系我们

18559313275

在线咨询: QQ交谈

邮箱: vip@exchanges.center

工作时间:周一至周五,9:00-17:30,节假日休息
返回顶部