WooCommerce产品搜索增强 插件

专为WooCommerce商店设计的全面搜索解决方案,极大提升您网站的产品搜索体验和功能。无论是提高用户体验还是增加转化率,本插件都能满足您的需求。

= 主要功能 =
* **智能搜索建议** – 当用户输入时实时显示相关产品建议,包含产品图片、价格和库存状态
* **模糊搜索匹配** – 即使用户拼写错误或使用近似词也能找到相关产品,特别适合中文拼音和多音字搜索
* **产品元标签自动生成** – 为产品页面自动生成SEO友好的元标签和结构化数据,提高搜索引擎可见度
* **高级产品过滤** – 允许用户通过价格、分类、评分、库存状态等多维度筛选产品
* **详细搜索分析** – 提供全面的搜索数据分析,包括热门搜索词、零结果搜索词和搜索趋势
* **响应式设计** – 完美适配各种屏幕尺寸,移动设备体验优秀

相关文章: WooCommerce 页脚增强器

<?php
/**
* Plugin Name: BDFG 产品搜索增强工具
* Plugin URI: https://beiduofengou.net/2025/01/12/bdfg-product-search/
* Description: 增强产品搜索体验,包括智能搜索建议、模糊搜索、元标签自动生成和高级过滤功能。
* Version: 1.0.1
* Author: BeiDuoFenGou
* Author URI: https://beiduofengou.net
* Text Domain: bdfg-product-search
* Domain Path: /languages
* Requires at least: 5.6
* Requires PHP: 7.4
* License: GPL v2 or later
*/

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

// 定义插件常量
define('BDFG_PRODUCT_SEARCH_VERSION', '1.0.1');
define('BDFG_PRODUCT_SEARCH_PATH', plugin_dir_path(__FILE__));
define('BDFG_PRODUCT_SEARCH_URL', plugin_dir_url(__FILE__));
define('BDFG_PRODUCT_SEARCH_FILE', __FILE__);
define('BDFG_PRODUCT_SEARCH_BASENAME', plugin_basename(__FILE__));

// 引入核心文件
require_once BDFG_PRODUCT_SEARCH_PATH . 'includes/class-bdfg-product-search.php';

// 初始化插件
function bdfg_product_search_init() {
// 加载文本域
load_plugin_textdomain('bdfg-product-search', false, dirname(plugin_basename(__FILE__)) . '/languages/');

// 启动插件
BDFG_Product_Search::get_instance();
}
add_action('plugins_loaded', 'bdfg_product_search_init');

// 插件激活时执行的操作
function bdfg_product_search_activate() {
// 确保满足最低要求
if (version_compare(PHP_VERSION, '7.4', '<')) {
deactivate_plugins(BDFG_PRODUCT_SEARCH_BASENAME);
wp_die('BDFG 产品搜索增强工具需要 PHP 7.4 或更高版本。');
}

if (!class_exists('WooCommerce')) {
deactivate_plugins(BDFG_PRODUCT_SEARCH_BASENAME);
wp_die('BDFG 产品搜索增强工具需要安装并激活 WooCommerce。');
}

// 创建数据表等初始化操作
require_once BDFG_PRODUCT_SEARCH_PATH . 'includes/class-bdfg-product-search.php';
$plugin = BDFG_Product_Search::get_instance();
$plugin->activate();

// 刷新重写规则
flush_rewrite_rules();
}
register_activation_hook(__FILE__, 'bdfg_product_search_activate');

// 插件停用时执行的操作
function bdfg_product_search_deactivate() {
require_once BDFG_PRODUCT_SEARCH_PATH . 'includes/class-bdfg-product-search.php';
$plugin = BDFG_Product_Search::get_instance();
$plugin->deactivate();

// 刷新重写规则
flush_rewrite_rules();
}
register_deactivation_hook(__FILE__, 'bdfg_product_search_deactivate');

includes/class-bdfg-product-search.php

<?php
/**
* BDFG 产品搜索增强工具核心类
*
* @package BDFG_Product_Search
* @since 1.0.0
*/

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

class BDFG_Product_Search {

/**
* 单例实例
*
* @var BDFG_Product_Search
*/
private static $instance = null;

/**
* 插件目录路径
*
* @var string
*/
private $plugin_path;

/**
* 插件URL
*
* @var string
*/
private $plugin_url;

/**
* 插件版本
*
* @var string
*/
private $version = '1.0.1';

/**
* 选项名称
*
* @var string
*/
private $option_name = 'bdfg_product_search_options';

/**
* 插件选项
*
* @var array
*/
private $options;

/**
* 获取单例实例
*
* @return BDFG_Product_Search
*/
public static function get_instance() {
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}

/**
* 构造函数
*/
private function __construct() {
$this->plugin_path = BDFG_PRODUCT_SEARCH_PATH;
$this->plugin_url = BDFG_PRODUCT_SEARCH_URL;
$this->options = get_option($this->option_name, $this->get_default_options());

// 加载依赖文件
$this->load_dependencies();

// 初始化插件
$this->init();
}

/**
* 加载依赖文件
*/
private function load_dependencies() {
// 加载管理类
require_once $this->plugin_path . 'includes/class-bdfg-admin.php';

// 加载前端类
require_once $this->plugin_path . 'includes/class-bdfg-frontend.php';

// 加载分析类
require_once $this->plugin_path . 'includes/class-bdfg-analytics.php';
}

/**
* 获取默认选项
*
* @return array
*/
private function get_default_options() {
return array(
'enable_meta_tags' => 'yes',
'enable_autocomplete' => 'yes',
'enable_fuzzy_search' => 'yes',
'enable_filters' => 'yes',
'fuzzy_match_threshold' => 3,
'search_results_limit' => 10,
'cache_lifetime' => 24, // 小时
);
}

/**
* 初始化插件
*/
private function init() {
// 初始化管理界面
new BDFG_Admin($this->plugin_path, $this->plugin_url, $this->version, $this->option_name, $this->options);

// 初始化前端功能
new BDFG_Frontend($this->plugin_path, $this->plugin_url, $this->version, $this->option_name, $this->options);

// 初始化分析功能
new BDFG_Analytics($this->plugin_path, $this->plugin_url, $this->version, $this->option_name, $this->options);

// 添加自定义短代码
add_shortcode('bdfg_product_search', array($this, 'search_form_shortcode'));
}

/**
* 插件激活时执行
*/
public function activate() {
// 如果是第一次激活,保存默认选项
if (!get_option($this->option_name)) {
update_option($this->option_name, $this->get_default_options());
}

// 创建必要的数据库表
$this->create_tables();

// 创建定时任务
if (!wp_next_scheduled('bdfg_daily_maintenance')) {
wp_schedule_event(time(), 'daily', 'bdfg_daily_maintenance');
}
}

/**
* 插件停用时执行
*/
public function deactivate() {
// 清除定时任务
wp_clear_scheduled_hook('bdfg_daily_maintenance');
}

/**
* 创建必要的数据库表
*/
private function create_tables() {
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();

// 创建搜索日志表
$search_logs_table = $wpdb->prefix . 'bdfg_search_logs';

if($wpdb->get_var("SHOW TABLES LIKE '$search_logs_table'") != $search_logs_table) {
$sql = "CREATE TABLE $search_logs_table (
id bigint(20) NOT NULL AUTO_INCREMENT,
search_term varchar(255) NOT NULL,
user_id bigint(20) DEFAULT NULL,
search_date datetime DEFAULT CURRENT_TIMESTAMP,
results_count int(11) DEFAULT 0,
ip_address varchar(100) DEFAULT '',
user_agent text,
PRIMARY KEY (id),
KEY search_term (search_term),
KEY search_date (search_date)
) $charset_collate;";

require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}

// 创建搜索建议表
$suggestions_table = $wpdb->prefix . 'bdfg_search_suggestions';

if($wpdb->get_var("SHOW TABLES LIKE '$suggestions_table'") != $suggestions_table) {
$sql = "CREATE TABLE $suggestions_table (
id bigint(20) NOT NULL AUTO_INCREMENT,
search_term varchar(255) NOT NULL,
suggestion varchar(255) NOT NULL,
frequency int(11) DEFAULT 1,
last_updated datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY term_suggestion (search_term, suggestion),
KEY search_term (search_term),
KEY frequency (frequency)
) $charset_collate;";

require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}
}

/**
* 搜索表单短代码
*
* @param array $atts 短代码属性
* @return string 短代码输出
*/
public function search_form_shortcode($atts) {
$atts = shortcode_atts(array(
'placeholder' => __('搜索BDFG产品...', 'bdfg-product-search'),
'button_text' => __('搜索', 'bdfg-product-search'),
'show_filters' => 'no',
), $atts, 'bdfg_product_search');

ob_start();
?>
<div class="bdfg-search-form-container">
<form role="search" method="get" class="bdfg-search-form" action="<?php echo esc_url(home_url('/')); ?>">
<div class="bdfg-search-input-wrap">
<input type="search" class="bdfg-search-field" placeholder="<?php echo esc_attr($atts['placeholder']); ?>" value="<?php echo get_search_query(); ?>" name="s" autocomplete="off" />
<input type="hidden" name="post_type" value="product" />
<button type="submit" class="bdfg-search-submit"><?php echo esc_html($atts['button_text']); ?><span class="bdfg-search-icon"></span></button>
</div>
<div class="bdfg-search-results"></div>
</form>

<?php
if ($atts['show_filters'] === 'yes' && $this->options['enable_filters'] === 'yes') {
// 显示过滤器
$frontend = new BDFG_Frontend($this->plugin_path, $this->plugin_url, $this->version, $this->option_name, $this->options);
$frontend->add_product_filters();
}
?>
</div>
<?php
return ob_get_clean();
}
}

includes/class-bdfg-admin.php

相关文章: WordPress优惠券提醒插件系统

<?php
/**
* BDFG 产品搜索增强工具管理类
*
* @package BDFG_Product_Search
* @since 1.0.0
*/

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

class BDFG_Admin {

/**
* 插件目录路径
*
* @var string
*/
private $plugin_path;

/**
* 插件URL
*
* @var string
*/
private $plugin_url;

/**
* 插件版本
*
* @var string
*/
private $version;

/**
* 选项名称
*
* @var string
*/
private $option_name;

/**
* 插件选项
*
* @var array
*/
private $options;

/**
* 构造函数
*
* @param string $plugin_path 插件目录路径
* @param string $plugin_url 插件URL
* @param string $version 插件版本
* @param string $option_name 选项名称
* @param array $options 插件选项
*/
public function __construct($plugin_path, $plugin_url, $version, $option_name, $options) {
$this->plugin_path = $plugin_path;
$this->plugin_url = $plugin_url;
$this->version = $version;
$this->option_name = $option_name;
$this->options = $options;

// 初始化管理功能
$this->init();
}

/**
* 初始化管理功能
*/
private function init() {
// 添加管理菜单
add_action('admin_menu', array($this, 'add_admin_menu'));

// 注册设置
add_action('admin_init', array($this, 'register_settings'));

// 加载管理样式和脚本
add_action('admin_enqueue_scripts', array($this, 'admin_enqueue_scripts'));

// 添加设置链接到插件页面
add_filter('plugin_action_links_' . BDFG_PRODUCT_SEARCH_BASENAME, array($this, 'plugin_action_links'));

// 添加插件元信息
add_filter('plugin_row_meta', array($this, 'plugin_row_meta'), 10, 2);
}

/**
* 添加管理菜单
*/
public function add_admin_menu() {
// 添加主菜单
add_menu_page(
__('BDFG 产品搜索', 'bdfg-product-search'),
__('BDFG 产品搜索', 'bdfg-product-search'),
'manage_options',
'bdfg-product-search',
array($this, 'render_admin_page'),
'dashicons-search',
58 // 在WooCommerce和设置之间显示
);

// 添加子菜单
add_submenu_page(
'bdfg-product-search',
__('设置', 'bdfg-product-search'),
__('设置', 'bdfg-product-search'),
'manage_options',
'bdfg-product-search',
array($this, 'render_admin_page')
);

// 添加搜索分析子菜单
add_submenu_page(
'bdfg-product-search',
__('搜索分析', 'bdfg-product-search'),
__('搜索分析', 'bdfg-product-search'),
'manage_options',
'bdfg-search-analytics',
array($this, 'render_analytics_page')
);

// 添加帮助文档子菜单
add_submenu_page(
'bdfg-product-search',
__('使用帮助', 'bdfg-product-search'),
__('使用帮助', 'bdfg-product-search'),
'manage_options',
'bdfg-search-help',
array($this, 'render_help_page')
);
}

/**
* 注册插件设置
*/
public function register_settings() {
register_setting(
'bdfg_product_search_group',
$this->option_name,
array($this, 'sanitize_options')
);

// 常规设置部分
add_settings_section(
'bdfg_product_search_general',
__('常规设置', 'bdfg-product-search'),
array($this, 'render_general_section'),
'bdfg-product-search'
);

// 添加设置字段
add_settings_field(
'enable_meta_tags',
__('产品元标签', 'bdfg-product-search'),
array($this, 'render_checkbox_field'),
'bdfg-product-search',
'bdfg_product_search_general',
array(
'id' => 'enable_meta_tags',
'label' => __('启用自动生成产品元标签', 'bdfg-product-search'),
'description' => __('为产品页面自动生成SEO友好的元标签,提高产品在搜索引擎中的可见度', 'bdfg-product-search'),
)
);

add_settings_field(
'enable_autocomplete',
__('智能搜索建议', 'bdfg-product-search'),
array($this, 'render_checkbox_field'),
'bdfg-product-search',
'bdfg_product_search_general',
array(
'id' => 'enable_autocomplete',
'label' => __('启用智能搜索建议功能', 'bdfg-product-search'),
'description' => __('当用户输入搜索词时实时显示相关产品建议,提升用户体验', 'bdfg-product-search'),
)
);

add_settings_field(
'enable_fuzzy_search',
__('模糊搜索', 'bdfg-product-search'),
array($this, 'render_checkbox_field'),
'bdfg-product-search',
'bdfg_product_search_general',
array(
'id' => 'enable_fuzzy_search',
'label' => __('启用模糊搜索功能', 'bdfg-product-search'),
'description' => __('即使用户拼写错误也能找到相关产品,适合中文词语变体和拼音搜索', 'bdfg-product-search'),
)
);

add_settings_field(
'enable_filters',
__('产品过滤器', 'bdfg-product-search'),
array($this, 'render_checkbox_field'),
'bdfg-product-search',
'bdfg_product_search_general',
array(
'id' => 'enable_filters',
'label' => __('启用高级产品过滤功能', 'bdfg-product-search'),
'description' => __('允许用户通过价格、类别、评分等过滤产品,优化购物体验', 'bdfg-product-search'),
)
);

// 高级设置部分
add_settings_section(
'bdfg_product_search_advanced',
__('高级设置', 'bdfg-product-search'),
array($this, 'render_advanced_section'),
'bdfg-product-search'
);

add_settings_field(
'fuzzy_match_threshold',
__('模糊匹配阈值', 'bdfg-product-search'),
array($this, 'render_number_field'),
'bdfg-product-search',
'bdfg_product_search_advanced',
array(
'id' => 'fuzzy_match_threshold',
'label' => __('编辑距离阈值', 'bdfg-product-search'),
'description' => __('较低的值提供更精确的结果,较高的值能找到更多的近似匹配项(建议值:2-5)', 'bdfg-product-search'),
'min' => 1,
'max' => 10,
'step' => 1
)
);

add_settings_field(
'search_results_limit',
__('搜索结果数量', 'bdfg-product-search'),
array($this, 'render_number_field'),
'bdfg-product-search',
'bdfg_product_search_advanced',
array(
'id' => 'search_results_limit',
'label' => __('结果', 'bdfg-product-search'),
'description' => __('自动完成下拉列表中显示的最大搜索结果数量', 'bdfg-product-search'),
'min' => 3,
'max' => 20,
'step' => 1
)
);

add_settings_field(
'cache_lifetime',
__('缓存生命周期', 'bdfg-product-search'),
array($this, 'render_number_field'),
'bdfg-product-search',
'bdfg_product_search_advanced',
array(
'id' => 'cache_lifetime',
'label' => __('小时', 'bdfg-product-search'),
'description' => __('搜索结果缓存的有效期(小时)。设置为0禁用缓存。', 'bdfg-product-search'),
'min' => 0,
'max' => 72,
'step' => 1
)
);
}

/**
* 清理设置选项
*
* @param array $options 提交的选项值
* @return array 清理后的选项值
*/
public function sanitize_options($options) {
$sanitized = array();

// 布尔选项
$sanitized['enable_meta_tags'] = isset($options['enable_meta_tags']) ? 'yes' : 'no';
$sanitized['enable_autocomplete'] = isset($options['enable_autocomplete']) ? 'yes' : 'no';
$sanitized['enable_fuzzy_search'] = isset($options['enable_fuzzy_search']) ? 'yes' : 'no';
$sanitized['enable_filters'] = isset($options['enable_filters']) ? 'yes' : 'no';

// 数值选项
$sanitized['fuzzy_match_threshold'] = isset($options['fuzzy_match_threshold'])
? intval($options['fuzzy_match_threshold'])
: 3;
$sanitized['fuzzy_match_threshold'] = max(1, min(10, $sanitized['fuzzy_match_threshold']));

$sanitized['search_results_limit'] = isset($options['search_results_limit'])
? intval($options['search_results_limit'])
: 10;
$sanitized['search_results_limit'] = max(3, min(20, $sanitized['search_results_limit']));

$sanitized['cache_lifetime'] = isset($options['cache_lifetime'])
? intval($options['cache_lifetime'])
: 24;
$sanitized['cache_lifetime'] = max(0, min(72, $sanitized['cache_lifetime']));

// 添加设置更新消息
add_settings_error(
'bdfg_product_search_messages',
'bdfg_product_search_message',
__('设置已保存。', 'bdfg-product-search'),
'updated'
);

return $sanitized;
}

/**
* 渲染常规设置部分
*/
public function render_general_section() {
echo '<p>' . __('配置BDFG产品搜索增强工具的基本功能。这些选项影响用户在您网站上的搜索体验。', 'bdfg-product-search') . '</p>';
}

/**
* 渲染高级设置部分
*/
public function render_advanced_section() {
echo '<p>' . __('这些设置影响BDFG产品搜索的性能和行为。请谨慎修改这些值。', 'bdfg-product-search') . '</p>';
}

/**
* 渲染复选框字段
*
* @param array $args 字段参数
*/
public function render_checkbox_field($args) {
$id = $args['id'];
$label = $args['label'];
$description = isset($args['description']) ? $args['description'] : '';
$checked = isset($this->options[$id]) && $this->options[$id] === 'yes' ? 'checked' : '';

echo '<label class="bdfg-switch">';
echo '<input type="checkbox" id="' . esc_attr($id) . '" name="' . esc_attr($this->option_name) . '[' . esc_attr($id) . ']" ' . $checked . ' />';
echo '<span class="bdfg-slider"></span>';
echo '</label>';
echo '<label for="' . esc_attr($id) . '" class="bdfg-checkbox-label">' . esc_html($label) . '</label>';

if (!empty($description)) {
echo '<p class="description">' . esc_html($description) . '</p>';
}
}

/**
* 渲染数字字段
*
* @param array $args 字段参数
*/
public function render_number_field($args) {
$id = $args['id'];
$label = $args['label'];
$description = isset($args['description']) ? $args['description'] : '';
$min = isset($args['min']) ? $args['min'] : 0;
$max = isset($args['max']) ? $args['max'] : 999;
$step = isset($args['step']) ? $args['step'] : 1;
$value = isset($this->options[$id]) ? $this->options[$id] : '';

echo '<div class="bdfg-number-field">';
echo '<input type="number" id="' . esc_attr($id) . '" name="' . esc_attr($this->option_name) . '[' . esc_attr($id) . ']" value="' . esc_attr($value) . '" min="' . esc_attr($min) . '" max="' . esc_attr($max) . '" step="' . esc_attr($step) . '" />';
echo ' <label for="' . esc_attr($id) . '">' . esc_html($label) . '</label>';
echo '</div>';

if (!empty($description)) {
echo '<p class="description">' . esc_html($description) . '</p>';
}
}

/**
* 渲染管理页面
*/
public function render_admin_page() {
if (!current_user_can('manage_options')) {
return;
}

?>
<div class="wrap bdfg-admin-wrap">
<div class="bdfg-admin-header">
<div class="bdfg-logo">
<img src="<?php echo esc_url($this->plugin_url . 'assets/images/bdfg-logo.png'); ?>" alt="BDFG Logo">
<h1><?php _e('BDFG 产品搜索增强工具', 'bdfg-product-search'); ?></h1>
</div>
<div class="bdfg-version">
<span><?php _e('版本', 'bdfg-product-search'); ?>: <?php echo esc_html($this->version); ?></span>
</div>
</div>

<div class="bdfg-admin-content">
<?php settings_errors('bdfg_product_search_messages'); ?>

<div class="bdfg-admin-tabs">
<a class="nav-tab nav-tab-active" href="#settings"><?php _e('设置', 'bdfg-product-search'); ?></a>
<a class="nav-tab" href="#shortcodes"><?php _e('短代码', 'bdfg-product-search'); ?></a>
<a class="nav-tab" href="#support"><?php _e('支持', 'bdfg-product-search'); ?></a>
</div>

<div class="bdfg-tab-content active" id="settings-content">
<form method="post" action="options.php">
<?php
settings_fields('bdfg_product_search_group');
do_settings_sections('bdfg-product-search');
submit_button(__('保存设置', 'bdfg-product-search'));
?>
</form>
</div>

<div class="bdfg-tab-content" id="shortcodes-content">
<h2><?php _e('短代码使用说明', 'bdfg-product-search'); ?></h2>

<div class="bdfg-shortcode-box">
<h3><?php _e('基本搜索表单', 'bdfg-product-search'); ?></h3>
<code class="bdfg-shortcode">[bdfg_product_search]</code>
<p class="description"><?php _e('在任何页面或文章中插入BDFG高级产品搜索表单', 'bdfg-product-search'); ?></p>
</div>

<div class="bdfg-shortcode-box">
<h3><?php _e('自定义搜索表单', 'bdfg-product-search'); ?></h3>
<code class="bdfg-shortcode">[bdfg_product_search placeholder="查找BDFG产品..." button_text="搜索" show_filters="yes"]</code>
<p class="description"><?php _e('自定义搜索表单,包括占位文本、按钮文本和是否显示过滤器', 'bdfg-product-search'); ?></p>

<table class="bdfg-shortcode-attrs">
<thead>
<tr>
<th><?php _e('参数', 'bdfg-product-search'); ?></th>
<th><?php _e('默认值', 'bdfg-product-search'); ?></th>
<th><?php _e('描述', 'bdfg-product-search'); ?></th>
</tr>
</thead>
<tbody>
<tr>
<td><code>placeholder</code></td>
<td><?php _e('搜索BDFG产品...', 'bdfg-product-search'); ?></td>
<td><?php _e('搜索框占位文本', 'bdfg-product-search'); ?></td>
</tr>
<tr>
<td><code>button_text</code></td>
<td><?php _e('搜索', 'bdfg-product-search'); ?></td>
<td><?php _e('搜索按钮文本', 'bdfg-product-search'); ?></td>
</tr>
<tr>
<td><code>show_filters</code></td>
<td>no</td>
<td><?php _e('是否显示产品过滤器(yes/no)', 'bdfg-product-search'); ?></td>
</tr>
</tbody>
</table>
</div>
</div>

<div class="bdfg-tab-content" id="support-content">
<h2><?php _e('支持与帮助', 'bdfg-product-search'); ?></h2>

<div class="bdfg-support-box">
<h3><?php _e('官方网站', 'bdfg-product-search'); ?></h3>
<p><?php _e('访问我们的官方网站获取更多信息和资源:', 'bdfg-product-search'); ?> <a href="https://beiduofengou.net" target="_blank">https://beiduofengou.net</a></p>
</div>

<div class="bdfg-support-box">
<h3><?php _e('使用文档', 'bdfg-product-search'); ?></h3>
<p><?php _e('查看详细的使用文档:', 'bdfg-product-search'); ?> <a href="https://beiduofengou.net/docs/bdfg-product-search" target="_blank"><?php _e('BDFG产品搜索增强工具文档', 'bdfg-product-search'); ?></a></p>
</div>

<div class="bdfg-support-box">
<h3><?php _e('联系我们', 'bdfg-product-search'); ?></h3>
<p><?php _e('如遇到任何问题,请联系我们的支持团队:', 'bdfg-product-search'); ?> <a href="mailto:[email protected]">[email protected]</a></p>
</div>
</div>
</div>

<div class="bdfg-admin-footer">
<p><?php _e('由 BeiDuoFenGou 倾情打造', 'bdfg-product-search'); ?> &copy; <?php echo date('Y'); ?> <a href="https://beiduofengou.net" target="_blank">beiduofengou.net</a></p>
</div>
</div>
<script>
jQuery(document).ready(function($) {
// 标签切换
$('.bdfg-admin-tabs .nav-tab').click(function(e) {
e.preventDefault();

var target = $(this).attr('href').replace('#', '');

$('.bdfg-admin-tabs .nav-tab').removeClass('nav-tab-active');
$(this).addClass('nav-tab-active');

$('.bdfg-tab-content').removeClass('active');
$('#' + target + '-content').addClass('active');
});

// 复制短代码到剪贴板
$('.bdfg-shortcode').click(function() {
var shortcode = $(this).text();
var tempTextarea = $('<textarea>');
$('body').append(tempTextarea);
tempTextarea.val(shortcode).select();
document.execCommand('copy');
tempTextarea.remove();

$(this).addClass('copied');
setTimeout(function() {
$('.bdfg-shortcode').removeClass('copied');
}, 1000);
});
});
</script>
<?php
}

/**
* 渲染搜索分析页面
*/
public function render_analytics_page() {
if (!current_user_can('manage_options')) {
return;
}

// 获取分析数据
$analytics = new BDFG_Analytics($this->plugin_path, $this->plugin_url, $this->version, $this->option_name, $this->options);
$data = $analytics->get_analytics_data();

?>
<div class="wrap bdfg-admin-wrap bdfg-analytics-wrap">
<div class="bdfg-admin-header">
<div class="bdfg-logo">
<img src="<?php echo esc_url($this->plugin_url . 'assets/images/bdfg-logo.png'); ?>" alt="BDFG Logo">
<h1><?php _e('BDFG 产品搜索分析', 'bdfg-product-search'); ?></h1>
</div>
</div>

<div class="bdfg-admin-content">
<div class="bdfg-date-filter">
<form method="get">
<input type="hidden" name="page" value="bdfg-search-analytics">
<label for="date-range"><?php _e('日期范围:', 'bdfg-product-search'); ?></label>
<select name="date_range" id="date-range">
<option value="7" <?php selected(isset($_GET['date_range']) ? $_GET['date_range'] : '30', '7'); ?>><?php _e('最近7天', 'bdfg-product-search'); ?></option>
<option value="30" <?php selected(isset($_GET['date_range']) ? $_GET['date_range'] : '30', '30'); ?>><?php _e('最近30天', 'bdfg-product-search'); ?></option>
<option value="90" <?php selected(isset($_GET['date_range']) ? $_GET['date_range'] : '30', '90'); ?>><?php _e('最近90天', 'bdfg-product-search'); ?></option>
</select>
<button type="submit" class="button"><?php _e('应用', 'bdfg-product-search'); ?></button>
</form>
</div>

<div class="bdfg-analytics-dashboard">
<!-- 概览卡片 -->
<div class="bdfg-analytics-row">
<div class="bdfg-card">
<div class="bdfg-card-header"><?php _e('搜索总次数', 'bdfg-product-search'); ?></div>
<div class="bdfg-card-value"><?php echo esc_html($data['total_searches']); ?></div>
<div class="bdfg-card-footer"><?php
$change = isset($data['search_change']) ? $data['search_change'] : 0;
$class = $change >= 0 ? 'positive' : 'negative';
$icon = $change >= 0 ? '↑' : '↓';
echo '<span class="' . esc_attr($class) . '">' . esc_html($icon . ' ' . abs($change) . '%') . '</span>';
_e(' 相比上期', 'bdfg-product-search');
?></div>
</div>

<div class="bdfg-card">
<div class="bdfg-card-header"><?php _e('独立搜索词', 'bdfg-product-search'); ?></div>
<div class="bdfg-card-value"><?php echo esc_html($data['unique_terms']); ?></div>
<div class="bdfg-card-footer"><?php _e('不同的搜索关键词', 'bdfg-product-search'); ?></div>
</div>

<div class="bdfg-card">
<div class="bdfg-card-header"><?php _e('有结果率', 'bdfg-product-search'); ?></div>
<div class="bdfg-card-value"><?php echo esc_html($data['success_rate']); ?>%</div>
<div class="bdfg-card-footer"><?php _e('返回结果的搜索比例', 'bdfg-product-search'); ?></div>
</div>

<div class="bdfg-card">
<div class="bdfg-card-header"><?php _e('平均结果数', 'bdfg-product-search'); ?></div>
<div class="bdfg-card-value"><?php echo esc_html($data['avg_results']); ?></div>
<div class="bdfg-card-footer"><?php _e('每次搜索平均产品数', 'bdfg-product-search'); ?></div>
</div>
</div>

<!-- 图表和表格 -->
<div class="bdfg-analytics-row">
<div class="bdfg-analytics-col">
<div class="bdfg-analytics-card">
<h2><?php _e('搜索趋势', 'bdfg-product-search'); ?></h2>
<div class="bdfg-chart-container">
<canvas id="bdfg-search-trends-chart"></canvas>
</div>
</div>
</div>
</div>

<div class="bdfg-analytics-row">
<div class="bdfg-analytics-col">
<div class="bdfg-analytics-card">
<h2><?php _e('热门搜索词', 'bdfg-product-search'); ?></h2>
<?php if (!empty($data['popular_searches'])): ?>
<table class="bdfg-analytics-table">
<thead>
<tr>
<th><?php _e('搜索词', 'bdfg-product-search'); ?></th>
<th><?php _e('搜索次数', 'bdfg-product-search'); ?></th>
<th><?php _e('平均结果数', 'bdfg-product-search'); ?></th>
<th><?php _e('详情', 'bdfg-product-search'); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($data['popular_searches'] as $search): ?>
<tr>
<td><?php echo esc_html($search->search_term); ?></td>
<td><?php echo esc_html($search->count); ?></td>
<td><?php echo esc_html(round($search->avg_results, 1)); ?></td>
<td>
<a href="<?php echo esc_url(admin_url('edit.php?post_type=product&s=' . urlencode($search->search_term))); ?>" target="_blank">
<?php _e('查看产品', 'bdfg-product-search'); ?>
</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php else: ?>
<p class="bdfg-no-data"><?php _e('暂无搜索数据', 'bdfg-product-search'); ?></p>
<?php endif; ?>
</div>
</div>

<div class="bdfg-analytics-col">
<div class="bdfg-analytics-card">
<h2><?php _e('零结果搜索词', 'bdfg-product-search'); ?></h2>
<?php if (!empty($data['zero_results'])): ?>
<table class="bdfg-analytics-table">
<thead>
<tr>
<th><?php _e('搜索词', 'bdfg-product-search'); ?></th>
<th><?php _e('搜索次数', 'bdfg-product-search'); ?></th>
<th><?php _e('最近搜索', 'bdfg-product-search'); ?></th>
<th><?php _e('操作', 'bdfg-product-search'); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($data['zero_results'] as $search): ?>
<tr>
<td><?php echo esc_html($search->search_term); ?></td>
<td><?php echo esc_html($search->count); ?></td>
<td><?php echo esc_html(date_i18n(get_option('date_format'), strtotime($search->last_search))); ?></td>
<td>
<a href="<?php echo esc_url(admin_url('post-new.php?post_type=product&bdfg_search_term=' . urlencode($search->search_term))); ?>" class="button button-small">
<?php _e('创建产品', 'bdfg-product-search'); ?>
</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php else: ?>
<p class="bdfg-no-data"><?php _e('没有零结果搜索记录', 'bdfg-product-search'); ?></p>
<?php endif; ?>
</div>
</div>
</div>
</div>
</div>

<div class="bdfg-admin-footer">
<p><?php _e('由 BeiDuoFenGou 倾情打造', 'bdfg-product-search'); ?> &copy; <?php echo date('Y'); ?> <a href="https://beiduofengou.net" target="_blank">beiduofengou.net</a></p>
</div>
</div>

<script>
jQuery(document).ready(function($) {
var ctx = document.getElementById('bdfg-search-trends-chart').getContext('2d');

var chartData = <?php echo json_encode($data['trends']); ?>;
var labels = chartData.map(function(item) { return item.date; });
var searchCounts = chartData.map(function(item) { return parseInt(item.count); });

new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: '<?php _e('每日搜索次数', 'bdfg-product-search'); ?>',
data: searchCounts,
backgroundColor: 'rgba(23, 107, 239, 0.1)',
borderColor: 'rgba(23, 107, 239, 1)',
borderWidth: 2,
tension: 0.3,
pointBackgroundColor: 'rgba(23, 107, 239, 1)',
pointRadius: 4,
pointHoverRadius: 6,
fill: true
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true,
grid: {
color: 'rgba(0, 0, 0, 0.05)'
}
},
x: {
grid: {
display: false
}
}
},
plugins: {
legend: {
display: false
},
tooltip: {
backgroundColor: 'rgba(0, 0, 0, 0.8)',
padding: 10,
titleColor: '#ffffff',
bodyColor: '#ffffff',
borderColor: 'rgba(255, 255, 255, 0.2)',
borderWidth: 1,
displayColors: false
}
},
interaction: {
mode: 'index',
intersect: false
}
}
});
});
</script>
<?php
}

/**
* 渲染帮助页面
*/
public function render_help_page() {
if (!current_user_can('manage_options')) {
return;
}

?>
<div class="wrap bdfg-admin-wrap bdfg-help-wrap">
<div class="bdfg-admin-header">
<div class="bdfg-logo">
<img src="<?php echo esc_url($this->plugin_url . 'assets/images/bdfg-logo.png'); ?>" alt="BDFG Logo">
<h1><?php _e('BDFG 产品搜索使用帮助', 'bdfg-product-search'); ?></h1>
</div>
</div>

<div class="bdfg-admin-content">
<div class="bdfg-help-nav">
<ul>
<li><a href="#getting-started" class="active"><?php _e('入门指南', 'bdfg-product-search'); ?></a></li>
<li><a href="#features"><?php _e('功能介绍', 'bdfg-product-search'); ?></a></li>
<li><a href="#shortcodes"><?php _e('短代码使用', 'bdfg-product-search'); ?></a></li>
<li><a href="#faq"><?php _e('常见问题', 'bdfg-product-search'); ?></a></li>
<li><a href="#troubleshooting"><?php _e('故障排除', 'bdfg-product-search'); ?></a></li>
</ul>
</div>

<div class="bdfg-help-content">
<div id="getting-started" class="bdfg-help-section active">
<h2><?php _e('入门指南', 'bdfg-product-search'); ?></h2>

<div class="bdfg-help-box">
<h3><?php _e('1. 安装与激活', 'bdfg-product-search'); ?></h3>
<p><?php _e('安装并激活BDFG产品搜索增强工具插件后,您可以在左侧菜单栏中找到"BDFG 产品搜索"选项。', 'bdfg-product-search'); ?></p>
</div>

<div class="bdfg-help-box">
<h3><?php _e('2. 基本配置', 'bdfg-product-search'); ?></h3>
<p><?php _e('进入"BDFG 产品搜索"设置页面,根据需求开启或关闭相关功能。默认情况下,所有主要功能均已启用。', 'bdfg-product-search'); ?></p>
<img src="<?php echo esc_url($this->plugin_url . 'assets/images/help/settings.jpg'); ?>" alt="设置页面">
</div>

<div class="bdfg-help-box">
<h3><?php _e('3. 添加搜索表单', 'bdfg-product-search'); ?></h3>
<p><?php _e('使用短代码 [bdfg_product_search] 在任何页面或文章中插入产品搜索表单。', 'bdfg-product-search'); ?></p>
<p><?php _e('或者,您可以使用小部件将搜索表单添加到侧边栏或其他小部件区域。', 'bdfg-product-search'); ?></p>
</div>

<div class="bdfg-help-box">
<h3><?php _e('4. 查看搜索分析', 'bdfg-product-search'); ?></h3>
<p><?php _e('访问"搜索分析"页面,了解用户搜索行为,查看热门搜索词和零结果搜索词统计。', 'bdfg-product-search'); ?></p>
</div>
</div>

<div id="features" class="bdfg-help-section">
<h2><?php _e('功能介绍', 'bdfg-product-search'); ?></h2>

<div class="bdfg-help-columns">
<div class="bdfg-help-column">
<div class="bdfg-feature-box">
<h3><?php _e('智能搜索建议', 'bdfg-product-search'); ?></h3>
<p><?php _e('在用户输入时实时显示相关产品建议,支持产品图片、价格和库存状态显示。减少输入时间,提高转化率。', 'bdfg-product-search'); ?></p>
</div>

<div class="bdfg-feature-box">
<h3><?php _e('模糊搜索匹配', 'bdfg-product-search'); ?></h3>
<p><?php _e('即使用户拼写错误或使用近似词也能找到相关产品。特别适合中文拼音变体和多音字搜索场景。', 'bdfg-product-search'); ?></p>
</div>
</div>

<div class="bdfg-help-column">
<div class="bdfg-feature-box">
<h3><?php _e('产品元标签自动生成', 'bdfg-product-search'); ?></h3>
<p><?php _e('自动为产品页面生成SEO友好的元标签和结构化数据,提高产品在搜索引擎中的可见度和排名。', 'bdfg-product-search'); ?></p>
</div>

<div class="bdfg-feature-box">
<h3><?php _e('高级产品过滤器', 'bdfg-product-search'); ?></h3>
<p><?php _e('允许用户通过价格范围、分类、评分和库存状态等多维度筛选产品,提升购物体验。', 'bdfg-product-search'); ?></p>
</div>
</div>
</div>

<div class="bdfg-help-box">
<h3><?php _e('详细搜索分析', 'bdfg-product-search'); ?></h3>
<p><?php _e('提供全面的搜索数据分析,包括搜索量趋势、热门搜索词、零结果搜索词等,帮助店主调整产品策略。', 'bdfg-product-search'); ?></p>
<img src="<?php echo esc_url($this->plugin_url . 'assets/images/help/analytics.jpg'); ?>" alt="搜索分析">
</div>
</div>

<div id="shortcodes" class="bdfg-help-section">
<h2><?php _e('短代码使用', 'bdfg-product-search'); ?></h2>

<div class="bdfg-help-box">
<h3><?php _e('基本短代码', 'bdfg-product-search'); ?></h3>
<code class="bdfg-shortcode">[bdfg_product_search]</code>
<p><?php _e('显示默认样式的BDFG产品搜索框。', 'bdfg-product-search'); ?></p>
</div>

<div class="bdfg-help-box">
<h3><?php _e('自定义占位符文本', 'bdfg-product-search'); ?></h3>
<code class="bdfg-shortcode">[bdfg_product_search placeholder="输入关键词搜索BDFG产品"]</code>
<p><?php _e('自定义搜索框中显示的占位符文本。', 'bdfg-product-search'); ?></p>
</div>

<div class="bdfg-help-box">
<h3><?php _e('自定义按钮文本', 'bdfg-product-search'); ?></h3>
<code class="bdfg-shortcode">[bdfg_product_search button_text="立即查找"]</code>
<p><?php _e('自定义搜索按钮上显示的文本。', 'bdfg-product-search'); ?></p>
</div>

<div class="bdfg-help-box">
<h3><?php _e('显示产品过滤器', 'bdfg-product-search'); ?></h3>
<code class="bdfg-shortcode">[bdfg_product_search show_filters="yes"]</code>
<p><?php _e('在搜索框下方显示高级产品过滤器,允许用户筛选结果。', 'bdfg-product-search'); ?></p>
</div>

<div class="bdfg-help-box">
<h3><?php _e('组合使用', 'bdfg-product-search'); ?></h3>
<code class="bdfg-shortcode">[bdfg_product_search placeholder="查找BDFG优质产品" button_text="开始搜索" show_filters="yes"]</code>
<p><?php _e('组合使用多个参数自定义搜索表单。', 'bdfg-product-search'); ?></p>
</div>
</div>

<div id="faq" class="bdfg-help-section">
<h2><?php _e('常见问题', 'bdfg-product-search'); ?></h2>

<div class="bdfg-faq-item">
<h3><?php _e('BDFG产品搜索增强工具是否与其他搜索插件兼容?', 'bdfg-product-search'); ?></h3>
<div class="bdfg-faq-answer">
<p><?php _e('是的,BDFG产品搜索增强工具专注于WooCommerce产品搜索,通常与其他针对文章和页面的搜索插件兼容。但为了避免潜在冲突,我们建议仅使用一个专门的产品搜索解决方案。', 'bdfg-product-search'); ?></p>
</div>
</div>

<div class="bdfg-faq-item">
<h3><?php _e('模糊搜索功能会影响网站性能吗?', 'bdfg-product-search'); ?></h3>
<div class="bdfg-faq-answer">
<p><?php _e('BDFG产品搜索采用优化算法和缓存机制,在大多数情况下不会显著影响网站性能。对于拥有数千产品的大型商店,我们建议将缓存生命周期设置为较长时间(12-24小时)以提高性能。', 'bdfg-product-search'); ?></p>
</div>
</div>

<div class="bdfg-faq-item">
<h3><?php _e('插件是否支持多语言商店?', 'bdfg-product-search'); ?></h3>
<div class="bdfg-faq-answer">
<p><?php _e('是的,BDFG产品搜索增强工具完全兼容多语言网站。插件支持翻译,并且模糊搜索算法经过优化,可处理各种字符集和语言特性,包括中文、英文和其他常见语言。', 'bdfg-product-search'); ?></p>
</div>
</div>

<div class="bdfg-faq-item">
<h3><?php _e('如何自定义搜索结果的外观?', 'bdfg-product-search'); ?></h3>
<div class="bdfg-faq-answer">
<p><?php _e('您可以通过两种方式自定义搜索结果外观:', 'bdfg-product-search'); ?></p>
<ol>
<li><?php _e('在您的主题中添加自定义CSS来覆盖默认样式', 'bdfg-product-search'); ?></li>
<li><?php _e('在主题目录中创建 <code>bdfg-product-search/search-results.php</code> 模板文件来完全自定义结果HTML结构', 'bdfg-product-search'); ?></li>
</ol>
</div>
</div>

<div class="bdfg-faq-item">
<h3><?php _e('搜索分析数据会影响网站存储空间吗?', 'bdfg-product-search'); ?></h3>
<div class="bdfg-faq-answer">
<p><?php _e('BDFG产品搜索采用高效的数据存储方式,搜索日志数据通常不会占用大量存储空间。系统还会自动清理超过90天的旧数据,确保数据库保持精简高效。', 'bdfg-product-search'); ?></p>
</div>
</div>
</div>

<div id="troubleshooting" class="bdfg-help-section">
<h2><?php _e('故障排除', 'bdfg-product-search'); ?></h2>

<div class="bdfg-help-box">
<h3><?php _e('搜索自动完成不工作', 'bdfg-product-search'); ?></h3>
<p><?php _e('如果智能搜索建议功能不工作,请检查:', 'bdfg-product-search'); ?></p>
<ol>
<li><?php _e('确认"启用智能搜索建议功能"选项已开启', 'bdfg-product-search'); ?></li>
<li><?php _e('检查您的主题是否有JavaScript错误(使用浏览器控制台)', 'bdfg-product-search'); ?></li>
<li><?php _e('确保您的网站未使用过于严格的内容安全策略(CSP)', 'bdfg-product-search'); ?></li>
<li><?php _e('临时禁用其他可能冲突的插件', 'bdfg-product-search'); ?></li>
</ol>
</div>

<div class="bdfg-help-box">
<h3><?php _e('搜索结果不相关', 'bdfg-product-search'); ?></h3>
<p><?php _e('如果搜索结果相关性较低,可以尝试:', 'bdfg-product-search'); ?></p>
<ol>
<li><?php _e('调整"模糊匹配阈值"设置(较低的值会产生更精确的结果)', 'bdfg-product-search'); ?></li>
<li><?php _e('确保产品标题、描述和属性包含相关的关键词', 'bdfg-product-search'); ?></li>
<li><?php _e('为产品添加更多元数据和标签', 'bdfg-product-search'); ?></li>
</ol>
</div>

<div class="bdfg-help-box">
<h3><?php _e('搜索分析数据未显示', 'bdfg-product-search'); ?></h3>
<p><?php _e('如果搜索分析页面未显示数据,请检查:', 'bdfg-product-search'); ?></p>
<ol>
<li><?php _e('确认数据库中存在 bdfg_search_logs 表', 'bdfg-product-search'); ?></li>
<li><?php _e('确保网站上至少有一些搜索活动', 'bdfg-product-search'); ?></li>
<li><?php _e('检查WordPress错误日志中是否有相关错误', 'bdfg-product-search'); ?></li>
</ol>
</div>

<div class="bdfg-help-box">
<h3><?php _e('联系支持', 'bdfg-product-search'); ?></h3>
<p><?php _e('如果您遇到无法解决的问题,请联系我们的支持团队:', 'bdfg-product-search'); ?></p>
<ul>
<li><?php _e('邮件:', 'bdfg-product-search'); ?> <a href="mailto:[email protected]">[email protected]</a></li>
<li><?php _e('官网支持:', 'bdfg-product-search'); ?> <a href="https://beiduofengou.net/support" target="_blank">https://beiduofengou.net/support</a></li>
</ul>
<p><?php _e('请在提交支持请求时提供以下信息:', 'bdfg-product-search'); ?></p>
<ul>
<li><?php _e('WordPress版本', 'bdfg-product-search'); ?></li>
<li><?php _e('WooCommerce版本', 'bdfg-product-search'); ?></li>
<li><?php _e('BDFG产品搜索增强工具版本', 'bdfg-product-search'); ?></li>
<li><?php _e('您使用的主题', 'bdfg-product-search'); ?></li>
<li><?php _e('问题的详细描述', 'bdfg-product-search'); ?></li>
</ul>
</div>
</div>
</div>
</div>

<div class="bdfg-admin-footer">
<p><?php _e('由 BeiDuoFenGou 倾情打造', 'bdfg-product-search'); ?> &copy; <?php echo date('Y'); ?> <a href="https://beiduofengou.net" target="_blank">beiduofengou.net</a></p>
</div>
</div>

<script>
jQuery(document).ready(function($) {
// 帮助页面导航
$('.bdfg-help-nav a').click(function(e) {
e.preventDefault();

// 获取目标部分ID
var target = $(this).attr('href');

// 更新活动导航项
$('.bdfg-help-nav a').removeClass('active');
$(this).addClass('active');

// 显示目标部分,隐藏其他部分
$('.bdfg-help-section').removeClass('active');
$(target).addClass('active');

// 平滑滚动到目标部分
$('html, body').animate({
scrollTop: $(target).offset().top - 50
}, 500);
});

// FAQ项目交互
$('.bdfg-faq-item h3').click(function() {
$(this).parent().toggleClass('active');
$(this).next('.bdfg-faq-answer').slideToggle(200);
});
});
</script>
<?php
}

/**
* 加载管理样式和脚本
*
* @param string $hook 当前管理页面的hook名称
*/
public function admin_enqueue_scripts($hook) {
// 仅在插件页面加载资源
if (strpos($hook, 'bdfg-product-search') === false && strpos($hook, 'bdfg-search-analytics') === false && strpos($hook, 'bdfg-search-help') === false) {
return;
}

// 加载管理CSS
wp_enqueue_style(
'bdfg-product-search-admin',
$this->plugin_url . 'assets/css/admin-style.css',
array(),
$this->version
);

// 加载管理JavaScript
wp_enqueue_script(
'bdfg-product-search-admin',
$this->plugin_url . 'assets/js/admin-script.js',
array('jquery'),
$this->version,
true
);

// 如果是分析页面,加载Chart.js
if (strpos($hook, 'bdfg-search-analytics') !== false) {
wp_enqueue_script(
'chart-js',
$this->plugin_url . 'assets/js/chart.min.js',
array(),
'3.9.1',
true
);
}
}

/**
* 添加插件操作链接
*
* @param array $links 插件操作链接数组
* @return array 修改后的链接数组
*/
public function plugin_action_links($links) {
$plugin_links = array(
'<a href="' . admin_url('admin.php?page=bdfg-product-search') . '">' . __('设置', 'bdfg-product-search') . '</a>',
'<a href="' . admin_url('admin.php?page=bdfg-search-analytics') . '">' . __('分析', 'bdfg-product-search') . '</a>'
);
return array_merge($plugin_links, $links);
}

/**
* 添加插件元信息
*
* @param array $links 插件元信息链接数组
* @param string $file 插件文件
* @return array 修改后的链接数组
*/
public function plugin_row_meta($links, $file) {
if (BDFG_PRODUCT_SEARCH_BASENAME === $file) {
$row_meta = array(
'docs' => '<a href="https://beiduofengou.net/docs/bdfg-product-search" target="_blank">' . __('文档', 'bdfg-product-search') . '</a>',
'support' => '<a href="https://beiduofengou.net/support" target="_blank">' . __('支持', 'bdfg-product-search') . '</a>',
);

return array_merge($links, $row_meta);
}

return $links;
}
}

includes/class-bdfg-frontend.php

<?php
/**
* BDFG 产品搜索增强工具前端类
*
* @package BDFG_Product_Search
* @since 1.0.0
*/

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

class BDFG_Frontend {

/**
* 插件目录路径
*
* @var string
*/
private $plugin_path;

/**
* 插件URL
*
* @var string
*/
private $plugin_url;

/**
* 插件版本
*
* @var string
*/
private $version;

/**
* 选项名称
*
* @var string
*/
private $option_name;

/**
* 插件选项
*
* @var array
*/
private $options;

/**
* 构造函数
*
* @param string $plugin_path 插件目录路径
* @param string $plugin_url 插件URL
* @param string $version 插件版本
* @param string $option_name 选项名称
* @param array $options 插件选项
*/
public function __construct($plugin_path, $plugin_url, $version, $option_name, $options) {
$this->plugin_path = $plugin_path;
$this->plugin_url = $plugin_url;
$this->version = $version;
$this->option_name = $option_name;
$this->options = $options;

// 初始化前端功能
$this->init();
}

/**
* 初始化前端功能
*/
private function init() {
// 加载前端脚本和样式
add_action('wp_enqueue_scripts', array($this, 'enqueue_scripts'));

// 添加产品元标签
if ($this->options['enable_meta_tags'] === 'yes') {
add_action('wp_head', array($this, 'add_product_meta_tags'), 1);
}

// 添加搜索自动完成API端点
if ($this->options['enable_autocomplete'] === 'yes') {
add_action('rest_api_init', array($this, 'register_autocomplete_endpoint'));
}

// 修改搜索查询以支持模糊搜索
if ($this->options['enable_fuzzy_search'] === 'yes') {
add_filter('posts_search', array($this, 'fuzzy_search_filter'), 10, 2);
}

// 添加产品过滤功能
if ($this->options['enable_filters'] === 'yes') {
add_action('woocommerce_before_shop_loop', array($this, 'add_product_filters'), 30);
add_action('pre_get_posts', array($this, 'filter_products_query'));
}

// 注册BDFG搜索小部件
add_action('widgets_init', array($this, 'register_widgets'));
}

/**
* 前端脚本和样式加载
*/
public function enqueue_scripts() {
// 加载主样式表
wp_enqueue_style(
'bdfg-product-search',
$this->plugin_url . 'assets/css/bdfg-product-search.css',
array(),
$this->version
);

// 自动完成功能
if ($this->options['enable_autocomplete'] === 'yes') {
wp_enqueue_script(
'bdfg-product-search',
$this->plugin_url . 'assets/js/bdfg-product-search.js',
array('jquery'),
$this->version,
true
);

wp_localize_script(
'bdfg-product-search',
'bdfg_product_search',
array(
'ajax_url' => rest_url('bdfg/v1/autocomplete'),
'nonce' => wp_create_nonce('wp_rest'),
'results_limit' => $this->options['search_results_limit'],
'no_results_text' => __('未找到相关产品', 'bdfg-product-search'),
'typing_text' => __('正在搜索...', 'bdfg-product-search'),
'view_all_text' => __('查看全部结果', 'bdfg-product-search'),
'enable_fuzzy' => $this->options['enable_fuzzy_search'] === 'yes',
'currency_symbol' => get_woocommerce_currency_symbol(),
'site_url' => site_url(),
)
);
}

// 过滤功能
if ($this->options['enable_filters'] === 'yes') {
wp_enqueue_style(
'bdfg-product-filters',
$this->plugin_url . 'assets/css/bdfg-product-filters.css',
array(),
$this->version
);

wp_enqueue_script(
'bdfg-product-filters',
$this->plugin_url . 'assets/js/bdfg-product-filters.js',
array('jquery', 'jquery-ui-slider'),
$this->version,
true
);
}
}

/**
* 添加产品页面的元标签
*/
public function add_product_meta_tags() {
// 只在产品页面添加
if (!is_singular('product')) {
return;
}

global $post;

// 获取产品数据
$product = wc_get_product($post->ID);

if (!$product) {
return;
}

// 获取产品信息
$title = $product->get_name();
$description = $product->get_short_description();
if (empty($description)) {
$description = wp_trim_words($product->get_description(), 30);
}

// 如果描述仍然为空,使用标题
if (empty($description)) {
$description = $title;
}

// 获取产品关键词
$keywords = array($title);

// 添加产品分类作为关键词
$categories = get_the_terms($post->ID, 'product_cat');
if ($categories && !is_wp_error($categories)) {
foreach ($categories as $category) {
$keywords[] = $category->name;

// 添加父分类
$parent_id = $category->parent;
while ($parent_id) {
$parent = get_term($parent_id, 'product_cat');
if ($parent && !is_wp_error($parent)) {
$keywords[] = $parent->name;
$parent_id = $parent->parent;
} else {
$parent_id = 0;
}
}
}
}

// 添加产品标签
$tags = get_the_terms($post->ID, 'product_tag');
if ($tags && !is_wp_error($tags)) {
foreach ($tags as $tag) {
$keywords[] = $tag->name;
}
}

// 添加SKU和品牌(如果有)
$sku = $product->get_sku();
if (!empty($sku)) {
$keywords[] = $sku;
}

// 获取额外的产品属性
$attributes = $product->get_attributes();
if (!empty($attributes)) {
foreach ($attributes as $attribute) {
if ($attribute->is_taxonomy()) {
$terms = wp_get_post_terms($product->get_id(), $attribute->get_name(), array('fields' => 'names'));
if (!is_wp_error($terms)) {
$keywords = array_merge($keywords, $terms);
}
} else {
$keywords[] = $attribute->get_options();
}
}
}

// 删除重复项并限制关键词数量
$keywords = array_unique($keywords);
$keywords = array_slice($keywords, 0, 20);

// 输出标准元标签
echo '<meta name="description" content="' . esc_attr($description) . '" />' . "\n";
echo '<meta name="keywords" content="' . esc_attr(implode(', ', $keywords)) . '" />' . "\n";

// Open Graph 标签
echo '<meta property="og:title" content="' . esc_attr($title) . '" />' . "\n";
echo '<meta property="og:description" content="' . esc_attr($description) . '" />' . "\n";
echo '<meta property="og:type" content="product" />' . "\n";
echo '<meta property="og:url" content="' . esc_url(get_permalink()) . '" />' . "\n";
echo '<meta property="product:brand" content="' . esc_attr(get_bloginfo('name')) . '" />' . "\n";

// 添加产品图片
$image_id = $product->get_image_id();
if ($image_id) {
$image_url = wp_get_attachment_image_src($image_id, 'large');
if ($image_url) {
echo '<meta property="og:image" content="' . esc_url($image_url[0]) . '" />' . "\n";
echo '<meta property="og:image:width" content="' . esc_attr($image_url[1]) . '" />' . "\n";
echo '<meta property="og:image:height" content="' . esc_attr($image_url[2]) . '" />' . "\n";
}
}

// 添加价格和货币信息
echo '<meta property="product:price:amount" content="' . esc_attr($product->get_price()) . '" />' . "\n";
echo '<meta property="product:price:currency" content="' . esc_attr(get_woocommerce_currency()) . '" />' . "\n";

// 添加商品库存状态
echo '<meta property="product:availability" content="' . esc_attr($product->is_in_stock() ? 'in stock' : 'out of stock') . '" />' . "\n";

// 添加商品条形码/GTIN(如果有)
$gtin = get_post_meta($product->get_id(), '_gtin', true);
if (!empty($gtin)) {
echo '<meta property="product:gtin" content="' . esc_attr($gtin) . '" />' . "\n";
}

// 添加商品颜色(如果有)
$color_attribute_name = 'pa_color';
if ($product->get_attribute($color_attribute_name)) {
echo '<meta property="product:color" content="' . esc_attr($product->get_attribute($color_attribute_name)) . '" />' . "\n";
}

// 添加TwitterCard标签
echo '<meta name="twitter:card" content="product" />' . "\n";
echo '<meta name="twitter:title" content="' . esc_attr($title) . '" />' . "\n";
echo '<meta name="twitter:description" content="' . esc_attr($description) . '" />' . "\n";
if ($image_id && $image_url) {
echo '<meta name="twitter:image" content="' . esc_url($image_url[0]) . '" />' . "\n";
}

// 添加结构化数据标记 (JSON-LD)
$this->add_product_schema($product);
}

/**
* 添加产品结构化数据
*
* @param WC_Product $product WooCommerce产品对象
*/
private function add_product_schema($product) {
// 基本产品信息
$schema = array(
'@context' => 'https://schema.org/',
'@type' => 'Product',
'name' => $product->get_name(),
'description' => wp_strip_all_tags($product->get_short_description() ? $product->get_short_description() : $product->get_description()),
'sku' => $product->get_sku(),
'brand' => array(
'@type' => 'Brand',
'name' => get_bloginfo('name')
),
'offers' => array(
'@type' => 'Offer',
'url' => get_permalink($product->get_id()),
'price' => $product->get_price(),
'priceCurrency' => get_woocommerce_currency(),
'priceValidUntil' => date('Y-m-d', strtotime('+1 year')),
'availability' => $product->is_in_stock() ? 'https://schema.org/InStock' : 'https://schema.org/OutOfStock',
'seller' => array(
'@type' => 'Organization',
'name' => get_bloginfo('name')
)
)
);

// 添加产品分类
$categories = get_the_terms($product->get_id(), 'product_cat');
if ($categories && !is_wp_error($categories)) {
$schema['category'] = $categories[0]->name;
}

// 添加产品图片
$image_id = $product->get_image_id();
if ($image_id) {
$image_url = wp_get_attachment_image_src($image_id, 'large');
if ($image_url) {
$schema['image'] = $image_url[0];
}
}

// 添加产品画廊图片
$gallery_image_ids = $product->get_gallery_image_ids();
if (!empty($gallery_image_ids)) {
$gallery_images = array();
foreach ($gallery_image_ids as $gallery_image_id) {
$gallery_image_url = wp_get_attachment_image_src($gallery_image_id, 'large');
if ($gallery_image_url) {
$gallery_images[] = $gallery_image_url[0];
}
}
if (!empty($gallery_images)) {
$schema['image'] = $gallery_images;
}
}
}

// 添加产品评分
if ($product->get_rating_count() > 0) {
$schema['aggregateRating'] = array(
'@type' => 'AggregateRating',
'ratingValue' => $product->get_average_rating(),
'reviewCount' => $product->get_rating_count(),
'bestRating' => '5',
'worstRating' => '1'
);

// 获取评论作为评论项
$comments = get_comments(array(
'post_id' => $product->get_id(),
'status' => 'approve',
'number' => 5,
));

if (!empty($comments)) {
$reviews = array();
foreach ($comments as $comment) {
$rating = get_comment_meta($comment->comment_ID, 'rating', true);
if (!$rating) continue;

$reviews[] = array(
'@type' => 'Review',
'reviewRating' => array(
'@type' => 'Rating',
'ratingValue' => $rating,
'bestRating' => '5',
'worstRating' => '1'
),
'author' => array(
'@type' => 'Person',
'name' => $comment->comment_author
),
'reviewBody' => $comment->comment_content,
'datePublished' => date('c', strtotime($comment->comment_date))
);
}

if (!empty($reviews)) {
$schema['review'] = $reviews;
}
}
}

// 如果是变体产品,添加变体信息
if ($product->is_type('variable')) {
$variations = $product->get_available_variations();
$variation_attributes = array();

if (!empty($variations)) {
foreach ($variations as $variation) {
$variation_obj = wc_get_product($variation['variation_id']);
if ($variation_obj) {
$variation_attributes[] = array(
'@type' => 'Offer',
'price' => $variation_obj->get_price(),
'priceCurrency' => get_woocommerce_currency(),
'availability' => $variation_obj->is_in_stock() ? 'https://schema.org/InStock' : 'https://schema.org/OutOfStock',
'url' => get_permalink($variation_obj->get_id()),
'priceValidUntil' => date('Y-m-d', strtotime('+1 year'))
);
}
}

if (!empty($variation_attributes)) {
$schema['offers'] = $variation_attributes;
}
}
}

// 输出JSON-LD
echo '<script type="application/ld+json">' . json_encode($schema, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . '</script>' . "\n";
}

/**
* 注册自动完成API端点
*/
public function register_autocomplete_endpoint() {
register_rest_route('bdfg/v1', '/autocomplete', array(
'methods' => 'GET',
'callback' => array($this, 'get_autocomplete_results'),
'permission_callback' => '__return_true',
'args' => array(
'term' => array(
'required' => true,
'sanitize_callback' => 'sanitize_text_field'
)
)
));
}

/**
* 获取自动完成搜索结果
*
* @param WP_REST_Request $request 请求对象
* @return WP_REST_Response 响应对象
*/
public function get_autocomplete_results($request) {
$search_term = $request->get_param('term');

if (empty($search_term)) {
return new WP_REST_Response(array(), 200);
}

// 记录用户访问信息
$this->log_search($search_term);

$limit = intval($this->options['search_results_limit']);

// 尝试从缓存获取结果
$cache_key = 'bdfg_autocomplete_' . md5($search_term . $limit);
$cached_results = get_transient($cache_key);

if (false !== $cached_results && $this->options['cache_lifetime'] > 0) {
return new WP_REST_Response($cached_results, 200);
}

// 构建搜索查询
$args = array(
'post_type' => 'product',
'post_status' => 'publish',
'posts_per_page' => $limit,
's' => $search_term,
'orderby' => 'relevance',
'order' => 'DESC',
);

// 执行查询
$query = new WP_Query($args);
$results = array();
$has_results = false;

if ($query->have_posts()) {
$has_results = true;

while ($query->have_posts()) {
$query->the_post();
$product = wc_get_product(get_the_ID());

if (!$product) {
continue;
}

$image_id = $product->get_image_id();
$image_url = $image_id ? wp_get_attachment_image_src($image_id, 'thumbnail')[0] : wc_placeholder_img_src('thumbnail');

// 获取产品价格
$regular_price = $product->get_regular_price();
$sale_price = $product->get_sale_price();
$on_sale = $product->is_on_sale();

$results[] = array(
'id' => $product->get_id(),
'title' => $product->get_name(),
'url' => get_permalink($product->get_id()),
'price_html' => $product->get_price_html(),
'regular_price' => $regular_price,
'sale_price' => $sale_price,
'on_sale' => $on_sale,
'image' => $image_url,
'stock' => $product->is_in_stock() ? __('有货', 'bdfg-product-search') : __('缺货', 'bdfg-product-search'),
'categories' => $this->get_product_categories($product->get_id()),
'rating' => $product->get_average_rating(),
'type' => $product->get_type(),
'excerpt' => $this->get_product_excerpt($product)
);
}
}

wp_reset_postdata();

// 如果启用了模糊搜索且没有结果,尝试模糊搜索
if (empty($results) && $this->options['enable_fuzzy_search'] === 'yes') {
$fuzzy_results = $this->perform_fuzzy_search($search_term, $limit);

if (!empty($fuzzy_results)) {
$has_results = true;
$results = $fuzzy_results;
}
}

// 记录搜索查询和结果数量
$this->log_search_query($search_term, count($results));

// 缓存结果
if ($this->options['cache_lifetime'] > 0) {
set_transient($cache_key, $results, intval($this->options['cache_lifetime']) * HOUR_IN_SECONDS);
}

return new WP_REST_Response($results, 200);
}

/**
* 执行模糊搜索
*
* @param string $search_term 搜索词
* @param int $limit 结果数量限制
* @return array 搜索结果
*/
private function perform_fuzzy_search($search_term, $limit) {
global $wpdb;

// 获取已发布产品的标题和ID
$products = $wpdb->get_results(
$wpdb->prepare(
"SELECT ID, post_title, post_excerpt, post_content
FROM {$wpdb->posts}
WHERE post_type = 'product'
AND post_status = 'publish'
LIMIT 1000"
)
);

$results = array();
$threshold = intval($this->options['fuzzy_match_threshold']);
$search_term_lower = mb_strtolower($search_term);

foreach ($products as $product_post) {
// 检查产品标题
$title_distance = $this->levenshtein_distance($search_term_lower, mb_strtolower($product_post->post_title));

// 检查产品内容中的关键词
$content_match = false;
if (strpos(mb_strtolower($product_post->post_content), $search_term_lower) !== false) {
$content_match = true;
}

// 检查产品摘要中的关键词
$excerpt_match = false;
if (strpos(mb_strtolower($product_post->post_excerpt), $search_term_lower) !== false) {
$excerpt_match = true;
}

// 检查产品SKU
$sku_match = false;
$sku = $wpdb->get_var($wpdb->prepare(
"SELECT meta_value FROM {$wpdb->postmeta}
WHERE post_id = %d
AND meta_key = '_sku'",
$product_post->ID
));

if ($sku && strpos(mb_strtolower($sku), $search_term_lower) !== false) {
$sku_match = true;
}

// 如果满足任一条件,则添加产品到结果中
if ($title_distance <= $threshold || $content_match || $excerpt_match || $sku_match) {
$product_obj = wc_get_product($product_post->ID);

if (!$product_obj) {
continue;
}

$image_id = $product_obj->get_image_id();
$image_url = $image_id ? wp_get_attachment_image_src($image_id, 'thumbnail')[0] : wc_placeholder_img_src('thumbnail');

// 获取产品价格
$regular_price = $product_obj->get_regular_price();
$sale_price = $product_obj->get_sale_price();
$on_sale = $product_obj->is_on_sale();

$results[] = array(
'id' => $product_obj->get_id(),
'title' => $product_obj->get_name(),
'url' => get_permalink($product_obj->get_id()),
'price_html' => $product_obj->get_price_html(),
'regular_price' => $regular_price,
'sale_price' => $sale_price,
'on_sale' => $on_sale,
'image' => $image_url,
'stock' => $product_obj->is_in_stock() ? __('有货', 'bdfg-product-search') : __('缺货', 'bdfg-product-search'),
'categories' => $this->get_product_categories($product_obj->get_id()),
'rating' => $product_obj->get_average_rating(),
'type' => $product_obj->get_type(),
'excerpt' => $this->get_product_excerpt($product_obj),
'distance' => $title_distance,
'fuzzy' => true
);
}
}

// 按编辑距离排序
usort($results, function($a, $b) {
return $a['distance'] - $b['distance'];
});

// 限制结果数量
return array_slice($results, 0, $limit);
}

/**
* 计算Levenshtein距离(编辑距离)
*
* @param string $str1 字符串1
* @param string $str2 字符串2
* @return int 编辑距离
*/
private function levenshtein_distance($str1, $str2) {
// 使用PHP内置的levenshtein函数
// 对于中文字符,先将字符串拆分为字符数组
if (preg_match('/[\x{4e00}-\x{9fa5}]/u', $str1) || preg_match('/[\x{4e00}-\x{9fa5}]/u', $str2)) {
// 中文字符处理
$s1 = preg_split('//u', $str1, -1, PREG_SPLIT_NO_EMPTY);
$s2 = preg_split('//u', $str2, -1, PREG_SPLIT_NO_EMPTY);

$n = count($s1);
$m = count($s2);

if ($n === 0) return $m;
if ($m === 0) return $n;

$distance = array();

for ($i = 0; $i <= $n; $i++) {
$distance[$i] = array();
$distance[$i][0] = $i;
}

for ($j = 0; $j <= $m; $j++) {
$distance[0][$j] = $j;
}

for ($i = 1; $i <= $n; $i++) {
for ($j = 1; $j <= $m; $j++) {
$cost = ($s1[$i - 1] === $s2[$j - 1]) ? 0 : 1;
$distance[$i][$j] = min(
$distance[$i - 1][$j] + 1, // 删除
$distance[$i][$j - 1] + 1, // 插入
$distance[$i - 1][$j - 1] + $cost // 替换
);
}
}

return $distance[$n][$m];
} else {
// 非中文使用PHP内置函数
return levenshtein($str1, $str2);
}
}

/**
* 获取产品分类
*
* @param int $product_id 产品ID
* @return string 分类名称,逗号分隔
*/
private function get_product_categories($product_id) {
$terms = get_the_terms($product_id, 'product_cat');

if (empty($terms) || is_wp_error($terms)) {
return '';
}

$categories = array();
foreach ($terms as $term) {
$categories[] = $term->name;
}

return implode(', ', $categories);
}

/**
* 获取产品摘要
*
* @param WC_Product $product 产品对象
* @return string 摘要文本
*/
private function get_product_excerpt($product) {
$excerpt = $product->get_short_description();

if (empty($excerpt)) {
$excerpt = $product->get_description();
$excerpt = wp_trim_words($excerpt, 20);
}

return $excerpt;
}

/**
* 记录搜索访问
*
* @param string $search_term 搜索词
*/
private function log_search($search_term) {
// 记录用户搜索词,用于后续建议功能
$existing_searches = get_option('bdfg_recent_searches', array());

// 将当前搜索添加到开头
array_unshift($existing_searches, array(
'term' => $search_term,
'time' => time()
));

// 保留最近的100个搜索
$existing_searches = array_slice($existing_searches, 0, 100);

update_option('bdfg_recent_searches', $existing_searches);
}

/**
* 记录搜索查询
*
* @param string $search_term 搜索词
* @param int $results_count 结果数量
*/
private function log_search_query($search_term, $results_count) {
global $wpdb;
$table_name = $wpdb->prefix . 'bdfg_search_logs';

$data = array(
'search_term' => $search_term,
'user_id' => get_current_user_id(),
'results_count' => $results_count,
'ip_address' => $this->get_client_ip(),
'user_agent' => isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ''
);

$wpdb->insert($table_name, $data);

// 如果是零结果搜索,更新建议表
if ($results_count === 0) {
$suggestions_table = $wpdb->prefix . 'bdfg_search_suggestions';

// 检查是否已有此搜索词的建议
$existing = $wpdb->get_var($wpdb->prepare(
"SELECT COUNT(*) FROM $suggestions_table WHERE search_term = %s",
$search_term
));

if (!$existing) {
// 添加到待处理建议列表
$wpdb->insert($suggestions_table, array(
'search_term' => $search_term,
'suggestion' => '',
'frequency' => 1,
'last_updated' => current_time('mysql')
));
} else {
// 更新频率
$wpdb->query($wpdb->prepare(
"UPDATE $suggestions_table SET frequency = frequency + 1, last_updated = %s WHERE search_term = %s",
current_time('mysql'),
$search_term
));
}
}
}

/**
* 获取客户端IP地址
*
* @return string IP地址
*/
private function get_client_ip() {
$ip = '';

// 检查各种可能的IP源
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
// 可能包含多个代理IP,取第一个
$ip_list = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$ip = trim($ip_list[0]);
} elseif (!empty($_SERVER['REMOTE_ADDR'])) {
$ip = $_SERVER['REMOTE_ADDR'];
}

// 确保IP格式有效
$ip = filter_var($ip, FILTER_VALIDATE_IP) ? $ip : '0.0.0.0';

return $ip;
}

/**
* 修改搜索查询以支持模糊搜索
*
* @param string $search 原搜索条件SQL
* @param WP_Query $wp_query 查询对象
* @return string 修改后的搜索条件SQL
*/
public function fuzzy_search_filter($search, $wp_query) {
global $wpdb;

// 仅修改前端产品搜索查询
if (!$wp_query->is_search() || !$wp_query->is_main_query() || is_admin()) {
return $search;
}

// 确保是产品搜索
$post_types = $wp_query->get('post_type');
if (empty($post_types) || (is_array($post_types) && !in_array('product', $post_types)) || $post_types !== 'product') {
return $search;
}

$search_term = $wp_query->get('s');

if (empty($search_term)) {
return $search;
}

// 清除现有的搜索条件
$search = '';

// 构建模糊搜索SQL
$like = '%' . $wpdb->esc_like($search_term) . '%';

// 搜索标题、内容、摘要、SKU和产品属性
$search = $wpdb->prepare(
" AND (
{$wpdb->posts}.post_title LIKE %s
OR {$wpdb->posts}.post_content LIKE %s
OR {$wpdb->posts}.post_excerpt LIKE %s
OR EXISTS (
SELECT * FROM {$wpdb->postmeta}
WHERE {$wpdb->postmeta}.post_id = {$wpdb->posts}.ID
AND (
({$wpdb->postmeta}.meta_key = '_sku' AND {$wpdb->postmeta}.meta_value LIKE %s)
OR ({$wpdb->postmeta}.meta_key LIKE 'attribute_%%' AND {$wpdb->postmeta}.meta_value LIKE %s)
OR ({$wpdb->postmeta}.meta_key = '_variation_description' AND {$wpdb->postmeta}.meta_value LIKE %s)
)
)
OR EXISTS (
SELECT * FROM {$wpdb->term_relationships}
JOIN {$wpdb->term_taxonomy} ON {$wpdb->term_relationships}.term_taxonomy_id = {$wpdb->term_taxonomy}.term_taxonomy_id
JOIN {$wpdb->terms} ON {$wpdb->term_taxonomy}.term_id = {$wpdb->terms}.term_id
WHERE {$wpdb->term_relationships}.object_id = {$wpdb->posts}.ID
AND {$wpdb->terms}.name LIKE %s
)
)",
$like, $like, $like, $like, $like, $like, $like
);

return $search;
}

/**
* 添加产品过滤器
*/
public function add_product_filters() {
// 仅在产品存档页面和搜索结果页显示
if (!is_shop() && !is_product_category() && !is_product_tag() && !is_search()) {
return;
}

// 获取分类列表
$categories = get_terms(array(
'taxonomy' => 'product_cat',
'hide_empty' => true,
));

// 获取价格范围
$min_max_price = $this->get_min_max_product_price();

// 获取评分选项
$rating_options = array(
5 => __('五星 (★★★★★)', 'bdfg-product-search'),
4 => __('四星及以上 (★★★★☆+)', 'bdfg-product-search'),
3 => __('三星及以上 (★★★☆☆+)', 'bdfg-product-search'),
2 => __('两星及以上 (★★☆☆☆+)', 'bdfg-product-search'),
1 => __('一星及以上 (★☆☆☆☆+)', 'bdfg-product-search'),
);

// 获取选中的过滤条件
$selected_category = isset($_GET['product_cat']) ? sanitize_text_field($_GET['product_cat']) : '';
$min_price = isset($_GET['min_price']) ? floatval($_GET['min_price']) : $min_max_price['min'];
$max_price = isset($_GET['max_price']) ? floatval($_GET['max_price']) : $min_max_price['max'];
$rating_filter = isset($_GET['rating_filter']) ? intval($_GET['rating_filter']) : 0;
$stock_status = isset($_GET['stock_status']) ? sanitize_text_field($_GET['stock_status']) : '';
$on_sale = isset($_GET['on_sale']) ? sanitize_text_field($_GET['on_sale']) : '';

// 获取当前页面URL
$current_url = $this->get_current_page_url();

?>
<div class="bdfg-product-filters">
<h3><?php _e('产品筛选', 'bdfg-product-search'); ?> <span class="bdfg-toggle-filters">+</span></h3>

<form method="get" action="<?php echo esc_url($current_url); ?>" class="bdfg-filters-form">
<?php
// 保留所有现有的URL参数,除了我们将在表单中设置的
$excluded_params = array('min_price', 'max_price', 'product_cat', 'rating_filter', 'stock_status', 'on_sale', 'paged');

foreach ($_GET as $key => $value) {
if (!in_array($key, $excluded_params) && $key !== 'bdfg_filter_submit') {
echo '<input type="hidden" name="' . esc_attr($key) . '" value="' . esc_attr($value) . '">';
}
}
?>

<div class="bdfg-filters-container">
<?php if (!empty($categories) && !is_product_category()): ?>
<div class="bdfg-filter-group">
<label for="product_cat"><?php _e('产品分类', 'bdfg-product-search'); ?></label>
<select name="product_cat" id="product_cat" class="bdfg-select">
<option value=""><?php _e('所有分类', 'bdfg-product-search'); ?></option>
<?php foreach ($categories as $category): ?>
<option value="<?php echo esc_attr($category->slug); ?>" <?php selected($selected_category, $category->slug); ?>>
<?php echo esc_html($category->name); ?> (<?php echo esc_html($category->count); ?>)
</option>
<?php endforeach; ?>
</select>
</div>
<?php endif; ?>

<div class="bdfg-filter-group">
<label for="price-range"><?php _e('价格区间', 'bdfg-product-search'); ?></label>
<div class="bdfg-price-slider-container">
<div class="bdfg-price-slider-values">
<span class="bdfg-price-label"><?php echo get_woocommerce_currency_symbol(); ?></span>
<input type="number" name="min_price" id="min_price" value="<?php echo esc_attr($min_price); ?>" min="<?php echo esc_attr($min_max_price['min']); ?>" max="<?php echo esc_attr($min_max_price['max']); ?>" step="1" class="bdfg-price-input">
<span class="bdfg-price-separator">-</span>
<span class="bdfg-price-label"><?php echo get_woocommerce_currency_symbol(); ?></span>
<input type="number" name="max_price" id="max_price" value="<?php echo esc_attr($max_price); ?>" min="<?php echo esc_attr($min_max_price['min']); ?>" max="<?php echo esc_attr($min_max_price['max']); ?>" step="1" class="bdfg-price-input">
</div>
<div class="bdfg-price-slider" data-min="<?php echo esc_attr($min_max_price['min']); ?>" data-max="<?php echo esc_attr($min_max_price['max']); ?>" data-current-min="<?php echo esc_attr($min_price); ?>" data-current-max="<?php echo esc_attr($max_price); ?>"></div>
</div>
</div>

<div class="bdfg-filter-group">
<label for="rating_filter"><?php _e('商品评分', 'bdfg-product-search'); ?></label>
<select name="rating_filter" id="rating_filter" class="bdfg-select">
<option value="0"><?php _e('所有评分', 'bdfg-product-search'); ?></option>
<?php foreach ($rating_options as $rating => $label): ?>
<option value="<?php echo esc_attr($rating); ?>" <?php selected($rating_filter, $rating); ?>>
<?php echo esc_html($label); ?>
</option>
<?php endforeach; ?>
</select>
</div>

<div class="bdfg-filter-group">
<label for="stock_status"><?php _e('库存状态', 'bdfg-product-search'); ?></label>
<select name="stock_status" id="stock_status" class="bdfg-select">
<option value=""><?php _e('所有状态', 'bdfg-product-search'); ?></option>
<option value="instock" <?php selected($stock_status, 'instock'); ?>><?php _e('有库存', 'bdfg-product-search'); ?></option>
<option value="outofstock" <?php selected($stock_status, 'outofstock'); ?>><?php _e('缺货', 'bdfg-product-search'); ?></option>
</select>
</div>

<div class="bdfg-filter-group bdfg-filter-checkbox">
<label for="on_sale">
<input type="checkbox" name="on_sale" id="on_sale" value="yes" <?php checked($on_sale, 'yes'); ?>>
<?php _e('仅显示促销商品', 'bdfg-product-search'); ?>
</label>
</div>
</div>

<div class="bdfg-filter-actions">
<button type="submit" name="bdfg_filter_submit" value="1" class="bdfg-filter-button bdfg-apply-button"><?php _e('应用筛选', 'bdfg-product-search'); ?></button>
<a href="<?php echo esc_url(remove_query_arg(array('min_price', 'max_price', 'rating_filter', 'stock_status', 'product_cat', 'on_sale', 'paged'))); ?>" class="bdfg-filter-button bdfg-reset-button"><?php _e('重置', 'bdfg-product-search'); ?></a>
</div>
</form>
</div>
<?php
}

/**
* 获取当前页面URL
*
* @return string 当前页面URL
*/
private function get_current_page_url() {
global $wp;

// 获取当前URL(不含查询参数)
$current_url = home_url($wp->request);

return $current_url;
}

/**
* 获取最低和最高产品价格
*
* @return array 包含min和max的价格范围数组
*/
private function get_min_max_product_price() {
global $wpdb;

$result = $wpdb->get_row("
SELECT MIN(meta_value+0) as min_price, MAX(meta_value+0) as max_price
FROM {$wpdb->postmeta}
WHERE meta_key = '_price'
AND meta_value > 0
");

$min = $result ? floor($result->min_price) : 0;
$max = $result ? ceil($result->max_price) : 1000;

// 确保最小和最大价格有意义
if ($min <= 0) $min = 0;
if ($max <= $min) $max = $min + 1000;

return array(
'min' => $min,
'max' => $max,
);
}

/**
* 应用产品过滤器
*
* @param WP_Query $query WordPress查询对象
*/
public function filter_products_query($query) {
// 仅修改前端产品查询
if (is_admin() || !$query->is_main_query() || (!is_shop() && !is_product_category() && !is_product_tag() && !is_search())) {
return;
}

// 产品分类过滤
if (isset($_GET['product_cat']) && !empty($_GET['product_cat'])) {
$product_cat = sanitize_text_field($_GET['product_cat']);
$query->set('tax_query', array(
array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => $product_cat,
'operator' => 'IN'
)
));
}

// 元查询数组
$meta_query = array();

// 价格过滤
if (isset($_GET['min_price']) && isset($_GET['max_price'])) {
$min_price = floatval($_GET['min_price']);
$max_price = floatval($_GET['max_price']);

$meta_query[] = array(
'key' => '_price',
'value' => array($min_price, $max_price),
'compare' => 'BETWEEN',
'type' => 'NUMERIC',
);
}

// 评分过滤
if (isset($_GET['rating_filter']) && intval($_GET['rating_filter']) > 0) {
$rating = intval($_GET['rating_filter']);

$meta_query[] = array(
'key' => '_wc_average_rating',
'value' => $rating,
'compare' => '>=',
'type' => 'NUMERIC',
);
}

// 库存状态过滤
if (isset($_GET['stock_status']) && !empty($_GET['stock_status'])) {
$stock_status = sanitize_text_field($_GET['stock_status']);

$meta_query[] = array(
'key' => '_stock_status',
'value' => $stock_status,
'compare' => '=',
);
}

// 促销商品过滤
if (isset($_GET['on_sale']) && $_GET['on_sale'] === 'yes') {
$product_ids_on_sale = wc_get_product_ids_on_sale();
$query->set('post__in', $product_ids_on_sale);
}

// 如果有元查询条件,设置查询
if (!empty($meta_query)) {
$existing_meta_query = $query->get('meta_query');
if (!empty($existing_meta_query) && is_array($existing_meta_query)) {
$meta_query = array_merge($existing_meta_query, $meta_query);
}

$query->set('meta_query', $meta_query);
}
}

/**
* 注册BDFG产品搜索小部件
*/
public function register_widgets() {
require_once $this->plugin_path . 'includes/class-bdfg-search-widget.php';
register_widget('BDFG_Search_Widget');
}
}

includes/class-bdfg-analytics.php

相关文章: WooCommerce 预定功能插件

<?php
/**
* BDFG 产品搜索增强工具分析类
*
* @package BDFG_Product_Search
* @since 1.0.0
*/

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

class BDFG_Analytics {

/**
* 插件目录路径
*
* @var string
*/
private $plugin_path;

/**
* 插件URL
*
* @var string
*/
private $plugin_url;

/**
* 插件版本
*
* @var string
*/
private $version;

/**
* 选项名称
*
* @var string
*/
private $option_name;

/**
* 插件选项
*
* @var array
*/
private $options;

/**
* 构造函数
*
* @param string $plugin_path 插件目录路径
* @param string $plugin_url 插件URL
* @param string $version 插件版本
* @param string $option_name 选项名称
* @param array $options 插件选项
*/
public function __construct($plugin_path, $plugin_url, $version, $option_name, $options) {
$this->plugin_path = $plugin_path;
$this->plugin_url = $plugin_url;
$this->version = $version;
$this->option_name = $option_name;
$this->options = $options;

// 初始化分析功能
$this->init();
}

/**
* 初始化分析功能
*/
private function init() {
// 注册定时任务钩子
add_action('bdfg_daily_maintenance', array($this, 'daily_maintenance'));

// 注册AJAX处理函数
add_action('wp_ajax_bdfg_export_analytics', array($this, 'export_analytics'));

// 添加仪表盘小部件
add_action('wp_dashboard_setup', array($this, 'add_dashboard_widget'));
}

/**
* 每日维护任务
*/
public function daily_maintenance() {
// 清理过期的缓存
$this->clear_expired_cache();

// 清理旧的搜索日志(90天前)
$this->clean_old_search_logs();

// 生成搜索统计报告
$this->generate_search_report();
}

/**
* 清理过期的缓存
*/
private function clear_expired_cache() {
global $wpdb;

// 删除所有BDFG相关的瞬时缓存
$wpdb->query(
"DELETE FROM {$wpdb->options}
WHERE option_name LIKE '_transient_bdfg_%'
OR option_name LIKE '_transient_timeout_bdfg_%'"
);
}

/**
* 清理旧的搜索日志
*/
private function clean_old_search_logs() {
global $wpdb;
$table_name = $wpdb->prefix . 'bdfg_search_logs';

// 删除90天前的日志
$wpdb->query(
$wpdb->prepare(
"DELETE FROM $table_name WHERE search_date < %s",
date('Y-m-d H:i:s', strtotime('-90 days'))
)
);
}

/**
* 生成搜索统计报告
*/
private function generate_search_report() {
$data = $this->get_analytics_data();

// 保存每日统计数据
$daily_stats = array(
'date' => date('Y-m-d'),
'total_searches' => $data['total_searches'],
'unique_terms' => $data['unique_terms'],
'success_rate' => $data['success_rate'],
'avg_results' => $data['avg_results'],
'popular_searches' => array_slice($data['popular_searches'], 0, 5),
'zero_results' => array_slice($data['zero_results'], 0, 5)
);

$existing_reports = get_option('bdfg_search_reports', array());
$existing_reports[date('Y-m-d')] = $daily_stats;

// 只保留最近30天的报告
if (count($existing_reports) > 30) {
$existing_reports = array_slice($existing_reports, -30, 30, true);
}

update_option('bdfg_search_reports', $existing_reports);
}

/**
* 获取分析数据
*
* @param int $days 要分析的天数
* @return array 分析数据
*/
public function get_analytics_data($days = 30) {
global $wpdb;
$table_name = $wpdb->prefix . 'bdfg_search_logs';

// 如果请求了不同的日期范围,使用指定的天数
if (isset($_GET['date_range']) && in_array($_GET['date_range'], array('7', '30', '90'))) {
$days = intval($_GET['date_range']);
}

// 确定日期范围
$date_from = date('Y-m-d H:i:s', strtotime("-$days days"));

// 获取总搜索次数
$total_searches = $wpdb->get_var(
$wpdb->prepare(
"SELECT COUNT(*) FROM $table_name WHERE search_date >= %s",
$date_from
)
);

// 获取唯一搜索词数量
$unique_terms = $wpdb->get_var(
$wpdb->prepare(
"SELECT COUNT(DISTINCT search_term) FROM $table_name WHERE search_date >= %s",
$date_from
)
);

// 获取有结果的搜索比例
$success_count = $wpdb->get_var(
$wpdb->prepare(
"SELECT COUNT(*) FROM $table_name WHERE search_date >= %s AND results_count > 0",
$date_from
)
);

$success_rate = $total_searches > 0 ? round(($success_count / $total_searches) * 100) : 0;

// 获取平均结果数
$avg_results = $wpdb->get_var(
$wpdb->prepare(
"SELECT AVG(results_count) FROM $table_name WHERE search_date >= %s",
$date_from
)
);

$avg_results = round($avg_results, 1);

// 获取热门搜索词
$popular_searches = $wpdb->get_results(
$wpdb->prepare(
"SELECT search_term, COUNT(*) as count, AVG(results_count) as avg_results
FROM $table_name
WHERE search_date >= %s
GROUP BY search_term
ORDER BY count DESC
LIMIT 10",
$date_from
)
);

// 获取零结果搜索词
$zero_results = $wpdb->get_results(
$wpdb->prepare(
"SELECT search_term, COUNT(*) as count, MAX(search_date) as last_search
FROM $table_name
WHERE results_count = 0
AND search_date >= %s
GROUP BY search_term
ORDER BY count DESC, last_search DESC
LIMIT 10",
$date_from
)
);

// 获取搜索趋势数据
$trends = $wpdb->get_results(
$wpdb->prepare(
"SELECT DATE(search_date) as date, COUNT(*) as count
FROM $table_name
WHERE search_date >= %s
GROUP BY DATE(search_date)
ORDER BY date ASC",
$date_from
)
);

// 计算搜索量变化率
$previous_period = $wpdb->get_var(
$wpdb->prepare(
"SELECT COUNT(*) FROM $table_name
WHERE search_date >= %s AND search_date < %s",
date('Y-m-d H:i:s', strtotime("-" . ($days * 2) . " days")),
$date_from
)
);

$search_change = 0;
if ($previous_period > 0) {
$search_change = round((($total_searches - $previous_period) / $previous_period) * 100);
}

return array(
'total_searches' => $total_searches,
'unique_terms' => $unique_terms,
'success_rate' => $success_rate,
'avg_results' => $avg_results,
'popular_searches' => $popular_searches,
'zero_results' => $zero_results,
'trends' => $trends,
'search_change' => $search_change,
'days' => $days
);
}

/**
* 导出分析数据
*/
public function export_analytics() {
// 检查权限
if (!current_user_can('manage_options')) {
wp_die(__('权限不足', 'bdfg-product-search'));
}

// 验证nonce
if (!isset($_GET['nonce']) || !wp_verify_nonce($_GET['nonce'], 'bdfg_export_analytics')) {
wp_die(__('安全检查失败', 'bdfg-product-search'));
}

global $wpdb;
$table_name = $wpdb->prefix . 'bdfg_search_logs';

// 获取导出天数
$days = isset($_GET['days']) ? intval($_GET['days']) : 30;
$date_from = date('Y-m-d H:i:s', strtotime("-$days days"));

// 获取要导出的数据
$data = $wpdb->get_results(
$wpdb->prepare(
"SELECT search_term, results_count, search_date, user_id, ip_address
FROM $table_name
WHERE search_date >= %s
ORDER BY search_date DESC",
$date_from
),
ARRAY_A
);

// 设置CSV文件头
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=bdfg-search-analytics-' . date('Y-m-d') . '.csv');

// 创建文件句柄
$output = fopen('php://output', 'w');

// 添加UTF-8 BOM
fputs($output, "\xEF\xBB\xBF");

// 添加CSV表头
fputcsv($output, array(
'搜索词',
'结果数量',
'搜索时间',
'用户ID',
'IP地址'
));

// 添加数据行
foreach ($data as $row) {
fputcsv($output, $row);
}

fclose($output);
exit;
}

/**
* 添加仪表盘小部件
*/
public function add_dashboard_widget() {
if (current_user_can('manage_options')) {
wp_add_dashboard_widget(
'bdfg_search_analytics_widget',
__('BDFG产品搜索统计', 'bdfg-product-search'),
array($this, 'render_dashboard_widget')
);
}
}

/**
* 渲染仪表盘小部件
*/
public function render_dashboard_widget() {
// 获取最近7天的数据
$data = $this->get_analytics_data(7);

?>
<div class="bdfg-dashboard-widget">
<div class="bdfg-dashboard-stats">
<div class="bdfg-stat-box">
<span class="bdfg-stat-value"><?php echo esc_html($data['total_searches']); ?></span>
<span class="bdfg-stat-label"><?php _e('搜索次数', 'bdfg-product-search'); ?></span>
</div>
<div class="bdfg-stat-box">
<span class="bdfg-stat-value"><?php echo esc_html($data['success_rate']); ?>%</span>
<span class="bdfg-stat-label"><?php _e('有结果率', 'bdfg-product-search'); ?></span>
</div>
</div>

<?php if (!empty($data['popular_searches'])): ?>
<h4><?php _e('热门搜索词', 'bdfg-product-search'); ?></h4>
<ul class="bdfg-search-terms">
<?php foreach (array_slice($data['popular_searches'], 0, 5) as $term): ?>
<li>
<span class="bdfg-term"><?php echo esc_html($term->search_term); ?></span>
<span class="bdfg-count"><?php echo esc_html($term->count); ?></span>
</li>
<?php endforeach; ?>
</ul>
<?php endif; ?>

<p class="bdfg-widget-footer">
<a href="<?php echo esc_url(admin_url('admin.php?page=bdfg-search-analytics')); ?>"><?php _e('查看完整报告', 'bdfg-product-search'); ?> →</a>
</p>
</div>

<style>
.bdfg-dashboard-stats {
display: flex;
justify-content: space-between;
margin-bottom: 15px;
}
.bdfg-stat-box {
text-align: center;
padding: 10px;
background: #f9f9f9;
border-radius: 3px;
flex: 1;
margin: 0 5px;
}
.bdfg-stat-value {
display: block;
font-size: 24px;
font-weight: bold;
color: #176bef;
}
.bdfg-stat-label {
font-size: 12px;
color: #666;
}
.bdfg-search-terms {
margin: 0;
padding: 0;
list-style: none;
}
.bdfg-search-terms li {
display: flex;
justify-content: space-between;
padding: 5px 0;
border-bottom: 1px solid #f0f0f0;
}
.bdfg-count {
background: #f0f0f0;
border-radius: 10px;
padding: 2px 8px;
font-size: 11px;
}
.bdfg-widget-footer {
margin-top: 15px;
text-align: right;
}
</style>
<?php
}
}

includes/class-bdfg-search-widget.php

<?php
/**
* BDFG 产品搜索小部件类
*
* @package BDFG_Product_Search
* @since 1.0.0
*/

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

class BDFG_Search_Widget extends WP_Widget {

/**
* 注册小部件
*/
public function __construct() {
parent::__construct(
'bdfg_product_search_widget', // 小部件ID
__('BDFG 产品搜索', 'bdfg-product-search'), // 小部件名称
array(
'description' => __('添加BDFG高级产品搜索表单到侧边栏', 'bdfg-product-search'),
'classname' => 'widget_bdfg_product_search',
)
);
}

/**
* 前端显示小部件
*
* @param array $args 小部件参数
* @param array $instance 小部件实例
*/
public function widget($args, $instance) {
$title = !empty($instance['title']) ? $instance['title'] : __('产品搜索', 'bdfg-product-search');
$placeholder = !empty($instance['placeholder']) ? $instance['placeholder'] : __('搜索BDFG产品...', 'bdfg-product-search');
$button_text = !empty($instance['button_text']) ? $instance['button_text'] : __('搜索', 'bdfg-product-search');
$show_filters = !empty($instance['show_filters']) ? $instance['show_filters'] : 'no';

// 应用小部件过滤器
$title = apply_filters('widget_title', $title, $instance, $this->id_base);

echo $args['before_widget'];

if ($title) {
echo $args['before_title'] . $title . $args['after_title'];
}

echo do_shortcode('[bdfg_product_search placeholder="' . esc_attr($placeholder) . '" button_text="' . esc_attr($button_text) . '" show_filters="' . esc_attr($show_filters) . '"]');

echo $args['after_widget'];
}

/**
* 后端小部件表单
*
* @param array $instance 当前实例
*/
public function form($instance) {
$title = !empty($instance['title']) ? $instance['title'] : __('产品搜索', 'bdfg-product-search');
$placeholder = !empty($instance['placeholder']) ? $instance['placeholder'] : __('搜索BDFG产品...', 'bdfg-product-search');
$button_text = !empty($instance['button_text']) ? $instance['button_text'] : __('搜索', 'bdfg-product-search');
$show_filters = !empty($instance['show_filters']) ? $instance['show_filters'] : 'no';
?>
<p>
<label for="<?php echo esc_attr($this->get_field_id('title')); ?>"><?php _e('标题:', 'bdfg-product-search'); ?></label>
<input class="widefat" id="<?php echo esc_attr($this->get_field_id('title')); ?>" name="<?php echo esc_attr($this->get_field_name('title')); ?>" type="text" value="<?php echo esc_attr($title); ?>">
</p>
<p>
<label for="<?php echo esc_attr($this->get_field_id('placeholder')); ?>"><?php _e('占位文本:', 'bdfg-product-search'); ?></label>
<input class="widefat" id="<?php echo esc_attr($this->get_field_id('placeholder')); ?>" name="<?php echo esc_attr($this->get_field_name('placeholder')); ?>" type="text" value="<?php echo esc_attr($placeholder); ?>">
</p>
<p>
<label for="<?php echo esc_attr($this->get_field_id('button_text')); ?>"><?php _e('按钮文本:', 'bdfg-product-search'); ?></label>
<input class="widefat" id="<?php echo esc_attr($this->get_field_id('button_text')); ?>" name="<?php echo esc_attr($this->get_field_name('button_text')); ?>" type="text" value="<?php echo esc_attr($button_text); ?>">
</p>
<p>
<input type="checkbox" class="checkbox" id="<?php echo esc_attr($this->get_field_id('show_filters')); ?>" name="<?php echo esc_attr($this->get_field_name('show_filters')); ?>" value="yes" <?php checked($show_filters, 'yes'); ?>>
<label for="<?php echo esc_attr($this->get_field_id('show_filters')); ?>"><?php _e('显示产品过滤器', 'bdfg-product-search'); ?></label>
</p>
<?php
}

/**
* 更新小部件实例
*
* @param array $new_instance 新实例
* @param array $old_instance 旧实例
* @return array 更新后的实例
*/
public function update($new_instance, $old_instance) {
$instance = array();
$instance['title'] = (!empty($new_instance['title'])) ? sanitize_text_field($new_instance['title']) : '';
$instance['placeholder'] = (!empty($new_instance['placeholder'])) ? sanitize_text_field($new_instance['placeholder']) : '';
$instance['button_text'] = (!empty($new_instance['button_text'])) ? sanitize_text_field($new_instance['button_text']) : '';
$instance['show_filters'] = (!empty($new_instance['show_filters'])) ? 'yes' : 'no';

return $instance;
}
}

assets/js/bdfg-product-search.js

相关文章: woocommerce产品分析插件

/**
* BDFG 产品搜索增强工具前端JS
*
* @package BDFG_Product_Search
* @since 1.0.0
* @author BeiDuoFenGou <[email protected]>
* @last_modified 2025-03-06 14:01:02
*/

(function($) {
'use strict';

// 初始化BDFG产品搜索
function initBDFGProductSearch() {
// 获取所有搜索表单
$('.bdfg-search-field').each(function() {
var $input = $(this);
var $form = $input.closest('form');
var $results = $form.find('.bdfg-search-results');
var $submitBtn = $form.find('.bdfg-search-submit');
var xhr = null;
var lastSearch = '';
var typingTimer;

// 添加获取焦点事件
$input.on('focus', function() {
if ($input.val().length > 0) {
$results.show();
}
});

// 添加键盘输入事件
$input.on('keyup', function(e) {
var searchTerm = $input.val().trim();

// 清除之前的定时器
clearTimeout(typingTimer);

// 上下键导航结果
if (e.keyCode === 38 || e.keyCode === 40) {
navigateResults(e.keyCode === 38 ? 'up' : 'down');
return;
}

// 按下回车键
if (e.keyCode === 13) {
var $selected = $results.find('.bdfg-search-item.selected');
if ($selected.length) {
e.preventDefault();
window.location.href = $selected.attr('data-url');
}
return;
}

// ESC键隐藏结果
if (e.keyCode === 27) {
$results.hide();
return;
}

if (searchTerm.length < 2) {
$results.hide();
return;
}

// 设置定时器延迟搜索,减少请求次数
typingTimer = setTimeout(function() {
if (searchTerm === lastSearch) {
return;
}

lastSearch = searchTerm;

// 显示"正在搜索"提示
$results.html('<div class="bdfg-searching">' + bdfg_product_search.typing_text + '</div>').show();

// 如果有进行中的请求,中止它
if (xhr && xhr.readyState !== 4) {
xhr.abort();
}

// 发送AJAX请求
xhr = $.ajax({
url: bdfg_product_search.ajax_url,
type: 'GET',
data: {
term: searchTerm
},
beforeSend: function(xhr) {
xhr.setRequestHeader('X-WP-Nonce', bdfg_product_search.nonce);
},
success: function(response) {
// 渲染搜索结果
renderResults(response, searchTerm);
},
error: function(jqXHR, textStatus, errorThrown) {
if (textStatus !== 'abort') {
$results.html('<div class="bdfg-error">搜索出错,请重试。</div>');
}
}
});
}, 300); // 300ms延迟,避免频繁请求
});

// 点击文档其他区域关闭结果
$(document).on('click', function(e) {
if (!$form.is(e.target) && $form.has(e.target).length === 0) {
$results.hide();
}
});

// 防止点击结果区域时触发表单提交
$results.on('click', function(e) {
e.stopPropagation();
});

// 上下键导航结果
function navigateResults(direction) {
var $items = $results.find('.bdfg-search-item');
var $selected = $results.find('.bdfg-search-item.selected');
var index = $items.index($selected);

if (!$items.length) return;

// 移除现有选择
$items.removeClass('selected');

if (direction === 'down') {
// 向下导航
index = (index + 1) % $items.length;
} else {
// 向上导航
index = (index - 1 + $items.length) % $items.length;
}

// 设置新的选择项
$($items[index]).addClass('selected');

// 如果选中项不在视图中,滚动到可见区域
var $selectedItem = $($items[index]);
var itemTop = $selectedItem.position().top;
var itemHeight = $selectedItem.outerHeight();
var containerHeight = $results.height();
var scrollTop = $results.scrollTop();

if (itemTop < 0) {
$results.scrollTop(scrollTop + itemTop);
} else if (itemTop + itemHeight > containerHeight) {
$results.scrollTop(scrollTop + itemTop - containerHeight + itemHeight);
}
}

// 渲染搜索结果
function renderResults(results, searchTerm) {
if (!results.length) {
$results.html('<div class="bdfg-no-results">' + bdfg_product_search.no_results_text + '</div>');
return;
}

var html = '<ul class="bdfg-search-items">';

for (var i = 0; i < results.length; i++) {
var result = results[i];
var productClass = 'bdfg-search-item';
if (i === 0) productClass += ' selected';
if (result.on_sale) productClass += ' on-sale';

html += '<li class="' + productClass + '" data-url="' + result.url + '">';
html += '<a href="' + result.url + '">';

// 产品图片
html += '<div class="bdfg-item-image">';
html += '<img src="' + result.image + '" alt="' + result.title + '">';
if (result.on_sale) {
html += '<span class="bdfg-sale-badge">促销</span>';
}
html += '</div>';

// 产品信息
html += '<div class="bdfg-item-info">';
html += '<h4 class="bdfg-item-title">' + highlightTerm(result.title, searchTerm) + '</h4>';

if (result.excerpt) {
html += '<p class="bdfg-item-excerpt">' + truncateText(result.excerpt, 80) + '</p>';
}

html += '<div class="bdfg-item-meta">';

// 价格
html += '<span class="bdfg-item-price">' + result.price_html + '</span>';

// 评分
if (result.rating > 0) {
html += '<span class="bdfg-item-rating">';
html += getRatingStars(result.rating);
html += '</span>';
}

// 库存状态
html += '<span class="bdfg-item-stock ' + (result.stock === '有货' ? 'in-stock' : 'out-of-stock') + '">';
html += result.stock;
html += '</span>';

html += '</div>'; // .bdfg-item-meta

if (result.categories) {
html += '<div class="bdfg-item-categories">' + result.categories + '</div>';
}

// 如果是模糊匹配结果,添加提示
if (result.fuzzy) {
html += '<div class="bdfg-fuzzy-match">模糊匹配结果</div>';
}

html += '</div>'; // .bdfg-item-info
html += '</a>';
html += '</li>';
}

html += '</ul>';

// 添加查看全部结果链接
html += '<div class="bdfg-view-all">';
html += '<a href="' + bdfg_product_search.site_url + '?s=' + encodeURIComponent(searchTerm) + '&post_type=product">';
html += bdfg_product_search.view_all_text;
html += '</a>';
html += '</div>';

$results.html(html);

// 为结果项添加悬停效果
$results.find('.bdfg-search-item').hover(
function() {
$results.find('.bdfg-search-item').removeClass('selected');
$(this).addClass('selected');
},
function() {
// 保持选中状态
}
);
}

// 高亮搜索词
function highlightTerm(text, term) {
if (!term) return text;

// 转义正则表达式特殊字符
term = term.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');

// 创建正则表达式
var regex = new RegExp('(' + term + ')', 'gi');

// 替换匹配项
return text.replace(regex, '<span class="bdfg-highlight">$1</span>');
}

// 截断文本
function truncateText(text, length) {
if (text.length <= length) return text;
return text.substring(0, length) + '...';
}

// 获取星级评分HTML
function getRatingStars(rating) {
var html = '<div class="bdfg-stars">';
var fullStars = Math.floor(rating);
var halfStar = rating % 1 >= 0.5;
var emptyStars = 5 - fullStars - (halfStar ? 1 : 0);

// 填充星
for (var i = 0; i < fullStars; i++) {
html += '<span class="bdfg-star bdfg-star-full">★</span>';
}

// 半星
if (halfStar) {
html += '<span class="bdfg-star bdfg-star-half">★</span>';
}

// 空星
for (var j = 0; j < emptyStars; j++) {
html += '<span class="bdfg-star bdfg-star-empty">☆</span>';
}

html += '</div>';
return html;
}
});
}

// 页面加载完成后初始化搜索
$(document).ready(function() {
initBDFGProductSearch();
});

})(jQuery);

assets/js/bdfg-product-filters.js

/**
* BDFG 产品搜索过滤器JS
*
* @package BDFG_Product_Search
* @since 1.0.0
* @author BeiDuoFenGou <[email protected]>
* @last_modified 2025-03-06 14:01:02
*/

(function($) {
'use strict';

// 初始化价格滑块
function initPriceSlider() {
var $slider = $('.bdfg-price-slider');

if ($slider.length) {
$slider.each(function() {
var $this = $(this);
var $minInput = $('#min_price');
var $maxInput = $('#max_price');
var min = parseFloat($this.data('min'));
var max = parseFloat($this.data('max'));
var currentMin = parseFloat($this.data('current-min'));
var currentMax = parseFloat($this.data('current-max'));

$this.slider({
range: true,
min: min,
max: max,
values: [currentMin, currentMax],
slide: function(event, ui) {
$minInput.val(ui.values[0]);
$maxInput.val(ui.values[1]);
}
});

// 输入框变化时更新滑块
$minInput.on('change', function() {
var value = parseFloat($(this).val());
if (isNaN(value)) {
value = min;
}
if (value < min) {
value = min;
}
if (value > $maxInput.val()) {
value = $maxInput.val();
}
$this.slider('values', 0, value);
});

$maxInput.on('change', function() {
var value = parseFloat($(this).val());
if (isNaN(value)) {
value = max;
}
if (value > max) {
value = max;
}
if (value < $minInput.val()) {
value = $minInput.val();
}
$this.slider('values', 1, value);
});
});
}
}

// 初始化过滤器切换
function initFilterToggle() {
$('.bdfg-toggle-filters').on('click', function() {
var $this = $(this);
var $container = $this.closest('.bdfg-product-filters').find('.bdfg-filters-container');

$container.slideToggle(300);

if ($this.text() === '+') {
$this.text('-');
} else {
$this.text('+');
}
});
}

// 添加移动设备适配
function initMobileFilters() {
if (window.matchMedia('(max-width: 768px)').matches) {
$('.bdfg-product-filters h3').trigger('click');
}
}

// 页面加载完成后初始化
$(document).ready(function() {
initPriceSlider();
initFilterToggle();
initMobileFilters();
});

})(jQuery);

assets/js/admin-script.js

/**
* BDFG 产品搜索增强工具管理界面JS
*
* @package BDFG_Product_Search
* @since 1.0.0
* @author BeiDuoFenGou <[email protected]>
* @last_modified 2025-03-06 14:01:02
* @created_by BeiDuoFenGou 
*/

(function($) {
'use strict';

// 初始化管理界面交互
function initAdminUI() {
// 标签切换功能
$('.bdfg-admin-tabs .nav-tab').on('click', function(e) {
e.preventDefault();

var target = $(this).attr('href').replace('#', '');

// 更新活动标签
$('.bdfg-admin-tabs .nav-tab').removeClass('nav-tab-active');
$(this).addClass('nav-tab-active');

// 显示目标内容
$('.bdfg-tab-content').removeClass('active');
$('#' + target + '-content').addClass('active');

// 存储用户偏好
if (typeof(Storage) !== "undefined") {
localStorage.setItem('bdfg_active_tab', target);
}
});

// 恢复用户之前选择的标签
if (typeof(Storage) !== "undefined") {
var lastTab = localStorage.getItem('bdfg_active_tab');
if (lastTab) {
$('.bdfg-admin-tabs .nav-tab[href="#' + lastTab + '"]').trigger('click');
}
}

// 复制短代码功能
$('.bdfg-shortcode').on('click', function() {
var $this = $(this);
var shortcode = $this.text();
var tempTextarea = $('<textarea>');

$('body').append(tempTextarea);
tempTextarea.val(shortcode).select();
document.execCommand('copy');
tempTextarea.remove();

$this.addClass('copied');

setTimeout(function() {
$this.removeClass('copied');
}, 1000);

// 显示复制成功提示
var $notification = $('<div class="bdfg-copy-notification">短代码已复制到剪贴板</div>');
$('body').append($notification);

setTimeout(function() {
$notification.addClass('show');
}, 10);

setTimeout(function() {
$notification.removeClass('show');
setTimeout(function() {
$notification.remove();
}, 300);
}, 2000);
});
}

// 初始化数据导出功能
function initDataExport() {
$('#bdfg-export-analytics').on('click', function(e) {
e.preventDefault();
var days = $('#export-days').val();
var url = $(this).data('url') + '&days=' + days;
window.location.href = url;
});
}

// 初始化高级设置工具提示
function initTooltips() {
$('.bdfg-has-tooltip').hover(
function() {
var $this = $(this);
var tooltipText = $this.data('tooltip');

if (!tooltipText) return;

var $tooltip = $('<div class="bdfg-tooltip">' + tooltipText + '</div>');
$this.append($tooltip);

// 定位工具提示
var thisPos = $this.position();
var tooltipHeight = $tooltip.outerHeight();

$tooltip.css({
top: thisPos.top - tooltipHeight - 10,
left: thisPos.left
});

setTimeout(function() {
$tooltip.addClass('show');
}, 10);
},
function() {
$(this).find('.bdfg-tooltip').remove();
}
);
}

// 页面加载完成后初始化管理界面
$(document).ready(function() {
initAdminUI();
initDataExport();
initTooltips();
});

})(jQuery);

assets/css/bdfg-product-search.css

/**
* BDFG 产品搜索增强工具前端样式
*
* @package BDFG_Product_Search
* @since 1.0.0
* @author BeiDuoFenGou <[email protected]>
* @last_modified 2025-03-06 14:01:02
*/

/* 搜索表单容器 */
.bdfg-search-form-container {
position: relative;
margin: 0 0 25px;
width: 100%;
}

/* 搜索表单 */
.bdfg-search-form {
position: relative;
width: 100%;
}

/* 输入框包装 */
.bdfg-search-input-wrap {
display: flex;
position: relative;
width: 100%;
}

/* 搜索字段 */
.bdfg-search-field {
flex-grow: 1;
height: 45px;
padding: 10px 15px;
font-size: 16px;
line-height: 1.4;
border: 2px solid #e3e3e3;
border-right: none;
border-radius: 4px 0 0 4px;
background-color: #fff;
box-sizing: border-box;
transition: border-color 0.3s;
outline: none;
box-shadow: none;
}

.bdfg-search-field:focus {
border-color: #176bef;
}

/* 搜索按钮 */
.bdfg-search-submit {
height: 45px;
padding: 0 20px;
font-size: 14px;
font-weight: 600;
color: #fff;
background-color: #176bef;
border: 2px solid #176bef;
border-radius: 0 4px 4px 0;
cursor: pointer;
transition: all 0.3s;
outline: none;
box-shadow: none;
}

.bdfg-search-submit:hover,
.bdfg-search-submit:focus {
background-color: #0e5ad7;
border-color: #0e5ad7;
}

/* 搜索图标 */
.bdfg-search-icon {
display: inline-block;
width: 18px;
height: 18px;
margin-left: 5px;
vertical-align: -4px;
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="%23ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>');
background-repeat: no-repeat;
background-position: center;
}

/* 搜索结果容器 */
.bdfg-search-results {
display: none;
position: absolute;
top: 100%;
left: 0;
width: 100%;
max-height: 450px;
margin-top: 4px;
overflow-y: auto;
background-color: #fff;
border: 1px solid #e3e3e3;
border-radius: 4px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
z-index: 9999;
}

/* 搜索中状态 */
.bdfg-searching {
padding: 15px;
text-align: center;
color: #666;
font-style: italic;
}

/* 无结果状态 */
.bdfg-no-results {
padding: 15px;
text-align: center;
color: #666;
}

/* 搜索结果列表 */
.bdfg-search-items {
list-style: none;
margin: 0;
padding: 0;
}

/* 搜索结果项 */
.bdfg-search-item {
padding: 0;
margin: 0;
border-bottom: 1px solid #f0f0f0;
transition: background-color 0.2s;
}

.bdfg-search-item:last-child {
border-bottom: none;
}

.bdfg-search-item a {
display: flex;
padding: 10px;
text-decoration: none !important;
color: #333 !important;
box-shadow: none !important;
}

.bdfg-search-item:hover,
.bdfg-search-item.selected {
background-color: #f9f9f9;
}

/* 搜索结果项图片 */
.bdfg-item-image {
position: relative;
width: 60px;
min-width: 60px;
height: 60px;
margin-right: 12px;
overflow: hidden;
border-radius: 3px;
}

.bdfg-item-image img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}

/* 促销标签 */
.bdfg-sale-badge {
position: absolute;
top: 0;
right: 0;
padding: 2px 5px;
font-size: 10px;
font-weight: 600;
color: #fff;
background-color: #e03232;
border-radius: 0 0 0 3px;
}

/* 搜索结果项信息 */
.bdfg-item-info {
flex-grow: 1;
overflow: hidden;
}

.bdfg-item-title {
margin: 0 0 5px;
font-size: 14px;
font-weight: 600;
line-height: 1.3;
color: #333;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}

.bdfg-item-excerpt {
margin: 0 0 5px;
font-size: 12px;
line-height: 1.4;
color: #666;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}

/* 元数据 */
.bdfg-item-meta {
display: flex;
align-items: center;
flex-wrap: wrap;
font-size: 12px;
color: #666;
}

.bdfg-item-price {
margin-right: 10px;
font-weight: 600;
color: #176bef;
}

.bdfg-item-rating {
margin-right: 10px;
}

.bdfg-item-stock {
font-size: 11px;
padding: 2px 6px;
border-radius: 10px;
}

.bdfg-item-stock.in-stock {
background-color: #e8f5e9;
color: #2e7d32;
}

.bdfg-item-stock.out-of-stock {
background-color: #ffebee;
color: #c62828;
}

/* 分类信息 */
.bdfg-item-categories {
margin-top: 5px;
font-size: 11px;
color: #888;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}

/* 模糊匹配提示 */
.bdfg-fuzzy-match {
margin-top: 5px;
font-size: 10px;
font-style: italic;
color: #888;
}

/* 高亮匹配文本 */
.bdfg-highlight {
font-weight: 700;
background-color: #fff9c4;
padding: 0 2px;
}

/* 评分星星 */
.bdfg-stars {
display: inline-flex;
line-height: 1;
}

.bdfg-star {
font-size: 12px;
color: #ffc107;
}

.bdfg-star-empty {
color: #e0e0e0;
}

/* 查看全部结果链接 */
.bdfg-view-all {
padding: 10px;
text-align: center;
border-top: 1px solid #f0f0f0;
background-color: #f9f9f9;
}

.bdfg-view-all a {
font-size: 13px;
font-weight: 600;
color: #176bef;
text-decoration: none;
}

.bdfg-view-all a:hover {
text-decoration: underline;
}

/* 错误状态 */
.bdfg-error {
padding: 15px;
text-align: center;
color: #c62828;
}

/* 响应式调整 */
@media (max-width: 768px) {
.bdfg-search-field {
font-size: 14px;
height: 40px;
}

.bdfg-search-submit {
height: 40px;
padding: 0 15px;
font-size: 13px;
}

.bdfg-search-results {
max-height: 350px;
}

.bdfg-item-image {
width: 50px;
min-width: 50px;
height: 50px;
}
}

/* BDFG品牌样式 */
.bdfg-powered {
font-size: 11px;
text-align: right;
margin-top: 5px;
color: #999;
}

.bdfg-powered a {
color: #176bef;
text-decoration: none;
}

assets/css/bdfg-product-filters.css

/**
* BDFG 产品搜索过滤器样式
*
* @package BDFG_Product_Search
* @since 1.0.0
* @author BeiDuoFenGou <[email protected]>
* @last_modified 2025-03-06 14:01:02
*/

/* 产品过滤器容器 */
.bdfg-product-filters {
margin: 0 0 25px;
padding: 15px;
background-color: #f9f9f9;
border-radius: 4px;
border: 1px solid #eee;
}

/* 标题 */
.bdfg-product-filters h3 {
margin: 0 0 15px;
padding-bottom: 10px;
font-size: 16px;
border-bottom: 1px solid #e3e3e3;
position: relative;
cursor: pointer;
}

/* 切换按钮 */
.bdfg-toggle-filters {
position: absolute;
right: 0;
top: 0;
font-size: 20px;
font-weight: bold;
line-height: 1;
color: #666;
transition: transform 0.3s;
}

/* 过滤器表单容器 */
.bdfg-filters-container {
display: block;
}

/* 过滤器组 */
.bdfg-filter-group {
margin-bottom: 15px;
}

.bdfg-filter-group label {
display: block;
font-size: 14px;
font-weight: 600;
margin-bottom: 6px;
color: #444;
}

/* 下拉选择器 */
.bdfg-select {
width: 100%;
height: 38px;
padding: 5px 10px;
font-size: 14px;
border: 1px solid #ddd;
border-radius: 4px;
background-color: #fff;
box-shadow: none;
outline: none;
transition: border-color 0.2s;
}

.bdfg-select:focus {
border-color: #176bef;
}

/* 价格滑块容器 */
.bdfg-price-slider-container {
padding: 10px 0;
}

/* 价格值显示 */
.bdfg-price-slider-values {
display: flex;
align-items: center;
margin-bottom: 10px;
}

.bdfg-price-label {
font-weight: bold;
color: #333;
}

.bdfg-price-separator {
margin: 0 8px;
color: #666;
}

.bdfg-price-input {
width: 80px;
height: 32px;
padding: 5px;
font-size: 13px;
border: 1px solid #ddd;
border-radius: 3px;
text-align: center;
outline: none;
}

/* 价格滑块 */
.bdfg-price-slider {
margin: 10px 7px 5px;
height: 8px;
border-radius: 4px;
background-color: #e0e0e0;
border: none;
}

.bdfg-price-slider .ui-slider-range {
background-color: #176bef;
border-radius: 4px;
}

.bdfg-price-slider .ui-slider-handle {
width: 18px;
height: 18px;
background-color: #fff;
border: 2px solid #176bef;
border-radius: 50%;
top: -5px;
cursor: pointer;
outline: none;
}

.bdfg-price-slider .ui-slider-handle:focus,
.bdfg-price-slider .ui-slider-handle:active {
border-color: #0e5ad7;
background-color: #f9f9f9;
}

/* 复选框样式 */
.bdfg-filter-checkbox {
margin-top: 15px;
}

.bdfg-filter-checkbox label {
display: flex;
align-items: center;
cursor: pointer;
}

.bdfg-filter-checkbox input[type="checkbox"] {
margin-right: 8px;
}

/* 按钮组 */
.bdfg-filter-actions {
display: flex;
margin-top: 20px;
}

.bdfg-filter-button {
padding: 8px 15px;
font-size: 14px;
font-weight: 600;
border: none;
border-radius: 3px;
cursor: pointer;
text-decoration: none;
text-align: center;
transition: all 0.2s;
}

.bdfg-apply-button {
color: #fff;
background-color: #176bef;
margin-right: 10px;
}

.bdfg-apply-button:hover {
background-color: #0e5ad7;
}

.bdfg-reset-button {
color: #333;
background-color: #e0e0e0;
display: inline-block;
}

.bdfg-reset-button:hover {
background-color: #ccc;
}

/* 响应式调整 */
@media (max-width: 768px) {
.bdfg-filters-container {
display: none;
}

.bdfg-price-slider-values {
flex-wrap: wrap;
}

.bdfg-price-input {
width: 70px;
}

.bdfg-filter-button {
flex: 1;
padding: 10px 5px;
}
}

/* 在小页面中使用紧凑布局 */
@media (max-width: 480px) {
.bdfg-product-filters {
padding: 10px;
}

.bdfg-price-input {
width: 60px;
}
}

/* BDFG品牌样式 */
.bdfg-filters-footer {
margin-top: 15px;
text-align: right;
font-size: 11px;
color: #999;
}

.bdfg-filters-footer a {
color: #176bef;
text-decoration: none;
}

assets/css/admin-style.css

/**
* BDFG 产品搜索增强工具管理界面样式
*
* @package BDFG_Product_Search
* @since 1.0.0
* @author BeiDuoFenGou <[email protected]>
* @last_modified 2025-03-06 14:01:02
*/

/* 主容器 */
.bdfg-admin-wrap {
max-width: 1200px;
margin: 20px 0;
}

/* 头部 */
.bdfg-admin-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding-bottom: 15px;
border-bottom: 1px solid #e0e0e0;
}

.bdfg-logo {
display: flex;
align-items: center;
}

.bdfg-logo img {
width: 40px;
height: 40px;
margin-right: 10px;
}

.bdfg-logo h1 {
margin: 0;
font-size: 22px;
font-weight: 600;
color: #333;
}

.bdfg-version {
font-size: 13px;
color: #666;
background-color: #f0f0f0;
padding: 4px 8px;
border-radius: 10px;
}

/* 内容区域 */
.bdfg-admin-content {
background-color: #fff;
padding: 20px;
border: 1px solid #e0e0e0;
border-radius: 4px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
}

/* 标签导航 */
.bdfg-admin-tabs {
margin-bottom: 20px;
border-bottom: 1px solid #e0e0e0;
}

.nav-tab {
margin-bottom: -1px;
}

.bdfg-tab-content {
display: none;
padding: 15px 0;
}

.bdfg-tab-content.active {
display: block;
}

/* 表单样式 */
.form-table th {
padding: 20px 10px 20px 0;
width: 200px;
}

/* 开关样式 */
.bdfg-switch {
position: relative;
display: inline-block;
width: 48px;
height: 24px;
margin-right: 10px;
}

.bdfg-switch input {
opacity: 0;
width: 0;
height: 0;
}

.bdfg-slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
transition: .3s;
border-radius: 24px;
}

.bdfg-slider:before {
position: absolute;
content: "";
height: 18px;
width: 18px;
left: 3px;
bottom: 3px;
background-color: white;
transition: .3s;
border-radius: 50%;
}

input:checked + .bdfg-slider {
background-color: #176bef;
}

input:focus + .bdfg-slider {
box-shadow: 0 0 1px #176bef;
}

input:checked + .bdfg-slider:before {
transform: translateX(24px);
}

.bdfg-checkbox-label {
font-weight: 600;
vertical-align: middle;
}

/* 数字字段 */
.bdfg-number-field {
display: flex;
align-items: center;
}

.bdfg-number-field input {
width: 70px;
text-align: center;
margin-right: 10px;
}

/* 短代码 */
.bdfg-shortcode-box {
margin-bottom: 25px;
padding: 15px;
background-color: #f9f9f9;
border: 1px solid #e0e0e0;
border-radius: 4px;
}

.bdfg-shortcode-box h3 {
margin-top: 0;
margin-bottom: 10px;
font-size: 14px;
font-weight: 600;
}

.bdfg-shortcode {
display: inline-block;
padding: 8px 12px;
margin-bottom: 10px;
font-family: monospace;
font-size: 13px;
color: #176bef;
background-color: #fff;
border: 1px solid #e0e0e0;
border-radius: 3px;
cursor: pointer;
transition: all 0.2s;
}

.bdfg-shortcode:hover {
border-color: #176bef;
background-color: #f0f7ff;
}

.bdfg-shortcode.copied {
border-color: #4caf50;
background-color: #e8f5e9;
color: #2e7d32;
}

.bdfg-shortcode-attrs {
width: 100%;
margin-top: 15px;
border-collapse: collapse;
}

.bdfg-shortcode-attrs th,
.bdfg-shortcode-attrs td {
padding: 8px;
text-align: left;
border-bottom: 1px solid #e0e0e0;
}

.bdfg-shortcode-attrs th {
background-color: #f0f0f0;
font-weight: 600;
}

/* 复制提示 */
.bdfg-copy-notification {
position: fixed;
bottom: 20px;
right: 20px;
padding: 10px 15px;
background-color: #333;
color: #fff;
border-radius: 3px;
font-size: 14px;
z-index: 9999;
opacity: 0;
transform: translateY(20px);
transition: all 0.3s;
}

.bdfg-copy-notification.show {
opacity: 1;
transform: translateY(0);
}

/* 支持框 */
.bdfg-support-box {
margin-bottom: 20px;
padding: 15px;
background-color: #f9f9f9;
border-left: 4px solid #176bef;
border-radius: 3px;
}

.bdfg-support-box h3 {
margin-top: 0;
margin-bottom: 10px;
font-size: 15px;
color: #333;
}

.bdfg-support-box p {
margin: 0;
}

/* 分析面板样式 */
.bdfg-analytics-wrap {
max-width: 1200px;
}

.bdfg-date-filter {
display: flex;
justify-content: flex-end;
margin-bottom: 15px;
}

.bdfg-analytics-dashboard {
margin-top: 20px;
}

.bdfg-analytics-row {
display: flex;
flex-wrap: wrap;
margin: 0 -10px 20px;
}

.bdfg-analytics-col {
padding: 0 10px;
flex: 1;
min-width: 300px;
margin-bottom: 20px;
}

.bdfg-card {
padding: 15px;
background-color: #fff;
border-radius: 4px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
text-align: center;
margin: 0 5px 10px;
flex: 1;
min-width: 150px;
}

.bdfg-card-header {
font-size: 14px;
font-weight: normal;
color: #666;
margin-bottom: 5px;
}

.bdfg-card-value {
font-size: 24px;
font-weight: 600;
color: #333;
margin: 5px 0;
}

.bdfg-card-footer {
font-size: 12px;
color: #666;
}

.bdfg-card-footer .positive {
color: #4caf50;
}

.bdfg-card-footer .negative {
color: #f44336;
}

.bdfg-analytics-card {
background-color: #fff;
border-radius: 4px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
padding: 15px;
margin-bottom: 20px;
}

.bdfg-analytics-card h2 {
margin-top: 0;
margin-bottom: 15px;
font-size: 16px;
font-weight: 600;
color: #333;
border-bottom: 1px solid #e0e0e0;
padding-bottom: 10px;
}

.bdfg-chart-container {
height: 300px;
position: relative;
}

.bdfg-analytics-table {
width: 100%;
border-collapse: collapse;
}

.bdfg-analytics-table th,
.bdfg-analytics-table td {
padding: 8px 10px;
text-align: left;
border-bottom: 1px solid #e0e0e0;
}

.bdfg-analytics-table th {
background-color: #f5f5f5;
font-weight: 600;
}

.bdfg-analytics-table tr:hover td {
background-color: #f9f9f9;
}

.bdfg-no-data {
padding: 20px;
text-align: center;
color: #666;
font-style: italic;
}

/* 帮助页面样式 */
.bdfg-help-wrap {
display: flex;
flex-direction: column;
}

.bdfg-help-nav {
margin-bottom: 20px;
border-bottom: 1px solid #e0e0e0;
}

.bdfg-help-nav ul {
display: flex;
flex-wrap: wrap;
margin: 0;
padding: 0;
list-style: none;
}

.bdfg-help-nav li {
margin: 0;
padding: 0;
}

.bdfg-help-nav a {
display: block;
padding: 10px 15px;
font-size: 14px;
font-weight: 500;
text-decoration: none;
color: #333;
border-bottom: 2px solid transparent;
}

.bdfg-help-nav a:hover {
color: #176bef;
}

.bdfg-help-nav a.active {
color: #176bef;
border-bottom-color: #176bef;
}

.bdfg-help-content {
flex: 1;
}

.bdfg-help-section {
display: none;
padding: 10px 0;
}

.bdfg-help-section.active {
display: block;
}

.bdfg-help-box {
margin-bottom: 25px;
padding: 15px;
border: 1px solid #e0e0e0;
border-radius: 4px;
background-color: #f9f9f9;
}

.bdfg-help-box h3 {
margin-top: 0;
margin-bottom: 10px;
font-size: 16px;
color: #333;
}

.bdfg-help-box img {
max-width: 100%;
height: auto;
margin: 10px 0;
border: 1px solid #e0e0e0;
border-radius: 4px;
}

.bdfg-help-columns {
display: flex;
flex-wrap: wrap;
margin: 0 -10px;
}

.bdfg-help-column {
flex: 1;
padding: 0 10px;
min-width: 300px;
margin-bottom: 20px;
}

.bdfg-feature-box {
padding: 15px;
margin-bottom: 20px;
background-color: #fff;
border: 1px solid #e0e0e0;
border-radius: 4px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
}

.bdfg-feature-box h3 {
margin-top: 0;
color: #176bef;
}

.bdfg-faq-item {
margin-bottom: 15px;
border-bottom: 1px solid #e0e0e0;
}

.bdfg-faq-item h3 {
position: relative;
margin: 0;
padding: 12px 0;
font-size: 15px;
font-weight: 500;
color: #333;
cursor: pointer;
}

.bdfg-faq-item h3::after {
content: "+";
position: absolute;
right: 0;
top: 12px;
font-size: 18px;
font-weight: normal;
color: #666;
transition: transform 0.3s;
}

.bdfg-faq-item.active h3::after {
content: "-";
}

.bdfg-faq-answer {
display: none;
padding: 0 0 15px;
}

.bdfg-faq-item.active .bdfg-faq-answer {
display: block;
}

/* 页脚 */
.bdfg-admin-footer {
margin-top: 20px;
padding-top: 15px;
border-top: 1px solid #e0e0e0;
text-align: center;
color: #666;
}

.bdfg-admin-footer p {
margin: 0;
font-size: 13px;
}

.bdfg-admin-footer a {
color: #176bef;
text-decoration: none;
}

/* 工具提示 */
.bdfg-has-tooltip {
position: relative;
display: inline-block;
margin-left: 5px;
width: 16px;
height: 16px;
background-color: #f0f0f0;
border-radius: 50%;
color: #666;
font-size: 12px;
line-height: 16px;
text-align: center;
cursor: help;
}

.bdfg-tooltip {
position: absolute;
z-index: 100;
width: 200px;
padding: 8px 10px;
background-color: #333;
color: #fff;
font-size: 12px;
font-weight: normal;
line-height: 1.4;
border-radius: 3px;
opacity: 0;
transform: translateY(5px);
transition: all 0.2s;
pointer-events: none;
}

.bdfg-tooltip::after {
content: "";
position: absolute;
bottom: -5px;
left: 50%;
margin-left: -5px;
border-width: 5px 5px 0;
border-style: solid;
border-color: #333 transparent transparent;
}

.bdfg-tooltip.show {
opacity: 1;
transform: translateY(0);
}

/* 适配暗色主题 */
@media (prefers-color-scheme: dark) {
.admin-color-midnight .bdfg-admin-content,
.admin-color-modern .bdfg-admin-content,
.admin-color-ocean .bdfg-admin-content,
.admin-color-coffee .bdfg-admin-content,
.admin-color-ectoplasm .bdfg-admin-content,
.admin-color-blue .bdfg-admin-content,
.admin-color-sunrise .bdfg-admin-content {
background-color: #32373c;
border-color: #23282d;
}
}

/* 响应式调整 */
@media (max-width: 782px) {
.bdfg-admin-header {
flex-direction: column;
align-items: flex-start;
}

.bdfg-version {
margin-top: 10px;
}

.bdfg-analytics-col {
flex: 100%;
}

.bdfg-chart-container {
height: 250px;
}

.form-table th {
width: auto;
}
}

 

Leave a Comment