首页 / 教程文章 / WordPress小批量定制插件实现智能生产排程的详细教程

WordPress小批量定制插件实现智能生产排程的详细教程

本教程介绍如何为中小型企业开发WordPress定制插件,实现经济高效的智能生产排程系统。内容涵盖从创建插件基础结构、设计数据库模型,到实现基于优先规则与约束规划的排程算法。详细步骤包括构建管理界面、可视化展示排程结果,以及通过AJAX实现实时数据交互,并扩展约束优化与冲突解决等高级功能,助力企业提升生产效率。

WordPress小批量定制插件实现智能生产排程的详细教程

概述

在当今制造业数字化转型的浪潮中,智能生产排程系统成为提升生产效率的关键工具。对于中小型企业而言,直接购买大型ERP系统往往成本过高,而WordPress作为全球最流行的内容管理系统,通过定制插件的方式可以实现经济高效的智能生产排程解决方案。本教程将详细介绍如何开发一个WordPress插件,实现小批量生产的智能排程功能。

环境准备与插件基础结构

首先,我们需要创建一个标准的WordPress插件结构。在WordPress的wp-content/plugins/目录下创建新文件夹smart-production-scheduler

<?php
/**
 * Plugin Name: 智能生产排程系统
 * Plugin URI: https://yourwebsite.com/
 * Description: 为小批量生产定制的智能排程插件
 * Version: 1.0.0
 * Author: 您的名称
 * License: GPL v2 or later
 */

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

// 定义插件常量
define('SPS_VERSION', '1.0.0');
define('SPS_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('SPS_PLUGIN_URL', plugin_dir_url(__FILE__));

// 初始化插件
class SmartProductionScheduler {
    
    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('admin_menu', array($this, 'add_admin_menu'));
        
        // 加载脚本和样式
        add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_assets'));
        
        // AJAX处理
        add_action('wp_ajax_sps_process_schedule', array($this, 'process_schedule_ajax'));
    }
    
    public function activate() {
        $this->create_tables();
        $this->insert_default_data();
    }
    
    public function deactivate() {
        // 清理临时数据
    }
}
// 初始化插件
SmartProductionScheduler::get_instance();
?>

数据库设计与数据模型

智能排程系统需要存储订单、机器、工序等关键数据。我们在插件激活时创建必要的数据库表。

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

private function create_tables() {
    global $wpdb;
    
    $charset_collate = $wpdb->get_charset_collate();
    
    // 订单表
    $orders_table = $wpdb->prefix . 'sps_orders';
    $sql_orders = "CREATE TABLE IF NOT EXISTS $orders_table (
        id INT(11) NOT NULL AUTO_INCREMENT,
        order_number VARCHAR(50) NOT NULL,
        product_name VARCHAR(255) NOT NULL,
        quantity INT(11) NOT NULL,
        priority TINYINT(1) DEFAULT 1 COMMENT '1-低, 2-中, 3-高',
        due_date DATE NOT NULL,
        status VARCHAR(20) DEFAULT 'pending',
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
        PRIMARY KEY (id),
        UNIQUE KEY order_number (order_number)
    ) $charset_collate;";
    
    // 机器资源表
    $machines_table = $wpdb->prefix . 'sps_machines';
    $sql_machines = "CREATE TABLE IF NOT EXISTS $machines_table (
        id INT(11) NOT NULL AUTO_INCREMENT,
        machine_name VARCHAR(100) NOT NULL,
        machine_type VARCHAR(50) NOT NULL,
        capacity_per_hour INT(11) NOT NULL,
        maintenance_schedule TEXT,
        status VARCHAR(20) DEFAULT 'active',
        PRIMARY KEY (id)
    ) $charset_collate;";
    
    // 工序表
    $processes_table = $wpdb->prefix . 'sps_processes';
    $sql_processes = "CREATE TABLE IF NOT EXISTS $processes_table (
        id INT(11) NOT NULL AUTO_INCREMENT,
        order_id INT(11) NOT NULL,
        process_name VARCHAR(100) NOT NULL,
        machine_id INT(11) NOT NULL,
        sequence INT(11) NOT NULL,
        estimated_hours DECIMAL(5,2) NOT NULL,
        actual_hours DECIMAL(5,2) DEFAULT NULL,
        start_time DATETIME DEFAULT NULL,
        end_time DATETIME DEFAULT NULL,
        status VARCHAR(20) DEFAULT 'pending',
        FOREIGN KEY (order_id) REFERENCES $orders_table(id) ON DELETE CASCADE,
        FOREIGN KEY (machine_id) REFERENCES $machines_table(id),
        PRIMARY KEY (id)
    ) $charset_collate;";
    
    // 排程结果表
    $schedules_table = $wpdb->prefix . 'sps_schedules';
    $sql_schedules = "CREATE TABLE IF NOT EXISTS $schedules_table (
        id INT(11) NOT NULL AUTO_INCREMENT,
        schedule_date DATE NOT NULL,
        machine_id INT(11) NOT NULL,
        process_id INT(11) NOT NULL,
        time_slot_start TIME NOT NULL,
        time_slot_end TIME NOT NULL,
        utilization_rate DECIMAL(5,2) DEFAULT 0,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
        PRIMARY KEY (id),
        FOREIGN KEY (machine_id) REFERENCES $machines_table(id),
        FOREIGN KEY (process_id) REFERENCES $processes_table(id)
    ) $charset_collate;";
    
    require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    dbDelta($sql_orders);
    dbDelta($sql_machines);
    dbDelta($sql_processes);
    dbDelta($sql_schedules);
}

private function insert_default_data() {
    global $wpdb;
    $machines_table = $wpdb->prefix . 'sps_machines';
    
    // 插入默认机器数据
    $default_machines = array(
        array('machine_name' => 'CNC-01', 'machine_type' => 'cnc', 'capacity_per_hour' => 10),
        array('machine_name' => '注塑机-01', 'machine_type' => 'injection', 'capacity_per_hour' => 15),
        array('machine_name' => '装配线-01', 'machine_type' => 'assembly', 'capacity_per_hour' => 20),
    );
    
    foreach ($default_machines as $machine) {
        $wpdb->insert($machines_table, $machine);
    }
}
?>

智能排程算法实现

核心的排程算法采用基于优先规则和约束规划的启发式方法。

<?php
// 在SmartProductionScheduler类中添加排程算法

public function generate_schedule($start_date, $end_date) {
    global $wpdb;
    
    $orders_table = $wpdb->prefix . 'sps_orders';
    $processes_table = $wpdb->prefix . 'sps_processes';
    $machines_table = $wpdb->prefix . 'sps_machines';
    $schedules_table = $wpdb->prefix . 'sps_schedules';
    
    // 1. 获取待排程的订单和工序
    $pending_orders = $wpdb->get_results("
        SELECT o.*, p.id as process_id, p.process_name, p.machine_id, 
               p.sequence, p.estimated_hours, m.machine_name, m.capacity_per_hour
        FROM $orders_table o
        JOIN $processes_table p ON o.id = p.order_id
        JOIN $machines_table m ON p.machine_id = m.id
        WHERE o.status = 'pending' AND p.status = 'pending'
        ORDER BY 
            o.priority DESC,
            o.due_date ASC,
            p.sequence ASC
    ");
    
    // 2. 初始化时间槽(以30分钟为单位)
    $time_slots = $this->generate_time_slots($start_date, $end_date);
    
    // 3. 机器可用性映射
    $machine_availability = array();
    $machines = $wpdb->get_results("SELECT id FROM $machines_table WHERE status = 'active'");
    foreach ($machines as $machine) {
        $machine_availability[$machine->id] = $time_slots;
    }
    
    // 4. 智能排程算法
    $schedule_results = array();
    
    foreach ($pending_orders as $order_process) {
        $machine_id = $order_process->machine_id;
        $required_slots = ceil($order_process->estimated_hours * 2); // 转换为30分钟槽
        
        // 寻找可用的连续时间槽
        $allocated_slots = $this->find_available_slots(
            $machine_availability[$machine_id], 
            $required_slots,
            $order_process->priority
        );
        
        if (!empty($allocated_slots)) {
            // 分配时间槽
            foreach ($allocated_slots as $slot) {
                $schedule_data = array(
                    'schedule_date' => $slot['date'],
                    'machine_id' => $machine_id,
                    'process_id' => $order_process->process_id,
                    'time_slot_start' => $slot['start_time'],
                    'time_slot_end' => $slot['end_time'],
                    'utilization_rate' => ($order_process->capacity_per_hour > 0) ? 
                        min(100, ($order_process->estimated_hours / $required_slots * 50)) : 0
                );
                
                $wpdb->insert($schedules_table, $schedule_data);
                
                // 更新机器可用性
                $machine_availability[$machine_id] = array_filter(
                    $machine_availability[$machine_id],
                    function($s) use ($slot) {
                        return !($s['date'] == $slot['date'] && 
                                $s['start_time'] == $slot['start_time']);
                    }
                );
            }
            
            // 更新工序状态
            $wpdb->update($processes_table, 
                array('status' => 'scheduled'), 
                array('id' => $order_process->process_id)
            );
            
            $schedule_results[] = array(
                'order' => $order_process->order_number,
                'process' => $order_process->process_name,
                'machine' => $order_process->machine_name,
                'slots_allocated' => count($allocated_slots)
            );
        }
    }
    
    return $schedule_results;
}

/**
 * 生成时间槽数组
 * @param string $start_date 开始日期
 * @param string $end_date 结束日期
 * @return array 时间槽数组
 */
private function generate_time_slots($start_date, $end_date) {
    $slots = array();
    $current_date = new DateTime($start_date);
    $end_date_obj = new DateTime($end_date);
    
    // 工作时间:8:00-12:00, 13:00-17:00
    $work_periods = array(
        array('start' => '08:00:00', 'end' => '12:00:00'),
        array('start' => '13:00:00', 'end' => '17:00:00')
    );
    
    while ($current_date <= $end_date_obj) {
        $date_str = $current_date->format('Y-m-d');
        
        foreach ($work_periods as $period) {
            $start_time = new DateTime($date_str . ' ' . $period['start']);
            $end_time = new DateTime($date_str . ' ' . $period['end']);
            
            while ($start_time < $end_time) {
                $slot_end = clone $start_time;
                $slot_end->modify('+30 minutes');
                
                if ($slot_end <= $end_time) {
                    $slots[] = array(
                        'date' => $date_str,
                        'start_time' => $start_time->format('H:i:s'),
                        'end_time' => $slot_end->format('H:i:s'),
                        'allocated' => false
                    );
                }
                
                $start_time->modify('+30 minutes');
            }
        }
        
        $current_date->modify('+1 day');
    }
    
    return $slots;
}

/**
 * 寻找可用时间槽
 * @param array $available_slots 可用时间槽
 * @param int $required_slots 所需时间槽数量
 * @param int $priority 优先级
 * @return array 分配的时间槽
 */
private function find_available_slots($available_slots, $required_slots, $priority) {
    $allocated_slots = array();
    $consecutive_count = 0;
    
    // 根据优先级调整搜索策略
    $max_gap = ($priority == 3) ? 0 : (($priority == 2) ? 1 : 2);
    $current_gap = 0;
    
    foreach ($available_slots as $slot) {
        if (!$slot['allocated']) {
            if ($consecutive_count == 0 || 
                ($this->is_consecutive_slot(end($allocated_slots), $slot) && $current_gap <= $max_gap)) {
                
                $allocated_slots[] = $slot;
                $consecutive_count++;
                $current_gap = 0;
                
                if ($consecutive_count >= $required_slots) {
                    return $allocated_slots;
                }
            } else {
                $current_gap++;
                if ($current_gap > $max_gap) {
                    // 重置搜索
                    $allocated_slots = array();
                    $consecutive_count = 0;
                    $current_gap = 0;
                }
            }
        }
    }
    
    return array(); // 没有找到足够的连续时间槽
}

/**
 * 检查时间槽是否连续
 */
private function is_consecutive_slot($prev_slot, $current_slot) {
    if (!$prev_slot) return true;
    
    if ($prev_slot['date'] == $current_slot['date']) {
        $prev_end = new DateTime($prev_slot['date'] . ' ' . $prev_slot['end_time']);
        $current_start = new DateTime($current_slot['date'] . ' ' . $current_slot['start_time']);
        
        return $prev_end == $current_start;
    }
    
    return false;
}
?>

管理界面与可视化展示

创建用户友好的管理界面,展示排程结果。

<?php
// 在SmartProductionScheduler类中添加管理界面方法

public function add_admin_menu() {
    add_menu_page(
        '智能生产排程',
        '生产排程',
        'manage_options',
        'smart-production-scheduler',
        array($this, 'render_main_page'),
        'dashicons-calendar-alt',
        30
    );
    
    add_submenu_page(
        'smart-production-scheduler',
        '订单管理',
        '订单管理',
        'manage_options',
        'sps-orders',
        array($this, 'render_orders_page')
    );
    
    add_submenu_page(
        'smart-production-scheduler',
        '机器管理',
        '机器管理',
        'manage_options',
        'sps-machines',
        array($this, 'render_machines_page')
    );
    
    add_submenu_page(
        'smart-production-scheduler',
        '排程结果',
        '排程结果',
        'manage_options',
        'sps-schedule',
        array($this, 'render_schedule_page')
    );
}

public function render_main_page() {
    ?>
    <div class="wrap">
        <h1>智能生产排程系统</h1>
        
        <div class="sps-dashboard">
            <div class="sps-card">
                <h3>快速排程</h3>
                <form method="post" action="<?php echo admin_url('admin-ajax.php'); ?>">
                    <input type="hidden" name="action" value="sps_process_schedule">
                    <?php wp_nonce_field('sps_schedule_nonce', 'sps_nonce'); ?>
                    
                    <p>
                        <label>开始日期:</label>
                        <input type="date" name="start_date" value="<?php echo date('Y-m-d'); ?>" required>
                    </p>
                    <p>
                        <label>结束日期:</label>
                        <input type="date" name="end_date" value="<?php echo date('Y-m-d', strtotime('+7 days')); ?>" required>
                    </p>
                    <p>
                        <label>排程策略:</label>
                        <select name="strategy">
                            <option value="due_date">按交货期优先</option>
                            <option value="priority">按订单优先级</option>
                            <option value="balanced">平衡负载</option>
                        </select>
                    </p>
                    <p>
                        <button type="submit" class="button button-primary">生成排程</button>
                    </p>
                </form>
            </div>
            
            <div class="sps-card">
                <h3>今日生产概览</h3>
                <div id="sps-today-overview">
                    <!-- 通过AJAX加载 -->
                </div>
            </div>
            
            <div class="sps-card">
                <h3>机器利用率</h3>
                <canvas id="sps-utilization-chart" width="400" height="200"></canvas>
            </div>
        </div>
    </div>
    
    <style>
        .sps-dashboard {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
            gap: 20px;
            margin-top: 20px;
        }
        .sps-card {
            background: #fff;
            padding: 20px;
            border-radius: 5px;
            box-shadow: 0 2px 5px rgba(0,0,0,0.1);
        }
        .sps-card h3 {
            margin-top: 0;
            border-bottom: 2px solid #0073aa;
            padding-bottom: 10px;
        }
    </style>
    
    <script>
    jQuery(document).ready(function($) {
        // 加载今日概览
        $.ajax({
            url: ajaxurl,
            type: 'POST',
            data: {
                action: 'sps_get_today_overview'
            },
            success: function(response) {
                $('#sps-today-overview').html(response);
            }
        });
        
        // 排程表单提交
        $('form').on('submit', function(e) {
            e.preventDefault();
            
            $.ajax({
                url: ajaxurl,
                type: 'POST',
                data: $(this).serialize(),
                beforeSend: function() {
                    $('button[type="submit"]').prop('disabled', true).text('排程中...');
                },
                success: function(response) {
                    alert('排程生成成功!');
                    location.reload();
                },
                error: function() {
                    alert('排程生成失败,请重试。');
                    $('button[type="submit"]').prop('disabled', false).text('生成排程');
                }
            });
        });
    });
    </script>
    <?php
}

public function render_schedule_page() {
    global $wpdb;
    $schedules_table = $wpdb->prefix . 'sps_schedules';
    $machines_table = $wpdb->prefix . 'sps_machines';
    $processes_table = $wpdb->prefix . 'sps_processes';
    $orders_table = $wpdb->prefix . 'sps_orders';
    
    // 获取排程数据
    $schedules = $wpdb->get_results("
        SELECT s.*, m.machine_name, p.process_name, o.order_number, o.product_name
        FROM $schedules_table s
        JOIN $machines_table m ON s.machine_id = m.id
        JOIN $processes_table p ON s.process_id = p.id
        JOIN $orders_table o ON p.order_id = o.id
        WHERE s.schedule_date >= CURDATE()
        ORDER BY s.schedule_date, s.time_slot_start, m.machine_name
    ");
    
    // 按日期和机器分组
    $grouped_schedules = array();
    foreach ($schedules as $schedule) {
        $date = $schedule->schedule_date;
        $machine = $schedule->machine_name;
        
        if (!isset($grouped_schedules[$date])) {
            $grouped_schedules[$date] = array();
        }
        if (!isset($grouped_schedules[$date][$machine])) {
            $grouped_schedules[$date][$machine] = array();
        }
        
        $grouped_schedules[$date][$machine][] = $schedule;
    }
    ?>
    <div class="wrap">
        <h1>生产排程结果</h1>
        
        <div class="sps-schedule-view">
            <?php if (empty($grouped_schedules)): ?>
                <p>暂无排程数据,请先生成排程。</p>
            <?php else: ?>
                <?php foreach ($grouped_schedules as $date => $machines): ?>
                    <div class="sps-date-section">
                        <h2><?php echo date('Y年m月d日', strtotime($date)); ?> (<?php echo date('D', strtotime($date)); ?>)</h2>
                        
                        <?php foreach ($machines as $machine_name => $slots): ?>
                            <div class="sps-machine-schedule">
                                <h3><?php echo $machine_name; ?></h3>
                                <div class="sps-time-slots">
                                    <?php foreach ($slots as $slot): ?>
                                        <div class="sps-slot" 
                                             style="width: <?php echo $this->calculate_slot_width($slot->time_slot_start, $slot->time_slot_end); ?>%;
                                                    background-color: <?php echo $this->get_priority_color($slot->utilization_rate); ?>;">
                                            <div class="sps-slot-content">
                                                <strong><?php echo $slot->order_number; ?></strong><br>
                                                <?php echo $slot->product_name; ?><br>
                                                <?php echo substr($slot->time_slot_start, 0, 5); ?>-<?php echo substr($slot->time_slot_end, 0, 5); ?><br>
                                                <small><?php echo $slot->process_name; ?></small>
                                            </div>
                                        </div>
                                    <?php endforeach; ?>
                                </div>
                            </div>
                        <?php endforeach; ?>
                    </div>
                <?php endforeach; ?>
            <?php endif; ?>
        </div>
    </div>
    
    <style>
        .sps-schedule-view {
            margin-top: 20px;
        }
        .sps-date-section {
            background: #fff;
            padding: 20px;
            margin-bottom: 20px;
            border-radius: 5px;
            box-shadow: 0 2px 5px rgba(0,0,0,0.1);
        }
        .sps-machine-schedule {
            margin: 15px 0;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 3px;
        }
        .sps-time-slots {
            display: flex;
            gap: 2px;
            margin-top: 10px;
            overflow-x: auto;
        }
        .sps-slot {
            min-width: 120px;
            padding: 8px;
            border-radius: 3px;
            color: #fff;
            text-align: center;
            font-size: 12px;
        }
        .sps-slot-content {
            line-height: 1.3;
        }
    </style>
    <?php
}

private function calculate_slot_width($start_time, $end_time) {
    $start = strtotime($start_time);
    $end = strtotime($end_time);
    $duration = ($end - $start) / 3600; // 小时数
    
    // 每个小时占10%宽度
    return min(100, $duration * 10);
}

private function get_priority_color($utilization_rate) {
    if ($utilization_rate >= 90) {
        return '#e74c3c'; // 红色 - 高负荷
    } elseif ($utilization_rate >= 70) {
        return '#f39c12'; // 橙色 - 中等负荷
    } else {
        return '#2ecc71'; // 绿色 - 正常负荷
    }
}
?>

AJAX处理与数据交互

实现前后端数据交互,提供实时更新功能。

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

public function process_schedule_ajax() {
    // 验证nonce
    if (!wp_verify_nonce($_POST['sps_nonce'], 'sps_schedule_nonce')) {
        wp_die('安全验证失败');
    }
    
    // 验证权限
    if (!current_user_can('manage_options')) {
        wp_die('权限不足');
    }
    
    $start_date = sanitize_text_field($_POST['start_date']);
    $end_date = sanitize_text_field($_POST['end_date']);
    $strategy = sanitize_text_field($_POST['strategy']);
    
    try {
        // 根据策略调整排序
        $this->apply_scheduling_strategy($strategy);
        
        // 生成排程
        $results = $this->generate_schedule($start_date, $end_date);
        
        // 记录操作日志
        $this->log_scheduling_action($start_date, $end_date, $strategy, count($results));
        
        wp_send_json_success(array(
            'message' => '排程生成成功',
            'scheduled_count' => count($results),
            'results' => $results
        ));
        
    } catch (Exception $e) {
        wp_send_json_error(array(
            'message' => '排程生成失败: ' . $e->getMessage()
        ));
    }
}

private function apply_scheduling_strategy($strategy) {
    global $wpdb;
    $orders_table = $wpdb->prefix . 'sps_orders';
    
    switch ($strategy) {
        case 'due_date':
            // 按交货期排序(默认)
            break;
            
        case 'priority':
            // 按优先级排序
            $wpdb->query("ALTER TABLE $orders_table ORDER BY priority DESC, due_date ASC");
            break;
            
        case 'balanced':
            // 平衡负载策略
            $this->apply_balanced_strategy();
            break;
    }
}

private function apply_balanced_strategy() {
    global $wpdb;
    $orders_table = $wpdb->prefix . 'sps_orders';
    $processes_table = $wpdb->prefix . 'sps_processes';
    
    // 获取所有待排程订单
    $orders = $wpdb->get_results("
        SELECT o.*, SUM(p.estimated_hours) as total_hours
        FROM $orders_table o
        JOIN $processes_table p ON o.id = p.order_id
        WHERE o.status = 'pending'
        GROUP BY o.id
        ORDER BY o.priority DESC, total_hours ASC
    ");
    
    // 重新排序订单ID
    $order_ids = array_map(function($order) {
        return $order->id;
    }, $orders);
    
    // 更新订单排序(通过临时字段)
    foreach ($order_ids as $index => $order_id) {
        $wpdb->update($orders_table, 
            array('custom_order' => $index + 1),
            array('id' => $order_id)
        );
    }
}

private function log_scheduling_action($start_date, $end_date, $strategy, $count) {
    global $wpdb;
    $logs_table = $wpdb->prefix . 'sps_logs';
    
    // 创建日志表(如果不存在)
    if ($wpdb->get_var("SHOW TABLES LIKE '$logs_table'") != $logs_table) {
        $charset_collate = $wpdb->get_charset_collate();
        $sql = "CREATE TABLE $logs_table (
            id INT(11) NOT NULL AUTO_INCREMENT,
            user_id INT(11) NOT NULL,
            action_type VARCHAR(50) NOT NULL,
            parameters TEXT,
            result TEXT,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY (id)
        ) $charset_collate;";
        
        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
        dbDelta($sql);
    }
    
    // 记录日志
    $wpdb->insert($logs_table, array(
        'user_id' => get_current_user_id(),
        'action_type' => 'schedule_generation',
        'parameters' => json_encode(array(
            'start_date' => $start_date,
            'end_date' => $end_date,
            'strategy' => $strategy
        )),
        'result' => json_encode(array(
            'scheduled_count' => $count,
            'timestamp' => current_time('mysql')
        ))
    ));
}

// 添加更多AJAX处理
add_action('wp_ajax_sps_get_today_overview', array($this, 'get_today_overview_ajax'));

public function get_today_overview_ajax() {
    global $wpdb;
    $schedules_table = $wpdb->prefix . 'sps_schedules';
    $machines_table = $wpdb->prefix . 'sps_machines';
    
    $today = date('Y-m-d');
    
    // 获取今日排程统计
    $stats = $wpdb->get_row("
        SELECT 
            COUNT(DISTINCT s.machine_id) as active_machines,
            COUNT(s.id) as total_slots,
            AVG(s.utilization_rate) as avg_utilization
        FROM $schedules_table s
        WHERE s.schedule_date = '$today'
    ");
    
    // 获取机器详情
    $machines = $wpdb->get_results("
        SELECT m.machine_name, 
               COUNT(s.id) as scheduled_slots,
               AVG(s.utilization_rate) as machine_utilization
        FROM $machines_table m
        LEFT JOIN $schedules_table s ON m.id = s.machine_id AND s.schedule_date = '$today'
        WHERE m.status = 'active'
        GROUP BY m.id
    ");
    
    ob_start();
    ?>
    <div class="sps-overview-stats">
        <p>活跃机器: <strong><?php echo $stats->active_machines ?? 0; ?></strong> 台</p>
        <p>排程任务: <strong><?php echo $stats->total_slots ?? 0; ?></strong> 个</p>
        <p>平均利用率: <strong><?php echo round($stats->avg_utilization ?? 0, 1); ?>%</strong></p>
    </div>
    
    <h4>机器状态</h4>
    <ul>
        <?php foreach ($machines as $machine): ?>
            <li>
                <?php echo $machine->machine_name; ?>:
                <?php echo $machine->scheduled_slots; ?> 个任务,
                利用率 <?php echo round($machine->machine_utilization, 1); ?>%
            </li>
        <?php endforeach; ?>
    </ul>
    <?php
    
    wp_die();
}
?>

高级功能:约束优化与冲突解决

<?php
// 在SmartProductionScheduler类中添加高级功能

/**
 * 优化现有排程,解决冲突
 */
public function optimize_schedule($schedule_ids = array()) {
    global $wpdb;
    $schedules_table = $wpdb->prefix . 'sps_schedules';
    
    // 获取需要优化的排程
    if (empty($schedule_ids)) {
        $schedule_ids = $wpdb->get_col("
            SELECT id FROM $schedules_table 
            WHERE schedule_date >= CURDATE()
            ORDER BY schedule_date, time_slot_start
        ");
    }
    
    $optimizations = array();
    
    foreach ($schedule_ids as $schedule_id) {
        $schedule = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM $schedules_table WHERE id = %d", $schedule_id
        ));
        
        // 检查冲突
        $conflicts = $this->detect_conflicts($schedule);
        
        if (!empty($conflicts)) {
            // 解决冲突
            $resolution = $this->resolve_conflict($schedule, $conflicts);
            
            if ($resolution['resolved']) {
                // 更新排程
                $wpdb->update($schedules_table, 
                    array(
                        'time_slot_start' => $resolution['new_start'],
                        'time_slot_end' => $resolution['new_end']
                    ),
                    array('id' => $schedule_id)
                );
                
                $optimizations[] = array(
                    'schedule_id' => $schedule_id,
                    'original' => $schedule->time_slot_start . '-' . $schedule->time_slot_end,
                    'optimized' => $resolution['new_start'] . '-' . $resolution['new_end'],
                    'reason' => $resolution['reason']
                );
            }
        }
    }
    
    return $optimizations;
}

/**
 * 检测排程冲突
 */
private function detect_conflicts($schedule) {
    global $wpdb;
    $schedules_table = $wpdb->prefix . 'sps_schedules';
    
    $conflicts = $wpdb->get_results($wpdb->prepare("
        SELECT s2.* 
        FROM $schedules_table s1
        JOIN $schedules_table s2 ON s1.machine_id = s2.machine_id 
            AND s1.schedule_date = s2.schedule_date
            AND s1.id != s2.id
        WHERE s1.id = %d 
        AND (
            (s1.time_slot_start < s2.time_slot_end AND s1.time_slot_end > s2.time_slot_start)
            OR ABS(TIMESTAMPDIFF(MINUTE, s1.time_slot_start, s2.time_slot_start)) < 30
        )
    ", $schedule->id));
    
    return $conflicts;
}

/**
 * 解决冲突
 */
private function resolve_conflict($schedule, $conflicts) {
    global $wpdb;
    $schedules_table = $wpdb->prefix . 'sps_schedules';
    
    // 尝试将任务移动到相邻时间槽
    $time_slots = $this->get_available_slots_for_machine(
        $schedule->machine_id,
        $schedule->schedule_date,
        $schedule->id
    );
    
    $required_duration = strtotime($schedule->time_slot_end) - strtotime($schedule->time_slot_start);
    
    foreach ($time_slots as $slot) {
        $slot_duration = strtotime($slot['end']) - strtotime($slot['start']);
        
        if ($slot_duration >= $required_duration) {
            return array(
                'resolved' => true,
                'new_start' => $slot['start'],
                'new_end' => date('H:i:s', strtotime($slot['start']) + $required_duration),
                'reason' => '避免机器冲突'
            );
        }
    }
    
    // 如果无法解决,返回原始时间
    return array(
        'resolved' => false,
        'reason' => '无可用时间槽'
    );
}

/**
 * 获取机器可用时间槽
 */
private function get_available_slots_for_machine($machine_id, $date, $exclude_schedule_id) {
    global $wpdb;
    $schedules_table = $wpdb->prefix . 'sps_schedules';
    
    // 获取该机器当天的所有排程
    $existing_schedules = $wpdb->get_results($wpdb->prepare("
        SELECT time_slot_start, time_slot_end
        FROM $schedules_table
        WHERE machine_id = %d 
        AND schedule_date = %s
        AND id != %d
        ORDER BY time_slot_start
    ", $machine_id, $date, $exclude_schedule_id));
    
本文来自网络投稿,不代表本站点的立场,转载请注明出处:https://www.gongxiangcang.com/6628.html

溯源库®作者

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

为您推荐

联系我们

联系我们

18559313275

在线咨询: QQ交谈

邮箱: vip@suyuanku.com

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

微信扫一扫关注我们

返回顶部