文章目录
-
- 在制造业和项目管理中,智能排产是一个关键环节,它能够优化资源分配、提高生产效率。本教程将指导您如何在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__)); // 初始化插件 require_once SPS_PLUGIN_DIR . 'includes/class-database.php'; require_once SPS_PLUGIN_DIR . 'includes/class-scheduler.php'; require_once SPS_PLUGIN_DIR . 'includes/class-frontend.php'; require_once SPS_PLUGIN_DIR . 'includes/class-admin.php'; // 激活和停用钩子 register_activation_hook(__FILE__, array('SPS_Database', 'create_tables')); register_deactivation_hook(__FILE__, array('SPS_Database', 'drop_tables')); // 初始化插件类 class Smart_Production_Scheduler { 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() { add_action('init', array($this, 'load_textdomain')); // 初始化各个模块 SPS_Database::init(); SPS_Scheduler::init(); SPS_Frontend::init(); SPS_Admin::init(); } public function load_textdomain() { load_plugin_textdomain('smart-production-scheduler', false, dirname(plugin_basename(__FILE__)) . '/languages/'); } } // 启动插件 Smart_Production_Scheduler::get_instance(); ?>
- 在includes/class-database.php中创建数据库表: <?php /** * 数据库处理类 */ class SPS_Database { public static function init() { // 数据库初始化代码 } /** * 创建插件所需的数据库表 */ public static function create_tables() { global $wpdb; $charset_collate = $wpdb->get_charset_collate(); // 订单表 $orders_table = $wpdb->prefix . 'sps_orders'; $orders_sql = "CREATE TABLE IF NOT EXISTS $orders_table ( id INT(11) NOT NULL AUTO_INCREMENT, customer_name VARCHAR(100) NOT NULL, product_type VARCHAR(50) NOT NULL, quantity INT(11) NOT NULL, production_time INT(11) NOT NULL COMMENT '生产所需时间(小时)', priority INT(11) DEFAULT 5 COMMENT '优先级,1-10,1为最高', due_date DATE NOT NULL COMMENT '交货日期', status VARCHAR(20) DEFAULT 'pending' COMMENT '订单状态', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ) $charset_collate;"; // 排产计划表 $schedule_table = $wpdb->prefix . 'sps_schedule'; $schedule_sql = "CREATE TABLE IF NOT EXISTS $schedule_table ( id INT(11) NOT NULL AUTO_INCREMENT, order_id INT(11) NOT NULL, machine_id INT(11) NOT NULL COMMENT '机器ID', start_time DATETIME NOT NULL, end_time DATETIME NOT NULL, completed TINYINT(1) DEFAULT 0 COMMENT '是否完成', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), FOREIGN KEY (order_id) REFERENCES $orders_table(id) ON DELETE CASCADE ) $charset_collate;"; // 机器资源表 $machines_table = $wpdb->prefix . 'sps_machines'; $machines_sql = "CREATE TABLE IF NOT EXISTS $machines_table ( id INT(11) NOT NULL AUTO_INCREMENT, machine_name VARCHAR(100) NOT NULL, capacity INT(11) NOT NULL COMMENT '每小时产能', status VARCHAR(20) DEFAULT 'available' COMMENT '机器状态', maintenance_schedule TEXT COMMENT '维护计划', PRIMARY KEY (id) ) $charset_collate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($orders_sql); dbDelta($schedule_sql); dbDelta($machines_sql); // 插入示例机器数据 self::insert_sample_machines(); } /** * 插入示例机器数据 */ private static function insert_sample_machines() { global $wpdb; $table = $wpdb->prefix . 'sps_machines'; $machines = array( array('machine_name' => 'CNC机床1', 'capacity' => 10), array('machine_name' => 'CNC机床2', 'capacity' => 8), array('machine_name' => '3D打印机1', 'capacity' => 5), array('machine_name' => '激光切割机', 'capacity' => 12), ); foreach ($machines as $machine) { $wpdb->insert($table, $machine); } } /** * 删除数据库表(插件停用时) */ public static function drop_tables() { global $wpdb; $tables = array( $wpdb->prefix . 'sps_schedule', $wpdb->prefix . 'sps_orders', $wpdb->prefix . 'sps_machines', ); foreach ($tables as $table) { $wpdb->query("DROP TABLE IF EXISTS $table"); } } } ?>
- 在includes/class-scheduler.php中实现核心排产算法: <?php /** * 智能排产算法类 */ class SPS_Scheduler { public static function init() { add_action('sps_generate_schedule', array(__CLASS__, 'generate_schedule')); } /** * 智能排产主函数 * @param array $orders 订单数组 * @param array $machines 机器数组 * @return array 排产结果 */ public static function intelligent_scheduling($orders, $machines) { // 按优先级和交货日期排序订单 usort($orders, function($a, $b) { if ($a['priority'] == $b['priority']) { return strtotime($a['due_date']) - strtotime($b['due_date']); } return $a['priority'] - $b['priority']; }); $schedule = array(); $machine_availability = array(); // 初始化机器可用时间 foreach ($machines as $machine) { $machine_availability[$machine['id']] = current_time('mysql'); } // 为每个订单分配机器 foreach ($orders as $order) { $best_machine = self::find_best_machine($order, $machines, $machine_availability); if ($best_machine) { $start_time = $machine_availability[$best_machine['id']]; $end_time = self::calculate_end_time($start_time, $order['production_time']); $schedule[] = array( 'order_id' => $order['id'], 'machine_id' => $best_machine['id'], 'start_time' => $start_time, 'end_time' => $end_time, 'order_details' => $order ); // 更新机器可用时间 $machine_availability[$best_machine['id']] = $end_time; } } return $schedule; } /** * 为订单寻找最佳机器 * @param array $order 订单信息 * @param array $machines 可用机器 * @param array $availability 机器可用时间 * @return array|null 最佳机器信息 */ private static function find_best_machine($order, $machines, $availability) { $best_machine = null; $best_score = PHP_INT_MAX; foreach ($machines as $machine) { if ($machine['status'] !== 'available') { continue; } // 计算分数:基于产能和可用时间 $capacity_score = $order['production_time'] / $machine['capacity']; $availability_time = strtotime($availability[$machine['id']]); $time_score = $availability_time; // 综合分数(可根据需求调整权重) $total_score = $capacity_score * 0.7 + $time_score * 0.3; if ($total_score < $best_score) { $best_score = $total_score; $best_machine = $machine; } } return $best_machine; } /** * 计算结束时间 * @param string $start_time 开始时间 * @param int $production_hours 生产所需小时数 * @return string 结束时间 */ private static function calculate_end_time($start_time, $production_hours) { $start_timestamp = strtotime($start_time); // 考虑工作时间(假设每天工作8小时) $work_hours_per_day = 8; $work_days_needed = ceil($production_hours / $work_hours_per_day); // 计算实际结束时间(跳过周末) $current_day = 0; $hours_remaining = $production_hours; while ($hours_remaining > 0) { $current_timestamp = $start_timestamp + ($current_day * 86400); $day_of_week = date('N', $current_timestamp); // 跳过周末(6=周六,7=周日) if ($day_of_week < 6) { $hours_today = min($work_hours_per_day, $hours_remaining); $hours_remaining -= $hours_today; } $current_day++; } $end_timestamp = $start_timestamp + ($current_day * 86400); return date('Y-m-d H:i:s', $end_timestamp); } /** * 生成排产计划 */ public static function generate_schedule() { global $wpdb; // 获取待排产的订单 $orders_table = $wpdb->prefix . 'sps_orders'; $orders = $wpdb->get_results( "SELECT * FROM $orders_table WHERE status = 'pending' ORDER BY priority, due_date", ARRAY_A ); // 获取可用机器 $machines_table = $wpdb->prefix . 'sps_machines'; $machines = $wpdb->get_results( "SELECT * FROM $machines_table WHERE status = 'available'", ARRAY_A ); if (empty($orders) || empty($machines)) { return false; } // 执行智能排产 $schedule = self::intelligent_scheduling($orders, $machines); // 保存排产结果到数据库 $schedule_table = $wpdb->prefix . 'sps_schedule'; foreach ($schedule as $item) { $wpdb->insert($schedule_table, array( 'order_id' => $item['order_id'], 'machine_id' => $item['machine_id'], 'start_time' => $item['start_time'], 'end_time' => $item['end_time'] )); // 更新订单状态 $wpdb->update( $orders_table, array('status' => 'scheduled'), array('id' => $item['order_id']) ); } return $schedule; } } ?>
- 在includes/class-frontend.php中创建用户提交订单的表单: <?php /** * 前端处理类 */ class SPS_Frontend { public static function init() { add_shortcode('sps_order_form', array(__CLASS__, 'order_form_shortcode')); add_action('wp_enqueue_scripts', array(__CLASS__, 'enqueue_scripts')); add_action('wp_ajax_sps_submit_order', array(__CLASS__, 'ajax_submit_order')); add_action('wp_ajax_nopriv_sps_submit_order', array(__CLASS__, 'ajax_submit_order')); } /** * 订单表单短代码 */ public static function order_form_shortcode() { ob_start(); ?> <div class="sps-order-form-container"> <h3>提交定制订单</h3> <form id="sps-order-form" method="post"> <?php wp_nonce_field('sps_submit_order', 'sps_nonce'); ?> <div class="form-group"> <label for="customer_name">客户名称 *</label> <input type="text" id="customer_name" name="customer_name" required> </div> <div class="form-group"> <label for="product_type">产品类型 *</label> <select id="product_type" name="product_type" required> <option value="">请选择</option> <option value="metal_part">金属零件</option> <option value="plastic_part">塑料零件</option> <option value="electronic_assembly">电子装配</option> <option value="custom_prototype">定制原型</option> </select> </div> <div class="form-group"> <label for="quantity">数量 *</label> <input type="number" id="quantity" name="quantity" min="1" max="1000" required> <small>小批量定制:1-1000件</small> </div> <div class="form-group"> <label for="production_time">预计生产时间(小时) *</label> <input type="number" id="production_time" name="production_time" min="1" max="500" required> </div> <div class="form-group"> <label for="priority">优先级 *</label> <select id="priority" name="priority" required> <option value="1">最高 (1)</option> <option value="3">高 (3)</option> <option value="5" selected>中 (5)</option> <option value="7">低 (7)</option> <option value="10">最低 (10)</option> </select> </div> <div class="form-group"> <label for="due_date">期望交货日期 *</label> <input type="date" id="due_date" name="due_date" required> </div> <div class="form-group"> <label for="notes">备注</label> <textarea id="notes" name="notes" rows="3"></textarea> </div> <button type="submit" class="sps-submit-btn">提交订单</button> <div id="sps-response-message"></div> </form> </div> <style> .sps-order-form-container { max-width: 600px; margin: 20px auto; padding: 20px; background: #f9f9f9; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } .form-group { margin-bottom: 15px; } .form-group label { display: block; margin-bottom: 5px; font-weight: bold; } .form-group input, .form-group select, .form-group textarea { width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; } .sps-submit-btn { background: #0073aa; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; } .sps-submit-btn:hover { background: #005a87; } #sps-response-message { margin-top: 15px; padding: 10px; border-radius: 4px; } .success { background: #d4edda; color: #155724; border: 1px solid #c3e6cb; } .error { background: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; } </style> <?php return ob_get_clean(); } /** * 提交订单的AJAX处理 */ public static function ajax_submit_order() { // 验证nonce if (!wp_verify_nonce($_POST['sps_nonce'], 'sps_submit_order')) { wp_die('安全验证失败'); } // 验证数据 $required_fields = array('customer_name', 'product_type', 'quantity', 'production_time', 'priority', 'due_date'); foreach ($required_fields as $field) { if (empty($_POST[$field])) { wp_send_json_error('请填写所有必填字段'); } } global $wpdb; $table = $wpdb->prefix . 'sps_orders'; // 准备数据 $order_data = array( 'customer_name' => sanitize_text_field($_POST['customer_name']), 'product_type' => sanitize_text_field($_POST['product_type']), 'quantity' => intval($_POST['quantity']), 'production_time' => intval($_POST['production_time']), 'priority' => intval($_POST['priority']), 'due_date' => sanitize_text_field($_POST['due_date']), 'status' => 'pending' ); // 插入数据库 $result = $wpdb->insert($table, $order_data); if ($result) { // 触发排产计划生成(可以设置为定时任务或手动触发) do_action('sps_generate_schedule'); wp_send_json_success(array( 'message' => '订单提交成功!订单ID:' . $wpdb->insert_id, 'order_id' => $wpdb->insert_id )); } else { wp_send_json_error('订单提交失败,请重试'); } } /** * 加载前端脚本和样式 */ public static function enqueue_scripts() { wp_enqueue_style('sps-frontend-style', SPS_PLUGIN_URL . 'assets/css/frontend.css'); wp_enqueue_script('sps-frontend-script', SPS_PLUGIN_URL . 'assets/js/frontend.js', array('jquery'), SPS_VERSION, true); wp_localize_script('sps-frontend-script', 'sps_ajax', array( 'ajax_url' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('sps_submit_order') )); } } ?>
- 在includes/class-admin.php中创建管理界面: <?php /** * 后台管理类 */ class SPS_Admin { public static function init() { add_action('admin_menu', array(__CLASS__, 'add_admin_menu')); add_action('admin_enqueue_scripts', array(__CLASS__, 'enqueue_admin_scripts')); add_action('admin_post_generate_schedule', array(__CLASS__, 'handle_generate_schedule')); } /** * 添加管理菜单 */ public static function add_admin_menu() { add_menu_page( '智能排产系统', '智能排产', 'manage_options', 'smart-production-scheduler', array(__CLASS__, 'display_dashboard'), 'dashicons-schedule', 30 ); add_submenu_page( 'smart-production-scheduler', '订单管理', '订单管理', 'manage_options', 'sps-orders', array(__CLASS__, 'display_orders_page') ); add_submenu_page( 'smart-production-scheduler', '排产计划', '排产计划', 'manage_options', 'sps-schedule', array(__CLASS__, 'display_schedule_page') ); add_submenu_page( 'smart-production-scheduler', '机器管理', '机器管理', 'manage_options', 'sps-machines', array(__CLASS__, 'display_machines_page') ); add_submenu_page( 'smart-production-scheduler', '排产设置', '排产设置', 'manage_options', 'sps-settings', array(__CLASS__, 'display_settings_page') ); } /** * 显示仪表板 */ public static function display_dashboard() { global $wpdb; // 获取统计数据 $orders_table = $wpdb->prefix . 'sps_orders'; $schedule_table = $wpdb->prefix . 'sps_schedule'; $machines_table = $wpdb->prefix . 'sps_machines'; $total_orders = $wpdb->get_var("SELECT COUNT(*) FROM $orders_table"); $pending_orders = $wpdb->get_var("SELECT COUNT(*) FROM $orders_table WHERE status = 'pending'"); $completed_orders = $wpdb->get_var("SELECT COUNT(*) FROM $orders_table WHERE status = 'completed'"); $active_machines = $wpdb->get_var("SELECT COUNT(*) FROM $machines_table WHERE status = 'available'"); ?> <div class="wrap"> <h1>智能排产系统仪表板</h1> <div class="sps-dashboard-widgets"> <div class="sps-widget"> <h3>总订单数</h3> <p class="sps-stat"><?php echo $total_orders; ?></p> </div> <div class="sps-widget"> <h3>待处理订单</h3> <p class="sps-stat"><?php echo $pending_orders; ?></p> </div> <div class="sps-widget"> <h3>已完成订单</h3> <p class="sps-stat"><?php echo $completed_orders; ?></p> </div> <div class="sps-widget"> <h3>可用机器</h3> <p class="sps-stat"><?php echo $active_machines; ?></p> </div> </div> <div class="sps-dashboard-actions"> <form method="post" action="<?php echo admin_url('admin-post.php'); ?>"> <input type="hidden" name="action" value="generate_schedule"> <?php wp_nonce_field('generate_schedule_action', 'generate_schedule_nonce'); ?> <button type="submit" class="button button-primary button-large"> 立即生成排产计划 </button> </form> </div> <div class="sps-recent-orders"> <h2>最近订单</h2> <?php self::display_orders_table(5); ?> </div> <div class="sps-upcoming-schedule"> <h2>即将开始的排产</h2> <?php self::display_upcoming_schedule(); ?> </div> </div> <style> .sps-dashboard-widgets { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin: 20px 0; } .sps-widget { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); text-align: center; } .sps-stat { font-size: 2em; font-weight: bold; color: #0073aa; margin: 10px 0; } .sps-dashboard-actions { margin: 30px 0; padding: 20px; background: white; border-radius: 8px; } </style> <?php } /** * 显示订单管理页面 */ public static function display_orders_page() { global $wpdb; $table = $wpdb->prefix . 'sps_orders'; // 处理批量操作 if (isset($_POST['action']) && $_POST['action'] == 'bulk_action') { self::handle_bulk_actions(); } // 获取订单数据 $orders = $wpdb->get_results("SELECT * FROM $table ORDER BY created_at DESC", ARRAY_A); ?> <div class="wrap"> <h1>订单管理</h1> <form method="post" action=""> <?php wp_nonce_field('bulk_action', 'bulk_action_nonce'); ?> <div class="tablenav top"> <div class="alignleft actions bulkactions"> <select name="bulk_action"> <option value="">批量操作</option> <option value="delete">删除</option> <option value="mark_completed">标记为完成</option> <option value="mark_pending">标记为待处理</option> </select> <button type="submit" class="button action">应用</button> </div> </div> <table class="wp-list-table widefat fixed striped"> <thead> <tr> <th class="check-column"><input type="checkbox" id="cb-select-all"></th> <th>ID</th> <th>客户名称</th> <th>产品类型</th> <th>数量</th> <th>生产时间</th> <th>优先级</th> <th>交货日期</th> <th>状态</th> <th>创建时间</th> <th>操作</th> </tr> </thead> <tbody> <?php foreach ($orders as $order): ?> <tr> <th scope="row"><input type="checkbox" name="order_ids[]" value="<?php echo $order['id']; ?>"></th> <td><?php echo $order['id']; ?></td> <td><?php echo esc_html($order['customer_name']); ?></td> <td><?php echo esc_html($order['product_type']); ?></td> <td><?php echo $order['quantity']; ?></td> <td><?php echo $order['production_time']; ?> 小时</td> <td> <span class="priority-badge priority-<?php echo $order['priority']; ?>"> <?php echo $order['priority']; ?> </span> </td> <td><?php echo $order['due_date']; ?></td> <td> <span class="status-badge status-<?php echo $order['status']; ?>"> <?php echo self::get_status_label($order['status']); ?> </span> </td> <td><?php echo $order['created_at']; ?></td> <td> <a href="#" class="button button-small view-order" data-id="<?php echo $order['id']; ?>">查看</a> <a href="#" class="button button-small delete-order" data-id="<?php echo $order['id']; ?>">删除</a> </td> </tr> <?php endforeach; ?> </tbody> </table> </form> </div> <style> .priority-badge { display: inline-block; padding: 2px 8px; border-radius: 12px; font-size: 12px; font-weight: bold; } .priority-1, .priority-2, .priority-3 { background: #ff6b6b; color: white; } .priority-4, .priority-5, .priority-6 { background: #ffd93d; color: #333; } .priority-7, .priority-8, .priority-9, .priority-10 { background: #6bcf7f; color: white; } .status-badge { display: inline-block; padding: 2px 8px; border-radius: 12px; font-size: 12px; font-weight: bold; } .status-pending { background: #ffd93d; color: #333; } .status-scheduled { background: #4d96ff; color: white; } .status-completed { background: #6bcf7f; color: white; } </style> <script> jQuery(document).ready(function($) { // 全选/取消全选 $('#cb-select-all').on('change', function() { $('input[name="order_ids[]"]').prop('checked', this.checked); }); // 查看订单详情 $('.view-order').on('click', function(e) { e.preventDefault(); var orderId = $(this).data('id'); // 这里可以添加查看详情的逻辑 alert('查看订单 ' + orderId + ' 的详情'); }); // 删除订单 $('.delete-order').on('click', function(e) { e.preventDefault(); if (confirm('确定要删除这个订单吗?')) { var orderId = $(this).data('id'); // 这里可以添加删除订单的AJAX请求 } }); }); </script> <?php } /** * 显示排产计划页面 */ public static function display_schedule_page() { global $wpdb; $schedule_table = $wpdb->prefix . 'sps_schedule'; $orders_table = $wpdb->prefix . 'sps_orders'; $machines_table = $wpdb->prefix . 'sps_machines'; // 获取排产数据 $schedule = $wpdb->get_results(" SELECT s.*, o.customer_name, o.product_type, m.machine_name FROM $schedule_table s LEFT JOIN $orders_table o ON s.order_id = o.id LEFT JOIN $machines_table m ON s.machine_id = m.id ORDER BY s.start_time ASC ", ARRAY_A); ?> <div class="wrap"> <h1>排产计划</h1> <div class="sps-gantt-chart"> <h2>甘特图</h2> <div class="gantt-container"> <?php foreach ($schedule as $item): $start_date = new DateTime($item['start_time']); $end_date = new DateTime($item['end_time']); $duration = $start_date->diff($end_date)->days; ?> <div class="gantt-item" style="margin-left: <?php echo $duration * 10; ?>px; width: <?php echo max(50, $duration * 20); ?>px;"> <div class="gantt-bar"> <span class="gantt-label"> <?php echo esc_html($item['customer_name']); ?> - <?php echo esc_html($item['product_type']); ?> </span> </div> <div class="gantt-info"> 机器: <?php echo esc_html($item['machine_name']); ?><br> 开始: <?php echo $item['start_time']; ?><br> 结束: <?php echo $item['end_time']; ?> </div> </div> <?php endforeach; ?> </div> </div> <table class="wp-list-table widefat fixed striped"> <thead> <tr> <th>订单ID</th> <th>客户名称</th> <th>产品类型</th> <th>机器</th> <th>开始时间</th> <th>结束时间</th> <th>状态</th> <th>操作</th> </tr> </thead> <tbody> <?php foreach ($schedule as $item): ?> <tr> <td><?php echo $item['order_id']; ?></td> <td><?php echo esc_html($item['customer_name']); ?></td> <td><?php echo esc_html($item['product_type']); ?></td> <td><?php echo esc_html($item['machine_name']); ?></td> <td><?php echo $item['start_time']; ?></td> <td><?php echo $item['end_time']; ?></td> <td> <?php if ($item['completed']): ?> <span class="status-badge status-completed">已完成</span> <?php else: ?> <span class="status-badge status-scheduled">已排产</span> <?php endif; ?> </td> <td> <button class="button button-small mark-completed" data-id="<?php echo $item['id']; ?>"> <?php echo $item['completed'] ? '取消完成' : '标记完成'; ?> </button> </td> </tr> <?php endforeach; ?> </tbody> </table> </div> <style> .sps-gantt-chart { margin: 20px 0; padding: 20px; background: white; border-radius: 8px; } .gantt-container { padding: 20px; background: #f5f5f5; border-radius: 4px; overflow-x: auto; } .gantt-item { margin: 10px 0; position: relative; } .gantt-bar { background: #4d96ff; color: white; padding: 8px 12px; border-radius: 4px; cursor: pointer; transition: background 0.3s; } .gantt-bar:hover { background: #2d76df; } .gantt-info { display: none; position: absolute;
在制造业和项目管理中,智能排产是一个关键环节,它能够优化资源分配、提高生产效率。本教程将指导您如何在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__));
// 初始化插件
require_once SPS_PLUGIN_DIR . 'includes/class-database.php';
require_once SPS_PLUGIN_DIR . 'includes/class-scheduler.php';
require_once SPS_PLUGIN_DIR . 'includes/class-frontend.php';
require_once SPS_PLUGIN_DIR . 'includes/class-admin.php';
// 激活和停用钩子
register_activation_hook(__FILE__, array('SPS_Database', 'create_tables'));
register_deactivation_hook(__FILE__, array('SPS_Database', 'drop_tables'));
// 初始化插件类
class Smart_Production_Scheduler {
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() {
add_action('init', array($this, 'load_textdomain'));
// 初始化各个模块
SPS_Database::init();
SPS_Scheduler::init();
SPS_Frontend::init();
SPS_Admin::init();
}
public function load_textdomain() {
load_plugin_textdomain('smart-production-scheduler', false, dirname(plugin_basename(__FILE__)) . '/languages/');
}
}
// 启动插件
Smart_Production_Scheduler::get_instance();
?>
在includes/class-database.php中创建数据库表:
<?php
/**
* 数据库处理类
*/
class SPS_Database {
public static function init() {
// 数据库初始化代码
}
/**
* 创建插件所需的数据库表
*/
public static function create_tables() {
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
// 订单表
$orders_table = $wpdb->prefix . 'sps_orders';
$orders_sql = "CREATE TABLE IF NOT EXISTS $orders_table (
id INT(11) NOT NULL AUTO_INCREMENT,
customer_name VARCHAR(100) NOT NULL,
product_type VARCHAR(50) NOT NULL,
quantity INT(11) NOT NULL,
production_time INT(11) NOT NULL COMMENT '生产所需时间(小时)',
priority INT(11) DEFAULT 5 COMMENT '优先级,1-10,1为最高',
due_date DATE NOT NULL COMMENT '交货日期',
status VARCHAR(20) DEFAULT 'pending' COMMENT '订单状态',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id)
) $charset_collate;";
// 排产计划表
$schedule_table = $wpdb->prefix . 'sps_schedule';
$schedule_sql = "CREATE TABLE IF NOT EXISTS $schedule_table (
id INT(11) NOT NULL AUTO_INCREMENT,
order_id INT(11) NOT NULL,
machine_id INT(11) NOT NULL COMMENT '机器ID',
start_time DATETIME NOT NULL,
end_time DATETIME NOT NULL,
completed TINYINT(1) DEFAULT 0 COMMENT '是否完成',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
FOREIGN KEY (order_id) REFERENCES $orders_table(id) ON DELETE CASCADE
) $charset_collate;";
// 机器资源表
$machines_table = $wpdb->prefix . 'sps_machines';
$machines_sql = "CREATE TABLE IF NOT EXISTS $machines_table (
id INT(11) NOT NULL AUTO_INCREMENT,
machine_name VARCHAR(100) NOT NULL,
capacity INT(11) NOT NULL COMMENT '每小时产能',
status VARCHAR(20) DEFAULT 'available' COMMENT '机器状态',
maintenance_schedule TEXT COMMENT '维护计划',
PRIMARY KEY (id)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($orders_sql);
dbDelta($schedule_sql);
dbDelta($machines_sql);
// 插入示例机器数据
self::insert_sample_machines();
}
/**
* 插入示例机器数据
*/
private static function insert_sample_machines() {
global $wpdb;
$table = $wpdb->prefix . 'sps_machines';
$machines = array(
array('machine_name' => 'CNC机床1', 'capacity' => 10),
array('machine_name' => 'CNC机床2', 'capacity' => 8),
array('machine_name' => '3D打印机1', 'capacity' => 5),
array('machine_name' => '激光切割机', 'capacity' => 12),
);
foreach ($machines as $machine) {
$wpdb->insert($table, $machine);
}
}
/**
* 删除数据库表(插件停用时)
*/
public static function drop_tables() {
global $wpdb;
$tables = array(
$wpdb->prefix . 'sps_schedule',
$wpdb->prefix . 'sps_orders',
$wpdb->prefix . 'sps_machines',
);
foreach ($tables as $table) {
$wpdb->query("DROP TABLE IF EXISTS $table");
}
}
}
?>
在includes/class-scheduler.php中实现核心排产算法:
<?php
/**
* 智能排产算法类
*/
class SPS_Scheduler {
public static function init() {
add_action('sps_generate_schedule', array(__CLASS__, 'generate_schedule'));
}
/**
* 智能排产主函数
* @param array $orders 订单数组
* @param array $machines 机器数组
* @return array 排产结果
*/
public static function intelligent_scheduling($orders, $machines) {
// 按优先级和交货日期排序订单
usort($orders, function($a, $b) {
if ($a['priority'] == $b['priority']) {
return strtotime($a['due_date']) - strtotime($b['due_date']);
}
return $a['priority'] - $b['priority'];
});
$schedule = array();
$machine_availability = array();
// 初始化机器可用时间
foreach ($machines as $machine) {
$machine_availability[$machine['id']] = current_time('mysql');
}
// 为每个订单分配机器
foreach ($orders as $order) {
$best_machine = self::find_best_machine($order, $machines, $machine_availability);
if ($best_machine) {
$start_time = $machine_availability[$best_machine['id']];
$end_time = self::calculate_end_time($start_time, $order['production_time']);
$schedule[] = array(
'order_id' => $order['id'],
'machine_id' => $best_machine['id'],
'start_time' => $start_time,
'end_time' => $end_time,
'order_details' => $order
);
// 更新机器可用时间
$machine_availability[$best_machine['id']] = $end_time;
}
}
return $schedule;
}
/**
* 为订单寻找最佳机器
* @param array $order 订单信息
* @param array $machines 可用机器
* @param array $availability 机器可用时间
* @return array|null 最佳机器信息
*/
private static function find_best_machine($order, $machines, $availability) {
$best_machine = null;
$best_score = PHP_INT_MAX;
foreach ($machines as $machine) {
if ($machine['status'] !== 'available') {
continue;
}
// 计算分数:基于产能和可用时间
$capacity_score = $order['production_time'] / $machine['capacity'];
$availability_time = strtotime($availability[$machine['id']]);
$time_score = $availability_time;
// 综合分数(可根据需求调整权重)
$total_score = $capacity_score * 0.7 + $time_score * 0.3;
if ($total_score < $best_score) {
$best_score = $total_score;
$best_machine = $machine;
}
}
return $best_machine;
}
/**
* 计算结束时间
* @param string $start_time 开始时间
* @param int $production_hours 生产所需小时数
* @return string 结束时间
*/
private static function calculate_end_time($start_time, $production_hours) {
$start_timestamp = strtotime($start_time);
// 考虑工作时间(假设每天工作8小时)
$work_hours_per_day = 8;
$work_days_needed = ceil($production_hours / $work_hours_per_day);
// 计算实际结束时间(跳过周末)
$current_day = 0;
$hours_remaining = $production_hours;
while ($hours_remaining > 0) {
$current_timestamp = $start_timestamp + ($current_day * 86400);
$day_of_week = date('N', $current_timestamp);
// 跳过周末(6=周六,7=周日)
if ($day_of_week < 6) {
$hours_today = min($work_hours_per_day, $hours_remaining);
$hours_remaining -= $hours_today;
}
$current_day++;
}
$end_timestamp = $start_timestamp + ($current_day * 86400);
return date('Y-m-d H:i:s', $end_timestamp);
}
/**
* 生成排产计划
*/
public static function generate_schedule() {
global $wpdb;
// 获取待排产的订单
$orders_table = $wpdb->prefix . 'sps_orders';
$orders = $wpdb->get_results(
"SELECT * FROM $orders_table WHERE status = 'pending' ORDER BY priority, due_date",
ARRAY_A
);
// 获取可用机器
$machines_table = $wpdb->prefix . 'sps_machines';
$machines = $wpdb->get_results(
"SELECT * FROM $machines_table WHERE status = 'available'",
ARRAY_A
);
if (empty($orders) || empty($machines)) {
return false;
}
// 执行智能排产
$schedule = self::intelligent_scheduling($orders, $machines);
// 保存排产结果到数据库
$schedule_table = $wpdb->prefix . 'sps_schedule';
foreach ($schedule as $item) {
$wpdb->insert($schedule_table, array(
'order_id' => $item['order_id'],
'machine_id' => $item['machine_id'],
'start_time' => $item['start_time'],
'end_time' => $item['end_time']
));
// 更新订单状态
$wpdb->update(
$orders_table,
array('status' => 'scheduled'),
array('id' => $item['order_id'])
);
}
return $schedule;
}
}
?>
在includes/class-frontend.php中创建用户提交订单的表单:
<?php
/**
* 前端处理类
*/
class SPS_Frontend {
public static function init() {
add_shortcode('sps_order_form', array(__CLASS__, 'order_form_shortcode'));
add_action('wp_enqueue_scripts', array(__CLASS__, 'enqueue_scripts'));
add_action('wp_ajax_sps_submit_order', array(__CLASS__, 'ajax_submit_order'));
add_action('wp_ajax_nopriv_sps_submit_order', array(__CLASS__, 'ajax_submit_order'));
}
/**
* 订单表单短代码
*/
public static function order_form_shortcode() {
ob_start();
?>
<div class="sps-order-form-container">
<h3>提交定制订单</h3>
<form id="sps-order-form" method="post">
<?php wp_nonce_field('sps_submit_order', 'sps_nonce'); ?>
<div class="form-group">
<label for="customer_name">客户名称 *</label>
<input type="text" id="customer_name" name="customer_name" required>
</div>
<div class="form-group">
<label for="product_type">产品类型 *</label>
<select id="product_type" name="product_type" required>
<option value="">请选择</option>
<option value="metal_part">金属零件</option>
<option value="plastic_part">塑料零件</option>
<option value="electronic_assembly">电子装配</option>
<option value="custom_prototype">定制原型</option>
</select>
</div>
<div class="form-group">
<label for="quantity">数量 *</label>
<input type="number" id="quantity" name="quantity" min="1" max="1000" required>
<small>小批量定制:1-1000件</small>
</div>
<div class="form-group">
<label for="production_time">预计生产时间(小时) *</label>
<input type="number" id="production_time" name="production_time" min="1" max="500" required>
</div>
<div class="form-group">
<label for="priority">优先级 *</label>
<select id="priority" name="priority" required>
<option value="1">最高 (1)</option>
<option value="3">高 (3)</option>
<option value="5" selected>中 (5)</option>
<option value="7">低 (7)</option>
<option value="10">最低 (10)</option>
</select>
</div>
<div class="form-group">
<label for="due_date">期望交货日期 *</label>
<input type="date" id="due_date" name="due_date" required>
</div>
<div class="form-group">
<label for="notes">备注</label>
<textarea id="notes" name="notes" rows="3"></textarea>
</div>
<button type="submit" class="sps-submit-btn">提交订单</button>
<div id="sps-response-message"></div>
</form>
</div>
<style>
.sps-order-form-container {
max-width: 600px;
margin: 20px auto;
padding: 20px;
background: #f9f9f9;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.form-group {
margin-bottom: 15px;
}
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
.form-group input,
.form-group select,
.form-group textarea {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
}
.sps-submit-btn {
background: #0073aa;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
}
.sps-submit-btn:hover {
background: #005a87;
}
#sps-response-message {
margin-top: 15px;
padding: 10px;
border-radius: 4px;
}
.success {
background: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.error {
background: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
</style>
<?php
return ob_get_clean();
}
/**
* 提交订单的AJAX处理
*/
public static function ajax_submit_order() {
// 验证nonce
if (!wp_verify_nonce($_POST['sps_nonce'], 'sps_submit_order')) {
wp_die('安全验证失败');
}
// 验证数据
$required_fields = array('customer_name', 'product_type', 'quantity', 'production_time', 'priority', 'due_date');
foreach ($required_fields as $field) {
if (empty($_POST[$field])) {
wp_send_json_error('请填写所有必填字段');
}
}
global $wpdb;
$table = $wpdb->prefix . 'sps_orders';
// 准备数据
$order_data = array(
'customer_name' => sanitize_text_field($_POST['customer_name']),
'product_type' => sanitize_text_field($_POST['product_type']),
'quantity' => intval($_POST['quantity']),
'production_time' => intval($_POST['production_time']),
'priority' => intval($_POST['priority']),
'due_date' => sanitize_text_field($_POST['due_date']),
'status' => 'pending'
);
// 插入数据库
$result = $wpdb->insert($table, $order_data);
if ($result) {
// 触发排产计划生成(可以设置为定时任务或手动触发)
do_action('sps_generate_schedule');
wp_send_json_success(array(
'message' => '订单提交成功!订单ID:' . $wpdb->insert_id,
'order_id' => $wpdb->insert_id
));
} else {
wp_send_json_error('订单提交失败,请重试');
}
}
/**
* 加载前端脚本和样式
*/
public static function enqueue_scripts() {
wp_enqueue_style('sps-frontend-style', SPS_PLUGIN_URL . 'assets/css/frontend.css');
wp_enqueue_script('sps-frontend-script', SPS_PLUGIN_URL . 'assets/js/frontend.js', array('jquery'), SPS_VERSION, true);
wp_localize_script('sps-frontend-script', 'sps_ajax', array(
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('sps_submit_order')
));
}
}
?>
在includes/class-admin.php中创建管理界面:
<?php
/**
* 后台管理类
*/
class SPS_Admin {
public static function init() {
add_action('admin_menu', array(__CLASS__, 'add_admin_menu'));
add_action('admin_enqueue_scripts', array(__CLASS__, 'enqueue_admin_scripts'));
add_action('admin_post_generate_schedule', array(__CLASS__, 'handle_generate_schedule'));
}
/**
* 添加管理菜单
*/
public static function add_admin_menu() {
add_menu_page(
'智能排产系统',
'智能排产',
'manage_options',
'smart-production-scheduler',
array(__CLASS__, 'display_dashboard'),
'dashicons-schedule',
30
);
add_submenu_page(
'smart-production-scheduler',
'订单管理',
'订单管理',
'manage_options',
'sps-orders',
array(__CLASS__, 'display_orders_page')
);
add_submenu_page(
'smart-production-scheduler',
'排产计划',
'排产计划',
'manage_options',
'sps-schedule',
array(__CLASS__, 'display_schedule_page')
);
add_submenu_page(
'smart-production-scheduler',
'机器管理',
'机器管理',
'manage_options',
'sps-machines',
array(__CLASS__, 'display_machines_page')
);
add_submenu_page(
'smart-production-scheduler',
'排产设置',
'排产设置',
'manage_options',
'sps-settings',
array(__CLASS__, 'display_settings_page')
);
}
/**
* 显示仪表板
*/
public static function display_dashboard() {
global $wpdb;
// 获取统计数据
$orders_table = $wpdb->prefix . 'sps_orders';
$schedule_table = $wpdb->prefix . 'sps_schedule';
$machines_table = $wpdb->prefix . 'sps_machines';
$total_orders = $wpdb->get_var("SELECT COUNT(*) FROM $orders_table");
$pending_orders = $wpdb->get_var("SELECT COUNT(*) FROM $orders_table WHERE status = 'pending'");
$completed_orders = $wpdb->get_var("SELECT COUNT(*) FROM $orders_table WHERE status = 'completed'");
$active_machines = $wpdb->get_var("SELECT COUNT(*) FROM $machines_table WHERE status = 'available'");
?>
<div class="wrap">
<h1>智能排产系统仪表板</h1>
<div class="sps-dashboard-widgets">
<div class="sps-widget">
<h3>总订单数</h3>
<p class="sps-stat"><?php echo $total_orders; ?></p>
</div>
<div class="sps-widget">
<h3>待处理订单</h3>
<p class="sps-stat"><?php echo $pending_orders; ?></p>
</div>
<div class="sps-widget">
<h3>已完成订单</h3>
<p class="sps-stat"><?php echo $completed_orders; ?></p>
</div>
<div class="sps-widget">
<h3>可用机器</h3>
<p class="sps-stat"><?php echo $active_machines; ?></p>
</div>
</div>
<div class="sps-dashboard-actions">
<form method="post" action="<?php echo admin_url('admin-post.php'); ?>">
<input type="hidden" name="action" value="generate_schedule">
<?php wp_nonce_field('generate_schedule_action', 'generate_schedule_nonce'); ?>
<button type="submit" class="button button-primary button-large">
立即生成排产计划
</button>
</form>
</div>
<div class="sps-recent-orders">
<h2>最近订单</h2>
<?php self::display_orders_table(5); ?>
</div>
<div class="sps-upcoming-schedule">
<h2>即将开始的排产</h2>
<?php self::display_upcoming_schedule(); ?>
</div>
</div>
<style>
.sps-dashboard-widgets {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
margin: 20px 0;
}
.sps-widget {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
text-align: center;
}
.sps-stat {
font-size: 2em;
font-weight: bold;
color: #0073aa;
margin: 10px 0;
}
.sps-dashboard-actions {
margin: 30px 0;
padding: 20px;
background: white;
border-radius: 8px;
}
</style>
<?php
}
/**
* 显示订单管理页面
*/
public static function display_orders_page() {
global $wpdb;
$table = $wpdb->prefix . 'sps_orders';
// 处理批量操作
if (isset($_POST['action']) && $_POST['action'] == 'bulk_action') {
self::handle_bulk_actions();
}
// 获取订单数据
$orders = $wpdb->get_results("SELECT * FROM $table ORDER BY created_at DESC", ARRAY_A);
?>
<div class="wrap">
<h1>订单管理</h1>
<form method="post" action="">
<?php wp_nonce_field('bulk_action', 'bulk_action_nonce'); ?>
<div class="tablenav top">
<div class="alignleft actions bulkactions">
<select name="bulk_action">
<option value="">批量操作</option>
<option value="delete">删除</option>
<option value="mark_completed">标记为完成</option>
<option value="mark_pending">标记为待处理</option>
</select>
<button type="submit" class="button action">应用</button>
</div>
</div>
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th class="check-column"><input type="checkbox" id="cb-select-all"></th>
<th>ID</th>
<th>客户名称</th>
<th>产品类型</th>
<th>数量</th>
<th>生产时间</th>
<th>优先级</th>
<th>交货日期</th>
<th>状态</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php foreach ($orders as $order): ?>
<tr>
<th scope="row"><input type="checkbox" name="order_ids[]" value="<?php echo $order['id']; ?>"></th>
<td><?php echo $order['id']; ?></td>
<td><?php echo esc_html($order['customer_name']); ?></td>
<td><?php echo esc_html($order['product_type']); ?></td>
<td><?php echo $order['quantity']; ?></td>
<td><?php echo $order['production_time']; ?> 小时</td>
<td>
<span class="priority-badge priority-<?php echo $order['priority']; ?>">
<?php echo $order['priority']; ?>
</span>
</td>
<td><?php echo $order['due_date']; ?></td>
<td>
<span class="status-badge status-<?php echo $order['status']; ?>">
<?php echo self::get_status_label($order['status']); ?>
</span>
</td>
<td><?php echo $order['created_at']; ?></td>
<td>
<a href="#" class="button button-small view-order" data-id="<?php echo $order['id']; ?>">查看</a>
<a href="#" class="button button-small delete-order" data-id="<?php echo $order['id']; ?>">删除</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</form>
</div>
<style>
.priority-badge {
display: inline-block;
padding: 2px 8px;
border-radius: 12px;
font-size: 12px;
font-weight: bold;
}
.priority-1, .priority-2, .priority-3 {
background: #ff6b6b;
color: white;
}
.priority-4, .priority-5, .priority-6 {
background: #ffd93d;
color: #333;
}
.priority-7, .priority-8, .priority-9, .priority-10 {
background: #6bcf7f;
color: white;
}
.status-badge {
display: inline-block;
padding: 2px 8px;
border-radius: 12px;
font-size: 12px;
font-weight: bold;
}
.status-pending {
background: #ffd93d;
color: #333;
}
.status-scheduled {
background: #4d96ff;
color: white;
}
.status-completed {
background: #6bcf7f;
color: white;
}
</style>
<script>
jQuery(document).ready(function($) {
// 全选/取消全选
$('#cb-select-all').on('change', function() {
$('input[name="order_ids[]"]').prop('checked', this.checked);
});
// 查看订单详情
$('.view-order').on('click', function(e) {
e.preventDefault();
var orderId = $(this).data('id');
// 这里可以添加查看详情的逻辑
alert('查看订单 ' + orderId + ' 的详情');
});
// 删除订单
$('.delete-order').on('click', function(e) {
e.preventDefault();
if (confirm('确定要删除这个订单吗?')) {
var orderId = $(this).data('id');
// 这里可以添加删除订单的AJAX请求
}
});
});
</script>
<?php
}
/**
* 显示排产计划页面
*/
public static function display_schedule_page() {
global $wpdb;
$schedule_table = $wpdb->prefix . 'sps_schedule';
$orders_table = $wpdb->prefix . 'sps_orders';
$machines_table = $wpdb->prefix . 'sps_machines';
// 获取排产数据
$schedule = $wpdb->get_results("
SELECT s.*, o.customer_name, o.product_type, m.machine_name
FROM $schedule_table s
LEFT JOIN $orders_table o ON s.order_id = o.id
LEFT JOIN $machines_table m ON s.machine_id = m.id
ORDER BY s.start_time ASC
", ARRAY_A);
?>
<div class="wrap">
<h1>排产计划</h1>
<div class="sps-gantt-chart">
<h2>甘特图</h2>
<div class="gantt-container">
<?php foreach ($schedule as $item):
$start_date = new DateTime($item['start_time']);
$end_date = new DateTime($item['end_time']);
$duration = $start_date->diff($end_date)->days;
?>
<div class="gantt-item" style="margin-left: <?php echo $duration * 10; ?>px; width: <?php echo max(50, $duration * 20); ?>px;">
<div class="gantt-bar">
<span class="gantt-label">
<?php echo esc_html($item['customer_name']); ?> -
<?php echo esc_html($item['product_type']); ?>
</span>
</div>
<div class="gantt-info">
机器: <?php echo esc_html($item['machine_name']); ?><br>
开始: <?php echo $item['start_time']; ?><br>
结束: <?php echo $item['end_time']; ?>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th>订单ID</th>
<th>客户名称</th>
<th>产品类型</th>
<th>机器</th>
<th>开始时间</th>
<th>结束时间</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php foreach ($schedule as $item): ?>
<tr>
<td><?php echo $item['order_id']; ?></td>
<td><?php echo esc_html($item['customer_name']); ?></td>
<td><?php echo esc_html($item['product_type']); ?></td>
<td><?php echo esc_html($item['machine_name']); ?></td>
<td><?php echo $item['start_time']; ?></td>
<td><?php echo $item['end_time']; ?></td>
<td>
<?php if ($item['completed']): ?>
<span class="status-badge status-completed">已完成</span>
<?php else: ?>
<span class="status-badge status-scheduled">已排产</span>
<?php endif; ?>
</td>
<td>
<button class="button button-small mark-completed" data-id="<?php echo $item['id']; ?>">
<?php echo $item['completed'] ? '取消完成' : '标记完成'; ?>
</button>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<style>
.sps-gantt-chart {
margin: 20px 0;
padding: 20px;
background: white;
border-radius: 8px;
}
.gantt-container {
padding: 20px;
background: #f5f5f5;
border-radius: 4px;
overflow-x: auto;
}
.gantt-item {
margin: 10px 0;
position: relative;
}
.gantt-bar {
background: #4d96ff;
color: white;
padding: 8px 12px;
border-radius: 4px;
cursor: pointer;
transition: background 0.3s;
}
.gantt-bar:hover {
background: #2d76df;
}
.gantt-info {
display: none;
position: absolute;


