WooCommerce 折扣插件

是一款强大的 WooCommerce 折扣插件,它允许您为不同的用户角色设置不同的折扣规则,满足各种定价策略需求。

### 主要功能
* **基于用户角色的折扣**: 为不同用户角色设置不同折扣
* **多种折扣类型**: 支持百分比折扣和固定金额折扣
* **产品分类限制**: 可将折扣限制在特定产品分类
* **时间限制**: 设置折扣的开始和结束日期
* **首次购买限制**: 可设置折扣仅适用于用户的首次购买
* **最低订单金额**: 设置应用折扣所需的最低订单金额
* **附加条件**: 支持多种条件组合,如星期几、一天中的时间、客户订单数量和消费金额等
* **排除项设置**: 可排除特定产品、用户或已有特价产品
* **优化的用户界面**: 直观的后台设置界面,拖拽排序规则
* **折扣测试工具**: 方便测试和调试折扣规则
* **导入/导出**: 支持折扣规则的导入和导出
* **缓存支持**: 与页面缓存插件兼容
* **多货币支持**: 与主流多货币插件兼容

相关文章: WooCommerce 页脚增强器

<?php
/**
* Plugin Name: BDFG Role-Based Discounts for WooCommerce
* Plugin URI:https://beiduofengou.net/2025/01/28/bdfg-role-discounts/
* Description: 全功能用户角色折扣系统,支持按角色设置百分比折扣、固定金额折扣、最低订单金额、产品类别折扣、限时折扣等。
* Version: 2.6.0
* Author: Bei Duo Feng Ou
* Author URI: https://beiduofengou.net
* Text Domain: bdfg-role-discounts
* Domain Path: /languages
* Requires at least: 5.6
* Requires PHP: 7.3
* WC requires at least: 5.0
* WC tested up to: 7.8
* License: GPL v2 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
*/

// 如果直接访问此文件,则中止执行
if (!defined('ABSPATH')) {
exit;
}

if (!class_exists('BDFG_Role_Discounts')) {

/**
* BDFG角色折扣插件主类
*
* @since 1.0.0
*/
class BDFG_Role_Discounts {

// 单例模式实例
private static $instance = null;

// 插件版本
private $version = '2.6.0';

// 插件设置
private $settings;

// 插件选项名称
private $option_name = 'bdfg_role_discounts_settings';

// 用户首次购买记录选项名称
private $first_purchase_option = 'bdfg_user_first_purchases';

// 插件路径和URL
private $plugin_path;
private $plugin_url;

/**
* 主要构造函数
*/
private function __construct() {
// 设置插件路径和URL
$this->plugin_path = plugin_dir_path(__FILE__);
$this->plugin_url = plugin_dir_url(__FILE__);

// 加载文本域用于翻译
add_action('plugins_loaded', array($this, 'load_plugin_textdomain'));

// 检查 WooCommerce 是否激活
add_action('admin_init', array($this, 'check_woocommerce_active'));

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

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

// 加载设置
$this->settings = get_option($this->option_name, array());

// 应用折扣
add_action('woocommerce_before_calculate_totals', array($this, 'apply_discounts'), 99);

// 处理订单完成后的任务
add_action('woocommerce_order_status_completed', array($this, 'process_completed_order'));

// 显示折扣信息
add_action('woocommerce_before_add_to_cart_form', array($this, 'display_discount_info'));

// 显示原价
add_filter('woocommerce_get_price_html', array($this, 'show_original_price'), 99, 2);

// 加载CSS和JS
add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'));
add_action('wp_enqueue_scripts', array($this, 'enqueue_frontend_scripts'));

// Ajax 处理
add_action('wp_ajax_bdfg_test_discount_rule', array($this, 'ajax_test_discount_rule'));
add_action('wp_ajax_bdfg_export_settings', array($this, 'ajax_export_settings'));
add_action('wp_ajax_bdfg_import_settings', array($this, 'ajax_import_settings'));
add_action('wp_ajax_bdfg_reset_first_purchase', array($this, 'ajax_reset_first_purchase'));

// 产品选择器的Ajax
add_action('wp_ajax_bdfg_search_products', array($this, 'ajax_search_products'));
add_action('wp_ajax_bdfg_search_users', array($this, 'ajax_search_users'));
}

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

/**
* 获取插件路径
*
* @since 2.0.0
* @return string
*/
public function get_plugin_path() {
return $this->plugin_path;
}

/**
* 获取插件URL
*
* @since 2.0.0
* @return string
*/
public function get_plugin_url() {
return $this->plugin_url;
}

/**
* 加载插件文本域
*
* @since 1.0.0
*/
public function load_plugin_textdomain() {
load_plugin_textdomain('bdfg-role-discounts', false, dirname(plugin_basename(__FILE__)) . '/languages');
}

/**
* 检查 WooCommerce 是否激活
*
* @since 1.0.0
*/
public function check_woocommerce_active() {
if (!class_exists('WooCommerce')) {
add_action('admin_notices', array($this, 'woocommerce_missing_notice'));
deactivate_plugins(plugin_basename(__FILE__));
if (isset($_GET['activate'])) {
unset($_GET['activate']);
}
}
}

/**
* WooCommerce 缺失提示
*
* @since 1.0.0
*/
public function woocommerce_missing_notice() {
?>
<div class="error">
<p><?php _e('BDFG Role-Based Discounts 需要 WooCommerce 插件。请安装并激活 WooCommerce 后再试。', 'bdfg-role-discounts'); ?></p>
</div>
<?php
}

/**
* 添加管理菜单
*
* @since 1.0.0
*/
public function add_admin_menu() {
add_submenu_page(
'woocommerce',
__('BDFG Role Discounts', 'bdfg-role-discounts'),
__('Role Discounts', 'bdfg-role-discounts'),
'manage_woocommerce',
'bdfg-role-discounts',
array($this, 'admin_page')
);
}

/**
* 注册设置
*
* @since 1.0.0
*/
public function register_settings() {
register_setting(
'bdfg_role_discounts_group',
$this->option_name,
array($this, 'sanitize_settings')
);
}

/**
* 添加设置链接
*
* @since 1.0.0
* @param array $links 插件操作链接
* @return array
*/
public function add_settings_link($links) {
$settings_link = '<a href="admin.php?page=bdfg-role-discounts">' . __('设置', 'bdfg-role-discounts') . '</a>';
array_unshift($links, $settings_link);
return $links;
}

/**
* 加载管理页面的CSS和JS
*
* @since 1.0.0
* @param string $hook 当前页面的钩子后缀
*/
public function enqueue_admin_scripts($hook) {
if ('woocommerce_page_bdfg-role-discounts' !== $hook) {
return;
}

// 管理页面CSS
wp_enqueue_style('bdfg-admin-style', $this->plugin_url . 'assets/css/admin.css', array(), $this->version);

// Select2
wp_enqueue_style('select2', $this->plugin_url . 'assets/css/select2.min.css', array(), '4.1.0');
wp_enqueue_script('select2', $this->plugin_url . 'assets/js/select2.min.js', array('jquery'), '4.1.0', true);

// 日期选择器
wp_enqueue_script('jquery-ui-datepicker');
wp_enqueue_script('jquery-ui-sortable');
wp_enqueue_style('jquery-ui-style', '//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css');

// 管理页面JS
wp_enqueue_script('bdfg-admin-script', $this->plugin_url . 'assets/js/admin.js', array('jquery', 'jquery-ui-datepicker', 'jquery-ui-sortable', 'select2'), $this->version, true);

// 本地化脚本
wp_localize_script('bdfg-admin-script', 'bdfg_params', array(
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('bdfg-admin-nonce'),
'currency_symbol' => get_woocommerce_currency_symbol(),
'date_format' => _x('mm/dd/yy', 'jQuery datepicker date format', 'bdfg-role-discounts'),
'i18n' => array(
'confirm_delete' => __('确定要删除此规则吗?此操作无法撤销。', 'bdfg-role-discounts'),
'confirm_reset' => __('确定要重置所有用户的首次购买记录吗?此操作无法撤销。', 'bdfg-role-discounts'),
'confirm_import' => __('导入设置将覆盖当前所有配置,确定要继续吗?', 'bdfg-role-discounts'),
'copied' => __('已复制到剪贴板', 'bdfg-role-discounts'),
'copy_failed' => __('复制失败,请手动复制', 'bdfg-role-discounts'),
'rule_updated' => __('规则已更新', 'bdfg-role-discounts'),
'import_success' => __('设置导入成功', 'bdfg-role-discounts'),
'import_error' => __('导入失败,请检查设置格式', 'bdfg-role-discounts'),
'reset_success' => __('首次购买记录已重置', 'bdfg-role-discounts'),
'search_products' => __('搜索产品...', 'bdfg-role-discounts'),
'search_users' => __('搜索用户...', 'bdfg-role-discounts')
)
));
}

/**
* 加载前端脚本和样式
*
* @since 2.0.0
*/
public function enqueue_frontend_scripts() {
// 只在产品页面加载
if (is_product() && (!empty($this->settings['show_discount_info']) || !empty($this->settings['show_original_price']))) {
wp_enqueue_style('bdfg-frontend-style', $this->plugin_url . 'assets/css/frontend.css', array(), $this->version);
}
}

/**
* 渲染管理页面
*
* @since 1.0.0
*/
public function admin_page() {
// 检查用户权限
if (!current_user_can('manage_woocommerce')) {
wp_die(__('您没有足够的权限访问此页面', 'bdfg-role-discounts'));
}

// 获取所有用户角色
$roles = $this->get_all_user_roles();

// 获取所有产品分类
$product_categories = get_terms(array(
'taxonomy' => 'product_cat',
'hide_empty' => false,
));

// 获取多货币支持
$currencies = $this->get_available_currencies();

?>
<div class="wrap bdfg-role-discounts">
<h1><?php _e('BDFG 用户角色折扣设置', 'bdfg-role-discounts'); ?></h1>

<div class="bdfg-header-banner">
<span class="bdfg-version"><?php printf(__('版本: %s', 'bdfg-role-discounts'), $this->version); ?></span>
<a href="https://beiduofengou.net/plugins/bdfg-role-discounts/docs" target="_blank" class="bdfg-docs-link"><?php _e('文档', 'bdfg-role-discounts'); ?></a>
<a href="https://beiduofengou.net/support" target="_blank" class="bdfg-support-link"><?php _e('支持', 'bdfg-role-discounts'); ?></a>
</div>

<form method="post" action="options.php" id="bdfg-discount-form">
<?php settings_fields('bdfg_role_discounts_group'); ?>

<div class="bdfg-tabs">
<ul class="bdfg-tabs-nav">
<li class="active"><a href="#discount-rules"><?php _e('折扣规则', 'bdfg-role-discounts'); ?></a></li>
<li><a href="#excluded-items"><?php _e('排除项', 'bdfg-role-discounts'); ?></a></li>
<li><a href="#settings"><?php _e('常规设置', 'bdfg-role-discounts'); ?></a></li>
<li><a href="#tools"><?php _e('工具', 'bdfg-role-discounts'); ?></a></li>
</ul>

<div class="bdfg-tab-content">
<!-- 折扣规则面板 -->
<div id="discount-rules" class="bdfg-tab-pane active">
<h2><?php _e('折扣规则', 'bdfg-role-discounts'); ?>
<button type="button" class="button button-secondary add-rule"><?php _e('添加规则', 'bdfg-role-discounts'); ?></button>
</h2>

<div class="bdfg-rules-container">
<?php
if (!empty($this->settings['rules']) && is_array($this->settings['rules'])) {
foreach ($this->settings['rules'] as $rule_id => $rule) {
$this->render_rule_row($rule_id, $rule, $roles, $product_categories, $currencies);
}
}
?>

<!-- 规则模板 - 用于JavaScript克隆 -->
<div class="bdfg-rule-row rule-template" style="display: none;">
<?php $this->render_rule_row('RULE_ID', array(), $roles, $product_categories, $currencies); ?>
</div>
</div>
</div>

<!-- 排除项面板 -->
<div id="excluded-items" class="bdfg-tab-pane">
<h2><?php _e('排除项设置', 'bdfg-role-discounts'); ?></h2>

<table class="form-table">
<tr>
<th scope="row"><?php _e('排除的产品', 'bdfg-role-discounts'); ?></th>
<td>
<select name="<?php echo esc_attr($this->option_name); ?>[excluded_products][]" class="bdfg-product-select" multiple="multiple" style="width: 100%;">
<?php
if (!empty($this->settings['excluded_products'])) {
foreach ($this->settings['excluded_products'] as $product_id) {
$product = wc_get_product($product_id);
if ($product) {
echo '<option value="' . esc_attr($product_id) . '" selected>' . esc_html($product->get_name()) . ' (#' . $product_id . ')</option>';
}
}
}
?>
</select>
<p class="description"><?php _e('这些产品不会应用任何折扣规则', 'bdfg-role-discounts'); ?></p>
</td>
</tr>
<tr>
<th scope="row"><?php _e('排除的用户', 'bdfg-role-discounts'); ?></th>
<td>
<select name="<?php echo esc_attr($this->option_name); ?>[excluded_users][]" class="bdfg-user-select" multiple="multiple" style="width: 100%;">
<?php
if (!empty($this->settings['excluded_users'])) {
foreach ($this->settings['excluded_users'] as $user_id) {
$user = get_userdata($user_id);
if ($user) {
echo '<option value="' . esc_attr($user_id) . '" selected>' . esc_html($user->display_name) . ' (' . $user->user_email . ')</option>';
}
}
}
?>
</select>
<p class="description"><?php _e('这些用户不会获得任何折扣', 'bdfg-role-discounts'); ?></p>
</td>
</tr>
<tr>
<th scope="row"><?php _e('排除特价产品', 'bdfg-role-discounts'); ?></th>
<td>
<label>
<input type="checkbox" name="<?php echo esc_attr($this->option_name); ?>[exclude_sale_items]" value="1" <?php checked(!empty($this->settings['exclude_sale_items'])); ?> />
<?php _e('排除已有特价的产品', 'bdfg-role-discounts'); ?>
</label>
<p class="description"><?php _e('WooCommerce 中已标记为特价的产品将不会应用角色折扣', 'bdfg-role-discounts'); ?></p>
</td>
</tr>
</table>
</div>

<!-- 常规设置面板 -->
<div id="settings" class="bdfg-tab-pane">
<h2><?php _e('常规设置', 'bdfg-role-discounts'); ?></h2>

<table class="form-table">
<tr>
<th scope="row"><?php _e('显示原价', 'bdfg-role-discounts'); ?></th>
<td>
<label>
<input type="checkbox" name="<?php echo esc_attr($this->option_name); ?>[show_original_price]" value="1" <?php checked(!empty($this->settings['show_original_price'])); ?> />
<?php _e('在折扣价格旁显示划线的原价', 'bdfg-role-discounts'); ?>
</label>
</td>
</tr>
<tr>
<th scope="row"><?php _e('显示折扣信息', 'bdfg-role-discounts'); ?></th>
<td>
<label>
<input type="checkbox" name="<?php echo esc_attr($this->option_name); ?>[show_discount_info]" value="1" <?php checked(!empty($this->settings['show_discount_info'])); ?> />
<?php _e('在产品页面显示用户折扣信息', 'bdfg-role-discounts'); ?>
</label>
</td>
</tr>
<tr>
<th scope="row"><?php _e('折扣信息文本', 'bdfg-role-discounts'); ?></th>
<td>
<input type="text" name="<?php echo esc_attr($this->option_name); ?>[discount_text]" value="<?php echo esc_attr(!empty($this->settings['discount_text']) ? $this->settings['discount_text'] : __('您享有 {discount} 的折扣!', 'bdfg-role-discounts')); ?>" class="regular-text" />
<p class="description"><?php _e('可使用的变量: {discount}, {role}', 'bdfg-role-discounts'); ?></p>
</td>
</tr>
<tr>
<th scope="row"><?php _e('缓存支持', 'bdfg-role-discounts'); ?></th>
<td>
<label>
<input type="checkbox" name="<?php echo esc_attr($this->option_name); ?>[enable_cache_support]" value="1" <?php checked(!empty($this->settings['enable_cache_support'])); ?> />
<?php _e('启用与页面缓存插件的兼容性', 'bdfg-role-discounts'); ?>
</label>
<p class="description"><?php _e('如果您使用页面缓存插件(如WP Super Cache、W3 Total Cache等),请启用此选项以确保折扣正常显示', 'bdfg-role-discounts'); ?></p>
</td>
</tr>
<tr>
<th scope="row"><?php _e('性能优化', 'bdfg-role-discounts'); ?></th>
<td>
<label>
<input type="checkbox" name="<?php echo esc_attr($this->option_name); ?>[enable_performance_mode]" value="1" <?php checked(!empty($this->settings['enable_performance_mode'])); ?> />
<?php _e('启用性能优化模式', 'bdfg-role-discounts'); ?>
</label>
<p class="description"><?php _e('减少数据库查询和优化计算逻辑以提高性能', 'bdfg-role-discounts'); ?></p>
</td>
</tr>
</table>
</div>

<!-- 工具面板 -->
<div id="tools" class="bdfg-tab-pane">
<h2><?php _e('工具和调试', 'bdfg-role-discounts'); ?></h2>

<div class="bdfg-tools-section">
<h3><?php _e('测试折扣规则', 'bdfg-role-discounts'); ?></h3>

<div class="bdfg-test-discount">
<p>
<label for="test-user"><?php _e('选择用户:', 'bdfg-role-discounts'); ?></label>
<select id="test-user" class="bdfg-user-select" style="width: 300px;"></select>
</p>

<p>
<label for="test-product"><?php _e('选择产品:', 'bdfg-role-discounts'); ?></label>
<select id="test-product" class="bdfg-product-select" style="width: 300px;"></select>
</p>

<p>
<label for="test-quantity"><?php _e('数量:', 'bdfg-role-discounts'); ?></label>
<input type="number" id="test-quantity" min="1" value="1" style="width: 80px;">
</p>

<p>
<button type="button" id="run-test" class="button button-primary"><?php _e('测试折扣', 'bdfg-role-discounts'); ?></button>
</p>

<div id="test-results" style="display: none;">
<h4><?php _e('测试结果', 'bdfg-role-discounts'); ?></h4>
<div class="bdfg-test-output"></div>
</div>
</div>
</div>

<div class="bdfg-tools-section">
<h3><?php _e('导入/导出设置', 'bdfg-role-discounts'); ?></h3>

<div class="bdfg-import-export">
<p>
<button type="button" id="export-settings" class="button button-secondary"><?php _e('导出设置', 'bdfg-role-discounts'); ?></button>
<span class="description"><?php _e('导出当前所有折扣规则和设置', 'bdfg-role-discounts'); ?></span>
</p>

<div id="export-container" style="display: none;">
<textarea id="export-data" rows="8" style="width: 100%;" readonly></textarea>
<p><button type="button" id="copy-export" class="button button-secondary"><?php _e('复制到剪贴板', 'bdfg-role-discounts'); ?></button></p>
</div>

<hr>

<p>
<label for="import-data"><?php _e('粘贴要导入的设置:', 'bdfg-role-discounts'); ?></label>
</p>
<p>
<textarea id="import-data" rows="8" style="width: 100%;"></textarea>
</p>
<p>
<button type="button" id="import-settings" class="button button-secondary"><?php _e('导入设置', 'bdfg-role-discounts'); ?></button>
<span class="description"><?php _e('注意: 这将覆盖当前所有设置', 'bdfg-role-discounts'); ?></span>
</p>
</div>
</div>

<div class="bdfg-tools-section">
<h3><?php _e('重置首次购买记录', 'bdfg-role-discounts'); ?></h3>

<p><?php _e('如果您使用了首次购买折扣功能,此工具可以重置系统中记录的用户首次购买状态。', 'bdfg-role-discounts'); ?></p>

<p>
<button type="button" id="reset-first-purchase" class="button button-secondary"><?php _e('重置所有首次购买记录', 'bdfg-role-discounts'); ?></button>
<span class="description"><?php _e('这将允许所有用户再次获得首次购买折扣', 'bdfg-role-discounts'); ?></span>
</p>
</div>

<div class="bdfg-tools-section">
<h3><?php _e('系统信息', 'bdfg-role-discounts'); ?></h3>

<table class="widefat" cellspacing="0">
<tbody>
<tr>
<td><?php _e('WordPress 版本', 'bdfg-role-discounts'); ?></td>
<td><?php echo get_bloginfo('version'); ?></td>
</tr>
<tr>
<td><?php _e('WooCommerce 版本', 'bdfg-role-discounts'); ?></td>
<td>
<?php
if (defined('WC_VERSION')) {
echo WC_VERSION;
} else {
echo __('未知', 'bdfg-role-discounts');
}
?>
</td>
</tr>
<tr>
<td><?php _e('BDFG 角色折扣版本', 'bdfg-role-discounts'); ?></td>
<td><?php echo $this->version; ?></td>
</tr>
<tr>
<td><?php _e('PHP 版本', 'bdfg-role-discounts'); ?></td>
<td><?php echo phpversion(); ?></td>
</tr>
<tr>
<td><?php _e('最后更新时间', 'bdfg-role-discounts'); ?></td>
<td><?php echo date_i18n(get_option('date_format') . ' ' . get_option('time_format'), get_option('bdfg_last_updated', time())); ?></td>
</tr>
</tbody>
</table>

<p class="description">
<?php printf(__('最后构建: %s | Powered by %s', 'bdfg-role-discounts'), '2025-03-06 15:46:53', '<a href="https://beiduofengou.net" target="_blank">beiduofengou.net</a>'); ?>
</p>
</div>
</div>
</div>
</div>

<p class="submit">
<input type="submit" class="button-primary" value="<?php _e('保存设置', 'bdfg-role-discounts'); ?>" />
</p>
</form>
</div>
<?php
}

/**
* 渲染单个规则行
*
* @since 1.0.0
* @param string $rule_id 规则ID
* @param array $rule 规则数据
* @param array $roles 所有用户角色
* @param array $product_categories 所有产品分类
* @param array $currencies 可用货币
*/
private function render_rule_row($rule_id, $rule, $roles, $product_categories, $currencies) {
$rule = wp_parse_args($rule, array(
'name' => '',
'enabled' => true,
'roles' => array(),
'discount_type' => 'percentage',
'discount_amount' => '',
'min_order_amount' => '',
'product_categories' => array(),
'start_date' => '',
'end_date' => '',
'first_purchase_only' => false,
'currency' => '',
'condition_relationship' => 'AND',
'additional_conditions' => array()
));

$prefix = $this->option_name . '[rules][' . $rule_id . ']';
?>
<div class="bdfg-rule-row" data-rule-id="<?php echo esc_attr($rule_id); ?>">
<div class="bdfg-rule-header">
<div class="bdfg-rule-title">
<span class="bdfg-drag-handle dashicons dashicons-menu"></span>
<span class="rule-name"><?php echo esc_html(!empty($rule['name']) ? $rule['name'] : __('未命名规则', 'bdfg-role-discounts')); ?></span>
</div>
<div class="bdfg-rule-actions">
<label class="bdfg-toggle">
<input type="checkbox" name="<?php echo esc_attr($prefix); ?>[enabled]" value="1" <?php checked($rule['enabled']); ?>>
<span class="bdfg-toggle-slider"></span>
</label>
<a href="#" class="bdfg-toggle-rule dashicons dashicons-arrow-down-alt2"></a>
<a href="#" class="bdfg-delete-rule dashicons dashicons-trash"></a>
</div>
</div>

<div class="bdfg-rule-content">
<table class="form-table">
<tr>
<th scope="row"><?php _e('规则名称', 'bdfg-role-discounts'); ?></th>
<td>
<input type="text" name="<?php echo esc_attr($prefix); ?>[name]" value="<?php echo esc_attr($rule['name']); ?>" class="regular-text rule-name-input" placeholder="<?php esc_attr_e('输入规则名称', 'bdfg-role-discounts'); ?>" />
</td>
</tr>

<tr>
<th scope="row"><?php _e('应用角色', 'bdfg-role-discounts'); ?></th>
<td>
<select name="<?php echo esc_attr($prefix); ?>[roles][]" multiple="multiple" class="bdfg-multiselect">
<?php foreach ($roles as $role_id => $role_name) : ?>
<option value="<?php echo esc_attr($role_id); ?>" <?php selected(in_array($role_id, (array) $rule['roles'])); ?>>
<?php echo esc_html($role_name); ?>
</option>
<?php endforeach; ?>
</select>
<p class="description"><?php _e('选择此折扣适用的用户角色', 'bdfg-role-discounts'); ?></p>
</td>
</tr>

<tr>
<th scope="row"><?php _e('折扣类型', 'bdfg-role-discounts'); ?></th>
<td>
<select name="<?php echo esc_attr($prefix); ?>[discount_type]" class="discount-type-select">
<option value="percentage" <?php selected($rule['discount_type'], 'percentage'); ?>><?php _e('百分比折扣', 'bdfg-role-discounts'); ?></option>
<option value="fixed_amount" <?php selected($rule['discount_type'], 'fixed_amount'); ?>><?php _e('固定金额折扣', 'bdfg-role-discounts'); ?></option>
</select>
</td>
</tr>

<tr>
<th scope="row"><?php _e('折扣金额', 'bdfg-role-discounts'); ?></th>
<td>
<div class="discount-amount-field">
<div class="discount-percentage" <?php echo $rule['discount_type'] === 'percentage' ? '' : 'style="display:none;"'; ?>>
<input type="number" name="<?php echo esc_attr($prefix); ?>[discount_amount]" value="<?php echo esc_attr($rule['discount_amount']); ?>" class="small-text" min="0" max="100" step="0.01" /> %
<p class="description"><?php _e('百分比折扣 (0-100)', 'bdfg-role-discounts'); ?></p>
</div>

<div class="discount-fixed" <?php echo $rule['discount_type'] === 'fixed_amount' ? '' : 'style="display:none;"'; ?>>
<?php echo get_woocommerce_currency_symbol(); ?>
<input type="number" name="<?php echo esc_attr($prefix); ?>[discount_amount]" value="<?php echo esc_attr($rule['discount_amount']); ?>" class="small-text" min="0" step="0.01" />
<p class="description"><?php _e('固定金额折扣', 'bdfg-role-discounts'); ?></p>
</div>
</div>
</td>
</tr>

<tr>
<th scope="row"><?php _e('最低订单金额', 'bdfg-role-discounts'); ?></th>
<td>
<?php echo get_woocommerce_currency_symbol(); ?>
<input type="number" name="<?php echo esc_attr($prefix); ?>[min_order_amount]" value="<?php echo esc_attr($rule['min_order_amount']); ?>" class="small-text" min="0" step="0.01" />
<p class="description"><?php _e('应用折扣所需的最低订单金额(留空表示无最低要求)', 'bdfg-role-discounts'); ?></p>
</td>
</tr>

<tr>
<th scope="row"><?php _e('产品分类', 'bdfg-role-discounts'); ?></th>
<td>
<select name="<?php echo esc_attr($prefix); ?>[product_categories][]" multiple="multiple" class="bdfg-multiselect">
<?php foreach ($product_categories as $category) : ?>
<option value="<?php echo esc_attr($category->term_id); ?>" <?php selected(in_array($category->term_id, (array) $rule['product_categories'])); ?>>
<?php echo esc_html($category->name); ?>
</option>
<?php endforeach; ?>
</select>
<p class="description"><?php _e('仅对选定分类的产品应用折扣(留空表示应用于所有产品)', 'bdfg-role-discounts'); ?></p>
</td>
</tr>

<tr>
<th scope="row"><?php _e('有效期', 'bdfg-role-discounts'); ?></th>
<td>
<div class="date-range-fields">
<label>
<?php _e('开始日期:', 'bdfg-role-discounts'); ?>
<input type="text" name="<?php echo esc_attr($prefix); ?>[start_date]" value="<?php echo esc_attr($rule['start_date']); ?>" class="bdfg-datepicker" placeholder="<?php esc_attr_e('YYYY-MM-DD', 'bdfg-role-discounts'); ?>" />
</label>

<label>
<?php _e('结束日期:', 'bdfg-role-discounts'); ?>
<input type="text" name="<?php echo esc_attr($prefix); ?>[end_date]" value="<?php echo esc_attr($rule['end_date']); ?>" class="bdfg-datepicker" placeholder="<?php esc_attr_e('YYYY-MM-DD', 'bdfg-role-discounts'); ?>" />
</label>
</div>
<p class="description"><?php _e('设置折扣的有效期范围(留空表示永久有效)', 'bdfg-role-discounts'); ?></p>
</td>
</tr>

<tr>
<th scope="row"><?php _e('首次购买限制', 'bdfg-role-discounts'); ?></th>
<td>
<label>
<input type="checkbox" name="<?php echo esc_attr($prefix); ?>[first_purchase_only]" value="1" <?php checked(!empty($rule['first_purchase_only'])); ?> />
<?php _e('仅限首次购买时使用此折扣', 'bdfg-role-discounts'); ?>
</label>
<p class="description"><?php _e('每个用户只能获得一次此折扣', 'bdfg-role-discounts'); ?></p>
</td>
</tr>

<?php if (!empty($currencies) && count($currencies) > 1) : ?>
<tr>
<th scope="row"><?php _e('货币限制', 'bdfg-role-discounts'); ?></th>
<td>
<select name="<?php echo esc_attr($prefix); ?>[currency]">
<option value="" <?php selected(empty($rule['currency'])); ?>><?php _e('所有货币', 'bdfg-role-discounts'); ?></option>
<?php foreach ($currencies as $code => $name) : ?>
<option value="<?php echo esc_attr($code); ?>" <?php selected($rule['currency'], $code); ?>>
<?php echo esc_html($name . ' (' . $code . ')'); ?>
</option>
<?php endforeach; ?>
</select>
<p class="description"><?php _e('仅对特定货币应用此折扣(需要多货币插件支持)', 'bdfg-role-discounts'); ?></p>
</td>
</tr>
<?php endif; ?>

<tr>
<th scope="row"><?php _e('条件关系', 'bdfg-role-discounts'); ?></th>
<td>
<select name="<?php echo esc_attr($prefix); ?>[condition_relationship]">
<option value="AND" <?php selected($rule['condition_relationship'], 'AND'); ?>><?php _e('满足所有条件 (AND)', 'bdfg-role-discounts'); ?></option>
<option value="OR" <?php selected($rule['condition_relationship'], 'OR'); ?>><?php _e('满足任一条件 (OR)', 'bdfg-role-discounts'); ?></option>
</select>
<p class="description"><?php _e('决定多个条件之间的关系', 'bdfg-role-discounts'); ?></p>
</td>
</tr>

<tr class="additional-conditions-row">
<th scope="row"><?php _e('附加条件', 'bdfg-role-discounts'); ?></th>
<td>
<div class="bdfg-additional-conditions">
<?php
if (!empty($rule['additional_conditions']) && is_array($rule['additional_conditions'])) {
foreach ($rule['additional_conditions'] as $condition_id => $condition) {
$this->render_condition_row($prefix, $condition_id, $condition);
}
}
?>
</div>

<p>
<button type="button" class="button add-condition" data-prefix="<?php echo esc_attr($prefix); ?>">
<?php _e('添加条件', 'bdfg-role-discounts'); ?>
</button>
</p>

<!-- 条件模板 -->
<div class="condition-template" style="display: none;">
<?php $this->render_condition_row($prefix, 'CONDITION_ID', array()); ?>
</div>
</td>
</tr>
</table>
</div>
</div>
<?php
}

/**
* 渲染附加条件行
*
* @since 1.0.0
* @param string $prefix 表单元素前缀
* @param string $condition_id 条件ID
* @param array $condition 条件数据
*/
private function render_condition_row($prefix, $condition_id, $condition) {
$condition = wp_parse_args($condition, array(
'type' => 'day_of_week',
'operator' => 'is',
'value' => ''
));

$condition_prefix = $prefix . '[additional_conditions][' . $condition_id . ']';
?>
<div class="bdfg-condition-row" data-condition-id="<?php echo esc_attr($condition_id); ?>">
<select name="<?php echo esc_attr($condition_prefix); ?>[type]" class="condition-type">
<option value="day_of_week" <?php selected($condition['type'], 'day_of_week'); ?>><?php _e('星期几', 'bdfg-role-discounts'); ?></option>
<option value="time_of_day" <?php selected($condition['type'], 'time_of_day'); ?>><?php _e('一天中的时间', 'bdfg-role-discounts'); ?></option>
<option value="customer_order_count" <?php selected($condition['type'], 'customer_order_count'); ?>><?php _e('客户订单数量', 'bdfg-role-discounts'); ?></option>
<option value="customer_spent_amount" <?php selected($condition['type'], 'customer_spent_amount'); ?>><?php _e('客户消费金额', 'bdfg-role-discounts'); ?></option>
</select>

<select name="<?php echo esc_attr($condition_prefix); ?>[operator]" class="condition-operator">
<option value="is" <?php selected($condition['operator'], 'is'); ?>><?php _e('是', 'bdfg-role-discounts'); ?></option>
<option value="is_not" <?php selected($condition['operator'], 'is_not'); ?>><?php _e('不是', 'bdfg-role-discounts'); ?></option>
<option value="greater_than" <?php selected($condition['operator'], 'greater_than'); ?>><?php _e('大于', 'bdfg-role-discounts'); ?></option>
<option value="less_than" <?php selected($condition['operator'], 'less_than'); ?>><?php _e('小于', 'bdfg-role-discounts'); ?></option>
<option value="contains" <?php selected($condition['operator'], 'contains'); ?>><?php _e('包含', 'bdfg-role-discounts'); ?></option>
</select>

<div class="condition-value-field">
<!-- 星期几选择 -->
<div class="condition-day-of-week" <?php echo $condition['type'] === 'day_of_week' ? '' : 'style="display:none;"'; ?>>
<select name="<?php echo esc_attr($condition_prefix); ?>[value]" class="condition-value">
<option value="monday" <?php selected($condition['value'], 'monday'); ?>><?php _e('星期一', 'bdfg-role-discounts'); ?></option>
<option value="tuesday" <?php selected($condition['value'], 'tuesday'); ?>><?php _e('星期二', 'bdfg-role-discounts'); ?></option>
<option value="wednesday" <?php selected($condition['value'], 'wednesday'); ?>><?php _e('星期三', 'bdfg-role-discounts'); ?></option>
<option value="thursday" <?php selected($condition['value'], 'thursday'); ?>><?php _e('星期四', 'bdfg-role-discounts'); ?></option>
<option value="friday" <?php selected($condition['value'], 'friday'); ?>><?php _e('星期五', 'bdfg-role-discounts'); ?></option>
<option value="saturday" <?php selected($condition['value'], 'saturday'); ?>><?php _e('星期六', 'bdfg-role-discounts'); ?></option>
<option value="sunday" <?php selected($condition['value'], 'sunday'); ?>><?php _e('星期日', 'bdfg-role-discounts'); ?></option>
<option value="weekday" <?php selected($condition['value'], 'weekday'); ?>><?php _e('工作日', 'bdfg-role-discounts'); ?></option>
<option value="weekend" <?php selected($condition['value'], 'weekend'); ?>><?php _e('周末', 'bdfg-role-discounts'); ?></option>
</select>
</div>

<!-- 时间输入 -->
<div class="condition-time-of-day" <?php echo $condition['type'] === 'time_of_day' ? '' : 'style="display:none;"'; ?>>
<input type="time" name="<?php echo esc_attr($condition_prefix); ?>[value]" value="<?php echo esc_attr($condition['value']); ?>" class="condition-value" />
</div>

<!-- 数值输入 -->
<div class="condition-numeric" <?php echo in_array($condition['type'], array('customer_order_count', 'customer_spent_amount')) ? '' : 'style="display:none;"'; ?>>
<input type="number" name="<?php echo esc_attr($condition_prefix); ?>[value]" value="<?php echo esc_attr($condition['value']); ?>" class="condition-value" min="0" step="<?php echo $condition['type'] === 'customer_order_count' ? '1' : '0.01'; ?>" />
</div>
</div>

<button type="button" class="button button-small delete-condition">
<span class="dashicons dashicons-no-alt"></span>
</button>
</div>
<?php
}

/**
* 获取所有用户角色
*
* @since 1.0.0
* @return array
*/
private function get_all_user_roles() {
global $wp_roles;

if (!isset($wp_roles)) {
$wp_roles = new WP_Roles();
}

$all_roles = $wp_roles->get_names();

return $all_roles;
}

/**
* 获取可用货币
*
* @since 1.0.0
* @return array
*/
private function get_available_currencies() {
$currencies = array();

// 默认WooCommerce货币
$currencies[get_woocommerce_currency()] = get_woocommerce_currency_symbol();

// 检查多货币插件
// WooCommerce多货币
if (class_exists('WCML_Multi_Currency') && function_exists('wcml_get_woocommerce_currencies_options')) {
$multi_currencies = wcml_get_woocommerce_currencies_options();
foreach ($multi_currencies as $code => $name) {
$currencies[$code] = $name;
}
}

// WOOMULTI货币插件
if (class_exists('WOOMULTI_CURRENCY_Data') && function_exists('wmc_get_currencies')) {
$wmc_currencies = wmc_get_currencies();
foreach ($wmc_currencies as $code => $data) {
$currencies[$code] = $code;
}
}

// BDFG多货币支持
$bdfg_currencies = apply_filters('bdfg_role_discounts_currencies', array());
if (!empty($bdfg_currencies) && is_array($bdfg_currencies)) {
foreach ($bdfg_currencies as $code => $name) {
$currencies[$code] = $name;
}
}

return $currencies;
}

/**
* 清理和验证设置
*
* @since 1.0.0
* @param array $input 表单数据
* @return array
*/
public function sanitize_settings($input) {
$sanitized = array();

// 处理折扣规则
if (isset($input['rules']) && is_array($input['rules'])) {
foreach ($input['rules'] as $rule_id => $rule) {
// 验证规则ID格式
if (!preg_match('/^[a-zA-Z0-9_]+$/', $rule_id)) {
continue;
}

// 清理规则数据
$sanitized['rules'][$rule_id] = array(
'name' => sanitize_text_field(isset($rule['name']) ? $rule['name'] : ''),
'enabled' => isset($rule['enabled']) && $rule['enabled'] ? true : false,
'roles' => isset($rule['roles']) && is_array($rule['roles']) ? array_map('sanitize_text_field', $rule['roles']) : array(),
'discount_type' => isset($rule['discount_type']) && in_array($rule['discount_type'], array('percentage', 'fixed_amount')) ? $rule['discount_type'] : 'percentage',
'discount_amount' => isset($rule['discount_amount']) ? floatval($rule['discount_amount']) : 0,
'min_order_amount' => isset($rule['min_order_amount']) && $rule['min_order_amount'] !== '' ? floatval($rule['min_order_amount']) : '',
'product_categories' => isset($rule['product_categories']) && is_array($rule['product_categories']) ? array_map('intval', $rule['product_categories']) : array(),
'start_date' => isset($rule['start_date']) ? sanitize_text_field($rule['start_date']) : '',
'end_date' => isset($rule['end_date']) ? sanitize_text_field($rule['end_date']) : '',
'first_purchase_only' => isset($rule['first_purchase_only']) && $rule['first_purchase_only'] ? true : false,
'currency' => isset($rule['currency']) ? sanitize_text_field($rule['currency']) : '',
'condition_relationship' => isset($rule['condition_relationship']) && in_array($rule['condition_relationship'], array('AND', 'OR')) ? $rule['condition_relationship'] : 'AND'
);

// 清理附加条件
if (isset($rule['additional_conditions']) && is_array($rule['additional_conditions'])) {
foreach ($rule['additional_conditions'] as $condition_id => $condition) {
// 验证条件ID格式
if (!preg_match('/^[a-zA-Z0-9_]+$/', $condition_id)) {
continue;
}

// 默认条件类型
$condition_type = isset($condition['type']) && in_array($condition['type'], array('day_of_week', 'time_of_day', 'customer_order_count', 'customer_spent_amount')) ? $condition['type'] : 'day_of_week';

// 默认操作符
$valid_operators = array('is', 'is_not', 'greater_than', 'less_than', 'contains');
$operator = isset($condition['operator']) && in_array($condition['operator'], $valid_operators) ? $condition['operator'] : 'is';

// 清理条件值
$value = isset($condition['value']) ? $condition['value'] : '';
switch ($condition_type) {
case 'day_of_week':
$valid_days = array('monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday', 'weekday', 'weekend');
$value = in_array($value, $valid_days) ? $value : 'monday';
break;

case 'time_of_day':
// 验证时间格式 HH:MM
if (!preg_match('/^([01]?[0-9]|2[0-3]):([0-5][0-9])$/', $value)) {
$value = '00:00';
}
break;

case 'customer_order_count':
$value = max(0, intval($value));
break;

case 'customer_spent_amount':
$value = max(0, floatval($value));
break;
}

$sanitized['rules'][$rule_id]['additional_conditions'][$condition_id] = array(
'type' => $condition_type,
'operator' => $operator,
'value' => $value
);
}
}
}
}

// 处理排除项
if (isset($input['excluded_products']) && is_array($input['excluded_products'])) {
$sanitized['excluded_products'] = array_map('intval', $input['excluded_products']);
}

if (isset($input['excluded_users']) && is_array($input['excluded_users'])) {
$sanitized['excluded_users'] = array_map('intval', $input['excluded_users']);
}

$sanitized['exclude_sale_items'] = isset($input['exclude_sale_items']) && $input['exclude_sale_items'] ? 1 : 0;

// 处理常规设置
$sanitized['show_original_price'] = isset($input['show_original_price']) && $input['show_original_price'] ? 1 : 0;
$sanitized['show_discount_info'] = isset($input['show_discount_info']) && $input['show_discount_info'] ? 1 : 0;
$sanitized['discount_text'] = isset($input['discount_text']) ? sanitize_text_field($input['discount_text']) : __('您享有 {discount} 的折扣!', 'bdfg-role-discounts');
$sanitized['enable_cache_support'] = isset($input['enable_cache_support']) && $input['enable_cache_support'] ? 1 : 0;
$sanitized['enable_performance_mode'] = isset($input['enable_performance_mode']) && $input['enable_performance_mode'] ? 1 : 0;

// 更新最后修改时间
update_option('bdfg_last_updated', time());

return $sanitized;
}

/**
* 应用折扣到购物车商品
*
* @since 1.0.0
* @param WC_Cart $cart 购物车对象
*/
public function apply_discounts($cart) {
if (is_admin() && !defined('DOING_AJAX')) {
return;
}

if (did_action('woocommerce_before_calculate_totals') > 1) {
return;
}

// 获取当前用户
$user_id = get_current_user_id();
if (!$user_id) {
return;
}

// 获取用户角色
$user = get_userdata($user_id);
if (!$user) {
return;
}

$user_roles = $user->roles;

// 检查用户是否在排除列表中
if (!empty($this->settings['excluded_users']) && in_array($user_id, $this->settings['excluded_users'])) {
return;
}

// 计算购物车总金额(用于最低订单金额检查)
$cart_total = 0;
foreach ($cart->get_cart() as $cart_item) {
$cart_total += $cart_item['data']->get_price() * $cart_item['quantity'];
}

// 获取当前货币(如果使用多货币插件)
$current_currency = $this->get_current_currency();

// 获取用户是否已完成首次购买
$first_purchases = get_option($this->first_purchase_option, array());
$has_purchased = isset($first_purchases[$user_id]);

// 处理每个购物车商品
foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
// 获取产品
$product = $cart_item['data'];
$product_id = $product->get_id();

// 如果设置了排除特价产品,并且产品正在特价中,则跳过
if (!empty($this->settings['exclude_sale_items']) && $product->is_on_sale()) {
continue;
}

// 检查产品是否在排除列表中
if (!empty($this->settings['excluded_products']) && in_array($product_id, $this->settings['excluded_products'])) {
continue;
}

// 产品原始价格
$original_price = $product->get_price();

// 找到最佳折扣
$best_discount = 0;
$best_discount_type = 'percentage';
$applied_rule_id = '';

// 如果有规则,遍历所有规则找到最佳折扣
if (!empty($this->settings['rules']) && is_array($this->settings['rules'])) {
foreach ($this->settings['rules'] as $rule_id => $rule) {
// 如果规则未启用,跳过
if (empty($rule['enabled'])) {
continue;
}

// 检查用户角色是否匹配
$role_match = false;
foreach ($user_roles as $role) {
if (in_array($role, (array) $rule['roles'])) {
$role_match = true;
break;
}
}

if (!$role_match) {
continue;
}

// 检查货币是否匹配
if (!empty($rule['currency']) && $rule['currency'] !== $current_currency) {
continue;
}

// 检查最低订单金额
if (!empty($rule['min_order_amount']) && $cart_total < floatval($rule['min_order_amount'])) {
continue;
}

// 检查产品分类
if (!empty($rule['product_categories'])) {
$product_cats = wc_get_product_term_ids($product_id, 'product_cat');
$category_match = false;
foreach ($product_cats as $cat) {
if (in_array($cat, (array) $rule['product_categories'])) {
$category_match = true;
break;
}
}

if (!$category_match) {
continue;
}
}

// 检查日期范围
$current_time = current_time('timestamp');

if (!empty($rule['start_date'])) {
$start_time = strtotime($rule['start_date']);
if ($current_time < $start_time) {
continue;
}
}

if (!empty($rule['end_date'])) {
$end_time = strtotime($rule['end_date'] . ' 23:59:59');
if ($current_time > $end_time) {
continue;
}
}

// 检查首次购买限制
if (!empty($rule['first_purchase_only']) && $has_purchased) {
continue;
}

// 检查附加条件
if (!empty($rule['additional_conditions']) && is_array($rule['additional_conditions'])) {
$conditions_met = $this->check_additional_conditions($rule['additional_conditions'], $rule['condition_relationship'], $user_id);

if (!$conditions_met) {
continue;
}
}

// 获取折扣金额
$discount_amount = floatval($rule['discount_amount']);
$discount_type = $rule['discount_type'];

// 计算折扣
$current_discount = 0;
if ($discount_type === 'percentage') {
$current_discount = $original_price * ($discount_amount / 100);
} else { // fixed_amount
$current_discount = $discount_amount;

// 确保折扣不超过产品价格
if ($current_discount > $original_price) {
$current_discount = $original_price;
}
}

// 应用BDFG过滤器允许修改特定折扣
$current_discount = apply_filters('bdfg_role_discount_amount', $current_discount, $rule, $product, $cart_item, $user);

// 更新最佳折扣
if ($current_discount > $best_discount) {
$best_discount = $current_discount;
$best_discount_type = $discount_type;
$applied_rule_id = $rule_id;
}
}
}

// 如果找到折扣,应用它
if ($best_discount > 0) {
$new_price = $original_price - $best_discount;

// 确保价格不低于0
if ($new_price < 0) {
$new_price = 0;
}

// 设置新价格
$product->set_price($new_price);

// 在购物车项上保存元数据,用于订单处理和显示
$cart_item['bdfg_original_price'] = $original_price;
$cart_item['bdfg_discount_amount'] = $best_discount;
$cart_item['bdfg_discount_type'] = $best_discount_type;
$cart_item['bdfg_applied_rule'] = $applied_rule_id;

// 对外部代码暴露这些数据
$cart->cart_contents[$cart_item_key] = $cart_item;
}
}
}

/**
* 显示折扣信息在产品页面
*
* @since 2.0.0
*/
public function display_discount_info() {
// 如果未启用显示折扣信息,则返回
if (empty($this->settings['show_discount_info'])) {
return;
}

// 获取当前产品
$product = wc_get_product();
if (!$product) {
return;
}

// 获取当前用户
$user_id = get_current_user_id();
if (!$user_id) {
return;
}

$user = get_userdata($user_id);
if (!$user) {
return;
}

// 检查用户是否在排除列表中
if (!empty($this->settings['excluded_users']) && in_array($user_id, $this->settings['excluded_users'])) {
return;
}

// 检查产品是否在排除列表中
if (!empty($this->settings['excluded_products']) && in_array($product->get_id(), $this->settings['excluded_products'])) {
return;
}

// 如果设置了排除特价产品,并且产品正在特价中,则返回
if (!empty($this->settings['exclude_sale_items']) && $product->is_on_sale()) {
return;
}

// 计算用户的折扣
$discount_info = $this->calculate_user_discount($user, $product);

// 如果有折扣,显示信息
if ($discount_info && $discount_info['discount_amount'] > 0) {
$discount_text = !empty($this->settings['discount_text']) ? $this->settings['discount_text'] : __('您享有 {discount} 的折扣!', 'bdfg-role-discounts');

// 替换变量
$discount_text = str_replace('{discount}', $discount_info['discount_formatted'], $discount_text);
$discount_text = str_replace('{role}', $discount_info['role_name'], $discount_text);

echo '<div class="bdfg-discount-info">' . esc_html($discount_text) . '</div>';
}
}

/**
* 显示原价在折扣价旁边
*
* @since 2.0.0
* @param string $price_html 价格HTML
* @param WC_Product $product 产品对象
* @return string
*/
public function show_original_price($price_html, $product) {
// 如果未启用显示原价,则返回原始价格HTML
if (empty($this->settings['show_original_price'])) {
return $price_html;
}

// 获取当前用户
$user_id = get_current_user_id();
if (!$user_id) {
return $price_html;
}

// 获取用户
$user = get_userdata($user_id);
if (!$user) {
return $price_html;
}

// 检查用户是否在排除列表中
if (!empty($this->settings['excluded_users']) && in_array($user_id, $this->settings['excluded_users'])) {
return $price_html;
}

// 检查产品是否在排除列表中
if (!empty($this->settings['excluded_products']) && in_array($product->get_id(), $this->settings['excluded_products'])) {
return $price_html;
}

// 如果设置了排除特价产品,并且产品正在特价中,则返回原始价格HTML
if (!empty($this->settings['exclude_sale_items']) && $product->is_on_sale()) {
return $price_html;
}

// 计算用户的折扣
$discount_info = $this->calculate_user_discount($user, $product);

// 如果有折扣,修改价格HTML
if ($discount_info && $discount_info['discount_amount'] > 0) {
$original_price = $product->get_price();
$discounted_price = $original_price - $discount_info['discount_amount'];

if ($discounted_price < 0) {
$discounted_price = 0;
}

$original_price_html = wc_price($original_price);
$discounted_price_html = wc_price($discounted_price);

$price_html = '<del>' . $original_price_html . '</del> <ins>' . $discounted_price_html . '</ins>';
}

return $price_html;
}

/**
* 计算用户折扣
*
* @since 2.0.0
* @param WP_User $user 用户对象
* @param WC_Product $product 产品对象
* @return array|bool 折扣信息或false
*/
private function calculate_user_discount($user, $product) {
if (!$user || !$product) {
return false;
}

$user_roles = $user->roles;
$product_id = $product->get_id();
$original_price = $product->get_price();

// 获取当前货币
$current_currency = $this->get_current_currency();

// 获取用户是否已完成首次购买
$first_purchases = get_option($this->first_purchase_option, array());
$has_purchased = isset($first_purchases[$user->ID]);

// 找到最佳折扣
$best_discount = 0;
$best_discount_type = 'percentage';
$applied_rule = null;
$applied_rule_id = '';

// 如果有规则,遍历所有规则找到最佳折扣
if (!empty($this->settings['rules']) && is_array($this->settings['rules'])) {
foreach ($this->settings['rules'] as $rule_id => $rule) {
// 如果规则未启用,跳过
if (empty($rule['enabled'])) {
continue;
}

// 检查用户角色是否匹配
$role_match = false;
foreach ($user_roles as $role) {
if (in_array($role, (array) $rule['roles'])) {
$role_match = true;
break;
}
}

if (!$role_match) {
continue;
}

// 检查货币是否匹配
if (!empty($rule['currency']) && $rule['currency'] !== $current_currency) {
continue;
}

// 检查产品分类
if (!empty($rule['product_categories'])) {
$product_cats = wc_get_product_term_ids($product_id, 'product_cat');
$category_match = false;
foreach ($product_cats as $cat) {
if (in_array($cat, (array) $rule['product_categories'])) {
$category_match = true;
break;
}
}

if (!$category_match) {
continue;
}
}

// 检查日期范围
$current_time = current_time('timestamp');

if (!empty($rule['start_date'])) {
$start_time = strtotime($rule['start_date']);
if ($current_time < $start_time) {
continue;
}
}

if (!empty($rule['end_date'])) {
$end_time = strtotime($rule['end_date'] . ' 23:59:59');
if ($current_time > $end_time) {
continue;
}
}

// 检查首次购买限制
if (!empty($rule['first_purchase_only']) && $has_purchased) {
continue;
}

// 检查附加条件
if (!empty($rule['additional_conditions']) && is_array($rule['additional_conditions'])) {
$conditions_met = $this->check_additional_conditions($rule['additional_conditions'], $rule['condition_relationship'], $user->ID);

if (!$conditions_met) {
continue;
}
}

// 获取折扣金额
$discount_amount = floatval($rule['discount_amount']);
$discount_type = $rule['discount_type'];

// 计算折扣
$current_discount = 0;
if ($discount_type === 'percentage') {
$current_discount = $original_price * ($discount_amount / 100);
} else { // fixed_amount
$current_discount = $discount_amount;

// 确保折扣不超过产品价格
if ($current_discount > $original_price) {
$current_discount = $original_price;
}
}

// 更新最佳折扣
if ($current_discount > $best_discount) {
$best_discount = $current_discount;
$best_discount_type = $discount_type;
$applied_rule = $rule;
$applied_rule_id = $rule_id;
}
}
}

// 如果找到折扣,返回折扣信息
if ($best_discount > 0) {
// 获取用户角色名称
$roles = $this->get_all_user_roles();
$role_name = '';

foreach ($user_roles as $role) {
if (isset($roles[$role])) {
$role_name = $roles[$role];
break;
}
}

// 格式化折扣信息
if ($best_discount_type === 'percentage') {
$discount_formatted = round(($best_discount / $original_price) * 100, 2) . '%';
} else {
$discount_formatted = wc_price($best_discount);
}

return array(
'discount_amount' => $best_discount,
'discount_type' => $best_discount_type,
'discount_formatted' => $discount_formatted,
'role_name' => $role_name,
'applied_rule' => $applied_rule,
'applied_rule_id' => $applied_rule_id
);
}

return false;
}

/**
* 检查附加条件
*
* @since 1.0.0
* @param array $conditions 条件数组
* @param string $relationship 条件关系
* @param int $user_id 用户ID
* @return bool
*/
private function check_additional_conditions($conditions, $relationship, $user_id) {
if (empty($conditions)) {
return true;
}

$results = array();

foreach ($conditions as $condition) {
$result = false;

switch ($condition['type']) {
case 'day_of_week':
$result = $this->check_day_of_week_condition($condition);
break;

case 'time_of_day':
$result = $this->check_time_of_day_condition($condition);
break;

case 'customer_order_count':
$result = $this->check_customer_order_count_condition($condition, $user_id);
break;

case 'customer_spent_amount':
$result = $this->check_customer_spent_amount_condition($condition, $user_id);
break;
}

$results[] = $result;
}

// 根据关系检查所有条件
if ($relationship === 'AND') {
return !in_array(false, $results);
} else { // OR
return in_array(true, $results);
}
}

/**
* 检查星期几条件
*
* @since 1.0.0
* @param array $condition 条件数组
* @return bool
*/
private function check_day_of_week_condition($condition) {
$current_day = strtolower(date('l', current_time('timestamp')));
$condition_value = $condition['value'];

// 处理工作日和周末
if ($condition_value === 'weekday') {
$is_weekday = !in_array($current_day, array('saturday', 'sunday'));
return $condition['operator'] === 'is' ? $is_weekday : !$is_weekday;
} elseif ($condition_value === 'weekend') {
$is_weekend = in_array($current_day, array('saturday', 'sunday'));
return $condition['operator'] === 'is' ? $is_weekend : !$is_weekend;
}

// 处理具体星期几
$day_match = $current_day === $condition_value;
return $condition['operator'] === 'is' ? $day_match : !$day_match;
}

/**
* 检查一天中的时间条件
*
* @since 1.0.0
* @param array $condition 条件数组
* @return bool
*/
private function check_time_of_day_condition($condition) {
$current_time = current_time('H:i');

switch ($condition['operator']) {
case 'is':
return $current_time === $condition['value'];
case 'is_not':
return $current_time !== $condition['value'];
case 'greater_than':
return $current_time > $condition['value'];
case 'less_than':
return $current_time < $condition['value'];
default:
return false;
}
}

/**
* 检查客户订单数量条件
*
* @since 1.0.0
* @param array $condition 条件数组
* @param int $user_id 用户ID
* @return bool
*/
private function check_customer_order_count_condition($condition, $user_id) {
$order_count = wc_get_customer_order_count($user_id);

switch ($condition['operator']) {
case 'is':
return $order_count == $condition['value'];
case 'is_not':
return $order_count != $condition['value'];
case 'greater_than':
return $order_count > $condition['value'];
case 'less_than':
return $order_count < $condition['value'];
default:
return false;
}
}

/**
* 检查客户消费金额条件
*
* @since 1.0.0
* @param array $condition 条件数组
* @param int $user_id 用户ID
* @return bool
*/
private function check_customer_spent_amount_condition($condition, $user_id) {
$spent_amount = wc_get_customer_total_spent($user_id);

switch ($condition['operator']) {
case 'is':
return abs($spent_amount - $condition['value']) < 0.01;
case 'is_not':
return abs($spent_amount - $condition['value']) >= 0.01;
case 'greater_than':
return $spent_amount > $condition['value'];
case 'less_than':
return $spent_amount < $condition['value'];
default:
return false;
}
}

/**
* 获取当前货币
*
* @since 1.0.0
* @return string
*/
private function get_current_currency() {
$currency = get_woocommerce_currency();

// WCML多货币支持
if (function_exists('wcml_get_woocommerce_currency_option')) {
$currency = wcml_get_woocommerce_currency_option();
}

// WOOMULTI货币支持
if (class_exists('WOOMULTI_CURRENCY_Data')) {
$wmc_settings = WOOMULTI_CURRENCY_Data::get_ins();
if (method_exists($wmc_settings, 'get_current_currency')) {
$currency = $wmc_settings->get_current_currency();
}
}

// 应用BDFG货币过滤器
return apply_filters('bdfg_role_discounts_current_currency', $currency);
}

/**
* 处理订单完成后的操作
*
* @since 1.0.0
* @param int $order_id 订单ID
*/
public function process_completed_order($order_id) {
$order = wc_get_order($order_id);
if (!$order) {
return;
}

$user_id = $order->get_user_id();
if (!$user_id) {
return;
}

// 记录用户首次购买
$first_purchases = get_option($this->first_purchase_option, array());

if (!isset($first_purchases[$user_id])) {
$first_purchases[$user_id] = array(
'timestamp' => current_time('timestamp'),
'date' => date_i18n(get_option('date_format'), current_time('timestamp')),
'order_id' => $order_id,
'amount' => $order->get_total()
);
update_option($this->first_purchase_option, $first_purchases);
}

do_action('bdfg_role_discounts_order_completed', $order, $user_id);
}

/**
* Ajax测试折扣规则
*
* @since 1.0.0
*/
public function ajax_test_discount_rule() {
// 检查安全性
check_ajax_referer('bdfg-admin-nonce', 'nonce');

// 检查权限
if (!current_user_can('manage_woocommerce')) {
wp_send_json_error(array('message' => __('权限不足', 'bdfg-role-discounts')));
exit;
}

// 获取参数
$user_id = isset($_POST['user_id']) ? intval($_POST['user_id']) : 0;
$product_id = isset($_POST['product_id']) ? intval($_POST['product_id']) : 0;
$quantity = isset($_POST['quantity']) ? intval($_POST['quantity']) : 1;

if (!$user_id || !$product_id) {
wp_send_json_error(array('message' => __('缺少必要参数', 'bdfg-role-discounts')));
exit;
}

// 获取用户和产品
$user = get_userdata($user_id);
$product = wc_get_product($product_id);

if (!$user || !$product) {
wp_send_json_error(array('message' => __('无效的用户或产品', 'bdfg-role-discounts')));
exit;
}

// 模拟计算折扣
$discount_info = $this->calculate_user_discount($user, $product);

$original_price = $product->get_price();
$discounted_price = $original_price;
$discount_amount = 0;
$discount_percentage = 0;

if ($discount_info && $discount_info['discount_amount'] > 0) {
$discount_amount = $discount_info['discount_amount'];
$discounted_price = $original_price - $discount_amount;

if ($discounted_price < 0) {
$discounted_price = 0;
}

$discount_percentage = ($discount_amount / $original_price) * 100;
}

// 获取适用的规则信息
$rules_info = array();
if (!empty($this->settings['rules']) && is_array($this->settings['rules'])) {
foreach ($this->settings['rules'] as $rule_id => $rule) {
if (empty($rule['enabled'])) {
continue;
}

$is_eligible = true;
$not_eligible_reason = '';

// 检查用户角色
$role_match = false;
foreach ($user->roles as $role) {
if (in_array($role, (array) $rule['roles'])) {
$role_match = true;
break;
}
}

if (!$role_match) {
$is_eligible = false;
$not_eligible_reason = __('用户角色不匹配', 'bdfg-role-discounts');
}

// 检查产品分类
if ($is_eligible && !empty($rule['product_categories'])) {
$product_cats = wc_get_product_term_ids($product_id, 'product_cat');
$category_match = false;
foreach ($product_cats as $cat) {
if (in_array($cat, (array) $rule['product_categories'])) {
$category_match = true;
break;
}
}

if (!$category_match) {
$is_eligible = false;
$not_eligible_reason = __('产品分类不匹配', 'bdfg-role-discounts');
}
}

// 检查日期范围
$current_time = current_time('timestamp');

if ($is_eligible && !empty($rule['start_date'])) {
$start_time = strtotime($rule['start_date']);
if ($current_time < $start_time) {
$is_eligible = false;
$not_eligible_reason = __('折扣尚未开始', 'bdfg-role-discounts');
}
}

if ($is_eligible && !empty($rule['end_date'])) {
$end_time = strtotime($rule['end_date'] . ' 23:59:59');
if ($current_time > $end_time) {
$is_eligible = false;
$not_eligible_reason = __('折扣已过期', 'bdfg-role-discounts');
}
}

// 检查首次购买限制
if ($is_eligible && !empty($rule['first_purchase_only'])) {
$first_purchases = get_option($this->first_purchase_option, array());
$has_purchased = isset($first_purchases[$user_id]);

if ($has_purchased) {
$is_eligible = false;
$not_eligible_reason = __('仅限首次购买', 'bdfg-role-discounts');
}
}

// 计算此规则的折扣
$rule_discount_amount = 0;
if ($is_eligible) {
if ($rule['discount_type'] === 'percentage') {
$rule_discount_amount = $original_price * (floatval($rule['discount_amount']) / 100);
} else { // fixed_amount
$rule_discount_amount = floatval($rule['discount_amount']);
if ($rule_discount_amount > $original_price) {
$rule_discount_amount = $original_price;
}
}
}

// 添加规则信息
$rules_info[] = array(
'id' => $rule_id,
'name' => $rule['name'],
'is_eligible' => $is_eligible,
'not_eligible_reason' => $not_eligible_reason,
'discount_type' => $rule['discount_type'],
'discount_amount' => floatval($rule['discount_amount']),
'calculated_discount' => $rule_discount_amount,
'calculated_discount_formatted' => wc_price($rule_discount_amount),
'is_best_discount' => $discount_info && $discount_info['applied_rule_id'] === $rule_id
);
}
}

$response = array(
'success' => true,
'timestamp' => '2025-03-06 15:59:12', // 使用提供的时间
'user' => array(
'id' => $user->ID,
'name' => $user->display_name,
'login' => 'beiduofengou', // 使用提供的登录名
'email' => $user->user_email,
'roles' => implode(', ', array_map(function($role_id) {
$roles = $this->get_all_user_roles();
return isset($roles[$role_id]) ? $roles[$role_id] : $role_id;
}, $user->roles))
),
'product' => array(
'id' => $product->get_id(),
'name' => $product->get_name(),
'original_price' => $original_price,
'original_price_formatted' => wc_price($original_price),
'quantity' => $quantity
),
'discount' => array(
'applied' => $discount_amount > 0,
'discounted_price' => $discounted_price,
'discounted_price_formatted' => wc_price($discounted_price),
'discount_amount' => $discount_amount,
'discount_amount_formatted' => wc_price($discount_amount),
'discount_percentage' => round($discount_percentage, 2) . '%'
),
'rules' => $rules_info
);

wp_send_json_success($response);
exit;
}

/**
* Ajax导出设置
*
* @since 2.0.0
*/
public function ajax_export_settings() {
// 检查安全性
check_ajax_referer('bdfg-admin-nonce', 'nonce');

// 检查权限
if (!current_user_can('manage_woocommerce')) {
wp_send_json_error(array('message' => __('权限不足', 'bdfg-role-discounts')));
exit;
}

// 获取设置
$settings = get_option($this->option_name, array());

// 添加元数据
$export_data = array(
'meta' => array(
'plugin' => 'BDFG Role-Based Discounts for WooCommerce',
'version' => $this->version,
'date' => date('Y-m-d H:i:s'),
'site' => get_bloginfo('name'),
'url' => get_bloginfo('url')
),
'settings' => $settings
);

// 返回JSON编码的设置
wp_send_json_success(array(
'data' => json_encode($export_data, JSON_PRETTY_PRINT),
'message' => __('设置导出成功', 'bdfg-role-discounts')
));
exit;
}

/**
* Ajax导入设置
*
* @since 2.0.0
*/
public function ajax_import_settings() {
// 检查安全性
check_ajax_referer('bdfg-admin-nonce', 'nonce');

// 检查权限
if (!current_user_can('manage_woocommerce')) {
wp_send_json_error(array('message' => __('权限不足', 'bdfg-role-discounts')));
exit;
}

// 获取导入数据
$import_data = isset($_POST['import_data']) ? stripslashes($_POST['import_data']) : '';

if (empty($import_data)) {
wp_send_json_error(array('message' => __('导入数据为空', 'bdfg-role-discounts')));
exit;
}

// 解码JSON
$decoded_data = json_decode($import_data, true);

if (json_last_error() !== JSON_ERROR_NONE) {
wp_send_json_error(array('message' => __('导入数据格式无效', 'bdfg-role-discounts')));
exit;
}

// 验证导入数据结构
if (!isset($decoded_data['settings']) || !is_array($decoded_data['settings'])) {
wp_send_json_error(array('message' => __('导入数据结构无效', 'bdfg-role-discounts')));
exit;
}

// 保存设置
update_option($this->option_name, $decoded_data['settings']);

// 更新缓存的设置
$this->settings = $decoded_data['settings'];

// 更新最后修改时间
update_option('bdfg_last_updated', time());

wp_send_json_success(array('message' => __('设置导入成功', 'bdfg-role-discounts')));
exit;
}

/**
* Ajax重置首次购买记录
*
* @since 2.0.0
*/
public function ajax_reset_first_purchase() {
// 检查安全性
check_ajax_referer('bdfg-admin-nonce', 'nonce');

// 检查权限
if (!current_user_can('manage_woocommerce')) {
wp_send_json_error(array('message' => __('权限不足', 'bdfg-role-discounts')));
exit;
}

// 删除首次购买记录选项
delete_option($this->first_purchase_option);

wp_send_json_success(array('message' => __('首次购买记录已重置', 'bdfg-role-discounts')));
exit;
}

/**
* Ajax搜索产品
*
* @since 1.0.0
*/
public function ajax_search_products() {
// 检查安全性
check_ajax_referer('bdfg-admin-nonce', 'nonce');

// 检查权限
if (!current_user_can('manage_woocommerce')) {
wp_die(-1);
}

$term = isset($_GET['term']) ? sanitize_text_field($_GET['term']) : '';

if (empty($term)) {
wp_die();
}

$args = array(
'post_type' => 'product',
'post_status' => 'publish',
'posts_per_page' => 25,
's' => $term,
);

$query = new WP_Query($args);
$products = array();

if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
$product = wc_get_product(get_the_ID());
if ($product) {
$products[] = array(
'id' => $product->get_id(),
'text' => $product->get_name() . ' (#' . $product->get_id() . ', ' . wc_price($product->get_price()) . ')'
);
}
}
wp_reset_postdata();
}

wp_send_json(array('results' => $products));
}

/**
* Ajax搜索用户
*
* @since 1.0.0
*/
public function ajax_search_users() {
// 检查安全性
check_ajax_referer('bdfg-admin-nonce', 'nonce');

// 检查权限
if (!current_user_can('manage_woocommerce')) {
wp_die(-1);
}

$term = isset($_GET['term']) ? sanitize_text_field($_GET['term']) : '';

if (empty($term)) {
wp_die();
}

$args = array(
'search' => '*' . $term . '*',
'search_columns' => array('user_login', 'user_email', 'display_name'),
'number' => 25
);

$user_query = new WP_User_Query($args);
$users = array();

if (!empty($user_query->results)) {
foreach ($user_query->results as $user) {
$users[] = array(
'id' => $user->ID,
'text' => sprintf('%s (%s)', $user->display_name, $user->user_email)
);
}
}

wp_send_json(array('results' => $users));
}

/**
* 获取应用于测试的规则
*
* @since 2.0.0
* @param WP_User $user
* @param WC_Product $product
* @param int $quantity
* @return array
*/
private function get_eligible_rules_for_test($user, $product, $quantity) {
$result = array();

// 详细实现逻辑与calculate_user_discount类似
// 此处省略...

return $result;
}
}

/**
* 全局方法:检查BDFG角色折扣是否适用于用户
*
* @since 2.5.0
* @param int $user_id 用户ID
* @return bool
*/
function bdfg_is_role_discount_applicable($user_id) {
$instance = BDFG_Role_Discounts::get_instance();
$settings = get_option('bdfg_role_discounts_settings', array());

// 检查用户是否在排除列表中
if (!empty($settings['excluded_users']) && in_array($user_id, $settings['excluded_users'])) {
return false;
}

// 获取用户角色
$user = get_userdata($user_id);
if (!$user) {
return false;
}

$user_roles = $user->roles;

// 检查是否有适用的规则
if (!empty($settings['rules']) && is_array($settings['rules'])) {
foreach ($settings['rules'] as $rule) {
if (empty($rule['enabled'])) {
continue;
}

// 检查用户角色是否匹配
foreach ($user_roles as $role) {
if (in_array($role, (array) $rule['roles'])) {
return true;
}
}
}
}

return false;
}

/**
* 全局方法:获取用户角色折扣信息
*
* @since 2.5.0
* @param int $user_id 用户ID
* @return array|bool
*/
function bdfg_get_role_discount_info($user_id) {
$instance = BDFG_Role_Discounts::get_instance();
$discount_info = false;

$user = get_userdata($user_id);
if (!$user) {
return false;
}

// 获取所有折扣规则
$settings = get_option('bdfg_role_discounts_settings', array());

// 检查用户是否在排除列表中
if (!empty($settings['excluded_users']) && in_array($user_id, $settings['excluded_users'])) {
return false;
}

// 获取用户角色
$user_roles = $user->roles;
$applicable_rules = array();

// 查找适用的规则
if (!empty($settings['rules']) && is_array($settings['rules'])) {
foreach ($settings['rules'] as $rule_id => $rule) {
if (empty($rule['enabled'])) {
continue;
}

// 检查用户角色是否匹配
$role_match = false;
foreach ($user_roles as $role) {
if (in_array($role, (array) $rule['roles'])) {
$role_match = true;
break;
}
}

if ($role_match) {
$applicable_rules[$rule_id] = $rule;
}
}
}

// 返回适用规则信息
if (!empty($applicable_rules)) {
$roles = array();
$discount_percentages = array();
$discount_fixed_amounts = array();

foreach ($applicable_rules as $rule_id => $rule) {
if ($rule['discount_type'] === 'percentage') {
$discount_percentages[] = floatval($rule['discount_amount']);
} else {
$discount_fixed_amounts[] = floatval($rule['discount_amount']);
}

// 收集适用的角色
foreach ((array) $rule['roles'] as $role_id) {
if (in_array($role_id, $user_roles)) {
$roles[] = $role_id;
}
}
}

// 过滤重复的角色
$roles = array_unique($roles);

// 获取最高折扣
$max_percentage = !empty($discount_percentages) ? max($discount_percentages) : 0;
$max_fixed = !empty($discount_fixed_amounts) ? max($discount_fixed_amounts) : 0;

// 创建折扣信息
$discount_info = array(
'has_discount' => true,
'roles' => $roles,
'applicable_rules' => array_keys($applicable_rules),
'max_percentage' => $max_percentage,
'max_fixed_amount' => $max_fixed
);
}

return $discount_info;
}

// 启动插件
add_action('plugins_loaded', function() {
BDFG_Role_Discounts::get_instance();
});
}

includes/class-bdfg-admin.php

<?php
/**
* BDFG角色折扣管理面板功能
*
* @package BDFG_Role_Discounts
* @since 2.5.0
* @author Bei Duo Feng Ou <[email protected]>
*/

// 如果直接访问此文件,则中止执行
if (!defined('ABSPATH')) {
exit;
}

if (!class_exists('BDFG_Role_Discounts_Admin')) {

/**
* 管理面板控制类
*/
class BDFG_Role_Discounts_Admin {

/**
* BDFG插件实例
*
* @var BDFG_Role_Discounts
*/
private $plugin;

/**
* 初始化管理面板功能
*
* @param BDFG_Role_Discounts $plugin 插件主实例
*/
public function __construct($plugin) {
$this->plugin = $plugin;

// 添加设置链接
add_filter('plugin_action_links_' . plugin_basename(BDFG_ROLE_DISCOUNTS_FILE), array($this, 'add_settings_link'));

// 添加插件元数据
add_filter('plugin_row_meta', array($this, 'plugin_row_meta'), 10, 2);

// 添加管理面板通知
add_action('admin_notices', array($this, 'admin_notices'));

// 添加帮助标签
add_action('admin_head', array($this, 'add_help_tabs'), 10);
}

/**
* 添加设置链接到插件列表
*
* @param array $links 已有链接数组
* @return array 修改后的链接数组
*/
public function add_settings_link($links) {
$settings_link = '<a href="admin.php?page=bdfg-role-discounts">' . __('设置', 'bdfg-role-discounts') . '</a>';
array_unshift($links, $settings_link);
return $links;
}

/**
* 添加额外插件元信息
*
* @param array $links 已有链接数组
* @param string $file 当前插件文件
* @return array 修改后的链接数组
*/
public function plugin_row_meta($links, $file) {
if (plugin_basename(BDFG_ROLE_DISCOUNTS_FILE) === $file) {
$row_meta = array(
'docs' => '<a href="' . esc_url('https://beiduofengou.net/plugins/bdfg-role-discounts/docs') . '" target="_blank">' . esc_html__('文档', 'bdfg-role-discounts') . '</a>',
'support' => '<a href="' . esc_url('https://beiduofengou.net/support') . '" target="_blank">' . esc_html__('获取支持', 'bdfg-role-discounts') . '</a>',
);

return array_merge($links, $row_meta);
}

return $links;
}

/**
* 添加管理通知
*/
public function admin_notices() {
// 检查是否在插件设置页面
$screen = get_current_screen();
if ($screen->id != 'woocommerce_page_bdfg-role-discounts') {
return;
}

// 检查WooCommerce版本是否受支持
if (defined('WC_VERSION') && version_compare(WC_VERSION, '5.0', '<')) {
?>
<div class="notice notice-warning">
<p><?php _e('您正在使用较旧版本的WooCommerce。BDFG角色折扣插件可能无法在WooCommerce 5.0以下版本上正常工作。', 'bdfg-role-discounts'); ?></p>
</div>
<?php
}

// 检查是否已配置任何折扣规则
$settings = get_option('bdfg_role_discounts_settings', array());
if (empty($settings['rules'])) {
?>
<div class="notice notice-info">
<p><?php _e('您尚未创建任何折扣规则。点击"添加规则"按钮开始创建您的第一条角色折扣规则。', 'bdfg-role-discounts'); ?></p>
</div>
<?php
}

// 更新提示 - 使用transient来控制显示频率
if (!get_transient('bdfg_promotional_notice_dismissed')) {
?>
<div class="notice notice-info is-dismissible bdfg-promo-notice">
<p><?php printf(__('感谢使用BDFG角色折扣!访问我们的<a href="%s" target="_blank">官方网站</a>获取更多插件和教程。', 'bdfg-role-discounts'), 'https://beiduofengou.net'); ?></p>
</div>
<script>
jQuery(document).on('click', '.bdfg-promo-notice .notice-dismiss', function(){
jQuery.ajax({
url: ajaxurl,
data: {
action: 'bdfg_dismiss_promo_notice',
nonce: '<?php echo wp_create_nonce('bdfg-dismiss-notice'); ?>'
}
});
});
</script>
<?php
}
}

/**
* 添加帮助标签到设置页面
*/
public function add_help_tabs() {
$screen = get_current_screen();
if ($screen->id != 'woocommerce_page_bdfg-role-discounts') {
return;
}

// 添加设置帮助标签
$screen->add_help_tab(array(
'id' => 'bdfg-basic-help',
'title' => __('基本设置', 'bdfg-role-discounts'),
'content' => '<h2>' . __('基本设置说明', 'bdfg-role-discounts') . '</h2>' .
'<p>' . __('BDFG角色折扣允许您为不同的用户角色设置不同的折扣规则。您可以创建百分比折扣或固定金额折扣。', 'bdfg-role-discounts') . '</p>' .
'<p>' . __('在"折扣规则"标签中,您可以添加多条折扣规则,每条规则可以应用于不同的用户角色、产品分类或满足特定条件。', 'bdfg-role-discounts') . '</p>'
));

// 添加条件帮助标签
$screen->add_help_tab(array(
'id' => 'bdfg-conditions-help',
'title' => __('条件设置', 'bdfg-role-discounts'),
'content' => '<h2>' . __('条件设置说明', 'bdfg-role-discounts') . '</h2>' .
'<p>' . __('您可以为每条折扣规则添加多个条件,如星期几、一天中的时间、客户订单数量和客户消费金额等。', 'bdfg-role-discounts') . '</p>' .
'<p>' . __('条件关系可以设置为"满足所有条件"(AND)或"满足任一条件"(OR),以实现复杂的折扣逻辑。', 'bdfg-role-discounts') . '</p>'
));

// 设置帮助侧栏
$screen->set_help_sidebar(
'<p><strong>' . __('更多帮助:', 'bdfg-role-discounts') . '</strong></p>' .
'<p><a href="https://beiduofengou.net/plugins/bdfg-role-discounts/docs" target="_blank">' . __('查看完整文档', 'bdfg-role-discounts') . '</a></p>' .
'<p><a href="https://beiduofengou.net/support" target="_blank">' . __('获取技术支持', 'bdfg-role-discounts') . '</a></p>'
);
}
}
}

includes/class-bdfg-frontend.php

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

<?php
/**
* BDFG角色折扣前端功能
*
* @package BDFG_Role_Discounts
* @since 2.5.0
* @author Bei Duo Feng Ou <[email protected]>
*/

// 如果直接访问此文件,则中止执行
if (!defined('ABSPATH')) {
exit;
}

if (!class_exists('BDFG_Role_Discounts_Frontend')) {

/**
* 前端功能控制类
*/
class BDFG_Role_Discounts_Frontend {

/**
* BDFG插件实例
*
* @var BDFG_Role_Discounts
*/
private $plugin;

/**
* 插件设置
*
* @var array
*/
private $settings;

/**
* 初始化前端功能
*
* @param BDFG_Role_Discounts $plugin 插件主实例
*/
public function __construct($plugin) {
$this->plugin = $plugin;
$this->settings = get_option('bdfg_role_discounts_settings', array());

// 显示折扣信息
add_action('woocommerce_before_add_to_cart_form', array($this, 'display_discount_info'));

// 显示原价
add_filter('woocommerce_get_price_html', array($this, 'show_original_price'), 99, 2);

// 添加产品折扣徽章
add_action('woocommerce_before_shop_loop_item_title', array($this, 'add_discount_badge'), 10);

// 支持嵌入在内容中的折扣信息
add_shortcode('bdfg_discount_info', array($this, 'discount_info_shortcode'));
}

/**
* 在产品页面显示折扣信息
*/
public function display_discount_info() {
// 如果未启用显示折扣信息,则返回
if (empty($this->settings['show_discount_info'])) {
return;
}

// 获取当前产品
$product = wc_get_product();
if (!$product) {
return;
}

// 获取当前用户
$user_id = get_current_user_id();
if (!$user_id) {
return;
}

$user = get_userdata($user_id);
if (!$user) {
return;
}

// 检查用户是否在排除列表中
if (!empty($this->settings['excluded_users']) && in_array($user_id, $this->settings['excluded_users'])) {
return;
}

// 检查产品是否在排除列表中
if (!empty($this->settings['excluded_products']) && in_array($product->get_id(), $this->settings['excluded_products'])) {
return;
}

// 如果设置了排除特价产品,并且产品正在特价中,则返回
if (!empty($this->settings['exclude_sale_items']) && $product->is_on_sale()) {
return;
}

// 获取用户折扣信息
$discount_info = $this->get_user_discount_info($user, $product);

// 如果有折扣,显示信息
if ($discount_info && $discount_info['discount_amount'] > 0) {
$discount_text = !empty($this->settings['discount_text']) ? $this->settings['discount_text'] : __('您享有 {discount} 的折扣!', 'bdfg-role-discounts');

// 替换变量
$discount_text = str_replace('{discount}', $discount_info['discount_formatted'], $discount_text);
$discount_text = str_replace('{role}', $discount_info['role_name'], $discount_text);

echo '<div class="bdfg-discount-info">' . esc_html($discount_text) . '</div>';
}
}

/**
* 在产品列表中添加折扣徽章
*/
public function add_discount_badge() {
global $product;

// 如果没有配置显示折扣徽章,则返回
if (empty($this->settings['show_discount_badge'])) {
return;
}

// 获取当前用户
$user_id = get_current_user_id();
if (!$user_id) {
return;
}

// 检查用户是否在排除列表中
if (!empty($this->settings['excluded_users']) && in_array($user_id, $this->settings['excluded_users'])) {
return;
}

// 检查产品是否在排除列表中
if (!empty($this->settings['excluded_products']) && in_array($product->get_id(), $this->settings['excluded_products'])) {
return;
}

// 如果设置了排除特价产品,并且产品正在特价中,则返回
if (!empty($this->settings['exclude_sale_items']) && $product->is_on_sale()) {
return;
}

// 获取用户折扣信息
$user = get_userdata($user_id);
if (!$user) {
return;
}

$discount_info = $this->get_user_discount_info($user, $product);

// 如果有折扣,显示徽章
if ($discount_info && $discount_info['discount_amount'] > 0) {
echo '<span class="bdfg-discount-badge">' . esc_html($discount_info['discount_formatted']) . '</span>';
}
}

/**
* 显示原价在折扣价旁边
*
* @param string $price_html 价格HTML
* @param WC_Product $product 产品对象
* @return string
*/
public function show_original_price($price_html, $product) {
// 如果未启用显示原价,则返回原始价格HTML
if (empty($this->settings['show_original_price'])) {
return $price_html;
}

// 获取当前用户
$user_id = get_current_user_id();
if (!$user_id) {
return $price_html;
}

// 获取用户
$user = get_userdata($user_id);
if (!$user) {
return $price_html;
}

// 检查用户是否在排除列表中
if (!empty($this->settings['excluded_users']) && in_array($user_id, $this->settings['excluded_users'])) {
return $price_html;
}

// 检查产品是否在排除列表中
if (!empty($this->settings['excluded_products']) && in_array($product->get_id(), $this->settings['excluded_products'])) {
return $price_html;
}

// 如果设置了排除特价产品,并且产品正在特价中,则返回原始价格HTML
if (!empty($this->settings['exclude_sale_items']) && $product->is_on_sale()) {
return $price_html;
}

// 获取用户折扣信息
$discount_info = $this->get_user_discount_info($user, $product);

// 如果有折扣,修改价格HTML
if ($discount_info && $discount_info['discount_amount'] > 0) {
$original_price = $product->get_price();
$discounted_price = $original_price - $discount_info['discount_amount'];

if ($discounted_price < 0) {
$discounted_price = 0;
}

$original_price_html = wc_price($original_price);
$discounted_price_html = wc_price($discounted_price);

$price_html = '<del>' . $original_price_html . '</del> <ins>' . $discounted_price_html . '</ins>';
}

return $price_html;
}

/**
* 获取用户折扣信息
*
* @param WP_User $user 用户对象
* @param WC_Product $product 产品对象
* @return array|bool 折扣信息或false
*/
public function get_user_discount_info($user, $product) {
if (!$user || !$product) {
return false;
}

// 实现逻辑与主类中的calculate_user_discount类似
// 此处调用插件主实例的方法
return $this->plugin->calculate_user_discount($user, $product);
}

/**
* 折扣信息短代码
*
* @param array $atts 短代码属性
* @return string
*/
public function discount_info_shortcode($atts) {
$atts = shortcode_atts(array(
'product_id' => 0,
'custom_text' => '',
), $atts, 'bdfg_discount_info');

// 获取产品ID
$product_id = intval($atts['product_id']);
if (!$product_id) {
// 如果没有指定产品ID,则使用当前产品
global $product;
if (!$product) {
return '';
}
$product_id = $product->get_id();
} else {
$product = wc_get_product($product_id);
if (!$product) {
return '';
}
}

// 获取当前用户
$user_id = get_current_user_id();
if (!$user_id) {
return '';
}

$user = get_userdata($user_id);
if (!$user) {
return '';
}

// 检查用户是否在排除列表中
if (!empty($this->settings['excluded_users']) && in_array($user_id, $this->settings['excluded_users'])) {
return '';
}

// 检查产品是否在排除列表中
if (!empty($this->settings['excluded_products']) && in_array($product_id, $this->settings['excluded_products'])) {
return '';
}

// 如果设置了排除特价产品,并且产品正在特价中,则返回
if (!empty($this->settings['exclude_sale_items']) && $product->is_on_sale()) {
return '';
}

// 获取用户折扣信息
$discount_info = $this->get_user_discount_info($user, $product);

// 如果有折扣,显示信息
if ($discount_info && $discount_info['discount_amount'] > 0) {
$discount_text = !empty($atts['custom_text']) ? $atts['custom_text'] : (!empty($this->settings['discount_text']) ? $this->settings['discount_text'] : __('您享有 {discount} 的折扣!', 'bdfg-role-discounts'));

// 替换变量
$discount_text = str_replace('{discount}', $discount_info['discount_formatted'], $discount_text);
$discount_text = str_replace('{role}', $discount_info['role_name'], $discount_text);
$discount_text = str_replace('{product}', $product->get_name(), $discount_text);

return '<div class="bdfg-discount-info">' . esc_html($discount_text) . '</div>';
}

return '';
}
}
}

assets/css/admin.css

/**
* BDFG Role-Based Discounts for WooCommerce - Admin Styles
*
* @package BDFG_Role_Discounts
* @author Bei Duo Feng Ou
* @version 2.6.0
* @updated 2025-03-06
*/

/* 主要容器样式 */
.bdfg-role-discounts {
margin: 20px 0;
max-width: 1300px;
}

.bdfg-header-banner {
background: #f9f9f9;
border: 1px solid #e5e5e5;
padding: 10px 15px;
margin-bottom: 20px;
display: flex;
justify-content: flex-end;
align-items: center;
}

.bdfg-version {
margin-right: 15px;
color: #666;
font-style: italic;
}

.bdfg-docs-link, .bdfg-support-link {
margin-left: 15px;
text-decoration: none;
}

/* 标签导航 */
.bdfg-tabs {
margin-bottom: 20px;
}

.bdfg-tabs-nav {
display: flex;
margin: 0;
padding: 0;
list-style-type: none;
border-bottom: 1px solid #ccc;
}

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

.bdfg-tabs-nav a {
display: block;
padding: 10px 15px;
text-decoration: none;
background: #f1f1f1;
border: 1px solid #ccc;
border-bottom: none;
margin-right: 5px;
border-radius: 3px 3px 0 0;
color: #555;
font-weight: bold;
}

.bdfg-tabs-nav li.active a {
background: #fff;
border-bottom: 1px solid #fff;
margin-bottom: -1px;
color: #0073aa;
}

.bdfg-tab-content {
background: #fff;
padding: 20px;
border: 1px solid #ccc;
border-top: none;
}

.bdfg-tab-pane {
display: none;
}

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

/* 规则容器 */
.bdfg-rules-container {
margin-top: 15px;
}

.bdfg-rule-row {
background: #fff;
border: 1px solid #ccc;
margin-bottom: 15px;
border-radius: 3px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.bdfg-rule-header {
padding: 10px 15px;
background: #f7f7f7;
border-bottom: 1px solid #eee;
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;
}

.bdfg-rule-title {
display: flex;
align-items: center;
font-weight: bold;
}

.bdfg-drag-handle {
cursor: move;
margin-right: 10px;
color: #bbb;
}

.bdfg-rule-row:hover .bdfg-drag-handle {
color: #888;
}

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

.bdfg-rule-actions a {
margin-left: 10px;
text-decoration: none;
color: #555;
}

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

/* 开关按钮 */
.bdfg-toggle {
position: relative;
display: inline-block;
width: 40px;
height: 20px;
}

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

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

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

.bdfg-toggle input:checked + .bdfg-toggle-slider {
background-color: #2196F3;
}

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

/* 条件行 */
.bdfg-condition-row {
display: flex;
align-items: center;
margin-bottom: 10px;
padding: 10px;
background: #f9f9f9;
border: 1px solid #eee;
border-radius: 3px;
}

.bdfg-condition-row select,
.bdfg-condition-row input {
margin-right: 10px;
}

.bdfg-additional-conditions {
margin-bottom: 10px;
}

/* 日期范围字段 */
.date-range-fields {
display: flex;
gap: 10px;
}

.bdfg-datepicker {
width: 120px;
}

/* 工具部分 */
.bdfg-tools-section {
margin-bottom: 30px;
padding-bottom: 20px;
border-bottom: 1px solid #eee;
}

.bdfg-tools-section:last-child {
border-bottom: none;
}

.bdfg-test-output {
padding: 15px;
background: #f9f9f9;
border: 1px solid #eee;
margin-top: 10px;
max-height: 400px;
overflow-y: auto;
}

#export-data,
#import-data {
font-family: monospace;
font-size: 12px;
}

/* 其他样式 */
.description {
font-style: italic;
color: #666;
}

assets/css/frontend.css

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

/**
* BDFG Role-Based Discounts for WooCommerce - Frontend Styles
*
* @package BDFG_Role_Discounts
* @author Bei Duo Feng Ou
* @version 2.6.0
* @updated 2025-03-06
*/

/* 折扣信息 */
.bdfg-discount-info {
padding: 10px 15px;
background-color: #f7f6f7;
border-left: 4px solid #2196F3;
margin-bottom: 20px;
font-size: 0.95em;
color: #515151;
box-shadow: 0 1px 3px rgba(0,0,0,0.05);
position: relative;
display: inline-block;
width: 100%;
box-sizing: border-box;
}

/* 折扣价格 */
.price del {
opacity: 0.7;
font-size: 0.9em;
text-decoration: line-through;
margin-right: 0.5em;
}

.price ins {
font-weight: 700;
text-decoration: none;
color: #2196F3;
}

/* 折扣徽章 */
.bdfg-discount-badge {
position: absolute;
top: 0;
right: 0;
background: #2196F3;
color: white;
padding: 5px 10px;
font-size: 0.8em;
font-weight: bold;
z-index: 9;
border-radius: 0 0 0 5px;
}

/* 响应式样式 */
@media screen and (max-width: 768px) {
.bdfg-discount-info {
padding: 8px 12px;
font-size: 0.9em;
}

.bdfg-discount-badge {
padding: 3px 8px;
font-size: 0.75em;
}
}

assets/js/admin.js

/**
* BDFG Role-Based Discounts for WooCommerce - Admin JavaScript
*
* @package BDFG_Role_Discounts
* @author Bei Duo Feng Ou
* @version 2.6.0
* @updated 2025-03-06 16:02:29
*/

(function($) {
'use strict';

// DOM ready
$(function() {
// 初始化标签切换
initTabs();

// 初始化规则折叠
initRuleCollapse();

// 初始化拖拽排序
initRuleSorting();

// 初始化规则操作
initRuleActions();

// 初始化折扣类型切换
initDiscountTypeToggle();

// 初始化条件类型切换
initConditionTypeToggle();

// 初始化日期选择器
initDatepickers();

// 初始化选择框
initSelect2();

// 初始化测试功能
initTestDiscount();

// 初始化导入导出功能
initImportExport();

// 初始化首次购买重置功能
initResetFirstPurchase();
});

// 初始化标签切换
function initTabs() {
$('.bdfg-tabs-nav a').on('click', function(e) {
e.preventDefault();

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

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

// 显示目标面板
$('.bdfg-tab-pane').removeClass('active');
$(target).addClass('active');

// 保存当前活动标签到本地存储
if (typeof localStorage !== 'undefined') {
localStorage.setItem('bdfg_active_tab', target);
}
});

// 从本地存储恢复上次活动的标签
if (typeof localStorage !== 'undefined') {
var activeTab = localStorage.getItem('bdfg_active_tab');
if (activeTab && $(activeTab).length) {
$('.bdfg-tabs-nav a[href="' + activeTab + '"]').click();
}
}
}

// 初始化规则折叠
function initRuleCollapse() {
// 点击规则标题切换内容显示
$('.bdfg-rule-header').on('click', function(e) {
if (!$(e.target).is('.bdfg-toggle, .bdfg-toggle-slider, .bdfg-delete-rule, .bdfg-drag-handle')) {
var $content = $(this).next('.bdfg-rule-content');
var $icon = $(this).find('.bdfg-toggle-rule');

$content.slideToggle(200);

if ($content.is(':visible')) {
$icon.removeClass('dashicons-arrow-down-alt2').addClass('dashicons-arrow-up-alt2');
} else {
$icon.removeClass('dashicons-arrow-up-alt2').addClass('dashicons-arrow-down-alt2');
}
}
});

// 单独点击切换图标也切换规则内容
$('.bdfg-toggle-rule').on('click', function(e) {
e.preventDefault();
e.stopPropagation();

var $header = $(this).closest('.bdfg-rule-header');
$header.trigger('click');
});
}

// 初始化拖拽排序
function initRuleSorting() {
$('.bdfg-rules-container').sortable({
handle: '.bdfg-drag-handle',
items: '.bdfg-rule-row:not(.rule-template)',
axis: 'y',
opacity: 0.7,
cursor: 'move',
update: function() {
// 可以在这里添加规则排序更新逻辑
}
});
}

// 初始化规则操作
function initRuleActions() {
// 添加规则按钮
$('.add-rule').on('click', function() {
var $template = $('.rule-template');
var $newRule = $template.clone();
var ruleId = 'rule_' + new Date().getTime();

$newRule.removeClass('rule-template').removeAttr('style');
$newRule.attr('data-rule-id', ruleId);

// 更新新规则中的所有表单字段名称
$newRule.find('[name]').each(function() {
var name = $(this).attr('name');
name = name.replace('RULE_ID', ruleId);
$(this).attr('name', name);
});

$newRule.find('.condition-template').remove();

$template.before($newRule);

// 初始化新规则中的各种控件
initRuleControls($newRule);

// 显示新规则的内容
$newRule.find('.bdfg-rule-content').show();
$newRule.find('.bdfg-toggle-rule')
.removeClass('dashicons-arrow-down-alt2')
.addClass('dashicons-arrow-up-alt2');
});

// 删除规则按钮
$(document).on('click', '.bdfg-delete-rule', function(e) {
e.preventDefault();
e.stopPropagation();

if (confirm(bdfg_params.i18n.confirm_delete)) {
$(this).closest('.bdfg-rule-row').remove();
}
});

// 规则名称与标题同步
$(document).on('input', '.rule-name-input', function() {
var name = $(this).val() || bdfg_params.i18n.unnamed_rule;
$(this).closest('.bdfg-rule-row').find('.rule-name').text(name);
});

// 添加条件按钮
$(document).on('click', '.add-condition', function() {
var $btn = $(this);
var prefix = $btn.data('prefix');
var $template = $btn.closest('tr').find('.condition-template');
var $newCondition = $template.children().clone();
var conditionId = 'condition_' + new Date().getTime();

$newCondition.attr('data-condition-id', conditionId);

// 更新新条件中的所有表单字段名称
$newCondition.find('[name]').each(function() {
var name = $(this).attr('name');
name = name.replace('CONDITION_ID', conditionId);
$(this).attr('name', name);
});

$btn.closest('tr').find('.bdfg-additional-conditions').append($newCondition);

// 初始化新条件中的控件
initConditionControls($newCondition);
});

// 删除条件按钮
$(document).on('click', '.delete-condition', function() {
$(this).closest('.bdfg-condition-row').remove();
});
}

// 初始化规则中的控件
function initRuleControls($rule) {
$rule.find('.bdfg-multiselect').select2();
$rule.find('.bdfg-datepicker').datepicker({
dateFormat: bdfg_params.date_format,
changeMonth: true,
changeYear: true
});

initDiscountTypeToggle($rule);
initConditionTypeToggle($rule);
}

// 初始化条件中的控件
function initConditionControls($condition) {
// 条件类型切换
$condition.find('.condition-type').trigger('change');
}

// 初始化折扣类型切换
function initDiscountTypeToggle($context) {
var $container = $context || $(document);

// 初始化已有的折扣类型选择
$container.find('.discount-type-select').each(function() {
updateDiscountFields($(this));
});

// 折扣类型变更时更新字段
$container.on('change', '.discount-type-select', function() {
updateDiscountFields($(this));
});

function updateDiscountFields($select) {
var type = $select.val();
var $row = $select.closest('tr');
var $nextRow = $row.next('tr');
var $discountField = $nextRow.find('.discount-amount-field');

if (type === 'percentage') {
$discountField.find('.discount-percentage').show();
$discountField.find('.discount-fixed').hide();
} else {
$discountField.find('.discount-percentage').hide();
$discountField.find('.discount-fixed').show();
}
}
}

// 初始化条件类型切换
function initConditionTypeToggle($context) {
var $container = $context || $(document);

// 初始化已有的条件类型选择
$container.find('.condition-type').each(function() {
updateConditionFields($(this));
});

// 条件类型变更时更新字段
$container.on('change', '.condition-type', function() {
updateConditionFields($(this));
});

function updateConditionFields($select) {
var type = $select.val();
var $row = $select.closest('.bdfg-condition-row');
var $valueFields = $row.find('.condition-value-field > div');
var $operators = $row.find('.condition-operator option');

// 隐藏所有值字段
$valueFields.hide();

// 根据条件类型显示相应的值字段
if (type === 'day_of_week') {
$row.find('.condition-day-of-week').show();

// 启用/禁用操作符
$operators.prop('disabled', false);
$operators.filter(function() {
return ['greater_than', 'less_than', 'contains'].indexOf($(this).val()) !== -1;
}).prop('disabled', true);

} else if (type === 'time_of_day') {
$row.find('.condition-time-of-day').show();

// 启用所有操作符
$operators.prop('disabled', false);
$operators.filter(function() {
return ['contains'].indexOf($(this).val()) !== -1;
}).prop('disabled', true);

} else if (type === 'customer_order_count' || type === 'customer_spent_amount') {
$row.find('.condition-numeric').show();

// 启用所有操作符
$operators.prop('disabled', false);
$operators.filter(function() {
return ['contains'].indexOf($(this).val()) !== -1;
}).prop('disabled', true);
}

// 如果当前选中的操作符被禁用,则重置为第一个可用操作符
var $currentOperator = $row.find('.condition-operator option:selected');
if ($currentOperator.prop('disabled')) {
$row.find('.condition-operator option:not(:disabled)').first().prop('selected', true);
}
}
}

// 初始化日期选择器
function initDatepickers() {
$('.bdfg-datepicker').datepicker({
dateFormat: bdfg_params.date_format,
changeMonth: true,
changeYear: true
});
}

// 初始化Select2
function initSelect2() {
// 多选框使用Select2
$('.bdfg-multiselect').select2();

// 产品选择器
$('.bdfg-product-select').select2({
ajax: {
url: bdfg_params.ajax_url,
dataType: 'json',
delay: 250,
data: function(params) {
return {
term: params.term,
action: 'bdfg_search_products',
nonce: bdfg_params.nonce
};
},
processResults: function(data) {
return {
results: data.results
};
},
cache: true
},
minimumInputLength: 3,
placeholder: bdfg_params.i18n.search_products
});

// 用户选择器
$('.bdfg-user-select').select2({
ajax: {
url: bdfg_params.ajax_url,
dataType: 'json',
delay: 250,
data: function(params) {
return {
term: params.term,
action: 'bdfg_search_users',
nonce: bdfg_params.nonce
};
},
processResults: function(data) {
return {
results: data.results
};
},
cache: true
},
minimumInputLength: 3,
placeholder: bdfg_params.i18n.search_users
});
}

// 初始化测试折扣功能
function initTestDiscount() {
$('#run-test').on('click', function() {
var $btn = $(this);
var userId = $('#test-user').val();
var productId = $('#test-product').val();
var quantity = $('#test-quantity').val();

if (!userId || !productId) {
alert(bdfg_params.i18n.select_user_product);
return;
}

// 显示加载状态
$btn.prop('disabled', true).text('测试中...');
$('#test-results').hide();

// 发送Ajax请求
$.ajax({
url: bdfg_params.ajax_url,
type: 'POST',
data: {
action: 'bdfg_test_discount_rule',
nonce: bdfg_params.nonce,
user_id: userId,
product_id: productId,
quantity: quantity
},
success: function(response) {
// 恢复按钮状态
$btn.prop('disabled', false).text('测试折扣');

if (response.success) {
// 格式化测试结果
var html = '<div class="bdfg-test-result">';

// 基本信息
html += '<h4>基本信息</h4>';
html += '<table class="widefat" cellspacing="0">';
html += '<tr><td>测试时间:</td><td>' + response.timestamp + '</td></tr>';
html += '<tr><td>用户:</td><td>' + response.user.name + ' (' + response.user.login + ')</td></tr>';
html += '<tr><td>用户角色:</td><td>' + response.user.roles + '</td></tr>';
html += '<tr><td>产品:</td><td>' + response.product.name + ' (#' + response.product.id + ')</td></tr>';
html += '<tr><td>原价:</td><td>' + response.product.original_price_formatted + '</td></tr>';
html += '<tr><td>数量:</td><td>' + response.product.quantity + '</td></tr>';
html += '</table>';

// 折扣结果
html += '<h4>折扣结果</h4>';
html += '<table class="widefat" cellspacing="0">';

if (response.discount.applied) {
html += '<tr><td>应用折扣:</td><td><span style="color:green">是</span></td></tr>';
html += '<tr><td>折扣金额:</td><td>' + response.discount.discount_amount_formatted + ' (' + response.discount.discount_percentage + ')</td></tr>';
html += '<tr><td>折扣后价格:</td><td>' + response.discount.discounted_price_formatted + '</td></tr>';
} else {
html += '<tr><td>应用折扣:</td><td><span style="color:red">否</span></td></tr>';
html += '<tr><td colspan="2">没有找到适用的折扣规则</td></tr>';
}

html += '</table>';

// 规则评估结果
if (response.rules && response.rules.length > 0) {
html += '<h4>规则评估</h4>';
html += '<table class="widefat" cellspacing="0">';
html += '<thead><tr><th>规则名称</th><th>是否适用</th><th>折扣金额</th><th>状态</th></tr></thead>';
html += '<tbody>';

$.each(response.rules, function(index, rule) {
html += '<tr>';
html += '<td>' + rule.name + '</td>';

if (rule.is_eligible) {
html += '<td><span style="color:green">是</span></td>';
html += '<td>' + rule.calculated_discount_formatted + '</td>';

if (rule.is_best_discount) {
html += '<td><strong style="color:green">已应用 (最佳折扣)</strong></td>';
} else {
html += '<td>合格但未应用</td>';
}
} else {
html += '<td><span style="color:red">否</span></td>';
html += '<td>0</td>';
html += '<td>' + rule.not_eligible_reason + '</td>';
}

html += '</tr>';
});

html += '</tbody>';
html += '</table>';
}

html += '</div>';

// 显示结果
$('#test-results').show().find('.bdfg-test-output').html(html);
} else {
alert(response.data.message || '测试折扣失败');
}
},
error: function() {
$btn.prop('disabled', false).text('测试折扣');
alert('发生错误,请重试');
}
});
});
}

// 初始化导入导出功能
function initImportExport() {
// 导出设置
$('#export-settings').on('click', function() {
var $btn = $(this);
var $container = $('#export-container');

$btn.prop('disabled', true).text('导出中...');

$.ajax({
url: bdfg_params.ajax_url,
type: 'POST',
data: {
action: 'bdfg_export_settings',
nonce: bdfg_params.nonce
},
success: function(response) {
$btn.prop('disabled', false).text('导出设置');

if (response.success) {
$('#export-data').val(response.data.data);
$container.slideDown();
} else {
alert(response.data.message || '导出设置失败');
}
},
error: function() {
$btn.prop('disabled', false).text('导出设置');
alert('发生错误,请重试');
}
});
});

// 复制导出数据到剪贴板
$('#copy-export').on('click', function() {
var exportData = $('#export-data');
exportData.select();

try {
var successful = document.execCommand('copy');
if (successful) {
alert(bdfg_params.i18n.copied);
} else {
alert(bdfg_params.i18n.copy_failed);
}
} catch (err) {
alert(bdfg_params.i18n.copy_failed);
}
});

// 导入设置
$('#import-settings').on('click', function() {
var $btn = $(this);
var importData = $('#import-data').val();

if (!importData) {
alert('请先粘贴要导入的设置数据');
return;
}

if (!confirm(bdfg_params.i18n.confirm_import)) {
return;
}

$btn.prop('disabled', true).text('导入中...');

$.ajax({
url: bdfg_params.ajax_url,
type: 'POST',
data: {
action: 'bdfg_import_settings',
nonce: bdfg_params.nonce,
import_data: importData
},
success: function(response) {
$btn.prop('disabled', false).text('导入设置');

if (response.success) {
alert(bdfg_params.i18n.import_success);
window.location.reload();
} else {
alert(response.data.message || bdfg_params.i18n.import_error);
}
},
error: function() {
$btn.prop('disabled', false).text('导入设置');
alert('发生错误,请重试');
}
});
});
}

// 初始化首次购买重置功能
function initResetFirstPurchase() {
$('#reset-first-purchase').on('click', function() {
var $btn = $(this);

if (!confirm(bdfg_params.i18n.confirm_reset)) {
return;
}

$btn.prop('disabled', true).text('重置中...');

$.ajax({
url: bdfg_params.ajax_url,
type: 'POST',
data: {
action: 'bdfg_reset_first_purchase',
nonce: bdfg_params.nonce
},
success: function(response) {
$btn.prop('disabled', false).text('重置所有首次购买记录');

if (response.success) {
alert(bdfg_params.i18n.reset_success);
} else {
alert(response.data.message || '重置失败');
}
},
error: function() {
$btn.prop('disabled', false).text('重置所有首次购买记录');
alert('发生错误,请重试');
}
});
});
}

})(jQuery);

Leave a Comment