文章目录
-
- 在当今快速发展的电商环境中,柔性供应链系统需要具备高度可扩展性和弹性。WordPress作为广泛使用的内容管理系统,结合定制化的供应链插件,可以构建强大的电商解决方案。然而,传统的部署方式在面对流量波动、快速迭代和跨环境一致性时面临挑战。 容器化技术通过将应用程序及其依赖项打包到标准化单元中,实现了环境一致性、快速部署和弹性扩展。本教程将详细介绍如何将WordPress柔性供应链软件进行容器化部署。
-
- 首先,我们需要在服务器上安装Docker和Docker Compose。以下是在Ubuntu系统上的安装步骤: #!/bin/bash # 更新系统包列表 sudo apt-get update # 安装必要的依赖包 sudo apt-get install -y apt-transport-https ca-certificates curl gnupg lsb-release # 添加Docker官方GPG密钥 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg # 设置稳定版仓库 echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null # 安装Docker引擎 sudo apt-get update sudo apt-get install -y docker-ce docker-ce-cli containerd.io # 安装Docker Compose sudo curl -L "https://github.com/docker/compose/releases/download/v2.15.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose # 验证安装 docker --version docker-compose --version
- 创建以下项目目录结构: wordpress-supply-chain/ ├── docker-compose.yml ├── nginx/ │ ├── Dockerfile │ └── nginx.conf ├── wordpress/ │ └── Dockerfile ├── mysql/ │ └── init.sql ├── php/ │ └── custom.ini └── plugins/ └── supply-chain-manager/ └── (供应链插件文件)
-
- 创建MySQL初始化脚本,用于设置供应链数据库: -- mysql/init.sql -- 创建供应链专用数据库 CREATE DATABASE IF NOT EXISTS supply_chain_db; USE supply_chain_db; -- 创建供应商表 CREATE TABLE IF NOT EXISTS suppliers ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL, contact_email VARCHAR(255), phone VARCHAR(50), address TEXT, reliability_score DECIMAL(3,2) DEFAULT 0.00, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 创建库存表 CREATE TABLE IF NOT EXISTS inventory ( id INT AUTO_INCREMENT PRIMARY KEY, product_id INT NOT NULL, supplier_id INT, quantity INT DEFAULT 0, reorder_level INT DEFAULT 10, last_restocked DATE, location VARCHAR(100), FOREIGN KEY (supplier_id) REFERENCES suppliers(id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 创建订单跟踪表 CREATE TABLE IF NOT EXISTS order_tracking ( id INT AUTO_INCREMENT PRIMARY KEY, order_id VARCHAR(50) NOT NULL, status ENUM('pending', 'processing', 'shipped', 'delivered', 'cancelled') DEFAULT 'pending', supplier_id INT, estimated_delivery DATE, actual_delivery DATE, tracking_number VARCHAR(100), notes TEXT, FOREIGN KEY (supplier_id) REFERENCES suppliers(id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 插入示例数据 INSERT INTO suppliers (name, contact_email, reliability_score) VALUES ('优质供应商A', 'supplierA@example.com', 4.8), ('快速配送B', 'supplierB@example.com', 4.5), ('经济优选C', 'supplierC@example.com', 4.2);
- 创建WordPress容器的Dockerfile,集成供应链插件: # wordpress/Dockerfile # 使用官方WordPress镜像作为基础 FROM wordpress:6.2-php8.1-apache # 设置维护者信息 LABEL maintainer="supply-chain-dev@example.com" # 安装必要的PHP扩展 RUN apt-get update && apt-get install -y libzip-dev libpng-dev libjpeg-dev libfreetype6-dev && docker-php-ext-configure gd --with-freetype --with-jpeg && docker-php-ext-install -j$(nproc) gd zip pdo_mysql # 复制自定义PHP配置 COPY ../php/custom.ini /usr/local/etc/php/conf.d/custom.ini # 复制供应链插件到WordPress插件目录 COPY ../plugins/supply-chain-manager /var/www/html/wp-content/plugins/supply-chain-manager # 设置插件目录权限 RUN chown -R www-data:www-data /var/www/html/wp-content/plugins/supply-chain-manager && chmod -R 755 /var/www/html/wp-content/plugins/supply-chain-manager # 创建供应链数据目录 RUN mkdir -p /var/www/html/wp-content/uploads/supply-chain && chown -R www-data:www-data /var/www/html/wp-content/uploads/supply-chain # 暴露Apache端口 EXPOSE 80 # 健康检查 HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 CMD curl -f http://localhost/ || exit 1
- 创建Nginx配置文件,优化WordPress性能: # nginx/nginx.conf events { worker_connections 1024; } http { # 基础配置 sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; # MIME类型 include /etc/nginx/mime.types; default_type application/octet-stream; # 日志配置 access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; # Gzip压缩 gzip on; gzip_vary on; gzip_min_length 1024; gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/atom+xml image/svg+xml; # WordPress上游服务器 upstream wordpress { server wordpress:80; } # 主服务器配置 server { listen 80; server_name supplychain.example.com; # 根目录 root /var/www/html; index index.php index.html index.htm; # WordPress重写规则 location / { try_files $uri $uri/ /index.php?$args; } # PHP处理 location ~ .php$ { fastcgi_pass wordpress:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; # 增加超时时间用于供应链数据处理 fastcgi_read_timeout 300; } # 静态文件缓存 location ~* .(js|css|png|jpg|jpeg|gif|ico|svg)$ { expires 1y; add_header Cache-Control "public, immutable"; } # 供应链API端点 location ~ ^/wp-json/supply-chain/ { # 增加API超时时间 fastcgi_read_timeout 60; # 允许跨域请求(开发环境) add_header 'Access-Control-Allow-Origin' '*' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always; } # 安全设置 location ~ /.ht { deny all; } } }
- 创建完整的docker-compose.yml文件,编排所有服务: # docker-compose.yml version: '3.8' services: # MySQL数据库服务 mysql: image: mysql:8.0 container_name: supply-chain-mysql restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:-secure_root_password} MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: ${DB_PASSWORD:-secure_password} volumes: - mysql_data:/var/lib/mysql - ./mysql/init.sql:/docker-entrypoint-initdb.d/init.sql networks: - supply-chain-network healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] timeout: 20s retries: 10 # WordPress应用服务 wordpress: build: ./wordpress container_name: supply-chain-wordpress restart: unless-stopped depends_on: mysql: condition: service_healthy environment: WORDPRESS_DB_HOST: mysql:3306 WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: ${DB_PASSWORD:-secure_password} WORDPRESS_DB_NAME: wordpress WORDPRESS_CONFIG_EXTRA: | define('WP_DEBUG', ${WP_DEBUG:-false}); define('WP_DEBUG_LOG', ${WP_DEBUG_LOG:-false}); define('SUPPLY_CHAIN_API_KEY', ${SUPPLY_CHAIN_API_KEY:-default_key}); volumes: - wordpress_data:/var/www/html/wp-content - ./plugins/supply-chain-manager:/var/www/html/wp-content/plugins/supply-chain-manager networks: - supply-chain-network expose: - "80" # Nginx反向代理 nginx: build: ./nginx container_name: supply-chain-nginx restart: unless-stopped depends_on: - wordpress ports: - "80:80" - "443:443" volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf - wordpress_data:/var/www/html/wp-content networks: - supply-chain-network # 供应链监控服务(可选) monitor: image: redis:7-alpine container_name: supply-chain-monitor restart: unless-stopped command: redis-server --appendonly yes volumes: - redis_data:/data networks: - supply-chain-network ports: - "6379:6379" # 备份服务 backup: image: alpine:latest container_name: supply-chain-backup restart: on-failure depends_on: - mysql - wordpress volumes: - backup_data:/backup - mysql_data:/var/lib/mysql:ro - wordpress_data:/var/www/html/wp-content:ro networks: - supply-chain-network command: > sh -c ' echo "备份服务启动..." while true; do # 每天凌晨3点执行备份 if [ $$(date +%H) -eq 03 ]; then echo "开始备份: $$(date)" # 备份MySQL数据库 mysqldump -h mysql -u wordpress -p$${DB_PASSWORD:-secure_password} wordpress > /backup/mysql-backup-$$(date +%Y%m%d).sql # 备份WordPress内容 tar -czf /backup/wordpress-backup-$$(date +%Y%m%d).tar.gz /var/www/html/wp-content echo "备份完成: $$(date)" # 删除7天前的备份 find /backup -name "*.sql" -mtime +7 -delete find /backup -name "*.tar.gz" -mtime +7 -delete fi sleep 3600 done ' # 数据卷定义 volumes: mysql_data: name: supply-chain-mysql-data wordpress_data: name: supply-chain-wordpress-data redis_data: name: supply-chain-redis-data backup_data: name: supply-chain-backup-data # 网络定义 networks: supply-chain-network: driver: bridge name: supply-chain-network
-
- 创建自动化部署脚本: #!/bin/bash # deploy.sh - WordPress供应链系统容器化部署脚本 set -e # 遇到错误时退出 # 颜色定义 RED='33[0;31m' GREEN='33[0;32m' YELLOW='33[1;33m' NC='33[0m' # No Color # 日志函数 log_info() { echo -e "${GREEN}[INFO]${NC} $1" } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } # 检查Docker是否安装 check_docker() { if ! command -v docker &> /dev/null; then log_error "Docker未安装,请先安装Docker" exit 1 fi if ! command -v docker-compose &> /dev/null; then log_error "Docker Compose未安装,请先安装Docker Compose" exit 1 fi log_info "Docker和Docker Compose已安装" } # 创建环境变量文件 setup_env() { if [ ! -f .env ]; then log_info "创建环境变量文件..." cat > .env << EOF # WordPress数据库配置 DB_ROOT_PASSWORD=$(openssl rand -base64 32) DB_PASSWORD=$(openssl rand -base64 32) # WordPress调试设置 WP_DEBUG=false WP_DEBUG_LOG=false # 供应链API密钥 SUPPLY_CHAIN_API_KEY=$(openssl rand -base64 32) # 时区设置 TZ=Asia/Shanghai EOF log_info "环境变量文件已创建" else log_warn "环境变量文件已存在,跳过创建" fi } # 构建并启动容器 start_containers() { log_info "开始构建Docker镜像..." docker-compose build --no-cache log_info "启动容器..." docker-compose up -d # 等待服务启动 log_info "等待服务启动..." sleep 30 # 检查服务状态 if docker-compose ps | grep -q "Up"; then log_info "所有服务已成功启动!" # 显示访问信息 echo "========================================" echo "WordPress供应链系统已部署完成!" echo "访问地址: http://localhost" echo "MySQL端口: 3306" echo "Redis监控: localhost:6379" echo "========================================" else log_error "部分服务启动失败,请检查日志" docker-compose logs exit 1 fi } # 执行健康检查 health_check() { log_info "执行健康检查..." # 检查WordPress if curl -f http://localhost > /dev/null 2>&1; then log_info "WordPress服务正常" else log_error "WordPress服务异常" fi # 检查MySQL if docker-compose exec -T mysql mysqladmin ping -h localhost > /dev/null 2>&1; then log_info "MySQL服务正常" else log_error "MySQL服务异常" fi } # 主函数 main() { log_info "开始部署WordPress供应链系统..." # 检查依赖 check_docker # 设置环境变量 setup_env # 启动容器 start_containers # 健康检查 health_check log_info "部署完成!" } # 执行主函数 main "$@"
- 创建供应链管理插件的核心功能文件: <?php /** * WordPress供应链管理插件 * 文件名: supply-chain-manager.php * 描述: 柔性供应链核心管理功能 */ // 防止直接访问 if (!defined('ABSPATH')) { exit; } /** * 供应链管理器主类 */ class SupplyChainManager { private $db; private $api_key; /** * 构造函数 */ public function __construct() { global $wpdb; $this->db = $wpdb; $this->api_key = defined('SUPPLY_CHAIN_API_KEY') ? SUPPLY_CHAIN_API_KEY : ''; // 初始化钩子 $this->init_hooks(); } /** * 初始化WordPress钩子 */ private function init_hooks() { // 添加管理菜单 add_action('admin_menu', array($this, 'add_admin_menu')); // 注册REST API端点 add_action('rest_api_init', array($this, 'register_rest_routes')); // 注册供应链数据表 register_activation_hook(__FILE__, array($this, 'create_tables')); // 添加库存检查钩子 add_action('woocommerce_checkout_order_processed', array($this, 'check_inventory'), 10, 3); // 添加供应商选择短代码 add_shortcode('supplier_selection', array($this, 'supplier_selection_shortcode')); } /** * 创建供应链数据表 */ public function create_tables() { require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); $charset_collate = $this->db->get_charset_collate(); // 供应商表 $suppliers_table = $this->db->prefix . 'supply_chain_suppliers'; $sql = "CREATE TABLE IF NOT EXISTS $suppliers_table ( id mediumint(9) NOT NULL AUTO_INCREMENT, name varchar(255) NOT NULL, code varchar(50) NOT NULL UNIQUE, contact_person varchar(100), email varchar(100), phone varchar(50), address text, reliability_score decimal(3,2) DEFAULT 0.00, lead_time_days int DEFAULT 7, minimum_order decimal(10,2), payment_terms text, is_active tinyint(1) DEFAULT 1, created_at datetime DEFAULT CURRENT_TIMESTAMP, updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), INDEX idx_reliability (reliability_score), INDEX idx_active (is_active) ) $charset_collate;"; dbDelta($sql); // 库存表 $inventory_table = $this->db->prefix . 'supply_chain_inventory'; $sql = "CREATE TABLE IF NOT EXISTS $inventory_table ( id mediumint(9) NOT NULL AUTO_INCREMENT, product_id bigint(20) NOT NULL, supplier_id mediumint(9), sku varchar(100), current_stock int DEFAULT 0, reserved_stock int DEFAULT 0, available_stock int GENERATED ALWAYS AS (current_stock - reserved_stock) STORED, reorder_point int DEFAULT 10, safety_stock int DEFAULT 5, unit_cost decimal(10,2), location varchar(100), batch_number varchar(50), expiry_date date, last_updated datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), FOREIGN KEY (supplier_id) REFERENCES $suppliers_table(id) ON DELETE SET NULL, INDEX idx_product (product_id), INDEX idx_available (available_stock), INDEX idx_reorder (reorder_point), UNIQUE KEY unique_product_supplier (product_id, supplier_id) ) $charset_collate;"; dbDelta($sql); // 采购订单表 $orders_table = $this->db->prefix . 'supply_chain_orders'; $sql = "CREATE TABLE IF NOT EXISTS $orders_table ( id mediumint(9) NOT NULL AUTO_INCREMENT, order_number varchar(50) NOT NULL UNIQUE, supplier_id mediumint(9) NOT NULL, status enum('draft','pending','confirmed','shipped','delivered','cancelled') DEFAULT 'draft', total_amount decimal(10,2) DEFAULT 0.00, currency varchar(3) DEFAULT 'USD', order_date datetime DEFAULT CURRENT_TIMESTAMP, expected_delivery date, actual_delivery date, notes text, created_by bigint(20), PRIMARY KEY (id), FOREIGN KEY (supplier_id) REFERENCES $suppliers_table(id), INDEX idx_status (status), INDEX idx_delivery (expected_delivery), INDEX idx_supplier (supplier_id) ) $charset_collate;"; dbDelta($sql); // 订单项表 $order_items_table = $this->db->prefix . 'supply_chain_order_items'; $sql = "CREATE TABLE IF NOT EXISTS $order_items_table ( id mediumint(9) NOT NULL AUTO_INCREMENT, order_id mediumint(9) NOT NULL, product_id bigint(20) NOT NULL, quantity int NOT NULL, unit_price decimal(10,2) NOT NULL, total_price decimal(10,2) GENERATED ALWAYS AS (quantity * unit_price) STORED, received_quantity int DEFAULT 0, status enum('pending','partial','completed') DEFAULT 'pending', PRIMARY KEY (id), FOREIGN KEY (order_id) REFERENCES $orders_table(id) ON DELETE CASCADE, INDEX idx_order (order_id), INDEX idx_product (product_id) ) $charset_collate;"; dbDelta($sql); } /** * 添加管理菜单 */ public function add_admin_menu() { add_menu_page( '供应链管理', '供应链', 'manage_options', 'supply-chain', array($this, 'render_dashboard'), 'dashicons-networking', 30 ); add_submenu_page( 'supply-chain', '供应商管理', '供应商', 'manage_options', 'supply-chain-suppliers', array($this, 'render_suppliers_page') ); add_submenu_page( 'supply-chain', '库存管理', '库存', 'manage_options', 'supply-chain-inventory', array($this, 'render_inventory_page') ); add_submenu_page( 'supply-chain', '采购订单', '采购订单', 'manage_options', 'supply-chain-orders', array($this, 'render_orders_page') ); add_submenu_page( 'supply-chain', '报表分析', '报表', 'manage_options', 'supply-chain-reports', array($this, 'render_reports_page') ); } /** * 注册REST API端点 */ public function register_rest_routes() { // 供应商API register_rest_route('supply-chain/v1', '/suppliers', array( 'methods' => 'GET', 'callback' => array($this, 'get_suppliers_api'), 'permission_callback' => array($this, 'check_api_permission') )); register_rest_route('supply-chain/v1', '/suppliers/(?P<id>d+)', array( 'methods' => 'GET', 'callback' => array($this, 'get_supplier_api'), 'permission_callback' => array($this, 'check_api_permission') )); // 库存API register_rest_route('supply-chain/v1', '/inventory', array( 'methods' => 'GET', 'callback' => array($this, 'get_inventory_api'), 'permission_callback' => array($this, 'check_api_permission') )); register_rest_route('supply-chain/v1', '/inventory/low-stock', array( 'methods' => 'GET', 'callback' => array($this, 'get_low_stock_api'), 'permission_callback' => array($this, 'check_api_permission') )); // 订单API register_rest_route('supply-chain/v1', '/orders', array( 'methods' => 'POST', 'callback' => array($this, 'create_order_api'), 'permission_callback' => array($this, 'check_api_permission') )); } /** * API权限检查 */ public function check_api_permission($request) { $api_key = $request->get_header('X-API-Key'); // 验证API密钥 if ($api_key === $this->api_key) { return true; } // 检查用户权限 if (current_user_can('manage_options')) { return true; } return new WP_Error('rest_forbidden', '无权访问', array('status' => 403)); } /** * 获取供应商列表API */ public function get_suppliers_api($request) { $table_name = $this->db->prefix . 'supply_chain_suppliers'; $page = $request->get_param('page') ? intval($request->get_param('page')) : 1; $per_page = $request->get_param('per_page') ? intval($request->get_param('per_page')) : 20; $offset = ($page - 1) * $per_page; // 构建查询 $sql = "SELECT * FROM $table_name WHERE is_active = 1"; // 添加筛选条件 if ($request->get_param('min_reliability')) { $min_reliability = floatval($request->get_param('min_reliability')); $sql .= $this->db->prepare(" AND reliability_score >= %f", $min_reliability); } // 添加排序 $orderby = $request->get_param('orderby') ?: 'reliability_score'; $order = $request->get_param('order') ?: 'DESC'; $sql .= " ORDER BY $orderby $order"; // 添加分页 $sql .= $this->db->prepare(" LIMIT %d OFFSET %d", $per_page, $offset); $suppliers = $this->db->get_results($sql); // 获取总数 $count_sql = "SELECT COUNT(*) FROM $table_name WHERE is_active = 1"; $total = $this->db->get_var($count_sql); return rest_ensure_response(array( 'data' => $suppliers, 'pagination' => array( 'page' => $page, 'per_page' => $per_page, 'total' => intval($total), 'total_pages' => ceil($total / $per_page) ) )); } /** * 检查库存 */ public function check_inventory($order_id, $posted_data, $order) { $items = $order->get_items(); foreach ($items as $item) { $product_id = $item->get_product_id(); $quantity = $item->get_quantity(); // 检查库存 $inventory_table = $this->db->prefix . 'supply_chain_inventory'; $sql = $this->db->prepare( "SELECT available_stock FROM $inventory_table WHERE product_id = %d", $product_id ); $available_stock = $this->db->get_var($sql); if ($available_stock < $quantity) { // 库存不足,触发补货逻辑 $this->trigger_reorder($product_id, $quantity - $available_stock); // 记录库存预留 $this->reserve_stock($product_id, $available_stock); // 发送通知 $this->send_low_stock_notification($product_id, $available_stock, $quantity); } else { // 预留库存 $this->reserve_stock($product_id, $quantity); } } } /** * 触发补货逻辑 */ private function trigger_reorder($product_id, $required_quantity) { // 获取最佳供应商 $best_supplier = $this->get_best_supplier($product_id); if ($best_supplier) { // 创建采购订单 $order_data = array( 'supplier_id' => $best_supplier->id, 'product_id' => $product_id, 'quantity' => max($required_quantity * 2, 50), // 最少补货50件或需求量的2倍 'unit_price' => $this->get_supplier_price($best_supplier->id, $product_id) ); $this->create_purchase_order($order_data); } } /** * 获取最佳供应商 */ private function get_best_supplier($product_id) { $suppliers_table = $this->db->prefix . 'supply_chain_suppliers'; $inventory_table = $this->db->prefix . 'supply_chain_inventory'; $sql = $this->db->prepare( "SELECT s.*, i.unit_price FROM $suppliers_table s INNER JOIN $inventory_table i ON s.id = i.supplier_id WHERE i.product_id = %d AND s.is_active = 1 ORDER BY s.reliability_score DESC, i.unit_price ASC LIMIT 1", $product_id ); return $this->db->get_row($sql); } /** * 供应商选择短代码 */ public function supplier_selection_shortcode($atts) { $atts = shortcode_atts(array( 'product_id' => 0, 'show_prices' => true ), $atts); if (!$atts['product_id']) { return '<p>请指定产品ID</p>'; } ob_start(); ?> <div class="supplier-selection-widget"> <h3>选择供应商</h3> <div class="supplier-options"> <?php $suppliers = $this->get_product_suppliers($atts['product_id']); foreach ($suppliers as $supplier) { ?> <div class="supplier-option"> <input type="radio" name="supplier_<?php echo $atts['product_id']; ?>" value="<?php echo $supplier->id; ?>" data-price="<?php echo $supplier->unit_price; ?>" data-lead-time="<?php echo $supplier->lead_time_days; ?>"> <label> <strong><?php echo esc_html($supplier->name); ?></strong> <?php if ($atts['show_prices']): ?> <span class="price">$<?php echo number_format($supplier->unit_price, 2); ?></span> <?php endif; ?> <span class="lead-time">交货期: <?php echo $supplier->lead_time_days; ?>天</span> <span class="reliability">可靠度: <?php echo $supplier->reliability_score; ?>/5</span> </label> </div> <?php } ?> </div> </div> <style> .supplier-selection-widget { border: 1px solid #ddd; padding: 20px; margin: 20px 0; border-radius: 5px; } .supplier-option { margin: 10px 0; padding: 10px; border: 1px solid #eee; border-radius: 3px; } .supplier-option:hover { background-color: #f9f9f9; } .supplier-option label { display: block; margin-left: 25px; cursor: pointer; } .supplier-option .price { color: #0073aa; font-weight: bold; margin-left: 15px; } .supplier-option .lead-time { color: #666; margin-left: 15px; font-size: 0.9em; } .supplier-option .reliability { color: #46b450; margin-left: 15px; font-size: 0.9em; } </style> <script> jQuery(document).ready(function($) { $('.supplier-option input').on('change', function() { var price = $(this).data('price'); var leadTime = $(this).data('lead-time'); // 更新产品价格和交货时间显示 $('.product-price').text('$' + price.toFixed(2)); $('.delivery-time').text('预计' + leadTime + '天内发货'); // 发送AJAX请求更新购物车 $.ajax({ url: '<?php echo rest_url('supply-chain/v1/update-cart'); ?>', method: 'POST', data: { product_id: <?php echo $atts['product_id']; ?>, supplier_id: $(this).val(), price: price } }); }); }); </script> <?php return ob_get_clean(); } /** * 获取产品供应商 */ private function get_product_suppliers($product_id) { $suppliers_table = $this->db->prefix . 'supply_chain_suppliers'; $inventory_table = $this->db->prefix . 'supply_chain_inventory'; $sql = $this->db->prepare( "SELECT s.*, i.unit_price FROM $suppliers_table s INNER JOIN $inventory_table i ON s.id = i.supplier_id WHERE i.product_id = %d AND s.is_active = 1 AND i.available_stock > 0 ORDER BY s.reliability_score DESC, i.unit_price ASC", $product_id ); return $this->db->get_results($sql); } /** * 渲染仪表板 */ public function render_dashboard() { ?> <div class="wrap supply-chain-dashboard"> <h1>供应链仪表板</h1> <div class="dashboard-stats"> <div class="stat-card"> <h3>活跃供应商</h3> <p class="stat-number"><?php echo $this->get_supplier_count(); ?></p> </div> <div class="stat-card"> <h3>低库存产品</h3> <p class="stat-number"><?php echo $this->get_low_stock_count(); ?></p> </div
在当今快速发展的电商环境中,柔性供应链系统需要具备高度可扩展性和弹性。WordPress作为广泛使用的内容管理系统,结合定制化的供应链插件,可以构建强大的电商解决方案。然而,传统的部署方式在面对流量波动、快速迭代和跨环境一致性时面临挑战。
容器化技术通过将应用程序及其依赖项打包到标准化单元中,实现了环境一致性、快速部署和弹性扩展。本教程将详细介绍如何将WordPress柔性供应链软件进行容器化部署。
首先,我们需要在服务器上安装Docker和Docker Compose。以下是在Ubuntu系统上的安装步骤:
#!/bin/bash
# 更新系统包列表
sudo apt-get update
# 安装必要的依赖包
sudo apt-get install -y
apt-transport-https
ca-certificates
curl
gnupg
lsb-release
# 添加Docker官方GPG密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# 设置稳定版仓库
echo
"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 安装Docker引擎
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
# 安装Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/download/v2.15.1/docker-compose-$(uname -s)-$(uname -m)"
-o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
# 验证安装
docker --version
docker-compose --version
创建以下项目目录结构:
wordpress-supply-chain/
├── docker-compose.yml
├── nginx/
│ ├── Dockerfile
│ └── nginx.conf
├── wordpress/
│ └── Dockerfile
├── mysql/
│ └── init.sql
├── php/
│ └── custom.ini
└── plugins/
└── supply-chain-manager/
└── (供应链插件文件)
创建MySQL初始化脚本,用于设置供应链数据库:
-- mysql/init.sql
-- 创建供应链专用数据库
CREATE DATABASE IF NOT EXISTS supply_chain_db;
USE supply_chain_db;
-- 创建供应商表
CREATE TABLE IF NOT EXISTS suppliers (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
contact_email VARCHAR(255),
phone VARCHAR(50),
address TEXT,
reliability_score DECIMAL(3,2) DEFAULT 0.00,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 创建库存表
CREATE TABLE IF NOT EXISTS inventory (
id INT AUTO_INCREMENT PRIMARY KEY,
product_id INT NOT NULL,
supplier_id INT,
quantity INT DEFAULT 0,
reorder_level INT DEFAULT 10,
last_restocked DATE,
location VARCHAR(100),
FOREIGN KEY (supplier_id) REFERENCES suppliers(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 创建订单跟踪表
CREATE TABLE IF NOT EXISTS order_tracking (
id INT AUTO_INCREMENT PRIMARY KEY,
order_id VARCHAR(50) NOT NULL,
status ENUM('pending', 'processing', 'shipped', 'delivered', 'cancelled') DEFAULT 'pending',
supplier_id INT,
estimated_delivery DATE,
actual_delivery DATE,
tracking_number VARCHAR(100),
notes TEXT,
FOREIGN KEY (supplier_id) REFERENCES suppliers(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 插入示例数据
INSERT INTO suppliers (name, contact_email, reliability_score) VALUES
('优质供应商A', 'supplierA@example.com', 4.8),
('快速配送B', 'supplierB@example.com', 4.5),
('经济优选C', 'supplierC@example.com', 4.2);
创建WordPress容器的Dockerfile,集成供应链插件:
# wordpress/Dockerfile
# 使用官方WordPress镜像作为基础
FROM wordpress:6.2-php8.1-apache
# 设置维护者信息
LABEL maintainer="supply-chain-dev@example.com"
# 安装必要的PHP扩展
RUN apt-get update && apt-get install -y
libzip-dev
libpng-dev
libjpeg-dev
libfreetype6-dev
&& docker-php-ext-configure gd --with-freetype --with-jpeg
&& docker-php-ext-install -j$(nproc) gd zip pdo_mysql
# 复制自定义PHP配置
COPY ../php/custom.ini /usr/local/etc/php/conf.d/custom.ini
# 复制供应链插件到WordPress插件目录
COPY ../plugins/supply-chain-manager /var/www/html/wp-content/plugins/supply-chain-manager
# 设置插件目录权限
RUN chown -R www-data:www-data /var/www/html/wp-content/plugins/supply-chain-manager
&& chmod -R 755 /var/www/html/wp-content/plugins/supply-chain-manager
# 创建供应链数据目录
RUN mkdir -p /var/www/html/wp-content/uploads/supply-chain
&& chown -R www-data:www-data /var/www/html/wp-content/uploads/supply-chain
# 暴露Apache端口
EXPOSE 80
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3
CMD curl -f http://localhost/ || exit 1
创建Nginx配置文件,优化WordPress性能:
# nginx/nginx.conf
events {
worker_connections 1024;
}
http {
# 基础配置
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# MIME类型
include /etc/nginx/mime.types;
default_type application/octet-stream;
# 日志配置
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
# Gzip压缩
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/atom+xml image/svg+xml;
# WordPress上游服务器
upstream wordpress {
server wordpress:80;
}
# 主服务器配置
server {
listen 80;
server_name supplychain.example.com;
# 根目录
root /var/www/html;
index index.php index.html index.htm;
# WordPress重写规则
location / {
try_files $uri $uri/ /index.php?$args;
}
# PHP处理
location ~ .php$ {
fastcgi_pass wordpress:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# 增加超时时间用于供应链数据处理
fastcgi_read_timeout 300;
}
# 静态文件缓存
location ~* .(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# 供应链API端点
location ~ ^/wp-json/supply-chain/ {
# 增加API超时时间
fastcgi_read_timeout 60;
# 允许跨域请求(开发环境)
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
}
# 安全设置
location ~ /.ht {
deny all;
}
}
}
创建完整的docker-compose.yml文件,编排所有服务:
# docker-compose.yml
version: '3.8'
services:
# MySQL数据库服务
mysql:
image: mysql:8.0
container_name: supply-chain-mysql
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:-secure_root_password}
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: ${DB_PASSWORD:-secure_password}
volumes:
- mysql_data:/var/lib/mysql
- ./mysql/init.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- supply-chain-network
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
timeout: 20s
retries: 10
# WordPress应用服务
wordpress:
build: ./wordpress
container_name: supply-chain-wordpress
restart: unless-stopped
depends_on:
mysql:
condition: service_healthy
environment:
WORDPRESS_DB_HOST: mysql:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: ${DB_PASSWORD:-secure_password}
WORDPRESS_DB_NAME: wordpress
WORDPRESS_CONFIG_EXTRA: |
define('WP_DEBUG', ${WP_DEBUG:-false});
define('WP_DEBUG_LOG', ${WP_DEBUG_LOG:-false});
define('SUPPLY_CHAIN_API_KEY', ${SUPPLY_CHAIN_API_KEY:-default_key});
volumes:
- wordpress_data:/var/www/html/wp-content
- ./plugins/supply-chain-manager:/var/www/html/wp-content/plugins/supply-chain-manager
networks:
- supply-chain-network
expose:
- "80"
# Nginx反向代理
nginx:
build: ./nginx
container_name: supply-chain-nginx
restart: unless-stopped
depends_on:
- wordpress
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- wordpress_data:/var/www/html/wp-content
networks:
- supply-chain-network
# 供应链监控服务(可选)
monitor:
image: redis:7-alpine
container_name: supply-chain-monitor
restart: unless-stopped
command: redis-server --appendonly yes
volumes:
- redis_data:/data
networks:
- supply-chain-network
ports:
- "6379:6379"
# 备份服务
backup:
image: alpine:latest
container_name: supply-chain-backup
restart: on-failure
depends_on:
- mysql
- wordpress
volumes:
- backup_data:/backup
- mysql_data:/var/lib/mysql:ro
- wordpress_data:/var/www/html/wp-content:ro
networks:
- supply-chain-network
command: >
sh -c '
echo "备份服务启动..."
while true; do
# 每天凌晨3点执行备份
if [ $$(date +%H) -eq 03 ]; then
echo "开始备份: $$(date)"
# 备份MySQL数据库
mysqldump -h mysql -u wordpress -p$${DB_PASSWORD:-secure_password} wordpress > /backup/mysql-backup-$$(date +%Y%m%d).sql
# 备份WordPress内容
tar -czf /backup/wordpress-backup-$$(date +%Y%m%d).tar.gz /var/www/html/wp-content
echo "备份完成: $$(date)"
# 删除7天前的备份
find /backup -name "*.sql" -mtime +7 -delete
find /backup -name "*.tar.gz" -mtime +7 -delete
fi
sleep 3600
done
'
# 数据卷定义
volumes:
mysql_data:
name: supply-chain-mysql-data
wordpress_data:
name: supply-chain-wordpress-data
redis_data:
name: supply-chain-redis-data
backup_data:
name: supply-chain-backup-data
# 网络定义
networks:
supply-chain-network:
driver: bridge
name: supply-chain-network
创建自动化部署脚本:
#!/bin/bash
# deploy.sh - WordPress供应链系统容器化部署脚本
set -e # 遇到错误时退出
# 颜色定义
RED='33[0;31m'
GREEN='33[0;32m'
YELLOW='33[1;33m'
NC='33[0m' # No Color
# 日志函数
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# 检查Docker是否安装
check_docker() {
if ! command -v docker &> /dev/null; then
log_error "Docker未安装,请先安装Docker"
exit 1
fi
if ! command -v docker-compose &> /dev/null; then
log_error "Docker Compose未安装,请先安装Docker Compose"
exit 1
fi
log_info "Docker和Docker Compose已安装"
}
# 创建环境变量文件
setup_env() {
if [ ! -f .env ]; then
log_info "创建环境变量文件..."
cat > .env << EOF
# WordPress数据库配置
DB_ROOT_PASSWORD=$(openssl rand -base64 32)
DB_PASSWORD=$(openssl rand -base64 32)
# WordPress调试设置
WP_DEBUG=false
WP_DEBUG_LOG=false
# 供应链API密钥
SUPPLY_CHAIN_API_KEY=$(openssl rand -base64 32)
# 时区设置
TZ=Asia/Shanghai
EOF
log_info "环境变量文件已创建"
else
log_warn "环境变量文件已存在,跳过创建"
fi
}
# 构建并启动容器
start_containers() {
log_info "开始构建Docker镜像..."
docker-compose build --no-cache
log_info "启动容器..."
docker-compose up -d
# 等待服务启动
log_info "等待服务启动..."
sleep 30
# 检查服务状态
if docker-compose ps | grep -q "Up"; then
log_info "所有服务已成功启动!"
# 显示访问信息
echo "========================================"
echo "WordPress供应链系统已部署完成!"
echo "访问地址: http://localhost"
echo "MySQL端口: 3306"
echo "Redis监控: localhost:6379"
echo "========================================"
else
log_error "部分服务启动失败,请检查日志"
docker-compose logs
exit 1
fi
}
# 执行健康检查
health_check() {
log_info "执行健康检查..."
# 检查WordPress
if curl -f http://localhost > /dev/null 2>&1; then
log_info "WordPress服务正常"
else
log_error "WordPress服务异常"
fi
# 检查MySQL
if docker-compose exec -T mysql mysqladmin ping -h localhost > /dev/null 2>&1; then
log_info "MySQL服务正常"
else
log_error "MySQL服务异常"
fi
}
# 主函数
main() {
log_info "开始部署WordPress供应链系统..."
# 检查依赖
check_docker
# 设置环境变量
setup_env
# 启动容器
start_containers
# 健康检查
health_check
log_info "部署完成!"
}
# 执行主函数
main "$@"
创建供应链管理插件的核心功能文件:
<?php
/**
* WordPress供应链管理插件
* 文件名: supply-chain-manager.php
* 描述: 柔性供应链核心管理功能
*/
// 防止直接访问
if (!defined('ABSPATH')) {
exit;
}
/**
* 供应链管理器主类
*/
class SupplyChainManager {
private $db;
private $api_key;
/**
* 构造函数
*/
public function __construct() {
global $wpdb;
$this->db = $wpdb;
$this->api_key = defined('SUPPLY_CHAIN_API_KEY') ? SUPPLY_CHAIN_API_KEY : '';
// 初始化钩子
$this->init_hooks();
}
/**
* 初始化WordPress钩子
*/
private function init_hooks() {
// 添加管理菜单
add_action('admin_menu', array($this, 'add_admin_menu'));
// 注册REST API端点
add_action('rest_api_init', array($this, 'register_rest_routes'));
// 注册供应链数据表
register_activation_hook(__FILE__, array($this, 'create_tables'));
// 添加库存检查钩子
add_action('woocommerce_checkout_order_processed', array($this, 'check_inventory'), 10, 3);
// 添加供应商选择短代码
add_shortcode('supplier_selection', array($this, 'supplier_selection_shortcode'));
}
/**
* 创建供应链数据表
*/
public function create_tables() {
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
$charset_collate = $this->db->get_charset_collate();
// 供应商表
$suppliers_table = $this->db->prefix . 'supply_chain_suppliers';
$sql = "CREATE TABLE IF NOT EXISTS $suppliers_table (
id mediumint(9) NOT NULL AUTO_INCREMENT,
name varchar(255) NOT NULL,
code varchar(50) NOT NULL UNIQUE,
contact_person varchar(100),
email varchar(100),
phone varchar(50),
address text,
reliability_score decimal(3,2) DEFAULT 0.00,
lead_time_days int DEFAULT 7,
minimum_order decimal(10,2),
payment_terms text,
is_active tinyint(1) DEFAULT 1,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
INDEX idx_reliability (reliability_score),
INDEX idx_active (is_active)
) $charset_collate;";
dbDelta($sql);
// 库存表
$inventory_table = $this->db->prefix . 'supply_chain_inventory';
$sql = "CREATE TABLE IF NOT EXISTS $inventory_table (
id mediumint(9) NOT NULL AUTO_INCREMENT,
product_id bigint(20) NOT NULL,
supplier_id mediumint(9),
sku varchar(100),
current_stock int DEFAULT 0,
reserved_stock int DEFAULT 0,
available_stock int GENERATED ALWAYS AS (current_stock - reserved_stock) STORED,
reorder_point int DEFAULT 10,
safety_stock int DEFAULT 5,
unit_cost decimal(10,2),
location varchar(100),
batch_number varchar(50),
expiry_date date,
last_updated datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
FOREIGN KEY (supplier_id) REFERENCES $suppliers_table(id) ON DELETE SET NULL,
INDEX idx_product (product_id),
INDEX idx_available (available_stock),
INDEX idx_reorder (reorder_point),
UNIQUE KEY unique_product_supplier (product_id, supplier_id)
) $charset_collate;";
dbDelta($sql);
// 采购订单表
$orders_table = $this->db->prefix . 'supply_chain_orders';
$sql = "CREATE TABLE IF NOT EXISTS $orders_table (
id mediumint(9) NOT NULL AUTO_INCREMENT,
order_number varchar(50) NOT NULL UNIQUE,
supplier_id mediumint(9) NOT NULL,
status enum('draft','pending','confirmed','shipped','delivered','cancelled') DEFAULT 'draft',
total_amount decimal(10,2) DEFAULT 0.00,
currency varchar(3) DEFAULT 'USD',
order_date datetime DEFAULT CURRENT_TIMESTAMP,
expected_delivery date,
actual_delivery date,
notes text,
created_by bigint(20),
PRIMARY KEY (id),
FOREIGN KEY (supplier_id) REFERENCES $suppliers_table(id),
INDEX idx_status (status),
INDEX idx_delivery (expected_delivery),
INDEX idx_supplier (supplier_id)
) $charset_collate;";
dbDelta($sql);
// 订单项表
$order_items_table = $this->db->prefix . 'supply_chain_order_items';
$sql = "CREATE TABLE IF NOT EXISTS $order_items_table (
id mediumint(9) NOT NULL AUTO_INCREMENT,
order_id mediumint(9) NOT NULL,
product_id bigint(20) NOT NULL,
quantity int NOT NULL,
unit_price decimal(10,2) NOT NULL,
total_price decimal(10,2) GENERATED ALWAYS AS (quantity * unit_price) STORED,
received_quantity int DEFAULT 0,
status enum('pending','partial','completed') DEFAULT 'pending',
PRIMARY KEY (id),
FOREIGN KEY (order_id) REFERENCES $orders_table(id) ON DELETE CASCADE,
INDEX idx_order (order_id),
INDEX idx_product (product_id)
) $charset_collate;";
dbDelta($sql);
}
/**
* 添加管理菜单
*/
public function add_admin_menu() {
add_menu_page(
'供应链管理',
'供应链',
'manage_options',
'supply-chain',
array($this, 'render_dashboard'),
'dashicons-networking',
30
);
add_submenu_page(
'supply-chain',
'供应商管理',
'供应商',
'manage_options',
'supply-chain-suppliers',
array($this, 'render_suppliers_page')
);
add_submenu_page(
'supply-chain',
'库存管理',
'库存',
'manage_options',
'supply-chain-inventory',
array($this, 'render_inventory_page')
);
add_submenu_page(
'supply-chain',
'采购订单',
'采购订单',
'manage_options',
'supply-chain-orders',
array($this, 'render_orders_page')
);
add_submenu_page(
'supply-chain',
'报表分析',
'报表',
'manage_options',
'supply-chain-reports',
array($this, 'render_reports_page')
);
}
/**
* 注册REST API端点
*/
public function register_rest_routes() {
// 供应商API
register_rest_route('supply-chain/v1', '/suppliers', array(
'methods' => 'GET',
'callback' => array($this, 'get_suppliers_api'),
'permission_callback' => array($this, 'check_api_permission')
));
register_rest_route('supply-chain/v1', '/suppliers/(?P<id>d+)', array(
'methods' => 'GET',
'callback' => array($this, 'get_supplier_api'),
'permission_callback' => array($this, 'check_api_permission')
));
// 库存API
register_rest_route('supply-chain/v1', '/inventory', array(
'methods' => 'GET',
'callback' => array($this, 'get_inventory_api'),
'permission_callback' => array($this, 'check_api_permission')
));
register_rest_route('supply-chain/v1', '/inventory/low-stock', array(
'methods' => 'GET',
'callback' => array($this, 'get_low_stock_api'),
'permission_callback' => array($this, 'check_api_permission')
));
// 订单API
register_rest_route('supply-chain/v1', '/orders', array(
'methods' => 'POST',
'callback' => array($this, 'create_order_api'),
'permission_callback' => array($this, 'check_api_permission')
));
}
/**
* API权限检查
*/
public function check_api_permission($request) {
$api_key = $request->get_header('X-API-Key');
// 验证API密钥
if ($api_key === $this->api_key) {
return true;
}
// 检查用户权限
if (current_user_can('manage_options')) {
return true;
}
return new WP_Error('rest_forbidden', '无权访问', array('status' => 403));
}
/**
* 获取供应商列表API
*/
public function get_suppliers_api($request) {
$table_name = $this->db->prefix . 'supply_chain_suppliers';
$page = $request->get_param('page') ? intval($request->get_param('page')) : 1;
$per_page = $request->get_param('per_page') ? intval($request->get_param('per_page')) : 20;
$offset = ($page - 1) * $per_page;
// 构建查询
$sql = "SELECT * FROM $table_name WHERE is_active = 1";
// 添加筛选条件
if ($request->get_param('min_reliability')) {
$min_reliability = floatval($request->get_param('min_reliability'));
$sql .= $this->db->prepare(" AND reliability_score >= %f", $min_reliability);
}
// 添加排序
$orderby = $request->get_param('orderby') ?: 'reliability_score';
$order = $request->get_param('order') ?: 'DESC';
$sql .= " ORDER BY $orderby $order";
// 添加分页
$sql .= $this->db->prepare(" LIMIT %d OFFSET %d", $per_page, $offset);
$suppliers = $this->db->get_results($sql);
// 获取总数
$count_sql = "SELECT COUNT(*) FROM $table_name WHERE is_active = 1";
$total = $this->db->get_var($count_sql);
return rest_ensure_response(array(
'data' => $suppliers,
'pagination' => array(
'page' => $page,
'per_page' => $per_page,
'total' => intval($total),
'total_pages' => ceil($total / $per_page)
)
));
}
/**
* 检查库存
*/
public function check_inventory($order_id, $posted_data, $order) {
$items = $order->get_items();
foreach ($items as $item) {
$product_id = $item->get_product_id();
$quantity = $item->get_quantity();
// 检查库存
$inventory_table = $this->db->prefix . 'supply_chain_inventory';
$sql = $this->db->prepare(
"SELECT available_stock FROM $inventory_table WHERE product_id = %d",
$product_id
);
$available_stock = $this->db->get_var($sql);
if ($available_stock < $quantity) {
// 库存不足,触发补货逻辑
$this->trigger_reorder($product_id, $quantity - $available_stock);
// 记录库存预留
$this->reserve_stock($product_id, $available_stock);
// 发送通知
$this->send_low_stock_notification($product_id, $available_stock, $quantity);
} else {
// 预留库存
$this->reserve_stock($product_id, $quantity);
}
}
}
/**
* 触发补货逻辑
*/
private function trigger_reorder($product_id, $required_quantity) {
// 获取最佳供应商
$best_supplier = $this->get_best_supplier($product_id);
if ($best_supplier) {
// 创建采购订单
$order_data = array(
'supplier_id' => $best_supplier->id,
'product_id' => $product_id,
'quantity' => max($required_quantity * 2, 50), // 最少补货50件或需求量的2倍
'unit_price' => $this->get_supplier_price($best_supplier->id, $product_id)
);
$this->create_purchase_order($order_data);
}
}
/**
* 获取最佳供应商
*/
private function get_best_supplier($product_id) {
$suppliers_table = $this->db->prefix . 'supply_chain_suppliers';
$inventory_table = $this->db->prefix . 'supply_chain_inventory';
$sql = $this->db->prepare(
"SELECT s.*, i.unit_price
FROM $suppliers_table s
INNER JOIN $inventory_table i ON s.id = i.supplier_id
WHERE i.product_id = %d
AND s.is_active = 1
ORDER BY s.reliability_score DESC, i.unit_price ASC
LIMIT 1",
$product_id
);
return $this->db->get_row($sql);
}
/**
* 供应商选择短代码
*/
public function supplier_selection_shortcode($atts) {
$atts = shortcode_atts(array(
'product_id' => 0,
'show_prices' => true
), $atts);
if (!$atts['product_id']) {
return '<p>请指定产品ID</p>';
}
ob_start();
?>
<div class="supplier-selection-widget">
<h3>选择供应商</h3>
<div class="supplier-options">
<?php
$suppliers = $this->get_product_suppliers($atts['product_id']);
foreach ($suppliers as $supplier) {
?>
<div class="supplier-option">
<input type="radio"
name="supplier_<?php echo $atts['product_id']; ?>"
value="<?php echo $supplier->id; ?>"
data-price="<?php echo $supplier->unit_price; ?>"
data-lead-time="<?php echo $supplier->lead_time_days; ?>">
<label>
<strong><?php echo esc_html($supplier->name); ?></strong>
<?php if ($atts['show_prices']): ?>
<span class="price">$<?php echo number_format($supplier->unit_price, 2); ?></span>
<?php endif; ?>
<span class="lead-time">交货期: <?php echo $supplier->lead_time_days; ?>天</span>
<span class="reliability">可靠度: <?php echo $supplier->reliability_score; ?>/5</span>
</label>
</div>
<?php
}
?>
</div>
</div>
<style>
.supplier-selection-widget {
border: 1px solid #ddd;
padding: 20px;
margin: 20px 0;
border-radius: 5px;
}
.supplier-option {
margin: 10px 0;
padding: 10px;
border: 1px solid #eee;
border-radius: 3px;
}
.supplier-option:hover {
background-color: #f9f9f9;
}
.supplier-option label {
display: block;
margin-left: 25px;
cursor: pointer;
}
.supplier-option .price {
color: #0073aa;
font-weight: bold;
margin-left: 15px;
}
.supplier-option .lead-time {
color: #666;
margin-left: 15px;
font-size: 0.9em;
}
.supplier-option .reliability {
color: #46b450;
margin-left: 15px;
font-size: 0.9em;
}
</style>
<script>
jQuery(document).ready(function($) {
$('.supplier-option input').on('change', function() {
var price = $(this).data('price');
var leadTime = $(this).data('lead-time');
// 更新产品价格和交货时间显示
$('.product-price').text('$' + price.toFixed(2));
$('.delivery-time').text('预计' + leadTime + '天内发货');
// 发送AJAX请求更新购物车
$.ajax({
url: '<?php echo rest_url('supply-chain/v1/update-cart'); ?>',
method: 'POST',
data: {
product_id: <?php echo $atts['product_id']; ?>,
supplier_id: $(this).val(),
price: price
}
});
});
});
</script>
<?php
return ob_get_clean();
}
/**
* 获取产品供应商
*/
private function get_product_suppliers($product_id) {
$suppliers_table = $this->db->prefix . 'supply_chain_suppliers';
$inventory_table = $this->db->prefix . 'supply_chain_inventory';
$sql = $this->db->prepare(
"SELECT s.*, i.unit_price
FROM $suppliers_table s
INNER JOIN $inventory_table i ON s.id = i.supplier_id
WHERE i.product_id = %d
AND s.is_active = 1
AND i.available_stock > 0
ORDER BY s.reliability_score DESC, i.unit_price ASC",
$product_id
);
return $this->db->get_results($sql);
}
/**
* 渲染仪表板
*/
public function render_dashboard() {
?>
<div class="wrap supply-chain-dashboard">
<h1>供应链仪表板</h1>
<div class="dashboard-stats">
<div class="stat-card">
<h3>活跃供应商</h3>
<p class="stat-number"><?php echo $this->get_supplier_count(); ?></p>
</div>
<div class="stat-card">
<h3>低库存产品</h3>
<p class="stat-number"><?php echo $this->get_low_stock_count(); ?></p>
</div


