文章目录[隐藏]
手把手教学:为WordPress集成智能化的网站表单数据清洗与去重工具
引言:为什么WordPress网站需要数据清洗与去重工具
在当今数字化时代,网站表单已成为企业与用户互动、收集信息的重要渠道。无论是联系表单、注册表单、调查问卷还是订单提交,WordPress网站每天都会通过各类表单收集大量用户数据。然而,这些数据往往存在各种质量问题:重复提交、格式不规范、信息不完整甚至包含恶意内容。
数据质量问题不仅影响后续的数据分析和业务决策,还可能导致营销资源浪费、客户体验下降以及系统性能问题。例如,同一用户多次提交相同信息会占用数据库空间,发送重复邮件可能引起用户反感,而不规范的数据格式则使数据分析变得困难。
传统上,WordPress管理员需要手动处理这些问题,耗时耗力且容易出错。因此,为WordPress集成智能化的数据清洗与去重工具显得尤为重要。本文将手把手教您如何通过WordPress代码二次开发,实现这一常用互联网小工具功能。
第一部分:理解WordPress表单数据处理机制
1.1 WordPress表单插件的工作原理
WordPress本身不提供强大的表单功能,大多数网站都依赖第三方表单插件,如Contact Form 7、Gravity Forms、WPForms等。这些插件通常遵循相似的工作流程:
- 前端渲染表单HTML
- 用户填写并提交表单
- 服务器端验证和处理数据
- 存储数据到数据库或发送到指定邮箱
- 显示成功或错误消息
理解这一流程是进行二次开发的基础。大多数表单插件都提供了丰富的钩子(Hooks)和过滤器(Filters),允许开发者在关键节点插入自定义代码。
1.2 WordPress数据存储方式分析
WordPress表单数据通常以以下几种方式存储:
- 自定义数据库表:专业表单插件如Gravity Forms会创建专用表存储提交数据
- 文章类型(Post Type):部分插件将表单提交存储为自定义文章类型
- 选项(Options):简单表单可能将数据存储在wp_options表中
- 直接发送到邮箱:不存储数据库,仅通过邮件发送
了解数据存储方式对于设计清洗和去重策略至关重要。我们的工具需要能够适应不同的存储方式,提供统一的处理接口。
第二部分:设计智能化数据清洗与去重系统
2.1 系统架构设计
一个完整的数据清洗与去重系统应包含以下模块:
- 数据采集模块:从不同来源收集表单数据
- 预处理模块:标准化数据格式
- 清洗规则引擎:根据预设规则清洗数据
- 去重算法模块:识别和合并重复数据
- 数据验证模块:验证数据有效性和完整性
- 日志与报告模块:记录处理过程和结果
- 管理界面模块:提供后台配置和监控界面
2.2 关键技术选择
在WordPress环境中实现这一系统,我们需要选择合适的技术方案:
- PHP作为主要开发语言:WordPress核心使用PHP,所有插件和主题都基于PHP
- MySQL数据库操作:直接操作WordPress数据库进行数据查询和更新
- WordPress钩子系统:利用Action和Filter钩子集成到现有表单处理流程
- JavaScript/AJAX:增强前端交互体验
- 正则表达式:用于复杂的数据格式匹配和清洗
2.3 数据清洗规则设计
数据清洗规则应根据具体业务需求定制,常见规则包括:
- 格式标准化:统一电话号码、日期、邮箱等格式
- 去除无效字符:清理HTML标签、特殊字符等
- 拼写校正:常见词汇的自动校正
- 缺失值处理:识别并标记或填充缺失数据
- 异常值检测:识别不符合业务逻辑的数据
- 敏感信息过滤:移除或加密敏感个人信息
2.4 去重算法设计
去重算法需要平衡准确性和性能:
- 精确匹配:完全相同的记录
- 模糊匹配:考虑拼写错误、缩写、同义词等
- 基于规则的匹配:根据业务规则定义重复条件
- 机器学习方法:使用相似度算法识别潜在重复
在WordPress环境中,考虑到性能限制,我们主要采用前三种方法。
第三部分:手把手实现数据清洗功能
3.1 创建WordPress插件框架
首先,我们创建一个基本的WordPress插件框架:
<?php
/**
* Plugin Name: 智能表单数据清洗与去重工具
* Plugin URI: https://yourwebsite.com/
* Description: 为WordPress表单提供智能数据清洗和去重功能
* Version: 1.0.0
* Author: 你的名字
* License: GPL v2 or later
*/
// 防止直接访问
if (!defined('ABSPATH')) {
exit;
}
// 定义插件常量
define('SFDCD_VERSION', '1.0.0');
define('SFDCD_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('SFDCD_PLUGIN_URL', plugin_dir_url(__FILE__));
// 初始化插件
class Smart_Form_Data_Cleaner {
private static $instance = null;
public static function get_instance() {
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct() {
$this->init_hooks();
}
private function init_hooks() {
// 初始化钩子
add_action('plugins_loaded', array($this, 'load_textdomain'));
add_action('admin_menu', array($this, 'add_admin_menu'));
add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'));
// 表单处理钩子 - 以Contact Form 7为例
add_filter('wpcf7_posted_data', array($this, 'clean_cf7_data'), 10, 1);
add_action('wpcf7_before_send_mail', array($this, 'check_duplicates_cf7'), 10, 3);
}
public function load_textdomain() {
load_plugin_textdomain('smart-form-data-cleaner', false, dirname(plugin_basename(__FILE__)) . '/languages');
}
// 其他方法将在后续步骤中添加
}
// 启动插件
Smart_Form_Data_Cleaner::get_instance();
3.2 实现基础数据清洗功能
接下来,我们实现基础的数据清洗功能:
class Data_Cleaner_Engine {
/**
* 清洗表单数据
* @param array $form_data 原始表单数据
* @return array 清洗后的数据
*/
public static function clean_form_data($form_data) {
if (!is_array($form_data) || empty($form_data)) {
return $form_data;
}
$cleaned_data = array();
foreach ($form_data as $field => $value) {
// 跳过空值
if (is_null($value) || $value === '') {
$cleaned_data[$field] = $value;
continue;
}
// 根据字段类型应用不同的清洗规则
$field_type = self::detect_field_type($field, $value);
$cleaned_value = self::apply_cleaning_rules($value, $field_type);
$cleaned_data[$field] = $cleaned_value;
}
return $cleaned_data;
}
/**
* 检测字段类型
*/
private static function detect_field_type($field_name, $value) {
$field_name = strtolower($field_name);
// 根据字段名关键词判断类型
if (strpos($field_name, 'email') !== false) {
return 'email';
} elseif (strpos($field_name, 'phone') !== false || strpos($field_name, 'tel') !== false) {
return 'phone';
} elseif (strpos($field_name, 'date') !== false) {
return 'date';
} elseif (strpos($field_name, 'name') !== false) {
return 'name';
} elseif (strpos($field_name, 'address') !== false) {
return 'address';
} elseif (strpos($field_name, 'url') !== false || strpos($field_name, 'website') !== false) {
return 'url';
} else {
// 根据值内容进一步判断
if (is_email($value)) {
return 'email';
} elseif (preg_match('/^d{10,}$/', preg_replace('/[^0-9]/', '', $value))) {
return 'phone';
} elseif (strtotime($value) !== false) {
return 'date';
} else {
return 'text';
}
}
}
/**
* 应用清洗规则
*/
private static function apply_cleaning_rules($value, $field_type) {
// 通用清洗:去除首尾空格、HTML标签、多余空白字符
$value = trim($value);
$value = strip_tags($value);
$value = preg_replace('/s+/', ' ', $value);
// 根据字段类型应用特定清洗规则
switch ($field_type) {
case 'email':
$value = self::clean_email($value);
break;
case 'phone':
$value = self::clean_phone($value);
break;
case 'date':
$value = self::clean_date($value);
break;
case 'name':
$value = self::clean_name($value);
break;
case 'url':
$value = self::clean_url($value);
break;
case 'address':
$value = self::clean_address($value);
break;
default:
// 对普通文本进行基本清洗
$value = self::clean_text($value);
}
return $value;
}
/**
* 清洗邮箱地址
*/
private static function clean_email($email) {
$email = strtolower(trim($email));
// 移除邮箱地址中的多余字符
$email = filter_var($email, FILTER_SANITIZE_EMAIL);
// 验证邮箱格式
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
// 尝试修复常见邮箱错误
$email = preg_replace('/s+/', '', $email);
$email = preg_replace('/[,;]/', '.', $email);
// 再次验证
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
// 如果仍然无效,记录错误但保留原值
error_log('无效的邮箱格式: ' . $email);
}
}
return $email;
}
/**
* 清洗电话号码
*/
private static function clean_phone($phone) {
// 移除非数字字符
$digits = preg_replace('/[^0-9]/', '', $phone);
// 根据不同国家/地区格式标准化
$country_code = self::detect_phone_country_code($digits);
switch ($country_code) {
case '86': // 中国
if (strlen($digits) === 11) {
return preg_replace('/(d{3})(d{4})(d{4})/', '$1 $2 $3', $digits);
}
break;
case '1': // 美国/加拿大
if (strlen($digits) === 10) {
return preg_replace('/(d{3})(d{3})(d{4})/', '($1) $2-$3', $digits);
} elseif (strlen($digits) === 11) {
return preg_replace('/(d{1})(d{3})(d{3})(d{4})/', '+$1 ($2) $3-$4', $digits);
}
break;
default:
// 通用格式化:每3-4位加空格
if (strlen($digits) > 6) {
$formatted = '';
while (strlen($digits) > 4) {
$formatted .= substr($digits, 0, 3) . ' ';
$digits = substr($digits, 3);
}
$formatted .= $digits;
return $formatted;
}
}
return $phone; // 如果无法标准化,返回原值
}
// 其他清洗方法...
}
3.3 集成到Contact Form 7
现在我们将清洗引擎集成到Contact Form 7中:
// 在Smart_Form_Data_Cleaner类中添加以下方法
public function clean_cf7_data($posted_data) {
// 应用数据清洗
$cleaned_data = Data_Cleaner_Engine::clean_form_data($posted_data);
// 记录清洗日志
$this->log_cleaning_process($posted_data, $cleaned_data);
return $cleaned_data;
}
public function check_duplicates_cf7($contact_form, &$abort, $submission) {
$posted_data = $submission->get_posted_data();
// 检查重复提交
$is_duplicate = $this->check_for_duplicates($posted_data, 'cf7');
if ($is_duplicate) {
// 如果是重复数据,可以阻止提交或标记为重复
$abort = true;
$submission->set_response(__('检测到重复提交,请勿重复提交表单。', 'smart-form-data-cleaner'));
// 或者可以选择不阻止,但记录重复
// $this->log_duplicate_submission($posted_data);
}
}
private function check_for_duplicates($form_data, $form_type) {
global $wpdb;
// 根据表单类型确定检查策略
$threshold_time = apply_filters('sfdcd_duplicate_threshold', 24 * HOUR_IN_SECONDS); // 默认24小时内
// 构建查询条件
$conditions = array();
$values = array();
// 检查关键字段:邮箱、电话等
foreach ($form_data as $field => $value) {
if ($this->is_key_field($field)) {
$conditions[] = "meta_value LIKE %s";
$values[] = '%' . $wpdb->esc_like($value) . '%';
}
}
if (empty($conditions)) {
return false;
}
// 查询数据库检查重复
$query = "SELECT COUNT(*) FROM {$wpdb->prefix}postmeta
WHERE meta_key IN ('_form_data', '_submission_data')
AND (" . implode(' OR ', $conditions) . ")
AND post_id IN (
SELECT ID FROM {$wpdb->prefix}posts
WHERE post_type = 'wpcf7_contact_form'
AND post_date > DATE_SUB(NOW(), INTERVAL %d SECOND)
)";
$values[] = $threshold_time;
$count = $wpdb->get_var($wpdb->prepare($query, $values));
return $count > 0;
}
private function is_key_field($field_name) {
$key_fields = array('email', 'phone', 'tel', 'mobile', 'e-mail');
foreach ($key_fields as $key) {
if (stripos($field_name, $key) !== false) {
return true;
}
}
return false;
}
第四部分:实现智能去重功能
4.1 设计去重算法
去重功能比简单清洗更复杂,需要智能识别相似但不完全相同的数据:
class Deduplication_Engine {
/**
* 查找重复记录
*/
public static function find_duplicates($new_data, $form_type, $threshold = 0.8) {
global $wpdb;
// 获取历史数据进行比较
$historical_data = self::get_historical_data($form_type);
$duplicates = array();
foreach ($historical_data as $record) {
$similarity = self::calculate_similarity($new_data, $record['data']);
if ($similarity >= $threshold) {
$duplicates[] = array(
'id' => $record['id'],
'similarity' => $similarity,
'data' => $record['data']
);
}
}
return $duplicates;
}
/**
* 计算两条记录之间的相似度
*/
private static function calculate_similarity($data1, $data2) {
$total_weight = 0;
$similarity_score = 0;
// 定义字段权重
$field_weights = array(
'email' => 0.4,
'phone' => 0.3,
'name' => 0.2,
'address' => 0.1
);
foreach ($data1 as $field => $value1) {
if (!isset($data2[$field])) {
continue;
}
$value2 = $data2[$field];
// 确定字段类型和权重
$field_type = Data_Cleaner_Engine::detect_field_type($field, $value1);
$weight = isset($field_weights[$field_type]) ? $field_weights[$field_type] : 0.05;
// 计算字段相似度
$field_similarity = self::compare_field_values($value1, $value2, $field_type);
$similarity_score += $field_similarity * $weight;
$total_weight += $weight;
}
// 避免除以零
if ($total_weight == 0) {
return 0;
}
return $similarity_score / $total_weight;
}
/**
* 比较字段值相似度
*/
private static function compare_field_values($value1, $value2, $field_type) {
if ($value1 === $value2) {
return 1.0;
}
// 空值处理
if (empty($value1) || empty($value2)) {
return 0.2; // 部分匹配分数
}
switch ($field_type) {
case 'email':
// 邮箱比较:考虑用户名和域名分开比较
list($user1, $domain1) = explode('@', strtolower($value1));
list($user2, $domain2) = explode('@', strtolower($value2));
$user_similarity = self::string_similarity($user1, $user2);
$domain_similarity = ($domain1 === $domain2) ? 1.0 : 0;
return ($user_similarity * 0.7) + ($domain_similarity * 0.3);
case 'phone':
// 电话号码比较:提取数字后比较
$digits1 = preg_replace('/[^0-9]/', '', $value1);
$digits2 = preg_replace('/[^0-9]/', '', $value2);
// 考虑国际区号差异
if (strlen($digits1) > 10 && strlen($digits2) > 10) {
// 都有国际区号,比较后8-10位
$compare1 = substr($digits1, -10);
$compare2 = substr($digits2, -10);
return ($compare1 === $compare2) ? 0.9 : 0;
} else {
// 直接比较
return ($digits1 === $digits2) ? 1.0 : self::string_similarity($digits1, $digits2);
}
case 'name':
// 姓名比较:考虑中英文、顺序、缩写
return self::name_similarity($value1, $value2);
default:
// 普通文本比较
return self::string_similarity($value1, $value2);
}
}
/**
* 字符串相似度计算(使用Levenshtein距离)
*/
private static function string_similarity($str1, $str2) {
$len1 = strlen($str1);
$len2 = strlen($str2);
if ($len1 === 0 || $len2 === 0) {
return 0;
}
// 计算Levenshtein距离
$distance = levenshtein(strtolower($str1), strtolower($str2));
$max_len = max($len1, $len2);
return 1 - ($distance / $max_len);
}
/**
* 姓名相似度计算
*/
private static function name_similarity($name1, $name2) {
// 转换为小写
$name1 = strtolower(trim($name1));
$name2 = strtolower(trim($name2));
// 完全相等
if ($name1 === $name2) {
return 1.0;
}
// 分割姓名组成部分
$parts1 = preg_split('/[s.,]+/', $name1);
$parts2 = preg_split('/[s.,]+/', $name2);
// 检查是否只是顺序不同
if (count(array_intersect($parts1, $parts2)) === count($parts1) &&
count($parts1) === count($parts2)) {
return 0.9;
}
// 检查缩写匹配
$initials1 = array_map(function($part) {
return substr($part, 0, 1);
}, $parts1);
$initials2 = array_map(function($part) {
return substr($part, 0, 1);
}, $parts2);
if (implode('', $initials1) === implode('', $initials2)) {
return 0.8;
}
// 计算平均相似度
$total_similarity = 0;
$comparisons = 0;
foreach ($parts1 as $part1) {
foreach ($parts2 as $part2) {
$similarity = self::string_similarity($part1, $part2);
if ($similarity > 0.7) {
$total_similarity += $similarity;
$comparisons++;
}
}
}
if ($comparisons > 0) {
return $total_similarity / $comparisons;
}
return self::string_similarity($name1, $name2);
}
/**
* 获取历史数据
*/
private static function get_historical_data($form_type, $limit = 100) {
global $wpdb;
$table_name = $wpdb->prefix . 'sfdcd_submissions';
// 检查表是否存在,如果不存在则返回空数组
if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) {
return array();
}
$query = $wpdb->prepare(
"SELECT id, form_data FROM $table_name
WHERE form_type = %s
ORDER BY submission_date DESC
LIMIT %d",
$form_type,
$limit
);
$results = $wpdb->get_results($query, ARRAY_A);
$historical_data = array();
foreach ($results as $row) {
$historical_data[] = array(
'id' => $row['id'],
'data' => maybe_unserialize($row['form_data'])
);
}
return $historical_data;
}
}
### 4.2 创建数据存储表
为了有效进行去重,我们需要创建专门的表来存储表单提交记录:
class Database_Manager {
/**
* 创建数据表
*/
public static function create_tables() {
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
$table_name = $wpdb->prefix . 'sfdcd_submissions';
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id bigint(20) NOT NULL AUTO_INCREMENT,
form_type varchar(100) NOT NULL,
form_id varchar(100) DEFAULT NULL,
form_data longtext NOT NULL,
cleaned_data longtext NOT NULL,
duplicate_check_hash varchar(64) DEFAULT NULL,
is_duplicate tinyint(1) DEFAULT 0,
duplicate_of bigint(20) DEFAULT NULL,
submission_date datetime DEFAULT CURRENT_TIMESTAMP,
processed_date datetime DEFAULT NULL,
PRIMARY KEY (id),
KEY form_type (form_type),
KEY duplicate_check_hash (duplicate_check_hash),
KEY submission_date (submission_date),
KEY is_duplicate (is_duplicate)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
// 创建清洗规则表
$rules_table = $wpdb->prefix . 'sfdcd_cleaning_rules';
$sql = "CREATE TABLE IF NOT EXISTS $rules_table (
id bigint(20) NOT NULL AUTO_INCREMENT,
rule_name varchar(200) NOT NULL,
rule_type varchar(50) NOT NULL,
field_pattern varchar(200) DEFAULT NULL,
condition text NOT NULL,
action text NOT NULL,
priority int(11) DEFAULT 10,
is_active tinyint(1) DEFAULT 1,
created_date datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY rule_type (rule_type),
KEY is_active (is_active)
) $charset_collate;";
dbDelta($sql);
}
/**
* 存储表单提交
*/
public static function store_submission($form_type, $form_id, $original_data, $cleaned_data) {
global $wpdb;
$table_name = $wpdb->prefix . 'sfdcd_submissions';
// 生成去重检查哈希
$hash_data = self::prepare_data_for_hashing($cleaned_data);
$duplicate_hash = md5(serialize($hash_data));
// 检查是否已存在相同哈希的记录
$existing = $wpdb->get_var($wpdb->prepare(
"SELECT id FROM $table_name
WHERE duplicate_check_hash = %s
AND form_type = %s
AND submission_date > DATE_SUB(NOW(), INTERVAL 7 DAY)",
$duplicate_hash,
$form_type
));
$is_duplicate = $existing ? 1 : 0;
$duplicate_of = $existing ? $existing : null;
// 插入新记录
$result = $wpdb->insert(
$table_name,
array(
'form_type' => $form_type,
'form_id' => $form_id,
'form_data' => maybe_serialize($original_data),
'cleaned_data' => maybe_serialize($cleaned_data),
'duplicate_check_hash' => $duplicate_hash,
'is_duplicate' => $is_duplicate,
'duplicate_of' => $duplicate_of,
'processed_date' => current_time('mysql')
),
array('%s', '%s', '%s', '%s', '%s', '%d', '%d', '%s')
);
return array(
'success' => $result !== false,
'submission_id' => $wpdb->insert_id,
'is_duplicate' => $is_duplicate,
'duplicate_of' => $duplicate_of
);
}
/**
* 准备用于哈希计算的数据
*/
private static function prepare_data_for_hashing($data) {
$hash_data = array();
// 只选择关键字段进行哈希计算
$key_fields = array('email', 'phone', 'name', 'user_login', 'e-mail');
foreach ($data as $field => $value) {
$field_lower = strtolower($field);
foreach ($key_fields as $key) {
if (strpos($field_lower, $key) !== false) {
$hash_data[$field] = $value;
break;
}
}
}
// 如果没有关键字段,使用所有字段
if (empty($hash_data)) {
$hash_data = $data;
}
// 对值进行标准化处理
foreach ($hash_data as &$value) {
if (is_string($value)) {
$value = strtolower(trim($value));
$value = preg_replace('/s+/', ' ', $value);
}
}
// 按键名排序确保一致性
ksort($hash_data);
return $hash_data;
}
}
## 第五部分:创建管理界面
### 5.1 后台管理菜单
// 在Smart_Form_Data_Cleaner类中添加管理界面方法
public function add_admin_menu() {
// 主菜单
add_menu_page(
__('智能表单数据清洗', 'smart-form-data-cleaner'),
__('数据清洗', 'smart-form-data-cleaner'),
'manage_options',
'smart-form-data-cleaner',
array($this, 'render_main_page'),
'dashicons-filter',
30
);
// 子菜单
add_submenu_page(
'smart-form-data-cleaner',
__('数据清洗记录', 'smart-form-data-cleaner'),
__('清洗记录', 'smart-form-data-cleaner'),
'manage_options',
'sfdcd-cleaning-logs',
array($this, 'render_cleaning_logs_page')
);
add_submenu_page(
'smart-form-data-cleaner',
__('重复数据管理', 'smart-form-data-cleaner'),
__('重复数据', 'smart-form-data-cleaner'),
'manage_options',
'sfdcd-duplicates',
array($this, 'render_duplicates_page')
);
add_submenu_page(
'smart-form-data-cleaner',
__('清洗规则设置', 'smart-form-data-cleaner'),
__('清洗规则', 'smart-form-data-cleaner'),
'manage_options',
'sfdcd-cleaning-rules',
array($this, 'render_rules_page')
);
add_submenu_page(
'smart-form-data-cleaner',
__('系统设置', 'smart-form-data-cleaner'),
__('系统设置', 'smart-form-data-cleaner'),
'manage_options',
'sfdcd-settings',
array($this, 'render_settings_page')
);
}
public function enqueue_admin_scripts($hook) {
// 只在我们插件页面加载资源
if (strpos($hook, 'smart-form-data-cleaner') === false &&
strpos($hook, 'sfdcd-') === false) {
return;
}
// 加载CSS
wp_enqueue_style(
'sfdcd-admin-style',
SFDCD_PLUGIN_URL . 'assets/css/admin.css',
array(),
SFDCD_VERSION
);
// 加载JavaScript
wp_enqueue_script(
'sfdcd-admin-script',
SFDCD_PLUGIN_URL . 'assets/js/admin.js',
array('jquery', 'jquery-ui-sortable', 'jquery-ui-dialog'),
SFDCD_VERSION,
true
);
// 本地化脚本
wp_localize_script('sfdcd-admin-script', 'sfdcd_ajax', array(
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('sfdcd_ajax_nonce'),
'confirm_delete' => __('确定要删除这条记录吗?', 'smart-form-data-cleaner'),
'processing' => __('处理中...', 'smart-form-data-cleaner')
));
}
### 5.2 主页面模板
public function render_main_page() {
// 检查数据库表是否存在,如果不存在则创建
Database_Manager::create_tables();
// 获取统计数据
$stats = $this->get_system_stats();
?>
<div class="wrap sfdcd-dashboard">
<h1><?php _e('智能表单数据清洗与去重工具', 'smart-form-data-cleaner'); ?></h1>
<div class="sfdcd-stats-container">
<div class="sfdcd-stat-card">
<h3><?php _e('今日提交', 'smart-form-data-cleaner'); ?></h3>
<div class="stat-number"><?php echo esc_html($stats['today_submissions']); ?></div>
</div>
<div class="sfdcd-stat-card">
<h3><?php _e('重复数据', 'smart-form-data-cleaner'); ?></h3>
<div class="stat-number"><?php echo esc_html($stats['duplicate_count']); ?></div>
<div class="stat-percentage"><?php echo esc_html($stats['duplicate_percentage']); ?>%</div>
</div>
<div class="sfdcd-stat-card">
<h3><?php _e('数据清洗', 'smart-form-data-cleaner'); ?></h3>
<div class="stat-number"><?php echo esc_html($stats['cleaned_count']); ?></div>
<div class="stat-percentage"><?php echo esc_html($stats['cleaning_rate']); ?>%</div>
</div>
<div class="sfdcd-stat-card">
<h3><?php _e('活跃规则', 'smart-form-data-cleaner'); ?></h3>
<div class="stat-number"><?php echo esc_html($stats['active_rules']); ?></div>
</div>
</div>
<div class="sfdcd-dashboard-content">
<div class="sfdcd-dashboard-column">
<div class="sfdcd-card">
<h2><?php _e('最近提交', 'smart-form-data-cleaner'); ?></h2>
<?php $this->render_recent_submissions(); ?>
</div>
<div class="sfdcd-card">
<h2><?php _e('快速操作', 'smart-form-data-cleaner'); ?></h2>
<div class="sfdcd-quick-actions">
<button class="button button-primary" onclick="location.href='?page=sfdcd-cleaning-rules&action=add'">
<?php _e('添加清洗规则', 'smart-form-data-cleaner'); ?>
</button>
<button class="button" onclick="sfdcd_run_manual_cleanup()">
<?php _e('手动清洗数据', 'smart-form-data-cleaner'); ?>
</button>
<button class="button" onclick="sfdcd_check_duplicates()">
<?php _e('检查重复数据', 'smart-form-data-cleaner'); ?>
</button>
<button class="button" onclick="location.href='?page=sfdcd-settings'">
<?php _e('系统设置', 'smart-form-data-cleaner'); ?>
</button>
</div>
</div>
</div>
<div class="sfdcd-dashboard-column">
<div class="sfdcd-card">
<h2><?php _e('系统状态', 'smart-form-data-cleaner'); ?></h2>
<div class="sfdcd-system-status">
<div class="status-item">
<span class="status-label"><?php _e('数据库表', 'smart-form-data-cleaner'); ?>:</span>
<span class="status-value status-ok"><?php _e('正常', 'smart-form-data-cleaner'); ?></span>
</div>
<div class="status-item">
<span class="status-label"><?php _e('最后运行', 'smart-form-data-cleaner'); ?>:</span>
<span class="status-value"><?php echo esc_html($stats['last_run']); ?></span>
</div>
<div class="status-item">
<span class="status-label"><?php _e('支持的表单插件', 'smart-form-data-cleaner'); ?>:</
