文章目录[隐藏]
构建WordPress柔性供应链可视化看板教程
引言:供应链可视化的价值
在当今全球化的商业环境中,供应链管理已成为企业成功的关键因素。柔性供应链可视化看板能够帮助企业实时监控物流状态、库存水平和订单进度,从而快速响应市场变化。本教程将指导您如何在WordPress平台上构建一个功能完善的柔性供应链可视化看板,无需昂贵的专业软件,即可实现供应链数据的直观展示与分析。
准备工作:环境与工具配置
在开始开发之前,请确保您的WordPress环境满足以下要求:
- WordPress 5.0或更高版本
- PHP 7.4或更高版本
- 管理员权限
-
安装并激活以下插件:
- Advanced Custom Fields(用于自定义字段)
- 图表生成插件(如Data Tables Generator)
第一步:创建供应链数据结构
1.1 自定义文章类型设置
我们将创建三个自定义文章类型来管理供应链数据:供应商、产品和订单。
<?php
/**
* 注册供应链相关自定义文章类型
*/
function register_supply_chain_post_types() {
// 注册供应商类型
$supplier_labels = array(
'name' => '供应商',
'singular_name' => '供应商',
'add_new' => '添加供应商',
'add_new_item' => '添加新供应商',
'edit_item' => '编辑供应商',
'new_item' => '新供应商',
'view_item' => '查看供应商',
'search_items' => '搜索供应商',
'not_found' => '未找到供应商',
'not_found_in_trash' => '回收站中无供应商'
);
register_post_type('supplier', array(
'labels' => $supplier_labels,
'public' => true,
'has_archive' => true,
'menu_icon' => 'dashicons-truck',
'supports' => array('title', 'editor', 'thumbnail'),
'show_in_rest' => true, // 启用Gutenberg编辑器支持
));
// 注册产品类型
$product_labels = array(
'name' => '供应链产品',
'singular_name' => '产品',
'add_new' => '添加产品',
'add_new_item' => '添加新产品',
'edit_item' => '编辑产品',
'new_item' => '新产品',
'view_item' => '查看产品',
'search_items' => '搜索产品',
);
register_post_type('supply_product', array(
'labels' => $product_labels,
'public' => true,
'has_archive' => true,
'menu_icon' => 'dashicons-products',
'supports' => array('title', 'editor', 'thumbnail'),
'show_in_rest' => true,
));
// 注册订单类型
$order_labels = array(
'name' => '供应链订单',
'singular_name' => '订单',
'add_new' => '添加订单',
'add_new_item' => '添加新订单',
'edit_item' => '编辑订单',
'new_item' => '新订单',
'view_item' => '查看订单',
);
register_post_type('supply_order', array(
'labels' => $order_labels,
'public' => true,
'has_archive' => true,
'menu_icon' => 'dashicons-clipboard',
'supports' => array('title'),
'show_in_rest' => true,
));
}
add_action('init', 'register_supply_chain_post_types');
?>
1.2 使用Advanced Custom Fields创建字段组
通过ACF插件创建以下字段组:
-
供应商字段组:
- 联系人姓名(文本)
- 联系电话(文本)
- 供应能力评级(选择:高/中/低)
- 地理位置(谷歌地图)
-
产品字段组:
- 产品SKU(文本)
- 当前库存(数字)
- 安全库存水平(数字)
- 关联供应商(关系字段)
-
订单字段组:
- 订单状态(选择:待处理/生产中/运输中/已完成)
- 订单数量(数字)
- 关联产品(关系字段)
- 预计交付日期(日期选择器)
- 实际交付日期(日期选择器)
第二步:构建可视化看板前端
2.1 创建看板页面模板
<?php
/**
* 供应链可视化看板模板
* Template Name: 供应链可视化看板
*/
get_header(); ?>
<div class="supply-chain-dashboard">
<div class="dashboard-header">
<h1>柔性供应链可视化看板</h1>
<div class="last-updated">最后更新: <span id="update-time"><?php echo current_time('Y-m-d H:i:s'); ?></span></div>
<button class="refresh-btn" onclick="refreshDashboard()">刷新数据</button>
</div>
<div class="dashboard-grid">
<!-- 关键指标卡片 -->
<div class="dashboard-card metrics-card">
<h3>关键绩效指标</h3>
<div class="metrics-grid">
<div class="metric-item">
<div class="metric-value" id="total-orders">0</div>
<div class="metric-label">总订单数</div>
</div>
<div class="metric-item">
<div class="metric-value" id="pending-orders">0</div>
<div class="metric-label">待处理订单</div>
</div>
<div class="metric-item">
<div class="metric-value" id="on-time-delivery">0%</div>
<div class="metric-label">准时交付率</div>
</div>
<div class="metric-item">
<div class="metric-value" id="inventory-alerts">0</div>
<div class="metric-label">库存预警</div>
</div>
</div>
</div>
<!-- 订单状态图表 -->
<div class="dashboard-card chart-card">
<h3>订单状态分布</h3>
<canvas id="order-status-chart" width="400" height="300"></canvas>
</div>
<!-- 库存水平图表 -->
<div class="dashboard-card chart-card">
<h3>库存水平监控</h3>
<canvas id="inventory-chart" width="400" height="300"></canvas>
</div>
<!-- 供应商绩效表格 -->
<div class="dashboard-card table-card">
<h3>供应商绩效排名</h3>
<table id="supplier-performance-table">
<thead>
<tr>
<th>供应商</th>
<th>订单完成率</th>
<th>准时率</th>
<th>质量评分</th>
<th>状态</th>
</tr>
</thead>
<tbody id="supplier-table-body">
<!-- 数据将通过AJAX加载 -->
</tbody>
</table>
</div>
<!-- 实时订单列表 -->
<div class="dashboard-card orders-card">
<h3>近期订单状态</h3>
<div class="orders-list" id="recent-orders">
<!-- 订单数据将通过AJAX加载 -->
</div>
</div>
</div>
</div>
<?php get_footer(); ?>
2.2 添加看板样式
/* 供应链看板样式 */
.supply-chain-dashboard {
padding: 20px;
background-color: #f5f7fa;
min-height: 100vh;
}
.dashboard-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30px;
padding-bottom: 20px;
border-bottom: 2px solid #e0e6ed;
}
.dashboard-header h1 {
color: #2c3e50;
margin: 0;
}
.last-updated {
color: #7f8c8d;
font-size: 14px;
}
.refresh-btn {
background-color: #3498db;
color: white;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
}
.refresh-btn:hover {
background-color: #2980b9;
}
.dashboard-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
gap: 20px;
}
.dashboard-card {
background: white;
border-radius: 8px;
padding: 20px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.dashboard-card h3 {
margin-top: 0;
color: #34495e;
border-bottom: 1px solid #ecf0f1;
padding-bottom: 10px;
}
.metrics-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 15px;
}
.metric-item {
text-align: center;
padding: 15px;
background-color: #f8f9fa;
border-radius: 6px;
}
.metric-value {
font-size: 28px;
font-weight: bold;
color: #2c3e50;
}
.metric-label {
font-size: 14px;
color: #7f8c8d;
margin-top: 5px;
}
.orders-list {
max-height: 300px;
overflow-y: auto;
}
.order-item {
padding: 10px;
border-bottom: 1px solid #ecf0f1;
display: flex;
justify-content: space-between;
}
.order-item:last-child {
border-bottom: none;
}
.order-status {
padding: 3px 8px;
border-radius: 12px;
font-size: 12px;
font-weight: bold;
}
.status-pending { background-color: #f39c12; color: white; }
.status-production { background-color: #3498db; color: white; }
.status-shipping { background-color: #9b59b6; color: white; }
.status-completed { background-color: #2ecc71; color: white; }
#supplier-performance-table {
width: 100%;
border-collapse: collapse;
}
#supplier-performance-table th,
#supplier-performance-table td {
padding: 12px;
text-align: left;
border-bottom: 1px solid #ddd;
}
#supplier-performance-table th {
background-color: #f2f6fc;
font-weight: bold;
}
第三步:实现数据交互功能
3.1 创建数据API端点
<?php
/**
* 注册供应链数据API端点
*/
function register_supply_chain_api() {
register_rest_route('supply-chain/v1', '/dashboard-data', array(
'methods' => 'GET',
'callback' => 'get_dashboard_data',
'permission_callback' => function() {
return current_user_can('edit_posts'); // 仅限有编辑权限的用户
}
));
register_rest_route('supply-chain/v1', '/refresh-data', array(
'methods' => 'POST',
'callback' => 'refresh_dashboard_data',
'permission_callback' => function() {
return current_user_can('edit_posts');
}
));
}
add_action('rest_api_init', 'register_supply_chain_api');
/**
* 获取看板数据
*/
function get_dashboard_data() {
$data = array();
// 获取订单统计数据
$order_stats = get_order_statistics();
$data['order_stats'] = $order_stats;
// 获取库存数据
$inventory_data = get_inventory_data();
$data['inventory'] = $inventory_data;
// 获取供应商绩效数据
$supplier_performance = get_supplier_performance();
$data['suppliers'] = $supplier_performance;
// 获取最近订单
$recent_orders = get_recent_orders(10);
$data['recent_orders'] = $recent_orders;
// 计算关键指标
$data['metrics'] = calculate_key_metrics($order_stats, $inventory_data);
return rest_ensure_response($data);
}
/**
* 获取订单统计数据
*/
function get_order_statistics() {
$statuses = array('pending', 'production', 'shipping', 'completed');
$stats = array();
foreach ($statuses as $status) {
$args = array(
'post_type' => 'supply_order',
'posts_per_page' => -1,
'meta_query' => array(
array(
'key' => 'order_status',
'value' => $status,
'compare' => '='
)
)
);
$query = new WP_Query($args);
$stats[$status] = $query->found_posts;
}
return $stats;
}
/**
* 获取库存数据
*/
function get_inventory_data() {
$inventory = array();
$args = array(
'post_type' => 'supply_product',
'posts_per_page' => -1,
);
$query = new WP_Query($args);
while ($query->have_posts()) {
$query->the_post();
$product_id = get_the_ID();
$current_stock = get_field('current_stock', $product_id);
$safety_stock = get_field('safety_stock_level', $product_id);
$inventory[] = array(
'product_name' => get_the_title(),
'current_stock' => $current_stock ?: 0,
'safety_stock' => $safety_stock ?: 10,
'status' => $current_stock <= $safety_stock ? 'low' : 'normal'
);
}
wp_reset_postdata();
return $inventory;
}
?>
3.2 实现前端JavaScript数据交互
/**
* 供应链看板数据交互脚本
*/
document.addEventListener('DOMContentLoaded', function() {
// 初始化看板
loadDashboardData();
// 设置自动刷新(每5分钟)
setInterval(loadDashboardData, 300000);
});
/**
* 加载看板数据
*/
function loadDashboardData() {
// 显示加载状态
document.getElementById('update-time').textContent = '加载中...';
// 获取API数据
fetch('/wp-json/supply-chain/v1/dashboard-data')
.then(response => response.json())
.then(data => {
updateDashboard(data);
updateCharts(data);
updateTables(data);
// 更新最后刷新时间
const now = new Date();
document.getElementById('update-time').textContent =
now.toLocaleDateString() + ' ' + now.toLocaleTimeString();
})
.catch(error => {
console.error('加载数据失败:', error);
document.getElementById('update-time').textContent = '加载失败';
});
}
/**
* 更新关键指标
*/
function updateDashboard(data) {
const metrics = data.metrics;
document.getElementById('total-orders').textContent = metrics.total_orders;
document.getElementById('pending-orders').textContent = metrics.pending_orders;
document.getElementById('on-time-delivery').textContent = metrics.on_time_delivery + '%';
document.getElementById('inventory-alerts').textContent = metrics.inventory_alerts;
}
/**
* 更新图表
*/
function updateCharts(data) {
// 订单状态图表
const orderCtx = document.getElementById('order-status-chart').getContext('2d');
const orderChart = new Chart(orderCtx, {
type: 'doughnut',
data: {
labels: ['待处理', '生产中', '运输中', '已完成'],
datasets: [{
data: [
data.order_stats.pending,
data.order_stats.production,
data.order_stats.shipping,
data.order_stats.completed
],
backgroundColor: [
'#f39c12',
'#3498db',
'#9b59b6',
'#2ecc71'
]
}]
},
options: {
responsive: true,
maintainAspectRatio: false
}
});
// 库存水平图表
const inventoryCtx = document.getElementById('inventory-chart').getContext('2d');
const productNames = data.inventory.map(item => item.product_name);
const currentStock = data.inventory.map(item => item.current_stock);
const safetyStock = data.inventory.map(item => item.safety_stock);
const inventoryChart = new Chart(inventoryCtx, {
type: 'bar',
data: {
labels: productNames,
datasets: [
{
label: '当前库存',
data: currentStock,
backgroundColor: '#3498db'
},
{
label: '安全库存',
data: safetyStock,
backgroundColor: '#e74c3c',
type: 'line',
fill: false
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true
}
}
}
});
}
/**
* 更新供应商表格
*/
function updateTables(data) {
// 更新供应商绩效表格
const supplierTableBody = document.getElementById('supplier-table-body');
supplierTableBody.innerHTML = '';
data.suppliers.forEach(supplier => {
const row = document.createElement('tr');
row.innerHTML = `
<td>${supplier.name}</td>
<td>${supplier.completion_rate}%</td>
<td>${supplier.quality_score}/10</td>
<td><span class="status-badge ${supplier.status}">${supplier.status_text}</span></td>
`;
supplierTableBody.appendChild(row);
});
// 更新近期订单列表
const recentOrdersContainer = document.getElementById('recent-orders');
recentOrdersContainer.innerHTML = '';
data.recent_orders.forEach(order => {
const orderItem = document.createElement('div');
orderItem.className = 'order-item';
orderItem.innerHTML = `
<div class="order-info">
<strong>${order.product_name}</strong>
<div class="order-meta">订单号: ${order.order_number}</div>
</div>
<div class="order-status-info">
<span class="order-status status-${order.status}">${order.status_text}</span>
<div class="order-date">${order.delivery_date}</div>
</div>
`;
recentOrdersContainer.appendChild(orderItem);
});
}
/**
* 手动刷新看板
*/
function refreshDashboard() {
const refreshBtn = document.querySelector('.refresh-btn');
const originalText = refreshBtn.textContent;
refreshBtn.textContent = '刷新中...';
refreshBtn.disabled = true;
loadDashboardData();
setTimeout(() => {
refreshBtn.textContent = originalText;
refreshBtn.disabled = false;
}, 1000);
}
第四步:添加高级功能与优化
4.1 实现实时通知系统
<?php
/**
* 供应链预警系统
*/
class SupplyChainAlertSystem {
/**
* 检查库存预警
*/
public static function check_inventory_alerts() {
$alerts = array();
$products = get_posts(array(
'post_type' => 'supply_product',
'posts_per_page' => -1,
));
foreach ($products as $product) {
$current_stock = get_field('current_stock', $product->ID);
$safety_stock = get_field('safety_stock_level', $product->ID);
$product_name = get_the_title($product->ID);
if ($current_stock <= $safety_stock) {
$alerts[] = array(
'type' => 'inventory',
'level' => $current_stock == 0 ? 'critical' : 'warning',
'message' => sprintf(
'产品 "%s" 库存不足!当前库存:%d,安全库存:%d',
$product_name,
$current_stock,
$safety_stock
),
'product_id' => $product->ID,
'timestamp' => current_time('mysql')
);
}
}
return $alerts;
}
/**
* 检查订单延迟
*/
public static function check_order_delays() {
$alerts = array();
$today = current_time('Y-m-d');
$orders = get_posts(array(
'post_type' => 'supply_order',
'posts_per_page' => -1,
'meta_query' => array(
'relation' => 'AND',
array(
'key' => 'order_status',
'value' => 'completed',
'compare' => '!='
),
array(
'key' => 'estimated_delivery_date',
'value' => $today,
'compare' => '<',
'type' => 'DATE'
)
)
));
foreach ($orders as $order) {
$estimated_date = get_field('estimated_delivery_date', $order->ID);
$product_id = get_field('related_product', $order->ID);
$product_name = get_the_title($product_id);
$alerts[] = array(
'type' => 'order_delay',
'level' => 'warning',
'message' => sprintf(
'订单 #%s (%s) 预计交付日期已过:%s',
$order->ID,
$product_name,
$estimated_date
),
'order_id' => $order->ID,
'timestamp' => current_time('mysql')
);
}
return $alerts;
}
/**
* 获取所有预警
*/
public static function get_all_alerts() {
$inventory_alerts = self::check_inventory_alerts();
$order_alerts = self::check_order_delays();
return array_merge($inventory_alerts, $order_alerts);
}
}
/**
* 注册预警API端点
*/
function register_alert_api() {
register_rest_route('supply-chain/v1', '/alerts', array(
'methods' => 'GET',
'callback' => 'get_supply_chain_alerts',
'permission_callback' => function() {
return current_user_can('edit_posts');
}
));
}
add_action('rest_api_init', 'register_alert_api');
function get_supply_chain_alerts() {
$alerts = SupplyChainAlertSystem::get_all_alerts();
return rest_ensure_response($alerts);
}
?>
4.2 添加预警通知前端组件
/**
* 预警通知系统
*/
class AlertSystem {
constructor() {
this.alertContainer = null;
this.init();
}
init() {
this.createAlertContainer();
this.loadAlerts();
setInterval(() => this.loadAlerts(), 60000); // 每分钟检查一次
}
createAlertContainer() {
const container = document.createElement('div');
container.id = 'supply-chain-alerts';
container.className = 'alert-container';
container.innerHTML = `
<div class="alert-header">
<h4>供应链预警</h4>
<button class="alert-toggle">隐藏</button>
</div>
<div class="alert-list" id="alert-list"></div>
`;
document.querySelector('.supply-chain-dashboard').prepend(container);
this.alertContainer = container;
// 添加切换显示/隐藏功能
container.querySelector('.alert-toggle').addEventListener('click', () => {
const list = container.querySelector('.alert-list');
const toggleBtn = container.querySelector('.alert-toggle');
if (list.style.display === 'none') {
list.style.display = 'block';
toggleBtn.textContent = '隐藏';
} else {
list.style.display = 'none';
toggleBtn.textContent = '显示';
}
});
}
async loadAlerts() {
try {
const response = await fetch('/wp-json/supply-chain/v1/alerts');
const alerts = await response.json();
this.displayAlerts(alerts);
} catch (error) {
console.error('加载预警失败:', error);
}
}
displayAlerts(alerts) {
const alertList = document.getElementById('alert-list');
if (alerts.length === 0) {
alertList.innerHTML = '<div class="alert-item no-alerts">暂无预警信息</div>';
return;
}
let alertHTML = '';
alerts.forEach(alert => {
const alertClass = `alert-item alert-${alert.level}`;
const time = new Date(alert.timestamp).toLocaleTimeString();
alertHTML += `
<div class="${alertClass}">
<div class="alert-icon">
${alert.level === 'critical' ? '⚠️' : 'ℹ️'}
</div>
<div class="alert-content">
<div class="alert-message">${alert.message}</div>
<div class="alert-time">${time}</div>
</div>
</div>
`;
});
alertList.innerHTML = alertHTML;
}
}
// 初始化预警系统
document.addEventListener('DOMContentLoaded', () => {
new AlertSystem();
});
4.3 添加预警系统样式
/* 预警系统样式 */
.alert-container {
background: white;
border-radius: 8px;
margin-bottom: 20px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.alert-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px 20px;
background-color: #f8f9fa;
border-bottom: 1px solid #e9ecef;
}
.alert-header h4 {
margin: 0;
color: #2c3e50;
}
.alert-toggle {
background: none;
border: 1px solid #dee2e6;
padding: 5px 15px;
border-radius: 4px;
cursor: pointer;
font-size: 12px;
}
.alert-toggle:hover {
background-color: #e9ecef;
}
.alert-list {
max-height: 300px;
overflow-y: auto;
}
.alert-item {
display: flex;
padding: 12px 20px;
border-bottom: 1px solid #f1f3f4;
align-items: flex-start;
}
.alert-item:last-child {
border-bottom: none;
}
.alert-item.no-alerts {
justify-content: center;
color: #6c757d;
font-style: italic;
}
.alert-item.alert-critical {
background-color: #fff5f5;
border-left: 4px solid #e53e3e;
}
.alert-item.alert-warning {
background-color: #fffaf0;
border-left: 4px solid #dd6b20;
}
.alert-icon {
font-size: 18px;
margin-right: 12px;
margin-top: 2px;
}
.alert-content {
flex: 1;
}
.alert-message {
font-weight: 500;
margin-bottom: 4px;
}
.alert-time {
font-size: 12px;
color: #6c757d;
}
.status-badge {
padding: 4px 8px;
border-radius: 12px;
font-size: 12px;
font-weight: bold;
}
.status-badge.active {
background-color: #2ecc71;
color: white;
}
.status-badge.inactive {
background-color: #95a5a6;
color: white;
}
.status-badge.warning {
background-color: #f39c12;
color: white;
}
第五步:数据导出与报告功能
5.1 实现数据导出功能
<?php
/**
* 数据导出功能
*/
class SupplyChainExporter {
/**
* 导出订单数据为CSV
*/
public static function export_orders_csv($start_date = null, $end_date = null) {
$args = array(
'post_type' => 'supply_order',
'posts_per_page' => -1,
'orderby' => 'date',
'order' => 'DESC'
);
// 添加日期筛选
if ($start_date && $end_date) {
$args['date_query'] = array(
array(
'after' => $start_date,
'before' => $end_date,
'inclusive' => true
)
);
}
$orders = get_posts($args);
// 设置CSV头部
$headers = array(
'订单ID',
'产品名称',
'订单数量',
'订单状态',
'预计交付日期',
'实际交付日期',
'创建时间'
);
$output = fopen('php://output', 'w');
fputcsv($output, $headers);
foreach ($orders as $order) {
$product_id = get_field('related_product', $order->ID);
$product_name = $product_id ? get_the_title($product_id) : 'N/A';
$row = array(
$order->ID,
$product_name,
get_field('order_quantity', $order->ID) ?: 0,
self::get_status_text(get_field('order_status', $order->ID)),
get_field('estimated_delivery_date', $order->ID) ?: '',
get_field('actual_delivery_date', $order->ID) ?: '',
get_the_date('Y-m-d H:i:s', $order->ID)
);
fputcsv($output, $row);
}
fclose($output);
}
/**
* 导出库存报告
*/
public static function export_inventory_report() {
$products = get_posts(array(
'post_type' => 'supply_product',
'posts_per_page' => -1,
'orderby' => 'title',
'order' => 'ASC'
));
$headers = array(
'产品ID',
'产品名称',
'SKU',
'当前库存',
'安全库存',
'库存状态',
'关联供应商'
);
$output = fopen('php://output', 'w');
fputcsv($output, $headers);
foreach ($products as $product) {
$current_stock = get_field('current_stock', $product->ID) ?: 0;
$safety_stock = get_field('safety_stock_level', $product->ID) ?: 0;
$sku = get_field('product_sku', $product->ID) ?: '';
$supplier_id = get_field('related_supplier', $product->ID);
$supplier_name = $supplier_id ? get_the_title($supplier_id) : 'N/A';
$status = $current_stock <= $safety_stock ? '库存不足' : '正常';
$row = array(
$product->ID,
get_the_title($product->ID),
$sku,
$current_stock,
$safety_stock,
$status,
$supplier_name
);
fputcsv($output, $row);
}
fclose($output);
}
/**
* 获取状态文本
*/
private static function get_status_text($status) {
$status_map = array(
'pending' => '待处理',
'production' => '生产中',
'shipping' => '运输中',
'completed' => '已完成'
);
return $status_map[$status] ?? $status;
}
}
/**
* 注册导出API端点
*/
function register_export_api() {
register_rest_route('supply-chain/v1', '/export/orders', array(
'methods' => 'GET',
'callback' => 'handle_orders_export',
'permission_callback' => function() {
return current_user_can('export');
}
));
register_rest_route('supply-chain/v1', '/export/inventory', array(
'methods' => 'GET',
'callback' => 'handle_inventory_export',
'permission_callback' => function() {
return current_user_can('export');
}
));
}
add_action('rest_api_init', 'register_export_api');
function handle_orders_export($request) {
$start_date = $request->get_param('start_date');
$end_date = $request->get_param('end_date');
// 设置CSV头
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=orders_export_' . date('Y-m-d') . '.csv');
SupplyChainExporter::export_orders_csv($start_date, $end_date);
exit;
}
function handle_inventory_export($request) {
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=inventory_report_' . date('Y-m-d') . '.csv');
SupplyChainExporter::export_inventory_report();
exit;
}
?>
5.2 添加导出功能前端界面
/**
* 数据导出功能
*/
class DataExporter {
constructor() {
this.initExportButtons();
}
initExportButtons() {
// 创建导出按钮容器
const exportContainer = document.createElement('div');
exportContainer.className = 'export-container';
exportContainer.innerHTML = `
<h4>数据导出</h4>
<div class="export-buttons">
<button class="export-btn" data-type="orders">导出订单数据</button>
<button class="export-btn" data-type="inventory">导出库存报告</button>
</div>
<div class="date-range" id="date-range-container" style="display: none;">
<h5>选择日期范围</h5>
<div class="date-inputs">
<div>
<label>开始日期:</label>
<input type="date" id="start-date">
</div>
<div>
<label>结束日期:</label>
<input type="date" id="end-date">
</div>
</div>
<button class="confirm-export">确认导出</button>
</div>
`;
document.querySelector('.dashboard-header').appendChild(exportContainer);
// 绑定按钮事件
document.querySelectorAll('.export-btn').forEach(button => {
button.addEventListener('click', (e) => {
const exportType = e.target.dataset.type;
this.handleExport(exportType);
});
});
document.querySelector('.confirm-export').addEventListener('click', () => {
this.performExport();
});
}
handleExport(type) {
this.currentExportType = type;
if (type === 'orders') {
// 显示日期选择器
document.getElementById('date-range-container').style.display = 'block';
} else {
// 直接导出库存报告
this.performExport();
}
}
performExport() {
let url = '';
if (this.currentExportType === 'orders') {
const startDate = document.getElementById('start-date').value;
const endDate = document.getElementById('end-date').value;
if (!startDate || !endDate) {
