文章目录
-
- 在当今快速变化的商业环境中,柔性供应链管理系统需要具备高度的灵活性和可扩展性。传统的WordPress主题开发模式将前后端逻辑紧密耦合,难以应对复杂业务需求的变化。前后端分离架构通过将用户界面与业务逻辑分离,使前端专注于展示和交互,后端专注于数据处理和API提供,大大提升了系统的可维护性和开发效率。 本教程将指导您如何为WordPress开发一个柔性供应链管理软件,采用现代的前后端分离技术栈:前端使用React,后端使用WordPress REST API,并通过自定义插件扩展供应链管理功能。
-
- 首先,确保您的开发环境满足以下要求: 本地服务器环境:推荐使用XAMPP、MAMP或Local by Flywheel WordPress安装:最新版本的WordPress(5.8+) Node.js环境:Node.js 14+ 和 npm/yarn 代码编辑器:VS Code、Sublime Text或PHPStorm
- 前端:React + Axios + Material-UI React提供组件化开发,便于构建复杂UI Axios简化HTTP请求处理 Material-UI提供美观的UI组件,加速开发 后端:WordPress REST API + 自定义插件 利用WordPress成熟的用户管理和权限系统 通过自定义插件扩展供应链管理功能 REST API提供标准化的数据接口
-
- 首先,在WordPress的wp-content/plugins目录下创建插件文件夹flexible-supply-chain,并创建主文件: <?php /** * Plugin Name: 柔性供应链管理系统 * Plugin URI: https://yourwebsite.com/ * Description: 为WordPress提供柔性供应链管理功能的插件 * Version: 1.0.0 * Author: 您的名称 * License: GPL v2 or later * Text Domain: flexible-supply-chain */ // 防止直接访问 if (!defined('ABSPATH')) { exit; } // 定义插件常量 define('FSC_VERSION', '1.0.0'); define('FSC_PLUGIN_DIR', plugin_dir_path(__FILE__)); define('FSC_PLUGIN_URL', plugin_dir_url(__FILE__)); // 初始化插件 class FlexibleSupplyChain { public function __construct() { // 注册激活和停用钩子 register_activation_hook(__FILE__, array($this, 'activate')); register_deactivation_hook(__FILE__, array($this, 'deactivate')); // 初始化插件功能 add_action('init', array($this, 'init')); } // 插件激活时执行 public function activate() { // 创建必要的数据库表 $this->create_tables(); // 刷新重写规则 flush_rewrite_rules(); } // 插件停用时执行 public function deactivate() { // 清理临时数据 flush_rewrite_rules(); } // 初始化插件 public function init() { // 注册自定义文章类型 $this->register_post_types(); // 注册REST API路由 add_action('rest_api_init', array($this, 'register_rest_routes')); // 加载文本域 load_plugin_textdomain('flexible-supply-chain', false, dirname(plugin_basename(__FILE__)) . '/languages'); } // 创建数据库表 private function create_tables() { global $wpdb; $charset_collate = $wpdb->get_charset_collate(); $table_name = $wpdb->prefix . 'supply_chain_inventory'; $sql = "CREATE TABLE IF NOT EXISTS $table_name ( id mediumint(9) NOT NULL AUTO_INCREMENT, product_id bigint(20) NOT NULL, warehouse_id mediumint(9) NOT NULL, quantity int(11) NOT NULL DEFAULT 0, safety_stock int(11) NOT NULL DEFAULT 10, last_updated datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY product_id (product_id), KEY warehouse_id (warehouse_id) ) $charset_collate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); } // 注册自定义文章类型 private function register_post_types() { // 产品自定义文章类型 register_post_type('supply_product', array( 'labels' => array( 'name' => __('产品', 'flexible-supply-chain'), 'singular_name' => __('产品', 'flexible-supply-chain') ), 'public' => true, 'has_archive' => true, 'supports' => array('title', 'editor', 'thumbnail', 'custom-fields'), 'show_in_rest' => true, // 启用REST API支持 'rest_base' => 'supply-products', 'menu_icon' => 'dashicons-products' ) ); // 供应商自定义文章类型 register_post_type('supply_vendor', array( 'labels' => array( 'name' => __('供应商', 'flexible-supply-chain'), 'singular_name' => __('供应商', 'flexible-supply-chain') ), 'public' => true, 'has_archive' => true, 'supports' => array('title', 'editor', 'thumbnail'), 'show_in_rest' => true, 'rest_base' => 'supply-vendors', 'menu_icon' => 'dashicons-businessperson' ) ); } // 注册REST API路由 public function register_rest_routes() { // 库存管理API register_rest_route('fsc/v1', '/inventory/(?P<id>d+)', array( 'methods' => 'GET', 'callback' => array($this, 'get_inventory'), 'permission_callback' => array($this, 'check_permissions') )); register_rest_route('fsc/v1', '/inventory', array( 'methods' => 'POST', 'callback' => array($this, 'update_inventory'), 'permission_callback' => array($this, 'check_permissions') )); // 订单处理API register_rest_route('fsc/v1', '/orders/process', array( 'methods' => 'POST', 'callback' => array($this, 'process_order'), 'permission_callback' => array($this, 'check_permissions') )); } // 获取库存信息 public function get_inventory($request) { global $wpdb; $product_id = $request['id']; $table_name = $wpdb->prefix . 'supply_chain_inventory'; $results = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $table_name WHERE product_id = %d", $product_id ) ); return rest_ensure_response($results); } // 更新库存 public function update_inventory($request) { global $wpdb; $parameters = $request->get_json_params(); $product_id = $parameters['product_id']; $warehouse_id = $parameters['warehouse_id']; $quantity = $parameters['quantity']; $table_name = $wpdb->prefix . 'supply_chain_inventory'; // 检查记录是否存在 $existing = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM $table_name WHERE product_id = %d AND warehouse_id = %d", $product_id, $warehouse_id ) ); if ($existing) { // 更新现有记录 $result = $wpdb->update( $table_name, array('quantity' => $quantity), array('id' => $existing), array('%d'), array('%d') ); } else { // 插入新记录 $result = $wpdb->insert( $table_name, array( 'product_id' => $product_id, 'warehouse_id' => $warehouse_id, 'quantity' => $quantity ), array('%d', '%d', '%d') ); } if ($result === false) { return new WP_Error('db_error', '数据库操作失败', array('status' => 500)); } return rest_ensure_response(array( 'success' => true, 'message' => '库存更新成功' )); } // 处理订单 public function process_order($request) { $parameters = $request->get_json_params(); $order_items = $parameters['items']; // 这里实现订单处理逻辑 // 包括库存检查、分配、更新等 $response = array( 'success' => true, 'message' => '订单处理完成', 'allocated_items' => $order_items ); return rest_ensure_response($response); } // 权限检查 public function check_permissions($request) { // 检查用户是否登录并具有适当权限 return current_user_can('manage_options'); } } // 初始化插件 new FlexibleSupplyChain(); ?>
- 供应链管理系统需要高效的数据存储结构。除了上述库存表,您可能还需要创建以下表: 订单表:存储客户订单信息 物流表:跟踪货物运输状态 需求预测表:存储销售预测数据
-
- 使用Create React App快速初始化前端项目: npx create-react-app supply-chain-frontend cd supply-chain-frontend npm install axios @mui/material @emotion/react @emotion/styled @mui/icons-material
-
- // src/components/InventoryManager.js import React, { useState, useEffect } from 'react'; import { Box, Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Typography, Button, TextField, Alert, CircularProgress } from '@mui/material'; import { Refresh as RefreshIcon } from '@mui/icons-material'; import axios from 'axios'; /** * 库存管理组件 * 显示和管理产品库存信息 */ const InventoryManager = () => { const [inventory, setInventory] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [updating, setUpdating] = useState(false); // 从WordPress REST API获取库存数据 const fetchInventory = async () => { try { setLoading(true); // 注意:这里需要替换为您的WordPress站点URL const response = await axios.get('http://your-wordpress-site.com/wp-json/fsc/v1/inventory/1'); setInventory(response.data); setError(null); } catch (err) { setError('获取库存数据失败: ' + err.message); console.error('库存数据获取错误:', err); } finally { setLoading(false); } }; // 组件加载时获取数据 useEffect(() => { fetchInventory(); }, []); // 更新库存数量 const updateStock = async (productId, warehouseId, newQuantity) => { try { setUpdating(true); await axios.post('http://your-wordpress-site.com/wp-json/fsc/v1/inventory', { product_id: productId, warehouse_id: warehouseId, quantity: newQuantity }); // 更新本地状态 setInventory(prev => prev.map(item => item.product_id === productId && item.warehouse_id === warehouseId ? { ...item, quantity: newQuantity } : item )); alert('库存更新成功!'); } catch (err) { alert('库存更新失败: ' + err.message); console.error('库存更新错误:', err); } finally { setUpdating(false); } }; // 处理库存数量变化 const handleQuantityChange = (productId, warehouseId, currentQuantity) => { const newQuantity = prompt('请输入新的库存数量:', currentQuantity); if (newQuantity !== null && !isNaN(newQuantity)) { updateStock(productId, warehouseId, parseInt(newQuantity, 10)); } }; if (loading) { return ( <Box display="flex" justifyContent="center" alignItems="center" minHeight="200px"> <CircularProgress /> <Typography variant="body1" sx={{ ml: 2 }}> 加载库存数据中... </Typography> </Box> ); } return ( <Paper elevation={3} sx={{ p: 3, mt: 3 }}> <Box display="flex" justifyContent="space-between" alignItems="center" mb={3}> <Typography variant="h5" component="h2"> 库存管理 </Typography> <Button variant="outlined" startIcon={<RefreshIcon />} onClick={fetchInventory} disabled={loading} > 刷新数据 </Button> </Box> {error && ( <Alert severity="error" sx={{ mb: 2 }}> {error} </Alert> )} <TableContainer> <Table> <TableHead> <TableRow> <TableCell>产品ID</TableCell> <TableCell>仓库ID</TableCell> <TableCell>当前库存</TableCell> <TableCell>安全库存</TableCell> <TableCell>最后更新</TableCell> <TableCell>操作</TableCell> </TableRow> </TableHead> <TableBody> {inventory.map((item) => ( <TableRow key={`${item.product_id}-${item.warehouse_id}`}> <TableCell>{item.product_id}</TableCell> <TableCell>{item.warehouse_id}</TableCell> <TableCell> <Box display="flex" alignItems="center"> <Typography variant="body1" sx={{ color: item.quantity <= item.safety_stock ? 'error.main' : 'inherit', fontWeight: item.quantity <= item.safety_stock ? 'bold' : 'normal' }} > {item.quantity} </Typography> {item.quantity <= item.safety_stock && ( <Typography variant="caption" color="error" sx={{ ml: 1 }}> (低于安全库存) </Typography> )} </Box> </TableCell> <TableCell>{item.safety_stock}</TableCell> <TableCell>{new Date(item.last_updated).toLocaleString()}</TableCell> <TableCell> <Button variant="outlined" size="small" onClick={() => handleQuantityChange( item.product_id, item.warehouse_id, item.quantity )} disabled={updating} > 调整库存 </Button> </TableCell> </TableRow> ))} </TableBody> </Table> </TableContainer> {inventory.length === 0 && !error && ( <Typography variant="body1" color="textSecondary" align="center" sx={{ py: 4 }}> 暂无库存数据 </Typography> )} </Paper> ); }; export default InventoryManager;
- // src/components/OrderProcessor.js import React, { useState } from 'react'; import { Box, Paper, Typography, Button, TextField, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Alert, Stepper, Step, StepLabel } from '@mui/material'; import axios from 'axios'; /** * 订单处理组件 * 处理新订单并分配库存 */ const OrderProcessor = () => { const [orderItems, setOrderItems] = useState([{ productId: '', quantity: 1 }]); const [processing, setProcessing] = useState(false); const [result, setResult] = useState(null); const [activeStep, setActiveStep] = useState(0); // 添加订单项 const addOrderItem = () => { setOrderItems([...orderItems, { productId: '', quantity: 1 }]); }; // 更新订单项 const updateOrderItem = (index, field, value) => { const updatedItems = [...orderItems]; updatedItems[index][field] = value; setOrderItems(updatedItems); }; // 移除订单项 const removeOrderItem = (index) => { if (orderItems.length > 1) { const updatedItems = orderItems.filter((_, i) => i !== index); setOrderItems(updatedItems); } }; // 提交订单处理 const processOrder = async () => { try { setProcessing(true); setActiveStep(1); // 发送订单到WordPress API const response = await axios.post( 'http://your-wordpress-site.com/wp-json/fsc/v1/orders/process', { items: orderItems.filter(item => item.productId && item.quantity > 0), timestamp: new Date().toISOString() } ); setResult(response.data); setActiveStep(2); } catch (error) { setResult({ success: false, message: '订单处理失败: ' + error.message }); setActiveStep(2); } finally { setProcessing(false); } }; // 重置表单 const resetForm = () => { setOrderItems([{ productId: '', quantity: 1 }]); setResult(null); setActiveStep(0); }; const steps = ['输入订单信息', '处理中', '完成']; return ( <Paper elevation={3} sx={{ p: 3, mt: 3 }}> <Typography variant="h5" component="h2" gutterBottom> 订单处理系统 </Typography> <Stepper activeStep={activeStep} sx={{ mb: 4 }}> {steps.map((label) => ( <Step key={label}> <StepLabel>{label}</StepLabel> </Step> ))} </Stepper> {activeStep === 0 && ( <> <Typography variant="h6" gutterBottom> 订单项目 </Typography> <TableContainer> <Table size="small"> <TableHead> <TableRow> <TableCell>产品ID</TableCell> <TableCell>数量</TableCell> <TableCell width="100">操作</TableCell> </TableRow> </TableHead> <TableBody> {orderItems.map((item, index) => ( <TableRow key={index}> <TableCell> <TextField size="small" value={item.productId} onChange={(e) => updateOrderItem(index, 'productId', e.target.value)} placeholder="输入产品ID" fullWidth /> </TableCell> <TableCell> <TextField size="small" type="number" value={item.quantity} onChange={(e) => updateOrderItem(index, 'quantity', parseInt(e.target.value) || 0)} inputProps={{ min: 1 }} /> </TableCell> <TableCell> <Button size="small" color="error" onClick={() => removeOrderItem(index)} disabled={orderItems.length <= 1} > 删除 </Button> </TableCell> </TableRow> ))} </TableBody> </Table> </TableContainer> <Box sx={{ mt: 2, display: 'flex', gap: 2 }}> <Button variant="outlined" onClick={addOrderItem}> 添加产品 </Button> <Button variant="contained" onClick={processOrder} disabled={processing || orderItems.every(item => !item.productId)} > 提交订单 </Button> </Box> </> )} {activeStep === 1 && ( <Box sx={{ textAlign: 'center', py: 4 }}> <Typography variant="h6" gutterBottom> 正在处理订单... </Typography> <Typography variant="body2" color="textSecondary"> 正在检查库存、分配资源并更新系统 </Typography> </Box> )} {activeStep === 2 && result && ( <Box> <Alert severity={result.success ? "success" : "error"} sx={{ mb: 3 }} > {result.message} </Alert> {result.success && result.allocated_items && ( <> <Typography variant="h6" gutterBottom> 分配结果 </Typography> <TableContainer> <Table size="small"> <TableHead> <TableRow> <TableCell>产品ID</TableCell> <TableCell>数量</TableCell> <TableCell>状态</TableCell> </TableRow> </TableHead> <TableBody> {result.allocated_items.map((item, index) => ( <TableRow key={index}> <TableCell>{item.productId}</TableCell> <TableCell>{item.quantity}</TableCell> <TableCell> <Typography variant="body2" color="success.main" sx={{ fontWeight: 'bold' }} > 已分配 </Typography> </TableCell> </TableRow> ))} </TableBody> </Table> </TableContainer> </> )} <Button variant="contained" onClick={resetForm} sx={{ mt: 3 }} > 处理新订单 </Button> </Box> )} </Paper> ); }; export default OrderProcessor;
- // src/App.js import React from 'react'; import { Container, Box, Typography, AppBar, Toolbar, CssBaseline, Grid, Paper } from '@mui/material'; import { Inventory as InventoryIcon, ShoppingCart as OrderIcon } from '@mui/icons-material'; import InventoryManager from './components/InventoryManager'; import OrderProcessor from './components/OrderProcessor'; import DemandForecast from './components/DemandForecast'; /** * 供应链管理仪表板主组件 * 集成所有供应链管理功能 */ function App() { return ( <> <CssBaseline /> <AppBar position="static"> <Toolbar> <InventoryIcon sx={{ mr: 2 }} /> <Typography variant="h6" component="div" sx={{ flexGrow: 1 }}> 柔性供应链管理系统 </Typography> </Toolbar> </AppBar> <Container maxWidth="lg" sx={{ mt: 4, mb: 4 }}> <Grid container spacing={3}> {/* 概览卡片 */} <Grid item xs={12} md={4}> <Paper sx={{ p: 2, display: 'flex', flexDirection: 'column', height: 140 }}> <Typography variant="h6" gutterBottom> 库存概览 </Typography> <Box sx={{ flexGrow: 1, display: 'flex', alignItems: 'center', justifyContent: 'center' }}> <Typography variant="h3" color="primary"> 1,248 </Typography> <Typography variant="body2" color="textSecondary" sx={{ ml: 1 }}> 个SKU </Typography> </Box> <Typography variant="caption" color="textSecondary"> 实时更新 </Typography> </Paper> </Grid> <Grid item xs={12} md={4}> <Paper sx={{ p: 2, display: 'flex', flexDirection: 'column', height: 140 }}> <Typography variant="h6" gutterBottom> 今日订单 </Typography> <Box sx={{ flexGrow: 1, display: 'flex', alignItems: 'center', justifyContent: 'center' }}> <Typography variant="h3" color="secondary"> 42 </Typography> <Typography variant="body2" color="textSecondary" sx={{ ml: 1 }}> 笔订单 </Typography> </Box> <Typography variant="caption" color="textSecondary"> 待处理: 3笔 </Typography> </Paper> </Grid> <Grid item xs={12} md={4}> <Paper sx={{ p: 2, display: 'flex', flexDirection: 'column', height: 140 }}> <Typography variant="h6" gutterBottom> 供应商状态 </Typography> <Box sx={{ flexGrow: 1, display: 'flex', alignItems: 'center', justifyContent: 'center' }}> <Typography variant="h3" color="success.main"> 15 </Typography> <Typography variant="body2" color="textSecondary" sx={{ ml: 1 }}> 个活跃供应商 </Typography> </Box> <Typography variant="caption" color="textSecondary"> 全部正常 </Typography> </Paper> </Grid> {/* 主要功能区域 */} <Grid item xs={12}> <InventoryManager /> </Grid> <Grid item xs={12} md={6}> <OrderProcessor /> </Grid> <Grid item xs={12} md={6}> <DemandForecast /> </Grid> </Grid> </Container> </> ); } export default App;
-
- 由于前端运行在不同端口,需要配置WordPress允许跨域请求: // 在插件中添加CORS支持 add_action('rest_api_init', function() { remove_filter('rest_pre_serve_request', 'rest_send_cors_headers'); add_filter('rest_pre_serve_request', function($value) { header('Access-Control-Allow-Origin: http://localhost:3000'); // 前端开发地址 header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS'); header('Access-Control-Allow-Credentials: true'); header('Access-Control-Allow-Headers: Authorization, Content-Type'); return $value; }); }, 15);
- // src/services/api.js import axios from 'axios'; // 创建axios实例 const api = axios.create({ baseURL: 'http://your-wordpress-site.com/wp-json', timeout: 10000, }); // 请求拦截器 - 添加认证头 api.interceptors.request.use( (config) => { // 从localStorage获取token const token = localStorage.getItem('wp_token'); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }, (error) => { return Promise.reject(error); } ); // 响应拦截器 - 处理错误 api.interceptors.response.use( (response) => response, (error) => { if (error.response?.status === 401) { // 处理未授权 localStorage.removeItem('wp_token'); window.location.href = '/login'; } return Promise.reject(error); } ); // 登录函数 export const login = async (username, password) => { try { const response = await axios.post( 'http://your-wordpress-site.com/wp-json/jwt-auth/v1/token', { username, password, } ); if (response.data.token) { localStorage.setItem('wp_token', response.data.token); return { success: true, data: response.data }; } } catch (error) { return { success: false, error: error.response?.data?.message || '登录失败' }; } }; export default api;
-
- 前端构建: npm run build WordPress集成: 将构建的React应用放入WordPress主题或插件目录 创建短代码或页面模板来加载React应用 // 创建短代码加载React应用 add_shortcode('supply_chain_dashboard', function() { ob_start(); ?> <div id="supply-chain-root"></div> <script> window.wpApiSettings = { root: '<?php echo esc_url_raw(rest_url()); ?>', nonce: '<?php echo wp_create_nonce('wp_rest'); ?>' }; </script> <?php return ob_get_clean(); });
- API缓存: // 添加REST API缓存 add_filter('rest_prepare_supply_product', function($response, $post, $request) { $response->header('Cache-Control', 'max-age=300, must-revalidate'); return $response; }, 10, 3); 前端代码分割: // 使用React.lazy进行代码分割 const DemandForecast = React.lazy(() => import('./components/DemandForecast'));
- 通过本教程,您已经学会了如何开发一个基于WordPress的柔性供应链管理系统的前后端分离架构。这种架构的优势在于: 前后端独立开发:前端团队可以使用现代JavaScript框架,后端团队专注于API和业务逻辑 更好的用户体验:React提供快速、响应式的用户界面 可扩展性:可以轻松添加新功能模块 复用性:API可以被多个客户端使用(Web、移动应用等)
在当今快速变化的商业环境中,柔性供应链管理系统需要具备高度的灵活性和可扩展性。传统的WordPress主题开发模式将前后端逻辑紧密耦合,难以应对复杂业务需求的变化。前后端分离架构通过将用户界面与业务逻辑分离,使前端专注于展示和交互,后端专注于数据处理和API提供,大大提升了系统的可维护性和开发效率。
本教程将指导您如何为WordPress开发一个柔性供应链管理软件,采用现代的前后端分离技术栈:前端使用React,后端使用WordPress REST API,并通过自定义插件扩展供应链管理功能。
首先,确保您的开发环境满足以下要求:
- 本地服务器环境:推荐使用XAMPP、MAMP或Local by Flywheel
- WordPress安装:最新版本的WordPress(5.8+)
- Node.js环境:Node.js 14+ 和 npm/yarn
- 代码编辑器:VS Code、Sublime Text或PHPStorm
-
前端:React + Axios + Material-UI
- React提供组件化开发,便于构建复杂UI
- Axios简化HTTP请求处理
- Material-UI提供美观的UI组件,加速开发
-
后端:WordPress REST API + 自定义插件
- 利用WordPress成熟的用户管理和权限系统
- 通过自定义插件扩展供应链管理功能
- REST API提供标准化的数据接口
前端:React + Axios + Material-UI
- React提供组件化开发,便于构建复杂UI
- Axios简化HTTP请求处理
- Material-UI提供美观的UI组件,加速开发
后端:WordPress REST API + 自定义插件
- 利用WordPress成熟的用户管理和权限系统
- 通过自定义插件扩展供应链管理功能
- REST API提供标准化的数据接口
首先,在WordPress的wp-content/plugins目录下创建插件文件夹flexible-supply-chain,并创建主文件:
<?php
/**
* Plugin Name: 柔性供应链管理系统
* Plugin URI: https://yourwebsite.com/
* Description: 为WordPress提供柔性供应链管理功能的插件
* Version: 1.0.0
* Author: 您的名称
* License: GPL v2 or later
* Text Domain: flexible-supply-chain
*/
// 防止直接访问
if (!defined('ABSPATH')) {
exit;
}
// 定义插件常量
define('FSC_VERSION', '1.0.0');
define('FSC_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('FSC_PLUGIN_URL', plugin_dir_url(__FILE__));
// 初始化插件
class FlexibleSupplyChain {
public function __construct() {
// 注册激活和停用钩子
register_activation_hook(__FILE__, array($this, 'activate'));
register_deactivation_hook(__FILE__, array($this, 'deactivate'));
// 初始化插件功能
add_action('init', array($this, 'init'));
}
// 插件激活时执行
public function activate() {
// 创建必要的数据库表
$this->create_tables();
// 刷新重写规则
flush_rewrite_rules();
}
// 插件停用时执行
public function deactivate() {
// 清理临时数据
flush_rewrite_rules();
}
// 初始化插件
public function init() {
// 注册自定义文章类型
$this->register_post_types();
// 注册REST API路由
add_action('rest_api_init', array($this, 'register_rest_routes'));
// 加载文本域
load_plugin_textdomain('flexible-supply-chain', false, dirname(plugin_basename(__FILE__)) . '/languages');
}
// 创建数据库表
private function create_tables() {
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
$table_name = $wpdb->prefix . 'supply_chain_inventory';
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
product_id bigint(20) NOT NULL,
warehouse_id mediumint(9) NOT NULL,
quantity int(11) NOT NULL DEFAULT 0,
safety_stock int(11) NOT NULL DEFAULT 10,
last_updated datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY product_id (product_id),
KEY warehouse_id (warehouse_id)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}
// 注册自定义文章类型
private function register_post_types() {
// 产品自定义文章类型
register_post_type('supply_product',
array(
'labels' => array(
'name' => __('产品', 'flexible-supply-chain'),
'singular_name' => __('产品', 'flexible-supply-chain')
),
'public' => true,
'has_archive' => true,
'supports' => array('title', 'editor', 'thumbnail', 'custom-fields'),
'show_in_rest' => true, // 启用REST API支持
'rest_base' => 'supply-products',
'menu_icon' => 'dashicons-products'
)
);
// 供应商自定义文章类型
register_post_type('supply_vendor',
array(
'labels' => array(
'name' => __('供应商', 'flexible-supply-chain'),
'singular_name' => __('供应商', 'flexible-supply-chain')
),
'public' => true,
'has_archive' => true,
'supports' => array('title', 'editor', 'thumbnail'),
'show_in_rest' => true,
'rest_base' => 'supply-vendors',
'menu_icon' => 'dashicons-businessperson'
)
);
}
// 注册REST API路由
public function register_rest_routes() {
// 库存管理API
register_rest_route('fsc/v1', '/inventory/(?P<id>d+)', array(
'methods' => 'GET',
'callback' => array($this, 'get_inventory'),
'permission_callback' => array($this, 'check_permissions')
));
register_rest_route('fsc/v1', '/inventory', array(
'methods' => 'POST',
'callback' => array($this, 'update_inventory'),
'permission_callback' => array($this, 'check_permissions')
));
// 订单处理API
register_rest_route('fsc/v1', '/orders/process', array(
'methods' => 'POST',
'callback' => array($this, 'process_order'),
'permission_callback' => array($this, 'check_permissions')
));
}
// 获取库存信息
public function get_inventory($request) {
global $wpdb;
$product_id = $request['id'];
$table_name = $wpdb->prefix . 'supply_chain_inventory';
$results = $wpdb->get_results(
$wpdb->prepare(
"SELECT * FROM $table_name WHERE product_id = %d",
$product_id
)
);
return rest_ensure_response($results);
}
// 更新库存
public function update_inventory($request) {
global $wpdb;
$parameters = $request->get_json_params();
$product_id = $parameters['product_id'];
$warehouse_id = $parameters['warehouse_id'];
$quantity = $parameters['quantity'];
$table_name = $wpdb->prefix . 'supply_chain_inventory';
// 检查记录是否存在
$existing = $wpdb->get_var(
$wpdb->prepare(
"SELECT id FROM $table_name WHERE product_id = %d AND warehouse_id = %d",
$product_id, $warehouse_id
)
);
if ($existing) {
// 更新现有记录
$result = $wpdb->update(
$table_name,
array('quantity' => $quantity),
array('id' => $existing),
array('%d'),
array('%d')
);
} else {
// 插入新记录
$result = $wpdb->insert(
$table_name,
array(
'product_id' => $product_id,
'warehouse_id' => $warehouse_id,
'quantity' => $quantity
),
array('%d', '%d', '%d')
);
}
if ($result === false) {
return new WP_Error('db_error', '数据库操作失败', array('status' => 500));
}
return rest_ensure_response(array(
'success' => true,
'message' => '库存更新成功'
));
}
// 处理订单
public function process_order($request) {
$parameters = $request->get_json_params();
$order_items = $parameters['items'];
// 这里实现订单处理逻辑
// 包括库存检查、分配、更新等
$response = array(
'success' => true,
'message' => '订单处理完成',
'allocated_items' => $order_items
);
return rest_ensure_response($response);
}
// 权限检查
public function check_permissions($request) {
// 检查用户是否登录并具有适当权限
return current_user_can('manage_options');
}
}
// 初始化插件
new FlexibleSupplyChain();
?>
供应链管理系统需要高效的数据存储结构。除了上述库存表,您可能还需要创建以下表:
- 订单表:存储客户订单信息
- 物流表:跟踪货物运输状态
- 需求预测表:存储销售预测数据
使用Create React App快速初始化前端项目:
npx create-react-app supply-chain-frontend
cd supply-chain-frontend
npm install axios @mui/material @emotion/react @emotion/styled @mui/icons-material
// src/components/InventoryManager.js
import React, { useState, useEffect } from 'react';
import {
Box,
Paper,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Typography,
Button,
TextField,
Alert,
CircularProgress
} from '@mui/material';
import { Refresh as RefreshIcon } from '@mui/icons-material';
import axios from 'axios';
/**
* 库存管理组件
* 显示和管理产品库存信息
*/
const InventoryManager = () => {
const [inventory, setInventory] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [updating, setUpdating] = useState(false);
// 从WordPress REST API获取库存数据
const fetchInventory = async () => {
try {
setLoading(true);
// 注意:这里需要替换为您的WordPress站点URL
const response = await axios.get('http://your-wordpress-site.com/wp-json/fsc/v1/inventory/1');
setInventory(response.data);
setError(null);
} catch (err) {
setError('获取库存数据失败: ' + err.message);
console.error('库存数据获取错误:', err);
} finally {
setLoading(false);
}
};
// 组件加载时获取数据
useEffect(() => {
fetchInventory();
}, []);
// 更新库存数量
const updateStock = async (productId, warehouseId, newQuantity) => {
try {
setUpdating(true);
await axios.post('http://your-wordpress-site.com/wp-json/fsc/v1/inventory', {
product_id: productId,
warehouse_id: warehouseId,
quantity: newQuantity
});
// 更新本地状态
setInventory(prev => prev.map(item =>
item.product_id === productId && item.warehouse_id === warehouseId
? { ...item, quantity: newQuantity }
: item
));
alert('库存更新成功!');
} catch (err) {
alert('库存更新失败: ' + err.message);
console.error('库存更新错误:', err);
} finally {
setUpdating(false);
}
};
// 处理库存数量变化
const handleQuantityChange = (productId, warehouseId, currentQuantity) => {
const newQuantity = prompt('请输入新的库存数量:', currentQuantity);
if (newQuantity !== null && !isNaN(newQuantity)) {
updateStock(productId, warehouseId, parseInt(newQuantity, 10));
}
};
if (loading) {
return (
<Box display="flex" justifyContent="center" alignItems="center" minHeight="200px">
<CircularProgress />
<Typography variant="body1" sx={{ ml: 2 }}>
加载库存数据中...
</Typography>
</Box>
);
}
return (
<Paper elevation={3} sx={{ p: 3, mt: 3 }}>
<Box display="flex" justifyContent="space-between" alignItems="center" mb={3}>
<Typography variant="h5" component="h2">
库存管理
</Typography>
<Button
variant="outlined"
startIcon={<RefreshIcon />}
onClick={fetchInventory}
disabled={loading}
>
刷新数据
</Button>
</Box>
{error && (
<Alert severity="error" sx={{ mb: 2 }}>
{error}
</Alert>
)}
<TableContainer>
<Table>
<TableHead>
<TableRow>
<TableCell>产品ID</TableCell>
<TableCell>仓库ID</TableCell>
<TableCell>当前库存</TableCell>
<TableCell>安全库存</TableCell>
<TableCell>最后更新</TableCell>
<TableCell>操作</TableCell>
</TableRow>
</TableHead>
<TableBody>
{inventory.map((item) => (
<TableRow key={`${item.product_id}-${item.warehouse_id}`}>
<TableCell>{item.product_id}</TableCell>
<TableCell>{item.warehouse_id}</TableCell>
<TableCell>
<Box display="flex" alignItems="center">
<Typography
variant="body1"
sx={{
color: item.quantity <= item.safety_stock ? 'error.main' : 'inherit',
fontWeight: item.quantity <= item.safety_stock ? 'bold' : 'normal'
}}
>
{item.quantity}
</Typography>
{item.quantity <= item.safety_stock && (
<Typography variant="caption" color="error" sx={{ ml: 1 }}>
(低于安全库存)
</Typography>
)}
</Box>
</TableCell>
<TableCell>{item.safety_stock}</TableCell>
<TableCell>{new Date(item.last_updated).toLocaleString()}</TableCell>
<TableCell>
<Button
variant="outlined"
size="small"
onClick={() => handleQuantityChange(
item.product_id,
item.warehouse_id,
item.quantity
)}
disabled={updating}
>
调整库存
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
{inventory.length === 0 && !error && (
<Typography variant="body1" color="textSecondary" align="center" sx={{ py: 4 }}>
暂无库存数据
</Typography>
)}
</Paper>
);
};
export default InventoryManager;
// src/components/InventoryManager.js
import React, { useState, useEffect } from 'react';
import {
Box,
Paper,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Typography,
Button,
TextField,
Alert,
CircularProgress
} from '@mui/material';
import { Refresh as RefreshIcon } from '@mui/icons-material';
import axios from 'axios';
/**
* 库存管理组件
* 显示和管理产品库存信息
*/
const InventoryManager = () => {
const [inventory, setInventory] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [updating, setUpdating] = useState(false);
// 从WordPress REST API获取库存数据
const fetchInventory = async () => {
try {
setLoading(true);
// 注意:这里需要替换为您的WordPress站点URL
const response = await axios.get('http://your-wordpress-site.com/wp-json/fsc/v1/inventory/1');
setInventory(response.data);
setError(null);
} catch (err) {
setError('获取库存数据失败: ' + err.message);
console.error('库存数据获取错误:', err);
} finally {
setLoading(false);
}
};
// 组件加载时获取数据
useEffect(() => {
fetchInventory();
}, []);
// 更新库存数量
const updateStock = async (productId, warehouseId, newQuantity) => {
try {
setUpdating(true);
await axios.post('http://your-wordpress-site.com/wp-json/fsc/v1/inventory', {
product_id: productId,
warehouse_id: warehouseId,
quantity: newQuantity
});
// 更新本地状态
setInventory(prev => prev.map(item =>
item.product_id === productId && item.warehouse_id === warehouseId
? { ...item, quantity: newQuantity }
: item
));
alert('库存更新成功!');
} catch (err) {
alert('库存更新失败: ' + err.message);
console.error('库存更新错误:', err);
} finally {
setUpdating(false);
}
};
// 处理库存数量变化
const handleQuantityChange = (productId, warehouseId, currentQuantity) => {
const newQuantity = prompt('请输入新的库存数量:', currentQuantity);
if (newQuantity !== null && !isNaN(newQuantity)) {
updateStock(productId, warehouseId, parseInt(newQuantity, 10));
}
};
if (loading) {
return (
<Box display="flex" justifyContent="center" alignItems="center" minHeight="200px">
<CircularProgress />
<Typography variant="body1" sx={{ ml: 2 }}>
加载库存数据中...
</Typography>
</Box>
);
}
return (
<Paper elevation={3} sx={{ p: 3, mt: 3 }}>
<Box display="flex" justifyContent="space-between" alignItems="center" mb={3}>
<Typography variant="h5" component="h2">
库存管理
</Typography>
<Button
variant="outlined"
startIcon={<RefreshIcon />}
onClick={fetchInventory}
disabled={loading}
>
刷新数据
</Button>
</Box>
{error && (
<Alert severity="error" sx={{ mb: 2 }}>
{error}
</Alert>
)}
<TableContainer>
<Table>
<TableHead>
<TableRow>
<TableCell>产品ID</TableCell>
<TableCell>仓库ID</TableCell>
<TableCell>当前库存</TableCell>
<TableCell>安全库存</TableCell>
<TableCell>最后更新</TableCell>
<TableCell>操作</TableCell>
</TableRow>
</TableHead>
<TableBody>
{inventory.map((item) => (
<TableRow key={`${item.product_id}-${item.warehouse_id}`}>
<TableCell>{item.product_id}</TableCell>
<TableCell>{item.warehouse_id}</TableCell>
<TableCell>
<Box display="flex" alignItems="center">
<Typography
variant="body1"
sx={{
color: item.quantity <= item.safety_stock ? 'error.main' : 'inherit',
fontWeight: item.quantity <= item.safety_stock ? 'bold' : 'normal'
}}
>
{item.quantity}
</Typography>
{item.quantity <= item.safety_stock && (
<Typography variant="caption" color="error" sx={{ ml: 1 }}>
(低于安全库存)
</Typography>
)}
</Box>
</TableCell>
<TableCell>{item.safety_stock}</TableCell>
<TableCell>{new Date(item.last_updated).toLocaleString()}</TableCell>
<TableCell>
<Button
variant="outlined"
size="small"
onClick={() => handleQuantityChange(
item.product_id,
item.warehouse_id,
item.quantity
)}
disabled={updating}
>
调整库存
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
{inventory.length === 0 && !error && (
<Typography variant="body1" color="textSecondary" align="center" sx={{ py: 4 }}>
暂无库存数据
</Typography>
)}
</Paper>
);
};
export default InventoryManager;
// src/components/OrderProcessor.js
import React, { useState } from 'react';
import {
Box,
Paper,
Typography,
Button,
TextField,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Alert,
Stepper,
Step,
StepLabel
} from '@mui/material';
import axios from 'axios';
/**
* 订单处理组件
* 处理新订单并分配库存
*/
const OrderProcessor = () => {
const [orderItems, setOrderItems] = useState([{ productId: '', quantity: 1 }]);
const [processing, setProcessing] = useState(false);
const [result, setResult] = useState(null);
const [activeStep, setActiveStep] = useState(0);
// 添加订单项
const addOrderItem = () => {
setOrderItems([...orderItems, { productId: '', quantity: 1 }]);
};
// 更新订单项
const updateOrderItem = (index, field, value) => {
const updatedItems = [...orderItems];
updatedItems[index][field] = value;
setOrderItems(updatedItems);
};
// 移除订单项
const removeOrderItem = (index) => {
if (orderItems.length > 1) {
const updatedItems = orderItems.filter((_, i) => i !== index);
setOrderItems(updatedItems);
}
};
// 提交订单处理
const processOrder = async () => {
try {
setProcessing(true);
setActiveStep(1);
// 发送订单到WordPress API
const response = await axios.post(
'http://your-wordpress-site.com/wp-json/fsc/v1/orders/process',
{
items: orderItems.filter(item => item.productId && item.quantity > 0),
timestamp: new Date().toISOString()
}
);
setResult(response.data);
setActiveStep(2);
} catch (error) {
setResult({
success: false,
message: '订单处理失败: ' + error.message
});
setActiveStep(2);
} finally {
setProcessing(false);
}
};
// 重置表单
const resetForm = () => {
setOrderItems([{ productId: '', quantity: 1 }]);
setResult(null);
setActiveStep(0);
};
const steps = ['输入订单信息', '处理中', '完成'];
return (
<Paper elevation={3} sx={{ p: 3, mt: 3 }}>
<Typography variant="h5" component="h2" gutterBottom>
订单处理系统
</Typography>
<Stepper activeStep={activeStep} sx={{ mb: 4 }}>
{steps.map((label) => (
<Step key={label}>
<StepLabel>{label}</StepLabel>
</Step>
))}
</Stepper>
{activeStep === 0 && (
<>
<Typography variant="h6" gutterBottom>
订单项目
</Typography>
<TableContainer>
<Table size="small">
<TableHead>
<TableRow>
<TableCell>产品ID</TableCell>
<TableCell>数量</TableCell>
<TableCell width="100">操作</TableCell>
</TableRow>
</TableHead>
<TableBody>
{orderItems.map((item, index) => (
<TableRow key={index}>
<TableCell>
<TextField
size="small"
value={item.productId}
onChange={(e) => updateOrderItem(index, 'productId', e.target.value)}
placeholder="输入产品ID"
fullWidth
/>
</TableCell>
<TableCell>
<TextField
size="small"
type="number"
value={item.quantity}
onChange={(e) => updateOrderItem(index, 'quantity', parseInt(e.target.value) || 0)}
inputProps={{ min: 1 }}
/>
</TableCell>
<TableCell>
<Button
size="small"
color="error"
onClick={() => removeOrderItem(index)}
disabled={orderItems.length <= 1}
>
删除
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
<Box sx={{ mt: 2, display: 'flex', gap: 2 }}>
<Button variant="outlined" onClick={addOrderItem}>
添加产品
</Button>
<Button
variant="contained"
onClick={processOrder}
disabled={processing || orderItems.every(item => !item.productId)}
>
提交订单
</Button>
</Box>
</>
)}
{activeStep === 1 && (
<Box sx={{ textAlign: 'center', py: 4 }}>
<Typography variant="h6" gutterBottom>
正在处理订单...
</Typography>
<Typography variant="body2" color="textSecondary">
正在检查库存、分配资源并更新系统
</Typography>
</Box>
)}
{activeStep === 2 && result && (
<Box>
<Alert
severity={result.success ? "success" : "error"}
sx={{ mb: 3 }}
>
{result.message}
</Alert>
{result.success && result.allocated_items && (
<>
<Typography variant="h6" gutterBottom>
分配结果
</Typography>
<TableContainer>
<Table size="small">
<TableHead>
<TableRow>
<TableCell>产品ID</TableCell>
<TableCell>数量</TableCell>
<TableCell>状态</TableCell>
</TableRow>
</TableHead>
<TableBody>
{result.allocated_items.map((item, index) => (
<TableRow key={index}>
<TableCell>{item.productId}</TableCell>
<TableCell>{item.quantity}</TableCell>
<TableCell>
<Typography
variant="body2"
color="success.main"
sx={{ fontWeight: 'bold' }}
>
已分配
</Typography>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</>
)}
<Button
variant="contained"
onClick={resetForm}
sx={{ mt: 3 }}
>
处理新订单
</Button>
</Box>
)}
</Paper>
);
};
export default OrderProcessor;
// src/components/OrderProcessor.js
import React, { useState } from 'react';
import {
Box,
Paper,
Typography,
Button,
TextField,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Alert,
Stepper,
Step,
StepLabel
} from '@mui/material';
import axios from 'axios';
/**
* 订单处理组件
* 处理新订单并分配库存
*/
const OrderProcessor = () => {
const [orderItems, setOrderItems] = useState([{ productId: '', quantity: 1 }]);
const [processing, setProcessing] = useState(false);
const [result, setResult] = useState(null);
const [activeStep, setActiveStep] = useState(0);
// 添加订单项
const addOrderItem = () => {
setOrderItems([...orderItems, { productId: '', quantity: 1 }]);
};
// 更新订单项
const updateOrderItem = (index, field, value) => {
const updatedItems = [...orderItems];
updatedItems[index][field] = value;
setOrderItems(updatedItems);
};
// 移除订单项
const removeOrderItem = (index) => {
if (orderItems.length > 1) {
const updatedItems = orderItems.filter((_, i) => i !== index);
setOrderItems(updatedItems);
}
};
// 提交订单处理
const processOrder = async () => {
try {
setProcessing(true);
setActiveStep(1);
// 发送订单到WordPress API
const response = await axios.post(
'http://your-wordpress-site.com/wp-json/fsc/v1/orders/process',
{
items: orderItems.filter(item => item.productId && item.quantity > 0),
timestamp: new Date().toISOString()
}
);
setResult(response.data);
setActiveStep(2);
} catch (error) {
setResult({
success: false,
message: '订单处理失败: ' + error.message
});
setActiveStep(2);
} finally {
setProcessing(false);
}
};
// 重置表单
const resetForm = () => {
setOrderItems([{ productId: '', quantity: 1 }]);
setResult(null);
setActiveStep(0);
};
const steps = ['输入订单信息', '处理中', '完成'];
return (
<Paper elevation={3} sx={{ p: 3, mt: 3 }}>
<Typography variant="h5" component="h2" gutterBottom>
订单处理系统
</Typography>
<Stepper activeStep={activeStep} sx={{ mb: 4 }}>
{steps.map((label) => (
<Step key={label}>
<StepLabel>{label}</StepLabel>
</Step>
))}
</Stepper>
{activeStep === 0 && (
<>
<Typography variant="h6" gutterBottom>
订单项目
</Typography>
<TableContainer>
<Table size="small">
<TableHead>
<TableRow>
<TableCell>产品ID</TableCell>
<TableCell>数量</TableCell>
<TableCell width="100">操作</TableCell>
</TableRow>
</TableHead>
<TableBody>
{orderItems.map((item, index) => (
<TableRow key={index}>
<TableCell>
<TextField
size="small"
value={item.productId}
onChange={(e) => updateOrderItem(index, 'productId', e.target.value)}
placeholder="输入产品ID"
fullWidth
/>
</TableCell>
<TableCell>
<TextField
size="small"
type="number"
value={item.quantity}
onChange={(e) => updateOrderItem(index, 'quantity', parseInt(e.target.value) || 0)}
inputProps={{ min: 1 }}
/>
</TableCell>
<TableCell>
<Button
size="small"
color="error"
onClick={() => removeOrderItem(index)}
disabled={orderItems.length <= 1}
>
删除
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
<Box sx={{ mt: 2, display: 'flex', gap: 2 }}>
<Button variant="outlined" onClick={addOrderItem}>
添加产品
</Button>
<Button
variant="contained"
onClick={processOrder}
disabled={processing || orderItems.every(item => !item.productId)}
>
提交订单
</Button>
</Box>
</>
)}
{activeStep === 1 && (
<Box sx={{ textAlign: 'center', py: 4 }}>
<Typography variant="h6" gutterBottom>
正在处理订单...
</Typography>
<Typography variant="body2" color="textSecondary">
正在检查库存、分配资源并更新系统
</Typography>
</Box>
)}
{activeStep === 2 && result && (
<Box>
<Alert
severity={result.success ? "success" : "error"}
sx={{ mb: 3 }}
>
{result.message}
</Alert>
{result.success && result.allocated_items && (
<>
<Typography variant="h6" gutterBottom>
分配结果
</Typography>
<TableContainer>
<Table size="small">
<TableHead>
<TableRow>
<TableCell>产品ID</TableCell>
<TableCell>数量</TableCell>
<TableCell>状态</TableCell>
</TableRow>
</TableHead>
<TableBody>
{result.allocated_items.map((item, index) => (
<TableRow key={index}>
<TableCell>{item.productId}</TableCell>
<TableCell>{item.quantity}</TableCell>
<TableCell>
<Typography
variant="body2"
color="success.main"
sx={{ fontWeight: 'bold' }}
>
已分配
</Typography>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</>
)}
<Button
variant="contained"
onClick={resetForm}
sx={{ mt: 3 }}
>
处理新订单
</Button>
</Box>
)}
</Paper>
);
};
export default OrderProcessor;
// src/App.js
import React from 'react';
import {
Container,
Box,
Typography,
AppBar,
Toolbar,
CssBaseline,
Grid,
Paper
} from '@mui/material';
import { Inventory as InventoryIcon, ShoppingCart as OrderIcon } from '@mui/icons-material';
import InventoryManager from './components/InventoryManager';
import OrderProcessor from './components/OrderProcessor';
import DemandForecast from './components/DemandForecast';
/**
* 供应链管理仪表板主组件
* 集成所有供应链管理功能
*/
function App() {
return (
<>
<CssBaseline />
<AppBar position="static">
<Toolbar>
<InventoryIcon sx={{ mr: 2 }} />
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
柔性供应链管理系统
</Typography>
</Toolbar>
</AppBar>
<Container maxWidth="lg" sx={{ mt: 4, mb: 4 }}>
<Grid container spacing={3}>
{/* 概览卡片 */}
<Grid item xs={12} md={4}>
<Paper sx={{ p: 2, display: 'flex', flexDirection: 'column', height: 140 }}>
<Typography variant="h6" gutterBottom>
库存概览
</Typography>
<Box sx={{ flexGrow: 1, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<Typography variant="h3" color="primary">
1,248
</Typography>
<Typography variant="body2" color="textSecondary" sx={{ ml: 1 }}>
个SKU
</Typography>
</Box>
<Typography variant="caption" color="textSecondary">
实时更新
</Typography>
</Paper>
</Grid>
<Grid item xs={12} md={4}>
<Paper sx={{ p: 2, display: 'flex', flexDirection: 'column', height: 140 }}>
<Typography variant="h6" gutterBottom>
今日订单
</Typography>
<Box sx={{ flexGrow: 1, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<Typography variant="h3" color="secondary">
42
</Typography>
<Typography variant="body2" color="textSecondary" sx={{ ml: 1 }}>
笔订单
</Typography>
</Box>
<Typography variant="caption" color="textSecondary">
待处理: 3笔
</Typography>
</Paper>
</Grid>
<Grid item xs={12} md={4}>
<Paper sx={{ p: 2, display: 'flex', flexDirection: 'column', height: 140 }}>
<Typography variant="h6" gutterBottom>
供应商状态
</Typography>
<Box sx={{ flexGrow: 1, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<Typography variant="h3" color="success.main">
15
</Typography>
<Typography variant="body2" color="textSecondary" sx={{ ml: 1 }}>
个活跃供应商
</Typography>
</Box>
<Typography variant="caption" color="textSecondary">
全部正常
</Typography>
</Paper>
</Grid>
{/* 主要功能区域 */}
<Grid item xs={12}>
<InventoryManager />
</Grid>
<Grid item xs={12} md={6}>
<OrderProcessor />
</Grid>
<Grid item xs={12} md={6}>
<DemandForecast />
</Grid>
</Grid>
</Container>
</>
);
}
export default App;
// src/App.js
import React from 'react';
import {
Container,
Box,
Typography,
AppBar,
Toolbar,
CssBaseline,
Grid,
Paper
} from '@mui/material';
import { Inventory as InventoryIcon, ShoppingCart as OrderIcon } from '@mui/icons-material';
import InventoryManager from './components/InventoryManager';
import OrderProcessor from './components/OrderProcessor';
import DemandForecast from './components/DemandForecast';
/**
* 供应链管理仪表板主组件
* 集成所有供应链管理功能
*/
function App() {
return (
<>
<CssBaseline />
<AppBar position="static">
<Toolbar>
<InventoryIcon sx={{ mr: 2 }} />
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
柔性供应链管理系统
</Typography>
</Toolbar>
</AppBar>
<Container maxWidth="lg" sx={{ mt: 4, mb: 4 }}>
<Grid container spacing={3}>
{/* 概览卡片 */}
<Grid item xs={12} md={4}>
<Paper sx={{ p: 2, display: 'flex', flexDirection: 'column', height: 140 }}>
<Typography variant="h6" gutterBottom>
库存概览
</Typography>
<Box sx={{ flexGrow: 1, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<Typography variant="h3" color="primary">
1,248
</Typography>
<Typography variant="body2" color="textSecondary" sx={{ ml: 1 }}>
个SKU
</Typography>
</Box>
<Typography variant="caption" color="textSecondary">
实时更新
</Typography>
</Paper>
</Grid>
<Grid item xs={12} md={4}>
<Paper sx={{ p: 2, display: 'flex', flexDirection: 'column', height: 140 }}>
<Typography variant="h6" gutterBottom>
今日订单
</Typography>
<Box sx={{ flexGrow: 1, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<Typography variant="h3" color="secondary">
42
</Typography>
<Typography variant="body2" color="textSecondary" sx={{ ml: 1 }}>
笔订单
</Typography>
</Box>
<Typography variant="caption" color="textSecondary">
待处理: 3笔
</Typography>
</Paper>
</Grid>
<Grid item xs={12} md={4}>
<Paper sx={{ p: 2, display: 'flex', flexDirection: 'column', height: 140 }}>
<Typography variant="h6" gutterBottom>
供应商状态
</Typography>
<Box sx={{ flexGrow: 1, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<Typography variant="h3" color="success.main">
15
</Typography>
<Typography variant="body2" color="textSecondary" sx={{ ml: 1 }}>
个活跃供应商
</Typography>
</Box>
<Typography variant="caption" color="textSecondary">
全部正常
</Typography>
</Paper>
</Grid>
{/* 主要功能区域 */}
<Grid item xs={12}>
<InventoryManager />
</Grid>
<Grid item xs={12} md={6}>
<OrderProcessor />
</Grid>
<Grid item xs={12} md={6}>
<DemandForecast />
</Grid>
</Grid>
</Container>
</>
);
}
export default App;
由于前端运行在不同端口,需要配置WordPress允许跨域请求:
// 在插件中添加CORS支持
add_action('rest_api_init', function() {
remove_filter('rest_pre_serve_request', 'rest_send_cors_headers');
add_filter('rest_pre_serve_request', function($value) {
header('Access-Control-Allow-Origin: http://localhost:3000'); // 前端开发地址
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Headers: Authorization, Content-Type');
return $value;
});
}, 15);
// src/services/api.js
import axios from 'axios';
// 创建axios实例
const api = axios.create({
baseURL: 'http://your-wordpress-site.com/wp-json',
timeout: 10000,
});
// 请求拦截器 - 添加认证头
api.interceptors.request.use(
(config) => {
// 从localStorage获取token
const token = localStorage.getItem('wp_token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
// 响应拦截器 - 处理错误
api.interceptors.response.use(
(response) => response,
(error) => {
if (error.response?.status === 401) {
// 处理未授权
localStorage.removeItem('wp_token');
window.location.href = '/login';
}
return Promise.reject(error);
}
);
// 登录函数
export const login = async (username, password) => {
try {
const response = await axios.post(
'http://your-wordpress-site.com/wp-json/jwt-auth/v1/token',
{
username,
password,
}
);
if (response.data.token) {
localStorage.setItem('wp_token', response.data.token);
return { success: true, data: response.data };
}
} catch (error) {
return {
success: false,
error: error.response?.data?.message || '登录失败'
};
}
};
export default api;
// src/services/api.js
import axios from 'axios';
// 创建axios实例
const api = axios.create({
baseURL: 'http://your-wordpress-site.com/wp-json',
timeout: 10000,
});
// 请求拦截器 - 添加认证头
api.interceptors.request.use(
(config) => {
// 从localStorage获取token
const token = localStorage.getItem('wp_token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
// 响应拦截器 - 处理错误
api.interceptors.response.use(
(response) => response,
(error) => {
if (error.response?.status === 401) {
// 处理未授权
localStorage.removeItem('wp_token');
window.location.href = '/login';
}
return Promise.reject(error);
}
);
// 登录函数
export const login = async (username, password) => {
try {
const response = await axios.post(
'http://your-wordpress-site.com/wp-json/jwt-auth/v1/token',
{
username,
password,
}
);
if (response.data.token) {
localStorage.setItem('wp_token', response.data.token);
return { success: true, data: response.data };
}
} catch (error) {
return {
success: false,
error: error.response?.data?.message || '登录失败'
};
}
};
export default api;
-
前端构建:
npm run build
-
WordPress集成:
- 将构建的React应用放入WordPress主题或插件目录
- 创建短代码或页面模板来加载React应用
// 创建短代码加载React应用
add_shortcode('supply_chain_dashboard', function() {
ob_start();
?>
<div id="supply-chain-root"></div>
<script>
window.wpApiSettings = {
root: '<?php echo esc_url_raw(rest_url()); ?>',
nonce: '<?php echo wp_create_nonce('wp_rest'); ?>'
};
</script>
<?php
return ob_get_clean();
});
前端构建:
npm run build
WordPress集成:
- 将构建的React应用放入WordPress主题或插件目录
- 创建短代码或页面模板来加载React应用
// 创建短代码加载React应用
add_shortcode('supply_chain_dashboard', function() {
ob_start();
?>
<div id="supply-chain-root"></div>
<script>
window.wpApiSettings = {
root: '<?php echo esc_url_raw(rest_url()); ?>',
nonce: '<?php echo wp_create_nonce('wp_rest'); ?>'
};
</script>
<?php
return ob_get_clean();
});
-
API缓存:
// 添加REST API缓存
add_filter('rest_prepare_supply_product', function($response, $post, $request) {
$response->header('Cache-Control', 'max-age=300, must-revalidate');
return $response;
}, 10, 3);
-
前端代码分割:
// 使用React.lazy进行代码分割
const DemandForecast = React.lazy(() => import('./components/DemandForecast'));
API缓存:
// 添加REST API缓存
add_filter('rest_prepare_supply_product', function($response, $post, $request) {
$response->header('Cache-Control', 'max-age=300, must-revalidate');
return $response;
}, 10, 3);
前端代码分割:
// 使用React.lazy进行代码分割
const DemandForecast = React.lazy(() => import('./components/DemandForecast'));
通过本教程,您已经学会了如何开发一个基于WordPress的柔性供应链管理系统的前后端分离架构。这种架构的优势在于:
- 前后端独立开发:前端团队可以使用现代JavaScript框架,后端团队专注于API和业务逻辑
- 更好的用户体验:React提供快速、响应式的用户界面
- 可扩展性:可以轻松添加新功能模块
- 复用性:API可以被多个客户端使用(Web、移动应用等)
- 实时库存更新:集成WebSocket实现实时库存监控
- 移动端应用:使用React Native开发移动应用
- 数据分析:集成数据可视化库(如Chart.js)进行销售分析
- 多仓库管理:扩展支持多个仓库的库存调拨功能
- 供应商门户:为供应商提供自助查询和订单管理界面
通过不断迭代和优化,您可以构建一个功能完善、性能优异的柔性供应链管理系统,满足企业不断变化的业务需求。


