首页 / 教程文章 / 构建WordPress柔性供应链可视化看板教程

构建WordPress柔性供应链可视化看板教程

构建WordPress柔性供应链可视化看板教程

引言:供应链可视化的价值

在当今全球化的商业环境中,供应链管理已成为企业成功的关键因素。柔性供应链可视化看板能够帮助企业实时监控物流状态、库存水平和订单进度,从而快速响应市场变化。本教程将指导您如何在WordPress平台上构建一个功能完善的柔性供应链可视化看板,无需昂贵的专业软件,即可实现供应链数据的直观展示与分析。

准备工作:环境与工具配置

在开始开发之前,请确保您的WordPress环境满足以下要求:

  1. WordPress 5.0或更高版本
  2. PHP 7.4或更高版本
  3. 管理员权限
  4. 安装并激活以下插件:

    • Advanced Custom Fields(用于自定义字段)
    • 图表生成插件(如Data Tables Generator)

第一步:创建供应链数据结构

1.1 自定义文章类型设置

我们将创建三个自定义文章类型来管理供应链数据:供应商、产品和订单。

<?php
/**
 * 注册供应链相关自定义文章类型
 */
function register_supply_chain_post_types() {
    // 注册供应商类型
    $supplier_labels = array(
        'name'               => '供应商',
        'singular_name'      => '供应商',
        'add_new'            => '添加供应商',
        'add_new_item'       => '添加新供应商',
        'edit_item'          => '编辑供应商',
        'new_item'           => '新供应商',
        'view_item'          => '查看供应商',
        'search_items'       => '搜索供应商',
        'not_found'          => '未找到供应商',
        'not_found_in_trash' => '回收站中无供应商'
    );
    
    register_post_type('supplier', array(
        'labels'             => $supplier_labels,
        'public'             => true,
        'has_archive'        => true,
        'menu_icon'          => 'dashicons-truck',
        'supports'           => array('title', 'editor', 'thumbnail'),
        'show_in_rest'       => true, // 启用Gutenberg编辑器支持
    ));
    
    // 注册产品类型
    $product_labels = array(
        'name'               => '供应链产品',
        'singular_name'      => '产品',
        'add_new'            => '添加产品',
        'add_new_item'       => '添加新产品',
        'edit_item'          => '编辑产品',
        'new_item'           => '新产品',
        'view_item'          => '查看产品',
        'search_items'       => '搜索产品',
    );
    
    register_post_type('supply_product', array(
        'labels'             => $product_labels,
        'public'             => true,
        'has_archive'        => true,
        'menu_icon'          => 'dashicons-products',
        'supports'           => array('title', 'editor', 'thumbnail'),
        'show_in_rest'       => true,
    ));
    
    // 注册订单类型
    $order_labels = array(
        'name'               => '供应链订单',
        'singular_name'      => '订单',
        'add_new'            => '添加订单',
        'add_new_item'       => '添加新订单',
        'edit_item'          => '编辑订单',
        'new_item'           => '新订单',
        'view_item'          => '查看订单',
    );
    
    register_post_type('supply_order', array(
        'labels'             => $order_labels,
        'public'             => true,
        'has_archive'        => true,
        'menu_icon'          => 'dashicons-clipboard',
        'supports'           => array('title'),
        'show_in_rest'       => true,
    ));
}
add_action('init', 'register_supply_chain_post_types');
?>

1.2 使用Advanced Custom Fields创建字段组

通过ACF插件创建以下字段组:

  1. 供应商字段组

    • 联系人姓名(文本)
    • 联系电话(文本)
    • 供应能力评级(选择:高/中/低)
    • 地理位置(谷歌地图)
  2. 产品字段组

    • 产品SKU(文本)
    • 当前库存(数字)
    • 安全库存水平(数字)
    • 关联供应商(关系字段)
  3. 订单字段组

    • 订单状态(选择:待处理/生产中/运输中/已完成)
    • 订单数量(数字)
    • 关联产品(关系字段)
    • 预计交付日期(日期选择器)
    • 实际交付日期(日期选择器)

第二步:构建可视化看板前端

2.1 创建看板页面模板

<?php
/**
 * 供应链可视化看板模板
 * Template Name: 供应链可视化看板
 */
get_header(); ?>

<div class="supply-chain-dashboard">
    <div class="dashboard-header">
        <h1>柔性供应链可视化看板</h1>
        <div class="last-updated">最后更新: <span id="update-time"><?php echo current_time('Y-m-d H:i:s'); ?></span></div>
        <button class="refresh-btn" onclick="refreshDashboard()">刷新数据</button>
    </div>
    
    <div class="dashboard-grid">
        <!-- 关键指标卡片 -->
        <div class="dashboard-card metrics-card">
            <h3>关键绩效指标</h3>
            <div class="metrics-grid">
                <div class="metric-item">
                    <div class="metric-value" id="total-orders">0</div>
                    <div class="metric-label">总订单数</div>
                </div>
                <div class="metric-item">
                    <div class="metric-value" id="pending-orders">0</div>
                    <div class="metric-label">待处理订单</div>
                </div>
                <div class="metric-item">
                    <div class="metric-value" id="on-time-delivery">0%</div>
                    <div class="metric-label">准时交付率</div>
                </div>
                <div class="metric-item">
                    <div class="metric-value" id="inventory-alerts">0</div>
                    <div class="metric-label">库存预警</div>
                </div>
            </div>
        </div>
        
        <!-- 订单状态图表 -->
        <div class="dashboard-card chart-card">
            <h3>订单状态分布</h3>
            <canvas id="order-status-chart" width="400" height="300"></canvas>
        </div>
        
        <!-- 库存水平图表 -->
        <div class="dashboard-card chart-card">
            <h3>库存水平监控</h3>
            <canvas id="inventory-chart" width="400" height="300"></canvas>
        </div>
        
        <!-- 供应商绩效表格 -->
        <div class="dashboard-card table-card">
            <h3>供应商绩效排名</h3>
            <table id="supplier-performance-table">
                <thead>
                    <tr>
                        <th>供应商</th>
                        <th>订单完成率</th>
                        <th>准时率</th>
                        <th>质量评分</th>
                        <th>状态</th>
                    </tr>
                </thead>
                <tbody id="supplier-table-body">
                    <!-- 数据将通过AJAX加载 -->
                </tbody>
            </table>
        </div>
        
        <!-- 实时订单列表 -->
        <div class="dashboard-card orders-card">
            <h3>近期订单状态</h3>
            <div class="orders-list" id="recent-orders">
                <!-- 订单数据将通过AJAX加载 -->
            </div>
        </div>
    </div>
</div>

<?php get_footer(); ?>

2.2 添加看板样式

/* 供应链看板样式 */
.supply-chain-dashboard {
    padding: 20px;
    background-color: #f5f7fa;
    min-height: 100vh;
}

.dashboard-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 30px;
    padding-bottom: 20px;
    border-bottom: 2px solid #e0e6ed;
}

.dashboard-header h1 {
    color: #2c3e50;
    margin: 0;
}

.last-updated {
    color: #7f8c8d;
    font-size: 14px;
}

.refresh-btn {
    background-color: #3498db;
    color: white;
    border: none;
    padding: 10px 20px;
    border-radius: 4px;
    cursor: pointer;
    font-weight: bold;
}

.refresh-btn:hover {
    background-color: #2980b9;
}

.dashboard-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
    gap: 20px;
}

.dashboard-card {
    background: white;
    border-radius: 8px;
    padding: 20px;
    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}

.dashboard-card h3 {
    margin-top: 0;
    color: #34495e;
    border-bottom: 1px solid #ecf0f1;
    padding-bottom: 10px;
}

.metrics-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 15px;
}

.metric-item {
    text-align: center;
    padding: 15px;
    background-color: #f8f9fa;
    border-radius: 6px;
}

.metric-value {
    font-size: 28px;
    font-weight: bold;
    color: #2c3e50;
}

.metric-label {
    font-size: 14px;
    color: #7f8c8d;
    margin-top: 5px;
}

.orders-list {
    max-height: 300px;
    overflow-y: auto;
}

.order-item {
    padding: 10px;
    border-bottom: 1px solid #ecf0f1;
    display: flex;
    justify-content: space-between;
}

.order-item:last-child {
    border-bottom: none;
}

.order-status {
    padding: 3px 8px;
    border-radius: 12px;
    font-size: 12px;
    font-weight: bold;
}

.status-pending { background-color: #f39c12; color: white; }
.status-production { background-color: #3498db; color: white; }
.status-shipping { background-color: #9b59b6; color: white; }
.status-completed { background-color: #2ecc71; color: white; }

#supplier-performance-table {
    width: 100%;
    border-collapse: collapse;
}

#supplier-performance-table th,
#supplier-performance-table td {
    padding: 12px;
    text-align: left;
    border-bottom: 1px solid #ddd;
}

#supplier-performance-table th {
    background-color: #f2f6fc;
    font-weight: bold;
}

第三步:实现数据交互功能

3.1 创建数据API端点

<?php
/**
 * 注册供应链数据API端点
 */
function register_supply_chain_api() {
    register_rest_route('supply-chain/v1', '/dashboard-data', array(
        'methods' => 'GET',
        'callback' => 'get_dashboard_data',
        'permission_callback' => function() {
            return current_user_can('edit_posts'); // 仅限有编辑权限的用户
        }
    ));
    
    register_rest_route('supply-chain/v1', '/refresh-data', array(
        'methods' => 'POST',
        'callback' => 'refresh_dashboard_data',
        'permission_callback' => function() {
            return current_user_can('edit_posts');
        }
    ));
}
add_action('rest_api_init', 'register_supply_chain_api');

/**
 * 获取看板数据
 */
function get_dashboard_data() {
    $data = array();
    
    // 获取订单统计数据
    $order_stats = get_order_statistics();
    $data['order_stats'] = $order_stats;
    
    // 获取库存数据
    $inventory_data = get_inventory_data();
    $data['inventory'] = $inventory_data;
    
    // 获取供应商绩效数据
    $supplier_performance = get_supplier_performance();
    $data['suppliers'] = $supplier_performance;
    
    // 获取最近订单
    $recent_orders = get_recent_orders(10);
    $data['recent_orders'] = $recent_orders;
    
    // 计算关键指标
    $data['metrics'] = calculate_key_metrics($order_stats, $inventory_data);
    
    return rest_ensure_response($data);
}

/**
 * 获取订单统计数据
 */
function get_order_statistics() {
    $statuses = array('pending', 'production', 'shipping', 'completed');
    $stats = array();
    
    foreach ($statuses as $status) {
        $args = array(
            'post_type' => 'supply_order',
            'posts_per_page' => -1,
            'meta_query' => array(
                array(
                    'key' => 'order_status',
                    'value' => $status,
                    'compare' => '='
                )
            )
        );
        
        $query = new WP_Query($args);
        $stats[$status] = $query->found_posts;
    }
    
    return $stats;
}

/**
 * 获取库存数据
 */
function get_inventory_data() {
    $inventory = array();
    
    $args = array(
        'post_type' => 'supply_product',
        'posts_per_page' => -1,
    );
    
    $query = new WP_Query($args);
    
    while ($query->have_posts()) {
        $query->the_post();
        $product_id = get_the_ID();
        
        $current_stock = get_field('current_stock', $product_id);
        $safety_stock = get_field('safety_stock_level', $product_id);
        
        $inventory[] = array(
            'product_name' => get_the_title(),
            'current_stock' => $current_stock ?: 0,
            'safety_stock' => $safety_stock ?: 10,
            'status' => $current_stock <= $safety_stock ? 'low' : 'normal'
        );
    }
    
    wp_reset_postdata();
    
    return $inventory;
}
?>

3.2 实现前端JavaScript数据交互

/**
 * 供应链看板数据交互脚本
 */
document.addEventListener('DOMContentLoaded', function() {
    // 初始化看板
    loadDashboardData();
    
    // 设置自动刷新(每5分钟)
    setInterval(loadDashboardData, 300000);
});

/**
 * 加载看板数据
 */
function loadDashboardData() {
    // 显示加载状态
    document.getElementById('update-time').textContent = '加载中...';
    
    // 获取API数据
    fetch('/wp-json/supply-chain/v1/dashboard-data')
        .then(response => response.json())
        .then(data => {
            updateDashboard(data);
            updateCharts(data);
            updateTables(data);
            
            // 更新最后刷新时间
            const now = new Date();
            document.getElementById('update-time').textContent = 
                now.toLocaleDateString() + ' ' + now.toLocaleTimeString();
        })
        .catch(error => {
            console.error('加载数据失败:', error);
            document.getElementById('update-time').textContent = '加载失败';
        });
}

/**
 * 更新关键指标
 */
function updateDashboard(data) {
    const metrics = data.metrics;
    
    document.getElementById('total-orders').textContent = metrics.total_orders;
    document.getElementById('pending-orders').textContent = metrics.pending_orders;
    document.getElementById('on-time-delivery').textContent = metrics.on_time_delivery + '%';
    document.getElementById('inventory-alerts').textContent = metrics.inventory_alerts;
}

/**
 * 更新图表
 */
function updateCharts(data) {
    // 订单状态图表
    const orderCtx = document.getElementById('order-status-chart').getContext('2d');
    const orderChart = new Chart(orderCtx, {
        type: 'doughnut',
        data: {
            labels: ['待处理', '生产中', '运输中', '已完成'],
            datasets: [{
                data: [
                    data.order_stats.pending,
                    data.order_stats.production,
                    data.order_stats.shipping,
                    data.order_stats.completed
                ],
                backgroundColor: [
                    '#f39c12',
                    '#3498db',
                    '#9b59b6',
                    '#2ecc71'
                ]
            }]
        },
        options: {
            responsive: true,
            maintainAspectRatio: false
        }
    });
    
    // 库存水平图表
    const inventoryCtx = document.getElementById('inventory-chart').getContext('2d');
    const productNames = data.inventory.map(item => item.product_name);
    const currentStock = data.inventory.map(item => item.current_stock);
    const safetyStock = data.inventory.map(item => item.safety_stock);
    
    const inventoryChart = new Chart(inventoryCtx, {
        type: 'bar',
        data: {
            labels: productNames,
            datasets: [
                {
                    label: '当前库存',
                    data: currentStock,
                    backgroundColor: '#3498db'
                },
                {
                    label: '安全库存',
                    data: safetyStock,
                    backgroundColor: '#e74c3c',
                    type: 'line',
                    fill: false
                }
            ]
        },
        options: {
            responsive: true,
            maintainAspectRatio: false,
            scales: {
                y: {
                    beginAtZero: true
                }
            }
        }
    });
}

/**
 * 更新供应商表格
 */
function updateTables(data) {
    // 更新供应商绩效表格
    const supplierTableBody = document.getElementById('supplier-table-body');
    supplierTableBody.innerHTML = '';
    
    data.suppliers.forEach(supplier => {
        const row = document.createElement('tr');
        
        row.innerHTML = `
            <td>${supplier.name}</td>
            <td>${supplier.completion_rate}%</td>
            <td>${supplier.quality_score}/10</td>
            <td><span class="status-badge ${supplier.status}">${supplier.status_text}</span></td>
        `;
        
        supplierTableBody.appendChild(row);
    });
    
    // 更新近期订单列表
    const recentOrdersContainer = document.getElementById('recent-orders');
    recentOrdersContainer.innerHTML = '';
    
    data.recent_orders.forEach(order => {
        const orderItem = document.createElement('div');
        orderItem.className = 'order-item';
        
        orderItem.innerHTML = `
            <div class="order-info">
                <strong>${order.product_name}</strong>
                <div class="order-meta">订单号: ${order.order_number}</div>
            </div>
            <div class="order-status-info">
                <span class="order-status status-${order.status}">${order.status_text}</span>
                <div class="order-date">${order.delivery_date}</div>
            </div>
        `;
        
        recentOrdersContainer.appendChild(orderItem);
    });
}

/**
 * 手动刷新看板
 */
function refreshDashboard() {
    const refreshBtn = document.querySelector('.refresh-btn');
    const originalText = refreshBtn.textContent;
    
    refreshBtn.textContent = '刷新中...';
    refreshBtn.disabled = true;
    
    loadDashboardData();
    
    setTimeout(() => {
        refreshBtn.textContent = originalText;
        refreshBtn.disabled = false;
    }, 1000);
}

第四步:添加高级功能与优化

4.1 实现实时通知系统

<?php
/**
 * 供应链预警系统
 */
class SupplyChainAlertSystem {
    
    /**
     * 检查库存预警
     */
    public static function check_inventory_alerts() {
        $alerts = array();
        
        $products = get_posts(array(
            'post_type' => 'supply_product',
            'posts_per_page' => -1,
        ));
        
        foreach ($products as $product) {
            $current_stock = get_field('current_stock', $product->ID);
            $safety_stock = get_field('safety_stock_level', $product->ID);
            $product_name = get_the_title($product->ID);
            
            if ($current_stock <= $safety_stock) {
                $alerts[] = array(
                    'type' => 'inventory',
                    'level' => $current_stock == 0 ? 'critical' : 'warning',
                    'message' => sprintf(
                        '产品 "%s" 库存不足!当前库存:%d,安全库存:%d',
                        $product_name,
                        $current_stock,
                        $safety_stock
                    ),
                    'product_id' => $product->ID,
                    'timestamp' => current_time('mysql')
                );
            }
        }
        
        return $alerts;
    }
    
    /**
     * 检查订单延迟
     */
    public static function check_order_delays() {
        $alerts = array();
        $today = current_time('Y-m-d');
        
        $orders = get_posts(array(
            'post_type' => 'supply_order',
            'posts_per_page' => -1,
            'meta_query' => array(
                'relation' => 'AND',
                array(
                    'key' => 'order_status',
                    'value' => 'completed',
                    'compare' => '!='
                ),
                array(
                    'key' => 'estimated_delivery_date',
                    'value' => $today,
                    'compare' => '<',
                    'type' => 'DATE'
                )
            )
        ));
        
        foreach ($orders as $order) {
            $estimated_date = get_field('estimated_delivery_date', $order->ID);
            $product_id = get_field('related_product', $order->ID);
            $product_name = get_the_title($product_id);
            
            $alerts[] = array(
                'type' => 'order_delay',
                'level' => 'warning',
                'message' => sprintf(
                    '订单 #%s (%s) 预计交付日期已过:%s',
                    $order->ID,
                    $product_name,
                    $estimated_date
                ),
                'order_id' => $order->ID,
                'timestamp' => current_time('mysql')
            );
        }
        
        return $alerts;
    }
    
    /**
     * 获取所有预警
     */
    public static function get_all_alerts() {
        $inventory_alerts = self::check_inventory_alerts();
        $order_alerts = self::check_order_delays();
        
        return array_merge($inventory_alerts, $order_alerts);
    }
}

/**
 * 注册预警API端点
 */
function register_alert_api() {
    register_rest_route('supply-chain/v1', '/alerts', array(
        'methods' => 'GET',
        'callback' => 'get_supply_chain_alerts',
        'permission_callback' => function() {
            return current_user_can('edit_posts');
        }
    ));
}
add_action('rest_api_init', 'register_alert_api');

function get_supply_chain_alerts() {
    $alerts = SupplyChainAlertSystem::get_all_alerts();
    return rest_ensure_response($alerts);
}
?>

4.2 添加预警通知前端组件

/**
 * 预警通知系统
 */
class AlertSystem {
    constructor() {
        this.alertContainer = null;
        this.init();
    }
    
    init() {
        this.createAlertContainer();
        this.loadAlerts();
        setInterval(() => this.loadAlerts(), 60000); // 每分钟检查一次
    }
    
    createAlertContainer() {
        const container = document.createElement('div');
        container.id = 'supply-chain-alerts';
        container.className = 'alert-container';
        
        container.innerHTML = `
            <div class="alert-header">
                <h4>供应链预警</h4>
                <button class="alert-toggle">隐藏</button>
            </div>
            <div class="alert-list" id="alert-list"></div>
        `;
        
        document.querySelector('.supply-chain-dashboard').prepend(container);
        this.alertContainer = container;
        
        // 添加切换显示/隐藏功能
        container.querySelector('.alert-toggle').addEventListener('click', () => {
            const list = container.querySelector('.alert-list');
            const toggleBtn = container.querySelector('.alert-toggle');
            
            if (list.style.display === 'none') {
                list.style.display = 'block';
                toggleBtn.textContent = '隐藏';
            } else {
                list.style.display = 'none';
                toggleBtn.textContent = '显示';
            }
        });
    }
    
    async loadAlerts() {
        try {
            const response = await fetch('/wp-json/supply-chain/v1/alerts');
            const alerts = await response.json();
            this.displayAlerts(alerts);
        } catch (error) {
            console.error('加载预警失败:', error);
        }
    }
    
    displayAlerts(alerts) {
        const alertList = document.getElementById('alert-list');
        
        if (alerts.length === 0) {
            alertList.innerHTML = '<div class="alert-item no-alerts">暂无预警信息</div>';
            return;
        }
        
        let alertHTML = '';
        
        alerts.forEach(alert => {
            const alertClass = `alert-item alert-${alert.level}`;
            const time = new Date(alert.timestamp).toLocaleTimeString();
            
            alertHTML += `
                <div class="${alertClass}">
                    <div class="alert-icon">
                        ${alert.level === 'critical' ? '⚠️' : 'ℹ️'}
                    </div>
                    <div class="alert-content">
                        <div class="alert-message">${alert.message}</div>
                        <div class="alert-time">${time}</div>
                    </div>
                </div>
            `;
        });
        
        alertList.innerHTML = alertHTML;
    }
}

// 初始化预警系统
document.addEventListener('DOMContentLoaded', () => {
    new AlertSystem();
});

4.3 添加预警系统样式

/* 预警系统样式 */
.alert-container {
    background: white;
    border-radius: 8px;
    margin-bottom: 20px;
    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
    overflow: hidden;
}

.alert-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 15px 20px;
    background-color: #f8f9fa;
    border-bottom: 1px solid #e9ecef;
}

.alert-header h4 {
    margin: 0;
    color: #2c3e50;
}

.alert-toggle {
    background: none;
    border: 1px solid #dee2e6;
    padding: 5px 15px;
    border-radius: 4px;
    cursor: pointer;
    font-size: 12px;
}

.alert-toggle:hover {
    background-color: #e9ecef;
}

.alert-list {
    max-height: 300px;
    overflow-y: auto;
}

.alert-item {
    display: flex;
    padding: 12px 20px;
    border-bottom: 1px solid #f1f3f4;
    align-items: flex-start;
}

.alert-item:last-child {
    border-bottom: none;
}

.alert-item.no-alerts {
    justify-content: center;
    color: #6c757d;
    font-style: italic;
}

.alert-item.alert-critical {
    background-color: #fff5f5;
    border-left: 4px solid #e53e3e;
}

.alert-item.alert-warning {
    background-color: #fffaf0;
    border-left: 4px solid #dd6b20;
}

.alert-icon {
    font-size: 18px;
    margin-right: 12px;
    margin-top: 2px;
}

.alert-content {
    flex: 1;
}

.alert-message {
    font-weight: 500;
    margin-bottom: 4px;
}

.alert-time {
    font-size: 12px;
    color: #6c757d;
}

.status-badge {
    padding: 4px 8px;
    border-radius: 12px;
    font-size: 12px;
    font-weight: bold;
}

.status-badge.active {
    background-color: #2ecc71;
    color: white;
}

.status-badge.inactive {
    background-color: #95a5a6;
    color: white;
}

.status-badge.warning {
    background-color: #f39c12;
    color: white;
}

第五步:数据导出与报告功能

5.1 实现数据导出功能

<?php
/**
 * 数据导出功能
 */
class SupplyChainExporter {
    
    /**
     * 导出订单数据为CSV
     */
    public static function export_orders_csv($start_date = null, $end_date = null) {
        $args = array(
            'post_type' => 'supply_order',
            'posts_per_page' => -1,
            'orderby' => 'date',
            'order' => 'DESC'
        );
        
        // 添加日期筛选
        if ($start_date && $end_date) {
            $args['date_query'] = array(
                array(
                    'after' => $start_date,
                    'before' => $end_date,
                    'inclusive' => true
                )
            );
        }
        
        $orders = get_posts($args);
        
        // 设置CSV头部
        $headers = array(
            '订单ID',
            '产品名称',
            '订单数量',
            '订单状态',
            '预计交付日期',
            '实际交付日期',
            '创建时间'
        );
        
        $output = fopen('php://output', 'w');
        fputcsv($output, $headers);
        
        foreach ($orders as $order) {
            $product_id = get_field('related_product', $order->ID);
            $product_name = $product_id ? get_the_title($product_id) : 'N/A';
            
            $row = array(
                $order->ID,
                $product_name,
                get_field('order_quantity', $order->ID) ?: 0,
                self::get_status_text(get_field('order_status', $order->ID)),
                get_field('estimated_delivery_date', $order->ID) ?: '',
                get_field('actual_delivery_date', $order->ID) ?: '',
                get_the_date('Y-m-d H:i:s', $order->ID)
            );
            
            fputcsv($output, $row);
        }
        
        fclose($output);
    }
    
    /**
     * 导出库存报告
     */
    public static function export_inventory_report() {
        $products = get_posts(array(
            'post_type' => 'supply_product',
            'posts_per_page' => -1,
            'orderby' => 'title',
            'order' => 'ASC'
        ));
        
        $headers = array(
            '产品ID',
            '产品名称',
            'SKU',
            '当前库存',
            '安全库存',
            '库存状态',
            '关联供应商'
        );
        
        $output = fopen('php://output', 'w');
        fputcsv($output, $headers);
        
        foreach ($products as $product) {
            $current_stock = get_field('current_stock', $product->ID) ?: 0;
            $safety_stock = get_field('safety_stock_level', $product->ID) ?: 0;
            $sku = get_field('product_sku', $product->ID) ?: '';
            
            $supplier_id = get_field('related_supplier', $product->ID);
            $supplier_name = $supplier_id ? get_the_title($supplier_id) : 'N/A';
            
            $status = $current_stock <= $safety_stock ? '库存不足' : '正常';
            
            $row = array(
                $product->ID,
                get_the_title($product->ID),
                $sku,
                $current_stock,
                $safety_stock,
                $status,
                $supplier_name
            );
            
            fputcsv($output, $row);
        }
        
        fclose($output);
    }
    
    /**
     * 获取状态文本
     */
    private static function get_status_text($status) {
        $status_map = array(
            'pending' => '待处理',
            'production' => '生产中',
            'shipping' => '运输中',
            'completed' => '已完成'
        );
        
        return $status_map[$status] ?? $status;
    }
}

/**
 * 注册导出API端点
 */
function register_export_api() {
    register_rest_route('supply-chain/v1', '/export/orders', array(
        'methods' => 'GET',
        'callback' => 'handle_orders_export',
        'permission_callback' => function() {
            return current_user_can('export');
        }
    ));
    
    register_rest_route('supply-chain/v1', '/export/inventory', array(
        'methods' => 'GET',
        'callback' => 'handle_inventory_export',
        'permission_callback' => function() {
            return current_user_can('export');
        }
    ));
}
add_action('rest_api_init', 'register_export_api');

function handle_orders_export($request) {
    $start_date = $request->get_param('start_date');
    $end_date = $request->get_param('end_date');
    
    // 设置CSV头
    header('Content-Type: text/csv; charset=utf-8');
    header('Content-Disposition: attachment; filename=orders_export_' . date('Y-m-d') . '.csv');
    
    SupplyChainExporter::export_orders_csv($start_date, $end_date);
    exit;
}

function handle_inventory_export($request) {
    header('Content-Type: text/csv; charset=utf-8');
    header('Content-Disposition: attachment; filename=inventory_report_' . date('Y-m-d') . '.csv');
    
    SupplyChainExporter::export_inventory_report();
    exit;
}
?>

5.2 添加导出功能前端界面

/**
 * 数据导出功能
 */
class DataExporter {
    constructor() {
        this.initExportButtons();
    }
    
    initExportButtons() {
        // 创建导出按钮容器
        const exportContainer = document.createElement('div');
        exportContainer.className = 'export-container';
        exportContainer.innerHTML = `
            <h4>数据导出</h4>
            <div class="export-buttons">
                <button class="export-btn" data-type="orders">导出订单数据</button>
                <button class="export-btn" data-type="inventory">导出库存报告</button>
            </div>
            <div class="date-range" id="date-range-container" style="display: none;">
                <h5>选择日期范围</h5>
                <div class="date-inputs">
                    <div>
                        <label>开始日期:</label>
                        <input type="date" id="start-date">
                    </div>
                    <div>
                        <label>结束日期:</label>
                        <input type="date" id="end-date">
                    </div>
                </div>
                <button class="confirm-export">确认导出</button>
            </div>
        `;
        
        document.querySelector('.dashboard-header').appendChild(exportContainer);
        
        // 绑定按钮事件
        document.querySelectorAll('.export-btn').forEach(button => {
            button.addEventListener('click', (e) => {
                const exportType = e.target.dataset.type;
                this.handleExport(exportType);
            });
        });
        
        document.querySelector('.confirm-export').addEventListener('click', () => {
            this.performExport();
        });
    }
    
    handleExport(type) {
        this.currentExportType = type;
        
        if (type === 'orders') {
            // 显示日期选择器
            document.getElementById('date-range-container').style.display = 'block';
        } else {
            // 直接导出库存报告
            this.performExport();
        }
    }
    
    performExport() {
        let url = '';
        
        if (this.currentExportType === 'orders') {
            const startDate = document.getElementById('start-date').value;
            const endDate = document.getElementById('end-date').value;
            
            if (!startDate || !endDate) {
本文来自网络,不代表柔性供应链服务中心立场,转载请注明出处:https://mall.org.cn/5799.html

EXCHANGES®作者

上一篇
下一篇

为您推荐

发表回复

联系我们

联系我们

18559313275

在线咨询: QQ交谈

邮箱: vip@exchanges.center

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