文章目录[隐藏]
WordPress文创插件实现柔性产品配置器开发详细教程
一、项目概述与准备工作
1.1 什么是柔性产品配置器
柔性产品配置器是一种允许用户自定义文创产品的交互工具。在WordPress电商场景中,这种配置器可以让客户选择不同的产品选项(如颜色、尺寸、材质、图案等),实时预览效果并生成个性化订单。这对于销售定制T恤、马克杯、手机壳等文创产品的网站尤为重要。
1.2 开发环境准备
在开始开发前,请确保您的环境满足以下要求:
- WordPress 5.0+ 版本
- PHP 7.4+ 版本
- MySQL 5.6+ 或 MariaDB 10.1+
- 基本的HTML、CSS、JavaScript知识
- 代码编辑器(如VS Code、Sublime Text等)
1.3 插件基础结构
首先,我们需要创建插件的基本文件结构:
wp-content/plugins/
└── flexible-product-configurator/
├── flexible-product-configurator.php
├── includes/
│ ├── class-configurator.php
│ ├── class-ajax-handler.php
│ └── class-admin.php
├── assets/
│ ├── css/
│ │ ├── frontend.css
│ │ └── admin.css
│ └── js/
│ ├── frontend.js
│ └── admin.js
├── templates/
│ ├── configurator-frontend.php
│ └── configurator-admin.php
└── languages/
二、创建主插件文件
2.1 插件头部信息
首先创建主插件文件 flexible-product-configurator.php:
<?php
/**
* Plugin Name: Flexible Product Configurator
* Plugin URI: https://yourwebsite.com/flexible-product-configurator
* Description: 文创产品柔性配置器,允许用户自定义产品选项
* Version: 1.0.0
* Author: Your Name
* Author URI: https://yourwebsite.com
* License: GPL v2 or later
* Text Domain: flexible-product-configurator
* Domain Path: /languages
*/
// 防止直接访问
if (!defined('ABSPATH')) {
exit;
}
// 定义插件常量
define('FPC_VERSION', '1.0.0');
define('FPC_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('FPC_PLUGIN_URL', plugin_dir_url(__FILE__));
define('FPC_PLUGIN_BASENAME', plugin_basename(__FILE__));
// 自动加载类文件
spl_autoload_register(function ($class) {
$prefix = 'FPC_';
$base_dir = FPC_PLUGIN_DIR . 'includes/';
$len = strlen($prefix);
if (strncmp($prefix, $class, $len) !== 0) {
return;
}
$relative_class = substr($class, $len);
$file = $base_dir . 'class-' . strtolower(str_replace('_', '-', $relative_class)) . '.php';
if (file_exists($file)) {
require $file;
}
});
// 初始化插件
function fpc_init() {
// 检查WooCommerce是否激活
if (!class_exists('WooCommerce')) {
add_action('admin_notices', function() {
echo '<div class="notice notice-error"><p>';
echo __('柔性产品配置器需要WooCommerce插件支持,请先安装并激活WooCommerce。', 'flexible-product-configurator');
echo '</p></div>';
});
return;
}
// 初始化核心类
FPC_Configurator::get_instance();
FPC_Ajax_Handler::get_instance();
if (is_admin()) {
FPC_Admin::get_instance();
}
}
add_action('plugins_loaded', 'fpc_init');
// 插件激活钩子
register_activation_hook(__FILE__, 'fpc_activate');
function fpc_activate() {
// 创建必要的数据库表
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
$table_name = $wpdb->prefix . 'fpc_product_configs';
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
product_id bigint(20) NOT NULL,
user_id bigint(20) DEFAULT NULL,
config_data longtext NOT NULL,
preview_image varchar(255) DEFAULT NULL,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY product_id (product_id),
KEY user_id (user_id)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
// 添加版本号
add_option('fpc_version', FPC_VERSION);
}
// 插件停用钩子
register_deactivation_hook(__FILE__, 'fpc_deactivate');
function fpc_deactivate() {
// 清理临时数据
wp_clear_scheduled_hook('fpc_daily_cleanup');
}
三、核心配置器类实现
3.1 配置器主类
创建 includes/class-configurator.php:
<?php
/**
* 柔性产品配置器核心类
*/
class FPC_Configurator {
private static $instance = null;
private $enabled_products = array();
public static function get_instance() {
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct() {
// 初始化钩子
add_action('init', array($this, 'init'));
add_action('wp_enqueue_scripts', array($this, 'enqueue_scripts'));
add_shortcode('product_configurator', array($this, 'render_configurator'));
// 添加到产品页面
add_action('woocommerce_before_add_to_cart_button', array($this, 'add_configurator_to_product'));
}
/**
* 初始化配置器
*/
public function init() {
// 注册配置器选项
$this->register_option_types();
// 加载文本域
load_plugin_textdomain(
'flexible-product-configurator',
false,
dirname(FPC_PLUGIN_BASENAME) . '/languages'
);
}
/**
* 注册选项类型
*/
private function register_option_types() {
// 这里定义不同类型的配置选项
$this->option_types = array(
'color' => array(
'label' => __('颜色选择', 'flexible-product-configurator'),
'template' => 'color-selector',
'has_preview' => true
),
'text' => array(
'label' => __('文本定制', 'flexible-product-configurator'),
'template' => 'text-input',
'has_preview' => true
),
'image' => array(
'label' => __('图片上传', 'flexible-product-configurator'),
'template' => 'image-upload',
'has_preview' => true
),
'dropdown' => array(
'label' => __('下拉选择', 'flexible-product-configurator'),
'template' => 'dropdown-select',
'has_preview' => true
),
'checkbox' => array(
'label' => __('复选框', 'flexible-product-configurator'),
'template' => 'checkbox-group',
'has_preview' => false
)
);
}
/**
* 加载前端脚本和样式
*/
public function enqueue_scripts() {
if (is_product()) {
global $product;
// 检查产品是否启用配置器
if ($this->is_product_configurable($product->get_id())) {
// 加载CSS
wp_enqueue_style(
'fpc-frontend',
FPC_PLUGIN_URL . 'assets/css/frontend.css',
array(),
FPC_VERSION
);
// 加载JavaScript
wp_enqueue_script(
'fpc-fabric',
'https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.5.0/fabric.min.js',
array(),
'4.5.0',
true
);
wp_enqueue_script(
'fpc-frontend',
FPC_PLUGIN_URL . 'assets/js/frontend.js',
array('jquery', 'fpc-fabric'),
FPC_VERSION,
true
);
// 本地化脚本
wp_localize_script('fpc-frontend', 'fpc_ajax', array(
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('fpc_nonce'),
'product_id' => $product->get_id(),
'text' => array(
'loading' => __('加载中...', 'flexible-product-configurator'),
'saving' => __('保存配置...', 'flexible-product-configurator'),
'error' => __('发生错误,请重试', 'flexible-product-configurator')
)
));
}
}
}
/**
* 检查产品是否可配置
*/
public function is_product_configurable($product_id) {
if (empty($this->enabled_products)) {
$this->enabled_products = get_posts(array(
'post_type' => 'product',
'meta_key' => '_fpc_enabled',
'meta_value' => 'yes',
'fields' => 'ids',
'posts_per_page' => -1
));
}
return in_array($product_id, $this->enabled_products);
}
/**
* 渲染配置器短代码
*/
public function render_configurator($atts) {
$atts = shortcode_atts(array(
'product_id' => 0,
'width' => '100%',
'height' => '500px'
), $atts, 'product_configurator');
if (!$atts['product_id']) {
global $product;
if ($product) {
$atts['product_id'] = $product->get_id();
}
}
if (!$this->is_product_configurable($atts['product_id'])) {
return '<p>' . __('此产品不支持配置', 'flexible-product-configurator') . '</p>';
}
ob_start();
include FPC_PLUGIN_DIR . 'templates/configurator-frontend.php';
return ob_get_clean();
}
/**
* 添加到产品页面
*/
public function add_configurator_to_product() {
global $product;
if ($this->is_product_configurable($product->get_id())) {
echo do_shortcode('[product_configurator product_id="' . $product->get_id() . '"]');
}
}
/**
* 获取产品配置选项
*/
public function get_product_options($product_id) {
$options = get_post_meta($product_id, '_fpc_options', true);
if (empty($options)) {
$options = array(
'base_image' => '',
'areas' => array(),
'options' => array()
);
}
return $options;
}
}
四、前端交互实现
4.1 前端JavaScript核心
创建 assets/js/frontend.js:
/**
* 柔性产品配置器前端交互
*/
(function($) {
'use strict';
var FPC_Frontend = {
// 初始化变量
canvas: null,
fabricCanvas: null,
currentProductId: 0,
currentConfig: {},
isSaving: false,
/**
* 初始化配置器
*/
init: function() {
this.currentProductId = fpc_ajax.product_id;
this.setupCanvas();
this.loadProductConfig();
this.bindEvents();
},
/**
* 设置Canvas画布
*/
setupCanvas: function() {
this.canvas = document.getElementById('fpc-canvas');
if (!this.canvas) {
console.error('Canvas元素未找到');
return;
}
// 初始化Fabric.js画布
this.fabricCanvas = new fabric.Canvas('fpc-canvas', {
backgroundColor: '#f5f5f5',
preserveObjectStacking: true
});
// 设置画布尺寸
this.resizeCanvas();
$(window).on('resize', this.resizeCanvas.bind(this));
},
/**
* 调整画布尺寸
*/
resizeCanvas: function() {
var container = $('#fpc-canvas-container');
var width = container.width();
var height = container.height() || 500;
this.fabricCanvas.setDimensions({
width: width,
height: height
});
this.fabricCanvas.calcOffset();
},
/**
* 加载产品配置
*/
loadProductConfig: function() {
var self = this;
$.ajax({
url: fpc_ajax.ajax_url,
type: 'POST',
data: {
action: 'fpc_get_product_config',
nonce: fpc_ajax.nonce,
product_id: this.currentProductId
},
beforeSend: function() {
$('#fpc-loading').show();
},
success: function(response) {
if (response.success) {
self.currentConfig = response.data;
self.renderProduct();
self.renderOptions();
} else {
self.showError(response.data);
}
},
error: function() {
self.showError(fpc_ajax.text.error);
},
complete: function() {
$('#fpc-loading').hide();
}
});
},
/**
* 渲染产品基础图像
*/
renderProduct: function() {
var self = this;
if (!this.currentConfig.base_image) {
return;
}
// 加载基础图像
fabric.Image.fromURL(this.currentConfig.base_image, function(img) {
// 设置图像为背景
img.set({
selectable: false,
evented: false,
hasControls: false,
hasBorders: false
});
// 调整图像尺寸以适应画布
var scale = Math.min(
self.fabricCanvas.width / img.width,
self.fabricCanvas.height / img.height
);
img.scale(scale);
img.set({
left: (self.fabricCanvas.width - img.width * scale) / 2,
top: (self.fabricCanvas.height - img.height * scale) / 2
});
self.fabricCanvas.setBackgroundImage(img, self.fabricCanvas.renderAll.bind(self.fabricCanvas));
// 渲染可配置区域
self.renderConfigurableAreas();
});
},
/**
* 渲染可配置区域
*/
renderConfigurableAreas: function() {
if (!this.currentConfig.areas || !Array.isArray(this.currentConfig.areas)) {
return;
}
var self = this;
this.currentConfig.areas.forEach(function(area, index) {
if (area.type === 'text') {
self.addTextArea(area, index);
} else if (area.type === 'image') {
self.addImageArea(area, index);
}
});
},
/**
* 添加文本区域
*/
addTextArea: function(area, index) {
var text = new fabric.Textbox(area.default_text || '点击编辑文本', {
left: area.x,
top: area.y,
width: area.width,
fontSize: area.font_size || 20,
fontFamily: area.font_family || 'Arial',
fill: area.color || '#000000',
textAlign: area.align || 'left',
editable: true,
hasControls: true,
lockScalingFlip: true,
data: {
areaIndex: index,
type: 'text'
}
});
// 添加文本变化事件
text.on('changed', this.onTextChanged.bind(this));
this.fabricCanvas.add(text);
},
/**
* 文本变化处理
*/
onTextChanged: function(e) {
var target = e.target;
var areaIndex = target.data.areaIndex;
if (this.currentConfig.areas[areaIndex]) {
this.currentConfig.areas[areaIndex].current_text = target.text;
this.updatePreview();
}
},
/**
* 渲染配置选项
*/
renderOptions: function() {
if (!this.currentConfig.options || !Array.isArray(this.currentConfig.options)) {
return;
}
var $optionsContainer = $('#fpc-options');
$optionsContainer.empty();
this.currentConfig.options.forEach(function(option, index) {
var $option = $('<div class="fpc-option"></div>');
$option.append('<h4>' + option.label + '</h4>');
switch (option.type) {
case 'color':
this.renderColorOption(option, index, $option);
break;
case 'dropdown':
this.renderDropdownOption(option, index, $option);
break;
case 'checkbox':
this.renderCheckboxOption(option, index, $option);
break;
}
$optionsContainer.append($option);
}.bind(this));
},
/**
* 渲染颜色选项
*/
renderColorOption: function(option, index, $container) {
var $colorPicker = $('<div class="fpc-color-picker"></div>');
option.choices.forEach(function(choice, choiceIndex) {
var $color = $('<div class="fpc-color-choice"></div>');
$color.css('background-color', choice.value);
$color.attr('title', choice.label);
$color.data('value', choice.value);
0) {
$color.addClass('active');
}
$color.on('click', function() {
$color.siblings().removeClass('active');
$color.addClass('active');
this.updateOptionValue(index, choice.value);
}.bind(this));
$colorPicker.append($color);
}.bind(this));
$container.append($colorPicker);
},
/**
* 更新选项值
*/
updateOptionValue: function(optionIndex, value) {
if (this.currentConfig.options[optionIndex]) {
this.currentConfig.options[optionIndex].value = value;
this.applyOptionToCanvas(optionIndex);
this.updatePreview();
}
},
/**
* 将选项应用到画布
*/
applyOptionToCanvas: function(optionIndex) {
var option = this.currentConfig.options[optionIndex];
// 根据选项类型应用变化
switch (option.target_type) {
case 'background_color':
this.fabricCanvas.backgroundColor = option.value;
this.fabricCanvas.renderAll();
break;
case 'text_color':
this.fabricCanvas.getObjects().forEach(function(obj) {
if (obj.data && obj.data.type === 'text') {
obj.set('fill', option.value);
}
});
this.fabricCanvas.renderAll();
break;
}
},
/**
* 更新预览
*/
updatePreview: function() {
// 这里可以添加实时预览更新逻辑
// 例如:更新缩略图或发送到服务器生成预览
},
/**
* 保存当前配置
*/
saveConfiguration: function() {
if (this.isSaving) return;
this.isSaving = true;
var self = this;
// 收集所有配置数据
var configData = {
product_id: this.currentProductId,
options: {},
areas: []
};
// 收集选项值
this.currentConfig.options.forEach(function(option, index) {
configData.options[option.id] = option.value || option.default;
});
// 收集区域数据
this.fabricCanvas.getObjects().forEach(function(obj) {
if (obj.data && obj.data.type === 'text') {
configData.areas.push({
type: 'text',
text: obj.text,
font_size: obj.fontSize,
font_family: obj.fontFamily,
color: obj.fill,
position: {
x: obj.left,
y: obj.top
}
});
}
});
// 生成预览图像
var previewData = this.fabricCanvas.toDataURL({
format: 'jpeg',
quality: 0.8
});
$.ajax({
url: fpc_ajax.ajax_url,
type: 'POST',
data: {
action: 'fpc_save_configuration',
nonce: fpc_ajax.nonce,
config_data: JSON.stringify(configData),
preview_image: previewData,
product_id: this.currentProductId
},
beforeSend: function() {
$('#fpc-saving').show();
},
success: function(response) {
if (response.success) {
self.showSuccess('配置已保存!');
// 更新购物车
self.addToCart(response.data.config_id);
} else {
self.showError(response.data);
}
},
error: function() {
self.showError(fpc_ajax.text.error);
},
complete: function() {
self.isSaving = false;
$('#fpc-saving').hide();
}
});
},
/**
* 添加到购物车
*/
addToCart: function(configId) {
$.ajax({
url: fpc_ajax.ajax_url,
type: 'POST',
data: {
action: 'fpc_add_to_cart',
nonce: fpc_ajax.nonce,
product_id: this.currentProductId,
config_id: configId
},
success: function(response) {
if (response.success) {
// 更新购物车数量
if (response.data.cart_count) {
$('.cart-count').text(response.data.cart_count);
}
self.showSuccess('已添加到购物车!');
}
}
});
},
/**
* 绑定事件
*/
bindEvents: function() {
var self = this;
// 保存按钮
$('#fpc-save-config').on('click', function() {
self.saveConfiguration();
});
// 重置按钮
$('#fpc-reset-config').on('click', function() {
if (confirm('确定要重置所有配置吗?')) {
self.loadProductConfig();
}
});
// 图片上传
$('#fpc-upload-image').on('change', function(e) {
self.handleImageUpload(e.target.files[0]);
});
},
/**
* 处理图片上传
*/
handleImageUpload: function(file) {
if (!file) return;
var reader = new FileReader();
var self = this;
reader.onload = function(e) {
fabric.Image.fromURL(e.target.result, function(img) {
// 添加图片到画布
img.set({
left: 100,
top: 100,
scaleX: 0.5,
scaleY: 0.5,
hasControls: true,
data: {
type: 'uploaded_image'
}
});
self.fabricCanvas.add(img);
self.fabricCanvas.setActiveObject(img);
});
};
reader.readAsDataURL(file);
},
/**
* 显示成功消息
*/
showSuccess: function(message) {
this.showMessage(message, 'success');
},
/**
* 显示错误消息
*/
showError: function(message) {
this.showMessage(message, 'error');
},
/**
* 显示消息
*/
showMessage: function(message, type) {
var $message = $('<div class="fpc-message fpc-message-' + type + '"></div>');
$message.text(message);
$('#fpc-messages').append($message);
setTimeout(function() {
$message.fadeOut(300, function() {
$(this).remove();
});
}, 3000);
}
};
// 文档加载完成后初始化
$(document).ready(function() {
FPC_Frontend.init();
});
})(jQuery);
## 五、AJAX处理类
### 5.1 创建AJAX处理器
创建 `includes/class-ajax-handler.php`:
<?php
/**
- AJAX请求处理器
*/
class FPC_Ajax_Handler {
private static $instance = null;
public static function get_instance() {
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct() {
// 注册AJAX动作
add_action('wp_ajax_fpc_get_product_config', array($this, 'get_product_config'));
add_action('wp_ajax_nopriv_fpc_get_product_config', array($this, 'get_product_config'));
add_action('wp_ajax_fpc_save_configuration', array($this, 'save_configuration'));
add_action('wp_ajax_nopriv_fpc_save_configuration', array($this, 'save_configuration'));
add_action('wp_ajax_fpc_add_to_cart', array($this, 'add_to_cart'));
add_action('wp_ajax_nopriv_fpc_add_to_cart', array($this, 'add_to_cart'));
add_action('wp_ajax_fpc_upload_image', array($this, 'upload_image'));
add_action('wp_ajax_nopriv_fpc_upload_image', array($this, 'upload_image'));
}
/**
* 获取产品配置
*/
public function get_product_config() {
// 验证nonce
if (!wp_verify_nonce($_POST['nonce'], 'fpc_nonce')) {
wp_die('安全验证失败');
}
$product_id = intval($_POST['product_id']);
if (!$product_id) {
wp_send_json_error('产品ID无效');
}
$configurator = FPC_Configurator::get_instance();
$options = $configurator->get_product_options($product_id);
// 添加默认值
if (!empty($options['options'])) {
foreach ($options['options'] as &$option) {
if (!isset($option['value']) && isset($option['default'])) {
$option['value'] = $option['default'];
}
}
}
wp_send_json_success($options);
}
/**
* 保存配置
*/
public function save_configuration() {
// 验证nonce
if (!wp_verify_nonce($_POST['nonce'], 'fpc_nonce')) {
wp_die('安全验证失败');
}
$product_id = intval($_POST['product_id']);
$config_data = json_decode(stripslashes($_POST['config_data']), true);
$preview_image = $_POST['preview_image'];
if (!$product_id || empty($config_data)) {
wp_send_json_error('数据无效');
}
global $wpdb;
$table_name = $wpdb->prefix . 'fpc_product_configs';
// 处理预览图片
$preview_url = '';
if (!empty($preview_image)) {
$preview_url = $this->save_preview_image($preview_image, $product_id);
}
// 保存到数据库
$data = array(
'product_id' => $product_id,
'user_id' => get_current_user_id(),
'config_data' => json_encode($config_data),
'preview_image' => $preview_url
);
$result = $wpdb->insert($table_name, $data);
if ($result) {
$config_id = $wpdb->insert_id;
// 创建配置的唯一标识符
$config_hash = wp_hash($config_id . time());
// 保存到用户会话
$user_configs = WC()->session->get('fpc_configurations', array());
$user_configs[$config_hash] = array(
'config_id' => $config_id,
'product_id' => $product_id,
'created' => time()
);
WC()->session->set('fpc_configurations', $user_configs);
wp_send_json_success(array(
'config_id' => $config_id,
'config_hash' => $config_hash
));
} else {
wp_send_json_error('保存配置失败');
}
}
/**
* 保存预览图片
*/
private function save_preview_image($base64_image, $product_id) {
// 移除base64头部
$base64_image = str_replace('data:image/jpeg;base64,', '', $base64_image);
$base64_image = str_replace(' ', '+', $base64_image);
// 解码图片
$image_data = base64_decode($base64_image);
if (!$image_data) {
return '';
}
// 创建上传目录
$upload_dir = wp_upload_dir();
$fpc_dir = $upload_dir['basedir'] . '/fpc-previews/';
if (!file_exists($fpc_dir)) {
wp_mkdir_p($fpc_dir);
}
// 生成文件名
$filename = 'product-' . $product_id . '-' . time() . '.jpg';
$filepath = $fpc_dir . $filename;
// 保存文件
if (file_put_contents($filepath, $image_data)) {
return $upload_dir['baseurl'] . '/fpc-previews/' . $filename;
}
return '';
}
/**
* 添加到购物车
*/
public function add_to_cart() {
// 验证nonce
if (!wp_verify_nonce($_POST['nonce'], 'fpc_nonce')) {
wp_die('安全验证失败');
}
$product_id = intval($_POST['product_id']);
$config_id = intval($_POST['config_id']);
if (!$product_id || !$config_id) {
wp_send_json_error('参数无效');
}
// 获取配置数据
global $wpdb;
$table_name = $wpdb->prefix . 'fpc_product_configs';
$config = $wpdb->get_row($wpdb->prepare(
"SELECT * FROM $table_name WHERE id = %d AND product_id = %d",
$config_id, $product_id
));
if (!$config) {
wp_send_json_error('配置不存在');
}
// 准备购物车数据
$cart_item_data = array(
'fpc_config_id' => $config_id,
'fpc_preview' => $config->preview_image,
'fpc_config_data' => json_decode($config->config_data, true)
);
// 添加到购物车
$cart_item_key = WC()->cart->add_to_cart(
$product_id,
1,
0,
array(),
$cart_item_data
);
if ($cart_item_key) {
wp_send_json_success(array(
'cart_count' => WC()->cart->get_cart_contents_count(),
'cart_item_key' => $cart_item_key
));
} else {
wp_send_json_error('添加到购物车失败');
}
}
/**
* 上传图片
*/
public function upload_image() {
// 验证nonce
if (!wp_verify_nonce($_POST['nonce'], 'fpc_nonce')) {
wp_die('安全验证失败');
}
if (!function_exists('wp_handle_upload')) {
require_once(ABSPATH . 'wp-admin/includes/file.php');
}
$uploadedfile = $_FILES['fpc_image'];
// 验证文件类型
$allowed_types = array('image/jpeg', 'image/png', 'image/gif');
if (!in_array($uploadedfile['type'], $allowed_types)) {
wp_send_json_error('不支持的文件类型');
}
// 验证文件大小(最大2MB)
if ($uploadedfile['size'] > 2 * 1024 * 1024) {
wp_send_json_error('文件大小不能超过2MB');
}
// 处理上传
$movefile = wp_handle_upload($uploadedfile, array('test_form' => false));
if ($movefile && !isset($movefile['error'])) {
wp_send_json_success(array(
'url' => $movefile['url'],
'file' => $movefile['file']
));
} else {
wp_send_json_error($movefile['error']);
}
}
}
## 六、管理界面实现
### 6.1 创建管理类
创建 `includes/class-admin.php`:
<?php
/**
- 管理界面类
*/
class FPC_Admin {
private static $instance = null;
public static function get_instance() {
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct() {
add_action('admin_menu', array($this, 'add_admin_menu'));
add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'));
add_action('add_meta_boxes', array($this, 'add_product_meta_box'));
add_action('save_post_product', array($this, 'save_product_meta'), 10, 2);
}
/**
* 添加管理菜单
*/
public function add_admin_menu() {
add_menu_page(
__('产品配置器', 'flexible-product-configurator'),
__('产品配置器', 'flexible-product-configurator'),
'manage_options',
'fpc-settings',
array($this, 'render_settings_page'),
'dashicons-admin-generic',
56
);
add_submenu_page(
'fpc-settings',
__('配置管理', 'flexible-product-configurator'),
__('配置管理', 'flexible-product-configurator'),
'manage_options',
'fpc-configs',
array($this, 'render_configs_page')
);
}
/**
* 加载管理脚本
*/
public function enqueue_admin_scripts($hook) {
global $post;
// 只在产品编辑页面和插件设置页面加载
if (($hook == 'post.php' && $post->post_type == 'product') ||
strpos($hook, 'fpc-') !== false) {
wp_enqueue_style(
'fpc-admin',
FPC_PLUGIN_URL . 'assets/css/admin.css',
array(),
FPC_VERSION
);
wp_enqueue_script(
'fpc-admin',
FPC_PLUGIN_URL . 'assets/js/admin.js',
array('jquery', 'jquery-ui-sortable'),
FPC_VERSION,
true
);
wp_localize_script('fpc-admin', 'fpc_admin', array(
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('fpc_admin_nonce'),
'text' => array(
'confirm_delete' => __('确定要删除这个选项吗?', 'flexible-product-configurator'),
'saving' => __('保存中...', 'flexible-product-configurator')
)
));
}
}
/**
* 添加产品元数据框
*/
public function add_product_meta_box() {
add_meta_box(
'fpc_product_configurator',
__('柔性产品配置器', 'flexible-product-configurator'),
array($this, 'render_product_meta_box'),
'product',
'normal',
'
