实操指南:实现实时物流追踪功能的3个集成方案(基于WordPress开发)
引言:为什么物流追踪对电商网站至关重要
在当今快速发展的电商环境中,实时物流追踪功能已成为提升用户体验和运营效率的关键要素。对于基于WordPress搭建的电商网站而言,集成物流追踪功能不仅能减少客户咨询压力,还能显著提高客户满意度和复购率。数据显示,提供实时物流追踪的电商网站客户满意度平均提升23%,退货率降低18%。
本指南专为WordPress开发者和行业新人设计,将详细介绍三种实用的物流追踪集成方案,从简单插件到深度API开发,帮助您根据自身技术水平和业务需求选择最合适的实现方式。
方案一:使用专业物流追踪插件(适合初学者)
1.1 插件选择与比较
对于刚接触WordPress开发的新手,使用专业插件是最快捷的实现方式。以下是几款优秀的物流追踪插件:
- TrackShip for WooCommerce:支持50多家物流公司,提供自动化追踪和自定义通知
- Advanced Shipment Tracking for WooCommerce:免费版本功能强大,支持多家物流商
- PostNL Track & Trace:针对特定物流公司的专业解决方案
1.2 安装与配置步骤
以Advanced Shipment Tracking for WooCommerce为例:
// 安装插件后,在主题的functions.php中添加以下代码以扩展功能
add_action('woocommerce_order_details_after_order_table', 'custom_tracking_display', 10, 1);
function custom_tracking_display($order) {
// 检查是否有追踪信息
$tracking_items = ast_get_tracking_items($order->get_id());
if (count($tracking_items) > 0) {
echo '<h3>物流追踪信息</h3>';
echo '<div class="tracking-info">';
foreach($tracking_items as $tracking) {
echo '<div class="tracking-item">';
echo '<p><strong>物流公司:</strong> ' . esc_html($tracking['formatted_tracking_provider']) . '</p>';
echo '<p><strong>运单号:</strong> ' . esc_html($tracking['tracking_number']) . '</p>';
// 生成追踪链接
$tracking_link = ast_get_tracking_link($tracking['tracking_number'], $tracking['tracking_provider']);
echo '<p><a href="' . esc_url($tracking_link) . '" target="_blank">点击查看实时物流状态</a></p>';
echo '</div>';
}
echo '</div>';
}
}
1.3 自定义样式与用户体验优化
/* 在主题的style.css中添加自定义样式 */
.tracking-info {
background: #f8f9fa;
border: 1px solid #e9ecef;
border-radius: 8px;
padding: 20px;
margin: 20px 0;
}
.tracking-item {
background: white;
padding: 15px;
margin-bottom: 15px;
border-radius: 5px;
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
}
.tracking-item p {
margin: 8px 0;
}
.tracking-item a {
display: inline-block;
background: #007cba;
color: white;
padding: 8px 16px;
border-radius: 4px;
text-decoration: none;
font-weight: 500;
}
.tracking-item a:hover {
background: #005a87;
}
1.4 优缺点分析
优点:
- 快速部署,无需编码经验
- 定期更新,兼容性有保障
- 通常包含多种物流公司支持
缺点:
- 高级功能可能需要付费
- 自定义程度有限
- 可能增加网站加载时间
方案二:通过API集成主流物流服务(适合中级开发者)
2.1 API选择与申请
对于有一定开发经验的程序员,直接通过API集成物流服务能提供更好的灵活性和控制力。主流物流API包括:
- 快递鸟API:支持国内外600+物流公司
- 快递100 API:覆盖全球1200家快递公司
- 17Track API:专业跨境物流追踪
以快递鸟API为例,首先需要:
- 注册快递鸟账号并获取API ID和Key
- 选择适合的套餐(通常有免费额度)
- 阅读API文档,了解请求格式和参数
2.2 创建自定义物流追踪模块
// 创建自定义物流追踪类
class KdniaoTracker {
private $api_id;
private $api_key;
private $request_url = 'http://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx';
public function __construct($api_id, $api_key) {
$this->api_id = $api_id;
$this->api_key = $api_key;
}
// 实时查询物流信息
public function get_real_time_tracking($shipper_code, $logistic_code, $order_code = '') {
$request_data = json_encode([
'ShipperCode' => $shipper_code,
'LogisticCode' => $logistic_code,
'OrderCode' => $order_code
]);
$data_sign = $this->encrypt($request_data, $this->api_key);
$post_data = [
'RequestData' => urlencode($request_data),
'EBusinessID' => $this->api_id,
'RequestType' => '1002', // 实时查询接口指令
'DataSign' => urlencode($data_sign),
'DataType' => '2'
];
$result = $this->send_post($this->request_url, $post_data);
return json_decode($result, true);
}
// 数据签名
private function encrypt($data, $appkey) {
return urlencode(base64_encode(md5($data . $appkey)));
}
// 发送POST请求
private function send_post($url, $post_data) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
}
2.3 与WooCommerce订单系统集成
// 在WooCommerce订单详情页添加追踪功能
add_action('add_meta_boxes', 'add_tracking_meta_box');
function add_tracking_meta_box() {
add_meta_box(
'custom_tracking_meta_box',
'物流追踪管理',
'render_tracking_meta_box',
'shop_order',
'side',
'high'
);
}
function render_tracking_meta_box($post) {
$order_id = $post->ID;
$order = wc_get_order($order_id);
// 获取已保存的物流信息
$tracking_data = get_post_meta($order_id, '_custom_tracking_data', true);
?>
<div class="tracking-input">
<p>
<label for="shipper_code">物流公司代码:</label>
<input type="text" id="shipper_code" name="shipper_code"
value="<?php echo isset($tracking_data['shipper_code']) ? esc_attr($tracking_data['shipper_code']) : ''; ?>">
</p>
<p>
<label for="tracking_number">运单号码:</label>
<input type="text" id="tracking_number" name="tracking_number"
value="<?php echo isset($tracking_data['tracking_number']) ? esc_attr($tracking_data['tracking_number']) : ''; ?>">
</p>
<p>
<button type="button" class="button button-primary"
onclick="fetchTrackingInfo(<?php echo $order_id; ?>)">
获取物流信息
</button>
</p>
</div>
<div id="tracking-result-<?php echo $order_id; ?>" class="tracking-result">
<?php
if (!empty($tracking_data['result'])) {
$this->display_tracking_info($tracking_data['result']);
}
?>
</div>
<script>
function fetchTrackingInfo(orderId) {
const shipperCode = document.getElementById('shipper_code').value;
const trackingNumber = document.getElementById('tracking_number').value;
// 使用AJAX获取物流信息
jQuery.post(
'<?php echo admin_url('admin-ajax.php'); ?>',
{
action: 'get_tracking_info',
order_id: orderId,
shipper_code: shipperCode,
tracking_number: trackingNumber,
security: '<?php echo wp_create_nonce('tracking_nonce'); ?>'
},
function(response) {
if (response.success) {
jQuery('#tracking-result-' + orderId).html(response.data);
} else {
alert('获取物流信息失败:' + response.data);
}
}
);
}
</script>
<?php
}
// AJAX处理函数
add_action('wp_ajax_get_tracking_info', 'ajax_get_tracking_info');
function ajax_get_tracking_info() {
check_ajax_referer('tracking_nonce', 'security');
$order_id = intval($_POST['order_id']);
$shipper_code = sanitize_text_field($_POST['shipper_code']);
$tracking_number = sanitize_text_field($_POST['tracking_number']);
// 初始化追踪器
$tracker = new KdniaoTracker('your_api_id', 'your_api_key');
$result = $tracker->get_real_time_tracking($shipper_code, $tracking_number);
// 保存到订单元数据
update_post_meta($order_id, '_custom_tracking_data', [
'shipper_code' => $shipper_code,
'tracking_number' => $tracking_number,
'result' => $result,
'last_updated' => current_time('timestamp')
]);
// 返回HTML格式的追踪信息
ob_start();
display_tracking_info($result);
$html = ob_get_clean();
wp_send_json_success($html);
}
function display_tracking_info($tracking_data) {
if ($tracking_data['Success']) {
echo '<div class="tracking-details">';
echo '<h4>物流状态:' . esc_html($tracking_data['State']) . '</h4>';
if (!empty($tracking_data['Traces'])) {
echo '<ul class="tracking-timeline">';
foreach (array_reverse($tracking_data['Traces']) as $trace) {
echo '<li>';
echo '<strong>' . esc_html($trace['AcceptTime']) . '</strong><br>';
echo esc_html($trace['AcceptStation']);
echo '</li>';
}
echo '</ul>';
}
echo '</div>';
} else {
echo '<p class="error">' . esc_html($tracking_data['Reason']) . '</p>';
}
}
2.4 添加前端客户展示界面
// 在客户订单详情页显示追踪信息
add_action('woocommerce_view_order', 'display_tracking_to_customer', 20);
function display_tracking_to_customer($order_id) {
$tracking_data = get_post_meta($order_id, '_custom_tracking_data', true);
if (empty($tracking_data['result'])) {
return;
}
?>
<section class="woocommerce-tracking-details">
<h2>物流追踪信息</h2>
<div class="tracking-card">
<div class="tracking-header">
<div class="tracking-number">
<span class="label">运单号码:</span>
<span class="value"><?php echo esc_html($tracking_data['tracking_number']); ?></span>
</div>
<div class="tracking-status">
<span class="status-badge status-<?php echo esc_attr(strtolower($tracking_data['result']['State'])); ?>">
<?php echo esc_html($tracking_data['result']['State']); ?>
</span>
</div>
</div>
<div class="tracking-timeline">
<?php
if (!empty($tracking_data['result']['Traces'])) {
$traces = array_reverse($tracking_data['result']['Traces']);
foreach ($traces as $index => $trace) {
$is_current = ($index === 0);
?>
<div class="timeline-item <?php echo $is_current ? 'current' : ''; ?>">
<div class="timeline-dot"></div>
<div class="timeline-content">
<div class="timeline-time"><?php echo esc_html($trace['AcceptTime']); ?></div>
<div class="timeline-description"><?php echo esc_html($trace['AcceptStation']); ?></div>
</div>
</div>
<?php
}
}
?>
</div>
</div>
</section>
<style>
.woocommerce-tracking-details {
margin: 40px 0;
}
.tracking-card {
background: white;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0,0,0,0.08);
padding: 24px;
}
.tracking-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24px;
padding-bottom: 16px;
border-bottom: 1px solid #eaeaea;
}
.status-badge {
padding: 6px 12px;
border-radius: 20px;
font-size: 14px;
font-weight: 500;
}
.status-0 { background: #e3f2fd; color: #1565c0; }
.status-1 { background: #fff3e0; color: #ef6c00; }
.status-2 { background: #e8f5e9; color: #2e7d32; }
.status-3 { background: #ffebee; color: #c62828; }
.tracking-timeline {
position: relative;
padding-left: 20px;
}
.tracking-timeline::before {
content: '';
position: absolute;
left: 9px;
top: 0;
bottom: 0;
width: 2px;
background: #e0e0e0;
}
.timeline-item {
position: relative;
margin-bottom: 24px;
}
.timeline-item.current .timeline-dot {
background: #2196f3;
border-color: #2196f3;
}
.timeline-dot {
position: absolute;
left: -26px;
top: 4px;
width: 12px;
height: 12px;
border-radius: 50%;
border: 2px solid #bdbdbd;
background: white;
z-index: 1;
}
.timeline-content {
margin-left: 10px;
}
.timeline-time {
font-weight: 600;
color: #333;
margin-bottom: 4px;
}
.timeline-description {
color: #666;
line-height: 1.5;
}
</style>
<?php
}
2.5 优缺点分析
优点:
- 高度自定义,完全控制用户体验
- 可集成多家物流公司,统一展示界面
- 数据实时性更好,减少延迟
缺点:
- 需要API调用费用(部分服务)
- 开发工作量较大
- 需要处理API变动和维护
方案三:构建完整的物流追踪系统(适合高级开发者)
3.1 系统架构设计
对于大型电商网站或物流公司,可能需要构建完整的物流追踪系统。系统架构应包括:
- 数据采集层:对接多家物流API,统一数据格式
- 数据处理层:清洗、标准化、存储物流数据
- 数据存储层:使用MySQL存储历史数据,Redis缓存实时数据
- 业务逻辑层:处理业务规则和通知逻辑
- 展示层:前端展示和用户交互
3.2 数据库设计
-- 创建物流追踪相关数据表
CREATE TABLE wp_logistics_tracking (
id BIGINT(20) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
order_id BIGINT(20) UNSIGNED NOT NULL,
shipping_provider VARCHAR(100) NOT NULL,
tracking_number VARCHAR(100) NOT NULL,
status VARCHAR(50) DEFAULT 'pending',
estimated_delivery DATE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_order_id (order_id),
INDEX idx_tracking_number (tracking_number),
INDEX idx_status (status)
);
CREATE TABLE wp_tracking_history (
id BIGINT(20) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
tracking_id BIGINT(20) UNSIGNED NOT NULL,
event_time DATETIME NOT NULL,
location VARCHAR(255),
description TEXT NOT NULL,
status_code VARCHAR(50),
raw_data TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (tracking_id) REFERENCES wp_logistics_tracking(id) ON DELETE CASCADE,
INDEX idx_tracking_id (tracking_id),
INDEX idx_event_time (event_time)
);
CREATE TABLE wp_shipping_providers (
id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
code VARCHAR(50) UNIQUE NOT NULL,
name VARCHAR(100) NOT NULL,
api_endpoint VARCHAR(255),
api_type VARCHAR(50),
is_active BOOLEAN DEFAULT TRUE,
priority INT DEFAULT 0,
config TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
3.3 核心类与模块设计
// 物流追踪系统核心类
class LogisticsTrackingSystem {
private $db;
private $cache;
private $providers = [];
public function __construct() {
global $wpdb;
$this->db = $wpdb;
$this->cache = wp_cache_init();
}
// 添加追踪信息
public function add_tracking($order_id, $provider_code, $tracking_number, $additional_data = []) {
// 验证订单存在
if (!$this->validate_order($order_id)) {
return new WP_Error('invalid_order', '订单不存在');
}
// 获取物流商信息
$provider = $this->get_provider($provider_code);
if (!$provider) {
return new WP_Error('invalid_provider', '不支持的物流公司');
}
// 保存追踪信息
$data = [
'order_id' => $order_id,
'shipping_provider' => $provider_code,
'tracking_number' => $tracking_number,
'status' => 'pending',
'additional_data' => maybe_serialize($additional_data)
];
$result = $this->db->insert(
$this->db->prefix . 'logistics_tracking',
$data,
['%d', '%s', '%s', '%s', '%s']
);
if ($result) {
$tracking_id = $this->db->insert_id;
// 触发初始同步
$this->sync_tracking_status($tracking_id);
// 记录操作日志
$this->log_operation($order_id, 'tracking_added', [
'tracking_id' => $tracking_id,
'provider' => $provider_code,
'tracking_number' => $tracking_number
]);
return $tracking_id;
}
return new WP_Error('db_error', '数据库插入失败');
}
// 同步追踪状态
public function sync_tracking_status($tracking_id, $force = false) {
// 检查缓存,避免频繁请求
$cache_key = 'tracking_status_' . $tracking_id;
$cached = $this->cache->get($cache_key);
if (!$force && $cached) {
return $cached;
}
// 获取追踪信息
$tracking = $this->get_tracking_by_id($tracking_id);
if (!$tracking) {
return new WP_Error('not_found', '追踪信息不存在');
}
// 根据物流商选择对应的API处理器
$provider = $this->get_provider($tracking->shipping_provider);
$api_handler = $this->get_api_handler($provider->api_type);
// 调用API获取最新状态
$result = $api_handler->get_tracking_info(
$tracking->tracking_number,
$provider->config
);
if (is_wp_error($result)) {
// API调用失败,记录错误但不更新状态
$this->log_error($tracking_id, $result);
return $result;
}
// 处理并标准化API响应
$normalized_data = $this->normalize_tracking_data($result, $provider->code);
// 更新数据库
$this->update_tracking_status($tracking_id, $normalized_data);
// 缓存结果(5分钟)
$this->cache->set($cache_key, $normalized_data, 300);
// 检查状态变化,触发相应动作
$this->check_status_change($tracking_id, $tracking->status, $normalized_data['status']);
return $normalized_data;
}
// 批量同步追踪状态
public function batch_sync_tracking($status = 'pending', $limit = 50) {
$table_name = $this->db->prefix . 'logistics_tracking';
// 获取需要同步的追踪记录
$trackings = $this->db->get_results(
$this->db->prepare(
"SELECT * FROM {$table_name}
WHERE status = %s
OR updated_at < DATE_SUB(NOW(), INTERVAL 1 HOUR)
ORDER BY updated_at ASC
LIMIT %d",
$status,
$limit
)
);
$results = [];
foreach ($trackings as $tracking) {
$result = $this->sync_tracking_status($tracking->id);
$results[$tracking->id] = $result;
}
return $results;
}
// 获取订单的所有追踪信息
public function get_order_tracking($order_id) {
$table_name = $this->db->prefix . 'logistics_tracking';
$trackings = $this->db->get_results(
$this->db->prepare(
"SELECT t.*,
p.name as provider_name,
p.api_type
FROM {$table_name} t
LEFT JOIN {$this->db->prefix}shipping_providers p
ON t.shipping_provider = p.code
WHERE t.order_id = %d
ORDER BY t.created_at DESC",
$order_id
)
);
// 获取每条追踪的详细信息
foreach ($trackings as &$tracking) {
$tracking->history = $this->get_tracking_history($tracking->id);
$tracking->estimated_delivery = $this->calculate_estimated_delivery($tracking);
}
return $trackings;
}
// 获取追踪历史
private function get_tracking_history($tracking_id) {
$table_name = $this->db->prefix . 'tracking_history';
return $this->db->get_results(
$this->db->prepare(
"SELECT * FROM {$table_name}
WHERE tracking_id = %d
ORDER BY event_time DESC",
$tracking_id
)
);
}
// 更新追踪状态
private function update_tracking_status($tracking_id, $data) {
// 更新主表状态
$this->db->update(
$this->db->prefix . 'logistics_tracking',
[
'status' => $data['status'],
'estimated_delivery' => $data['estimated_delivery'],
'updated_at' => current_time('mysql')
],
['id' => $tracking_id],
['%s', '%s', '%s'],
['%d']
);
// 添加历史记录
foreach ($data['history'] as $event) {
$this->db->insert(
$this->db->prefix . 'tracking_history',
[
'tracking_id' => $tracking_id,
'event_time' => $event['time'],
'location' => $event['location'],
'description' => $event['description'],
'status_code' => $event['status_code'],
'raw_data' => maybe_serialize($event['raw_data'])
],
['%d', '%s', '%s', '%s', '%s', '%s']
);
}
}
// 标准化追踪数据
private function normalize_tracking_data($api_data, $provider_code) {
// 根据不同的API响应格式进行标准化
$normalizer = $this->get_data_normalizer($provider_code);
return $normalizer->normalize($api_data);
}
// 检查状态变化并触发动作
private function check_status_change($tracking_id, $old_status, $new_status) {
if ($old_status !== $new_status) {
// 获取订单信息
$tracking = $this->get_tracking_by_id($tracking_id);
$order = wc_get_order($tracking->order_id);
// 发送状态变更通知
$this->send_status_notification($order, $tracking, $new_status);
// 更新订单备注
$order->add_order_note(
sprintf(
'物流状态更新:%s → %s (运单号:%s)',
$old_status,
$new_status,
$tracking->tracking_number
)
);
// 如果已签收,触发相应动作
if ($new_status === 'delivered') {
$this->on_delivery_completed($order, $tracking);
}
}
}
// 发送状态通知
private function send_status_notification($order, $tracking, $new_status) {
$customer_email = $order->get_billing_email();
$customer_name = $order->get_billing_first_name();
// 邮件通知
$subject = sprintf('您的订单物流状态已更新 (#%s)', $order->get_order_number());
$message = $this->get_email_template('status_update', [
'order_number' => $order->get_order_number(),
'customer_name' => $customer_name,
'tracking_number' => $tracking->tracking_number,
'old_status' => $tracking->status,
'new_status' => $new_status,
'tracking_url' => $this->get_tracking_url($tracking),
'estimated_delivery' => $tracking->estimated_delivery
]);
wp_mail($customer_email, $subject, $message, ['Content-Type: text/html; charset=UTF-8']);
// 短信通知(可选)
if ($this->sms_enabled()) {
$this->send_sms_notification($order, $tracking, $new_status);
}
}
// 计算预计送达时间
private function calculate_estimated_delivery($tracking) {
// 基于物流公司、历史数据和当前状态智能计算
$provider = $this->get_provider($tracking->shipping_provider);
// 如果有API提供的预计时间,使用API数据
if (!empty($tracking->api_estimated_delivery)) {
return $tracking->api_estimated_delivery;
}
// 基于历史数据计算
$history = $this->get_tracking_history($tracking->id);
if (count($history) > 0) {
$first_event = end($history);
$first_date = strtotime($first_event->event_time);
$current_date = current_time('timestamp');
// 根据物流公司类型和距离估算
$estimated_days = $this->estimate_delivery_days(
$provider->code,
$first_date,
$current_date,
$tracking->status
);
return date('Y-m-d', $current_date + ($estimated_days * 86400));
}
return null;
}
}
3.4 后台管理界面开发
// 添加物流追踪管理菜单
add_action('admin_menu', 'register_logistics_tracking_menu');
function register_logistics_tracking_menu() {
add_menu_page(
'物流追踪管理',
'物流追踪',
'manage_woocommerce',
'logistics-tracking',
'render_tracking_dashboard',
'dashicons-location-alt',
56
);
add_submenu_page(
'logistics-tracking',
'追踪记录',
'追踪记录',
'manage_woocommerce',
'logistics-tracking',
'render_tracking_dashboard'
);
add_submenu_page(
'logistics-tracking',
'物流公司管理',
'物流公司',
'manage_options',
'logistics-providers',
'render_providers_page'
);
add_submenu_page(
'logistics-tracking',
'同步设置',
'同步设置',
'manage_options',
'logistics-settings',
'render_settings_page'
);
}
// 渲染追踪仪表板
function render_tracking_dashboard() {
$tracking_system = new LogisticsTrackingSystem();
// 获取筛选参数
$status = isset($_GET['status']) ? sanitize_text_field($_GET['status']) : 'all';
$provider = isset($_GET['provider']) ? sanitize_text_field($_GET['provider']) : '';
$date_from = isset($_GET['date_from']) ? sanitize_text_field($_GET['date_from']) : '';
$date_to = isset($_GET['date_to']) ? sanitize_text_field($_GET['date_to']) : '';
// 获取统计数据
$stats = $tracking_system->get_tracking_stats($status, $provider, $date_from, $date_to);
// 获取追踪列表
$per_page = 20;
$current_page = max(1, isset($_GET['paged']) ? intval($_GET['paged']) : 1);
$offset = ($current_page - 1) * $per_page;
$trackings = $tracking_system->get_tracking_list(
$status, $provider, $date_from, $date_to, $offset, $per_page
);
?>
<div class="wrap">
<h1 class="wp-heading-inline">物流追踪管理</h1>
<!-- 统计卡片 -->
<div class="tracking-stats">
<div class="stat-card">
<span class="stat-number"><?php echo esc_html($stats['total']); ?></span>
<span class="stat-label">总追踪数</span>
</div>
<div class="stat-card">
<span class="stat-number"><?php echo esc_html($stats['pending']); ?></span>
<span class="stat-label">待处理</span>
</div>
<div class="stat-card">
<span class="stat-number"><?php echo esc_html($stats['in_transit']); ?></span>
<span class="stat-label">运输中</span>
</div>
<div class="stat-card">
<span class="stat-number"><?php echo esc_html($stats['delivered']); ?></span>
<span class="stat-label">已送达</span>
</div>
</div>
<!-- 筛选表单 -->
<div class="tracking-filters">
<form method="get" action="">
<input type="hidden" name="page" value="logistics-tracking">
<select name="status">
<option value="all" <?php selected($status, 'all'); ?>>所有状态</option>
<option value="pending" <?php selected($status, 'pending'); ?>>待处理</option>
<option value="in_transit" <?php selected($status, 'in_transit'); ?>>运输中</option>
<option value="out_for_delivery" <?php selected($status, 'out_for_delivery'); ?>>派送中</option>
<option value="delivered" <?php selected($status, 'delivered'); ?>>已送达</option>
<option value="exception" <?php selected($status, 'exception'); ?>>异常</option>
</select>
<select name="provider">
<option value="">所有物流公司</option>
<?php
$providers = $tracking_system->get_all_providers();
foreach ($providers as $provider_item) {
printf(
'<option value="%s" %s>%s</option>',
esc_attr($provider_item->code),
selected($provider, $provider_item->code, false),
esc_html($provider_item->name)
);
}
?>
</select>
<input type="date" name="date_from" value="<?php echo esc_attr($date_from); ?>" placeholder="开始日期">
<input type="date" name="date_to" value="<?php echo esc_attr($date_to); ?>" placeholder="结束日期">
<button type="submit" class="button">筛选</button>
<button type="button" class="button button-secondary" onclick="batchSyncTracking()">批量同步</button>
</form>
</div>
<!-- 追踪列表 -->
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th>订单号</th>
<th>物流公司</th>
<th>运单号</th>
<th>状态</th>
<th>最后更新</th>
<th>预计送达</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php if (empty($trackings)) : ?>
<tr>
<td colspan="7" style="text-align: center;">暂无追踪记录</td>
</tr>
<?php else : ?>
<?php foreach ($trackings as $tracking) : ?>
<tr>
<td>
<a href="<?php echo get_edit_post_link($tracking->order_id); ?>">
#<?php echo esc_html($tracking->order_id); ?>
</a>
</td>
<td><?php echo esc_html($tracking->provider_name); ?></td>
<td>
<code><?php echo esc_html($tracking->tracking_number); ?></code>
<button type="button" class="button-link copy-tracking"
data-tracking="<?php echo esc_attr($tracking->tracking_number); ?>">
复制
</button>
</td>
<td>
<span class="status-badge status-<?php echo esc_attr($tracking->status); ?>">
<?php echo esc_html($this->get_status_label($tracking->status)); ?>
</span>
</td>
<td><?php echo esc_html(human_time_diff(strtotime($tracking->updated_at)) . '前'); ?></td>
