文章目录[隐藏]
实操指南:连接ERP系统数据接口的5个实施要点
引言:为什么WordPress开发者需要了解ERP集成
在当今数字化商业环境中,企业资源规划(ERP)系统已成为企业管理核心。对于WordPress开发者而言,将网站与ERP系统连接不仅能提升网站价值,还能为企业创造无缝的线上线下体验。无论是电子商务网站需要同步库存和订单,还是企业官网需要展示实时业务数据,ERP集成都是实现这些功能的关键。
本指南将基于WordPress开源系统,详细讲解连接ERP数据接口的5个核心实施要点,帮助行业新人和程序员掌握这一重要技能。我们将从基础概念入手,逐步深入到具体代码实现,确保您能够理解并应用这些知识。
要点一:理解ERP接口类型与通信协议
1.1 常见的ERP接口类型
在开始集成之前,首先需要了解ERP系统通常提供的接口类型:
RESTful API:现代ERP系统(如Odoo、SAP S/4HANA Cloud)普遍提供RESTful接口,使用HTTP方法(GET、POST、PUT、DELETE)进行数据操作。这种接口易于理解和使用,是WordPress集成的首选。
SOAP Web服务:较老的ERP系统(如SAP ECC)可能主要提供SOAP接口,使用XML格式和WSDL描述。虽然较为复杂,但在企业环境中仍广泛使用。
文件传输接口:一些系统通过SFTP/FTP服务器交换CSV、XML或JSON文件,适合批量数据同步。
数据库直连:直接连接ERP数据库(如MySQL、SQL Server),但通常不推荐,因为可能绕过业务逻辑和安全控制。
1.2 通信协议与安全考虑
HTTPS与SSL/TLS:所有外部通信必须使用HTTPS,确保数据传输安全。在WordPress中,确保wp_remote_get()和wp_remote_post()函数使用正确的SSL验证。
认证与授权:
- API密钥:简单的静态令牌
- OAuth 2.0:更安全的授权框架,适合用户级权限控制
- 基本认证:用户名密码Base64编码,仅限HTTPS环境下使用
- JWT(JSON Web Tokens):无状态令牌,适合微服务架构
1.3 WordPress中的HTTP请求处理
WordPress提供了安全的HTTP请求函数,应优先使用这些内置函数而非直接调用cURL:
// 使用wp_remote_get获取数据
$response = wp_remote_get('https://erp.example.com/api/products', array(
'headers' => array(
'Authorization' => 'Bearer ' . $api_token,
'Content-Type' => 'application/json',
),
'timeout' => 30,
'sslverify' => true, // 生产环境应为true
));
// 检查响应
if (is_wp_error($response)) {
$error_message = $response->get_error_message();
// 错误处理
} else {
$body = wp_remote_retrieve_body($response);
$data = json_decode($body, true);
// 处理数据
}
// 使用wp_remote_post发送数据
$response = wp_remote_post('https://erp.example.com/api/orders', array(
'headers' => array(
'Authorization' => 'Bearer ' . $api_token,
'Content-Type' => 'application/json',
),
'body' => json_encode(array(
'order_id' => 1001,
'customer' => 'John Doe',
'items' => array(...)
)),
'timeout' => 30,
'sslverify' => true,
));
要点二:设计稳健的数据同步架构
2.1 同步模式选择
实时同步:用户操作时立即与ERP通信。适合库存检查、价格查询等需要即时数据的场景。
// 实时检查库存示例
function check_real_time_stock($product_id) {
$api_url = get_option('erp_api_url') . '/inventory';
$api_key = get_option('erp_api_key');
$response = wp_remote_get($api_url . '?product_id=' . $product_id, array(
'headers' => array('API-Key' => $api_key),
'timeout' => 5, // 短超时,避免影响用户体验
));
if (!is_wp_error($response) && wp_remote_retrieve_response_code($response) === 200) {
$stock_data = json_decode(wp_remote_retrieve_body($response), true);
return $stock_data['quantity'] ?? 0;
}
// 失败时返回缓存值或默认值
return get_transient('cached_stock_' . $product_id) ?? 0;
}
定时批处理:使用WordPress Cron定时同步数据。适合产品目录、客户信息等不常变化的数据。
// 注册定时任务
add_action('init', function() {
if (!wp_next_scheduled('erp_daily_sync')) {
wp_schedule_event(time(), 'daily', 'erp_daily_sync');
}
});
// 产品同步处理
add_action('erp_daily_sync', 'sync_products_from_erp');
function sync_products_from_erp() {
$last_sync = get_option('erp_last_product_sync', 0);
$api_url = get_option('erp_api_url') . '/products/updated-since/' . $last_sync;
$response = wp_remote_get($api_url, array(
'headers' => array('API-Key' => get_option('erp_api_key')),
'timeout' => 60,
));
if (!is_wp_error($response) && wp_remote_retrieve_response_code($response) === 200) {
$products = json_decode(wp_remote_retrieve_body($response), true);
foreach ($products as $product) {
// 创建或更新WordPress产品(假设使用WooCommerce)
sync_single_product($product);
}
update_option('erp_last_product_sync', time());
}
}
事件驱动同步:ERP系统通过Webhook通知WordPress数据变化。这是最有效的同步方式,但需要ERP系统支持。
2.2 数据映射与转换
ERP系统和WordPress通常使用不同的数据模型,需要进行字段映射:
// ERP产品到WooCommerce产品的映射示例
function map_erp_to_woocommerce_product($erp_product) {
$wc_product = array(
'name' => $erp_product['description'] ?? '',
'sku' => $erp_product['item_code'] ?? '',
'regular_price' => $erp_product['price'] ?? 0,
'description' => $erp_product['long_description'] ?? '',
'short_description' => $erp_product['short_description'] ?? '',
'manage_stock' => true,
'stock_quantity' => $erp_product['available_quantity'] ?? 0,
'stock_status' => ($erp_product['available_quantity'] > 0) ? 'instock' : 'outofstock',
// 分类映射
'category_ids' => map_erp_categories($erp_product['categories']),
// 自定义字段
'meta_data' => array(
array('key' => '_erp_id', 'value' => $erp_product['id']),
array('key' => '_erp_last_updated', 'value' => $erp_product['updated_at']),
)
);
return $wc_product;
}
// 分类映射辅助函数
function map_erp_categories($erp_categories) {
$category_ids = array();
foreach ($erp_categories as $erp_cat) {
$term = get_term_by('name', $erp_cat['name'], 'product_cat');
if (!$term) {
// 创建不存在的分类
$term = wp_insert_term($erp_cat['name'], 'product_cat');
if (!is_wp_error($term)) {
$category_ids[] = $term['term_id'];
}
} else {
$category_ids[] = $term->term_id;
}
}
return $category_ids;
}
2.3 错误处理与重试机制
稳健的集成必须包含完善的错误处理:
class ERP_Sync_Handler {
private $max_retries = 3;
private $retry_delay = 5; // 秒
public function sync_with_retry($data, $endpoint) {
$retry_count = 0;
while ($retry_count <= $this->max_retries) {
try {
$result = $this->call_erp_api($data, $endpoint);
if ($result['success']) {
return $result;
} else {
// 记录错误但可重试
$this->log_error('ERP API调用失败但可重试: ' . $result['message']);
$retry_count++;
if ($retry_count <= $this->max_retries) {
sleep($this->retry_delay * $retry_count); // 递增延迟
}
}
} catch (Exception $e) {
// 不可重试的错误
$this->log_error('ERP API调用异常: ' . $e->getMessage());
throw $e;
}
}
// 达到最大重试次数
$this->log_error("ERP API调用失败,已达到最大重试次数: {$endpoint}");
return array(
'success' => false,
'message' => 'Maximum retry attempts reached'
);
}
private function call_erp_api($data, $endpoint) {
// API调用实现
}
private function log_error($message) {
// 记录到WordPress日志或专用日志表
error_log('[ERP Sync] ' . $message);
// 可选的数据库日志
global $wpdb;
$wpdb->insert(
$wpdb->prefix . 'erp_sync_logs',
array(
'level' => 'error',
'message' => $message,
'endpoint' => $endpoint,
'created_at' => current_time('mysql')
)
);
}
}
要点三:安全实施与访问控制
3.1 安全存储凭证
绝对不要在代码中硬编码API密钥或密码:
// 错误做法 - 硬编码凭证
define('ERP_API_KEY', 'my_secret_key_here');
// 正确做法 - 使用WordPress选项或常量
class ERP_Config {
const SETTINGS_GROUP = 'erp_integration_settings';
public static function get_api_key() {
// 首先检查常量(适合不同环境配置)
if (defined('ERP_API_KEY')) {
return ERP_API_KEY;
}
// 然后检查数据库选项
$api_key = get_option('erp_api_key');
if (empty($api_key)) {
// 记录错误但返回空值
error_log('ERP API密钥未配置');
}
return $api_key;
}
public static function get_api_url() {
$url = get_option('erp_api_url');
if (empty($url)) {
// 默认值或错误处理
$url = 'https://erp.example.com/api';
}
return trailingslashit($url);
}
}
// 在wp-config.php中定义环境特定常量(可选)
// define('ERP_API_KEY', 'production_key_here');
// define('ERP_API_URL', 'https://erp.production.com/api');
3.2 创建安全的设置页面
为管理员提供安全的配置界面:
// 添加ERP设置页面
add_action('admin_menu', function() {
add_options_page(
'ERP集成设置',
'ERP集成',
'manage_options',
'erp-integration',
'erp_settings_page'
);
});
function erp_settings_page() {
// 权限检查
if (!current_user_can('manage_options')) {
wp_die('您没有权限访问此页面');
}
// 保存设置
if (isset($_POST['submit_erp_settings']) && check_admin_referer('erp_settings_nonce')) {
update_option('erp_api_url', sanitize_url($_POST['erp_api_url']));
// 如果密码字段不为空,则更新
if (!empty($_POST['erp_api_key'])) {
update_option('erp_api_key', $_POST['erp_api_key']);
}
update_option('erp_sync_frequency', sanitize_text_field($_POST['sync_frequency']));
echo '<div class="notice notice-success"><p>设置已保存</p></div>';
}
// 获取当前值
$api_url = get_option('erp_api_url', '');
$sync_frequency = get_option('erp_sync_frequency', 'daily');
?>
<div class="wrap">
<h1>ERP系统集成设置</h1>
<form method="post" action="">
<?php wp_nonce_field('erp_settings_nonce'); ?>
<table class="form-table">
<tr>
<th scope="row"><label for="erp_api_url">ERP API地址</label></th>
<td>
<input type="url" id="erp_api_url" name="erp_api_url"
value="<?php echo esc_attr($api_url); ?>"
class="regular-text" required>
<p class="description">ERP系统的API基础地址,例如: https://erp.example.com/api</p>
</td>
</tr>
<tr>
<th scope="row"><label for="erp_api_key">API密钥</label></th>
<td>
<input type="password" id="erp_api_key" name="erp_api_key"
value="" class="regular-text">
<p class="description">留空以保持当前密钥不变</p>
</td>
</tr>
<tr>
<th scope="row"><label for="sync_frequency">数据同步频率</label></th>
<td>
<select id="sync_frequency" name="sync_frequency">
<option value="hourly" <?php selected($sync_frequency, 'hourly'); ?>>每小时</option>
<option value="twicedaily" <?php selected($sync_frequency, 'twicedaily'); ?>>每12小时</option>
<option value="daily" <?php selected($sync_frequency, 'daily'); ?>>每天</option>
<option value="weekly" <?php selected($sync_frequency, 'weekly'); ?>>每周</option>
</select>
</td>
</tr>
</table>
<p class="submit">
<input type="submit" name="submit_erp_settings"
class="button button-primary" value="保存设置">
</p>
</form>
<h2>连接测试</h2>
<button id="test-erp-connection" class="button">测试ERP连接</button>
<div id="test-result" style="margin-top: 10px;"></div>
<script>
jQuery(document).ready(function($) {
$('#test-erp-connection').click(function() {
$('#test-result').html('<p>测试中...</p>');
$.post(ajaxurl, {
action: 'test_erp_connection',
nonce: '<?php echo wp_create_nonce("test_erp_connection"); ?>'
}, function(response) {
$('#test-result').html('<p>' + response.data.message + '</p>');
}).fail(function() {
$('#test-result').html('<p>测试请求失败</p>');
});
});
});
</script>
</div>
<?php
}
// AJAX连接测试
add_action('wp_ajax_test_erp_connection', function() {
check_ajax_referer('test_erp_connection', 'nonce');
if (!current_user_can('manage_options')) {
wp_die('权限不足');
}
$api_url = get_option('erp_api_url');
$api_key = get_option('erp_api_key');
if (empty($api_url) || empty($api_key)) {
wp_send_json_error(array('message' => 'API地址或密钥未配置'));
return;
}
// 测试连接
$response = wp_remote_get($api_url . '/health', array(
'headers' => array('API-Key' => $api_key),
'timeout' => 10,
));
if (is_wp_error($response)) {
wp_send_json_error(array('message' => '连接失败: ' . $response->get_error_message()));
} elseif (wp_remote_retrieve_response_code($response) === 200) {
wp_send_json_success(array('message' => '连接成功! ERP系统正常响应'));
} else {
wp_send_json_error(array(
'message' => 'ERP系统返回错误: HTTP ' . wp_remote_retrieve_response_code($response)
));
}
});
3.3 输入验证与输出转义
防止注入攻击和数据污染:
// 处理ERP Webhook的示例
add_action('rest_api_init', function() {
register_rest_route('erp/v1', '/webhook/order', array(
'methods' => 'POST',
'callback' => 'handle_erp_webhook',
'permission_callback' => 'verify_erp_webhook',
));
});
function verify_erp_webhook($request) {
// 验证Webhook签名
$signature = $request->get_header('X-ERP-Signature');
$payload = $request->get_body();
$expected_signature = hash_hmac('sha256', $payload, get_option('erp_webhook_secret'));
return hash_equals($expected_signature, $signature);
}
function handle_erp_webhook($request) {
// 验证和清理输入数据
$params = $request->get_json_params();
// 验证必要字段
$required_fields = ['order_id', 'status', 'customer_email'];
foreach ($required_fields as $field) {
if (!isset($params[$field])) {
return new WP_Error('missing_field', "缺少必要字段: {$field}", array('status' => 400));
}
}
// 清理和验证数据
$order_id = intval($params['order_id']);
$status = sanitize_text_field($params['status']);
$customer_email = sanitize_email($params['customer_email']);
// 验证订单状态是否有效
$valid_statuses = ['pending', 'processing', 'completed', 'cancelled'];
if (!in_array($status, $valid_statuses)) {
return new WP_Error('invalid_status', "无效的订单状态: {$status}", array('status' => 400));
}
// 查找对应的WooCommerce订单
$order = wc_get_order($order_id);
if (!$order) {
return new WP_Error('order_not_found', "订单不存在: {$order_id}", array('status' => 404));
}
// 更新订单状态
$order->update_status($status, 'ERP系统同步更新');
// 记录同步日志
$log_data = array(
'order_id' => $order_id,
'status' => $status,
'sync_time' => current_time('mysql'),
'source' => 'erp_webhook'
);
// 安全地存储日志
global $wpdb;
$wpdb->insert(
$wpdb->prefix . 'erp_sync_logs',
$log_data
);
return rest_ensure_response(array(
'success' => true,
'message' => '订单状态已更新',
'order_id' => $order_id,
'new_status' => $status
));
}
要点四:性能优化与缓存策略
4.1 实施多级缓存机制
class ERP_Cache_Manager {
private $cache_group = 'erp_data';
private $cache_expiration = 3600; // 1小时
public function get_product_data($product_id, $force_refresh = false) {
$cache_key = 'product_' . $product_id;
// 检查内存缓存(WordPress对象缓存)
$cached_data = wp_cache_get($cache_key, $this->cache_group);
if ($cached_data !== false && !$force_refresh) {
return $cached_data;
}
// 检查数据库缓存(transients)
$transient_key = 'erp_product_' . md5($product_id);
$cached_data = get_transient($transient_key);
if ($cached_data !== false && !$force_refresh) {
// 同时更新内存缓存
wp_cache_set($cache_key, $cached_data, $this->cache_group, $this->cache_expiration);
return $cached_data;
}
// 从ERP API获取数据
$api_data = $this->fetch_product_from_erp($product_id);
if ($api_data) {
// 更新所有缓存层
wp_cache_set($cache_key, $api_data, $this->cache_group, $this->cache_expiration);
set_transient($transient_key, $api_data, $this->cache_expiration);
// 可选:存储到自定义数据库表进行长期缓存
$this->store_in_database_cache($product_id, $api_data);
}
return $api_data;
}
public function invalidate_product_cache($product_id) {
// 清除所有缓存层
$cache_key = 'product_' . $product_id;
wp_cache_delete($cache_key, $this->cache_group);
$transient_key = 'erp_product_' . md5($product_id);
delete_transient($transient_key);
// 清除数据库缓存
$this->delete_database_cache($product_id);
}
private function fetch_product_from_erp($product_id) {
// 实际的API调用
$api_url = ERP_Config::get_api_url() . 'products/' . $product_id;
$response = wp_remote_get($api_url, array(
'headers' => array('API-Key' => ERP_Config::get_api_key()),
'timeout' => 10,
));
if (is_wp_error($response) || wp_remote_retrieve_response_code($response) !== 200) {
// 如果API失败,尝试返回过期的缓存数据
$stale_data = $this->get_stale_cache($product_id);
if ($stale_data) {
// 记录降级使用
error_log('使用过期的产品缓存数据: ' . $product_id);
return $stale_data;
}
return false;
}
return json_decode(wp_remote_retrieve_body($response), true);
}
}
4.2 批量处理与请求优化
class ERP_Batch_Processor {
public function sync_products_in_batches($product_ids, $batch_size = 50) {
$results = array(
'success' => array(),
'failed' => array(),
'total' => count($product_ids)
);
// 分批处理
$batches = array_chunk($product_ids, $batch_size);
foreach ($batches as $batch_index => $batch) {
// 构建批量请求
$batch_request = array(
'action' => 'get_products',
'product_ids' => $batch,
'fields' => array('id', 'name', 'price', 'stock', 'sku')
);
$response = $this->call_erp_batch_api($batch_request);
if ($response && $response['success']) {
foreach ($response['data'] as $product_data) {
$this->process_single_product($product_data);
$results['success'][] = $product_data['id'];
}
} else {
// 批量失败,回退到单个请求
foreach ($batch as $product_id) {
$single_result = $this->sync_single_product($product_id);
if ($single_result) {
$results['success'][] = $product_id;
} else {
$results['failed'][] = $product_id;
}
}
}
// 避免触发API速率限制
if ($batch_index < count($batches) - 1) {
sleep(1); // 批次间暂停
}
}
return $results;
}
private function call_erp_batch_api($batch_data) {
$api_url = ERP_Config::get_api_url() . 'batch';
$response = wp_remote_post($api_url, array(
'headers' => array(
'API-Key' => ERP_Config::get_api_key(),
'Content-Type' => 'application/json'
),
'body' => json_encode($batch_data),
'timeout' => 30,
));
if (is_wp_error($response)) {
error_log('批量API调用失败: ' . $response->get_error_message());
return false;
}
$status_code = wp_remote_retrieve_response_code($response);
if ($status_code !== 200) {
error_log("批量API返回错误状态码: {$status_code}");
return false;
}
return json_decode(wp_remote_retrieve_body($response), true);
}
}
4.3 异步处理与队列系统
class ERP_Async_Processor {
public function enqueue_sync_task($task_type, $data) {
// 使用WordPress的Cron系统作为简单队列
$task_id = wp_generate_uuid4();
$task_data = array(
'task_id' => $task_id,
'type' => $task_type,
'data' => $data,
'created_at' => time(),
'status' => 'pending'
);
// 存储任务到选项表
$tasks = get_option('erp_pending_tasks', array());
$tasks[$task_id] = $task_data;
update_option('erp_pending_tasks', $tasks);
// 调度处理
if (!wp_next_scheduled('process_erp_tasks')) {
wp_schedule_single_event(time() + 60, 'process_erp_tasks');
}
return $task_id;
}
public function process_tasks() {
$tasks = get_option('erp_pending_tasks', array());
// 每次处理最多5个任务
$processed = 0;
$max_per_run = 5;
foreach ($tasks as $task_id => $task) {
if ($task['status'] === 'pending' && $processed < $max_per_run) {
// 更新状态为处理中
$tasks[$task_id]['status'] = 'processing';
$tasks[$task_id]['started_at'] = time();
update_option('erp_pending_tasks', $tasks);
// 执行任务
$result = $this->execute_task($task);
// 更新任务状态
$tasks[$task_id]['status'] = $result['success'] ? 'completed' : 'failed';
$tasks[$task_id]['completed_at'] = time();
$tasks[$task_id]['result'] = $result;
$processed++;
}
}
update_option('erp_pending_tasks', $tasks);
// 如果还有待处理任务,重新调度
$remaining = count(array_filter($tasks, function($task) {
return $task['status'] === 'pending';
}));
if ($remaining > 0) {
wp_schedule_single_event(time() + 60, 'process_erp_tasks');
}
}
private function execute_task($task) {
switch ($task['type']) {
case 'sync_product':
return $this->sync_product_task($task['data']);
case 'sync_order':
return $this->sync_order_task($task['data']);
case 'sync_customer':
return $this->sync_customer_task($task['data']);
default:
return array('success' => false, 'message' => '未知任务类型');
}
}
}
要点五:监控、日志与故障排除
5.1 实现全面的日志系统
class ERP_Logger {
const LOG_LEVEL_DEBUG = 1;
const LOG_LEVEL_INFO = 2;
const LOG_LEVEL_WARNING = 3;
const LOG_LEVEL_ERROR = 4;
private $log_table;
private $min_log_level;
public function __construct() {
global $wpdb;
$this->log_table = $wpdb->prefix . 'erp_logs';
$this->min_log_level = defined('ERP_LOG_LEVEL') ? ERP_LOG_LEVEL : self::LOG_LEVEL_INFO;
// 确保日志表存在
$this->create_log_table();
}
private function create_log_table() {
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE IF NOT EXISTS {$this->log_table} (
id bigint(20) NOT NULL AUTO_INCREMENT,
level tinyint(1) NOT NULL,
module varchar(50) NOT NULL,
message text NOT NULL,
context longtext,
user_id bigint(20) DEFAULT NULL,
ip_address varchar(45) DEFAULT NULL,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY level (level),
KEY module (module),
KEY created_at (created_at)
) {$charset_collate};";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}
public function log($level, $module, $message, $context = array()) {
if ($level < $this->min_log_level) {
return;
}
global $wpdb;
// 添加上下文信息
$context['wp_debug'] = defined('WP_DEBUG') && WP_DEBUG;
$context['php_version'] = PHP_VERSION;
$context['wordpress_version'] = get_bloginfo('version');
// 获取当前用户
$user_id = get_current_user_id();
$user_id = $user_id ?: null;
// 获取IP地址
$ip_address = $this->get_client_ip();
$wpdb->insert(
$this->log_table,
array(
'level' => $level,
'module' => $module,
'message' => $message,
'context' => json_encode($context),
'user_id' => $user_id,
'ip_address' => $ip_address
),
array('%d', '%s', '%s', '%s', '%d', '%s')
);
// 同时输出到WordPress调试日志
if (defined('WP_DEBUG') && WP_DEBUG) {
$level_name = $this->get_level_name($level);
error_log("[ERP {$level_name}] {$module}: {$message}");
}
}
public function get_logs($filters = array(), $limit = 100, $offset = 0) {
global $wpdb;
$where = array('1=1');
$params = array();
if (!empty($filters['level'])) {
$where[] = 'level = %d';
$params[] = $filters['level'];
}
if (!empty($filters['module'])) {
$where[] = 'module = %s';
$params[] = $filters['module'];
}
if (!empty($filters['start_date'])) {
$where[] = 'created_at >= %s';
$params[] = $filters['start_date'];
}
if (!empty($filters['end_date'])) {
$where[] = 'created_at <= %s';
$params[] = $filters['end_date'];
}
$where_clause = implode(' AND ', $where);
if (!empty($params)) {
$where_clause = $wpdb->prepare($where_clause, $params);
}
$query = "SELECT * FROM {$this->log_table}
WHERE {$where_clause}
ORDER BY created_at DESC
LIMIT %d OFFSET %d";
return $wpdb->get_results(
$wpdb->prepare($query, $limit, $offset)
);
}
public function cleanup_old_logs($days_to_keep = 30) {
global $wpdb;
$cutoff_date = date('Y-m-d H:i:s', strtotime("-{$days_to_keep} days"));
$wpdb->query(
$wpdb->prepare(
"DELETE FROM {$this->log_table} WHERE created_at < %s",
$cutoff_date
)
);
return $wpdb->rows_affected;
}
}
5.2 创建监控仪表板
class ERP_Monitor_Dashboard {
public function add_admin_page() {
add_menu_page(
'ERP监控',
'ERP监控',
'manage_options',
'erp-monitor',
array($this, 'render_dashboard'),
'dashicons-dashboard',
30
);
}
public function render_dashboard() {
?>
<div class="wrap">
<h1>ERP系统集成监控</h1>
<div class="erp-monitor-stats">
<div class="stat-card">
<h3>API响应时间</h3>
<div class="stat-value"><?php echo $this->get_avg_response_time(); ?>ms</div>
<div class="stat-trend">最近24小时</div>
</div>
<div class="stat-card">
<h3>同步成功率</h3>
<div class="stat-value"><?php echo $this->get_sync_success_rate(); ?>%</div>
<div class="stat-trend">最近7天</div>
</div>
<div class="stat-card">
<h3>待处理任务</h3>
<div class="stat-value"><?php echo $this->get_pending_tasks_count(); ?></div>
<div class="stat-trend">需要处理</div>
</div>
</div>
<h2>最近错误日志</h2>
<?php $this->render_error_logs(); ?>
<h2>同步状态</h2>
<?php $this->render_sync_status(); ?>
<h2>手动操作</h2>
<div class="manual-actions">
<button class="button button-primary" onclick="clearErpCache()">清除缓存</button>
<button class="button" onclick="forceFullSync()">强制全量同步</button>
<button class="button" onclick="testAllConnections()">测试所有连接</button>
</div>
</div>
<style>
.erp-monitor-stats {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
margin: 20px 0;
}
.stat-card {
background: white;
border: 1px solid #ccd0d4;
padding: 20px;
border-radius: 4px;
text-align: center;
}
.stat-value {
font-size: 2em;
font-weight: bold;
margin: 10px 0;
}
.stat-trend {
color: #666;
font-size: 0.9em;
}
</style>
<script>
