文章目录
-
- 在当今信息爆炸的时代,网络传媒网站面临着内容过载的挑战。用户往往没有时间阅读完整的文章,而一个精准、吸引人的摘要可以显著提高点击率和用户留存率。本教程将指导您开发一个WordPress智能摘要生成插件,该插件能够根据文章内容自动生成柔性、可定制的摘要,特别适合新闻、博客和内容聚合类网站。
- 我们的智能摘要插件将包含以下核心功能: 自动提取文章关键内容生成摘要 支持多种摘要生成算法 可自定义摘要长度和风格 提供手动编辑摘要的选项 支持多语言内容处理 缓存机制提高性能
- 在开始开发之前,请确保您具备以下环境: WordPress 5.0+ 安装 PHP 7.2+ 环境 基础的HTML/CSS/JavaScript知识 文本编辑器或IDE
- 首先,我们创建插件的基本目录结构: wp-content/plugins/ └── smart-content-summary/ ├── smart-content-summary.php # 主插件文件 ├── includes/ │ ├── class-summary-generator.php # 摘要生成核心类 │ ├── class-admin-interface.php # 管理界面类 │ └── class-cache-handler.php # 缓存处理类 ├── assets/ │ ├── css/ │ │ └── admin-style.css # 管理界面样式 │ └── js/ │ └── admin-script.js # 管理界面脚本 └── languages/ # 国际化文件
- 创建主插件文件 smart-content-summary.php: <?php /** * 插件名称: Smart Content Summary * 插件URI: https://yourwebsite.com/ * 描述: 智能内容摘要生成插件,为网络传媒网站提供柔性摘要生成功能 * 版本: 1.0.0 * 作者: Your Name * 作者URI: https://yourwebsite.com/ * 许可证: GPL v2 or later * 文本域: smart-content-summary */ // 防止直接访问 if (!defined('ABSPATH')) { exit; } // 定义插件常量 define('SCS_VERSION', '1.0.0'); define('SCS_PLUGIN_DIR', plugin_dir_path(__FILE__)); define('SCS_PLUGIN_URL', plugin_dir_url(__FILE__)); // 自动加载类文件 spl_autoload_register(function ($class_name) { if (strpos($class_name, 'SCS_') === 0) { $file = SCS_PLUGIN_DIR . 'includes/class-' . strtolower(str_replace('_', '-', $class_name)) . '.php'; if (file_exists($file)) { require_once $file; } } }); // 初始化插件 function scs_init_plugin() { // 检查WordPress版本 if (version_compare(get_bloginfo('version'), '5.0', '<')) { add_action('admin_notices', function() { echo '<div class="notice notice-error"><p>'; echo __('Smart Content Summary 需要 WordPress 5.0 或更高版本', 'smart-content-summary'); echo '</p></div>'; }); return; } // 初始化核心类 $summary_generator = new SCS_Summary_Generator(); $admin_interface = new SCS_Admin_Interface(); // 注册激活和停用钩子 register_activation_hook(__FILE__, 'scs_activate_plugin'); register_deactivation_hook(__FILE__, 'scs_deactivate_plugin'); } add_action('plugins_loaded', 'scs_init_plugin'); // 插件激活函数 function scs_activate_plugin() { // 创建必要的数据库表 global $wpdb; $charset_collate = $wpdb->get_charset_collate(); $table_name = $wpdb->prefix . 'scs_summary_cache'; $sql = "CREATE TABLE IF NOT EXISTS $table_name ( id bigint(20) NOT NULL AUTO_INCREMENT, post_id bigint(20) NOT NULL, content_hash varchar(32) NOT NULL, summary text NOT NULL, algorithm varchar(50) NOT NULL, created_at datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY post_id (post_id), KEY content_hash (content_hash) ) $charset_collate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); // 设置默认选项 $default_options = array( 'default_length' => 150, 'default_algorithm' => 'extractive', 'enable_cache' => true, 'cache_duration' => 86400, // 24小时 'auto_generate' => true ); add_option('scs_settings', $default_options); } // 插件停用函数 function scs_deactivate_plugin() { // 清理定时任务 wp_clear_scheduled_hook('scs_daily_cleanup'); }
- 创建 includes/class-summary-generator.php: <?php /** * 智能摘要生成核心类 * 提供多种摘要生成算法 */ class SCS_Summary_Generator { private $settings; public function __construct() { $this->settings = get_option('scs_settings', array()); // 注册文章保存钩子 add_action('save_post', array($this, 'generate_summary_on_save'), 10, 3); // 添加摘要到文章内容 add_filter('the_content', array($this, 'add_summary_to_content'), 5); } /** * 在文章保存时生成摘要 */ public function generate_summary_on_save($post_id, $post, $update) { // 检查自动生成设置 if (!$this->settings['auto_generate'] ?? true) { return; } // 检查文章类型 if (!in_array($post->post_type, array('post', 'page'))) { return; } // 检查是否自动保存或修订 if (wp_is_post_autosave($post_id) || wp_is_post_revision($post_id)) { return; } // 生成摘要 $summary = $this->generate_summary($post->post_content, $post_id); // 保存摘要到文章元数据 if ($summary) { update_post_meta($post_id, '_scs_auto_summary', $summary); } } /** * 生成摘要的主函数 * @param string $content 文章内容 * @param int $post_id 文章ID * @return string 生成的摘要 */ public function generate_summary($content, $post_id = null) { // 清理HTML标签,获取纯文本 $plain_text = wp_strip_all_tags($content); // 检查缓存 if ($this->settings['enable_cache'] ?? true && $post_id) { $cached_summary = $this->get_cached_summary($post_id, $plain_text); if ($cached_summary) { return $cached_summary; } } // 根据设置选择算法 $algorithm = $this->settings['default_algorithm'] ?? 'extractive'; $summary = ''; switch ($algorithm) { case 'extractive': $summary = $this->extractive_summary($plain_text); break; case 'abstractive': $summary = $this->abstractive_summary($plain_text); break; case 'lead_paragraph': $summary = $this->lead_paragraph_summary($plain_text); break; default: $summary = $this->extractive_summary($plain_text); } // 缓存结果 if ($this->settings['enable_cache'] ?? true && $post_id) { $this->cache_summary($post_id, $plain_text, $summary, $algorithm); } return $summary; } /** * 提取式摘要算法 * 从原文中提取最重要的句子 */ private function extractive_summary($text, $max_length = null) { if (is_null($max_length)) { $max_length = $this->settings['default_length'] ?? 150; } // 分割成句子 $sentences = $this->split_sentences($text); if (count($sentences) <= 1) { return $text; } // 计算句子权重(简单实现:基于位置和关键词) $weighted_sentences = array(); $total_sentences = count($sentences); for ($i = 0; $i < $total_sentences; $i++) { $sentence = $sentences[$i]; $weight = 0; // 位置权重:开头和结尾的句子更重要 if ($i < 2) { $weight += 0.3; // 前两句 } elseif ($i > $total_sentences - 3) { $weight += 0.2; // 最后两句 } // 长度权重:中等长度的句子更好 $sentence_length = strlen($sentence); if ($sentence_length > 50 && $sentence_length < 150) { $weight += 0.2; } // 关键词权重(简单实现:检查常见关键词) $keywords = array('总结', '因此', '所以', '然而', '重要的是', '关键'); foreach ($keywords as $keyword) { if (strpos($sentence, $keyword) !== false) { $weight += 0.1; } } $weighted_sentences[] = array( 'sentence' => $sentence, 'weight' => $weight, 'original_index' => $i ); } // 按权重排序 usort($weighted_sentences, function($a, $b) { return $b['weight'] <=> $a['weight']; }); // 选择最重要的句子,直到达到最大长度 $summary = ''; $current_length = 0; // 按原始顺序排序选中的句子 $selected_sentences = array(); foreach ($weighted_sentences as $item) { if ($current_length + strlen($item['sentence']) <= $max_length) { $selected_sentences[$item['original_index']] = $item['sentence']; $current_length += strlen($item['sentence']); } } ksort($selected_sentences); $summary = implode('。', $selected_sentences) . '。'; // 如果摘要太短,使用前导段落方法 if (strlen($summary) < $max_length / 2) { $summary = $this->lead_paragraph_summary($text, $max_length); } return $summary; } /** * 抽象式摘要算法(简化版) * 注意:完整的抽象式摘要需要NLP和机器学习模型 * 这里提供一个简化版本,使用规则和同义词替换 */ private function abstractive_summary($text, $max_length = null) { if (is_null($max_length)) { $max_length = $this->settings['default_length'] ?? 150; } // 首先使用提取式方法获取关键句子 $extractive = $this->extractive_summary($text, $max_length * 1.5); // 简化句子结构(这里是一个简单示例) $simplified = $this->simplify_sentences($extractive); // 截断到指定长度 if (strlen($simplified) > $max_length) { $simplified = mb_substr($simplified, 0, $max_length) . '...'; } return $simplified; } /** * 前导段落摘要算法 * 提取文章开头的部分作为摘要 */ private function lead_paragraph_summary($text, $max_length = null) { if (is_null($max_length)) { $max_length = $this->settings['default_length'] ?? 150; } // 清理多余空白 $text = preg_replace('/s+/', ' ', $text); // 截取前导部分 if (strlen($text) > $max_length) { $summary = mb_substr($text, 0, $max_length); // 确保在完整的句子处结束 $last_period = strrpos($summary, '。'); if ($last_period > $max_length * 0.7) { $summary = substr($summary, 0, $last_period + 3); } else { $summary .= '...'; } } else { $summary = $text; } return $summary; } /** * 分割句子 */ private function split_sentences($text) { // 中文句子分割(简单实现) $sentences = preg_split('/(?<=[。!?])/u', $text, -1, PREG_SPLIT_NO_EMPTY); return array_filter($sentences, function($sentence) { return trim($sentence) !== ''; }); } /** * 简化句子(抽象式摘要的辅助函数) */ private function simplify_sentences($text) { // 这里可以添加更复杂的NLP处理 // 目前只是一个简单示例 // 移除一些修饰性短语 $patterns = array( '/毫无疑问,/' => '', '/可以说,/' => '', '/值得注意的是,/' => '', '/总的来说,/' => '', ); $simplified = preg_replace(array_keys($patterns), array_values($patterns), $text); return $simplified; } /** * 从缓存获取摘要 */ private function get_cached_summary($post_id, $content) { global $wpdb; $table_name = $wpdb->prefix . 'scs_summary_cache'; $content_hash = md5($content); $cache_duration = $this->settings['cache_duration'] ?? 86400; $expiry_time = date('Y-m-d H:i:s', time() - $cache_duration); $query = $wpdb->prepare( "SELECT summary FROM $table_name WHERE post_id = %d AND content_hash = %s AND created_at > %s LIMIT 1", $post_id, $content_hash, $expiry_time ); return $wpdb->get_var($query); } /** * 缓存摘要 */ private function cache_summary($post_id, $content, $summary, $algorithm) { global $wpdb; $table_name = $wpdb->prefix . 'scs_summary_cache'; $content_hash = md5($content); // 删除旧缓存 $wpdb->delete( $table_name, array('post_id' => $post_id, 'content_hash' => $content_hash), array('%d', '%s') ); // 插入新缓存 $wpdb->insert( $table_name, array( 'post_id' => $post_id, 'content_hash' => $content_hash, 'summary' => $summary, 'algorithm' => $algorithm ), array('%d', '%s', '%s', '%s') ); } /** * 将摘要添加到文章内容 */ public function add_summary_to_content($content) { if (!is_single() && !is_page()) { return $content; } global $post; $summary = get_post_meta($post->ID, '_scs_auto_summary', true); if (!$summary) { return $content; } // 创建摘要显示框 $summary_html = '<div class="scs-content-summary">'; $summary_html .= '<h3>' . __('内容摘要', 'smart-content-summary') . '</h3>'; $summary_html .= '<p>' . esc_html($summary) . '</p>'; $summary_html .= '</div>'; // 将摘要添加到内容开头 return $summary_html . $content; } }
- 创建 includes/class-admin-interface.php: <?php /** * 插件管理界面类 * 提供设置页面和文章编辑界面集成 */ class SCS_Admin_Interface { public function __construct() { // 添加设置菜单 add_action('admin_menu', array($this, 'add_admin_menu')); // 注册设置 add_action('admin_init', array($this, 'register_settings')); // 在文章编辑页面添加元框 add_action('add_meta_boxes', array($this, 'add_meta_boxes')); // 保存元框数据 add_action('save_post', array($this, 'save_meta_box_data'), 10, 2); // 添加文章列表列 add_filter('manage_posts_columns', array($this, 'add_summary_column')); add_action('manage_posts_custom_column', array($this, 'display_summary_column'), 10, 2); } /** * 添加管理菜单 */ public function add_admin_menu() { add_options_page( __('智能摘要设置', 'smart-content-summary'), 'manage_options', 'smart-content-summary', array($this, 'display_settings_page') ); } /** * 显示设置页面 */ public function display_settings_page() { ?> <div class="wrap"> <h1><?php echo esc_html__('智能内容摘要设置', 'smart-content-summary'); ?></h1> <form method="post" action="options.php"> <?php settings_fields('scs_settings_group'); do_settings_sections('smart-content-summary'); submit_button(); ?> </form> <div class="scs-test-section"> <h2><?php echo esc_html__('摘要生成测试', 'smart-content-summary'); ?></h2> <textarea id="scs-test-content" rows="6" style="width:100%;" placeholder="<?php echo esc_attr__('在此输入测试内容...', 'smart-content-summary'); ?>"></textarea> <div style="margin: 10px 0;"> <label for="scs-test-algorithm"><?php echo esc_html__('算法选择:', 'smart-content-summary'); ?></label> <select id="scs-test-algorithm"> <option value="extractive"><?php echo esc_html__('提取式摘要', 'smart-content-summary'); ?></option> <option value="abstractive"><?php echo esc_html__('抽象式摘要', 'smart-content-summary'); ?></option> <option value="lead_paragraph"><?php echo esc_html__('前导段落', 'smart-content-summary'); ?></option> </select> <label for="scs-test-length" style="margin-left:20px;"><?php echo esc_html__('长度:', 'smart-content-summary'); ?></label> <input type="number" id="scs-test-length" value="150" min="50" max="500"> <button type="button" id="scs-test-button" class="button button-primary"><?php echo esc_html__('生成测试摘要', 'smart-content-summary'); ?></button> </div> <div id="scs-test-result" style="background:#f5f5f5; padding:15px; border:1px solid #ddd; display:none;"> <h4><?php echo esc_html__('生成结果:', 'smart-content-summary'); ?></h4> <p id="scs-test-result-text"></p> </div> </div> </div> <script> jQuery(document).ready(function($) { $('#scs-test-button').on('click', function() { var content = $('#scs-test-content').val(); var algorithm = $('#scs-test-algorithm').val(); var length = $('#scs-test-length').val(); if (!content.trim()) { alert('<?php echo esc_js(__('请输入测试内容', 'smart-content-summary')); ?>'); return; } $(this).prop('disabled', true).text('<?php echo esc_js(__('生成中...', 'smart-content-summary')); ?>'); $.ajax({ url: ajaxurl, type: 'POST', data: { action: 'scs_test_summary', content: content, algorithm: algorithm, length: length, nonce: '<?php echo wp_create_nonce("scs_test_nonce"); ?>' }, success: function(response) { if (response.success) { $('#scs-test-result-text').text(response.data.summary); $('#scs-test-result').show(); } else { alert(response.data || '<?php echo esc_js(__('生成失败', 'smart-content-summary')); ?>'); } }, complete: function() { $('#scs-test-button').prop('disabled', false).text('<?php echo esc_js(__('生成测试摘要', 'smart-content-summary')); ?>'); } }); }); }); </script> <?php } /** * 注册设置 */ public function register_settings() { register_setting('scs_settings_group', 'scs_settings', array($this, 'sanitize_settings')); // 基本设置部分 add_settings_section( 'scs_basic_settings', __('基本设置', 'smart-content-summary'), array($this, 'render_basic_settings_section'), 'smart-content-summary' ); // 算法设置部分 add_settings_section( 'scs_algorithm_settings', __('算法设置', 'smart-content-summary'), array($this, 'render_algorithm_settings_section'), 'smart-content-summary' ); // 高级设置部分 add_settings_section( 'scs_advanced_settings', __('高级设置', 'smart-content-summary'), array($this, 'render_advanced_settings_section'), 'smart-content-summary' ); // 添加各个设置字段 $this->add_settings_fields(); } /** * 添加设置字段 */ private function add_settings_fields() { // 默认摘要长度 add_settings_field( 'default_length', __('默认摘要长度', 'smart-content-summary'), array($this, 'render_default_length_field'), 'smart-content-summary', 'scs_basic_settings' ); // 默认算法 add_settings_field( 'default_algorithm', __('默认摘要算法', 'smart-content-summary'), array($this, 'render_default_algorithm_field'), 'smart-content-summary', 'scs_algorithm_settings' ); // 自动生成 add_settings_field( 'auto_generate', __('自动生成摘要', 'smart-content-summary'), array($this, 'render_auto_generate_field'), 'smart-content-summary', 'scs_basic_settings' ); // 缓存设置 add_settings_field( 'enable_cache', __('启用缓存', 'smart-content-summary'), array($this, 'render_enable_cache_field'), 'smart-content-summary', 'scs_advanced_settings' ); // 缓存时长 add_settings_field( 'cache_duration', __('缓存时长(秒)', 'smart-content-summary'), array($this, 'render_cache_duration_field'), 'smart-content-summary', 'scs_advanced_settings' ); } /** * 渲染设置字段 */ public function render_default_length_field() { $settings = get_option('scs_settings'); $value = $settings['default_length'] ?? 150; ?> <input type="number" name="scs_settings[default_length]" value="<?php echo esc_attr($value); ?>" min="50" max="1000"> <p class="description"><?php echo esc_html__('摘要的默认字符长度', 'smart-content-summary'); ?></p> <?php } public function render_default_algorithm_field() { $settings = get_option('scs_settings'); $value = $settings['default_algorithm'] ?? 'extractive'; ?> <select name="scs_settings[default_algorithm]"> <option value="extractive" <?php selected($value, 'extractive'); ?>><?php echo esc_html__('提取式摘要', 'smart-content-summary'); ?></option> <option value="abstractive" <?php selected($value, 'abstractive'); ?>><?php echo esc_html__('抽象式摘要', 'smart-content-summary'); ?></option> <option value="lead_paragraph" <?php selected($value, 'lead_paragraph'); ?>><?php echo esc_html__('前导段落', 'smart-content-summary'); ?></option> </select> <p class="description"><?php echo esc_html__('选择默认的摘要生成算法', 'smart-content-summary'); ?></p> <?php } public function render_auto_generate_field() { $settings = get_option('scs_settings'); $value = $settings['auto_generate'] ?? true; ?> <label> <input type="checkbox" name="scs_settings[auto_generate]" value="1" <?php checked($value, true); ?>> <?php echo esc_html__('保存文章时自动生成摘要', 'smart-content-summary'); ?> </label> <?php } public function render_enable_cache_field() { $settings = get_option('scs_settings'); $value = $settings['enable_cache'] ?? true; ?> <label> <input type="checkbox" name="scs_settings[enable_cache]" value="1" <?php checked($value, true); ?>> <?php echo esc_html__('启用摘要缓存以提高性能', 'smart-content-summary'); ?> </label> <?php } public function render_cache_duration_field() { $settings = get_option('scs_settings'); $value = $settings['cache_duration'] ?? 86400; ?> <input type="number" name="scs_settings[cache_duration]" value="<?php echo esc_attr($value); ?>" min="3600" max="2592000"> <p class="description"><?php echo esc_html__('缓存过期时间,默认24小时(86400秒)', 'smart-content-summary'); ?></p> <?php } /** * 渲染设置部分描述 */ public function render_basic_settings_section() { echo '<p>' . esc_html__('配置插件的基本行为', 'smart-content-summary') . '</p>'; } public function render_algorithm_settings_section() { echo '<p>' . esc_html__('配置摘要生成算法', 'smart-content-summary') . '</p>'; } public function render_advanced_settings_section() { echo '<p>' . esc_html__('高级性能配置选项', 'smart-content-summary') . '</p>'; } /** * 清理设置数据 */ public function sanitize_settings($input) { $sanitized = array(); $sanitized['default_length'] = absint($input['default_length'] ?? 150); if ($sanitized['default_length'] < 50) $sanitized['default_length'] = 50; if ($sanitized['default_length'] > 1000) $sanitized['default_length'] = 1000; $sanitized['default_algorithm'] = sanitize_text_field($input['default_algorithm'] ?? 'extractive'); $allowed_algorithms = array('extractive', 'abstractive', 'lead_paragraph'); if (!in_array($sanitized['default_algorithm'], $allowed_algorithms)) { $sanitized['default_algorithm'] = 'extractive'; } $sanitized['auto_generate'] = !empty($input['auto_generate']); $sanitized['enable_cache'] = !empty($input['enable_cache']); $sanitized['cache_duration'] = absint($input['cache_duration'] ?? 86400); return $sanitized; } /** * 添加文章编辑页面的元框 */ public function add_meta_boxes() { $post_types = apply_filters('scs_post_types', array('post', 'page')); foreach ($post_types as $post_type) { add_meta_box( 'scs_summary_meta_box', __('智能内容摘要', 'smart-content-summary'), array($this, 'render_meta_box'), $post_type, 'normal', 'high' ); } } /** * 渲染元框内容 */ public function render_meta_box($post) { wp_nonce_field('scs_summary_meta_box', 'scs_summary_nonce'); $auto_summary = get_post_meta($post->ID, '_scs_auto_summary', true); $manual_summary = get_post_meta($post->ID, '_scs_manual_summary', true); $use_manual = get_post_meta($post->ID, '_scs_use_manual', true); ?> <div class="scs-meta-box"> <div style="margin-bottom: 15px;"> <label> <input type="radio" name="scs_summary_type" value="auto" <?php checked(!$use_manual); ?>> <?php echo esc_html__('自动生成摘要', 'smart-content-summary'); ?> </label> <label style="margin-left: 20px;"> <input type="radio" name="scs_summary_type" value="manual" <?php checked($use_manual); ?>> <?php echo esc_html__('手动编辑摘要', 'smart-content-summary'); ?> </label> </div> <div id="scs-auto-summary-section" style="<?php echo $use_manual ? 'display:none;' : ''; ?>"> <p><strong><?php echo esc_html__('自动生成的摘要:', 'smart-content-summary'); ?></strong></p> <textarea id="scs-auto-summary" rows="4" style="width:100%;" readonly><?php echo esc_textarea($auto_summary); ?></textarea> <button type="button" id="scs-regenerate-button" class="button button-secondary" style="margin-top:10px;"> <?php echo esc_html__('重新生成摘要', 'smart-content-summary'); ?> </button> </div> <div id="scs-manual-summary-section" style="<?php echo !$use_manual ? 'display:none;' : ''; ?>"> <p><strong><?php echo esc_html__('手动编辑摘要:', 'smart-content-summary'); ?></strong></p> <textarea name="scs_manual_summary" rows="4" style="width:100%;"><?php echo esc_textarea($manual_summary); ?></textarea> </div> <input type="hidden" id="scs_auto_summary" name="scs_auto_summary" value="<?php echo esc_attr($auto_summary); ?>"> </div> <script> jQuery(document).ready(function($) { // 切换摘要类型 $('input[name="scs_summary_type"]').on('change', function() { if ($(this).val() === 'auto') { $('#scs-auto-summary-section').show(); $('#scs-manual-summary-section').hide(); } else { $('#scs-auto-summary-section').hide(); $('#scs-manual-summary-section').show(); } }); // 重新生成摘要 $('#scs-regenerate-button').on('click', function() { if (!confirm('<?php echo esc_js(__('确定要重新生成摘要吗?', 'smart-content-summary')); ?>')) { return; } $(this).prop('disabled', true).text('<?php echo esc_js(__('生成中...', 'smart-content-summary')); ?>'); $.ajax({ url: ajaxurl, type: 'POST', data: { action: 'scs_regenerate_summary', post_id: <?php echo $post->ID; ?>, nonce: '<?php echo wp_create_nonce("scs_regenerate_nonce"); ?>' }, success: function(response) { if (response.success) { $('#scs-auto-summary').val(response.data.summary); $('#scs_auto_summary').val(response.data.summary); } else { alert(response.data || '<?php echo esc_js(__('生成失败', 'smart-content-summary')); ?>'); } }, complete: function() { $('#scs-regenerate-button').prop('disabled', false).text('<?php echo esc_js(__('重新生成摘要', 'smart-content-summary')); ?>'); } }); }); }); </script> <?php } /** * 保存元框数据 */ public function save_meta_box_data($post_id, $post) { // 检查nonce if (!isset($_POST['scs_summary_nonce']) || !wp_verify_nonce($_POST['scs_summary_nonce'], 'scs_summary_meta_box')) { return; } // 检查权限 if (!current_user_can('edit_post', $post_id)) { return; } // 检查自动保存 if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return; } // 保存摘要类型 $use_manual = ($_POST['scs_summary_type'] ?? 'auto') === 'manual'; update_post_meta($post_id, '_scs_use_manual', $use_manual); // 保存自动生成的摘要 if (isset($_POST['scs_auto_summary'])) { update_post_meta($post_id, '_scs_auto_summary', sanitize_textarea_field($_POST['scs_auto_summary'])); } // 保存手动编辑的摘要 if (isset($_POST['scs_manual_summary'])) { update_post_meta($post_id, '_scs_manual_summary', sanitize_textarea_field($_POST['scs_manual_summary'])); } } /** * 添加文章列表列 */ public function add_summary_column($columns) { $columns['scs_summary'] = __('智能摘要', 'smart-content-summary'); return $columns; } /** * 显示文章列表列内容 */ public function display_summary_column($column, $post_id) { if ($column !== 'scs_summary') { return; } $use_manual = get_post_meta($post_id, '_scs_use_manual', true); if ($use_manual) { $summary = get_post_meta($post_id, '_scs_manual_summary', true); $type = __('手动', 'smart-content-summary'); } else { $summary = get_post_meta($post_id, '_scs_auto_summary', true);
在当今信息爆炸的时代,网络传媒网站面临着内容过载的挑战。用户往往没有时间阅读完整的文章,而一个精准、吸引人的摘要可以显著提高点击率和用户留存率。本教程将指导您开发一个WordPress智能摘要生成插件,该插件能够根据文章内容自动生成柔性、可定制的摘要,特别适合新闻、博客和内容聚合类网站。
我们的智能摘要插件将包含以下核心功能:
- 自动提取文章关键内容生成摘要
- 支持多种摘要生成算法
- 可自定义摘要长度和风格
- 提供手动编辑摘要的选项
- 支持多语言内容处理
- 缓存机制提高性能
在开始开发之前,请确保您具备以下环境:
- WordPress 5.0+ 安装
- PHP 7.2+ 环境
- 基础的HTML/CSS/JavaScript知识
- 文本编辑器或IDE
首先,我们创建插件的基本目录结构:
wp-content/plugins/
└── smart-content-summary/
├── smart-content-summary.php # 主插件文件
├── includes/
│ ├── class-summary-generator.php # 摘要生成核心类
│ ├── class-admin-interface.php # 管理界面类
│ └── class-cache-handler.php # 缓存处理类
├── assets/
│ ├── css/
│ │ └── admin-style.css # 管理界面样式
│ └── js/
│ └── admin-script.js # 管理界面脚本
└── languages/ # 国际化文件
创建主插件文件 smart-content-summary.php:
<?php
/**
* 插件名称: Smart Content Summary
* 插件URI: https://yourwebsite.com/
* 描述: 智能内容摘要生成插件,为网络传媒网站提供柔性摘要生成功能
* 版本: 1.0.0
* 作者: Your Name
* 作者URI: https://yourwebsite.com/
* 许可证: GPL v2 or later
* 文本域: smart-content-summary
*/
// 防止直接访问
if (!defined('ABSPATH')) {
exit;
}
// 定义插件常量
define('SCS_VERSION', '1.0.0');
define('SCS_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('SCS_PLUGIN_URL', plugin_dir_url(__FILE__));
// 自动加载类文件
spl_autoload_register(function ($class_name) {
if (strpos($class_name, 'SCS_') === 0) {
$file = SCS_PLUGIN_DIR . 'includes/class-' . strtolower(str_replace('_', '-', $class_name)) . '.php';
if (file_exists($file)) {
require_once $file;
}
}
});
// 初始化插件
function scs_init_plugin() {
// 检查WordPress版本
if (version_compare(get_bloginfo('version'), '5.0', '<')) {
add_action('admin_notices', function() {
echo '<div class="notice notice-error"><p>';
echo __('Smart Content Summary 需要 WordPress 5.0 或更高版本', 'smart-content-summary');
echo '</p></div>';
});
return;
}
// 初始化核心类
$summary_generator = new SCS_Summary_Generator();
$admin_interface = new SCS_Admin_Interface();
// 注册激活和停用钩子
register_activation_hook(__FILE__, 'scs_activate_plugin');
register_deactivation_hook(__FILE__, 'scs_deactivate_plugin');
}
add_action('plugins_loaded', 'scs_init_plugin');
// 插件激活函数
function scs_activate_plugin() {
// 创建必要的数据库表
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
$table_name = $wpdb->prefix . 'scs_summary_cache';
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id bigint(20) NOT NULL AUTO_INCREMENT,
post_id bigint(20) NOT NULL,
content_hash varchar(32) NOT NULL,
summary text NOT NULL,
algorithm varchar(50) NOT NULL,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY post_id (post_id),
KEY content_hash (content_hash)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
// 设置默认选项
$default_options = array(
'default_length' => 150,
'default_algorithm' => 'extractive',
'enable_cache' => true,
'cache_duration' => 86400, // 24小时
'auto_generate' => true
);
add_option('scs_settings', $default_options);
}
// 插件停用函数
function scs_deactivate_plugin() {
// 清理定时任务
wp_clear_scheduled_hook('scs_daily_cleanup');
}
创建 includes/class-summary-generator.php:
<?php
/**
* 智能摘要生成核心类
* 提供多种摘要生成算法
*/
class SCS_Summary_Generator {
private $settings;
public function __construct() {
$this->settings = get_option('scs_settings', array());
// 注册文章保存钩子
add_action('save_post', array($this, 'generate_summary_on_save'), 10, 3);
// 添加摘要到文章内容
add_filter('the_content', array($this, 'add_summary_to_content'), 5);
}
/**
* 在文章保存时生成摘要
*/
public function generate_summary_on_save($post_id, $post, $update) {
// 检查自动生成设置
if (!$this->settings['auto_generate'] ?? true) {
return;
}
// 检查文章类型
if (!in_array($post->post_type, array('post', 'page'))) {
return;
}
// 检查是否自动保存或修订
if (wp_is_post_autosave($post_id) || wp_is_post_revision($post_id)) {
return;
}
// 生成摘要
$summary = $this->generate_summary($post->post_content, $post_id);
// 保存摘要到文章元数据
if ($summary) {
update_post_meta($post_id, '_scs_auto_summary', $summary);
}
}
/**
* 生成摘要的主函数
* @param string $content 文章内容
* @param int $post_id 文章ID
* @return string 生成的摘要
*/
public function generate_summary($content, $post_id = null) {
// 清理HTML标签,获取纯文本
$plain_text = wp_strip_all_tags($content);
// 检查缓存
if ($this->settings['enable_cache'] ?? true && $post_id) {
$cached_summary = $this->get_cached_summary($post_id, $plain_text);
if ($cached_summary) {
return $cached_summary;
}
}
// 根据设置选择算法
$algorithm = $this->settings['default_algorithm'] ?? 'extractive';
$summary = '';
switch ($algorithm) {
case 'extractive':
$summary = $this->extractive_summary($plain_text);
break;
case 'abstractive':
$summary = $this->abstractive_summary($plain_text);
break;
case 'lead_paragraph':
$summary = $this->lead_paragraph_summary($plain_text);
break;
default:
$summary = $this->extractive_summary($plain_text);
}
// 缓存结果
if ($this->settings['enable_cache'] ?? true && $post_id) {
$this->cache_summary($post_id, $plain_text, $summary, $algorithm);
}
return $summary;
}
/**
* 提取式摘要算法
* 从原文中提取最重要的句子
*/
private function extractive_summary($text, $max_length = null) {
if (is_null($max_length)) {
$max_length = $this->settings['default_length'] ?? 150;
}
// 分割成句子
$sentences = $this->split_sentences($text);
if (count($sentences) <= 1) {
return $text;
}
// 计算句子权重(简单实现:基于位置和关键词)
$weighted_sentences = array();
$total_sentences = count($sentences);
for ($i = 0; $i < $total_sentences; $i++) {
$sentence = $sentences[$i];
$weight = 0;
// 位置权重:开头和结尾的句子更重要
if ($i < 2) {
$weight += 0.3; // 前两句
} elseif ($i > $total_sentences - 3) {
$weight += 0.2; // 最后两句
}
// 长度权重:中等长度的句子更好
$sentence_length = strlen($sentence);
if ($sentence_length > 50 && $sentence_length < 150) {
$weight += 0.2;
}
// 关键词权重(简单实现:检查常见关键词)
$keywords = array('总结', '因此', '所以', '然而', '重要的是', '关键');
foreach ($keywords as $keyword) {
if (strpos($sentence, $keyword) !== false) {
$weight += 0.1;
}
}
$weighted_sentences[] = array(
'sentence' => $sentence,
'weight' => $weight,
'original_index' => $i
);
}
// 按权重排序
usort($weighted_sentences, function($a, $b) {
return $b['weight'] <=> $a['weight'];
});
// 选择最重要的句子,直到达到最大长度
$summary = '';
$current_length = 0;
// 按原始顺序排序选中的句子
$selected_sentences = array();
foreach ($weighted_sentences as $item) {
if ($current_length + strlen($item['sentence']) <= $max_length) {
$selected_sentences[$item['original_index']] = $item['sentence'];
$current_length += strlen($item['sentence']);
}
}
ksort($selected_sentences);
$summary = implode('。', $selected_sentences) . '。';
// 如果摘要太短,使用前导段落方法
if (strlen($summary) < $max_length / 2) {
$summary = $this->lead_paragraph_summary($text, $max_length);
}
return $summary;
}
/**
* 抽象式摘要算法(简化版)
* 注意:完整的抽象式摘要需要NLP和机器学习模型
* 这里提供一个简化版本,使用规则和同义词替换
*/
private function abstractive_summary($text, $max_length = null) {
if (is_null($max_length)) {
$max_length = $this->settings['default_length'] ?? 150;
}
// 首先使用提取式方法获取关键句子
$extractive = $this->extractive_summary($text, $max_length * 1.5);
// 简化句子结构(这里是一个简单示例)
$simplified = $this->simplify_sentences($extractive);
// 截断到指定长度
if (strlen($simplified) > $max_length) {
$simplified = mb_substr($simplified, 0, $max_length) . '...';
}
return $simplified;
}
/**
* 前导段落摘要算法
* 提取文章开头的部分作为摘要
*/
private function lead_paragraph_summary($text, $max_length = null) {
if (is_null($max_length)) {
$max_length = $this->settings['default_length'] ?? 150;
}
// 清理多余空白
$text = preg_replace('/s+/', ' ', $text);
// 截取前导部分
if (strlen($text) > $max_length) {
$summary = mb_substr($text, 0, $max_length);
// 确保在完整的句子处结束
$last_period = strrpos($summary, '。');
if ($last_period > $max_length * 0.7) {
$summary = substr($summary, 0, $last_period + 3);
} else {
$summary .= '...';
}
} else {
$summary = $text;
}
return $summary;
}
/**
* 分割句子
*/
private function split_sentences($text) {
// 中文句子分割(简单实现)
$sentences = preg_split('/(?<=[。!?])/u', $text, -1, PREG_SPLIT_NO_EMPTY);
return array_filter($sentences, function($sentence) {
return trim($sentence) !== '';
});
}
/**
* 简化句子(抽象式摘要的辅助函数)
*/
private function simplify_sentences($text) {
// 这里可以添加更复杂的NLP处理
// 目前只是一个简单示例
// 移除一些修饰性短语
$patterns = array(
'/毫无疑问,/' => '',
'/可以说,/' => '',
'/值得注意的是,/' => '',
'/总的来说,/' => '',
);
$simplified = preg_replace(array_keys($patterns), array_values($patterns), $text);
return $simplified;
}
/**
* 从缓存获取摘要
*/
private function get_cached_summary($post_id, $content) {
global $wpdb;
$table_name = $wpdb->prefix . 'scs_summary_cache';
$content_hash = md5($content);
$cache_duration = $this->settings['cache_duration'] ?? 86400;
$expiry_time = date('Y-m-d H:i:s', time() - $cache_duration);
$query = $wpdb->prepare(
"SELECT summary FROM $table_name WHERE post_id = %d AND content_hash = %s AND created_at > %s LIMIT 1",
$post_id,
$content_hash,
$expiry_time
);
return $wpdb->get_var($query);
}
/**
* 缓存摘要
*/
private function cache_summary($post_id, $content, $summary, $algorithm) {
global $wpdb;
$table_name = $wpdb->prefix . 'scs_summary_cache';
$content_hash = md5($content);
// 删除旧缓存
$wpdb->delete(
$table_name,
array('post_id' => $post_id, 'content_hash' => $content_hash),
array('%d', '%s')
);
// 插入新缓存
$wpdb->insert(
$table_name,
array(
'post_id' => $post_id,
'content_hash' => $content_hash,
'summary' => $summary,
'algorithm' => $algorithm
),
array('%d', '%s', '%s', '%s')
);
}
/**
* 将摘要添加到文章内容
*/
public function add_summary_to_content($content) {
if (!is_single() && !is_page()) {
return $content;
}
global $post;
$summary = get_post_meta($post->ID, '_scs_auto_summary', true);
if (!$summary) {
return $content;
}
// 创建摘要显示框
$summary_html = '<div class="scs-content-summary">';
$summary_html .= '<h3>' . __('内容摘要', 'smart-content-summary') . '</h3>';
$summary_html .= '<p>' . esc_html($summary) . '</p>';
$summary_html .= '</div>';
// 将摘要添加到内容开头
return $summary_html . $content;
}
}
创建 includes/class-admin-interface.php:
<?php
/**
* 插件管理界面类
* 提供设置页面和文章编辑界面集成
*/
class SCS_Admin_Interface {
public function __construct() {
// 添加设置菜单
add_action('admin_menu', array($this, 'add_admin_menu'));
// 注册设置
add_action('admin_init', array($this, 'register_settings'));
// 在文章编辑页面添加元框
add_action('add_meta_boxes', array($this, 'add_meta_boxes'));
// 保存元框数据
add_action('save_post', array($this, 'save_meta_box_data'), 10, 2);
// 添加文章列表列
add_filter('manage_posts_columns', array($this, 'add_summary_column'));
add_action('manage_posts_custom_column', array($this, 'display_summary_column'), 10, 2);
}
/**
* 添加管理菜单
*/
public function add_admin_menu() {
add_options_page(
__('智能摘要设置', 'smart-content-summary'),
'manage_options',
'smart-content-summary',
array($this, 'display_settings_page')
);
}
/**
* 显示设置页面
*/
public function display_settings_page() {
?>
<div class="wrap">
<h1><?php echo esc_html__('智能内容摘要设置', 'smart-content-summary'); ?></h1>
<form method="post" action="options.php">
<?php
settings_fields('scs_settings_group');
do_settings_sections('smart-content-summary');
submit_button();
?>
</form>
<div class="scs-test-section">
<h2><?php echo esc_html__('摘要生成测试', 'smart-content-summary'); ?></h2>
<textarea id="scs-test-content" rows="6" style="width:100%;" placeholder="<?php echo esc_attr__('在此输入测试内容...', 'smart-content-summary'); ?>"></textarea>
<div style="margin: 10px 0;">
<label for="scs-test-algorithm"><?php echo esc_html__('算法选择:', 'smart-content-summary'); ?></label>
<select id="scs-test-algorithm">
<option value="extractive"><?php echo esc_html__('提取式摘要', 'smart-content-summary'); ?></option>
<option value="abstractive"><?php echo esc_html__('抽象式摘要', 'smart-content-summary'); ?></option>
<option value="lead_paragraph"><?php echo esc_html__('前导段落', 'smart-content-summary'); ?></option>
</select>
<label for="scs-test-length" style="margin-left:20px;"><?php echo esc_html__('长度:', 'smart-content-summary'); ?></label>
<input type="number" id="scs-test-length" value="150" min="50" max="500">
<button type="button" id="scs-test-button" class="button button-primary"><?php echo esc_html__('生成测试摘要', 'smart-content-summary'); ?></button>
</div>
<div id="scs-test-result" style="background:#f5f5f5; padding:15px; border:1px solid #ddd; display:none;">
<h4><?php echo esc_html__('生成结果:', 'smart-content-summary'); ?></h4>
<p id="scs-test-result-text"></p>
</div>
</div>
</div>
<script>
jQuery(document).ready(function($) {
$('#scs-test-button').on('click', function() {
var content = $('#scs-test-content').val();
var algorithm = $('#scs-test-algorithm').val();
var length = $('#scs-test-length').val();
if (!content.trim()) {
alert('<?php echo esc_js(__('请输入测试内容', 'smart-content-summary')); ?>');
return;
}
$(this).prop('disabled', true).text('<?php echo esc_js(__('生成中...', 'smart-content-summary')); ?>');
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'scs_test_summary',
content: content,
algorithm: algorithm,
length: length,
nonce: '<?php echo wp_create_nonce("scs_test_nonce"); ?>'
},
success: function(response) {
if (response.success) {
$('#scs-test-result-text').text(response.data.summary);
$('#scs-test-result').show();
} else {
alert(response.data || '<?php echo esc_js(__('生成失败', 'smart-content-summary')); ?>');
}
},
complete: function() {
$('#scs-test-button').prop('disabled', false).text('<?php echo esc_js(__('生成测试摘要', 'smart-content-summary')); ?>');
}
});
});
});
</script>
<?php
}
/**
* 注册设置
*/
public function register_settings() {
register_setting('scs_settings_group', 'scs_settings', array($this, 'sanitize_settings'));
// 基本设置部分
add_settings_section(
'scs_basic_settings',
__('基本设置', 'smart-content-summary'),
array($this, 'render_basic_settings_section'),
'smart-content-summary'
);
// 算法设置部分
add_settings_section(
'scs_algorithm_settings',
__('算法设置', 'smart-content-summary'),
array($this, 'render_algorithm_settings_section'),
'smart-content-summary'
);
// 高级设置部分
add_settings_section(
'scs_advanced_settings',
__('高级设置', 'smart-content-summary'),
array($this, 'render_advanced_settings_section'),
'smart-content-summary'
);
// 添加各个设置字段
$this->add_settings_fields();
}
/**
* 添加设置字段
*/
private function add_settings_fields() {
// 默认摘要长度
add_settings_field(
'default_length',
__('默认摘要长度', 'smart-content-summary'),
array($this, 'render_default_length_field'),
'smart-content-summary',
'scs_basic_settings'
);
// 默认算法
add_settings_field(
'default_algorithm',
__('默认摘要算法', 'smart-content-summary'),
array($this, 'render_default_algorithm_field'),
'smart-content-summary',
'scs_algorithm_settings'
);
// 自动生成
add_settings_field(
'auto_generate',
__('自动生成摘要', 'smart-content-summary'),
array($this, 'render_auto_generate_field'),
'smart-content-summary',
'scs_basic_settings'
);
// 缓存设置
add_settings_field(
'enable_cache',
__('启用缓存', 'smart-content-summary'),
array($this, 'render_enable_cache_field'),
'smart-content-summary',
'scs_advanced_settings'
);
// 缓存时长
add_settings_field(
'cache_duration',
__('缓存时长(秒)', 'smart-content-summary'),
array($this, 'render_cache_duration_field'),
'smart-content-summary',
'scs_advanced_settings'
);
}
/**
* 渲染设置字段
*/
public function render_default_length_field() {
$settings = get_option('scs_settings');
$value = $settings['default_length'] ?? 150;
?>
<input type="number" name="scs_settings[default_length]" value="<?php echo esc_attr($value); ?>" min="50" max="1000">
<p class="description"><?php echo esc_html__('摘要的默认字符长度', 'smart-content-summary'); ?></p>
<?php
}
public function render_default_algorithm_field() {
$settings = get_option('scs_settings');
$value = $settings['default_algorithm'] ?? 'extractive';
?>
<select name="scs_settings[default_algorithm]">
<option value="extractive" <?php selected($value, 'extractive'); ?>><?php echo esc_html__('提取式摘要', 'smart-content-summary'); ?></option>
<option value="abstractive" <?php selected($value, 'abstractive'); ?>><?php echo esc_html__('抽象式摘要', 'smart-content-summary'); ?></option>
<option value="lead_paragraph" <?php selected($value, 'lead_paragraph'); ?>><?php echo esc_html__('前导段落', 'smart-content-summary'); ?></option>
</select>
<p class="description"><?php echo esc_html__('选择默认的摘要生成算法', 'smart-content-summary'); ?></p>
<?php
}
public function render_auto_generate_field() {
$settings = get_option('scs_settings');
$value = $settings['auto_generate'] ?? true;
?>
<label>
<input type="checkbox" name="scs_settings[auto_generate]" value="1" <?php checked($value, true); ?>>
<?php echo esc_html__('保存文章时自动生成摘要', 'smart-content-summary'); ?>
</label>
<?php
}
public function render_enable_cache_field() {
$settings = get_option('scs_settings');
$value = $settings['enable_cache'] ?? true;
?>
<label>
<input type="checkbox" name="scs_settings[enable_cache]" value="1" <?php checked($value, true); ?>>
<?php echo esc_html__('启用摘要缓存以提高性能', 'smart-content-summary'); ?>
</label>
<?php
}
public function render_cache_duration_field() {
$settings = get_option('scs_settings');
$value = $settings['cache_duration'] ?? 86400;
?>
<input type="number" name="scs_settings[cache_duration]" value="<?php echo esc_attr($value); ?>" min="3600" max="2592000">
<p class="description"><?php echo esc_html__('缓存过期时间,默认24小时(86400秒)', 'smart-content-summary'); ?></p>
<?php
}
/**
* 渲染设置部分描述
*/
public function render_basic_settings_section() {
echo '<p>' . esc_html__('配置插件的基本行为', 'smart-content-summary') . '</p>';
}
public function render_algorithm_settings_section() {
echo '<p>' . esc_html__('配置摘要生成算法', 'smart-content-summary') . '</p>';
}
public function render_advanced_settings_section() {
echo '<p>' . esc_html__('高级性能配置选项', 'smart-content-summary') . '</p>';
}
/**
* 清理设置数据
*/
public function sanitize_settings($input) {
$sanitized = array();
$sanitized['default_length'] = absint($input['default_length'] ?? 150);
if ($sanitized['default_length'] < 50) $sanitized['default_length'] = 50;
if ($sanitized['default_length'] > 1000) $sanitized['default_length'] = 1000;
$sanitized['default_algorithm'] = sanitize_text_field($input['default_algorithm'] ?? 'extractive');
$allowed_algorithms = array('extractive', 'abstractive', 'lead_paragraph');
if (!in_array($sanitized['default_algorithm'], $allowed_algorithms)) {
$sanitized['default_algorithm'] = 'extractive';
}
$sanitized['auto_generate'] = !empty($input['auto_generate']);
$sanitized['enable_cache'] = !empty($input['enable_cache']);
$sanitized['cache_duration'] = absint($input['cache_duration'] ?? 86400);
return $sanitized;
}
/**
* 添加文章编辑页面的元框
*/
public function add_meta_boxes() {
$post_types = apply_filters('scs_post_types', array('post', 'page'));
foreach ($post_types as $post_type) {
add_meta_box(
'scs_summary_meta_box',
__('智能内容摘要', 'smart-content-summary'),
array($this, 'render_meta_box'),
$post_type,
'normal',
'high'
);
}
}
/**
* 渲染元框内容
*/
public function render_meta_box($post) {
wp_nonce_field('scs_summary_meta_box', 'scs_summary_nonce');
$auto_summary = get_post_meta($post->ID, '_scs_auto_summary', true);
$manual_summary = get_post_meta($post->ID, '_scs_manual_summary', true);
$use_manual = get_post_meta($post->ID, '_scs_use_manual', true);
?>
<div class="scs-meta-box">
<div style="margin-bottom: 15px;">
<label>
<input type="radio" name="scs_summary_type" value="auto" <?php checked(!$use_manual); ?>>
<?php echo esc_html__('自动生成摘要', 'smart-content-summary'); ?>
</label>
<label style="margin-left: 20px;">
<input type="radio" name="scs_summary_type" value="manual" <?php checked($use_manual); ?>>
<?php echo esc_html__('手动编辑摘要', 'smart-content-summary'); ?>
</label>
</div>
<div id="scs-auto-summary-section" style="<?php echo $use_manual ? 'display:none;' : ''; ?>">
<p><strong><?php echo esc_html__('自动生成的摘要:', 'smart-content-summary'); ?></strong></p>
<textarea id="scs-auto-summary" rows="4" style="width:100%;" readonly><?php echo esc_textarea($auto_summary); ?></textarea>
<button type="button" id="scs-regenerate-button" class="button button-secondary" style="margin-top:10px;">
<?php echo esc_html__('重新生成摘要', 'smart-content-summary'); ?>
</button>
</div>
<div id="scs-manual-summary-section" style="<?php echo !$use_manual ? 'display:none;' : ''; ?>">
<p><strong><?php echo esc_html__('手动编辑摘要:', 'smart-content-summary'); ?></strong></p>
<textarea name="scs_manual_summary" rows="4" style="width:100%;"><?php echo esc_textarea($manual_summary); ?></textarea>
</div>
<input type="hidden" id="scs_auto_summary" name="scs_auto_summary" value="<?php echo esc_attr($auto_summary); ?>">
</div>
<script>
jQuery(document).ready(function($) {
// 切换摘要类型
$('input[name="scs_summary_type"]').on('change', function() {
if ($(this).val() === 'auto') {
$('#scs-auto-summary-section').show();
$('#scs-manual-summary-section').hide();
} else {
$('#scs-auto-summary-section').hide();
$('#scs-manual-summary-section').show();
}
});
// 重新生成摘要
$('#scs-regenerate-button').on('click', function() {
if (!confirm('<?php echo esc_js(__('确定要重新生成摘要吗?', 'smart-content-summary')); ?>')) {
return;
}
$(this).prop('disabled', true).text('<?php echo esc_js(__('生成中...', 'smart-content-summary')); ?>');
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'scs_regenerate_summary',
post_id: <?php echo $post->ID; ?>,
nonce: '<?php echo wp_create_nonce("scs_regenerate_nonce"); ?>'
},
success: function(response) {
if (response.success) {
$('#scs-auto-summary').val(response.data.summary);
$('#scs_auto_summary').val(response.data.summary);
} else {
alert(response.data || '<?php echo esc_js(__('生成失败', 'smart-content-summary')); ?>');
}
},
complete: function() {
$('#scs-regenerate-button').prop('disabled', false).text('<?php echo esc_js(__('重新生成摘要', 'smart-content-summary')); ?>');
}
});
});
});
</script>
<?php
}
/**
* 保存元框数据
*/
public function save_meta_box_data($post_id, $post) {
// 检查nonce
if (!isset($_POST['scs_summary_nonce']) ||
!wp_verify_nonce($_POST['scs_summary_nonce'], 'scs_summary_meta_box')) {
return;
}
// 检查权限
if (!current_user_can('edit_post', $post_id)) {
return;
}
// 检查自动保存
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
// 保存摘要类型
$use_manual = ($_POST['scs_summary_type'] ?? 'auto') === 'manual';
update_post_meta($post_id, '_scs_use_manual', $use_manual);
// 保存自动生成的摘要
if (isset($_POST['scs_auto_summary'])) {
update_post_meta($post_id, '_scs_auto_summary', sanitize_textarea_field($_POST['scs_auto_summary']));
}
// 保存手动编辑的摘要
if (isset($_POST['scs_manual_summary'])) {
update_post_meta($post_id, '_scs_manual_summary', sanitize_textarea_field($_POST['scs_manual_summary']));
}
}
/**
* 添加文章列表列
*/
public function add_summary_column($columns) {
$columns['scs_summary'] = __('智能摘要', 'smart-content-summary');
return $columns;
}
/**
* 显示文章列表列内容
*/
public function display_summary_column($column, $post_id) {
if ($column !== 'scs_summary') {
return;
}
$use_manual = get_post_meta($post_id, '_scs_use_manual', true);
if ($use_manual) {
$summary = get_post_meta($post_id, '_scs_manual_summary', true);
$type = __('手动', 'smart-content-summary');
} else {
$summary = get_post_meta($post_id, '_scs_auto_summary', true);


