首页 / 教程文章 / WordPress小批量定制插件实现供应商在线打样的教程

WordPress小批量定制插件实现供应商在线打样的教程

WordPress小批量定制插件实现供应商在线打样教程

概述:为什么需要在线打样功能

在定制产品行业中,供应商与客户之间的沟通效率直接影响业务成败。传统打样流程通常涉及多次邮件往来、文件传输和实物寄送,耗时耗力。通过WordPress插件实现在线打样功能,可以让客户直接在网站上提交设计需求,供应商实时查看并反馈,大幅缩短打样周期。

本教程将指导您开发一个完整的WordPress小批量定制插件,实现供应商在线打样功能。我们将从环境搭建开始,逐步实现用户提交、供应商审核、在线标注和版本管理等功能。

环境准备与插件基础结构

首先,我们需要创建一个标准的WordPress插件。在wp-content/plugins目录下创建新文件夹"custom-sampling"。

<?php
/**
 * Plugin Name: 小批量定制在线打样系统
 * Plugin URI: https://yourwebsite.com/
 * Description: 实现供应商在线打样功能的WordPress插件
 * Version: 1.0.0
 * Author: 您的名称
 * License: GPL v2 or later
 * Text Domain: custom-sampling
 */

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

// 定义插件常量
define('CS_PLUGIN_PATH', plugin_dir_path(__FILE__));
define('CS_PLUGIN_URL', plugin_dir_url(__FILE__));
define('CS_VERSION', '1.0.0');

// 初始化插件
class CustomSamplingPlugin {
    
    private static $instance = null;
    
    public static function get_instance() {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    private function __construct() {
        $this->init_hooks();
    }
    
    private function init_hooks() {
        // 激活/停用钩子
        register_activation_hook(__FILE__, array($this, 'activate'));
        register_deactivation_hook(__FILE__, array($this, 'deactivate'));
        
        // 初始化
        add_action('init', array($this, 'init'));
        
        // 管理菜单
        add_action('admin_menu', array($this, 'add_admin_menu'));
        
        // 前端脚本和样式
        add_action('wp_enqueue_scripts', array($this, 'enqueue_frontend_assets'));
        
        // 管理端脚本和样式
        add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_assets'));
    }
    
    public function activate() {
        $this->create_tables();
        flush_rewrite_rules();
    }
    
    public function deactivate() {
        flush_rewrite_rules();
    }
    
    public function init() {
        // 加载文本域
        load_plugin_textdomain('custom-sampling', false, dirname(plugin_basename(__FILE__)) . '/languages');
    }
    
    // 创建数据库表
    private function create_tables() {
        global $wpdb;
        
        $charset_collate = $wpdb->get_charset_collate();
        $table_name = $wpdb->prefix . 'custom_sampling_requests';
        
        $sql = "CREATE TABLE IF NOT EXISTS $table_name (
            id mediumint(9) NOT NULL AUTO_INCREMENT,
            customer_id mediumint(9) NOT NULL,
            product_name varchar(255) NOT NULL,
            design_files text NOT NULL,
            specifications text NOT NULL,
            status varchar(50) DEFAULT 'pending',
            supplier_notes text,
            revised_files text,
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
            PRIMARY KEY (id)
        ) $charset_collate;";
        
        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
        dbDelta($sql);
    }
    
    // 添加管理菜单
    public function add_admin_menu() {
        add_menu_page(
            '在线打样管理',
            '在线打样',
            'manage_options',
            'custom-sampling',
            array($this, 'render_admin_page'),
            'dashicons-format-image',
            30
        );
        
        add_submenu_page(
            'custom-sampling',
            '打样请求',
            '所有请求',
            'manage_options',
            'custom-sampling',
            array($this, 'render_admin_page')
        );
        
        add_submenu_page(
            'custom-sampling',
            '供应商设置',
            '供应商设置',
            'manage_options',
            'custom-sampling-suppliers',
            array($this, 'render_suppliers_page')
        );
    }
    
    public function render_admin_page() {
        include CS_PLUGIN_PATH . 'templates/admin/main.php';
    }
    
    public function render_suppliers_page() {
        include CS_PLUGIN_PATH . 'templates/admin/suppliers.php';
    }
    
    public function enqueue_frontend_assets() {
        wp_enqueue_style(
            'custom-sampling-frontend',
            CS_PLUGIN_URL . 'assets/css/frontend.css',
            array(),
            CS_VERSION
        );
        
        wp_enqueue_script(
            'custom-sampling-frontend',
            CS_PLUGIN_URL . 'assets/js/frontend.js',
            array('jquery'),
            CS_VERSION,
            true
        );
        
        // 本地化脚本
        wp_localize_script('custom-sampling-frontend', 'cs_ajax', array(
            'ajax_url' => admin_url('admin-ajax.php'),
            'nonce' => wp_create_nonce('custom_sampling_nonce')
        ));
    }
    
    public function enqueue_admin_assets($hook) {
        if (strpos($hook, 'custom-sampling') === false) {
            return;
        }
        
        wp_enqueue_style(
            'custom-sampling-admin',
            CS_PLUGIN_URL . 'assets/css/admin.css',
            array(),
            CS_VERSION
        );
        
        wp_enqueue_script(
            'custom-sampling-admin',
            CS_PLUGIN_URL . 'assets/js/admin.js',
            array('jquery', 'wp-color-picker'),
            CS_VERSION,
            true
        );
        
        // 引入图像标注库
        wp_enqueue_script(
            'fabric-js',
            'https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.5.0/fabric.min.js',
            array(),
            '4.5.0',
            true
        );
    }
}

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

数据库设计与数据模型

在线打样系统的核心是高效的数据管理。我们设计了以下数据表结构来存储打样请求信息:

<?php
/**
 * 打样请求数据模型
 * 处理所有与打样请求相关的数据库操作
 */

class SamplingRequestModel {
    
    private $table_name;
    
    public function __construct() {
        global $wpdb;
        $this->table_name = $wpdb->prefix . 'custom_sampling_requests';
    }
    
    /**
     * 创建新的打样请求
     * @param array $data 请求数据
     * @return int|false 插入ID或false
     */
    public function create_request($data) {
        global $wpdb;
        
        $defaults = array(
            'customer_id' => get_current_user_id(),
            'product_name' => '',
            'design_files' => '',
            'specifications' => '',
            'status' => 'pending',
            'supplier_notes' => '',
            'revised_files' => ''
        );
        
        $data = wp_parse_args($data, $defaults);
        
        // 序列化数组字段
        if (is_array($data['design_files'])) {
            $data['design_files'] = serialize($data['design_files']);
        }
        
        if (is_array($data['revised_files'])) {
            $data['revised_files'] = serialize($data['revised_files']);
        }
        
        $result = $wpdb->insert(
            $this->table_name,
            $data,
            array('%d', '%s', '%s', '%s', '%s', '%s', '%s')
        );
        
        return $result ? $wpdb->insert_id : false;
    }
    
    /**
     * 获取打样请求
     * @param int $id 请求ID
     * @return array|null 请求数据或null
     */
    public function get_request($id) {
        global $wpdb;
        
        $query = $wpdb->prepare(
            "SELECT * FROM {$this->table_name} WHERE id = %d",
            $id
        );
        
        $request = $wpdb->get_row($query, ARRAY_A);
        
        if ($request) {
            // 反序列化数组字段
            $request['design_files'] = maybe_unserialize($request['design_files']);
            $request['revised_files'] = maybe_unserialize($request['revised_files']);
        }
        
        return $request;
    }
    
    /**
     * 更新打样请求
     * @param int $id 请求ID
     * @param array $data 更新数据
     * @return bool 是否成功
     */
    public function update_request($id, $data) {
        global $wpdb;
        
        // 序列化数组字段
        if (isset($data['design_files']) && is_array($data['design_files'])) {
            $data['design_files'] = serialize($data['design_files']);
        }
        
        if (isset($data['revised_files']) && is_array($data['revised_files'])) {
            $data['revised_files'] = serialize($data['revised_files']);
        }
        
        $result = $wpdb->update(
            $this->table_name,
            $data,
            array('id' => $id),
            array('%s', '%s', '%s', '%s', '%s', '%s'),
            array('%d')
        );
        
        return $result !== false;
    }
    
    /**
     * 获取用户的所有打样请求
     * @param int $user_id 用户ID
     * @param string $status 状态筛选
     * @return array 请求列表
     */
    public function get_user_requests($user_id, $status = '') {
        global $wpdb;
        
        $where = "WHERE customer_id = %d";
        $params = array($user_id);
        
        if (!empty($status)) {
            $where .= " AND status = %s";
            $params[] = $status;
        }
        
        $query = $wpdb->prepare(
            "SELECT * FROM {$this->table_name} {$where} ORDER BY created_at DESC",
            $params
        );
        
        $requests = $wpdb->get_results($query, ARRAY_A);
        
        // 反序列化数组字段
        foreach ($requests as &$request) {
            $request['design_files'] = maybe_unserialize($request['design_files']);
            $request['revised_files'] = maybe_unserialize($request['revised_files']);
        }
        
        return $requests;
    }
    
    /**
     * 获取所有打样请求(管理员)
     * @param array $args 查询参数
     * @return array 请求列表
     */
    public function get_all_requests($args = array()) {
        global $wpdb;
        
        $defaults = array(
            'status' => '',
            'page' => 1,
            'per_page' => 20,
            'search' => ''
        );
        
        $args = wp_parse_args($args, $defaults);
        
        $where = "WHERE 1=1";
        $params = array();
        
        if (!empty($args['status'])) {
            $where .= " AND status = %s";
            $params[] = $args['status'];
        }
        
        if (!empty($args['search'])) {
            $where .= " AND (product_name LIKE %s OR specifications LIKE %s)";
            $search_term = '%' . $wpdb->esc_like($args['search']) . '%';
            $params[] = $search_term;
            $params[] = $search_term;
        }
        
        $offset = ($args['page'] - 1) * $args['per_page'];
        
        $query = $wpdb->prepare(
            "SELECT SQL_CALC_FOUND_ROWS * FROM {$this->table_name} 
             {$where} 
             ORDER BY created_at DESC 
             LIMIT %d, %d",
            array_merge($params, array($offset, $args['per_page']))
        );
        
        $requests = $wpdb->get_results($query, ARRAY_A);
        $total = $wpdb->get_var("SELECT FOUND_ROWS()");
        
        // 反序列化数组字段
        foreach ($requests as &$request) {
            $request['design_files'] = maybe_unserialize($request['design_files']);
            $request['revised_files'] = maybe_unserialize($request['revised_files']);
        }
        
        return array(
            'requests' => $requests,
            'total' => $total,
            'total_pages' => ceil($total / $args['per_page'])
        );
    }
}
?>

前端提交表单与文件上传

客户提交打样请求的界面需要直观易用。以下是前端表单的实现代码:

<?php
/**
 * 前端打样请求表单
 * 通过短码嵌入到任何页面
 */

class SamplingRequestForm {
    
    public function __construct() {
        add_shortcode('sampling_request_form', array($this, 'render_form'));
        add_action('wp_ajax_submit_sampling_request', array($this, 'handle_submission'));
        add_action('wp_ajax_nopriv_submit_sampling_request', array($this, 'handle_submission'));
    }
    
    /**
     * 渲染提交表单
     */
    public function render_form() {
        // 检查用户是否登录
        if (!is_user_logged_in()) {
            return '<div class="cs-alert">请先登录后再提交打样请求。</div>';
        }
        
        ob_start();
        ?>
        <div class="custom-sampling-form">
            <h2>在线打样请求</h2>
            
            <form id="sampling-request-form" enctype="multipart/form-data">
                <?php wp_nonce_field('submit_sampling_request', 'sampling_nonce'); ?>
                
                <div class="form-group">
                    <label for="product_name">产品名称 *</label>
                    <input type="text" id="product_name" name="product_name" required>
                </div>
                
                <div class="form-group">
                    <label for="product_category">产品类别</label>
                    <select id="product_category" name="product_category">
                        <option value="apparel">服装</option>
                        <option value="accessories">配饰</option>
                        <option value="home_decor">家居装饰</option>
                        <option value="promotional">促销品</option>
                        <option value="other">其他</option>
                    </select>
                </div>
                
                <div class="form-group">
                    <label for="quantity">预计数量</label>
                    <input type="number" id="quantity" name="quantity" min="50" max="10000" value="100">
                    <small>小批量定制范围:50-10000件</small>
                </div>
                
                <div class="form-group">
                    <label for="specifications">详细规格要求 *</label>
                    <textarea id="specifications" name="specifications" rows="6" required 
                              placeholder="请详细描述您的需求,包括尺寸、材料、颜色、工艺等要求..."></textarea>
                </div>
                
                <div class="form-group">
                    <label>设计文件上传</label>
                    <div class="file-upload-area" id="file-upload-area">
                        <div class="upload-instructions">
                            <p>拖放文件到这里,或点击选择文件</p>
                            <p>支持格式:JPG, PNG, PDF, AI, PSD (最大 20MB)</p>
                        </div>
                        <input type="file" id="design_files" name="design_files[]" 
                               multiple accept=".jpg,.jpeg,.png,.pdf,.ai,.psd" style="display: none;">
                        <div class="file-preview" id="file-preview"></div>
                    </div>
                    <button type="button" class="button" id="select-files-btn">选择文件</button>
                </div>
                
                <div class="form-group">
                    <label for="deadline">期望完成时间</label>
                    <input type="date" id="deadline" name="deadline" min="<?php echo date('Y-m-d', strtotime('+3 days')); ?>">
                </div>
                
                <div class="form-group">
                    <label for="additional_notes">附加说明</label>
                    <textarea id="additional_notes" name="additional_notes" rows="3"></textarea>
                </div>
                
                <div class="form-actions">
                    <button type="submit" class="button button-primary">提交打样请求</button>
                    <div class="loading-spinner" style="display: none;">提交中...</div>
                </div>
                
                <div id="form-message"></div>
            </form>
        </div>
        
        <script>
        jQuery(document).ready(function($) {
            // 文件上传处理
            $('#select-files-btn').on('click', function() {
                $('#design_files').click();
            });
            
            $('#design_files').on('change', function(e) {
                handleFileSelection(e.target.files);
            });
            
            // 拖放功能
            $('#file-upload-area').on('dragover', function(e) {
                e.preventDefault();
                $(this).addClass('dragover');
            });
            
            $('#file-upload-area').on('dragleave', function(e) {
                e.preventDefault();
                $(this).removeClass('dragover');
            });
            
            $('#file-upload-area').on('drop', function(e) {
                e.preventDefault();
                $(this).removeClass('dragover');
                handleFileSelection(e.originalEvent.dataTransfer.files);
            });
            
            function handleFileSelection(files) {
                var preview = $('#file-preview');
                preview.empty();
                
                for (var i = 0; i < files.length; i++) {
                    var file = files[i];
                    var fileName = file.name;
                    var fileSize = (file.size / 1024 / 1024).toFixed(2); // MB
                    
                    var fileHtml = `
                        <div class="file-info">
                            <span class="file-name">${fileName}</span>
                            <span class="file-size">${fileSize} MB</span>
                            <button type="button" class="remove-file" data-index="${i}">×</button>
                        </div>
                    `;
                    preview.append(fileHtml);
                }
                
                // 移除文件按钮
                $('.remove-file').on('click', function() {
                    $(this).closest('.file-item').remove();
                    updateFileInput();
                });
            }
            
            function updateFileInput() {
                // 这里可以添加逻辑来更新实际的文件输入
            }
            
            // 表单提交
            $('#sampling-request-form').on('submit', function(e) {
                e.preventDefault();
                
                var formData = new FormData(this);
                var files = $('#design_files')[0].files;
                
                // 添加文件到FormData
                for (var i = 0; i < files.length; i++) {
                    formData.append('design_files_' + i, files[i]);
                }
                
                // 显示加载状态
                $('.loading-spinner').show();
                $('button[type="submit"]').prop('disabled', true);
                
                $.ajax({
                    url: cs_ajax.ajax_url,
                    type: 'POST',
                    data: formData,
                    processData: false,
                    contentType: false,
                    dataType: 'json',
                    success: function(response) {
                        if (response.success) {
                            $('#form-message').html(
                                '<div class="success-message">' + 
                                '打样请求已成功提交!我们将在24小时内联系您。' +
                                '</div>'
                            );
                            $('#sampling-request-form')[0].reset();
                            $('#file-preview').empty();
                        } else {
                            $('#form-message').html(
                                '<div class="error-message">' + 
                                response.data.message +
                                '</div>'
                            );
                        }
                    },
                    error: function() {
                        $('#form-message').html(
                            '<div class="error-message">提交失败,请稍后重试。</div>'
                        );
                    },
                    complete: function() {
                        $('.loading-spinner').hide();
                        $('button[type="submit"]').prop('disabled', false);
                    }
                });
            });
        });
        </script>
        <?php
        return ob_get_clean();
    }
    
    /**
     * 处理表单提交
     */
    public function handle_submission() {
        // 验证nonce
        if (!wp_verify_nonce($_POST['sampling_nonce'], 'submit_sampling_request')) {
            wp_send_json_error(array('message' => '安全验证失败'));
        }
        
        // 验证用户登录
        if (!is_user_logged_in()) {
            wp_send_json_error(array('message' => '请先登录'));
        }
        
        // 处理文件上传
        $uploaded_files = array();
        
        if (!empty($_FILES)) {
            require_once(ABSPATH . 'wp-admin/includes/file.php');
            require_once(ABSPATH . 'wp-admin/includes/image.php');
            
            foreach ($_FILES as $key => $file) {
                if (strpos($key, 'design_files_') === 0 && $file['error'] === UPLOAD_ERR_OK) {
                    $upload = wp_handle_upload($file, array('test_form' => false));
                    
                    if (!isset($upload['error'])) {
                        $uploaded_files[] = $upload['url'];
                        
                        // 创建媒体库附件
                        $attachment = array(
                            'post_mime_type' => $upload['type'],
                            'post_title' => sanitize_file_name($file['name']),
                            'post_content' => '',
                            'post_status' => 'inherit'
                        );
                        
                        $attach_id = wp_insert_attachment($attachment, $upload['file']);
                        wp_update_attachment_metadata($attach_id, wp_generate_attachment_metadata($attach_id, $upload['file']));
                    }
                }
            }
        }
        
        // 准备数据
        $data = array(
            'product_name' => sanitize_text_field($_POST['product_name']),
            'specifications' => wp_kses_post($_POST['specifications']),
            'design_files' => $uploaded_files,
            'additional_data' => array(
                'product_category' => sanitize_text_field($_POST['product_category']),
                'quantity' => intval($_POST['quantity']),
                'deadline' => sanitize_text_field($_POST['deadline']),
                'additional_notes' => wp_kses_post($_POST['additional_notes'])
            )
        );
        
        // 保存到数据库
        $model = new SamplingRequestModel();
        $request_id = $model->create_request($data);
        
        if ($request_id) {
            // 发送通知邮件
            $this->send_notification_email($request_id, $data);
            
            wp_send_json_success(array(
                'message' => '请求提交成功',
                'request_id' => $request_id
            ));
        } else {
            wp_send_json_error(array('message' => '保存失败,请稍后重试'));
        }
    }
    
    /**
     * 发送通知邮件
     */
    private function send_notification_email($request_id, $data) {
        $admin_email = get_option('admin_email');
        $customer = wp_get_current_user();
        
        $subject = sprintf('新的打样请求 #%d - %s', $request_id, $data['product_name']);
        
        $message = sprintf(
            "新的打样请求已提交:nn" .
            "请求编号:%dn" .
            "产品名称:%sn" .
            "客户:%s (%s)n" .
            "预计数量:%dn" .
            "提交时间:%snn" .
            "详细规格:n%snn" .
            "请登录管理后台查看详情:%s",
            $request_id,
            $data['product_name'],
            $customer->display_name,
            $customer->user_email,
            $data['additional_data']['quantity'],
            current_time('mysql'),
            $data['specifications'],
            admin_url('admin.php?page=custom-sampling&action=view&id=' . $request_id)
        );
        
        wp_mail($admin_email, $subject, $message);
    }
}

new SamplingRequestForm();
?>

供应商后台管理界面

供应商需要一个直观的管理界面来处理打样请求:

<?php
/**
 * 供应商管理界面
 * 显示所有打样请求并提供处理功能
 */

class SupplierAdminInterface {
    
    public function __construct() {
        add_action('admin_init', array($this, 'handle_actions'));
    }
    
    /**
     * 渲染管理主页面
     */
    public function render_main_page() {
        $model = new SamplingRequestModel();
        
        // 获取筛选参数
        $status = isset($_GET['status']) ? sanitize_text_field($_GET['status']) : '';
        $search = isset($_GET['s']) ? sanitize_text_field($_GET['s']) : '';
        $paged = isset($_GET['paged']) ? intval($_GET['paged']) : 1;
        
        $args = array(
            'status' => $status,
            'search' => $search,
            'page' => $paged,
            'per_page' => 20
        );
        
        $result = $model->get_all_requests($args);
        $requests = $result['requests'];
        $total_pages = $result['total_pages'];
        ?>
        
        <div class="wrap">
            <h1 class="wp-heading-inline">打样请求管理</h1>
            
            <!-- 筛选表单 -->
            <div class="cs-filter-box">
                <form method="get" action="<?php echo admin_url('admin.php'); ?>">
                    <input type="hidden" name="page" value="custom-sampling">
                    
                    <select name="status" onchange="this.form.submit()">
                        <option value="">所有状态</option>
                        <option value="pending" <?php selected($status, 'pending'); ?>>待处理</option>
                        <option value="reviewing" <?php selected($status, 'reviewing'); ?>>审核中</option>
                        <option value="needs_revision" <?php selected($status, 'needs_revision'); ?>>需要修改</option>
                        <option value="approved" <?php selected($status, 'approved'); ?>>已批准</option>
                        <option value="rejected" <?php selected($status, 'rejected'); ?>>已拒绝</option>
                        <option value="completed" <?php selected($status, 'completed'); ?>>已完成</option>
                    </select>
                    
                    <input type="text" name="s" placeholder="搜索产品名称或规格" 
                           value="<?php echo esc_attr($search); ?>">
                    <button type="submit" class="button">搜索</button>
                </form>
            </div>
            
            <!-- 请求列表 -->
            <table class="wp-list-table widefat fixed striped">
                <thead>
                    <tr>
                        <th>ID</th>
                        <th>产品名称</th>
                        <th>客户</th>
                        <th>提交时间</th>
                        <th>状态</th>
                        <th>操作</th>
                    </tr>
                </thead>
                <tbody>
                    <?php if (empty($requests)): ?>
                        <tr>
                            <td colspan="6" style="text-align: center;">暂无打样请求</td>
                        </tr>
                    <?php else: ?>
                        <?php foreach ($requests as $request): ?>
                            <?php 
                            $customer = get_userdata($request['customer_id']);
                            $status_class = 'status-' . $request['status'];
                            ?>
                            <tr>
                                <td>#<?php echo $request['id']; ?></td>
                                <td>
                                    <strong><?php echo esc_html($request['product_name']); ?></strong>
                                    <?php if (!empty($request['additional_data']['quantity'])): ?>
                                        <br><small>数量: <?php echo $request['additional_data']['quantity']; ?>件</small>
                                    <?php endif; ?>
                                </td>
                                <td>
                                    <?php if ($customer): ?>
                                        <?php echo esc_html($customer->display_name); ?><br>
                                        <small><?php echo esc_html($customer->user_email); ?></small>
                                    <?php else: ?>
                                        用户已删除
                                    <?php endif; ?>
                                </td>
                                <td><?php echo date('Y-m-d H:i', strtotime($request['created_at'])); ?></td>
                                <td>
                                    <span class="cs-status-badge <?php echo $status_class; ?>">
                                        <?php echo $this->get_status_label($request['status']); ?>
                                    </span>
                                </td>
                                <td>
                                    <a href="<?php echo admin_url('admin.php?page=custom-sampling&action=view&id=' . $request['id']); ?>" 
                                       class="button button-small">查看详情</a>
                                    <?php if ($request['status'] === 'pending' || $request['status'] === 'reviewing'): ?>
                                        <a href="<?php echo admin_url('admin.php?page=custom-sampling&action=review&id=' . $request['id']); ?>" 
                                           class="button button-small button-primary">审核</a>
                                    <?php endif; ?>
                                </td>
                            </tr>
                        <?php endforeach; ?>
                    <?php endif; ?>
                </tbody>
            </table>
            
            <!-- 分页 -->
            <?php if ($total_pages > 1): ?>
                <div class="tablenav bottom">
                    <div class="tablenav-pages">
                        <?php
                        echo paginate_links(array(
                            'base' => add_query_arg('paged', '%#%'),
                            'format' => '',
                            'prev_text' => '&laquo;',
                            'next_text' => '&raquo;',
                            'total' => $total_pages,
                            'current' => $paged
                        ));
                        ?>
                    </div>
                </div>
            <?php endif; ?>
        </div>
        
        <style>
        .cs-status-badge {
            display: inline-block;
            padding: 3px 8px;
            border-radius: 3px;
            font-size: 12px;
            font-weight: 600;
        }
        .status-pending { background: #f0ad4e; color: white; }
        .status-reviewing { background: #5bc0de; color: white; }
        .status-needs_revision { background: #d9534f; color: white; }
        .status-approved { background: #5cb85c; color: white; }
        .status-rejected { background: #d9534f; color: white; }
        .status-completed { background: #5cb85c; color: white; }
        .cs-filter-box {
            background: #fff;
            padding: 15px;
            margin: 20px 0;
            border: 1px solid #ccd0d4;
        }
        .cs-filter-box select,
        .cs-filter-box input[type="text"] {
            margin-right: 10px;
        }
        </style>
        <?php
    }
    
    /**
     * 获取状态标签
     */
    private function get_status_label($status) {
        $labels = array(
            'pending' => '待处理',
            'reviewing' => '审核中',
            'needs_revision' => '需要修改',
            'approved' => '已批准',
            'rejected' => '已拒绝',
            'completed' => '已完成'
        );
        
        return isset($labels[$status]) ? $labels[$status] : $status;
    }
    
    /**
     * 处理管理操作
     */
    public function handle_actions() {
        if (!isset($_GET['page']) || $_GET['page'] !== 'custom-sampling') {
            return;
        }
        
        $action = isset($_GET['action']) ? $_GET['action'] : '';
        $request_id = isset($_GET['id']) ? intval($_GET['id']) : 0;
        
        if (!$request_id) {
            return;
        }
        
        $model = new SamplingRequestModel();
        
        switch ($action) {
            case 'update_status':
                if (isset($_POST['status']) && wp_verify_nonce($_POST['_wpnonce'], 'update_status_' . $request_id)) {
                    $status = sanitize_text_field($_POST['status']);
                    $notes = isset($_POST['supplier_notes']) ? wp_kses_post($_POST['supplier_notes']) : '';
                    
                    $model->update_request($request_id, array(
                        'status' => $status,
                        'supplier_notes' => $notes
                    ));
                    
                    // 发送状态更新通知
                    $this->send_status_notification($request_id, $status, $notes);
                    
                    wp_redirect(admin_url('admin.php?page=custom-sampling&action=view&id=' . $request_id . '&updated=1'));
                    exit;
                }
                break;
                
            case 'upload_revision':
                if (wp_verify_nonce($_POST['_wpnonce'], 'upload_revision_' . $request_id)) {
                    $this->handle_revision_upload($request_id);
                }
                break;
        }
    }
    
    /**
     * 发送状态更新通知
     */
    private function send_status_notification($request_id, $status, $notes) {
        $request = (new SamplingRequestModel())->get_request($request_id);
        $customer = get_userdata($request['customer_id']);
        
        if (!$customer) {
            return;
        }
        
        $status_labels = array(
            'approved' => '已批准',
            'rejected' => '已拒绝',
            'needs_revision' => '需要修改',
            'completed' => '已完成'
        );
        
        $subject = sprintf('打样请求 #%d 状态更新', $request_id);
        
        $message = sprintf(
            "您的打样请求状态已更新:nn" .
            "请求编号:%dn" .
            "产品名称:%sn" .
            "新状态:%sn" .
            "供应商备注:%snn" .
            "请登录网站查看详情:%s",
            $request_id,
            $request['product_name'],
            $status_labels[$status] ?? $status,
            $notes,
            home_url('/my-account/sampling-requests/')
        );
        
        wp_mail($customer->user_email, $subject, $message);
    }
}

new SupplierAdminInterface();
?>

在线标注与批注系统

供应商需要能够在设计图上直接标注和批注:

<?php
/**
 * 在线图像标注系统
 * 使用Fabric.js实现
 */

class ImageAnnotationSystem {
    
    public function __construct() {
        add_action('admin_enqueue_scripts', array($this, 'enqueue_annotation_scripts'));
        add_action('wp_ajax_save_annotation', array($this, 'save_annotation'));
    }
    
    /**
     * 渲染标注界面
     */
    public function render_annotation_interface($request_id, $image_urls) {
        ?>
        <div class="annotation-container">
            <div class="annotation-header">
                <h2>设计图批注</h2>
                <div class="annotation-tools">
                    <button type="button" class="button" id="tool-select">选择</button>
                    <button type="button" class="button" id="tool-rectangle">矩形</button>
                    <button type="button" class="button" id="tool-circle">圆形</button>
                    <button type="button" class="button" id="tool-arrow">箭头</button>
                    <button type="button" class="button" id="tool-text">文字</button>
                    <button type="button" class="button" id="tool-freehand">自由绘制</button>
                    <input type="color" id="color-picker" value="#FF0000">
本文来自网络,不代表柔性供应链服务中心立场,转载请注明出处:https://mall.org.cn/6142.html

EXCHANGES®作者

上一篇
下一篇

为您推荐

发表回复

联系我们

联系我们

18559313275

在线咨询: QQ交谈

邮箱: vip@exchanges.center

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