首页 / 教程文章 / 实现小批量快速打样的WordPress集成插件教程

实现小批量快速打样的WordPress集成插件教程

本教程指导如何开发一个WordPress插件,以支持小批量快速打样流程。插件涵盖产品提交、状态跟踪和团队协作功能,适合初创企业和小型设计团队。教程详细介绍了插件的基础结构、数据库设计、管理界面、前端表单、AJAX处理、样式优化以及项目状态跟踪与协作系统的实现步骤,帮助用户高效管理打样项目。

实现小批量快速打样的WordPress集成插件教程

概述

在当今快速发展的电商环境中,小批量快速打样已成为产品开发的关键环节。本教程将指导您创建一个WordPress插件,帮助用户高效管理小批量打样流程。这个插件将包含产品提交、打样状态跟踪和团队协作功能,适合初创企业和小型设计团队使用。

插件架构设计

1. 插件基础结构

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

<?php
/**
 * 插件名称: 小批量快速打样管理系统
 * 版本: 1.0.0
 * 描述: 用于管理小批量产品打样流程的WordPress插件
 * 作者: 您的姓名
 * 文本域: rapid-prototyping
 */

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

// 定义插件常量
define('RP_PLUGIN_VERSION', '1.0.0');
define('RP_PLUGIN_PATH', plugin_dir_path(__FILE__));
define('RP_PLUGIN_URL', plugin_dir_url(__FILE__));

// 初始化插件
class RapidPrototypingPlugin {
    
    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('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'));
        add_action('wp_enqueue_scripts', array($this, 'enqueue_frontend_scripts'));
    }
    
    public function activate() {
        $this->create_database_tables();
        $this->create_default_options();
    }
    
    public function deactivate() {
        // 清理临时数据
        $this->cleanup_temporary_data();
    }
    
    public function init() {
        // 加载文本域
        load_plugin_textdomain('rapid-prototyping', false, dirname(plugin_basename(__FILE__)) . '/languages');
        
        // 注册自定义文章类型
        $this->register_custom_post_types();
    }
    
    // 其他方法将在下面实现
}

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

2. 数据库表设计

创建必要的数据库表来存储打样项目数据:

<?php
// 在RapidPrototypingPlugin类中添加以下方法

private function create_database_tables() {
    global $wpdb;
    
    $charset_collate = $wpdb->get_charset_collate();
    $table_name = $wpdb->prefix . 'rapid_prototyping_projects';
    
    // 项目表
    $sql = "CREATE TABLE IF NOT EXISTS $table_name (
        id mediumint(9) NOT NULL AUTO_INCREMENT,
        project_name varchar(255) NOT NULL,
        description text,
        designer_id bigint(20) NOT NULL,
        status varchar(50) DEFAULT 'draft',
        priority tinyint(1) DEFAULT 1,
        materials text,
        quantity int(11) DEFAULT 1,
        due_date datetime,
        created_at datetime DEFAULT CURRENT_TIMESTAMP,
        updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        PRIMARY KEY (id),
        KEY designer_id (designer_id),
        KEY status (status)
    ) $charset_collate;";
    
    require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    dbDelta($sql);
    
    // 打样版本表
    $versions_table = $wpdb->prefix . 'rapid_prototyping_versions';
    $sql = "CREATE TABLE IF NOT EXISTS $versions_table (
        id mediumint(9) NOT NULL AUTO_INCREMENT,
        project_id mediumint(9) NOT NULL,
        version_number varchar(20) NOT NULL,
        file_url varchar(500),
        notes text,
        feedback text,
        approved_by bigint(20),
        approved_at datetime,
        created_at datetime DEFAULT CURRENT_TIMESTAMP,
        PRIMARY KEY (id),
        KEY project_id (project_id),
        FOREIGN KEY (project_id) REFERENCES $table_name(id) ON DELETE CASCADE
    ) $charset_collate;";
    
    dbDelta($sql);
    
    // 团队成员表
    $team_table = $wpdb->prefix . 'rapid_prototyping_team';
    $sql = "CREATE TABLE IF NOT EXISTS $team_table (
        id mediumint(9) NOT NULL AUTO_INCREMENT,
        project_id mediumint(9) NOT NULL,
        user_id bigint(20) NOT NULL,
        role varchar(50) NOT NULL,
        added_at datetime DEFAULT CURRENT_TIMESTAMP,
        PRIMARY KEY (id),
        UNIQUE KEY project_user (project_id, user_id),
        FOREIGN KEY (project_id) REFERENCES $table_name(id) ON DELETE CASCADE
    ) $charset_collate;";
    
    dbDelta($sql);
}
?>

3. 管理界面实现

创建插件管理页面和功能:

<?php
// 在RapidPrototypingPlugin类中添加以下方法

public function add_admin_menu() {
    // 主菜单
    add_menu_page(
        __('快速打样管理', 'rapid-prototyping'),
        __('快速打样', 'rapid-prototyping'),
        'manage_options',
        'rapid-prototyping',
        array($this, 'render_dashboard_page'),
        'dashicons-hammer',
        30
    );
    
    // 子菜单
    add_submenu_page(
        'rapid-prototyping',
        __('所有项目', 'rapid-prototyping'),
        __('所有项目', 'rapid-prototyping'),
        'manage_options',
        'rp-projects',
        array($this, 'render_projects_page')
    );
    
    add_submenu_page(
        'rapid-prototyping',
        __('添加新项目', 'rapid-prototyping'),
        __('添加新项目', 'rapid-prototyping'),
        'manage_options',
        'rp-add-project',
        array($this, 'render_add_project_page')
    );
    
    add_submenu_page(
        'rapid-prototyping',
        __('设置', 'rapid-prototyping'),
        __('设置', 'rapid-prototyping'),
        'manage_options',
        'rp-settings',
        array($this, 'render_settings_page')
    );
}

public function render_dashboard_page() {
    ?>
    <div class="wrap rp-dashboard">
        <h1><?php _e('快速打样仪表板', 'rapid-prototyping'); ?></h1>
        
        <div class="rp-stats-container">
            <?php $this->display_statistics(); ?>
        </div>
        
        <div class="rp-recent-projects">
            <h2><?php _e('最近项目', 'rapid-prototyping'); ?></h2>
            <?php $this->display_recent_projects(); ?>
        </div>
    </div>
    <?php
}

private function display_statistics() {
    global $wpdb;
    $table_name = $wpdb->prefix . 'rapid_prototyping_projects';
    
    // 获取统计数据
    $total_projects = $wpdb->get_var("SELECT COUNT(*) FROM $table_name");
    $active_projects = $wpdb->get_var("SELECT COUNT(*) FROM $table_name WHERE status IN ('in_progress', 'review')");
    $completed_projects = $wpdb->get_var("SELECT COUNT(*) FROM $table_name WHERE status = 'completed'");
    
    ?>
    <div class="rp-stats-grid">
        <div class="rp-stat-card">
            <h3><?php echo esc_html($total_projects); ?></h3>
            <p><?php _e('总项目数', 'rapid-prototyping'); ?></p>
        </div>
        <div class="rp-stat-card">
            <h3><?php echo esc_html($active_projects); ?></h3>
            <p><?php _e('进行中项目', 'rapid-prototyping'); ?></p>
        </div>
        <div class="rp-stat-card">
            <h3><?php echo esc_html($completed_projects); ?></h3>
            <p><?php _e('已完成项目', 'rapid-prototyping'); ?></p>
        </div>
    </div>
    <?php
}
?>

4. 前端提交表单

创建用户提交打样请求的前端表单:

<?php
// 创建短码处理类
class RP_Shortcodes {
    
    public static function init() {
        add_shortcode('rp_submission_form', array(__CLASS__, 'render_submission_form'));
        add_shortcode('rp_project_status', array(__CLASS__, 'render_project_status'));
    }
    
    public static function render_submission_form($atts) {
        // 检查用户是否登录
        if (!is_user_logged_in()) {
            return '<p>' . __('请登录后提交打样请求。', 'rapid-prototyping') . '</p>';
        }
        
        ob_start();
        ?>
        <div class="rp-submission-form-container">
            <h2><?php _e('提交打样请求', 'rapid-prototyping'); ?></h2>
            
            <form id="rp-submission-form" method="post" enctype="multipart/form-data">
                <?php wp_nonce_field('rp_submit_project', 'rp_nonce'); ?>
                
                <div class="rp-form-group">
                    <label for="project_name"><?php _e('项目名称', 'rapid-prototyping'); ?> *</label>
                    <input type="text" id="project_name" name="project_name" required>
                </div>
                
                <div class="rp-form-group">
                    <label for="description"><?php _e('项目描述', 'rapid-prototyping'); ?></label>
                    <textarea id="description" name="description" rows="4"></textarea>
                </div>
                
                <div class="rp-form-row">
                    <div class="rp-form-group">
                        <label for="quantity"><?php _e('打样数量', 'rapid-prototyping'); ?></label>
                        <input type="number" id="quantity" name="quantity" min="1" max="100" value="1">
                    </div>
                    
                    <div class="rp-form-group">
                        <label for="priority"><?php _e('优先级', 'rapid-prototyping'); ?></label>
                        <select id="priority" name="priority">
                            <option value="1"><?php _e('低', 'rapid-prototyping'); ?></option>
                            <option value="2" selected><?php _e('中', 'rapid-prototyping'); ?></option>
                            <option value="3"><?php _e('高', 'rapid-prototyping'); ?></option>
                        </select>
                    </div>
                </div>
                
                <div class="rp-form-group">
                    <label for="materials"><?php _e('使用材料', 'rapid-prototyping'); ?></label>
                    <textarea id="materials" name="materials" rows="3" 
                              placeholder="<?php esc_attr_e('请详细描述所需材料...', 'rapid-prototyping'); ?>"></textarea>
                </div>
                
                <div class="rp-form-group">
                    <label for="due_date"><?php _e('期望完成日期', 'rapid-prototyping'); ?></label>
                    <input type="date" id="due_date" name="due_date">
                </div>
                
                <div class="rp-form-group">
                    <label for="design_files"><?php _e('设计文件', 'rapid-prototyping'); ?></label>
                    <input type="file" id="design_files" name="design_files[]" multiple accept=".jpg,.png,.pdf,.stl,.obj">
                    <p class="rp-help-text"><?php _e('支持JPG, PNG, PDF, STL, OBJ格式,最多5个文件', 'rapid-prototyping'); ?></p>
                </div>
                
                <div class="rp-form-group">
                    <label for="additional_notes"><?php _e('附加说明', 'rapid-prototyping'); ?></label>
                    <textarea id="additional_notes" name="additional_notes" rows="3"></textarea>
                </div>
                
                <button type="submit" class="rp-submit-button">
                    <?php _e('提交打样请求', 'rapid-prototyping'); ?>
                </button>
                
                <div id="rp-form-message"></div>
            </form>
        </div>
        
        <script>
        jQuery(document).ready(function($) {
            $('#rp-submission-form').on('submit', function(e) {
                e.preventDefault();
                
                var formData = new FormData(this);
                formData.append('action', 'rp_submit_project');
                
                $.ajax({
                    url: '<?php echo admin_url("admin-ajax.php"); ?>',
                    type: 'POST',
                    data: formData,
                    processData: false,
                    contentType: false,
                    success: function(response) {
                        if (response.success) {
                            $('#rp-form-message').html(
                                '<div class="rp-success">' + response.data.message + '</div>'
                            );
                            $('#rp-submission-form')[0].reset();
                        } else {
                            $('#rp-form-message').html(
                                '<div class="rp-error">' + response.data.message + '</div>'
                            );
                        }
                    }
                });
            });
        });
        </script>
        <?php
        
        return ob_get_clean();
    }
}

// 在插件初始化时注册短码
add_action('init', array('RP_Shortcodes', 'init'));
?>

5. AJAX处理与数据验证

处理表单提交的AJAX请求:

<?php
// 在RapidPrototypingPlugin类中添加AJAX处理方法

private function init_ajax_handlers() {
    add_action('wp_ajax_rp_submit_project', array($this, 'handle_project_submission'));
    add_action('wp_ajax_nopriv_rp_submit_project', array($this, 'handle_no_privilege'));
    
    add_action('wp_ajax_rp_get_project_status', array($this, 'get_project_status'));
}

public function handle_project_submission() {
    // 验证nonce
    if (!wp_verify_nonce($_POST['rp_nonce'], 'rp_submit_project')) {
        wp_die(__('安全验证失败', 'rapid-prototyping'));
    }
    
    // 验证用户权限
    if (!is_user_logged_in()) {
        wp_send_json_error(array(
            'message' => __('请先登录', 'rapid-prototyping')
        ));
    }
    
    // 验证必填字段
    $required_fields = array('project_name');
    foreach ($required_fields as $field) {
        if (empty($_POST[$field])) {
            wp_send_json_error(array(
                'message' => sprintf(__('%s为必填字段', 'rapid-prototyping'), $field)
            ));
        }
    }
    
    global $wpdb;
    $table_name = $wpdb->prefix . 'rapid_prototyping_projects';
    
    // 准备数据
    $project_data = array(
        'project_name' => sanitize_text_field($_POST['project_name']),
        'description' => sanitize_textarea_field($_POST['description']),
        'designer_id' => get_current_user_id(),
        'status' => 'draft',
        'priority' => intval($_POST['priority']),
        'materials' => sanitize_textarea_field($_POST['materials']),
        'quantity' => intval($_POST['quantity']),
        'due_date' => !empty($_POST['due_date']) ? sanitize_text_field($_POST['due_date']) : null,
        'created_at' => current_time('mysql')
    );
    
    // 插入数据库
    $result = $wpdb->insert($table_name, $project_data);
    
    if ($result) {
        $project_id = $wpdb->insert_id;
        
        // 处理文件上传
        $this->handle_file_uploads($project_id);
        
        // 发送通知邮件
        $this->send_notification_email($project_id);
        
        wp_send_json_success(array(
            'message' => __('打样请求提交成功!', 'rapid-prototyping'),
            'project_id' => $project_id
        ));
    } else {
        wp_send_json_error(array(
            'message' => __('提交失败,请重试', 'rapid-prototyping')
        ));
    }
}

private function handle_file_uploads($project_id) {
    if (!empty($_FILES['design_files'])) {
        require_once(ABSPATH . 'wp-admin/includes/file.php');
        require_once(ABSPATH . 'wp-admin/includes/media.php');
        require_once(ABSPATH . 'wp-admin/includes/image.php');
        
        $files = $_FILES['design_files'];
        $upload_dir = wp_upload_dir();
        $rp_dir = $upload_dir['basedir'] . '/rapid-prototyping/' . $project_id;
        
        // 创建目录
        if (!file_exists($rp_dir)) {
            wp_mkdir_p($rp_dir);
        }
        
        // 处理多个文件
        foreach ($files['name'] as $key => $value) {
            if ($files['name'][$key]) {
                $file = array(
                    'name' => $files['name'][$key],
                    'type' => $files['type'][$key],
                    'tmp_name' => $files['tmp_name'][$key],
                    'error' => $files['error'][$key],
                    'size' => $files['size'][$key]
                );
                
                $upload_overrides = array('test_form' => false);
                $movefile = wp_handle_upload($file, $upload_overrides);
                
                if ($movefile && !isset($movefile['error'])) {
                    // 保存文件信息到数据库
                    $this->save_file_info($project_id, $movefile['url'], $file['name']);
                }
            }
        }
    }
}
?>

6. 样式与脚本优化

6. 样式与脚本优化

为插件添加专业的前端样式和交互功能:

<?php
// 在RapidPrototypingPlugin类中添加以下方法

public function enqueue_admin_scripts($hook) {
    // 只在插件页面加载
    if (strpos($hook, 'rapid-prototyping') === false) {
        return;
    }
    
    // 加载CSS样式
    wp_enqueue_style(
        'rp-admin-style',
        RP_PLUGIN_URL . 'assets/css/admin.css',
        array(),
        RP_PLUGIN_VERSION
    );
    
    // 加载JavaScript
    wp_enqueue_script(
        'rp-admin-script',
        RP_PLUGIN_URL . 'assets/js/admin.js',
        array('jquery', 'jquery-ui-sortable', 'jquery-ui-datepicker'),
        RP_PLUGIN_VERSION,
        true
    );
    
    // 加载日期选择器样式
    wp_enqueue_style(
        'jquery-ui-style',
        'https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css'
    );
    
    // 本地化脚本
    wp_localize_script('rp-admin-script', 'rp_admin', array(
        'ajax_url' => admin_url('admin-ajax.php'),
        'nonce' => wp_create_nonce('rp_admin_nonce'),
        'confirm_delete' => __('确定要删除这个项目吗?', 'rapid-prototyping'),
        'saving' => __('保存中...', 'rapid-prototyping'),
        'saved' => __('已保存', 'rapid-prototyping')
    ));
}

public function enqueue_frontend_scripts() {
    // 只在需要的地方加载
    if (has_shortcode(get_post()->post_content, 'rp_submission_form') || 
        has_shortcode(get_post()->post_content, 'rp_project_status')) {
        
        // 前端CSS
        wp_enqueue_style(
            'rp-frontend-style',
            RP_PLUGIN_URL . 'assets/css/frontend.css',
            array(),
            RP_PLUGIN_VERSION
        );
        
        // 前端JavaScript
        wp_enqueue_script(
            'rp-frontend-script',
            RP_PLUGIN_URL . 'assets/js/frontend.js',
            array('jquery'),
            RP_PLUGIN_VERSION,
            true
        );
        
        // 本地化脚本
        wp_localize_script('rp-frontend-script', 'rp_frontend', array(
            'ajax_url' => admin_url('admin-ajax.php'),
            'nonce' => wp_create_nonce('rp_frontend_nonce'),
            'uploading' => __('上传中...', 'rapid-prototyping'),
            'max_files' => __('最多只能上传5个文件', 'rapid-prototyping'),
            'invalid_file' => __('文件格式不支持', 'rapid-prototyping')
        ));
    }
}
?>

<!-- assets/css/admin.css -->
<style>
/* 管理界面样式 */
.rp-dashboard {
    padding: 20px;
}

.rp-stats-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: 20px;
    margin: 20px 0;
}

.rp-stat-card {
    background: #fff;
    border: 1px solid #ccd0d4;
    border-radius: 4px;
    padding: 20px;
    text-align: center;
    box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}

.rp-stat-card h3 {
    font-size: 2em;
    margin: 0 0 10px;
    color: #2271b1;
}

.rp-projects-table {
    background: #fff;
    border: 1px solid #ccd0d4;
    border-radius: 4px;
    overflow: hidden;
}

.rp-projects-table table {
    width: 100%;
    border-collapse: collapse;
}

.rp-projects-table th {
    background: #f6f7f7;
    padding: 12px;
    text-align: left;
    border-bottom: 2px solid #ccd0d4;
}

.rp-projects-table td {
    padding: 12px;
    border-bottom: 1px solid #f0f0f0;
}

.rp-status-badge {
    display: inline-block;
    padding: 4px 8px;
    border-radius: 12px;
    font-size: 12px;
    font-weight: 600;
}

.rp-status-draft { background: #f0f0f0; color: #666; }
.rp-status-in_progress { background: #e1f5fe; color: #0277bd; }
.rp-status-review { background: #fff3e0; color: #ef6c00; }
.rp-status-completed { background: #e8f5e9; color: #2e7d32; }
.rp-status-cancelled { background: #ffebee; color: #c62828; }

.rp-action-buttons {
    display: flex;
    gap: 5px;
}

.rp-btn {
    padding: 6px 12px;
    border: none;
    border-radius: 3px;
    cursor: pointer;
    font-size: 13px;
    text-decoration: none;
    display: inline-block;
}

.rp-btn-primary {
    background: #2271b1;
    color: white;
}

.rp-btn-secondary {
    background: #f6f7f7;
    color: #2271b1;
    border: 1px solid #2271b1;
}

.rp-btn-danger {
    background: #d63638;
    color: white;
}

.rp-form-container {
    background: #fff;
    padding: 20px;
    border: 1px solid #ccd0d4;
    border-radius: 4px;
    max-width: 800px;
}

.rp-form-group {
    margin-bottom: 20px;
}

.rp-form-group label {
    display: block;
    margin-bottom: 5px;
    font-weight: 600;
}

.rp-form-group input[type="text"],
.rp-form-group input[type="number"],
.rp-form-group input[type="date"],
.rp-form-group select,
.rp-form-group textarea {
    width: 100%;
    padding: 8px;
    border: 1px solid #8c8f94;
    border-radius: 4px;
    box-sizing: border-box;
}

.rp-form-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
}

.rp-help-text {
    font-size: 12px;
    color: #666;
    margin-top: 5px;
}
</style>

<!-- assets/js/admin.js -->
<script>
jQuery(document).ready(function($) {
    // 项目状态快速编辑
    $('.rp-status-select').on('change', function() {
        var projectId = $(this).data('project-id');
        var newStatus = $(this).val();
        
        $.ajax({
            url: rp_admin.ajax_url,
            type: 'POST',
            data: {
                action: 'rp_update_status',
                project_id: projectId,
                status: newStatus,
                nonce: rp_admin.nonce
            },
            beforeSend: function() {
                $(this).prop('disabled', true);
            },
            success: function(response) {
                if (response.success) {
                    // 更新状态徽章
                    var badge = $('.rp-status-badge[data-project-id="' + projectId + '"]');
                    badge.removeClass().addClass('rp-status-badge rp-status-' + newStatus)
                        .text(response.data.status_label);
                    
                    // 显示成功消息
                    showMessage(response.data.message, 'success');
                } else {
                    showMessage(response.data.message, 'error');
                }
            },
            complete: function() {
                $(this).prop('disabled', false);
            }
        });
    });
    
    // 批量操作
    $('#rp-bulk-action').on('click', function() {
        var action = $('#bulk-action-selector').val();
        var selectedProjects = $('.rp-project-checkbox:checked').map(function() {
            return $(this).val();
        }).get();
        
        if (selectedProjects.length === 0) {
            alert('请至少选择一个项目');
            return;
        }
        
        if (confirm('确定要执行此操作吗?')) {
            $.ajax({
                url: rp_admin.ajax_url,
                type: 'POST',
                data: {
                    action: 'rp_bulk_action',
                    projects: selectedProjects,
                    bulk_action: action,
                    nonce: rp_admin.nonce
                },
                success: function(response) {
                    if (response.success) {
                        location.reload();
                    } else {
                        showMessage(response.data.message, 'error');
                    }
                }
            });
        }
    });
    
    // 日期选择器
    $('.rp-datepicker').datepicker({
        dateFormat: 'yy-mm-dd',
        minDate: 0
    });
    
    // 文件上传预览
    $('.rp-file-upload').on('change', function(e) {
        var files = e.target.files;
        var previewContainer = $(this).siblings('.rp-file-preview');
        previewContainer.empty();
        
        for (var i = 0; i < files.length; i++) {
            var file = files[i];
            var reader = new FileReader();
            
            reader.onload = function(e) {
                var preview = $('<div class="rp-file-preview-item"></div>');
                if (file.type.startsWith('image/')) {
                    preview.append('<img src="' + e.target.result + '" alt="' + file.name + '">');
                }
                preview.append('<span>' + file.name + '</span>');
                previewContainer.append(preview);
            }
            
            reader.readAsDataURL(file);
        }
    });
    
    function showMessage(message, type) {
        var messageDiv = $('<div class="rp-message rp-message-' + type + '"></div>')
            .text(message)
            .hide()
            .appendTo('.wrap');
        
        messageDiv.fadeIn().delay(3000).fadeOut(function() {
            $(this).remove();
        });
    }
});
</script>

7. 项目状态跟踪系统

实现完整的项目状态跟踪和工作流管理:

<?php
// 在RapidPrototypingPlugin类中添加状态管理方法

class RP_Workflow_Manager {
    
    private static $statuses = array(
        'draft' => array(
            'label' => '草稿',
            'color' => '#666',
            'next_steps' => array('in_progress', 'cancelled')
        ),
        'in_progress' => array(
            'label' => '进行中',
            'color' => '#0277bd',
            'next_steps' => array('review', 'cancelled')
        ),
        'review' => array(
            'label' => '审核中',
            'color' => '#ef6c00',
            'next_steps' => array('in_progress', 'completed', 'cancelled')
        ),
        'completed' => array(
            'label' => '已完成',
            'color' => '#2e7d32',
            'next_steps' => array()
        ),
        'cancelled' => array(
            'label' => '已取消',
            'color' => '#c62828',
            'next_steps' => array()
        )
    );
    
    public static function get_statuses() {
        return apply_filters('rp_workflow_statuses', self::$statuses);
    }
    
    public static function get_status_label($status) {
        $statuses = self::get_statuses();
        return isset($statuses[$status]) ? $statuses[$status]['label'] : $status;
    }
    
    public static function get_next_possible_statuses($current_status) {
        $statuses = self::get_statuses();
        return isset($statuses[$current_status]) ? $statuses[$current_status]['next_steps'] : array();
    }
    
    public static function can_transition($from_status, $to_status) {
        $next_steps = self::get_next_possible_statuses($from_status);
        return in_array($to_status, $next_steps);
    }
    
    public static function update_project_status($project_id, $new_status, $user_id = null) {
        global $wpdb;
        
        $table_name = $wpdb->prefix . 'rapid_prototyping_projects';
        
        // 获取当前状态
        $current_status = $wpdb->get_var($wpdb->prepare(
            "SELECT status FROM $table_name WHERE id = %d",
            $project_id
        ));
        
        // 检查状态转换是否允许
        if (!self::can_transition($current_status, $new_status)) {
            return new WP_Error('invalid_transition', 
                sprintf(__('无法从"%s"状态转换到"%s"状态', 'rapid-prototyping'),
                    self::get_status_label($current_status),
                    self::get_status_label($new_status)
                )
            );
        }
        
        // 更新状态
        $result = $wpdb->update(
            $table_name,
            array('status' => $new_status, 'updated_at' => current_time('mysql')),
            array('id' => $project_id)
        );
        
        if ($result !== false) {
            // 记录状态变更历史
            self::log_status_change($project_id, $current_status, $new_status, $user_id);
            
            // 发送通知
            self::send_status_notification($project_id, $current_status, $new_status);
            
            return true;
        }
        
        return false;
    }
    
    private static function log_status_change($project_id, $old_status, $new_status, $user_id = null) {
        global $wpdb;
        
        $log_table = $wpdb->prefix . 'rapid_prototyping_status_log';
        
        $wpdb->insert($log_table, array(
            'project_id' => $project_id,
            'old_status' => $old_status,
            'new_status' => $new_status,
            'changed_by' => $user_id ?: get_current_user_id(),
            'changed_at' => current_time('mysql')
        ));
    }
    
    private static function send_status_notification($project_id, $old_status, $new_status) {
        global $wpdb;
        
        $project_table = $wpdb->prefix . 'rapid_prototyping_projects';
        $team_table = $wpdb->prefix . 'rapid_prototyping_team';
        
        // 获取项目信息
        $project = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM $project_table WHERE id = %d",
            $project_id
        ));
        
        // 获取团队成员
        $team_members = $wpdb->get_results($wpdb->prepare(
            "SELECT user_id FROM $team_table WHERE project_id = %d",
            $project_id
        ));
        
        // 收集所有需要通知的用户
        $recipients = array($project->designer_id);
        foreach ($team_members as $member) {
            $recipients[] = $member->user_id;
        }
        $recipients = array_unique($recipients);
        
        // 发送邮件给每个用户
        foreach ($recipients as $user_id) {
            $user = get_user_by('id', $user_id);
            if ($user) {
                $subject = sprintf(__('项目状态更新: %s', 'rapid-prototyping'), $project->project_name);
                
                $message = sprintf(__(
                    '您好 %s,

您的项目"%s"状态已更新:
从: %s
到: %s

项目详情: %s

感谢您使用快速打样系统。
', 'rapid-prototyping'),
                    $user->display_name,
                    $project->project_name,
                    self::get_status_label($old_status),
                    self::get_status_label($new_status),
                    admin_url('admin.php?page=rp-projects&action=view&id=' . $project_id)
                );
                
                wp_mail($user->user_email, $subject, $message);
            }
        }
    }
    
    public static function get_status_timeline($project_id) {
        global $wpdb;
        
        $log_table = $wpdb->prefix . 'rapid_prototyping_status_log';
        
        $logs = $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM $log_table 
             WHERE project_id = %d 
             ORDER BY changed_at DESC",
            $project_id
        ));
        
        $timeline = array();
        foreach ($logs as $log) {
            $user = get_user_by('id', $log->changed_by);
            $timeline[] = array(
                'timestamp' => $log->changed_at,
                'old_status' => self::get_status_label($log->old_status),
                'new_status' => self::get_status_label($log->new_status),
                'changed_by' => $user ? $user->display_name : __('系统', 'rapid-prototyping'),
                'avatar' => $user ? get_avatar_url($user->ID, array('size' => 32)) : ''
            );
        }
        
        return $timeline;
    }
}
?>

8. 团队协作功能

实现团队成员管理和协作功能:

<?php
// 团队管理类
class RP_Team_Manager {
    
    public static function add_team_member($project_id, $user_id, $role = 'collaborator') {
        global $wpdb;
        
        $table_name = $wpdb->prefix . 'rapid_prototyping_team';
        
        // 检查是否已是团队成员
        $existing = $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM $table_name 
             WHERE project_id = %d AND user_id = %d",
            $project_id, $user_id
        ));
        
        if ($existing > 0) {
            return new WP_Error('already_member', 
                __('该用户已是团队成员', 'rapid-prototyping'));
        }
        
        // 添加团队成员
        $result = $wpdb->insert($table_name, array(
            'project_id' => $project_id,
本文来自网络投稿,不代表本站点的立场,转载请注明出处:https://www.gongxiangcang.com/5766.html

溯源库®作者

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

为您推荐

联系我们

联系我们

18559313275

在线咨询: QQ交谈

邮箱: vip@suyuanku.com

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

微信扫一扫关注我们

返回顶部