首页 / 教程文章 / WordPress文创插件实现柔性产品定制选项器开发教程

WordPress文创插件实现柔性产品定制选项器开发教程

本教程详细讲解如何开发WordPress文创产品定制插件,以满足市场对个性化产品的需求。通过模块化设计,实现可灵活配置的颜色、图案、文字等定制选项。内容涵盖开发环境搭建、数据库设计、前后端界面开发、实时预览功能及与WooCommerce的集成,帮助商家为用户提供自主设计文创产品的便捷工具,提升电商体验与销售灵活性。

WordPress文创插件实现柔性产品定制选项器开发教程

一、前言:为什么需要柔性产品定制选项器

在文创产品销售领域,消费者越来越追求个性化和独特性。传统的固定产品选项已无法满足市场需求,柔性产品定制成为文创电商的重要发展方向。通过WordPress插件实现产品定制选项器,可以让用户自由组合设计元素,如颜色、图案、文字、尺寸等,从而创造出独一无二的文创产品。

本教程将带领您从零开始开发一个完整的WordPress文创产品定制插件,实现灵活的产品选项配置功能。我们将采用模块化设计思路,确保代码的可维护性和扩展性。

二、开发环境准备与插件基础结构

首先,我们需要创建一个标准的WordPress插件目录结构:

<?php
/**
 * Plugin Name: 文创产品定制选项器
 * Plugin URI: https://yourwebsite.com/
 * Description: 为WordPress文创产品提供灵活的定制选项功能
 * Version: 1.0.0
 * Author: 您的名称
 * License: GPL v2 or later
 * Text Domain: cultural-product-customizer
 */

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

// 定义插件常量
define('CPC_PLUGIN_PATH', plugin_dir_path(__FILE__));
define('CPC_PLUGIN_URL', plugin_dir_url(__FILE__));
define('CPC_VERSION', '1.0.0');

// 初始化插件
class CulturalProductCustomizer {
    
    private static $instance = null;
    
    public static function get_instance() {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    private function __construct() {
        $this->init_hooks();
    }
    
    private function init_hooks() {
        // 插件激活时执行
        register_activation_hook(__FILE__, array($this, 'activate'));
        
        // 插件停用时执行
        register_deactivation_hook(__FILE__, array($this, 'deactivate'));
        
        // 初始化
        add_action('init', array($this, 'init'));
        
        // 管理员菜单
        add_action('admin_menu', array($this, 'add_admin_menu'));
        
        // 加载脚本和样式
        add_action('wp_enqueue_scripts', array($this, 'enqueue_frontend_assets'));
        add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_assets'));
    }
    
    public function activate() {
        // 创建必要的数据库表
        $this->create_database_tables();
        
        // 设置默认选项
        $this->set_default_options();
        
        // 刷新重写规则
        flush_rewrite_rules();
    }
    
    public function deactivate() {
        // 清理临时数据
        flush_rewrite_rules();
    }
    
    public function init() {
        // 加载文本域
        load_plugin_textdomain('cultural-product-customizer', false, dirname(plugin_basename(__FILE__)) . '/languages');
        
        // 注册自定义文章类型
        $this->register_custom_post_types();
    }
    
    // 其他方法将在后续部分实现
}

// 启动插件
CulturalProductCustomizer::get_instance();
?>

三、数据库设计与选项配置系统

为了实现灵活的选项配置,我们需要设计一个可扩展的数据库结构:

<?php
// 创建数据库表
private function create_database_tables() {
    global $wpdb;
    
    $charset_collate = $wpdb->get_charset_collate();
    $table_name = $wpdb->prefix . 'cpc_product_options';
    
    $sql = "CREATE TABLE IF NOT EXISTS $table_name (
        id mediumint(9) NOT NULL AUTO_INCREMENT,
        product_id bigint(20) NOT NULL,
        option_type varchar(50) NOT NULL,
        option_name varchar(255) NOT NULL,
        option_label varchar(255) NOT NULL,
        option_values text NOT NULL,
        is_required tinyint(1) DEFAULT 0,
        display_order int(11) DEFAULT 0,
        created_at datetime DEFAULT CURRENT_TIMESTAMP,
        PRIMARY KEY (id),
        KEY product_id (product_id)
    ) $charset_collate;";
    
    require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    dbDelta($sql);
    
    // 创建选项值表
    $values_table = $wpdb->prefix . 'cpc_option_values';
    
    $sql2 = "CREATE TABLE IF NOT EXISTS $values_table (
        id mediumint(9) NOT NULL AUTO_INCREMENT,
        option_id mediumint(9) NOT NULL,
        value_key varchar(100) NOT NULL,
        value_label varchar(255) NOT NULL,
        price_adjustment decimal(10,2) DEFAULT 0.00,
        image_url varchar(500) DEFAULT NULL,
        display_order int(11) DEFAULT 0,
        PRIMARY KEY (id),
        KEY option_id (option_id)
    ) $charset_collate;";
    
    dbDelta($sql2);
}

// 注册自定义文章类型
private function register_custom_post_types() {
    // 文创产品自定义文章类型
    register_post_type('cultural_product',
        array(
            'labels' => array(
                'name' => __('文创产品', 'cultural-product-customizer'),
                'singular_name' => __('文创产品', 'cultural-product-customizer')
            ),
            'public' => true,
            'has_archive' => true,
            'supports' => array('title', 'editor', 'thumbnail', 'excerpt'),
            'menu_icon' => 'dashicons-art',
            'rewrite' => array('slug' => 'cultural-products'),
            'show_in_rest' => true,
        )
    );
}
?>

四、后台选项管理界面开发

创建后台管理界面,让商家可以轻松配置产品选项:

<?php
// 添加管理员菜单
public function add_admin_menu() {
    add_menu_page(
        __('文创产品定制', 'cultural-product-customizer'),
        __('文创定制', 'cultural-product-customizer'),
        'manage_options',
        'cpc-dashboard',
        array($this, 'render_dashboard_page'),
        'dashicons-admin-customizer',
        30
    );
    
    add_submenu_page(
        'cpc-dashboard',
        __('产品选项管理', 'cultural-product-customizer'),
        __('选项管理', 'cultural-product-customizer'),
        'manage_options',
        'cpc-options',
        array($this, 'render_options_page')
    );
    
    add_submenu_page(
        'cpc-dashboard',
        __('设置', 'cultural-product-customizer'),
        __('设置', 'cultural-product-customizer'),
        'manage_options',
        'cpc-settings',
        array($this, 'render_settings_page')
    );
}

// 渲染选项管理页面
public function render_options_page() {
    // 检查权限
    if (!current_user_can('manage_options')) {
        wp_die(__('您没有权限访问此页面。', 'cultural-product-customizer'));
    }
    
    // 处理表单提交
    if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['cpc_save_option'])) {
        $this->save_product_option($_POST);
    }
    
    // 获取所有产品
    $products = get_posts(array(
        'post_type' => 'cultural_product',
        'posts_per_page' => -1,
        'post_status' => 'publish'
    ));
    
    // 获取已保存的选项
    $product_id = isset($_GET['product_id']) ? intval($_GET['product_id']) : 0;
    $options = $this->get_product_options($product_id);
    
    // 渲染页面
    ?>
    <div class="wrap">
        <h1><?php echo esc_html__('产品选项管理', 'cultural-product-customizer'); ?></h1>
        
        <div class="cpc-admin-container">
            <!-- 产品选择器 -->
            <div class="cpc-product-selector">
                <label for="cpc-product-select"><?php _e('选择产品:', 'cultural-product-customizer'); ?></label>
                <select id="cpc-product-select" onchange="window.location.href='?page=cpc-options&product_id='+this.value">
                    <option value="0"><?php _e('-- 选择产品 --', 'cultural-product-customizer'); ?></option>
                    <?php foreach ($products as $product): ?>
                        <option value="<?php echo $product->ID; ?>" <?php selected($product_id, $product->ID); ?>>
                            <?php echo esc_html($product->post_title); ?>
                        </option>
                    <?php endforeach; ?>
                </select>
            </div>
            
            <?php if ($product_id): ?>
                <!-- 选项表单 -->
                <form method="post" class="cpc-options-form">
                    <input type="hidden" name="product_id" value="<?php echo $product_id; ?>">
                    
                    <div id="cpc-options-container">
                        <?php foreach ($options as $index => $option): ?>
                            <div class="cpc-option-group" data-index="<?php echo $index; ?>">
                                <h3><?php _e('选项组', 'cultural-product-customizer'); ?> #<?php echo $index + 1; ?></h3>
                                
                                <div class="cpc-form-row">
                                    <label><?php _e('选项类型:', 'cultural-product-customizer'); ?></label>
                                    <select name="options[<?php echo $index; ?>][type]" class="cpc-option-type">
                                        <option value="select" <?php selected($option['type'], 'select'); ?>><?php _e('下拉选择', 'cultural-product-customizer'); ?></option>
                                        <option value="radio" <?php selected($option['type'], 'radio'); ?>><?php _e('单选按钮', 'cultural-product-customizer'); ?></option>
                                        <option value="checkbox" <?php selected($option['type'], 'checkbox'); ?>><?php _e('复选框', 'cultural-product-customizer'); ?></option>
                                        <option value="text" <?php selected($option['type'], 'text'); ?>><?php _e('文本输入', 'cultural-product-customizer'); ?></option>
                                        <option value="image" <?php selected($option['type'], 'image'); ?>><?php _e('图片选择', 'cultural-product-customizer'); ?></option>
                                    </select>
                                </div>
                                
                                <div class="cpc-form-row">
                                    <label><?php _e('选项名称:', 'cultural-product-customizer'); ?></label>
                                    <input type="text" name="options[<?php echo $index; ?>][name]" 
                                           value="<?php echo esc_attr($option['name']); ?>" 
                                           placeholder="例如: color, size">
                                </div>
                                
                                <div class="cpc-form-row">
                                    <label><?php _e('显示标签:', 'cultural-product-customizer'); ?></label>
                                    <input type="text" name="options[<?php echo $index; ?>][label]" 
                                           value="<?php echo esc_attr($option['label']); ?>" 
                                           placeholder="例如: 选择颜色, 选择尺寸">
                                </div>
                                
                                <!-- 选项值区域 -->
                                <div class="cpc-option-values">
                                    <h4><?php _e('选项值:', 'cultural-product-customizer'); ?></h4>
                                    <?php foreach ($option['values'] as $value_index => $value): ?>
                                        <div class="cpc-value-row">
                                            <input type="text" 
                                                   name="options[<?php echo $index; ?>][values][<?php echo $value_index; ?>][key]" 
                                                   value="<?php echo esc_attr($value['key']); ?>" 
                                                   placeholder="值键名">
                                            <input type="text" 
                                                   name="options[<?php echo $index; ?>][values][<?php echo $value_index; ?>][label]" 
                                                   value="<?php echo esc_attr($value['label']); ?>" 
                                                   placeholder="显示标签">
                                            <input type="number" step="0.01" 
                                                   name="options[<?php echo $index; ?>][values][<?php echo $value_index; ?>][price]" 
                                                   value="<?php echo esc_attr($value['price']); ?>" 
                                                   placeholder="价格调整">
                                            <button type="button" class="button cpc-remove-value"><?php _e('删除', 'cultural-product-customizer'); ?></button>
                                        </div>
                                    <?php endforeach; ?>
                                </div>
                                
                                <button type="button" class="button cpc-add-value"><?php _e('添加选项值', 'cultural-product-customizer'); ?></button>
                                <button type="button" class="button button-danger cpc-remove-option"><?php _e('删除此选项', 'cultural-product-customizer'); ?></button>
                            </div>
                        <?php endforeach; ?>
                    </div>
                    
                    <button type="button" id="cpc-add-option" class="button button-primary"><?php _e('添加新选项', 'cultural-product-customizer'); ?></button>
                    
                    <div class="cpc-form-actions">
                        <input type="submit" name="cpc_save_option" class="button button-primary" value="<?php _e('保存选项', 'cultural-product-customizer'); ?>">
                    </div>
                </form>
            <?php endif; ?>
        </div>
    </div>
    <?php
}
?>

五、前端定制器界面实现

前端定制器是用户直接交互的部分,需要良好的用户体验:

<?php
// 前端定制器短码
public function register_shortcodes() {
    add_shortcode('cultural_product_customizer', array($this, 'render_product_customizer'));
}

// 渲染产品定制器
public function render_product_customizer($atts) {
    $atts = shortcode_atts(array(
        'product_id' => 0,
    ), $atts, 'cultural_product_customizer');
    
    $product_id = intval($atts['product_id']);
    
    if (!$product_id) {
        return '<p>' . __('请指定产品ID。', 'cultural-product-customizer') . '</p>';
    }
    
    // 获取产品选项
    $options = $this->get_product_options($product_id);
    
    if (empty($options)) {
        return '<p>' . __('该产品暂无定制选项。', 'cultural-product-customizer') . '</p>';
    }
    
    ob_start();
    ?>
    <div class="cpc-product-customizer" data-product-id="<?php echo $product_id; ?>">
        <div class="cpc-customizer-container">
            <!-- 产品预览区域 -->
            <div class="cpc-preview-area">
                <div class="cpc-product-base">
                    <?php echo get_the_post_thumbnail($product_id, 'large'); ?>
                </div>
                <div class="cpc-customizations"></div>
            </div>
            
            <!-- 选项控制区域 -->
            <div class="cpc-controls-area">
                <h3><?php _e('定制您的产品', 'cultural-product-customizer'); ?></h3>
                
                <form id="cpc-customization-form">
                    <?php foreach ($options as $index => $option): ?>
                        <div class="cpc-option-control" data-option-type="<?php echo esc_attr($option['type']); ?>">
                            <label class="cpc-option-label">
                                <?php echo esc_html($option['label']); ?>
                                <?php if ($option['required']): ?>
                                    <span class="cpc-required">*</span>
                                <?php endif; ?>
                            </label>
                            
                            <div class="cpc-option-input">
                                <?php switch ($option['type']):
                                    case 'select': ?>
                                        <select name="options[<?php echo esc_attr($option['name']); ?>]" 
                                                class="cpc-option-select" 
                                                <?php echo $option['required'] ? 'required' : ''; ?>>
                                            <option value=""><?php _e('请选择', 'cultural-product-customizer'); ?></option>
                                            <?php foreach ($option['values'] as $value): ?>
                                                <option value="<?php echo esc_attr($value['key']); ?>" 
                                                        data-price="<?php echo esc_attr($value['price']); ?>"
                                                        data-image="<?php echo esc_attr($value['image']); ?>">
                                                    <?php echo esc_html($value['label']); ?>
                                                    <?php if ($value['price'] != 0): ?>
                                                        (<?php echo $value['price'] > 0 ? '+' : ''; ?><?php echo get_woocommerce_currency_symbol() . $value['price']; ?>)
                                                    <?php endif; ?>
                                                </option>
                                            <?php endforeach; ?>
                                        </select>
                                        <?php break;
                                    
                                    case 'radio': ?>
                                        <div class="cpc-radio-group">
                                            <?php foreach ($option['values'] as $value): ?>
                                                <label class="cpc-radio-label">
                                                    <input type="radio" 
                                                           name="options[<?php echo esc_attr($option['name']); ?>]" 
                                                           value="<?php echo esc_attr($value['key']); ?>"
                                                           data-price="<?php echo esc_attr($value['price']); ?>"
                                                           data-image="<?php echo esc_attr($value['image']); ?>"
                                                           <?php echo $option['required'] ? 'required' : ''; ?>>
                                                    <span class="cpc-radio-text">
                                                        <?php echo esc_html($value['label']); ?>
                                                        <?php if ($value['price'] != 0): ?>
                                                            <span class="cpc-price-adjustment">
                                                                (<?php echo $value['price'] > 0 ? '+' : ''; ?><?php echo get_woocommerce_currency_symbol() . $value['price']; ?>)
                                                            </span>
                                                        <?php endif; ?>
                                                    </span>
                                                </label>
                                            <?php endforeach; ?>
                                        </div>
                                        <?php break;
                                    
                                    case 'image': ?>
                                        <div class="cpc-image-selector">
                                            <?php foreach ($option['values'] as $value): ?>
                                                <div class="cpc-image-option" 
                                                     data-value="<?php echo esc_attr($value['key']); ?>"
                                                        data-price="<?php echo esc_attr($value['price']); ?>">
                                                    <?php if (!empty($value['image'])): ?>
                                                        <img src="<?php echo esc_url($value['image']); ?>" 
                                                             alt="<?php echo esc_attr($value['label']); ?>">
                                                    <?php endif; ?>
                                                    <span class="cpc-image-label"><?php echo esc_html($value['label']); ?></span>
                                                </div>
                                            <?php endforeach; ?>
                                        </div>
                                        <?php break;
                                    
                                    case 'text': ?>
                                        <input type="text" 
                                               name="options[<?php echo esc_attr($option['name']); ?>]" 
                                               class="cpc-text-input" 
                                               placeholder="<?php _e('请输入', 'cultural-product-customizer'); ?>"
                                               <?php echo $option['required'] ? 'required' : ''; ?>>
                                        <?php break;
                                    
                                    case 'checkbox': ?>
                                        <div class="cpc-checkbox-group">
                                            <?php foreach ($option['values'] as $value): ?>
                                                <label class="cpc-checkbox-label">
                                                    <input type="checkbox" 
                                                           name="options[<?php echo esc_attr($option['name']); ?>][]" 
                                                           value="<?php echo esc_attr($value['key']); ?>"
                                                           data-price="<?php echo esc_attr($value['price']); ?>"
                                                           data-image="<?php echo esc_attr($value['image']); ?>">
                                                    <span class="cpc-checkbox-text">
                                                        <?php echo esc_html($value['label']); ?>
                                                        <?php if ($value['price'] != 0): ?>
                                                            <span class="cpc-price-adjustment">
                                                                (<?php echo $value['price'] > 0 ? '+' : ''; ?><?php echo get_woocommerce_currency_symbol() . $value['price']; ?>)
                                                            </span>
                                                        <?php endif; ?>
                                                    </span>
                                                </label>
                                            <?php endforeach; ?>
                                        </div>
                                        <?php break;
                                endswitch; ?>
                            </div>
                            
                            <?php if (!empty($option['description'])): ?>
                                <p class="cpc-option-description"><?php echo esc_html($option['description']); ?></p>
                            <?php endif; ?>
                        </div>
                    <?php endforeach; ?>
                    
                    <!-- 价格汇总 -->
                    <div class="cpc-price-summary">
                        <h4><?php _e('价格详情', 'cultural-product-customizer'); ?></h4>
                        <div class="cpc-base-price">
                            <span><?php _e('基础价格:', 'cultural-product-customizer'); ?></span>
                            <span class="cpc-base-price-amount"><?php echo get_woocommerce_currency_symbol(); ?><span id="cpc-base-price">0.00</span></span>
                        </div>
                        <div class="cpc-options-price">
                            <span><?php _e('选项加价:', 'cultural-product-customizer'); ?></span>
                            <span class="cpc-options-price-amount"><?php echo get_woocommerce_currency_symbol(); ?><span id="cpc-options-total">0.00</span></span>
                        </div>
                        <div class="cpc-total-price">
                            <span><?php _e('总计:', 'cultural-product-customizer'); ?></span>
                            <span class="cpc-total-price-amount"><?php echo get_woocommerce_currency_symbol(); ?><span id="cpc-final-price">0.00</span></span>
                        </div>
                    </div>
                    
                    <!-- 添加到购物车 -->
                    <div class="cpc-add-to-cart">
                        <input type="hidden" name="customizations" id="cpc-customizations-data">
                        <button type="button" id="cpc-update-preview" class="button">
                            <?php _e('更新预览', 'cultural-product-customizer'); ?>
                        </button>
                        <button type="submit" id="cpc-add-to-cart" class="button button-primary">
                            <?php _e('添加到购物车', 'cultural-product-customizer'); ?>
                        </button>
                    </div>
                </form>
            </div>
        </div>
    </div>
    <?php
    
    return ob_get_clean();
}
?>

六、JavaScript交互与实时预览功能

实现前端JavaScript交互逻辑,提供实时预览和价格计算:

// 文件: assets/js/frontend-customizer.js
jQuery(document).ready(function($) {
    'use strict';
    
    // 初始化定制器
    function initProductCustomizer() {
        const $customizer = $('.cpc-product-customizer');
        if (!$customizer.length) return;
        
        const productId = $customizer.data('product-id');
        let basePrice = 0;
        let optionsTotal = 0;
        
        // 获取基础价格
        $.ajax({
            url: cpc_ajax.ajax_url,
            type: 'POST',
            data: {
                action: 'cpc_get_product_price',
                product_id: productId,
                security: cpc_ajax.nonce
            },
            success: function(response) {
                if (response.success) {
                    basePrice = parseFloat(response.data.price);
                    $('#cpc-base-price').text(basePrice.toFixed(2));
                    updateTotalPrice();
                }
            }
        });
        
        // 选项变更事件
        $customizer.on('change', '.cpc-option-select, .cpc-radio-group input, .cpc-text-input', handleOptionChange);
        $customizer.on('click', '.cpc-image-option', handleImageSelect);
        $customizer.on('change', '.cpc-checkbox-group input', handleCheckboxChange);
        
        // 更新预览按钮
        $('#cpc-update-preview').on('click', updateProductPreview);
        
        // 添加到购物车
        $('#cpc-add-to-cart').on('click', addToCart);
        
        // 处理选项变更
        function handleOptionChange() {
            const $option = $(this).closest('.cpc-option-control');
            const optionType = $option.data('option-type');
            const optionName = $option.find('[name^="options"]').attr('name').match(/[(.*?)]/)[1];
            
            let selectedValue = '';
            let priceAdjustment = 0;
            
            switch (optionType) {
                case 'select':
                    const $select = $option.find('select');
                    selectedValue = $select.val();
                    priceAdjustment = parseFloat($select.find('option:selected').data('price') || 0);
                    break;
                    
                case 'radio':
                    const $selectedRadio = $option.find('input:checked');
                    selectedValue = $selectedRadio.val();
                    priceAdjustment = parseFloat($selectedRadio.data('price') || 0);
                    break;
                    
                case 'text':
                    selectedValue = $option.find('input').val();
                    // 文本选项可以设置每字符价格
                    priceAdjustment = selectedValue.length * 0.5; // 示例:每字符0.5元
                    break;
            }
            
            // 更新价格
            updateOptionPrice(optionName, priceAdjustment);
            updateTotalPrice();
        }
        
        // 处理图片选择
        function handleImageSelect() {
            const $option = $(this).closest('.cpc-option-control');
            const $allOptions = $option.find('.cpc-image-option');
            
            // 移除其他选项的选中状态
            $allOptions.removeClass('selected');
            
            // 设置当前选项为选中
            $(this).addClass('selected');
            
            const optionName = $option.find('[name^="options"]').attr('name').match(/[(.*?)]/)[1];
            const priceAdjustment = parseFloat($(this).data('price') || 0);
            const imageUrl = $(this).find('img').attr('src');
            
            // 更新价格
            updateOptionPrice(optionName, priceAdjustment);
            updateTotalPrice();
            
            // 更新预览
            if (imageUrl) {
                updatePreviewImage(optionName, imageUrl);
            }
        }
        
        // 处理复选框变更
        function handleCheckboxChange() {
            const $option = $(this).closest('.cpc-option-control');
            const optionName = $option.find('[name^="options"]').attr('name').match(/[(.*?)]/)[1];
            
            let totalAdjustment = 0;
            $option.find('input:checked').each(function() {
                totalAdjustment += parseFloat($(this).data('price') || 0);
            });
            
            // 更新价格
            updateOptionPrice(optionName, totalAdjustment);
            updateTotalPrice();
        }
        
        // 更新选项价格
        function updateOptionPrice(optionName, adjustment) {
            // 存储每个选项的价格调整
            if (!window.cpcOptionPrices) {
                window.cpcOptionPrices = {};
            }
            window.cpcOptionPrices[optionName] = adjustment;
            
            // 重新计算总选项价格
            optionsTotal = 0;
            for (const key in window.cpcOptionPrices) {
                optionsTotal += window.cpcOptionPrices[key];
            }
            
            $('#cpc-options-total').text(optionsTotal.toFixed(2));
        }
        
        // 更新总价格
        function updateTotalPrice() {
            const totalPrice = basePrice + optionsTotal;
            $('#cpc-final-price').text(totalPrice.toFixed(2));
        }
        
        // 更新产品预览
        function updateProductPreview() {
            const customizations = {};
            
            // 收集所有选项值
            $('.cpc-option-control').each(function() {
                const $control = $(this);
                const optionType = $control.data('option-type');
                const optionName = $control.find('[name^="options"]').attr('name').match(/[(.*?)]/)[1];
                
                let value = '';
                
                switch (optionType) {
                    case 'select':
                        value = $control.find('select').val();
                        break;
                    case 'radio':
                        value = $control.find('input:checked').val();
                        break;
                    case 'text':
                        value = $control.find('input').val();
                        break;
                    case 'checkbox':
                        const values = [];
                        $control.find('input:checked').each(function() {
                            values.push($(this).val());
                        });
                        value = values.join(',');
                        break;
                    case 'image':
                        value = $control.find('.cpc-image-option.selected').data('value');
                        break;
                }
                
                if (value) {
                    customizations[optionName] = value;
                }
            });
            
            // 发送AJAX请求更新预览
            $.ajax({
                url: cpc_ajax.ajax_url,
                type: 'POST',
                data: {
                    action: 'cpc_update_preview',
                    product_id: productId,
                    customizations: customizations,
                    security: cpc_ajax.nonce
                },
                success: function(response) {
                    if (response.success) {
                        // 更新预览区域
                        $('.cpc-customizations').html(response.data.preview_html);
                    }
                }
            });
        }
        
        // 添加到购物车
        function addToCart() {
            const customizations = {};
            let isValid = true;
            
            // 验证必填选项
            $('.cpc-option-control').each(function() {
                const $control = $(this);
                const isRequired = $control.find('.cpc-required').length > 0;
                const optionType = $control.data('option-type');
                
                if (isRequired) {
                    let hasValue = false;
                    
                    switch (optionType) {
                        case 'select':
                            hasValue = !!$control.find('select').val();
                            break;
                        case 'radio':
                            hasValue = $control.find('input:checked').length > 0;
                            break;
                        case 'text':
                            hasValue = !!$control.find('input').val().trim();
                            break;
                        case 'checkbox':
                            hasValue = $control.find('input:checked').length > 0;
                            break;
                        case 'image':
                            hasValue = $control.find('.cpc-image-option.selected').length > 0;
                            break;
                    }
                    
                    if (!hasValue) {
                        isValid = false;
                        $control.addClass('cpc-error');
                    } else {
                        $control.removeClass('cpc-error');
                    }
                }
                
                // 收集数据
                const optionName = $control.find('[name^="options"]').attr('name').match(/[(.*?)]/)[1];
                let value = '';
                
                switch (optionType) {
                    case 'select':
                        value = $control.find('select').val();
                        break;
                    case 'radio':
                        value = $control.find('input:checked').val();
                        break;
                    case 'text':
                        value = $control.find('input').val();
                        break;
                    case 'checkbox':
                        const values = [];
                        $control.find('input:checked').each(function() {
                            values.push($(this).val());
                        });
                        value = values.join(',');
                        break;
                    case 'image':
                        value = $control.find('.cpc-image-option.selected').data('value');
                        break;
                }
                
                if (value) {
                    customizations[optionName] = value;
                }
            });
            
            if (!isValid) {
                alert('请填写所有必填选项');
                return;
            }
            
            // 添加到购物车
            $.ajax({
                url: cpc_ajax.ajax_url,
                type: 'POST',
                data: {
                    action: 'cpc_add_to_cart',
                    product_id: productId,
                    customizations: customizations,
                    options_total: optionsTotal,
                    security: cpc_ajax.nonce
                },
                success: function(response) {
                    if (response.success) {
                        // 显示成功消息
                        alert('产品已添加到购物车!');
                        
                        // 可选:跳转到购物车页面
                        if (response.data.redirect) {
                            window.location.href = response.data.redirect;
                        }
                    } else {
                        alert('添加失败:' + response.data.message);
                    }
                }
            });
        }
        
        // 更新预览图片
        function updatePreviewImage(optionName, imageUrl) {
            const $preview = $('.cpc-customizations');
            let $layer = $preview.find(`.cpc-layer-${optionName}`);
            
            if (!$layer.length) {
                $layer = $('<div>', {
                    class: `cpc-preview-layer cpc-layer-${optionName}`,
                    css: {
                        position: 'absolute',
                        top: 0,
                        left: 0,
                        'z-index': 10
                    }
                }).appendTo($preview);
            }
            
            $layer.html(`<img src="${imageUrl}" alt="${optionName}" style="max-width: 100%;">`);
        }
    }
    
    // 初始化
    initProductCustomizer();
});

七、与WooCommerce集成

将定制器与WooCommerce购物车和订单系统集成:

<?php
// 集成WooCommerce
public function integrate_woocommerce() {
    // 检查WooCommerce是否激活
    if (!class_exists('WooCommerce')) {
        return;
    }
    
    // 添加到购物车处理
    add_action('woocommerce_add_to_cart', array($this, 'handle_custom_product_add_to_cart'), 10, 6);
    
    // 在购物车中显示定制选项
    add_filter('woocommerce_get_item_data', array($this, 'display_customizations_in_cart'), 10, 2);
    
    // 将定制数据保存到订单项
    add_action('woocommerce_checkout_create_order_line_item', array($this, 'save_customizations_to_order_item'), 10, 4);
    
    // 在订单详情中显示定制选项
    add_action('woocommerce_order_item_meta_end', array($this, 'display_customizations_in_order'), 10, 3);
    
    // 价格计算
    add_action('woocommerce_before_calculate_totals', array($this, 'calculate_custom_product_price'), 10, 1);
}

// 处理添加到购物车
public function handle_custom_product_add_to_cart($cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data) {
    // 检查是否有定制数据
    if (isset($_POST['customizations']) && !empty($_POST['customizations'])) {
        $customizations = json_decode(stripslashes($_POST['customizations']), true);
        
        if ($customizations) {
            WC()->cart->cart_contents[$cart_item_key]['customizations'] = $customizations;
            
            // 保存选项总价
            if (isset($_POST['options_total'])) {
                WC()->cart->cart_contents[$cart_item_key]['options_total'] = floatval($_POST['options_total']);
            }
        }
    }
}

// 在购物车中显示定制选项
public function display_customizations_in_cart($item_data, $cart_item) {
    if (isset($cart_item['customizations']) && is_array($cart_item['customizations'])) {
        foreach ($cart_item['customizations'] as $key => $value) {
            if (!empty($value)) {
                // 获取选项标签
                $option_label = $this->get_option_label($cart_item['product_id'], $key);
                
                $item_data[] = array(
                    'name' => $option_label ?: ucfirst(str_replace('_', ' ', $key)),
                    'value' => $this->format_customization_value($cart_item['product_id'], $key, $value)
                );
            }
        }
    }
    
    return $item_data;
}

// 保存定制数据到订单项
public function save_customizations_to_order_item($item, $cart_item_key, $values, $order) {
    if (isset($values['customizations'])) {
        $item->add_meta_data('_customizations', $values['customizations']);
    }
    
    if (isset($values['options_total'])) {
        $item->add_meta_data('_options_total', $values['options_total']);
    }
}

// 计算定制产品价格
public function calculate_custom_product_price($cart) {
本文来自网络投稿,不代表本站点的立场,转载请注明出处:https://www.gongxiangcang.com/6569.html

溯源库®作者

漳州柔性供应链服务有限公司 小批量订单定制化服务商( 投稿邮箱:vip@jiaochengku.com)
上一篇
下一篇

为您推荐

联系我们

联系我们

18559313275

在线咨询: QQ交谈

邮箱: vip@suyuanku.com

工作时间:周一至周五,9:00-17:30,节假日休息
关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部