首页 / 教程文章 / WordPress小批量定制插件支持客户自助设计的实战教程

WordPress小批量定制插件支持客户自助设计的实战教程

WordPress小批量定制插件支持客户自助设计的实战教程

一、项目背景与需求分析

在当今数字化时代,许多中小型企业需要为其WordPress网站添加特定功能,但又不想投入大量资金开发完整插件。本教程将指导您创建一个支持客户自助设计的小批量定制插件,让用户能够通过简单界面自定义网站功能。

核心需求:

  1. 允许用户通过前端界面自定义内容展示
  2. 支持小批量配置(如颜色、文本、布局等)
  3. 数据安全且不影响网站性能
  4. 易于非技术人员操作

二、插件基础架构搭建

首先,我们创建插件的基本文件结构:

<?php
/**
 * Plugin Name: 客户自助设计工具
 * Plugin URI: https://yourwebsite.com/
 * Description: 允许客户通过前端界面自定义网站元素的小批量定制插件
 * Version: 1.0.0
 * Author: 您的名称
 * License: GPL v2 or later
 */

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

// 定义插件常量
define('CSD_PLUGIN_PATH', plugin_dir_path(__FILE__));
define('CSD_PLUGIN_URL', plugin_dir_url(__FILE__));
define('CSD_VERSION', '1.0.0');

// 初始化插件
class ClientSelfDesign {
    
    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_shortcode('csd_designer', array($this, 'render_designer_shortcode'));
        
        // 注册AJAX处理
        add_action('wp_ajax_csd_save_design', array($this, 'save_design'));
        add_action('wp_ajax_nopriv_csd_save_design', array($this, 'save_design'));
    }
    
    public function activate() {
        // 创建数据库表
        $this->create_database_table();
        
        // 设置默认选项
        add_option('csd_default_settings', array(
            'primary_color' => '#3498db',
            'secondary_color' => '#2ecc71',
            'max_designs_per_user' => 5,
            'allow_public_designs' => true
        ));
    }
    
    public function deactivate() {
        // 清理临时数据
        delete_transient('csd_recent_designs');
    }
    
    public function init() {
        // 加载文本域
        load_plugin_textdomain('csd', false, dirname(plugin_basename(__FILE__)) . '/languages');
    }
    
    // 其他方法将在下面实现
}

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

三、数据库设计与数据存储

接下来,我们创建存储用户设计的数据库表:

// 在ClientSelfDesign类中添加以下方法

private function create_database_table() {
    global $wpdb;
    
    $table_name = $wpdb->prefix . 'csd_designs';
    $charset_collate = $wpdb->get_charset_collate();
    
    $sql = "CREATE TABLE IF NOT EXISTS $table_name (
        id mediumint(9) NOT NULL AUTO_INCREMENT,
        user_id bigint(20) NOT NULL,
        design_name varchar(100) NOT NULL,
        design_data longtext NOT NULL,
        design_type varchar(50) DEFAULT 'basic',
        is_public tinyint(1) DEFAULT 0,
        created_at datetime DEFAULT CURRENT_TIMESTAMP,
        updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        PRIMARY KEY (id),
        KEY user_id (user_id),
        KEY design_type (design_type)
    ) $charset_collate;";
    
    require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    dbDelta($sql);
    
    // 添加版本号,便于后续升级
    add_option('csd_db_version', '1.0');
}

四、前端设计器界面实现

创建用户自助设计的前端界面:

// 在ClientSelfDesign类中添加以下方法

public function render_designer_shortcode($atts) {
    // 短代码属性处理
    $atts = shortcode_atts(array(
        'type' => 'basic',
        'max_elements' => 10
    ), $atts, 'csd_designer');
    
    // 检查用户权限
    if (!is_user_logged_in()) {
        return '<div class="csd-login-required">' . 
               __('请先登录以使用设计工具', 'csd') . 
               wp_login_url(get_permalink()) . 
               '</div>';
    }
    
    // 获取用户现有设计数量
    $user_id = get_current_user_id();
    $design_count = $this->get_user_design_count($user_id);
    $max_designs = get_option('csd_default_settings')['max_designs_per_user'];
    
    if ($design_count >= $max_designs) {
        return '<div class="csd-limit-reached">' . 
               sprintf(__('您已达到最大设计数量(%d),请删除一些旧设计以创建新设计', 'csd'), $max_designs) . 
               '</div>';
    }
    
    // 输出设计器HTML
    ob_start();
    ?>
    <div id="csd-designer-container" class="csd-designer" data-type="<?php echo esc_attr($atts['type']); ?>">
        <div class="csd-header">
            <h2><?php _e('自助设计工具', 'csd'); ?></h2>
            <div class="csd-design-count">
                <?php printf(__('已使用: %d/%d', 'csd'), $design_count, $max_designs); ?>
            </div>
        </div>
        
        <div class="csd-toolbar">
            <div class="csd-tool-group">
                <button type="button" class="csd-tool-btn" data-tool="text">
                    <span class="dashicons dashicons-editor-textcolor"></span>
                    <?php _e('添加文本', 'csd'); ?>
                </button>
                <button type="button" class="csd-tool-btn" data-tool="image">
                    <span class="dashicons dashicons-format-image"></span>
                    <?php _e('添加图片', 'csd'); ?>
                </button>
                <button type="button" class="csd-tool-btn" data-tool="shape">
                    <span class="dashicons dashicons-forms"></span>
                    <?php _e('添加形状', 'csd'); ?>
                </button>
            </div>
            
            <div class="csd-color-picker">
                <label><?php _e('主题色:', 'csd'); ?></label>
                <input type="color" id="csd-primary-color" value="#3498db">
                <input type="color" id="csd-secondary-color" value="#2ecc71">
            </div>
        </div>
        
        <div class="csd-workspace">
            <div class="csd-canvas" id="csd-design-canvas">
                <!-- 设计元素将在这里动态添加 -->
                <div class="csd-default-message">
                    <?php _e('从工具栏选择工具开始设计', 'csd'); ?>
                </div>
            </div>
            
            <div class="csd-properties-panel">
                <h3><?php _e('属性设置', 'csd'); ?></h3>
                <div id="csd-properties-form">
                    <!-- 属性表单将根据选中元素动态加载 -->
                </div>
            </div>
        </div>
        
        <div class="csd-footer">
            <div class="csd-design-info">
                <input type="text" id="csd-design-name" 
                       placeholder="<?php esc_attr_e('输入设计名称', 'csd'); ?>" 
                       maxlength="100">
                <label>
                    <input type="checkbox" id="csd-design-public">
                    <?php _e('公开此设计', 'csd'); ?>
                </label>
            </div>
            
            <div class="csd-actions">
                <button type="button" id="csd-preview-btn" class="button">
                    <?php _e('预览', 'csd'); ?>
                </button>
                <button type="button" id="csd-save-btn" class="button button-primary">
                    <?php _e('保存设计', 'csd'); ?>
                </button>
                <button type="button" id="csd-reset-btn" class="button button-secondary">
                    <?php _e('重置', 'csd'); ?>
                </button>
            </div>
        </div>
        
        <!-- 预览模态框 -->
        <div id="csd-preview-modal" class="csd-modal" style="display:none;">
            <div class="csd-modal-content">
                <span class="csd-close-modal">&times;</span>
                <h3><?php _e('设计预览', 'csd'); ?></h3>
                <div id="csd-preview-content"></div>
            </div>
        </div>
    </div>
    
    <!-- 加载JavaScript -->
    <script type="text/javascript">
    var csd_ajax_url = '<?php echo admin_url('admin-ajax.php'); ?>';
    var csd_nonce = '<?php echo wp_create_nonce('csd_save_design_nonce'); ?>';
    var csd_user_id = <?php echo $user_id; ?>;
    </script>
    <?php
    
    return ob_get_clean();
}

// 获取用户设计数量
private function get_user_design_count($user_id) {
    global $wpdb;
    $table_name = $wpdb->prefix . 'csd_designs';
    
    return $wpdb->get_var($wpdb->prepare(
        "SELECT COUNT(*) FROM $table_name WHERE user_id = %d",
        $user_id
    ));
}

五、JavaScript交互与AJAX处理

创建前端交互逻辑:

// 创建文件: assets/js/csd-designer.js
jQuery(document).ready(function($) {
    'use strict';
    
    var CSD_Designer = {
        currentTool: null,
        selectedElement: null,
        designData: {
            elements: [],
            colors: {
                primary: '#3498db',
                secondary: '#2ecc71'
            },
            settings: {}
        },
        
        init: function() {
            this.bindEvents();
            this.loadColorSettings();
        },
        
        bindEvents: function() {
            // 工具按钮点击
            $('.csd-tool-btn').on('click', this.handleToolClick.bind(this));
            
            // 颜色选择器变化
            $('#csd-primary-color, #csd-secondary-color').on('change', this.handleColorChange.bind(this));
            
            // 保存设计
            $('#csd-save-btn').on('click', this.saveDesign.bind(this));
            
            // 预览设计
            $('#csd-preview-btn').on('click', this.previewDesign.bind(this));
            
            // 重置设计
            $('#csd-reset-btn').on('click', this.resetDesign.bind(this));
            
            // 关闭模态框
            $('.csd-close-modal').on('click', function() {
                $('#csd-preview-modal').hide();
            });
        },
        
        handleToolClick: function(e) {
            var tool = $(e.currentTarget).data('tool');
            this.currentTool = tool;
            
            switch(tool) {
                case 'text':
                    this.addTextElement();
                    break;
                case 'image':
                    this.addImageElement();
                    break;
                case 'shape':
                    this.addShapeElement();
                    break;
            }
        },
        
        addTextElement: function() {
            var elementId = 'element_' + Date.now();
            var element = {
                id: elementId,
                type: 'text',
                content: '新文本',
                styles: {
                    fontSize: '16px',
                    color: this.designData.colors.primary,
                    fontWeight: 'normal',
                    textAlign: 'left'
                },
                position: { x: 50, y: 50 }
            };
            
            this.designData.elements.push(element);
            this.renderElement(element);
            this.selectElement(elementId);
        },
        
        addImageElement: function() {
            // 创建图片上传逻辑
            this.openMediaUploader();
        },
        
        addShapeElement: function() {
            var elementId = 'element_' + Date.now();
            var element = {
                id: elementId,
                type: 'shape',
                shapeType: 'rectangle',
                styles: {
                    backgroundColor: this.designData.colors.secondary,
                    width: '100px',
                    height: '100px',
                    borderRadius: '0px'
                },
                position: { x: 100, y: 100 }
            };
            
            this.designData.elements.push(element);
            this.renderElement(element);
            this.selectElement(elementId);
        },
        
        renderElement: function(element) {
            var $canvas = $('#csd-design-canvas');
            var $element = $('<div class="csd-element"></div>')
                .attr('id', element.id)
                .css({
                    position: 'absolute',
                    left: element.position.x + 'px',
                    top: element.position.y + 'px'
                })
                .data('element-data', element);
            
            switch(element.type) {
                case 'text':
                    $element.addClass('csd-text-element')
                        .text(element.content)
                        .css(element.styles);
                    break;
                case 'shape':
                    $element.addClass('csd-shape-element')
                        .css(element.styles);
                    break;
            }
            
            $element.on('click', this.handleElementClick.bind(this));
            $canvas.append($element);
        },
        
        handleElementClick: function(e) {
            var elementId = $(e.currentTarget).attr('id');
            this.selectElement(elementId);
        },
        
        selectElement: function(elementId) {
            this.selectedElement = elementId;
            $('.csd-element').removeClass('selected');
            $('#' + elementId).addClass('selected');
            this.loadPropertiesForm(elementId);
        },
        
        loadPropertiesForm: function(elementId) {
            var element = this.getElementById(elementId);
            if (!element) return;
            
            var formHtml = '';
            
            switch(element.type) {
                case 'text':
                    formHtml = this.getTextPropertiesForm(element);
                    break;
                case 'shape':
                    formHtml = this.getShapePropertiesForm(element);
                    break;
            }
            
            $('#csd-properties-form').html(formHtml);
            this.bindPropertiesEvents();
        },
        
        getTextPropertiesForm: function(element) {
            return `
                <div class="csd-property-group">
                    <label>文本内容:</label>
                    <input type="text" class="csd-property-input" 
                           data-property="content" 
                           value="${element.content}">
                </div>
                <div class="csd-property-group">
                    <label>字体大小:</label>
                    <input type="range" class="csd-property-input" 
                           data-property="fontSize" min="8" max="72"
                           value="${parseInt(element.styles.fontSize)}">
                    <span class="csd-property-value">${element.styles.fontSize}</span>
                </div>
                <div class="csd-property-group">
                    <label>文字颜色:</label>
                    <input type="color" class="csd-property-input" 
                           data-property="color"
                           value="${element.styles.color}">
                </div>
            `;
        },
        
        bindPropertiesEvents: function() {
            var self = this;
            
            $('.csd-property-input').on('input change', function() {
                var property = $(this).data('property');
                var value = $(this).val();
                
                if ($(this).attr('type') === 'range') {
                    value = value + 'px';
                    $(this).siblings('.csd-property-value').text(value);
                }
                
                self.updateSelectedElement(property, value);
            });
        },
        
        updateSelectedElement: function(property, value) {
            if (!this.selectedElement) return;
            
            var element = this.getElementById(this.selectedElement);
            if (!element) return;
            
            if (property === 'content') {
                element.content = value;
                $('#' + this.selectedElement).text(value);
            } else {
                element.styles[property] = value;
                $('#' + this.selectedElement).css(property, value);
            }
        },
        
        getElementById: function(elementId) {
            return this.designData.elements.find(function(el) {
                return el.id === elementId;
            });
        },
        
        handleColorChange: function(e) {
            var colorType = e.target.id.replace('csd-', '').replace('-color', '');
            this.designData.colors[colorType] = $(e.target).val();
        },
        
        saveDesign: function() {
            var designName = $('#csd-design-name').val().trim();
            var isPublic = $('#csd-design-public').is(':checked') ? 1 : 0;
            
            if (!designName) {
                alert('请输入设计名称');
                return;
            }
            
            var designData = {
                name: designName,
                data: this.designData,
                is_public: isPublic
            };
            
            $.ajax({
                url: csd_ajax_url,
                type: 'POST',
                data: {
                    action: 'csd_save_design',
                    nonce: csd_nonce,
                    user_id: csd_user_id,
                    design_data: designData
                },
                beforeSend: function() {

true).text('保存中...');

            },
            success: function(response) {
                if (response.success) {
                    alert('设计保存成功!');
                    // 刷新页面显示新设计
                    location.reload();
                } else {
                    alert('保存失败: ' + response.data);
                }
            },
            error: function() {
                alert('网络错误,请重试');
            },
            complete: function() {
                $('#csd-save-btn').prop('disabled', false).text('保存设计');
            }
        });
    },
    
    previewDesign: function() {
        var previewHtml = '<div class="csd-preview-container">';
        
        this.designData.elements.forEach(function(element) {
            previewHtml += '<div class="csd-preview-element" style="';
            previewHtml += 'position:absolute;';
            previewHtml += 'left:' + element.position.x + 'px;';
            previewHtml += 'top:' + element.position.y + 'px;';
            
            for (var style in element.styles) {
                previewHtml += style + ':' + element.styles[style] + ';';
            }
            
            previewHtml += '">';
            previewHtml += element.content || '';
            previewHtml += '</div>';
        });
        
        previewHtml += '</div>';
        
        $('#csd-preview-content').html(previewHtml);
        $('#csd-preview-modal').show();
    },
    
    resetDesign: function() {
        if (confirm('确定要重置所有设计吗?')) {
            this.designData.elements = [];
            $('#csd-design-canvas').html('<div class="csd-default-message">从工具栏选择工具开始设计</div>');
            $('#csd-properties-form').empty();
            this.selectedElement = null;
        }
    },
    
    loadColorSettings: function() {
        this.designData.colors.primary = $('#csd-primary-color').val();
        this.designData.colors.secondary = $('#csd-secondary-color').val();
    },
    
    openMediaUploader: function() {
        var frame = wp.media({
            title: '选择图片',
            multiple: false,
            library: {
                type: 'image'
            },
            button: {
                text: '使用此图片'
            }
        });
        
        frame.on('select', function() {
            var attachment = frame.state().get('selection').first().toJSON();
            CSD_Designer.addImageFromMedia(attachment);
        });
        
        frame.open();
    },
    
    addImageFromMedia: function(attachment) {
        var elementId = 'element_' + Date.now();
        var element = {
            id: elementId,
            type: 'image',
            url: attachment.url,
            alt: attachment.alt,
            styles: {
                width: '200px',
                height: 'auto'
            },
            position: { x: 150, y: 150 }
        };
        
        this.designData.elements.push(element);
        
        var $canvas = $('#csd-design-canvas');
        var $img = $('<img>')
            .attr('src', attachment.url)
            .attr('alt', attachment.alt)
            .css({
                position: 'absolute',
                left: element.position.x + 'px',
                top: element.position.y + 'px',
                width: element.styles.width
            })
            .addClass('csd-element csd-image-element')
            .attr('id', elementId)
            .data('element-data', element);
        
        $img.on('click', this.handleElementClick.bind(this));
        $canvas.append($img);
        this.selectElement(elementId);
    }
};

// 初始化设计器
CSD_Designer.init();

});


## 六、后端数据处理与保存

实现AJAX保存功能:

// 在ClientSelfDesign类中添加以下方法

public function save_design() {

// 验证nonce
if (!wp_verify_nonce($_POST['nonce'], 'csd_save_design_nonce')) {
    wp_die('安全验证失败');
}

// 验证用户权限
$user_id = intval($_POST['user_id']);
if ($user_id !== get_current_user_id()) {
    wp_die('用户权限错误');
}

// 获取并清理数据
$design_data = json_decode(stripslashes($_POST['design_data']), true);

if (!$design_data) {
    wp_send_json_error('无效的设计数据');
}

// 验证设计数量限制
$max_designs = get_option('csd_default_settings')['max_designs_per_user'];
$current_count = $this->get_user_design_count($user_id);

if ($current_count >= $max_designs) {
    wp_send_json_error('已达到最大设计数量限制');
}

// 保存到数据库
global $wpdb;
$table_name = $wpdb->prefix . 'csd_designs';

$result = $wpdb->insert(
    $table_name,
    array(
        'user_id' => $user_id,
        'design_name' => sanitize_text_field($design_data['name']),
        'design_data' => json_encode($design_data['data']),
        'design_type' => 'custom',
        'is_public' => $design_data['is_public'] ? 1 : 0
    ),
    array('%d', '%s', '%s', '%s', '%d')
);

if ($result) {
    // 清除缓存
    delete_transient('csd_user_designs_' . $user_id);
    
    wp_send_json_success(array(
        'design_id' => $wpdb->insert_id,
        'message' => '设计保存成功'
    ));
} else {
    wp_send_json_error('数据库保存失败');
}

}

// 添加获取用户设计的函数
public function get_user_designs($user_id) {

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

$cache_key = 'csd_user_designs_' . $user_id;
$designs = get_transient($cache_key);

if (false === $designs) {
    $designs = $wpdb->get_results($wpdb->prepare(
        "SELECT * FROM $table_name WHERE user_id = %d ORDER BY created_at DESC",
        $user_id
    ), ARRAY_A);
    
    set_transient($cache_key, $designs, HOUR_IN_SECONDS);
}

return $designs;

}


## 七、管理界面与样式优化

创建管理后台界面:

// 在ClientSelfDesign类中添加以下方法

public function add_admin_menu() {

add_menu_page(
    '客户设计管理',
    '客户设计',
    'manage_options',
    'csd-designs',
    array($this, 'render_admin_page'),
    'dashicons-art',
    30
);

add_submenu_page(
    'csd-designs',
    '设计设置',
    '设置',
    'manage_options',
    'csd-settings',
    array($this, 'render_settings_page')
);

}

public function render_admin_page() {

?>
<div class="wrap">
    <h1><?php _e('客户设计管理', 'csd'); ?></h1>
    
    <div class="csd-admin-container">
        <div class="csd-stats">
            <?php
            global $wpdb;
            $table_name = $wpdb->prefix . 'csd_designs';
            
            $total_designs = $wpdb->get_var("SELECT COUNT(*) FROM $table_name");
            $total_users = $wpdb->get_var("SELECT COUNT(DISTINCT user_id) FROM $table_name");
            $public_designs = $wpdb->get_var("SELECT COUNT(*) FROM $table_name WHERE is_public = 1");
            ?>
            
            <div class="csd-stat-card">
                <h3><?php echo $total_designs; ?></h3>
                <p>总设计数</p>
            </div>
            
            <div class="csd-stat-card">
                <h3><?php echo $total_users; ?></h3>
                <p>使用用户数</p>
            </div>
            
            <div class="csd-stat-card">
                <h3><?php echo $public_designs; ?></h3>
                <p>公开设计数</p>
            </div>
        </div>
        
        <table class="wp-list-table widefat fixed striped">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>设计名称</th>
                    <th>用户</th>
                    <th>类型</th>
                    <th>公开</th>
                    <th>创建时间</th>
                    <th>操作</th>
                </tr>
            </thead>
            <tbody>
                <?php
                $designs = $wpdb->get_results(
                    "SELECT d.*, u.user_login 
                     FROM $table_name d 
                     LEFT JOIN {$wpdb->users} u ON d.user_id = u.ID 
                     ORDER BY d.created_at DESC 
                     LIMIT 50"
                );
                
                foreach ($designs as $design) {
                    ?>
                    <tr>
                        <td><?php echo $design->id; ?></td>
                        <td><?php echo esc_html($design->design_name); ?></td>
                        <td><?php echo $design->user_login ?: '游客'; ?></td>
                        <td><?php echo $design->design_type; ?></td>
                        <td><?php echo $design->is_public ? '是' : '否'; ?></td>
                        <td><?php echo date('Y-m-d H:i', strtotime($design->created_at)); ?></td>
                        <td>
                            <button class="button button-small csd-preview-btn" 
                                    data-design-id="<?php echo $design->id; ?>">
                                预览
                            </button>
                            <button class="button button-small button-link-delete csd-delete-btn"
                                    data-design-id="<?php echo $design->id; ?>">
                                删除
                            </button>
                        </td>
                    </tr>
                    <?php
                }
                ?>
            </tbody>
        </table>
    </div>
</div>
<?php

}

public function render_settings_page() {

$settings = get_option('csd_default_settings', array());

if ($_SERVER['REQUEST_METHOD'] === 'POST' && check_admin_referer('csd_settings_update')) {
    $new_settings = array(
        'primary_color' => sanitize_hex_color($_POST['primary_color']),
        'secondary_color' => sanitize_hex_color($_POST['secondary_color']),
        'max_designs_per_user' => intval($_POST['max_designs_per_user']),
        'allow_public_designs' => isset($_POST['allow_public_designs']) ? true : false
    );
    
    update_option('csd_default_settings', $new_settings);
    $settings = $new_settings;
    
    echo '<div class="notice notice-success"><p>设置已保存</p></div>';
}
?>
<div class="wrap">
    <h1><?php _e('设计工具设置', 'csd'); ?></h1>
    
    <form method="post" action="">
        <?php wp_nonce_field('csd_settings_update'); ?>
        
        <table class="form-table">
            <tr>
                <th scope="row">主色调</th>
                <td>
                    <input type="color" name="primary_color" 
                           value="<?php echo esc_attr($settings['primary_color']); ?>">
                </td>
            </tr>
            
            <tr>
                <th scope="row">辅色调</th>
                <td>
                    <input type="color" name="secondary_color" 
                           value="<?php echo esc_attr($settings['secondary_color']); ?>">
                </td>
            </tr>
            
            <tr>
                <th scope="row">用户最大设计数</th>
                <td>
                    <input type="number" name="max_designs_per_user" 
                           value="<?php echo esc_attr($settings['max_designs_per_user']); ?>"
                           min="1" max="50">
                    <p class="description">每个用户最多可以保存的设计数量</p>
                </td>
            </tr>
            
            <tr>
                <th scope="row">允许公开设计</th>
                <td>
                    <label>
                        <input type="checkbox" name="allow_public_designs" value="1" 
                               <?php checked($settings['allow_public_designs']); ?>>
                        允许用户将设计设为公开
                    </label>
                </td>
            </tr>
        </table>
        
        <?php submit_button(); ?>
    </form>
</div>
<?php

}


## 八、CSS样式文件

创建插件样式文件:

/ 创建文件: assets/css/csd-designer.css /

/ 设计器主容器 /
.csd-designer {

background: #fff;
border: 1px solid #ddd;
border-radius: 4px;
padding: 20px;
margin: 20px 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;

}

/ 头部样式 /
.csd-header {

display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding-bottom: 15px;
border-bottom: 2px solid #f0f0f0;

}

.csd-header h2 {

margin: 0;
color: #333;

}

.csd-design-count {

background: #f7f7f7;
padding: 5px 10px;
border-radius: 3px;
font-size: 14px;
color: #666;

}

/ 工具栏样式 /
.csd-toolbar {

background: #f9f9f9;
padding: 15px;
border-radius: 4px;
margin-bottom: 20px;
display: flex;
justify-content: space-between;
align-items: center;

}

.csd-tool-group {

display: flex;
gap: 10px;

}

.csd-tool-btn {

display: flex;
align-items: center;
gap: 5px;
padding: 8px 15px;
background: #fff;
border: 1px solid #ddd;
border-radius: 3px;
cursor: pointer;
transition: all 0.3s ease;

}

.csd-tool-btn:hover {

background: #f0f0f0;
border-color: #999;

}

.csd-tool-btn .dashicons {

font-size: 16px;
width: 16px;
height: 16px;

}

.csd-color-picker {

display: flex;
align-items: center;
gap: 10px;

}

.csd-color-picker label {

font-weight: 600;
color: #555;

}

.csd-color-picker input[type="color"] {

width: 40px;
height: 40px;
border: 2px solid #ddd;
border-radius: 4px;
cursor: pointer;

}

/ 工作区样式 /
.csd-workspace {

display: grid;
grid-template-columns: 3fr 1fr;
gap: 20px;
min-height: 500px;

}

.csd-canvas {

background: #f8f9fa;
border: 2px dashed #dee2e6;
border-radius: 4px;
position: relative;
min-height: 500px;

}

.csd-default-message {

position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #6c757d;
font-size: 16px;

}

/ 设计元素样式 /
.csd-element {

cursor: move;
user-select: none;
transition: all 0.2s ease;

}

.csd-element.selected {

outline: 2px solid #007cba;
outline-offset: 2px;

}

.csd-text-element {

padding: 5px;
min-width: 50px;
min-height: 20px;

}

.csd-shape-element {

background: #3498db;

}

/ 属性面板样式 /
.csd-properties-panel {

background: #fff;
border: 1px solid #ddd;
border-radius: 4px;
padding: 15px;

}

.csd-properties-panel h3 {

margin-top: 0;
margin-bottom: 15px;
color: #333;
font-size: 16px;

}

.csd-property-group {

margin-bottom: 15px;

}

.csd-property-group label {

display: block;
margin-bottom: 5px;
font-weight: 600;
color: #555;
font-size: 14px;

}

.csd-property-input {

width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 3px;
font-size: 14px;

}

.csd-property-value {

display: inline-block;
margin-left: 10px;
font-size: 14px;
color: #666;

}

/ 底部样式 /
.csd-footer {

margin-top: 20px;
padding-top: 20px;
border-top: 1px solid #eee;
display: flex;
justify-content: space-between;
align-items: center;

}

.csd-design-info {

display: flex;
gap: 15px;
align-items: center;

}

csd-design-name {

padding: 8px 12px;
border: 1px solid #ddd;
border-radius: 3px;
width: 200px;

}

.csd-design-info label {

display: flex;
align-items: center;
gap: 5px;
font-size: 14px;
color: #555;

}

.csd-actions {

display: flex;
gap: 10px;

}

/ 模态框样式 /
.csd-modal {

display: none;
position: fixed;
z-index: 1000;
left
本文来自网络,不代表柔性供应链服务中心立场,转载请注明出处:https://mall.org.cn/6431.html

EXCHANGES®作者

上一篇
下一篇

为您推荐

发表回复

联系我们

联系我们

18559313275

在线咨询: QQ交谈

邮箱: vip@exchanges.center

工作时间:周一至周五,9:00-17:30,节假日休息
返回顶部