文章目录[隐藏]
WordPress柔性供应链软件的前后端分离开发教程
引言:为什么选择前后端分离架构
在当今快速变化的商业环境中,柔性供应链管理系统需要具备高度的灵活性和可扩展性。传统的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();
?>
数据库设计与优化
供应链管理系统需要高效的数据存储结构。除了上述库存表,您可能还需要创建以下表:
- 订单表:存储客户订单信息
- 物流表:跟踪货物运输状态
- 需求预测表:存储销售预测数据
前端开发:构建React供应链管理界面
项目初始化与配置
使用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
核心组件开发
1. 库存管理组件
// 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;
2. 订单处理组件
// 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;
3. 仪表板主组件
// 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;
API集成与安全配置
跨域资源共享(CORS)配置
由于前端运行在不同端口,需要配置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、移动应用等)
进一步扩展建议
- 实时库存更新:集成WebSocket实现实时库存监控
- 移动端应用:使用React Native开发移动应用
- 数据分析:集成数据可视化库(如Chart.js)进行销售分析
- 多仓库管理:扩展支持多个仓库的库存调拨功能
- 供应商门户:为供应商提供自助查询和订单管理界面
通过不断迭代和优化,您可以构建一个功能完善、性能优异的柔性供应链管理系统,满足企业不断变化的业务需求。
