首页 / 教程文章 / WordPress柔性供应链需求预测模块的开发与应用教程

WordPress柔性供应链需求预测模块的开发与应用教程

WordPress柔性供应链需求预测模块的开发与应用教程

引言:供应链数字化转型的必要性

在当今快速变化的商业环境中,供应链管理已成为企业竞争力的核心要素。传统供应链系统往往缺乏灵活性,难以应对市场需求波动、原材料供应不稳定等挑战。WordPress作为全球最流行的内容管理系统,不仅适用于网站建设,通过扩展开发也能成为强大的企业管理平台。本文将详细介绍如何在WordPress中开发一个柔性供应链需求预测模块,帮助企业实现数据驱动的智能决策。

模块架构设计

系统整体架构

我们的柔性供应链需求预测模块将采用分层架构设计:

  1. 数据层:负责收集和存储历史销售数据、库存数据、市场趋势数据等
  2. 处理层:包含数据清洗、特征工程和预测算法
  3. 应用层:提供用户界面和API接口
  4. 展示层:可视化预测结果和报表

技术栈选择

  • WordPress作为基础平台
  • PHP 7.4+ 作为后端语言
  • MySQL 8.0+ 作为数据库
  • Python 3.8+ 用于机器学习算法(通过REST API集成)
  • JavaScript/Chart.js 用于数据可视化
  • WooCommerce(可选)用于获取销售数据

数据库设计与实现

创建预测数据表

-- 创建需求预测主表
CREATE TABLE wp_supply_chain_forecast (
    id INT AUTO_INCREMENT PRIMARY KEY,
    product_id INT NOT NULL,
    forecast_date DATE NOT NULL,
    predicted_demand DECIMAL(10, 2) NOT NULL,
    confidence_interval_lower DECIMAL(10, 2),
    confidence_interval_upper DECIMAL(10, 2),
    algorithm_used VARCHAR(50),
    actual_demand DECIMAL(10, 2) DEFAULT NULL,
    forecast_error DECIMAL(10, 2) DEFAULT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_product_date (product_id, forecast_date)
);

-- 创建历史销售数据表
CREATE TABLE wp_sales_history (
    id INT AUTO_INCREMENT PRIMARY KEY,
    product_id INT NOT NULL,
    sale_date DATE NOT NULL,
    quantity_sold INT NOT NULL,
    price DECIMAL(10, 2),
    promotion_flag TINYINT(1) DEFAULT 0,
    seasonality_factor DECIMAL(5, 2) DEFAULT 1.00,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_product_sale_date (product_id, sale_date)
);

-- 创建外部因素表
CREATE TABLE wp_external_factors (
    id INT AUTO_INCREMENT PRIMARY KEY,
    factor_date DATE NOT NULL,
    weather_index DECIMAL(5, 2),
    economic_indicator DECIMAL(8, 2),
    competitor_activity_level DECIMAL(5, 2),
    special_event_flag TINYINT(1) DEFAULT 0,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    UNIQUE KEY unique_date (factor_date)
);

核心预测算法实现

PHP预测引擎类

<?php
/**
 * WordPress柔性供应链需求预测模块
 * 预测引擎核心类
 */

class SupplyChainForecastEngine {
    
    private $db;
    private $table_prefix;
    
    /**
     * 构造函数
     */
    public function __construct() {
        global $wpdb;
        $this->db = $wpdb;
        $this->table_prefix = $wpdb->prefix;
    }
    
    /**
     * 移动平均法预测
     * @param int $product_id 产品ID
     * @param int $periods 预测周期数
     * @param int $window_size 移动窗口大小
     * @return array 预测结果
     */
    public function movingAverageForecast($product_id, $periods = 30, $window_size = 7) {
        // 获取历史销售数据
        $history_table = $this->table_prefix . 'sales_history';
        $query = $this->db->prepare(
            "SELECT sale_date, quantity_sold 
             FROM {$history_table} 
             WHERE product_id = %d 
             ORDER BY sale_date DESC 
             LIMIT %d",
            $product_id,
            $window_size * 3  // 获取足够的历史数据
        );
        
        $historical_data = $this->db->get_results($query, ARRAY_A);
        
        if (empty($historical_data)) {
            return ['error' => '没有足够的历史数据'];
        }
        
        // 提取销售量数据
        $sales = array_column($historical_data, 'quantity_sold');
        
        // 计算移动平均值
        $forecasts = [];
        for ($i = 0; $i < $periods; $i++) {
            // 获取最近window_size个数据点
            $recent_sales = array_slice($sales, $i, $window_size);
            
            // 如果数据不足,使用可用数据
            if (count($recent_sales) < $window_size) {
                $recent_sales = array_slice($sales, 0, $window_size);
            }
            
            // 计算平均值
            $average = array_sum($recent_sales) / count($recent_sales);
            
            // 添加季节性调整(简化示例)
            $seasonal_factor = $this->calculateSeasonalFactor($product_id, $i);
            $adjusted_forecast = $average * $seasonal_factor;
            
            $forecasts[] = [
                'period' => $i + 1,
                'forecast' => round($adjusted_forecast, 2),
                'method' => 'moving_average',
                'window_size' => $window_size
            ];
        }
        
        return $forecasts;
    }
    
    /**
     * 指数平滑法预测
     * @param int $product_id 产品ID
     * @param int $periods 预测周期数
     * @param float $alpha 平滑系数 (0-1)
     * @return array 预测结果
     */
    public function exponentialSmoothingForecast($product_id, $periods = 30, $alpha = 0.3) {
        $history_table = $this->table_prefix . 'sales_history';
        
        // 获取历史数据
        $query = $this->db->prepare(
            "SELECT quantity_sold 
             FROM {$history_table} 
             WHERE product_id = %d 
             ORDER BY sale_date DESC 
             LIMIT 100",
            $product_id
        );
        
        $historical_data = $this->db->get_col($query);
        
        if (count($historical_data) < 2) {
            return ['error' => '需要至少2个历史数据点'];
        }
        
        // 反转数组使数据按时间顺序排列
        $historical_data = array_reverse($historical_data);
        
        // 初始化
        $forecasts = [];
        $last_forecast = $historical_data[0];
        
        // 生成预测
        for ($i = 0; $i < $periods; $i++) {
            if ($i < count($historical_data)) {
                // 使用历史数据更新预测
                $last_forecast = $alpha * $historical_data[$i] + (1 - $alpha) * $last_forecast;
            }
            
            // 添加趋势调整(霍尔特线性趋势法简化版)
            $trend_adjustment = $this->calculateTrendAdjustment($historical_data);
            $adjusted_forecast = $last_forecast + $trend_adjustment * ($i + 1);
            
            $forecasts[] = [
                'period' => $i + 1,
                'forecast' => round(max(0, $adjusted_forecast), 2), // 确保非负
                'method' => 'exponential_smoothing',
                'alpha' => $alpha
            ];
        }
        
        return $forecasts;
    }
    
    /**
     * 计算季节性因子
     * @param int $product_id 产品ID
     * @param int $period_offset 周期偏移
     * @return float 季节性因子
     */
    private function calculateSeasonalFactor($product_id, $period_offset) {
        // 简化版季节性因子计算
        // 实际应用中应根据历史数据计算真实的季节性模式
        
        $month = date('n', strtotime("+{$period_offset} days"));
        
        // 示例季节性模式(可根据实际数据调整)
        $seasonal_patterns = [
            12 => 1.5,  // 12月:节日季,需求增加50%
            1 => 1.2,   // 1月:需求增加20%
            6 => 0.8,   // 6月:需求减少20%
            7 => 0.7,   // 7月:需求减少30%
        ];
        
        return $seasonal_patterns[$month] ?? 1.0;
    }
    
    /**
     * 计算趋势调整
     * @param array $historical_data 历史数据
     * @return float 趋势值
     */
    private function calculateTrendAdjustment($historical_data) {
        if (count($historical_data) < 2) {
            return 0;
        }
        
        // 简单线性趋势计算
        $n = count($historical_data);
        $sum_x = 0;
        $sum_y = 0;
        $sum_xy = 0;
        $sum_x2 = 0;
        
        for ($i = 0; $i < $n; $i++) {
            $sum_x += $i;
            $sum_y += $historical_data[$i];
            $sum_xy += $i * $historical_data[$i];
            $sum_x2 += $i * $i;
        }
        
        // 计算斜率(趋势)
        $slope = ($n * $sum_xy - $sum_x * $sum_y) / ($n * $sum_x2 - $sum_x * $sum_x);
        
        return $slope;
    }
    
    /**
     * 保存预测结果到数据库
     * @param int $product_id 产品ID
     * @param array $forecasts 预测结果数组
     * @return bool 保存是否成功
     */
    public function saveForecasts($product_id, $forecasts) {
        $forecast_table = $this->table_prefix . 'supply_chain_forecast';
        
        foreach ($forecasts as $forecast) {
            $forecast_date = date('Y-m-d', strtotime("+{$forecast['period']} days"));
            
            $data = [
                'product_id' => $product_id,
                'forecast_date' => $forecast_date,
                'predicted_demand' => $forecast['forecast'],
                'algorithm_used' => $forecast['method'],
                'confidence_interval_lower' => $forecast['forecast'] * 0.8, // 80%置信下限
                'confidence_interval_upper' => $forecast['forecast'] * 1.2, // 80%置信上限
            ];
            
            $format = ['%d', '%s', '%f', '%s', '%f', '%f'];
            
            $this->db->insert($forecast_table, $data, $format);
        }
        
        return true;
    }
}
?>

WordPress插件集成

主插件文件

<?php
/**
 * Plugin Name: 柔性供应链需求预测模块
 * Plugin URI: https://yourwebsite.com/
 * Description: WordPress柔性供应链需求预测系统
 * Version: 1.0.0
 * Author: Your Name
 * License: GPL v2 or later
 */

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

// 定义插件常量
define('SC_FORECAST_VERSION', '1.0.0');
define('SC_FORECAST_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('SC_FORECAST_PLUGIN_URL', plugin_dir_url(__FILE__));

// 包含核心类
require_once SC_FORECAST_PLUGIN_DIR . 'includes/class-forecast-engine.php';
require_once SC_FORECAST_PLUGIN_DIR . 'includes/class-forecast-admin.php';
require_once SC_FORECAST_PLUGIN_DIR . 'includes/class-data-collector.php';

/**
 * 插件激活时创建数据库表
 */
register_activation_hook(__FILE__, 'sc_forecast_activate');

function sc_forecast_activate() {
    global $wpdb;
    
    $charset_collate = $wpdb->get_charset_collate();
    
    // 创建数据库表的SQL语句(同上文数据库设计部分)
    // 这里应包含完整的建表语句
    
    require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    dbDelta($sql);
    
    // 设置默认选项
    add_option('sc_forecast_version', SC_FORECAST_VERSION);
}

/**
 * 初始化插件
 */
function sc_forecast_init() {
    // 初始化预测引擎
    $forecast_engine = new SupplyChainForecastEngine();
    
    // 初始化管理界面
    if (is_admin()) {
        $admin_interface = new ForecastAdminInterface();
    }
    
    // 初始化数据收集器
    $data_collector = new DataCollector();
}
add_action('plugins_loaded', 'sc_forecast_init');

/**
 * 添加管理菜单
 */
function sc_forecast_add_admin_menu() {
    add_menu_page(
        '供应链预测',
        '供应链预测',
        'manage_options',
        'supply-chain-forecast',
        'sc_forecast_admin_page',
        'dashicons-chart-line',
        30
    );
    
    add_submenu_page(
        'supply-chain-forecast',
        '预测设置',
        '预测设置',
        'manage_options',
        'sc-forecast-settings',
        'sc_forecast_settings_page'
    );
    
    add_submenu_page(
        'supply-chain-forecast',
        '预测报告',
        '预测报告',
        'manage_options',
        'sc-forecast-reports',
        'sc_forecast_reports_page'
    );
}
add_action('admin_menu', 'sc_forecast_add_admin_menu');

/**
 * 主管理页面
 */
function sc_forecast_admin_page() {
    ?>
    <div class="wrap">
        <h1>柔性供应链需求预测系统</h1>
        
        <div class="sc-forecast-dashboard">
            <div class="sc-row">
                <div class="sc-col-6">
                    <div class="sc-card">
                        <h3>快速预测</h3>
                        <form method="post" action="<?php echo admin_url('admin-post.php'); ?>">
                            <input type="hidden" name="action" value="run_forecast">
                            <?php wp_nonce_field('run_forecast_action', 'run_forecast_nonce'); ?>
                            
                            <p>
                                <label for="product_id">选择产品:</label>
                                <select name="product_id" id="product_id" required>
                                    <option value="">请选择产品</option>
                                    <!-- 这里应动态加载产品选项 -->
                                </select>
                            </p>
                            
                            <p>
                                <label for="forecast_method">预测方法:</label>
                                <select name="forecast_method" id="forecast_method">
                                    <option value="moving_average">移动平均法</option>
                                    <option value="exponential_smoothing">指数平滑法</option>
                                    <option value="ensemble">组合预测</option>
                                </select>
                            </p>
                            
                            <p>
                                <label for="forecast_periods">预测周期(天):</label>
                                <input type="number" name="forecast_periods" id="forecast_periods" 
                                       value="30" min="7" max="365">
                            </p>
                            
                            <p>
                                <input type="submit" class="button button-primary" value="开始预测">
                            </p>
                        </form>
                    </div>
                </div>
                
                <div class="sc-col-6">
                    <div class="sc-card">
                        <h3>预测概览</h3>
                        <div id="forecast-chart-container">
                            <canvas id="forecast-chart"></canvas>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    
    <script>
    // 使用Chart.js显示预测图表
    document.addEventListener('DOMContentLoaded', function() {
        var ctx = document.getElementById('forecast-chart').getContext('2d');
        var forecastChart = new Chart(ctx, {
            type: 'line',
            data: {
                labels: [], // 日期标签
                datasets: [{
                    label: '预测需求',
                    data: [], // 预测数据
                    borderColor: 'rgb(75, 192, 192)',
                    tension: 0.1
                }, {
                    label: '实际需求',
                    data: [], // 实际数据
                    borderColor: 'rgb(255, 99, 132)',
                    tension: 0.1
                }]
            },
            options: {
                responsive: true,
                plugins: {
                    title: {
                        display: true,
                        text: '需求预测趋势图'
                    }
                },
                scales: {
                    y: {
                        beginAtZero: true,
                        title: {
                            display: true,
                            text: '需求量'
                        }
                    }
                }
            }
        });
        
        // 加载初始数据
        loadForecastData();
        
        function loadForecastData() {
            jQuery.ajax({
                url: ajaxurl,
                type: 'POST',
                data: {
                    action: 'get_forecast_data',
                    product_id: 1 // 默认产品ID
                },
                success: function(response) {
                    if (response.success) {
                        forecastChart.data.labels = response.data.dates;
                        forecastChart.data.datasets[0].data = response.data.forecasts;
                        forecastChart.data.datasets[1].data = response.data.actuals;
                        forecastChart.update();
                    }
                }
            });
        }
    });
    </script>
    <?php
}
?>

数据可视化与报表

预测结果可视化

// 高级可视化组件 - 预测仪表板
class ForecastDashboard {
    constructor(containerId) {
        this.container = document.getElementById(containerId);
        this.charts = {};
        this.init();
    }
    init() {
        this.createLayout();
        this.loadData();
        this.setupEventListeners();
    }
    
    createLayout() {
        this.container.innerHTML = `
            <div class="forecast-dashboard">
                <div class="dashboard-header">
                    <h2>供应链需求预测仪表板</h2>
                    <div class="dashboard-controls">
                        <select id="timeRange" class="form-control">
                            <option value="7">最近7天</option>
                            <option value="30" selected>最近30天</option>
                            <option value="90">最近90天</option>
                            <option value="365">最近1年</option>
                        </select>
                        <select id="productFilter" class="form-control">
                            <option value="all">所有产品</option>
                        </select>
                        <button id="refreshBtn" class="btn btn-primary">刷新数据</button>
                        <button id="exportBtn" class="btn btn-secondary">导出报告</button>
                    </div>
                </div>
                
                <div class="dashboard-metrics">
                    <div class="metric-card">
                        <div class="metric-title">平均预测准确率</div>
                        <div class="metric-value" id="accuracyRate">--%</div>
                        <div class="metric-trend" id="accuracyTrend"></div>
                    </div>
                    <div class="metric-card">
                        <div class="metric-title">总预测需求</div>
                        <div class="metric-value" id="totalForecast">--</div>
                        <div class="metric-subtitle">未来30天</div>
                    </div>
                    <div class="metric-card">
                        <div class="metric-title">库存周转率</div>
                        <div class="metric-value" id="turnoverRate">--</div>
                        <div class="metric-trend" id="turnoverTrend"></div>
                    </div>
                    <div class="metric-card">
                        <div class="metric-title">预测置信度</div>
                        <div class="metric-value" id="confidenceLevel">--%</div>
                        <div class="metric-subtitle">平均置信区间</div>
                    </div>
                </div>
                
                <div class="dashboard-charts">
                    <div class="chart-container full-width">
                        <canvas id="forecastTrendChart"></canvas>
                    </div>
                    <div class="chart-container">
                        <canvas id="accuracyChart"></canvas>
                    </div>
                    <div class="chart-container">
                        <canvas id="productMixChart"></canvas>
                    </div>
                </div>
                
                <div class="dashboard-table">
                    <h3>详细预测数据</h3>
                    <table id="forecastTable" class="display">
                        <thead>
                            <tr>
                                <th>产品名称</th>
                                <th>预测日期</th>
                                <th>预测需求</th>
                                <th>实际需求</th>
                                <th>预测误差</th>
                                <th>置信区间</th>
                                <th>算法</th>
                                <th>建议采购量</th>
                            </tr>
                        </thead>
                        <tbody></tbody>
                    </table>
                </div>
            </div>
        `;
    }
    
    async loadData() {
        try {
            const response = await fetch(ajaxurl, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                body: new URLSearchParams({
                    action: 'get_forecast_dashboard_data',
                    time_range: document.getElementById('timeRange').value,
                    product_id: document.getElementById('productFilter').value
                })
            });
            
            const data = await response.json();
            
            if (data.success) {
                this.updateMetrics(data.data.metrics);
                this.renderCharts(data.data.charts);
                this.updateTable(data.data.table);
                this.updateProductFilter(data.data.products);
            }
        } catch (error) {
            console.error('加载数据失败:', error);
        }
    }
    
    updateMetrics(metrics) {
        document.getElementById('accuracyRate').textContent = 
            `${(metrics.accuracy * 100).toFixed(1)}%`;
        document.getElementById('totalForecast').textContent = 
            metrics.total_forecast.toLocaleString();
        document.getElementById('turnoverRate').textContent = 
            metrics.turnover_rate.toFixed(2);
        document.getElementById('confidenceLevel').textContent = 
            `${(metrics.confidence * 100).toFixed(1)}%`;
        
        // 更新趋势指示器
        this.updateTrendIndicator('accuracyTrend', metrics.accuracy_trend);
        this.updateTrendIndicator('turnoverTrend', metrics.turnover_trend);
    }
    
    updateTrendIndicator(elementId, trend) {
        const element = document.getElementById(elementId);
        if (trend > 0) {
            element.innerHTML = `<span class="trend-up">↑ ${trend}%</span>`;
            element.className = 'metric-trend trend-up';
        } else if (trend < 0) {
            element.innerHTML = `<span class="trend-down">↓ ${Math.abs(trend)}%</span>`;
            element.className = 'metric-trend trend-down';
        } else {
            element.innerHTML = `<span class="trend-neutral">→ 持平</span>`;
            element.className = 'metric-trend trend-neutral';
        }
    }
    
    renderCharts(chartData) {
        // 趋势图
        if (!this.charts.trendChart) {
            const ctx = document.getElementById('forecastTrendChart').getContext('2d');
            this.charts.trendChart = new Chart(ctx, {
                type: 'line',
                data: {
                    labels: chartData.trend.labels,
                    datasets: [{
                        label: '预测需求',
                        data: chartData.trend.forecast,
                        borderColor: '#4CAF50',
                        backgroundColor: 'rgba(76, 175, 80, 0.1)',
                        fill: true,
                        tension: 0.4
                    }, {
                        label: '实际需求',
                        data: chartData.trend.actual,
                        borderColor: '#2196F3',
                        borderDash: [5, 5],
                        tension: 0.4
                    }, {
                        label: '置信区间上限',
                        data: chartData.trend.upper,
                        borderColor: 'rgba(76, 175, 80, 0.3)',
                        borderDash: [2, 2],
                        fill: false,
                        tension: 0.4
                    }, {
                        label: '置信区间下限',
                        data: chartData.trend.lower,
                        borderColor: 'rgba(76, 175, 80, 0.3)',
                        borderDash: [2, 2],
                        fill: '-1',
                        tension: 0.4
                    }]
                },
                options: {
                    responsive: true,
                    plugins: {
                        title: {
                            display: true,
                            text: '需求预测趋势与置信区间'
                        },
                        tooltip: {
                            mode: 'index',
                            intersect: false
                        }
                    },
                    scales: {
                        x: {
                            title: {
                                display: true,
                                text: '日期'
                            }
                        },
                        y: {
                            title: {
                                display: true,
                                text: '需求量'
                            },
                            beginAtZero: true
                        }
                    }
                }
            });
        } else {
            this.charts.trendChart.data = {
                labels: chartData.trend.labels,
                datasets: this.charts.trendChart.data.datasets.map((dataset, index) => ({
                    ...dataset,
                    data: index === 0 ? chartData.trend.forecast :
                          index === 1 ? chartData.trend.actual :
                          index === 2 ? chartData.trend.upper : chartData.trend.lower
                }))
            };
            this.charts.trendChart.update();
        }
        
        // 准确率图
        if (!this.charts.accuracyChart) {
            const ctx = document.getElementById('accuracyChart').getContext('2d');
            this.charts.accuracyChart = new Chart(ctx, {
                type: 'bar',
                data: {
                    labels: chartData.accuracy.labels,
                    datasets: [{
                        label: '预测准确率',
                        data: chartData.accuracy.values,
                        backgroundColor: chartData.accuracy.values.map(value => 
                            value >= 90 ? '#4CAF50' : 
                            value >= 80 ? '#FFC107' : '#F44336'
                        ),
                        borderColor: '#333',
                        borderWidth: 1
                    }]
                },
                options: {
                    responsive: true,
                    plugins: {
                        title: {
                            display: true,
                            text: '各算法预测准确率对比'
                        }
                    },
                    scales: {
                        y: {
                            beginAtZero: true,
                            max: 100,
                            title: {
                                display: true,
                                text: '准确率 (%)'
                            }
                        }
                    }
                }
            });
        }
        
        // 产品结构图
        if (!this.charts.productMixChart) {
            const ctx = document.getElementById('productMixChart').getContext('2d');
            this.charts.productMixChart = new Chart(ctx, {
                type: 'doughnut',
                data: {
                    labels: chartData.productMix.labels,
                    datasets: [{
                        data: chartData.productMix.values,
                        backgroundColor: [
                            '#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0',
                            '#9966FF', '#FF9F40', '#8AC926', '#1982C4'
                        ]
                    }]
                },
                options: {
                    responsive: true,
                    plugins: {
                        title: {
                            display: true,
                            text: '预测需求产品结构'
                        },
                        legend: {
                            position: 'right'
                        }
                    }
                }
            });
        }
    }
    
    updateTable(tableData) {
        const tableBody = document.querySelector('#forecastTable tbody');
        tableBody.innerHTML = '';
        
        tableData.forEach(row => {
            const tr = document.createElement('tr');
            
            // 计算预测误差百分比
            const errorPercent = row.actual_demand ? 
                ((row.forecast_error / row.actual_demand) * 100).toFixed(1) : '--';
            
            // 根据误差大小设置颜色
            const errorClass = Math.abs(errorPercent) <= 10 ? 'error-low' :
                              Math.abs(errorPercent) <= 20 ? 'error-medium' : 'error-high';
            
            tr.innerHTML = `
                <td>${row.product_name}</td>
                <td>${row.forecast_date}</td>
                <td>${row.predicted_demand.toLocaleString()}</td>
                <td>${row.actual_demand ? row.actual_demand.toLocaleString() : '--'}</td>
                <td class="${errorClass}">
                    ${row.forecast_error ? `${row.forecast_error.toLocaleString()} (${errorPercent}%)` : '--'}
                </td>
                <td>${row.confidence_lower.toLocaleString()} - ${row.confidence_upper.toLocaleString()}</td>
                <td>${this.getAlgorithmName(row.algorithm_used)}</td>
                <td>
                    <span class="recommended-qty">
                        ${this.calculateRecommendedQuantity(row)}
                    </span>
                </td>
            `;
            
            tableBody.appendChild(tr);
        });
    }
    
    getAlgorithmName(algorithmCode) {
        const algorithms = {
            'moving_average': '移动平均',
            'exponential_smoothing': '指数平滑',
            'arima': 'ARIMA模型',
            'ensemble': '组合预测',
            'neural_network': '神经网络'
        };
        return algorithms[algorithmCode] || algorithmCode;
    }
    
    calculateRecommendedQuantity(row) {
        // 基于预测需求、当前库存和安全库存计算建议采购量
        const safetyStock = row.predicted_demand * 0.2; // 20%的安全库存
        const recommended = Math.max(0, 
            row.predicted_demand + safetyStock - (row.current_stock || 0)
        );
        return Math.ceil(recommended).toLocaleString();
    }
    
    updateProductFilter(products) {
        const filter = document.getElementById('productFilter');
        filter.innerHTML = '<option value="all">所有产品</option>';
        
        products.forEach(product => {
            const option = document.createElement('option');
            option.value = product.id;
            option.textContent = product.name;
            filter.appendChild(option);
        });
    }
    
    setupEventListeners() {
        document.getElementById('refreshBtn').addEventListener('click', () => this.loadData());
        document.getElementById('timeRange').addEventListener('change', () => this.loadData());
        document.getElementById('productFilter').addEventListener('change', () => this.loadData());
        document.getElementById('exportBtn').addEventListener('click', () => this.exportReport());
    }
    
    async exportReport() {
        try {
            const response = await fetch(ajaxurl, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                body: new URLSearchParams({
                    action: 'export_forecast_report',
                    time_range: document.getElementById('timeRange').value,
                    product_id: document.getElementById('productFilter').value,
                    report_type: 'detailed'
                })
            });
            
            if (response.ok) {
                const blob = await response.blob();
                const url = window.URL.createObjectURL(blob);
                const a = document.createElement('a');
                a.href = url;
                a.download = `供应链预测报告_${new Date().toISOString().split('T')[0]}.xlsx`;
                document.body.appendChild(a);
                a.click();
                document.body.removeChild(a);
                window.URL.revokeObjectURL(url);
            }
        } catch (error) {
            console.error('导出报告失败:', error);
            alert('导出报告失败,请重试');
        }
    }
}

// 初始化仪表板
document.addEventListener('DOMContentLoaded', function() {
    const dashboard = new ForecastDashboard('forecastDashboardContainer');
});

高级预测功能:机器学习集成

Python机器学习API服务

# ml_forecast_service.py
"""
WordPress供应链预测的机器学习API服务
使用Flask提供RESTful API接口
"""

import pandas as pd
import numpy as np
from flask import Flask, request, jsonify
from flask_cors import CORS
import joblib
import mysql.connector
from datetime import datetime, timedelta
import warnings
warnings.filterwarnings('ignore')

# 机器学习库
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import TimeSeriesSplit
import xgboost as xgb
from prophet import Prophet

app = Flask(__name__)
CORS(app)

class AdvancedForecastModel:
    """高级预测模型类"""
    
    def __init__(self):
        self.models = {}
        self.scaler = StandardScaler()
        self.db_config = {
            'host': 'localhost',
            'user': 'wordpress_user',
            'password': 'your_password',
            'database': 'wordpress_db'
        }
        
    def connect_db(self):
        """连接MySQL数据库"""
        return mysql.connector.connect(**self.db_config)
    
    def load_training_data(self, product_id, lookback_days=365):
        """加载训练数据"""
        conn = self.connect_db()
        query = """
        SELECT 
            sh.sale_date,
            sh.quantity_sold,
            sh.price,
            sh.promotion_flag,
            sh.seasonality_factor,
            ef.weather_index,
            ef.economic_indicator,
            ef.competitor_activity_level,
            ef.special_event_flag,
            DAYOFWEEK(sh.sale_date) as day_of_week,
            MONTH(sh.sale_date) as month,
            DAY(sh.sale_date) as day,
            CASE 
                WHEN DAYOFWEEK(sh.sale_date) IN (1, 7) THEN 1 
                ELSE 0 
            END as is_weekend,
            LAG(sh.quantity_sold, 1) OVER (ORDER BY sh.sale_date) as lag_1,
            LAG(sh.quantity_sold, 7) OVER (ORDER BY sh.sale_date) as lag_7,
            LAG(sh.quantity_sold, 30) OVER (ORDER BY sh.sale_date) as lag_30,
            AVG(sh.quantity_sold) OVER (
                ORDER BY sh.sale_date 
                ROWS BETWEEN 6 PRECEDING AND CURRENT ROW
            ) as moving_avg_7,
            AVG(sh.quantity_sold) OVER (
                ORDER BY sh.sale_date 
                ROWS BETWEEN 29 PRECEDING AND CURRENT ROW
            ) as moving_avg_30
        FROM wp_sales_history sh
        LEFT JOIN wp_external_factors ef ON sh.sale_date = ef.factor_date
        WHERE sh.product_id = %s
            AND sh.sale_date >= DATE_SUB(CURDATE(), INTERVAL %s DAY)
        ORDER BY sh.sale_date
        """
        
        df = pd.read_sql(query, conn, params=(product_id, lookback_days))
        conn.close()
        
        if df.empty:
            return None
        
        # 处理缺失值
        df.fillna(method='ffill', inplace=True)
        df.fillna(0, inplace=True)
        
        return df
    
    def prepare_features(self, df):
        """准备特征数据"""
        # 分离特征和目标变量
        features = df.drop(['sale_date', 'quantity_sold'], axis=1)
        target = df['quantity_sold']
        
        # 标准化数值特征
        numeric_features = features.select_dtypes(include=[np.number]).columns
        features[numeric_features] = self.scaler.fit_transform(features[numeric_features])
        
        return features, target
    
    def train_prophet_model(self, df, periods=30):
        """使用Facebook Prophet进行时间序列预测"""
        # 准备Prophet数据格式
        prophet_df = df[['sale_date', 'quantity_sold']].copy()
        prophet_df.columns = ['ds', 'y']
        
        # 添加节假日信息
        holidays = pd.DataFrame({
            'holiday': 'promotion',
            'ds': pd.to_datetime(df[df['promotion_flag'] == 1]['sale_date']),
本文来自网络,不代表柔性供应链服务中心立场,转载请注明出处:https://mall.org.cn/5943.html

EXCHANGES®作者

上一篇
下一篇

为您推荐

发表回复

联系我们

联系我们

18559313275

在线咨询: QQ交谈

邮箱: vip@exchanges.center

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