文章目录
-
- 在当今电商竞争激烈的环境中,个性化包装已成为提升品牌形象和客户体验的重要手段。然而,许多中小型电商企业面临一个共同难题:传统包装解决方案往往需要大批量定制,成本高昂且缺乏灵活性。 本教程将指导您开发一个支持小批量个性化包装的WordPress插件,让店主能够为不同客户提供独特的包装体验,同时保持成本可控。该插件将允许客户在结账时选择包装样式、添加个性化信息,并实时查看包装效果预览。
- 在开始开发之前,请确保您已准备好以下环境: WordPress 5.0+ 安装 PHP 7.2+ 环境 基础的HTML、CSS、JavaScript知识 代码编辑器(如VS Code、Sublime Text等)
- 首先,我们需要创建插件的基本文件结构: custom-packaging-helper/ │ ├── custom-packaging-helper.php # 主插件文件 ├── includes/ │ ├── class-admin-settings.php # 后台设置类 │ ├── class-packaging-manager.php # 包装管理类 │ └── class-checkout-integration.php # 结账集成类 ├── assets/ │ ├── css/ │ │ └── admin-style.css # 后台样式 │ ├── js/ │ │ └── packaging-preview.js # 包装预览脚本 │ └── images/ # 包装模板图片 ├── templates/ │ └── packaging-preview.php # 预览模板 └── uninstall.php # 卸载脚本
- 创建主插件文件 custom-packaging-helper.php: <?php /** * Plugin Name: 小批量个性化包装助手 * Plugin URI: https://yourwebsite.com/custom-packaging-helper * Description: 为WooCommerce提供小批量个性化包装解决方案 * Version: 1.0.0 * Author: 您的名字 * License: GPL v2 or later * Text Domain: custom-packaging-helper */ // 防止直接访问 if (!defined('ABSPATH')) { exit; } // 定义插件常量 define('CPH_VERSION', '1.0.0'); define('CPH_PLUGIN_DIR', plugin_dir_path(__FILE__)); define('CPH_PLUGIN_URL', plugin_dir_url(__FILE__)); // 检查WooCommerce是否激活 function cph_check_woocommerce() { if (!class_exists('WooCommerce')) { add_action('admin_notices', function() { ?> <div class="notice notice-error"> <p><?php _e('小批量个性化包装插件需要WooCommerce支持,请先安装并激活WooCommerce插件。', 'custom-packaging-helper'); ?></p> </div> <?php }); return false; } return true; } // 初始化插件 function cph_init() { if (!cph_check_woocommerce()) { return; } // 加载必要文件 require_once CPH_PLUGIN_DIR . 'includes/class-packaging-manager.php'; require_once CPH_PLUGIN_DIR . 'includes/class-admin-settings.php'; require_once CPH_PH_PLUGIN_DIR . 'includes/class-checkout-integration.php'; // 初始化核心类 new CPH_Packaging_Manager(); new CPH_Admin_Settings(); new CPH_Checkout_Integration(); } add_action('plugins_loaded', 'cph_init'); // 激活插件时的操作 function cph_activate() { // 创建必要的数据库表 global $wpdb; $charset_collate = $wpdb->get_charset_collate(); $table_name = $wpdb->prefix . 'cph_packaging_designs'; $sql = "CREATE TABLE IF NOT EXISTS $table_name ( id mediumint(9) NOT NULL AUTO_INCREMENT, design_name varchar(100) NOT NULL, design_type varchar(50) NOT NULL, thumbnail_url varchar(255), price_additional decimal(10,2) DEFAULT 0.00, max_characters int DEFAULT 50, is_active tinyint(1) DEFAULT 1, created_at datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ) $charset_collate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); // 设置默认选项 add_option('cph_enable_plugin', 'yes'); add_option('cph_minimum_order_amount', 0); add_option('cph_default_packaging_price', 2.99); } register_activation_hook(__FILE__, 'cph_activate'); // 停用插件时的操作 function cph_deactivate() { // 清理临时数据 wp_clear_scheduled_hook('cph_daily_cleanup'); } register_deactivation_hook(__FILE__, 'cph_deactivate');
- 创建 includes/class-packaging-manager.php: <?php /** * 包装设计管理类 * 处理包装设计的CRUD操作 */ class CPH_Packaging_Manager { public function __construct() { add_action('init', array($this, 'register_post_type')); add_action('add_meta_boxes', array($this, 'add_packaging_meta_boxes')); add_action('save_post', array($this, 'save_packaging_meta')); } // 注册自定义帖子类型 public function register_post_type() { $labels = array( 'name' => __('包装设计', 'custom-packaging-helper'), 'singular_name' => __('包装设计', 'custom-packaging-helper'), 'menu_name' => __('个性化包装', 'custom-packaging-helper'), 'add_new' => __('添加新设计', 'custom-packaging-helper'), 'add_new_item' => __('添加新包装设计', 'custom-packaging-helper'), 'edit_item' => __('编辑包装设计', 'custom-packaging-helper'), 'new_item' => __('新包装设计', 'custom-packaging-helper'), ); $args = array( 'labels' => $labels, 'public' => false, 'publicly_queryable' => false, 'show_ui' => true, 'show_in_menu' => true, 'query_var' => true, 'capability_type' => 'post', 'has_archive' => false, 'hierarchical' => false, 'menu_position' => 56, 'menu_icon' => 'dashicons-archive', 'supports' => array('title', 'thumbnail'), ); register_post_type('cph_packaging', $args); } // 添加元数据框 public function add_packaging_meta_boxes() { add_meta_box( 'cph_packaging_details', __('包装设计详情', 'custom-packaging-helper'), array($this, 'render_packaging_meta_box'), 'cph_packaging', 'normal', 'high' ); } // 渲染元数据框内容 public function render_packaging_meta_box($post) { // 添加安全验证 wp_nonce_field('cph_save_packaging_data', 'cph_packaging_nonce'); // 获取现有值 $price = get_post_meta($post->ID, '_cph_packaging_price', true); $type = get_post_meta($post->ID, '_cph_packaging_type', true); $max_chars = get_post_meta($post->ID, '_cph_max_characters', true); $is_active = get_post_meta($post->ID, '_cph_is_active', true); // 设置默认值 $price = $price ? $price : 2.99; $max_chars = $max_chars ? $max_chars : 50; $is_active = $is_active === '' ? 1 : $is_active; ?> <div class="cph-metabox"> <p> <label for="cph_packaging_price"><?php _e('附加价格 (USD):', 'custom-packaging-helper'); ?></label> <input type="number" step="0.01" min="0" id="cph_packaging_price" name="cph_packaging_price" value="<?php echo esc_attr($price); ?>" /> </p> <p> <label for="cph_packaging_type"><?php _e('包装类型:', 'custom-packaging-helper'); ?></label> <select id="cph_packaging_type" name="cph_packaging_type"> <option value="birthday" <?php selected($type, 'birthday'); ?>><?php _e('生日主题', 'custom-packaging-helper'); ?></option> <option value="holiday" <?php selected($type, 'holiday'); ?>><?php _e('节日主题', 'custom-packaging-helper'); ?></option> <option value="elegant" <?php selected($type, 'elegant'); ?>><?php _e('优雅简约', 'custom-packaging-helper'); ?></option> <option value="custom" <?php selected($type, 'custom'); ?>><?php _e('自定义设计', 'custom-packaging-helper'); ?></option> </select> </p> <p> <label for="cph_max_characters"><?php _e('最大字符数:', 'custom-packaging-helper'); ?></label> <input type="number" min="0" max="200" id="cph_max_characters" name="cph_max_characters" value="<?php echo esc_attr($max_chars); ?>" /> <span class="description"><?php _e('个性化信息的最大字符限制', 'custom-packaging-helper'); ?></span> </p> <p> <label for="cph_is_active"> <input type="checkbox" id="cph_is_active" name="cph_is_active" value="1" <?php checked($is_active, 1); ?> /> <?php _e('启用此包装设计', 'custom-packaging-helper'); ?> </label> </p> </div> <?php } // 保存元数据 public function save_packaging_meta($post_id) { // 检查安全验证 if (!isset($_POST['cph_packaging_nonce']) || !wp_verify_nonce($_POST['cph_packaging_nonce'], 'cph_save_packaging_data')) { return; } // 检查自动保存 if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return; } // 检查权限 if (!current_user_can('edit_post', $post_id)) { return; } // 保存字段 $fields = array( 'cph_packaging_price', 'cph_packaging_type', 'cph_max_characters', 'cph_is_active' ); foreach ($fields as $field) { if (isset($_POST[$field])) { $value = sanitize_text_field($_POST[$field]); update_post_meta($post_id, '_' . $field, $value); } } } // 获取可用的包装设计 public static function get_available_designs() { $args = array( 'post_type' => 'cph_packaging', 'posts_per_page' => -1, 'meta_query' => array( array( 'key' => '_cph_is_active', 'value' => '1', 'compare' => '=' ) ) ); $designs = get_posts($args); $result = array(); foreach ($designs as $design) { $result[] = array( 'id' => $design->ID, 'name' => $design->post_title, 'price' => get_post_meta($design->ID, '_cph_packaging_price', true), 'type' => get_post_meta($design->ID, '_cph_packaging_type', true), 'max_chars' => get_post_meta($design->ID, '_cph_max_characters', true), 'thumbnail' => get_the_post_thumbnail_url($design->ID, 'medium') ); } return $result; } }
- 创建 includes/class-checkout-integration.php: <?php /** * 结账页面集成类 * 在WooCommerce结账页面添加个性化包装选项 */ class CPH_Checkout_Integration { public function __construct() { // 在结账页面添加包装选项 add_action('woocommerce_before_order_notes', array($this, 'add_packaging_options')); // 验证并保存包装选择 add_action('woocommerce_checkout_process', array($this, 'validate_packaging_options')); add_action('woocommerce_checkout_update_order_meta', array($this, 'save_packaging_options')); // 在订单详情页显示包装信息 add_action('woocommerce_order_details_after_order_table', array($this, 'display_packaging_in_order')); // 添加包装费用到购物车 add_action('woocommerce_cart_calculate_fees', array($this, 'add_packaging_fee')); } // 在结账页面添加包装选项 public function add_packaging_options($checkout) { $designs = CPH_Packaging_Manager::get_available_designs(); if (empty($designs)) { return; } echo '<div id="cph-packaging-options">'; echo '<h3>' . __('个性化包装选项', 'custom-packaging-helper') . '</h3>'; // 包装设计选择 woocommerce_form_field('cph_packaging_design', array( 'type' => 'select', 'class' => array('form-row-wide'), 'label' => __('选择包装设计', 'custom-packaging-helper'), 'options' => $this->get_design_options($designs), 'required' => false, ), $checkout->get_value('cph_packaging_design')); // 个性化信息输入 woocommerce_form_field('cph_personalized_message', array( 'type' => 'textarea', 'class' => array('form-row-wide'), 'label' => __('个性化信息', 'custom-packaging-helper'), 'placeholder' => __('请输入您想在包装上显示的信息(最多50个字符)', 'custom-packaging-helper'), 'required' => false, 'maxlength' => 50, ), $checkout->get_value('cph_personalized_message')); // 包装预览区域 echo '<div id="cph-preview-area" style="display:none; margin-top:20px; padding:15px; border:1px solid #ddd; border-radius:5px;">'; echo '<h4>' . __('包装预览', 'custom-packaging-helper') . '</h4>'; echo '<div id="cph-preview-content"></div>'; echo '</div>'; echo '</div>'; // 添加预览脚本 $this->add_preview_script($designs); } // 生成设计选项数组 private function get_design_options($designs) { $options = array('' => __('请选择包装设计', 'custom-packaging-helper')); foreach ($designs as $design) { $price_text = $design['price'] > 0 ? sprintf(__(' (+$%s)', 'custom-packaging-helper'), $design['price']) : __(' (免费)', 'custom-packaging-helper'); $options[$design['id']] = $design['name'] . $price_text; } return $options; } // 添加预览JavaScript private function add_preview_script($designs) { ?> <script type="text/javascript"> jQuery(document).ready(function($) { var designs = <?php echo json_encode($designs); ?>; // 当选择包装设计时 $('#cph_packaging_design').change(function() { var designId = $(this).val(); var previewArea = $('#cph-preview-area'); var previewContent = $('#cph-preview-content'); if (designId) { // 查找选中的设计 var selectedDesign = designs.find(function(design) { return design.id == designId; }); if (selectedDesign) { // 显示预览 var previewHtml = '<div class="packaging-preview">'; if (selectedDesign.thumbnail) { previewHtml += '<img src="' + selectedDesign.thumbnail + '" style="max-width:200px; margin-bottom:10px;" />'; } previewHtml += '<p><strong>' + selectedDesign.name + '</strong></p>'; previewHtml += '<p>类型: ' + selectedDesign.type + '</p>'; if (selectedDesign.price > 0) { previewHtml += '<p>附加费用: $' + selectedDesign.price + '</p>'; } previewHtml += '</div>'; previewContent.html(previewHtml); previewArea.show(); } } else { previewArea.hide(); } }); // 实时更新个性化信息预览 $('#cph_personalized_message').on('input', function() { var message = $(this).val(); var charCount = message.length; var maxChars = 50; // 更新字符计数
- // 实时更新个性化信息预览 $('#cph_personalized_message').on('input', function() { var message = $(this).val(); var charCount = message.length; var maxChars = 50; // 更新字符计数 var counter = $('#cph-char-counter'); if (counter.length === 0) { $(this).after('<div id="cph-char-counter" style="font-size:12px; color:#666;"></div>'); counter = $('#cph-char-counter'); } counter.text('字符数: ' + charCount + '/' + maxChars); // 如果选择了包装设计,更新预览 if ($('#cph_packaging_design').val()) { var previewContent = $('#cph-preview-content'); var messagePreview = previewContent.find('.personalized-message'); if (messagePreview.length === 0) { previewContent.append('<div class="personalized-message" style="margin-top:10px; padding:10px; background:#f5f5f5; border-radius:3px;"></div>'); messagePreview = previewContent.find('.personalized-message'); } messagePreview.html('<strong>个性化信息:</strong><br>' + message); } }); }); </script> <?php } // 验证包装选项 public function validate_packaging_options() { $design_id = isset($_POST['cph_packaging_design']) ? intval($_POST['cph_packaging_design']) : 0; $message = isset($_POST['cph_personalized_message']) ? sanitize_textarea_field($_POST['cph_personalized_message']) : ''; if ($design_id > 0) { // 获取设计详情 $design = get_post($design_id); if (!$design || $design->post_type !== 'cph_packaging') { wc_add_notice(__('选择的包装设计无效。', 'custom-packaging-helper'), 'error'); return; } // 检查设计是否启用 $is_active = get_post_meta($design_id, '_cph_is_active', true); if (!$is_active) { wc_add_notice(__('选择的包装设计暂不可用。', 'custom-packaging-helper'), 'error'); return; } // 验证消息长度 $max_chars = get_post_meta($design_id, '_cph_max_characters', true); $max_chars = $max_chars ? intval($max_chars) : 50; if (strlen($message) > $max_chars) { wc_add_notice(sprintf(__('个性化信息不能超过%d个字符。', 'custom-packaging-helper'), $max_chars), 'error'); } } } // 保存包装选项到订单 public function save_packaging_options($order_id) { if (isset($_POST['cph_packaging_design'])) { $design_id = intval($_POST['cph_packaging_design']); if ($design_id > 0) { // 保存设计ID update_post_meta($order_id, '_cph_packaging_design_id', $design_id); // 保存设计名称和价格 $design_name = get_the_title($design_id); $design_price = get_post_meta($design_id, '_cph_packaging_price', true); update_post_meta($order_id, '_cph_packaging_design_name', $design_name); update_post_meta($order_id, '_cph_packaging_design_price', $design_price); // 保存个性化信息 if (isset($_POST['cph_personalized_message'])) { $message = sanitize_textarea_field($_POST['cph_personalized_message']); update_post_meta($order_id, '_cph_personalized_message', $message); } } } } // 在订单详情页显示包装信息 public function display_packaging_in_order($order) { $design_id = get_post_meta($order->get_id(), '_cph_packaging_design_id', true); if ($design_id) { echo '<section class="cph-order-packaging-details">'; echo '<h2>' . __('个性化包装详情', 'custom-packaging-helper') . '</h2>'; echo '<table class="woocommerce-table woocommerce-table--order-details shop_table order_details">'; echo '<tbody>'; $design_name = get_post_meta($order->get_id(), '_cph_packaging_design_name', true); $design_price = get_post_meta($order->get_id(), '_cph_packaging_design_price', true); $message = get_post_meta($order->get_id(), '_cph_personalized_message', true); echo '<tr>'; echo '<th scope="row">' . __('包装设计', 'custom-packaging-helper') . ':</th>'; echo '<td>' . esc_html($design_name) . '</td>'; echo '</tr>'; if ($message) { echo '<tr>'; echo '<th scope="row">' . __('个性化信息', 'custom-packaging-helper') . ':</th>'; echo '<td>' . nl2br(esc_html($message)) . '</td>'; echo '</tr>'; } echo '</tbody>'; echo '</table>'; echo '</section>'; } } // 添加包装费用到购物车 public function add_packaging_fee($cart) { if (is_admin() && !defined('DOING_AJAX')) { return; } // 检查是否在结账页面且选择了包装设计 if (isset($_POST['post_data'])) { parse_str($_POST['post_data'], $post_data); $design_id = isset($post_data['cph_packaging_design']) ? intval($post_data['cph_packaging_design']) : 0; } else { $design_id = isset($_POST['cph_packaging_design']) ? intval($_POST['cph_packaging_design']) : 0; } if ($design_id > 0) { $design_price = get_post_meta($design_id, '_cph_packaging_price', true); $design_name = get_the_title($design_id); if ($design_price && floatval($design_price) > 0) { $fee = floatval($design_price); $cart->add_fee(__('个性化包装', 'custom-packaging-helper') . ' - ' . $design_name, $fee); } } } }
- 创建 includes/class-admin-settings.php: <?php /** * 后台设置类 * 提供插件配置选项 */ class CPH_Admin_Settings { public function __construct() { add_action('admin_menu', array($this, 'add_admin_menu')); add_action('admin_init', array($this, 'register_settings')); add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts')); } // 添加管理菜单 public function add_admin_menu() { add_submenu_page( 'edit.php?post_type=cph_packaging', __('个性化包装设置', 'custom-packaging-helper'), __('设置', 'custom-packaging-helper'), 'manage_options', 'cph-settings', array($this, 'render_settings_page') ); } // 注册设置 public function register_settings() { register_setting('cph_settings_group', 'cph_general_settings'); add_settings_section( 'cph_general_section', __('常规设置', 'custom-packaging-helper'), array($this, 'render_general_section'), 'cph-settings' ); add_settings_field( 'cph_enable_plugin', __('启用插件', 'custom-packaging-helper'), array($this, 'render_enable_field'), 'cph-settings', 'cph_general_section' ); add_settings_field( 'cph_minimum_order', __('最低订单金额', 'custom-packaging-helper'), array($this, 'render_minimum_order_field'), 'cph-settings', 'cph_general_section' ); add_settings_field( 'cph_default_price', __('默认包装价格', 'custom-packaging-helper'), array($this, 'render_default_price_field'), 'cph-settings', 'cph_general_section' ); add_settings_field( 'cph_packaging_types', __('包装类型', 'custom-packaging-helper'), array($this, 'render_packaging_types_field'), 'cph-settings', 'cph_general_section' ); } // 渲染设置页面 public function render_settings_page() { ?> <div class="wrap"> <h1><?php echo esc_html(get_admin_page_title()); ?></h1> <form method="post" action="options.php"> <?php settings_fields('cph_settings_group'); do_settings_sections('cph-settings'); submit_button(); ?> </form> <div class="cph-stats" style="margin-top: 30px; padding: 20px; background: #f5f5f5; border-radius: 5px;"> <h2><?php _e('使用统计', 'custom-packaging-helper'); ?></h2> <?php $this->render_usage_stats(); ?> </div> </div> <?php } // 渲染常规设置部分 public function render_general_section() { echo '<p>' . __('配置个性化包装插件的基本设置。', 'custom-packaging-helper') . '</p>'; } // 渲染启用字段 public function render_enable_field() { $options = get_option('cph_general_settings'); $enabled = isset($options['enable_plugin']) ? $options['enable_plugin'] : 'yes'; ?> <label> <input type="checkbox" name="cph_general_settings[enable_plugin]" value="yes" <?php checked($enabled, 'yes'); ?> /> <?php _e('启用个性化包装功能', 'custom-packaging-helper'); ?> </label> <?php } // 渲染最低订单金额字段 public function render_minimum_order_field() { $options = get_option('cph_general_settings'); $minimum = isset($options['minimum_order']) ? $options['minimum_order'] : 0; ?> <input type="number" name="cph_general_settings[minimum_order]" value="<?php echo esc_attr($minimum); ?>" min="0" step="0.01" /> <p class="description"><?php _e('设置可以使用个性化包装的最低订单金额(0表示无限制)', 'custom-packaging-helper'); ?></p> <?php } // 渲染默认价格字段 public function render_default_price_field() { $options = get_option('cph_general_settings'); $price = isset($options['default_price']) ? $options['default_price'] : 2.99; ?> <input type="number" name="cph_general_settings[default_price]" value="<?php echo esc_attr($price); ?>" min="0" step="0.01" /> <p class="description"><?php _e('新包装设计的默认价格', 'custom-packaging-helper'); ?></p> <?php } // 渲染包装类型字段 public function render_packaging_types_field() { $options = get_option('cph_general_settings'); $types = isset($options['packaging_types']) ? $options['packaging_types'] : "生日主题n节日主题n优雅简约n自定义设计"; ?> <textarea name="cph_general_settings[packaging_types]" rows="5" cols="50"><?php echo esc_textarea($types); ?></textarea> <p class="description"><?php _e('每行一个包装类型,这些类型将在添加新包装设计时可用', 'custom-packaging-helper'); ?></p> <?php } // 渲染使用统计 public function render_usage_stats() { global $wpdb; // 统计使用个性化包装的订单数量 $order_count = $wpdb->get_var(" SELECT COUNT(DISTINCT post_id) FROM {$wpdb->postmeta} WHERE meta_key = '_cph_packaging_design_id' "); // 统计最受欢迎的包装设计 $popular_designs = $wpdb->get_results(" SELECT meta_value as design_id, COUNT(*) as usage_count FROM {$wpdb->postmeta} WHERE meta_key = '_cph_packaging_design_id' GROUP BY meta_value ORDER BY usage_count DESC LIMIT 5 "); echo '<p><strong>' . __('总使用次数:', 'custom-packaging-helper') . '</strong> ' . intval($order_count) . '</p>'; if (!empty($popular_designs)) { echo '<h3>' . __('最受欢迎的包装设计', 'custom-packaging-helper') . '</h3>'; echo '<ul>'; foreach ($popular_designs as $design) { $design_name = get_the_title($design->design_id); echo '<li>' . esc_html($design_name) . ': ' . intval($design->usage_count) . ' ' . __('次', 'custom-packaging-helper') . '</li>'; } echo '</ul>'; } } // 加载后台脚本和样式 public function enqueue_admin_scripts($hook) { if (strpos($hook, 'cph_packaging') === false && strpos($hook, 'cph-settings') === false) { return; } wp_enqueue_style( 'cph-admin-style', CPH_PLUGIN_URL . 'assets/css/admin-style.css', array(), CPH_VERSION ); wp_enqueue_script( 'cph-admin-script', CPH_PLUGIN_URL . 'assets/js/admin-script.js', array('jquery'), CPH_VERSION, true ); } }
- 创建 assets/js/packaging-preview.js: /** * 包装预览增强功能 * 提供更丰富的包装预览体验 */ (function($) { 'use strict'; // 包装预览类 class PackagingPreview { constructor() { this.init(); } init() { // 监听包装设计选择 $(document).on('change', '#cph_packaging_design', (e) => { this.updateDesignPreview(e.target.value); }); // 监听个性化信息输入 $(document).on('input', '#cph_personalized_message', (e) => { this.updateMessagePreview(e.target.value); }); // 初始化字符计数器 this.initCharCounter(); } // 更新设计预览 updateDesignPreview(designId) { if (!designId) { $('#cph-preview-area').hide(); return; } // 通过AJAX获取设计详情 $.ajax({ url: cph_ajax.ajax_url, type: 'POST', data: { action: 'cph_get_design_details', design_id: designId, nonce: cph_ajax.nonce }, success: (response) => { if (response.success) { this.renderPreview(response.data); } else { console.error('获取设计详情失败:', response.data); } }, error: (xhr, status, error) => { console.error('AJAX请求失败:', error); } }); } // 渲染预览 renderPreview(design) { let previewHtml = ` <div class="packaging-preview-container"> <div class="packaging-image"> ${design.thumbnail ? `<img src="${design.thumbnail}" alt="${design.name}" />` : ''} </div> <div class="packaging-details"> <h4>${design.name}</h4> <p><strong>类型:</strong> ${design.type}</p> <p><strong>价格:</strong> $${design.price}</p> <p><strong>最大字符数:</strong> ${design.max_chars}</p> </div> <div class="packaging-message-preview"> <h5>信息预览:</h5> <div class="message-content"> ${$('#cph_personalized_message').val() || '请输入个性化信息...'} </div> </div> </div> `; $('#cph-preview-content').html(previewHtml); $('#cph-preview-area').show(); // 添加3D预览效果 this.add3DEffect(); } // 更新信息预览 updateMessagePreview(message) { const previewArea = $('.packaging-message-preview .message-content'); if (previewArea.length) { previewArea.text(message || '请输入个性化信息...'); // 添加打字机效果 this.typewriterEffect(previewArea, message); } } // 初始化字符计数器 initCharCounter() { const textarea = $('#cph_personalized_message'); const maxChars = textarea.data('max-chars') || 50; textarea.after(` <div class="char-counter"> <span class="current">0</span>/<span class="max">${maxChars}</span> <div class="char-progress"></div> </div> `); this.updateCharCounter(); } // 更新字符计数器 updateCharCounter() {
在当今电商竞争激烈的环境中,个性化包装已成为提升品牌形象和客户体验的重要手段。然而,许多中小型电商企业面临一个共同难题:传统包装解决方案往往需要大批量定制,成本高昂且缺乏灵活性。
本教程将指导您开发一个支持小批量个性化包装的WordPress插件,让店主能够为不同客户提供独特的包装体验,同时保持成本可控。该插件将允许客户在结账时选择包装样式、添加个性化信息,并实时查看包装效果预览。
在开始开发之前,请确保您已准备好以下环境:
- WordPress 5.0+ 安装
- PHP 7.2+ 环境
- 基础的HTML、CSS、JavaScript知识
- 代码编辑器(如VS Code、Sublime Text等)
首先,我们需要创建插件的基本文件结构:
custom-packaging-helper/
│
├── custom-packaging-helper.php # 主插件文件
├── includes/
│ ├── class-admin-settings.php # 后台设置类
│ ├── class-packaging-manager.php # 包装管理类
│ └── class-checkout-integration.php # 结账集成类
├── assets/
│ ├── css/
│ │ └── admin-style.css # 后台样式
│ ├── js/
│ │ └── packaging-preview.js # 包装预览脚本
│ └── images/ # 包装模板图片
├── templates/
│ └── packaging-preview.php # 预览模板
└── uninstall.php # 卸载脚本
创建主插件文件 custom-packaging-helper.php:
<?php
/**
* Plugin Name: 小批量个性化包装助手
* Plugin URI: https://yourwebsite.com/custom-packaging-helper
* Description: 为WooCommerce提供小批量个性化包装解决方案
* Version: 1.0.0
* Author: 您的名字
* License: GPL v2 or later
* Text Domain: custom-packaging-helper
*/
// 防止直接访问
if (!defined('ABSPATH')) {
exit;
}
// 定义插件常量
define('CPH_VERSION', '1.0.0');
define('CPH_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('CPH_PLUGIN_URL', plugin_dir_url(__FILE__));
// 检查WooCommerce是否激活
function cph_check_woocommerce() {
if (!class_exists('WooCommerce')) {
add_action('admin_notices', function() {
?>
<div class="notice notice-error">
<p><?php _e('小批量个性化包装插件需要WooCommerce支持,请先安装并激活WooCommerce插件。', 'custom-packaging-helper'); ?></p>
</div>
<?php
});
return false;
}
return true;
}
// 初始化插件
function cph_init() {
if (!cph_check_woocommerce()) {
return;
}
// 加载必要文件
require_once CPH_PLUGIN_DIR . 'includes/class-packaging-manager.php';
require_once CPH_PLUGIN_DIR . 'includes/class-admin-settings.php';
require_once CPH_PH_PLUGIN_DIR . 'includes/class-checkout-integration.php';
// 初始化核心类
new CPH_Packaging_Manager();
new CPH_Admin_Settings();
new CPH_Checkout_Integration();
}
add_action('plugins_loaded', 'cph_init');
// 激活插件时的操作
function cph_activate() {
// 创建必要的数据库表
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
$table_name = $wpdb->prefix . 'cph_packaging_designs';
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
design_name varchar(100) NOT NULL,
design_type varchar(50) NOT NULL,
thumbnail_url varchar(255),
price_additional decimal(10,2) DEFAULT 0.00,
max_characters int DEFAULT 50,
is_active tinyint(1) DEFAULT 1,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
// 设置默认选项
add_option('cph_enable_plugin', 'yes');
add_option('cph_minimum_order_amount', 0);
add_option('cph_default_packaging_price', 2.99);
}
register_activation_hook(__FILE__, 'cph_activate');
// 停用插件时的操作
function cph_deactivate() {
// 清理临时数据
wp_clear_scheduled_hook('cph_daily_cleanup');
}
register_deactivation_hook(__FILE__, 'cph_deactivate');
创建 includes/class-packaging-manager.php:
<?php
/**
* 包装设计管理类
* 处理包装设计的CRUD操作
*/
class CPH_Packaging_Manager {
public function __construct() {
add_action('init', array($this, 'register_post_type'));
add_action('add_meta_boxes', array($this, 'add_packaging_meta_boxes'));
add_action('save_post', array($this, 'save_packaging_meta'));
}
// 注册自定义帖子类型
public function register_post_type() {
$labels = array(
'name' => __('包装设计', 'custom-packaging-helper'),
'singular_name' => __('包装设计', 'custom-packaging-helper'),
'menu_name' => __('个性化包装', 'custom-packaging-helper'),
'add_new' => __('添加新设计', 'custom-packaging-helper'),
'add_new_item' => __('添加新包装设计', 'custom-packaging-helper'),
'edit_item' => __('编辑包装设计', 'custom-packaging-helper'),
'new_item' => __('新包装设计', 'custom-packaging-helper'),
);
$args = array(
'labels' => $labels,
'public' => false,
'publicly_queryable' => false,
'show_ui' => true,
'show_in_menu' => true,
'query_var' => true,
'capability_type' => 'post',
'has_archive' => false,
'hierarchical' => false,
'menu_position' => 56,
'menu_icon' => 'dashicons-archive',
'supports' => array('title', 'thumbnail'),
);
register_post_type('cph_packaging', $args);
}
// 添加元数据框
public function add_packaging_meta_boxes() {
add_meta_box(
'cph_packaging_details',
__('包装设计详情', 'custom-packaging-helper'),
array($this, 'render_packaging_meta_box'),
'cph_packaging',
'normal',
'high'
);
}
// 渲染元数据框内容
public function render_packaging_meta_box($post) {
// 添加安全验证
wp_nonce_field('cph_save_packaging_data', 'cph_packaging_nonce');
// 获取现有值
$price = get_post_meta($post->ID, '_cph_packaging_price', true);
$type = get_post_meta($post->ID, '_cph_packaging_type', true);
$max_chars = get_post_meta($post->ID, '_cph_max_characters', true);
$is_active = get_post_meta($post->ID, '_cph_is_active', true);
// 设置默认值
$price = $price ? $price : 2.99;
$max_chars = $max_chars ? $max_chars : 50;
$is_active = $is_active === '' ? 1 : $is_active;
?>
<div class="cph-metabox">
<p>
<label for="cph_packaging_price"><?php _e('附加价格 (USD):', 'custom-packaging-helper'); ?></label>
<input type="number" step="0.01" min="0" id="cph_packaging_price"
name="cph_packaging_price" value="<?php echo esc_attr($price); ?>" />
</p>
<p>
<label for="cph_packaging_type"><?php _e('包装类型:', 'custom-packaging-helper'); ?></label>
<select id="cph_packaging_type" name="cph_packaging_type">
<option value="birthday" <?php selected($type, 'birthday'); ?>><?php _e('生日主题', 'custom-packaging-helper'); ?></option>
<option value="holiday" <?php selected($type, 'holiday'); ?>><?php _e('节日主题', 'custom-packaging-helper'); ?></option>
<option value="elegant" <?php selected($type, 'elegant'); ?>><?php _e('优雅简约', 'custom-packaging-helper'); ?></option>
<option value="custom" <?php selected($type, 'custom'); ?>><?php _e('自定义设计', 'custom-packaging-helper'); ?></option>
</select>
</p>
<p>
<label for="cph_max_characters"><?php _e('最大字符数:', 'custom-packaging-helper'); ?></label>
<input type="number" min="0" max="200" id="cph_max_characters"
name="cph_max_characters" value="<?php echo esc_attr($max_chars); ?>" />
<span class="description"><?php _e('个性化信息的最大字符限制', 'custom-packaging-helper'); ?></span>
</p>
<p>
<label for="cph_is_active">
<input type="checkbox" id="cph_is_active" name="cph_is_active" value="1" <?php checked($is_active, 1); ?> />
<?php _e('启用此包装设计', 'custom-packaging-helper'); ?>
</label>
</p>
</div>
<?php
}
// 保存元数据
public function save_packaging_meta($post_id) {
// 检查安全验证
if (!isset($_POST['cph_packaging_nonce']) ||
!wp_verify_nonce($_POST['cph_packaging_nonce'], 'cph_save_packaging_data')) {
return;
}
// 检查自动保存
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
// 检查权限
if (!current_user_can('edit_post', $post_id)) {
return;
}
// 保存字段
$fields = array(
'cph_packaging_price',
'cph_packaging_type',
'cph_max_characters',
'cph_is_active'
);
foreach ($fields as $field) {
if (isset($_POST[$field])) {
$value = sanitize_text_field($_POST[$field]);
update_post_meta($post_id, '_' . $field, $value);
}
}
}
// 获取可用的包装设计
public static function get_available_designs() {
$args = array(
'post_type' => 'cph_packaging',
'posts_per_page' => -1,
'meta_query' => array(
array(
'key' => '_cph_is_active',
'value' => '1',
'compare' => '='
)
)
);
$designs = get_posts($args);
$result = array();
foreach ($designs as $design) {
$result[] = array(
'id' => $design->ID,
'name' => $design->post_title,
'price' => get_post_meta($design->ID, '_cph_packaging_price', true),
'type' => get_post_meta($design->ID, '_cph_packaging_type', true),
'max_chars' => get_post_meta($design->ID, '_cph_max_characters', true),
'thumbnail' => get_the_post_thumbnail_url($design->ID, 'medium')
);
}
return $result;
}
}
创建 includes/class-checkout-integration.php:
<?php
/**
* 结账页面集成类
* 在WooCommerce结账页面添加个性化包装选项
*/
class CPH_Checkout_Integration {
public function __construct() {
// 在结账页面添加包装选项
add_action('woocommerce_before_order_notes', array($this, 'add_packaging_options'));
// 验证并保存包装选择
add_action('woocommerce_checkout_process', array($this, 'validate_packaging_options'));
add_action('woocommerce_checkout_update_order_meta', array($this, 'save_packaging_options'));
// 在订单详情页显示包装信息
add_action('woocommerce_order_details_after_order_table', array($this, 'display_packaging_in_order'));
// 添加包装费用到购物车
add_action('woocommerce_cart_calculate_fees', array($this, 'add_packaging_fee'));
}
// 在结账页面添加包装选项
public function add_packaging_options($checkout) {
$designs = CPH_Packaging_Manager::get_available_designs();
if (empty($designs)) {
return;
}
echo '<div id="cph-packaging-options">';
echo '<h3>' . __('个性化包装选项', 'custom-packaging-helper') . '</h3>';
// 包装设计选择
woocommerce_form_field('cph_packaging_design', array(
'type' => 'select',
'class' => array('form-row-wide'),
'label' => __('选择包装设计', 'custom-packaging-helper'),
'options' => $this->get_design_options($designs),
'required' => false,
), $checkout->get_value('cph_packaging_design'));
// 个性化信息输入
woocommerce_form_field('cph_personalized_message', array(
'type' => 'textarea',
'class' => array('form-row-wide'),
'label' => __('个性化信息', 'custom-packaging-helper'),
'placeholder' => __('请输入您想在包装上显示的信息(最多50个字符)', 'custom-packaging-helper'),
'required' => false,
'maxlength' => 50,
), $checkout->get_value('cph_personalized_message'));
// 包装预览区域
echo '<div id="cph-preview-area" style="display:none; margin-top:20px; padding:15px; border:1px solid #ddd; border-radius:5px;">';
echo '<h4>' . __('包装预览', 'custom-packaging-helper') . '</h4>';
echo '<div id="cph-preview-content"></div>';
echo '</div>';
echo '</div>';
// 添加预览脚本
$this->add_preview_script($designs);
}
// 生成设计选项数组
private function get_design_options($designs) {
$options = array('' => __('请选择包装设计', 'custom-packaging-helper'));
foreach ($designs as $design) {
$price_text = $design['price'] > 0 ? sprintf(__(' (+$%s)', 'custom-packaging-helper'), $design['price']) : __(' (免费)', 'custom-packaging-helper');
$options[$design['id']] = $design['name'] . $price_text;
}
return $options;
}
// 添加预览JavaScript
private function add_preview_script($designs) {
?>
<script type="text/javascript">
jQuery(document).ready(function($) {
var designs = <?php echo json_encode($designs); ?>;
// 当选择包装设计时
$('#cph_packaging_design').change(function() {
var designId = $(this).val();
var previewArea = $('#cph-preview-area');
var previewContent = $('#cph-preview-content');
if (designId) {
// 查找选中的设计
var selectedDesign = designs.find(function(design) {
return design.id == designId;
});
if (selectedDesign) {
// 显示预览
var previewHtml = '<div class="packaging-preview">';
if (selectedDesign.thumbnail) {
previewHtml += '<img src="' + selectedDesign.thumbnail + '" style="max-width:200px; margin-bottom:10px;" />';
}
previewHtml += '<p><strong>' + selectedDesign.name + '</strong></p>';
previewHtml += '<p>类型: ' + selectedDesign.type + '</p>';
if (selectedDesign.price > 0) {
previewHtml += '<p>附加费用: $' + selectedDesign.price + '</p>';
}
previewHtml += '</div>';
previewContent.html(previewHtml);
previewArea.show();
}
} else {
previewArea.hide();
}
});
// 实时更新个性化信息预览
$('#cph_personalized_message').on('input', function() {
var message = $(this).val();
var charCount = message.length;
var maxChars = 50;
// 更新字符计数
// 实时更新个性化信息预览
$('#cph_personalized_message').on('input', function() {
var message = $(this).val();
var charCount = message.length;
var maxChars = 50;
// 更新字符计数
var counter = $('#cph-char-counter');
if (counter.length === 0) {
$(this).after('<div id="cph-char-counter" style="font-size:12px; color:#666;"></div>');
counter = $('#cph-char-counter');
}
counter.text('字符数: ' + charCount + '/' + maxChars);
// 如果选择了包装设计,更新预览
if ($('#cph_packaging_design').val()) {
var previewContent = $('#cph-preview-content');
var messagePreview = previewContent.find('.personalized-message');
if (messagePreview.length === 0) {
previewContent.append('<div class="personalized-message" style="margin-top:10px; padding:10px; background:#f5f5f5; border-radius:3px;"></div>');
messagePreview = previewContent.find('.personalized-message');
}
messagePreview.html('<strong>个性化信息:</strong><br>' + message);
}
});
});
</script>
<?php
}
// 验证包装选项
public function validate_packaging_options() {
$design_id = isset($_POST['cph_packaging_design']) ? intval($_POST['cph_packaging_design']) : 0;
$message = isset($_POST['cph_personalized_message']) ? sanitize_textarea_field($_POST['cph_personalized_message']) : '';
if ($design_id > 0) {
// 获取设计详情
$design = get_post($design_id);
if (!$design || $design->post_type !== 'cph_packaging') {
wc_add_notice(__('选择的包装设计无效。', 'custom-packaging-helper'), 'error');
return;
}
// 检查设计是否启用
$is_active = get_post_meta($design_id, '_cph_is_active', true);
if (!$is_active) {
wc_add_notice(__('选择的包装设计暂不可用。', 'custom-packaging-helper'), 'error');
return;
}
// 验证消息长度
$max_chars = get_post_meta($design_id, '_cph_max_characters', true);
$max_chars = $max_chars ? intval($max_chars) : 50;
if (strlen($message) > $max_chars) {
wc_add_notice(sprintf(__('个性化信息不能超过%d个字符。', 'custom-packaging-helper'), $max_chars), 'error');
}
}
}
// 保存包装选项到订单
public function save_packaging_options($order_id) {
if (isset($_POST['cph_packaging_design'])) {
$design_id = intval($_POST['cph_packaging_design']);
if ($design_id > 0) {
// 保存设计ID
update_post_meta($order_id, '_cph_packaging_design_id', $design_id);
// 保存设计名称和价格
$design_name = get_the_title($design_id);
$design_price = get_post_meta($design_id, '_cph_packaging_price', true);
update_post_meta($order_id, '_cph_packaging_design_name', $design_name);
update_post_meta($order_id, '_cph_packaging_design_price', $design_price);
// 保存个性化信息
if (isset($_POST['cph_personalized_message'])) {
$message = sanitize_textarea_field($_POST['cph_personalized_message']);
update_post_meta($order_id, '_cph_personalized_message', $message);
}
}
}
}
// 在订单详情页显示包装信息
public function display_packaging_in_order($order) {
$design_id = get_post_meta($order->get_id(), '_cph_packaging_design_id', true);
if ($design_id) {
echo '<section class="cph-order-packaging-details">';
echo '<h2>' . __('个性化包装详情', 'custom-packaging-helper') . '</h2>';
echo '<table class="woocommerce-table woocommerce-table--order-details shop_table order_details">';
echo '<tbody>';
$design_name = get_post_meta($order->get_id(), '_cph_packaging_design_name', true);
$design_price = get_post_meta($order->get_id(), '_cph_packaging_design_price', true);
$message = get_post_meta($order->get_id(), '_cph_personalized_message', true);
echo '<tr>';
echo '<th scope="row">' . __('包装设计', 'custom-packaging-helper') . ':</th>';
echo '<td>' . esc_html($design_name) . '</td>';
echo '</tr>';
if ($message) {
echo '<tr>';
echo '<th scope="row">' . __('个性化信息', 'custom-packaging-helper') . ':</th>';
echo '<td>' . nl2br(esc_html($message)) . '</td>';
echo '</tr>';
}
echo '</tbody>';
echo '</table>';
echo '</section>';
}
}
// 添加包装费用到购物车
public function add_packaging_fee($cart) {
if (is_admin() && !defined('DOING_AJAX')) {
return;
}
// 检查是否在结账页面且选择了包装设计
if (isset($_POST['post_data'])) {
parse_str($_POST['post_data'], $post_data);
$design_id = isset($post_data['cph_packaging_design']) ? intval($post_data['cph_packaging_design']) : 0;
} else {
$design_id = isset($_POST['cph_packaging_design']) ? intval($_POST['cph_packaging_design']) : 0;
}
if ($design_id > 0) {
$design_price = get_post_meta($design_id, '_cph_packaging_price', true);
$design_name = get_the_title($design_id);
if ($design_price && floatval($design_price) > 0) {
$fee = floatval($design_price);
$cart->add_fee(__('个性化包装', 'custom-packaging-helper') . ' - ' . $design_name, $fee);
}
}
}
}
// 实时更新个性化信息预览
$('#cph_personalized_message').on('input', function() {
var message = $(this).val();
var charCount = message.length;
var maxChars = 50;
// 更新字符计数
var counter = $('#cph-char-counter');
if (counter.length === 0) {
$(this).after('<div id="cph-char-counter" style="font-size:12px; color:#666;"></div>');
counter = $('#cph-char-counter');
}
counter.text('字符数: ' + charCount + '/' + maxChars);
// 如果选择了包装设计,更新预览
if ($('#cph_packaging_design').val()) {
var previewContent = $('#cph-preview-content');
var messagePreview = previewContent.find('.personalized-message');
if (messagePreview.length === 0) {
previewContent.append('<div class="personalized-message" style="margin-top:10px; padding:10px; background:#f5f5f5; border-radius:3px;"></div>');
messagePreview = previewContent.find('.personalized-message');
}
messagePreview.html('<strong>个性化信息:</strong><br>' + message);
}
});
});
</script>
<?php
}
// 验证包装选项
public function validate_packaging_options() {
$design_id = isset($_POST['cph_packaging_design']) ? intval($_POST['cph_packaging_design']) : 0;
$message = isset($_POST['cph_personalized_message']) ? sanitize_textarea_field($_POST['cph_personalized_message']) : '';
if ($design_id > 0) {
// 获取设计详情
$design = get_post($design_id);
if (!$design || $design->post_type !== 'cph_packaging') {
wc_add_notice(__('选择的包装设计无效。', 'custom-packaging-helper'), 'error');
return;
}
// 检查设计是否启用
$is_active = get_post_meta($design_id, '_cph_is_active', true);
if (!$is_active) {
wc_add_notice(__('选择的包装设计暂不可用。', 'custom-packaging-helper'), 'error');
return;
}
// 验证消息长度
$max_chars = get_post_meta($design_id, '_cph_max_characters', true);
$max_chars = $max_chars ? intval($max_chars) : 50;
if (strlen($message) > $max_chars) {
wc_add_notice(sprintf(__('个性化信息不能超过%d个字符。', 'custom-packaging-helper'), $max_chars), 'error');
}
}
}
// 保存包装选项到订单
public function save_packaging_options($order_id) {
if (isset($_POST['cph_packaging_design'])) {
$design_id = intval($_POST['cph_packaging_design']);
if ($design_id > 0) {
// 保存设计ID
update_post_meta($order_id, '_cph_packaging_design_id', $design_id);
// 保存设计名称和价格
$design_name = get_the_title($design_id);
$design_price = get_post_meta($design_id, '_cph_packaging_price', true);
update_post_meta($order_id, '_cph_packaging_design_name', $design_name);
update_post_meta($order_id, '_cph_packaging_design_price', $design_price);
// 保存个性化信息
if (isset($_POST['cph_personalized_message'])) {
$message = sanitize_textarea_field($_POST['cph_personalized_message']);
update_post_meta($order_id, '_cph_personalized_message', $message);
}
}
}
}
// 在订单详情页显示包装信息
public function display_packaging_in_order($order) {
$design_id = get_post_meta($order->get_id(), '_cph_packaging_design_id', true);
if ($design_id) {
echo '<section class="cph-order-packaging-details">';
echo '<h2>' . __('个性化包装详情', 'custom-packaging-helper') . '</h2>';
echo '<table class="woocommerce-table woocommerce-table--order-details shop_table order_details">';
echo '<tbody>';
$design_name = get_post_meta($order->get_id(), '_cph_packaging_design_name', true);
$design_price = get_post_meta($order->get_id(), '_cph_packaging_design_price', true);
$message = get_post_meta($order->get_id(), '_cph_personalized_message', true);
echo '<tr>';
echo '<th scope="row">' . __('包装设计', 'custom-packaging-helper') . ':</th>';
echo '<td>' . esc_html($design_name) . '</td>';
echo '</tr>';
if ($message) {
echo '<tr>';
echo '<th scope="row">' . __('个性化信息', 'custom-packaging-helper') . ':</th>';
echo '<td>' . nl2br(esc_html($message)) . '</td>';
echo '</tr>';
}
echo '</tbody>';
echo '</table>';
echo '</section>';
}
}
// 添加包装费用到购物车
public function add_packaging_fee($cart) {
if (is_admin() && !defined('DOING_AJAX')) {
return;
}
// 检查是否在结账页面且选择了包装设计
if (isset($_POST['post_data'])) {
parse_str($_POST['post_data'], $post_data);
$design_id = isset($post_data['cph_packaging_design']) ? intval($post_data['cph_packaging_design']) : 0;
} else {
$design_id = isset($_POST['cph_packaging_design']) ? intval($_POST['cph_packaging_design']) : 0;
}
if ($design_id > 0) {
$design_price = get_post_meta($design_id, '_cph_packaging_price', true);
$design_name = get_the_title($design_id);
if ($design_price && floatval($design_price) > 0) {
$fee = floatval($design_price);
$cart->add_fee(__('个性化包装', 'custom-packaging-helper') . ' - ' . $design_name, $fee);
}
}
}
}
创建 includes/class-admin-settings.php:
<?php
/**
* 后台设置类
* 提供插件配置选项
*/
class CPH_Admin_Settings {
public function __construct() {
add_action('admin_menu', array($this, 'add_admin_menu'));
add_action('admin_init', array($this, 'register_settings'));
add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'));
}
// 添加管理菜单
public function add_admin_menu() {
add_submenu_page(
'edit.php?post_type=cph_packaging',
__('个性化包装设置', 'custom-packaging-helper'),
__('设置', 'custom-packaging-helper'),
'manage_options',
'cph-settings',
array($this, 'render_settings_page')
);
}
// 注册设置
public function register_settings() {
register_setting('cph_settings_group', 'cph_general_settings');
add_settings_section(
'cph_general_section',
__('常规设置', 'custom-packaging-helper'),
array($this, 'render_general_section'),
'cph-settings'
);
add_settings_field(
'cph_enable_plugin',
__('启用插件', 'custom-packaging-helper'),
array($this, 'render_enable_field'),
'cph-settings',
'cph_general_section'
);
add_settings_field(
'cph_minimum_order',
__('最低订单金额', 'custom-packaging-helper'),
array($this, 'render_minimum_order_field'),
'cph-settings',
'cph_general_section'
);
add_settings_field(
'cph_default_price',
__('默认包装价格', 'custom-packaging-helper'),
array($this, 'render_default_price_field'),
'cph-settings',
'cph_general_section'
);
add_settings_field(
'cph_packaging_types',
__('包装类型', 'custom-packaging-helper'),
array($this, 'render_packaging_types_field'),
'cph-settings',
'cph_general_section'
);
}
// 渲染设置页面
public function render_settings_page() {
?>
<div class="wrap">
<h1><?php echo esc_html(get_admin_page_title()); ?></h1>
<form method="post" action="options.php">
<?php
settings_fields('cph_settings_group');
do_settings_sections('cph-settings');
submit_button();
?>
</form>
<div class="cph-stats" style="margin-top: 30px; padding: 20px; background: #f5f5f5; border-radius: 5px;">
<h2><?php _e('使用统计', 'custom-packaging-helper'); ?></h2>
<?php $this->render_usage_stats(); ?>
</div>
</div>
<?php
}
// 渲染常规设置部分
public function render_general_section() {
echo '<p>' . __('配置个性化包装插件的基本设置。', 'custom-packaging-helper') . '</p>';
}
// 渲染启用字段
public function render_enable_field() {
$options = get_option('cph_general_settings');
$enabled = isset($options['enable_plugin']) ? $options['enable_plugin'] : 'yes';
?>
<label>
<input type="checkbox" name="cph_general_settings[enable_plugin]" value="yes" <?php checked($enabled, 'yes'); ?> />
<?php _e('启用个性化包装功能', 'custom-packaging-helper'); ?>
</label>
<?php
}
// 渲染最低订单金额字段
public function render_minimum_order_field() {
$options = get_option('cph_general_settings');
$minimum = isset($options['minimum_order']) ? $options['minimum_order'] : 0;
?>
<input type="number" name="cph_general_settings[minimum_order]" value="<?php echo esc_attr($minimum); ?>" min="0" step="0.01" />
<p class="description"><?php _e('设置可以使用个性化包装的最低订单金额(0表示无限制)', 'custom-packaging-helper'); ?></p>
<?php
}
// 渲染默认价格字段
public function render_default_price_field() {
$options = get_option('cph_general_settings');
$price = isset($options['default_price']) ? $options['default_price'] : 2.99;
?>
<input type="number" name="cph_general_settings[default_price]" value="<?php echo esc_attr($price); ?>" min="0" step="0.01" />
<p class="description"><?php _e('新包装设计的默认价格', 'custom-packaging-helper'); ?></p>
<?php
}
// 渲染包装类型字段
public function render_packaging_types_field() {
$options = get_option('cph_general_settings');
$types = isset($options['packaging_types']) ? $options['packaging_types'] : "生日主题n节日主题n优雅简约n自定义设计";
?>
<textarea name="cph_general_settings[packaging_types]" rows="5" cols="50"><?php echo esc_textarea($types); ?></textarea>
<p class="description"><?php _e('每行一个包装类型,这些类型将在添加新包装设计时可用', 'custom-packaging-helper'); ?></p>
<?php
}
// 渲染使用统计
public function render_usage_stats() {
global $wpdb;
// 统计使用个性化包装的订单数量
$order_count = $wpdb->get_var("
SELECT COUNT(DISTINCT post_id)
FROM {$wpdb->postmeta}
WHERE meta_key = '_cph_packaging_design_id'
");
// 统计最受欢迎的包装设计
$popular_designs = $wpdb->get_results("
SELECT meta_value as design_id, COUNT(*) as usage_count
FROM {$wpdb->postmeta}
WHERE meta_key = '_cph_packaging_design_id'
GROUP BY meta_value
ORDER BY usage_count DESC
LIMIT 5
");
echo '<p><strong>' . __('总使用次数:', 'custom-packaging-helper') . '</strong> ' . intval($order_count) . '</p>';
if (!empty($popular_designs)) {
echo '<h3>' . __('最受欢迎的包装设计', 'custom-packaging-helper') . '</h3>';
echo '<ul>';
foreach ($popular_designs as $design) {
$design_name = get_the_title($design->design_id);
echo '<li>' . esc_html($design_name) . ': ' . intval($design->usage_count) . ' ' . __('次', 'custom-packaging-helper') . '</li>';
}
echo '</ul>';
}
}
// 加载后台脚本和样式
public function enqueue_admin_scripts($hook) {
if (strpos($hook, 'cph_packaging') === false && strpos($hook, 'cph-settings') === false) {
return;
}
wp_enqueue_style(
'cph-admin-style',
CPH_PLUGIN_URL . 'assets/css/admin-style.css',
array(),
CPH_VERSION
);
wp_enqueue_script(
'cph-admin-script',
CPH_PLUGIN_URL . 'assets/js/admin-script.js',
array('jquery'),
CPH_VERSION,
true
);
}
}
创建 assets/js/packaging-preview.js:
/**
* 包装预览增强功能
* 提供更丰富的包装预览体验
*/
(function($) {
'use strict';
// 包装预览类
class PackagingPreview {
constructor() {
this.init();
}
init() {
// 监听包装设计选择
$(document).on('change', '#cph_packaging_design', (e) => {
this.updateDesignPreview(e.target.value);
});
// 监听个性化信息输入
$(document).on('input', '#cph_personalized_message', (e) => {
this.updateMessagePreview(e.target.value);
});
// 初始化字符计数器
this.initCharCounter();
}
// 更新设计预览
updateDesignPreview(designId) {
if (!designId) {
$('#cph-preview-area').hide();
return;
}
// 通过AJAX获取设计详情
$.ajax({
url: cph_ajax.ajax_url,
type: 'POST',
data: {
action: 'cph_get_design_details',
design_id: designId,
nonce: cph_ajax.nonce
},
success: (response) => {
if (response.success) {
this.renderPreview(response.data);
} else {
console.error('获取设计详情失败:', response.data);
}
},
error: (xhr, status, error) => {
console.error('AJAX请求失败:', error);
}
});
}
// 渲染预览
renderPreview(design) {
let previewHtml = `
<div class="packaging-preview-container">
<div class="packaging-image">
${design.thumbnail ? `<img src="${design.thumbnail}" alt="${design.name}" />` : ''}
</div>
<div class="packaging-details">
<h4>${design.name}</h4>
<p><strong>类型:</strong> ${design.type}</p>
<p><strong>价格:</strong> $${design.price}</p>
<p><strong>最大字符数:</strong> ${design.max_chars}</p>
</div>
<div class="packaging-message-preview">
<h5>信息预览:</h5>
<div class="message-content">
${$('#cph_personalized_message').val() || '请输入个性化信息...'}
</div>
</div>
</div>
`;
$('#cph-preview-content').html(previewHtml);
$('#cph-preview-area').show();
// 添加3D预览效果
this.add3DEffect();
}
// 更新信息预览
updateMessagePreview(message) {
const previewArea = $('.packaging-message-preview .message-content');
if (previewArea.length) {
previewArea.text(message || '请输入个性化信息...');
// 添加打字机效果
this.typewriterEffect(previewArea, message);
}
}
// 初始化字符计数器
initCharCounter() {
const textarea = $('#cph_personalized_message');
const maxChars = textarea.data('max-chars') || 50;
textarea.after(`
<div class="char-counter">
<span class="current">0</span>/<span class="max">${maxChars}</span>
<div class="char-progress"></div>
</div>
`);
this.updateCharCounter();
}
// 更新字符计数器
updateCharCounter() {


