文章目录
-
- 在当今电商和内容管理系统中,供应商管理是企业运营的重要环节。WordPress作为全球最流行的内容管理系统,虽然拥有丰富的插件生态,但针对柔性供应商管理的专业解决方案仍然有限。本教程将带领您从零开始开发一个完整的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('VSM_PLUGIN_DIR', plugin_dir_path(__FILE__)); define('VSM_PLUGIN_URL', plugin_dir_url(__FILE__)); define('VSM_VERSION', '1.0.0'); // 初始化插件 function vsm_init() { // 检查必要依赖 if (!class_exists('WooCommerce') && !class_exists('Easy_Digital_Downloads')) { add_action('admin_notices', function() { echo '<div class="notice notice-warning"><p>供应商管理模块建议与WooCommerce或EDD配合使用</p></div>'; }); } // 加载核心类 require_once VSM_PLUGIN_DIR . 'includes/class-vendor-manager.php'; require_once VSM_PLUGIN_DIR . 'includes/class-vendor-post-type.php'; require_once VSM_PLUGIN_DIR . 'includes/class-vendor-meta-boxes.php'; } add_action('plugins_loaded', 'vsm_init');
- 创建供应商专用的自定义文章类型,这是整个模块的基础: <?php // 文件路径: includes/class-vendor-post-type.php class VSM_Vendor_Post_Type { public function __construct() { add_action('init', array($this, 'register_vendor_post_type')); add_action('init', array($this, 'register_vendor_taxonomies')); } /** * 注册供应商自定义文章类型 */ public function register_vendor_post_type() { $labels = array( 'name' => '供应商', 'singular_name' => '供应商', 'menu_name' => '供应商管理', 'add_new' => '添加供应商', 'add_new_item' => '添加新供应商', 'edit_item' => '编辑供应商', 'new_item' => '新供应商', 'view_item' => '查看供应商', 'search_items' => '搜索供应商', 'not_found' => '未找到供应商', 'not_found_in_trash' => '回收站中无供应商' ); $args = array( 'labels' => $labels, 'public' => true, 'publicly_queryable' => true, 'show_ui' => true, 'show_in_menu' => true, 'query_var' => true, 'rewrite' => array('slug' => 'vendor'), 'capability_type' => 'post', 'has_archive' => true, 'hierarchical' => false, 'menu_position' => 30, 'menu_icon' => 'dashicons-businessperson', 'supports' => array('title', 'editor', 'thumbnail', 'excerpt'), 'show_in_rest' => true, // 支持Gutenberg编辑器 ); register_post_type('vsm_vendor', $args); } /** * 注册供应商分类法 */ public function register_vendor_taxonomies() { // 供应商分类 register_taxonomy( 'vsm_vendor_category', 'vsm_vendor', array( 'labels' => array( 'name' => '供应商分类', 'singular_name' => '供应商分类', ), 'hierarchical' => true, 'show_ui' => true, 'show_admin_column' => true, 'query_var' => true, 'rewrite' => array('slug' => 'vendor-category'), 'show_in_rest' => true, ) ); // 供应商标签 register_taxonomy( 'vsm_vendor_tag', 'vsm_vendor', array( 'labels' => array( 'name' => '供应商标签', 'singular_name' => '供应商标签', ), 'hierarchical' => false, 'show_ui' => true, 'show_admin_column' => true, 'query_var' => true, 'rewrite' => array('slug' => 'vendor-tag'), 'show_in_rest' => true, ) ); } } // 初始化类 new VSM_Vendor_Post_Type();
- 为供应商添加详细的元数据字段,存储供应商的详细信息: <?php // 文件路径: includes/class-vendor-meta-boxes.php class VSM_Vendor_Meta_Boxes { public function __construct() { add_action('add_meta_boxes', array($this, 'add_vendor_meta_boxes')); add_action('save_post_vsm_vendor', array($this, 'save_vendor_meta_data')); add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts')); } /** * 添加供应商元数据框 */ public function add_vendor_meta_boxes() { add_meta_box( 'vsm_vendor_details', '供应商详细信息', array($this, 'render_vendor_details_meta_box'), 'vsm_vendor', 'normal', 'high' ); add_meta_box( 'vsm_vendor_performance', '供应商绩效评估', array($this, 'render_vendor_performance_meta_box'), 'vsm_vendor', 'side', 'default' ); } /** * 渲染供应商详细信息元数据框 */ public function render_vendor_details_meta_box($post) { // 添加安全验证 wp_nonce_field('vsm_vendor_meta_box', 'vsm_vendor_meta_box_nonce'); // 获取现有值 $contact_person = get_post_meta($post->ID, '_vsm_contact_person', true); $email = get_post_meta($post->ID, '_vsm_email', true); $phone = get_post_meta($post->ID, '_vsm_phone', true); $address = get_post_meta($post->ID, '_vsm_address', true); $website = get_post_meta($post->ID, '_vsm_website', true); $tax_number = get_post_meta($post->ID, '_vsm_tax_number', true); $contract_date = get_post_meta($post->ID, '_vsm_contract_date', true); $contract_expiry = get_post_meta($post->ID, '_vsm_contract_expiry', true); // 输出HTML表单 ?> <div class="vsm-meta-box"> <table class="form-table"> <tr> <th><label for="vsm_contact_person">联系人</label></th> <td> <input type="text" id="vsm_contact_person" name="vsm_contact_person" value="<?php echo esc_attr($contact_person); ?>" class="regular-text"> </td> </tr> <tr> <th><label for="vsm_email">邮箱地址</label></th> <td> <input type="email" id="vsm_email" name="vsm_email" value="<?php echo esc_attr($email); ?>" class="regular-text"> </td> </tr> <tr> <th><label for="vsm_phone">联系电话</label></th> <td> <input type="tel" id="vsm_phone" name="vsm_phone" value="<?php echo esc_attr($phone); ?>" class="regular-text"> </td> </tr> <tr> <th><label for="vsm_address">地址</label></th> <td> <textarea id="vsm_address" name="vsm_address" rows="3" class="large-text"><?php echo esc_textarea($address); ?></textarea> </td> </tr> <tr> <th><label for="vsm_contract_date">合同开始日期</label></th> <td> <input type="date" id="vsm_contract_date" name="vsm_contract_date" value="<?php echo esc_attr($contract_date); ?>"> </td> </tr> <tr> <th><label for="vsm_contract_expiry">合同到期日</label></th> <td> <input type="date" id="vsm_contract_expiry" name="vsm_contract_expiry" value="<?php echo esc_attr($contract_expiry); ?>"> <p class="description">到期前30天将发送提醒邮件</p> </td> </tr> </table> </div> <?php } /** * 保存供应商元数据 */ public function save_vendor_meta_data($post_id) { // 安全检查 if (!isset($_POST['vsm_vendor_meta_box_nonce']) || !wp_verify_nonce($_POST['vsm_vendor_meta_box_nonce'], 'vsm_vendor_meta_box')) { return; } // 检查自动保存 if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return; } // 检查用户权限 if (!current_user_can('edit_post', $post_id)) { return; } // 保存字段数据 $fields = array( 'vsm_contact_person', 'vsm_email', 'vsm_phone', 'vsm_address', 'vsm_website', 'vsm_tax_number', 'vsm_contract_date', 'vsm_contract_expiry' ); foreach ($fields as $field) { if (isset($_POST[$field])) { $value = sanitize_text_field($_POST[$field]); update_post_meta($post_id, '_' . $field, $value); } } // 自动计算并保存绩效评分 $this->calculate_vendor_performance($post_id); } /** * 计算供应商绩效评分 */ private function calculate_vendor_performance($vendor_id) { // 这里可以添加复杂的绩效计算逻辑 // 示例:基于订单完成率、产品质量、交货时间等计算 $base_score = 80; // 基础分 $adjustments = 0; // 调整分 // 模拟计算逻辑 $on_time_delivery = get_post_meta($vendor_id, '_vsm_on_time_delivery', true); if ($on_time_delivery > 95) { $adjustments += 10; } elseif ($on_time_delivery < 80) { $adjustments -= 15; } $quality_rating = get_post_meta($vendor_id, '_vsm_quality_rating', true); if ($quality_rating > 4.5) { $adjustments += 10; } elseif ($quality_rating < 3.0) { $adjustments -= 20; } $final_score = max(0, min(100, $base_score + $adjustments)); update_post_meta($vendor_id, '_vsm_performance_score', $final_score); // 根据评分设置供应商状态 $status = '良好'; if ($final_score < 60) { $status = '需改进'; } elseif ($final_score < 80) { $status = '一般'; } elseif ($final_score >= 90) { $status = '优秀'; } update_post_meta($vendor_id, '_vsm_status', $status); } /** * 加载管理端脚本和样式 */ public function enqueue_admin_scripts($hook) { global $post_type; if (($hook == 'post.php' || $hook == 'post-new.php') && $post_type == 'vsm_vendor') { wp_enqueue_style('vsm-admin-style', VSM_PLUGIN_URL . 'assets/css/admin.css', array(), VSM_VERSION); wp_enqueue_script('vsm-admin-script', VSM_PLUGIN_URL . 'assets/js/admin.js', array('jquery', 'jquery-ui-datepicker'), VSM_VERSION, true); // 本地化脚本 wp_localize_script('vsm-admin-script', 'vsm_admin', array( 'ajax_url' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('vsm_admin_nonce') )); } } } new VSM_Vendor_Meta_Boxes();
- 创建供应商与WooCommerce产品的关联功能: <?php // 文件路径: includes/class-vendor-product-relationship.php class VSM_Vendor_Product_Relationship { public function __construct() { // 为产品添加供应商选择框 add_action('woocommerce_product_options_general_product_data', array($this, 'add_vendor_to_product')); add_action('woocommerce_process_product_meta', array($this, 'save_product_vendor')); // 在供应商页面显示关联产品 add_action('add_meta_boxes', array($this, 'add_vendor_products_meta_box')); // 添加供应商筛选到产品列表 add_action('restrict_manage_posts', array($this, 'add_vendor_filter_to_products')); add_filter('parse_query', array($this, 'filter_products_by_vendor')); } /** * 在产品编辑页面添加供应商选择 */ public function add_vendor_to_product() { global $post; $args = array( 'post_type' => 'vsm_vendor', 'posts_per_page' => -1, 'post_status' => 'publish', 'orderby' => 'title', 'order' => 'ASC' ); $vendors = get_posts($args); if (empty($vendors)) { return; } echo '<div class="options_group">'; woocommerce_wp_select(array( 'id' => '_vsm_product_vendor', 'label' => '供应商', 'options' => $this->get_vendors_array($vendors), 'desc_tip' => true, 'description' => '选择该产品的供应商' )); echo '</div>'; } /** * 将供应商转换为选项数组 */ private function get_vendors_array($vendors) { $vendors_array = array('' => '选择供应商'); foreach ($vendors as $vendor) { $vendors_array[$vendor->ID] = $vendor->post_title; } return $vendors_array; } /** * 保存产品供应商关联 */ public function save_product_vendor($product_id) { if (isset($_POST['_vsm_product_vendor'])) { $vendor_id = intval($_POST['_vsm_product_vendor']); update_post_meta($product_id, '_vsm_product_vendor', $vendor_id); // 同时更新供应商的产品列表 $this->update_vendor_products($vendor_id, $product_id, 'add'); } } /** * 更新供应商的产品列表 */ private function update_vendor_products($vendor_id, $product_id, $action = 'add') { $vendor_products = get_post_meta($vendor_id, '_vsm_products', true); if (!is_array($vendor_products)) { $vendor_products = array(); } if ($action === 'add') { if (!in_array($product_id, $vendor_products)) { $vendor_products[] = $product_id; } } elseif ($action === 'remove') { $vendor_products = array_diff($vendor_products, array($product_id)); } update_post_meta($vendor_id, '_vsm_products', $vendor_products); } /** * 在产品列表添加供应商筛选 */ public function add_vendor_filter_to_products() { global $post_type; if ($post_type !== 'product') { return; } $args = array( 'post_type' => 'vsm_vendor', 'posts_per_page' => -1, 'post_status' => 'publish' ); $vendors = get_posts($args); if (empty($vendors)) { return; } $current_vendor = isset($_GET['vsm_vendor_filter']) ? $_GET['vsm_vendor_filter'] : ''; echo '<select name="vsm_vendor_filter" id="vsm_vendor_filter">'; echo '<option value="">所有供应商</option>'; foreach ($vendors as $vendor) { printf(
- <?php // 文件路径: includes/class-vendor-performance.php class VSM_Vendor_Performance { private $metrics_weights = array( 'delivery_time' => 0.3, 'quality' => 0.4, 'communication' => 0.2, 'pricing' => 0.1 ); public function __construct() { add_action('admin_menu', array($this, 'add_performance_page')); add_action('wp_ajax_vsm_log_performance', array($this, 'log_performance_ajax')); add_action('vsm_daily_performance_cron', array($this, 'calculate_daily_performance')); // 注册定时任务 if (!wp_next_scheduled('vsm_daily_performance_cron')) { wp_schedule_event(time(), 'daily', 'vsm_daily_performance_cron'); } } /** * 添加绩效管理页面 */ public function add_performance_page() { add_submenu_page( 'edit.php?post_type=vsm_vendor', '供应商绩效报表', '绩效报表', 'manage_options', 'vsm-performance', array($this, 'render_performance_page') ); } /** * 渲染绩效报表页面 */ public function render_performance_page() { ?> <div class="wrap"> <h1 class="wp-heading-inline">供应商绩效报表</h1> <hr class="wp-header-end"> <div class="vsm-performance-filters"> <form method="get" action=""> <input type="hidden" name="post_type" value="vsm_vendor"> <input type="hidden" name="page" value="vsm-performance"> <label for="time_range">时间范围:</label> <select name="time_range" id="time_range"> <option value="7days">最近7天</option> <option value="30days">最近30天</option> <option value="90days">最近90天</option> <option value="custom">自定义</option> </select> <div id="custom_date_range" style="display:none; margin-top:10px;"> <label>从:</label> <input type="date" name="date_from" value="<?php echo date('Y-m-d', strtotime('-30 days')); ?>"> <label>到:</label> <input type="date" name="date_to" value="<?php echo date('Y-m-d'); ?>"> </div> <button type="submit" class="button button-primary">筛选</button> </form> </div> <div class="vsm-performance-stats"> <?php $this->display_performance_stats(); ?> </div> <div class="vsm-performance-table"> <?php $this->display_performance_table(); ?> </div> <div class="vsm-performance-charts"> <?php $this->display_performance_charts(); ?> </div> </div> <script> jQuery(document).ready(function($) { $('#time_range').change(function() { if ($(this).val() === 'custom') { $('#custom_date_range').show(); } else { $('#custom_date_range').hide(); } }); }); </script> <?php } /** * 显示绩效统计 */ private function display_performance_stats() { global $wpdb; $stats = array( 'total_vendors' => 0, 'avg_score' => 0, 'top_performer' => '', 'needs_improvement' => 0 ); // 获取所有供应商 $vendors = get_posts(array( 'post_type' => 'vsm_vendor', 'posts_per_page' => -1, 'post_status' => 'publish' )); $stats['total_vendors'] = count($vendors); if ($stats['total_vendors'] > 0) { $total_score = 0; $top_score = 0; foreach ($vendors as $vendor) { $score = get_post_meta($vendor->ID, '_vsm_performance_score', true); $score = $score ? floatval($score) : 0; $total_score += $score; if ($score > $top_score) { $top_score = $score; $stats['top_performer'] = $vendor->post_title; } if ($score < 60) { $stats['needs_improvement']++; } } $stats['avg_score'] = round($total_score / $stats['total_vendors'], 1); } ?> <div class="vsm-stats-grid"> <div class="vsm-stat-card"> <h3>供应商总数</h3> <div class="vsm-stat-number"><?php echo $stats['total_vendors']; ?></div> </div> <div class="vsm-stat-card"> <h3>平均绩效分</h3> <div class="vsm-stat-number"><?php echo $stats['avg_score']; ?></div> </div> <div class="vsm-stat-card"> <h3>最佳供应商</h3> <div class="vsm-stat-number"><?php echo $stats['top_performer']; ?></div> </div> <div class="vsm-stat-card"> <h3>需改进供应商</h3> <div class="vsm-stat-number"><?php echo $stats['needs_improvement']; ?></div> </div> </div> <?php } /** * 显示绩效表格 */ private function display_performance_table() { $vendors = get_posts(array( 'post_type' => 'vsm_vendor', 'posts_per_page' => -1, 'post_status' => 'publish', 'orderby' => 'meta_value_num', 'meta_key' => '_vsm_performance_score', 'order' => 'DESC' )); ?> <table class="wp-list-table widefat fixed striped"> <thead> <tr> <th>供应商名称</th> <th>绩效评分</th> <th>状态</th> <th>准时交货率</th> <th>质量评分</th> <th>沟通评分</th> <th>最后评估时间</th> <th>操作</th> </tr> </thead> <tbody> <?php if (empty($vendors)): ?> <tr> <td colspan="8" style="text-align:center;">暂无供应商数据</td> </tr> <?php else: ?> <?php foreach ($vendors as $vendor): $score = get_post_meta($vendor->ID, '_vsm_performance_score', true); $status = get_post_meta($vendor->ID, '_vsm_status', true); $delivery_rate = get_post_meta($vendor->ID, '_vsm_on_time_delivery', true); $quality = get_post_meta($vendor->ID, '_vsm_quality_rating', true); $communication = get_post_meta($vendor->ID, '_vsm_communication_score', true); $last_evaluated = get_post_meta($vendor->ID, '_vsm_last_evaluated', true); // 确定状态颜色 $status_class = ''; if ($score >= 90) $status_class = 'vsm-status-excellent'; elseif ($score >= 80) $status_class = 'vsm-status-good'; elseif ($score >= 60) $status_class = 'vsm-status-fair'; else $status_class = 'vsm-status-poor'; ?> <tr> <td> <strong> <a href="<?php echo get_edit_post_link($vendor->ID); ?>"> <?php echo esc_html($vendor->post_title); ?> </a> </strong> </td> <td> <div class="vsm-score-bar"> <div class="vsm-score-fill" style="width: <?php echo esc_attr($score); ?>%;"></div> <span class="vsm-score-text"><?php echo esc_html($score); ?></span> </div> </td> <td> <span class="vsm-status-badge <?php echo $status_class; ?>"> <?php echo esc_html($status); ?> </span> </td> <td><?php echo $delivery_rate ? esc_html($delivery_rate) . '%' : 'N/A'; ?></td> <td><?php echo $quality ? esc_html($quality) . '/5' : 'N/A'; ?></td> <td><?php echo $communication ? esc_html($communication) . '/10' : 'N/A'; ?></td> <td><?php echo $last_evaluated ? date('Y-m-d', strtotime($last_evaluated)) : 'N/A'; ?></td> <td> <button class="button button-small vsm-evaluate-btn" data-vendor-id="<?php echo $vendor->ID; ?>"> 重新评估 </button> </td> </tr> <?php endforeach; ?> <?php endif; ?> </tbody> </table> <?php } /** * 记录绩效数据(AJAX接口) */ public function log_performance_ajax() { // 验证nonce if (!check_ajax_referer('vsm_admin_nonce', 'nonce', false)) { wp_die('安全验证失败'); } $vendor_id = intval($_POST['vendor_id']); $metric = sanitize_text_field($_POST['metric']); $value = floatval($_POST['value']); $notes = sanitize_textarea_field($_POST['notes']); if (!$vendor_id || !$metric) { wp_send_json_error('参数错误'); } // 记录绩效数据 $performance_log = get_post_meta($vendor_id, '_vsm_performance_log', true); if (!is_array($performance_log)) { $performance_log = array(); } $log_entry = array( 'timestamp' => current_time('mysql'), 'metric' => $metric, 'value' => $value, 'notes' => $notes, 'recorded_by' => get_current_user_id() ); $performance_log[] = $log_entry; update_post_meta($vendor_id, '_vsm_performance_log', $performance_log); // 更新特定指标 update_post_meta($vendor_id, '_vsm_' . $metric, $value); // 重新计算总分 $this->calculate_vendor_score($vendor_id); wp_send_json_success('绩效数据已记录'); } /** * 计算供应商总分 */ private function calculate_vendor_score($vendor_id) { $total_score = 0; $total_weight = 0; foreach ($this->metrics_weights as $metric => $weight) { $value = get_post_meta($vendor_id, '_vsm_' . $metric, true); if ($value !== '') { // 标准化分数(假设各指标满分100) $normalized_score = min(100, max(0, floatval($value))); $total_score += $normalized_score * $weight; $total_weight += $weight; } } if ($total_weight > 0) { $final_score = round($total_score / $total_weight, 1); update_post_meta($vendor_id, '_vsm_performance_score', $final_score); update_post_meta($vendor_id, '_vsm_last_evaluated', current_time('mysql')); } return $final_score; } /** * 每日绩效计算任务 */ public function calculate_daily_performance() { $vendors = get_posts(array( 'post_type' => 'vsm_vendor', 'posts_per_page' => -1, 'post_status' => 'publish' )); foreach ($vendors as $vendor) { $this->calculate_vendor_score($vendor->ID); } } }
- <?php // 文件路径: includes/class-vendor-frontend.php class VSM_Vendor_Frontend { public function __construct() { // 注册短代码 add_shortcode('vsm_vendor_list', array($this, 'vendor_list_shortcode')); add_shortcode('vsm_vendor_detail', array($this, 'vendor_detail_shortcode')); // 添加供应商模板 add_filter('template_include', array($this, 'vendor_template')); // 注册前端样式和脚本 add_action('wp_enqueue_scripts', array($this, 'enqueue_frontend_assets')); } /** * 供应商列表短代码 */ public function vendor_list_shortcode($atts) { $atts = shortcode_atts(array( 'category' => '', 'limit' => 12, 'columns' => 3, 'show_rating' => 'yes' ), $atts, 'vsm_vendor_list'); $args = array( 'post_type' => 'vsm_vendor', 'posts_per_page' => intval($atts['limit']), 'post_status' => 'publish' ); if (!empty($atts['category'])) { $args['tax_query'] = array( array( 'taxonomy' => 'vsm_vendor_category', 'field' => 'slug', 'terms' => $atts['category'] ) ); } $vendors = new WP_Query($args); if (!$vendors->have_posts()) { return '<p>暂无供应商信息</p>'; } ob_start(); ?> <div class="vsm-vendor-grid vsm-columns-<?php echo esc_attr($atts['columns']); ?>"> <?php while ($vendors->have_posts()): $vendors->the_post(); $vendor_id = get_the_ID(); $score = get_post_meta($vendor_id, '_vsm_performance_score', true); $contact_person = get_post_meta($vendor_id, '_vsm_contact_person', true); $phone = get_post_meta($vendor_id, '_vsm_phone', true); ?> <div class="vsm-vendor-card"> <div class="vsm-vendor-thumbnail"> <?php if (has_post_thumbnail()): ?> <a href="<?php the_permalink(); ?>"> <?php the_post_thumbnail('medium'); ?> </a> <?php endif; ?> </div> <div class="vsm-vendor-content"> <h3 class="vsm-vendor-title"> <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a> </h3> <?php if ($atts['show_rating'] === 'yes' && $score): ?> <div class="vsm-vendor-rating"> <div class="vsm-rating-stars" data-score="<?php echo esc_attr($score); ?>"></div> <span class="vsm-rating-score"><?php echo esc_html($score); ?>分</span> </div> <?php endif; ?> <div class="vsm-vendor-excerpt"> <?php the_excerpt(); ?> </div> <div class="vsm-vendor-meta"> <?php if ($contact_person): ?> <div class="vsm-meta-item"> <span class="dashicons dashicons-businessperson"></span> <?php echo esc_html($contact_person); ?> </div> <?php endif; ?> <?php if ($phone): ?> <div class="vsm-meta-item"> <span class="dashicons dashicons-phone"></span> <?php echo esc_html($phone); ?> </div> <?php endif; ?> </div> <a href="<?php the_permalink(); ?>" class="vsm-view-details"> 查看详情 </a> </div> </div> <?php endwhile; wp_reset_postdata(); ?> </div> <?php if ($vendors->max_num_pages > 1): ?> <div class="vsm-pagination"> <?php echo paginate_links(array( 'total' => $vendors->max_num_pages, 'current' => max(1, get_query_var('paged')), 'prev_text' => '«', 'next_text' => '»' )); ?> </div> <?php endif; return ob_get_clean(); } /** * 供应商详情短代码 */ public function vendor_detail_shortcode($atts) { $atts = shortcode_atts(array( 'id' => 0, 'show_products' => 'yes' ), $atts, 'vsm_vendor_detail'); $vendor_id = intval($atts['id']); if (!$vendor_id || get_post_type($vendor_id) !== 'vsm_vendor') { return '<p>供应商不存在</p>'; } ob_start(); // 设置全局post变量 global $post; $post = get_post($vendor_id); setup_postdata($post); ?> <div class="vsm-vendor-detail"> <div class="vsm-vendor-header"> <div class="vsm-vendor-header-left">
在当今电商和内容管理系统中,供应商管理是企业运营的重要环节。WordPress作为全球最流行的内容管理系统,虽然拥有丰富的插件生态,但针对柔性供应商管理的专业解决方案仍然有限。本教程将带领您从零开始开发一个完整的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('VSM_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('VSM_PLUGIN_URL', plugin_dir_url(__FILE__));
define('VSM_VERSION', '1.0.0');
// 初始化插件
function vsm_init() {
// 检查必要依赖
if (!class_exists('WooCommerce') && !class_exists('Easy_Digital_Downloads')) {
add_action('admin_notices', function() {
echo '<div class="notice notice-warning"><p>供应商管理模块建议与WooCommerce或EDD配合使用</p></div>';
});
}
// 加载核心类
require_once VSM_PLUGIN_DIR . 'includes/class-vendor-manager.php';
require_once VSM_PLUGIN_DIR . 'includes/class-vendor-post-type.php';
require_once VSM_PLUGIN_DIR . 'includes/class-vendor-meta-boxes.php';
}
add_action('plugins_loaded', 'vsm_init');
创建供应商专用的自定义文章类型,这是整个模块的基础:
<?php
// 文件路径: includes/class-vendor-post-type.php
class VSM_Vendor_Post_Type {
public function __construct() {
add_action('init', array($this, 'register_vendor_post_type'));
add_action('init', array($this, 'register_vendor_taxonomies'));
}
/**
* 注册供应商自定义文章类型
*/
public function register_vendor_post_type() {
$labels = array(
'name' => '供应商',
'singular_name' => '供应商',
'menu_name' => '供应商管理',
'add_new' => '添加供应商',
'add_new_item' => '添加新供应商',
'edit_item' => '编辑供应商',
'new_item' => '新供应商',
'view_item' => '查看供应商',
'search_items' => '搜索供应商',
'not_found' => '未找到供应商',
'not_found_in_trash' => '回收站中无供应商'
);
$args = array(
'labels' => $labels,
'public' => true,
'publicly_queryable' => true,
'show_ui' => true,
'show_in_menu' => true,
'query_var' => true,
'rewrite' => array('slug' => 'vendor'),
'capability_type' => 'post',
'has_archive' => true,
'hierarchical' => false,
'menu_position' => 30,
'menu_icon' => 'dashicons-businessperson',
'supports' => array('title', 'editor', 'thumbnail', 'excerpt'),
'show_in_rest' => true, // 支持Gutenberg编辑器
);
register_post_type('vsm_vendor', $args);
}
/**
* 注册供应商分类法
*/
public function register_vendor_taxonomies() {
// 供应商分类
register_taxonomy(
'vsm_vendor_category',
'vsm_vendor',
array(
'labels' => array(
'name' => '供应商分类',
'singular_name' => '供应商分类',
),
'hierarchical' => true,
'show_ui' => true,
'show_admin_column' => true,
'query_var' => true,
'rewrite' => array('slug' => 'vendor-category'),
'show_in_rest' => true,
)
);
// 供应商标签
register_taxonomy(
'vsm_vendor_tag',
'vsm_vendor',
array(
'labels' => array(
'name' => '供应商标签',
'singular_name' => '供应商标签',
),
'hierarchical' => false,
'show_ui' => true,
'show_admin_column' => true,
'query_var' => true,
'rewrite' => array('slug' => 'vendor-tag'),
'show_in_rest' => true,
)
);
}
}
// 初始化类
new VSM_Vendor_Post_Type();
为供应商添加详细的元数据字段,存储供应商的详细信息:
<?php
// 文件路径: includes/class-vendor-meta-boxes.php
class VSM_Vendor_Meta_Boxes {
public function __construct() {
add_action('add_meta_boxes', array($this, 'add_vendor_meta_boxes'));
add_action('save_post_vsm_vendor', array($this, 'save_vendor_meta_data'));
add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'));
}
/**
* 添加供应商元数据框
*/
public function add_vendor_meta_boxes() {
add_meta_box(
'vsm_vendor_details',
'供应商详细信息',
array($this, 'render_vendor_details_meta_box'),
'vsm_vendor',
'normal',
'high'
);
add_meta_box(
'vsm_vendor_performance',
'供应商绩效评估',
array($this, 'render_vendor_performance_meta_box'),
'vsm_vendor',
'side',
'default'
);
}
/**
* 渲染供应商详细信息元数据框
*/
public function render_vendor_details_meta_box($post) {
// 添加安全验证
wp_nonce_field('vsm_vendor_meta_box', 'vsm_vendor_meta_box_nonce');
// 获取现有值
$contact_person = get_post_meta($post->ID, '_vsm_contact_person', true);
$email = get_post_meta($post->ID, '_vsm_email', true);
$phone = get_post_meta($post->ID, '_vsm_phone', true);
$address = get_post_meta($post->ID, '_vsm_address', true);
$website = get_post_meta($post->ID, '_vsm_website', true);
$tax_number = get_post_meta($post->ID, '_vsm_tax_number', true);
$contract_date = get_post_meta($post->ID, '_vsm_contract_date', true);
$contract_expiry = get_post_meta($post->ID, '_vsm_contract_expiry', true);
// 输出HTML表单
?>
<div class="vsm-meta-box">
<table class="form-table">
<tr>
<th><label for="vsm_contact_person">联系人</label></th>
<td>
<input type="text" id="vsm_contact_person" name="vsm_contact_person"
value="<?php echo esc_attr($contact_person); ?>" class="regular-text">
</td>
</tr>
<tr>
<th><label for="vsm_email">邮箱地址</label></th>
<td>
<input type="email" id="vsm_email" name="vsm_email"
value="<?php echo esc_attr($email); ?>" class="regular-text">
</td>
</tr>
<tr>
<th><label for="vsm_phone">联系电话</label></th>
<td>
<input type="tel" id="vsm_phone" name="vsm_phone"
value="<?php echo esc_attr($phone); ?>" class="regular-text">
</td>
</tr>
<tr>
<th><label for="vsm_address">地址</label></th>
<td>
<textarea id="vsm_address" name="vsm_address" rows="3"
class="large-text"><?php echo esc_textarea($address); ?></textarea>
</td>
</tr>
<tr>
<th><label for="vsm_contract_date">合同开始日期</label></th>
<td>
<input type="date" id="vsm_contract_date" name="vsm_contract_date"
value="<?php echo esc_attr($contract_date); ?>">
</td>
</tr>
<tr>
<th><label for="vsm_contract_expiry">合同到期日</label></th>
<td>
<input type="date" id="vsm_contract_expiry" name="vsm_contract_expiry"
value="<?php echo esc_attr($contract_expiry); ?>">
<p class="description">到期前30天将发送提醒邮件</p>
</td>
</tr>
</table>
</div>
<?php
}
/**
* 保存供应商元数据
*/
public function save_vendor_meta_data($post_id) {
// 安全检查
if (!isset($_POST['vsm_vendor_meta_box_nonce']) ||
!wp_verify_nonce($_POST['vsm_vendor_meta_box_nonce'], 'vsm_vendor_meta_box')) {
return;
}
// 检查自动保存
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
// 检查用户权限
if (!current_user_can('edit_post', $post_id)) {
return;
}
// 保存字段数据
$fields = array(
'vsm_contact_person',
'vsm_email',
'vsm_phone',
'vsm_address',
'vsm_website',
'vsm_tax_number',
'vsm_contract_date',
'vsm_contract_expiry'
);
foreach ($fields as $field) {
if (isset($_POST[$field])) {
$value = sanitize_text_field($_POST[$field]);
update_post_meta($post_id, '_' . $field, $value);
}
}
// 自动计算并保存绩效评分
$this->calculate_vendor_performance($post_id);
}
/**
* 计算供应商绩效评分
*/
private function calculate_vendor_performance($vendor_id) {
// 这里可以添加复杂的绩效计算逻辑
// 示例:基于订单完成率、产品质量、交货时间等计算
$base_score = 80; // 基础分
$adjustments = 0; // 调整分
// 模拟计算逻辑
$on_time_delivery = get_post_meta($vendor_id, '_vsm_on_time_delivery', true);
if ($on_time_delivery > 95) {
$adjustments += 10;
} elseif ($on_time_delivery < 80) {
$adjustments -= 15;
}
$quality_rating = get_post_meta($vendor_id, '_vsm_quality_rating', true);
if ($quality_rating > 4.5) {
$adjustments += 10;
} elseif ($quality_rating < 3.0) {
$adjustments -= 20;
}
$final_score = max(0, min(100, $base_score + $adjustments));
update_post_meta($vendor_id, '_vsm_performance_score', $final_score);
// 根据评分设置供应商状态
$status = '良好';
if ($final_score < 60) {
$status = '需改进';
} elseif ($final_score < 80) {
$status = '一般';
} elseif ($final_score >= 90) {
$status = '优秀';
}
update_post_meta($vendor_id, '_vsm_status', $status);
}
/**
* 加载管理端脚本和样式
*/
public function enqueue_admin_scripts($hook) {
global $post_type;
if (($hook == 'post.php' || $hook == 'post-new.php') && $post_type == 'vsm_vendor') {
wp_enqueue_style('vsm-admin-style', VSM_PLUGIN_URL . 'assets/css/admin.css', array(), VSM_VERSION);
wp_enqueue_script('vsm-admin-script', VSM_PLUGIN_URL . 'assets/js/admin.js', array('jquery', 'jquery-ui-datepicker'), VSM_VERSION, true);
// 本地化脚本
wp_localize_script('vsm-admin-script', 'vsm_admin', array(
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('vsm_admin_nonce')
));
}
}
}
new VSM_Vendor_Meta_Boxes();
创建供应商与WooCommerce产品的关联功能:
<?php
// 文件路径: includes/class-vendor-product-relationship.php
class VSM_Vendor_Product_Relationship {
public function __construct() {
// 为产品添加供应商选择框
add_action('woocommerce_product_options_general_product_data', array($this, 'add_vendor_to_product'));
add_action('woocommerce_process_product_meta', array($this, 'save_product_vendor'));
// 在供应商页面显示关联产品
add_action('add_meta_boxes', array($this, 'add_vendor_products_meta_box'));
// 添加供应商筛选到产品列表
add_action('restrict_manage_posts', array($this, 'add_vendor_filter_to_products'));
add_filter('parse_query', array($this, 'filter_products_by_vendor'));
}
/**
* 在产品编辑页面添加供应商选择
*/
public function add_vendor_to_product() {
global $post;
$args = array(
'post_type' => 'vsm_vendor',
'posts_per_page' => -1,
'post_status' => 'publish',
'orderby' => 'title',
'order' => 'ASC'
);
$vendors = get_posts($args);
if (empty($vendors)) {
return;
}
echo '<div class="options_group">';
woocommerce_wp_select(array(
'id' => '_vsm_product_vendor',
'label' => '供应商',
'options' => $this->get_vendors_array($vendors),
'desc_tip' => true,
'description' => '选择该产品的供应商'
));
echo '</div>';
}
/**
* 将供应商转换为选项数组
*/
private function get_vendors_array($vendors) {
$vendors_array = array('' => '选择供应商');
foreach ($vendors as $vendor) {
$vendors_array[$vendor->ID] = $vendor->post_title;
}
return $vendors_array;
}
/**
* 保存产品供应商关联
*/
public function save_product_vendor($product_id) {
if (isset($_POST['_vsm_product_vendor'])) {
$vendor_id = intval($_POST['_vsm_product_vendor']);
update_post_meta($product_id, '_vsm_product_vendor', $vendor_id);
// 同时更新供应商的产品列表
$this->update_vendor_products($vendor_id, $product_id, 'add');
}
}
/**
* 更新供应商的产品列表
*/
private function update_vendor_products($vendor_id, $product_id, $action = 'add') {
$vendor_products = get_post_meta($vendor_id, '_vsm_products', true);
if (!is_array($vendor_products)) {
$vendor_products = array();
}
if ($action === 'add') {
if (!in_array($product_id, $vendor_products)) {
$vendor_products[] = $product_id;
}
} elseif ($action === 'remove') {
$vendor_products = array_diff($vendor_products, array($product_id));
}
update_post_meta($vendor_id, '_vsm_products', $vendor_products);
}
/**
* 在产品列表添加供应商筛选
*/
public function add_vendor_filter_to_products() {
global $post_type;
if ($post_type !== 'product') {
return;
}
$args = array(
'post_type' => 'vsm_vendor',
'posts_per_page' => -1,
'post_status' => 'publish'
);
$vendors = get_posts($args);
if (empty($vendors)) {
return;
}
$current_vendor = isset($_GET['vsm_vendor_filter']) ? $_GET['vsm_vendor_filter'] : '';
echo '<select name="vsm_vendor_filter" id="vsm_vendor_filter">';
echo '<option value="">所有供应商</option>';
foreach ($vendors as $vendor) {
printf(
<?php
// 文件路径: includes/class-vendor-performance.php
class VSM_Vendor_Performance {
private $metrics_weights = array(
'delivery_time' => 0.3,
'quality' => 0.4,
'communication' => 0.2,
'pricing' => 0.1
);
public function __construct() {
add_action('admin_menu', array($this, 'add_performance_page'));
add_action('wp_ajax_vsm_log_performance', array($this, 'log_performance_ajax'));
add_action('vsm_daily_performance_cron', array($this, 'calculate_daily_performance'));
// 注册定时任务
if (!wp_next_scheduled('vsm_daily_performance_cron')) {
wp_schedule_event(time(), 'daily', 'vsm_daily_performance_cron');
}
}
/**
* 添加绩效管理页面
*/
public function add_performance_page() {
add_submenu_page(
'edit.php?post_type=vsm_vendor',
'供应商绩效报表',
'绩效报表',
'manage_options',
'vsm-performance',
array($this, 'render_performance_page')
);
}
/**
* 渲染绩效报表页面
*/
public function render_performance_page() {
?>
<div class="wrap">
<h1 class="wp-heading-inline">供应商绩效报表</h1>
<hr class="wp-header-end">
<div class="vsm-performance-filters">
<form method="get" action="">
<input type="hidden" name="post_type" value="vsm_vendor">
<input type="hidden" name="page" value="vsm-performance">
<label for="time_range">时间范围:</label>
<select name="time_range" id="time_range">
<option value="7days">最近7天</option>
<option value="30days">最近30天</option>
<option value="90days">最近90天</option>
<option value="custom">自定义</option>
</select>
<div id="custom_date_range" style="display:none; margin-top:10px;">
<label>从:</label>
<input type="date" name="date_from" value="<?php echo date('Y-m-d', strtotime('-30 days')); ?>">
<label>到:</label>
<input type="date" name="date_to" value="<?php echo date('Y-m-d'); ?>">
</div>
<button type="submit" class="button button-primary">筛选</button>
</form>
</div>
<div class="vsm-performance-stats">
<?php $this->display_performance_stats(); ?>
</div>
<div class="vsm-performance-table">
<?php $this->display_performance_table(); ?>
</div>
<div class="vsm-performance-charts">
<?php $this->display_performance_charts(); ?>
</div>
</div>
<script>
jQuery(document).ready(function($) {
$('#time_range').change(function() {
if ($(this).val() === 'custom') {
$('#custom_date_range').show();
} else {
$('#custom_date_range').hide();
}
});
});
</script>
<?php
}
/**
* 显示绩效统计
*/
private function display_performance_stats() {
global $wpdb;
$stats = array(
'total_vendors' => 0,
'avg_score' => 0,
'top_performer' => '',
'needs_improvement' => 0
);
// 获取所有供应商
$vendors = get_posts(array(
'post_type' => 'vsm_vendor',
'posts_per_page' => -1,
'post_status' => 'publish'
));
$stats['total_vendors'] = count($vendors);
if ($stats['total_vendors'] > 0) {
$total_score = 0;
$top_score = 0;
foreach ($vendors as $vendor) {
$score = get_post_meta($vendor->ID, '_vsm_performance_score', true);
$score = $score ? floatval($score) : 0;
$total_score += $score;
if ($score > $top_score) {
$top_score = $score;
$stats['top_performer'] = $vendor->post_title;
}
if ($score < 60) {
$stats['needs_improvement']++;
}
}
$stats['avg_score'] = round($total_score / $stats['total_vendors'], 1);
}
?>
<div class="vsm-stats-grid">
<div class="vsm-stat-card">
<h3>供应商总数</h3>
<div class="vsm-stat-number"><?php echo $stats['total_vendors']; ?></div>
</div>
<div class="vsm-stat-card">
<h3>平均绩效分</h3>
<div class="vsm-stat-number"><?php echo $stats['avg_score']; ?></div>
</div>
<div class="vsm-stat-card">
<h3>最佳供应商</h3>
<div class="vsm-stat-number"><?php echo $stats['top_performer']; ?></div>
</div>
<div class="vsm-stat-card">
<h3>需改进供应商</h3>
<div class="vsm-stat-number"><?php echo $stats['needs_improvement']; ?></div>
</div>
</div>
<?php
}
/**
* 显示绩效表格
*/
private function display_performance_table() {
$vendors = get_posts(array(
'post_type' => 'vsm_vendor',
'posts_per_page' => -1,
'post_status' => 'publish',
'orderby' => 'meta_value_num',
'meta_key' => '_vsm_performance_score',
'order' => 'DESC'
));
?>
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th>供应商名称</th>
<th>绩效评分</th>
<th>状态</th>
<th>准时交货率</th>
<th>质量评分</th>
<th>沟通评分</th>
<th>最后评估时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php if (empty($vendors)): ?>
<tr>
<td colspan="8" style="text-align:center;">暂无供应商数据</td>
</tr>
<?php else: ?>
<?php foreach ($vendors as $vendor):
$score = get_post_meta($vendor->ID, '_vsm_performance_score', true);
$status = get_post_meta($vendor->ID, '_vsm_status', true);
$delivery_rate = get_post_meta($vendor->ID, '_vsm_on_time_delivery', true);
$quality = get_post_meta($vendor->ID, '_vsm_quality_rating', true);
$communication = get_post_meta($vendor->ID, '_vsm_communication_score', true);
$last_evaluated = get_post_meta($vendor->ID, '_vsm_last_evaluated', true);
// 确定状态颜色
$status_class = '';
if ($score >= 90) $status_class = 'vsm-status-excellent';
elseif ($score >= 80) $status_class = 'vsm-status-good';
elseif ($score >= 60) $status_class = 'vsm-status-fair';
else $status_class = 'vsm-status-poor';
?>
<tr>
<td>
<strong>
<a href="<?php echo get_edit_post_link($vendor->ID); ?>">
<?php echo esc_html($vendor->post_title); ?>
</a>
</strong>
</td>
<td>
<div class="vsm-score-bar">
<div class="vsm-score-fill" style="width: <?php echo esc_attr($score); ?>%;"></div>
<span class="vsm-score-text"><?php echo esc_html($score); ?></span>
</div>
</td>
<td>
<span class="vsm-status-badge <?php echo $status_class; ?>">
<?php echo esc_html($status); ?>
</span>
</td>
<td><?php echo $delivery_rate ? esc_html($delivery_rate) . '%' : 'N/A'; ?></td>
<td><?php echo $quality ? esc_html($quality) . '/5' : 'N/A'; ?></td>
<td><?php echo $communication ? esc_html($communication) . '/10' : 'N/A'; ?></td>
<td><?php echo $last_evaluated ? date('Y-m-d', strtotime($last_evaluated)) : 'N/A'; ?></td>
<td>
<button class="button button-small vsm-evaluate-btn"
data-vendor-id="<?php echo $vendor->ID; ?>">
重新评估
</button>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
<?php
}
/**
* 记录绩效数据(AJAX接口)
*/
public function log_performance_ajax() {
// 验证nonce
if (!check_ajax_referer('vsm_admin_nonce', 'nonce', false)) {
wp_die('安全验证失败');
}
$vendor_id = intval($_POST['vendor_id']);
$metric = sanitize_text_field($_POST['metric']);
$value = floatval($_POST['value']);
$notes = sanitize_textarea_field($_POST['notes']);
if (!$vendor_id || !$metric) {
wp_send_json_error('参数错误');
}
// 记录绩效数据
$performance_log = get_post_meta($vendor_id, '_vsm_performance_log', true);
if (!is_array($performance_log)) {
$performance_log = array();
}
$log_entry = array(
'timestamp' => current_time('mysql'),
'metric' => $metric,
'value' => $value,
'notes' => $notes,
'recorded_by' => get_current_user_id()
);
$performance_log[] = $log_entry;
update_post_meta($vendor_id, '_vsm_performance_log', $performance_log);
// 更新特定指标
update_post_meta($vendor_id, '_vsm_' . $metric, $value);
// 重新计算总分
$this->calculate_vendor_score($vendor_id);
wp_send_json_success('绩效数据已记录');
}
/**
* 计算供应商总分
*/
private function calculate_vendor_score($vendor_id) {
$total_score = 0;
$total_weight = 0;
foreach ($this->metrics_weights as $metric => $weight) {
$value = get_post_meta($vendor_id, '_vsm_' . $metric, true);
if ($value !== '') {
// 标准化分数(假设各指标满分100)
$normalized_score = min(100, max(0, floatval($value)));
$total_score += $normalized_score * $weight;
$total_weight += $weight;
}
}
if ($total_weight > 0) {
$final_score = round($total_score / $total_weight, 1);
update_post_meta($vendor_id, '_vsm_performance_score', $final_score);
update_post_meta($vendor_id, '_vsm_last_evaluated', current_time('mysql'));
}
return $final_score;
}
/**
* 每日绩效计算任务
*/
public function calculate_daily_performance() {
$vendors = get_posts(array(
'post_type' => 'vsm_vendor',
'posts_per_page' => -1,
'post_status' => 'publish'
));
foreach ($vendors as $vendor) {
$this->calculate_vendor_score($vendor->ID);
}
}
}
<?php
// 文件路径: includes/class-vendor-performance.php
class VSM_Vendor_Performance {
private $metrics_weights = array(
'delivery_time' => 0.3,
'quality' => 0.4,
'communication' => 0.2,
'pricing' => 0.1
);
public function __construct() {
add_action('admin_menu', array($this, 'add_performance_page'));
add_action('wp_ajax_vsm_log_performance', array($this, 'log_performance_ajax'));
add_action('vsm_daily_performance_cron', array($this, 'calculate_daily_performance'));
// 注册定时任务
if (!wp_next_scheduled('vsm_daily_performance_cron')) {
wp_schedule_event(time(), 'daily', 'vsm_daily_performance_cron');
}
}
/**
* 添加绩效管理页面
*/
public function add_performance_page() {
add_submenu_page(
'edit.php?post_type=vsm_vendor',
'供应商绩效报表',
'绩效报表',
'manage_options',
'vsm-performance',
array($this, 'render_performance_page')
);
}
/**
* 渲染绩效报表页面
*/
public function render_performance_page() {
?>
<div class="wrap">
<h1 class="wp-heading-inline">供应商绩效报表</h1>
<hr class="wp-header-end">
<div class="vsm-performance-filters">
<form method="get" action="">
<input type="hidden" name="post_type" value="vsm_vendor">
<input type="hidden" name="page" value="vsm-performance">
<label for="time_range">时间范围:</label>
<select name="time_range" id="time_range">
<option value="7days">最近7天</option>
<option value="30days">最近30天</option>
<option value="90days">最近90天</option>
<option value="custom">自定义</option>
</select>
<div id="custom_date_range" style="display:none; margin-top:10px;">
<label>从:</label>
<input type="date" name="date_from" value="<?php echo date('Y-m-d', strtotime('-30 days')); ?>">
<label>到:</label>
<input type="date" name="date_to" value="<?php echo date('Y-m-d'); ?>">
</div>
<button type="submit" class="button button-primary">筛选</button>
</form>
</div>
<div class="vsm-performance-stats">
<?php $this->display_performance_stats(); ?>
</div>
<div class="vsm-performance-table">
<?php $this->display_performance_table(); ?>
</div>
<div class="vsm-performance-charts">
<?php $this->display_performance_charts(); ?>
</div>
</div>
<script>
jQuery(document).ready(function($) {
$('#time_range').change(function() {
if ($(this).val() === 'custom') {
$('#custom_date_range').show();
} else {
$('#custom_date_range').hide();
}
});
});
</script>
<?php
}
/**
* 显示绩效统计
*/
private function display_performance_stats() {
global $wpdb;
$stats = array(
'total_vendors' => 0,
'avg_score' => 0,
'top_performer' => '',
'needs_improvement' => 0
);
// 获取所有供应商
$vendors = get_posts(array(
'post_type' => 'vsm_vendor',
'posts_per_page' => -1,
'post_status' => 'publish'
));
$stats['total_vendors'] = count($vendors);
if ($stats['total_vendors'] > 0) {
$total_score = 0;
$top_score = 0;
foreach ($vendors as $vendor) {
$score = get_post_meta($vendor->ID, '_vsm_performance_score', true);
$score = $score ? floatval($score) : 0;
$total_score += $score;
if ($score > $top_score) {
$top_score = $score;
$stats['top_performer'] = $vendor->post_title;
}
if ($score < 60) {
$stats['needs_improvement']++;
}
}
$stats['avg_score'] = round($total_score / $stats['total_vendors'], 1);
}
?>
<div class="vsm-stats-grid">
<div class="vsm-stat-card">
<h3>供应商总数</h3>
<div class="vsm-stat-number"><?php echo $stats['total_vendors']; ?></div>
</div>
<div class="vsm-stat-card">
<h3>平均绩效分</h3>
<div class="vsm-stat-number"><?php echo $stats['avg_score']; ?></div>
</div>
<div class="vsm-stat-card">
<h3>最佳供应商</h3>
<div class="vsm-stat-number"><?php echo $stats['top_performer']; ?></div>
</div>
<div class="vsm-stat-card">
<h3>需改进供应商</h3>
<div class="vsm-stat-number"><?php echo $stats['needs_improvement']; ?></div>
</div>
</div>
<?php
}
/**
* 显示绩效表格
*/
private function display_performance_table() {
$vendors = get_posts(array(
'post_type' => 'vsm_vendor',
'posts_per_page' => -1,
'post_status' => 'publish',
'orderby' => 'meta_value_num',
'meta_key' => '_vsm_performance_score',
'order' => 'DESC'
));
?>
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th>供应商名称</th>
<th>绩效评分</th>
<th>状态</th>
<th>准时交货率</th>
<th>质量评分</th>
<th>沟通评分</th>
<th>最后评估时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php if (empty($vendors)): ?>
<tr>
<td colspan="8" style="text-align:center;">暂无供应商数据</td>
</tr>
<?php else: ?>
<?php foreach ($vendors as $vendor):
$score = get_post_meta($vendor->ID, '_vsm_performance_score', true);
$status = get_post_meta($vendor->ID, '_vsm_status', true);
$delivery_rate = get_post_meta($vendor->ID, '_vsm_on_time_delivery', true);
$quality = get_post_meta($vendor->ID, '_vsm_quality_rating', true);
$communication = get_post_meta($vendor->ID, '_vsm_communication_score', true);
$last_evaluated = get_post_meta($vendor->ID, '_vsm_last_evaluated', true);
// 确定状态颜色
$status_class = '';
if ($score >= 90) $status_class = 'vsm-status-excellent';
elseif ($score >= 80) $status_class = 'vsm-status-good';
elseif ($score >= 60) $status_class = 'vsm-status-fair';
else $status_class = 'vsm-status-poor';
?>
<tr>
<td>
<strong>
<a href="<?php echo get_edit_post_link($vendor->ID); ?>">
<?php echo esc_html($vendor->post_title); ?>
</a>
</strong>
</td>
<td>
<div class="vsm-score-bar">
<div class="vsm-score-fill" style="width: <?php echo esc_attr($score); ?>%;"></div>
<span class="vsm-score-text"><?php echo esc_html($score); ?></span>
</div>
</td>
<td>
<span class="vsm-status-badge <?php echo $status_class; ?>">
<?php echo esc_html($status); ?>
</span>
</td>
<td><?php echo $delivery_rate ? esc_html($delivery_rate) . '%' : 'N/A'; ?></td>
<td><?php echo $quality ? esc_html($quality) . '/5' : 'N/A'; ?></td>
<td><?php echo $communication ? esc_html($communication) . '/10' : 'N/A'; ?></td>
<td><?php echo $last_evaluated ? date('Y-m-d', strtotime($last_evaluated)) : 'N/A'; ?></td>
<td>
<button class="button button-small vsm-evaluate-btn"
data-vendor-id="<?php echo $vendor->ID; ?>">
重新评估
</button>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
<?php
}
/**
* 记录绩效数据(AJAX接口)
*/
public function log_performance_ajax() {
// 验证nonce
if (!check_ajax_referer('vsm_admin_nonce', 'nonce', false)) {
wp_die('安全验证失败');
}
$vendor_id = intval($_POST['vendor_id']);
$metric = sanitize_text_field($_POST['metric']);
$value = floatval($_POST['value']);
$notes = sanitize_textarea_field($_POST['notes']);
if (!$vendor_id || !$metric) {
wp_send_json_error('参数错误');
}
// 记录绩效数据
$performance_log = get_post_meta($vendor_id, '_vsm_performance_log', true);
if (!is_array($performance_log)) {
$performance_log = array();
}
$log_entry = array(
'timestamp' => current_time('mysql'),
'metric' => $metric,
'value' => $value,
'notes' => $notes,
'recorded_by' => get_current_user_id()
);
$performance_log[] = $log_entry;
update_post_meta($vendor_id, '_vsm_performance_log', $performance_log);
// 更新特定指标
update_post_meta($vendor_id, '_vsm_' . $metric, $value);
// 重新计算总分
$this->calculate_vendor_score($vendor_id);
wp_send_json_success('绩效数据已记录');
}
/**
* 计算供应商总分
*/
private function calculate_vendor_score($vendor_id) {
$total_score = 0;
$total_weight = 0;
foreach ($this->metrics_weights as $metric => $weight) {
$value = get_post_meta($vendor_id, '_vsm_' . $metric, true);
if ($value !== '') {
// 标准化分数(假设各指标满分100)
$normalized_score = min(100, max(0, floatval($value)));
$total_score += $normalized_score * $weight;
$total_weight += $weight;
}
}
if ($total_weight > 0) {
$final_score = round($total_score / $total_weight, 1);
update_post_meta($vendor_id, '_vsm_performance_score', $final_score);
update_post_meta($vendor_id, '_vsm_last_evaluated', current_time('mysql'));
}
return $final_score;
}
/**
* 每日绩效计算任务
*/
public function calculate_daily_performance() {
$vendors = get_posts(array(
'post_type' => 'vsm_vendor',
'posts_per_page' => -1,
'post_status' => 'publish'
));
foreach ($vendors as $vendor) {
$this->calculate_vendor_score($vendor->ID);
}
}
}
<?php
// 文件路径: includes/class-vendor-frontend.php
class VSM_Vendor_Frontend {
public function __construct() {
// 注册短代码
add_shortcode('vsm_vendor_list', array($this, 'vendor_list_shortcode'));
add_shortcode('vsm_vendor_detail', array($this, 'vendor_detail_shortcode'));
// 添加供应商模板
add_filter('template_include', array($this, 'vendor_template'));
// 注册前端样式和脚本
add_action('wp_enqueue_scripts', array($this, 'enqueue_frontend_assets'));
}
/**
* 供应商列表短代码
*/
public function vendor_list_shortcode($atts) {
$atts = shortcode_atts(array(
'category' => '',
'limit' => 12,
'columns' => 3,
'show_rating' => 'yes'
), $atts, 'vsm_vendor_list');
$args = array(
'post_type' => 'vsm_vendor',
'posts_per_page' => intval($atts['limit']),
'post_status' => 'publish'
);
if (!empty($atts['category'])) {
$args['tax_query'] = array(
array(
'taxonomy' => 'vsm_vendor_category',
'field' => 'slug',
'terms' => $atts['category']
)
);
}
$vendors = new WP_Query($args);
if (!$vendors->have_posts()) {
return '<p>暂无供应商信息</p>';
}
ob_start();
?>
<div class="vsm-vendor-grid vsm-columns-<?php echo esc_attr($atts['columns']); ?>">
<?php while ($vendors->have_posts()): $vendors->the_post();
$vendor_id = get_the_ID();
$score = get_post_meta($vendor_id, '_vsm_performance_score', true);
$contact_person = get_post_meta($vendor_id, '_vsm_contact_person', true);
$phone = get_post_meta($vendor_id, '_vsm_phone', true);
?>
<div class="vsm-vendor-card">
<div class="vsm-vendor-thumbnail">
<?php if (has_post_thumbnail()): ?>
<a href="<?php the_permalink(); ?>">
<?php the_post_thumbnail('medium'); ?>
</a>
<?php endif; ?>
</div>
<div class="vsm-vendor-content">
<h3 class="vsm-vendor-title">
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
</h3>
<?php if ($atts['show_rating'] === 'yes' && $score): ?>
<div class="vsm-vendor-rating">
<div class="vsm-rating-stars" data-score="<?php echo esc_attr($score); ?>"></div>
<span class="vsm-rating-score"><?php echo esc_html($score); ?>分</span>
</div>
<?php endif; ?>
<div class="vsm-vendor-excerpt">
<?php the_excerpt(); ?>
</div>
<div class="vsm-vendor-meta">
<?php if ($contact_person): ?>
<div class="vsm-meta-item">
<span class="dashicons dashicons-businessperson"></span>
<?php echo esc_html($contact_person); ?>
</div>
<?php endif; ?>
<?php if ($phone): ?>
<div class="vsm-meta-item">
<span class="dashicons dashicons-phone"></span>
<?php echo esc_html($phone); ?>
</div>
<?php endif; ?>
</div>
<a href="<?php the_permalink(); ?>" class="vsm-view-details">
查看详情
</a>
</div>
</div>
<?php endwhile; wp_reset_postdata(); ?>
</div>
<?php if ($vendors->max_num_pages > 1): ?>
<div class="vsm-pagination">
<?php
echo paginate_links(array(
'total' => $vendors->max_num_pages,
'current' => max(1, get_query_var('paged')),
'prev_text' => '«',
'next_text' => '»'
));
?>
</div>
<?php endif;
return ob_get_clean();
}
/**
* 供应商详情短代码
*/
public function vendor_detail_shortcode($atts) {
$atts = shortcode_atts(array(
'id' => 0,
'show_products' => 'yes'
), $atts, 'vsm_vendor_detail');
$vendor_id = intval($atts['id']);
if (!$vendor_id || get_post_type($vendor_id) !== 'vsm_vendor') {
return '<p>供应商不存在</p>';
}
ob_start();
// 设置全局post变量
global $post;
$post = get_post($vendor_id);
setup_postdata($post);
?>
<div class="vsm-vendor-detail">
<div class="vsm-vendor-header">
<div class="vsm-vendor-header-left">
<?php
// 文件路径: includes/class-vendor-frontend.php
class VSM_Vendor_Frontend {
public function __construct() {
// 注册短代码
add_shortcode('vsm_vendor_list', array($this, 'vendor_list_shortcode'));
add_shortcode('vsm_vendor_detail', array($this, 'vendor_detail_shortcode'));
// 添加供应商模板
add_filter('template_include', array($this, 'vendor_template'));
// 注册前端样式和脚本
add_action('wp_enqueue_scripts', array($this, 'enqueue_frontend_assets'));
}
/**
* 供应商列表短代码
*/
public function vendor_list_shortcode($atts) {
$atts = shortcode_atts(array(
'category' => '',
'limit' => 12,
'columns' => 3,
'show_rating' => 'yes'
), $atts, 'vsm_vendor_list');
$args = array(
'post_type' => 'vsm_vendor',
'posts_per_page' => intval($atts['limit']),
'post_status' => 'publish'
);
if (!empty($atts['category'])) {
$args['tax_query'] = array(
array(
'taxonomy' => 'vsm_vendor_category',
'field' => 'slug',
'terms' => $atts['category']
)
);
}
$vendors = new WP_Query($args);
if (!$vendors->have_posts()) {
return '<p>暂无供应商信息</p>';
}
ob_start();
?>
<div class="vsm-vendor-grid vsm-columns-<?php echo esc_attr($atts['columns']); ?>">
<?php while ($vendors->have_posts()): $vendors->the_post();
$vendor_id = get_the_ID();
$score = get_post_meta($vendor_id, '_vsm_performance_score', true);
$contact_person = get_post_meta($vendor_id, '_vsm_contact_person', true);
$phone = get_post_meta($vendor_id, '_vsm_phone', true);
?>
<div class="vsm-vendor-card">
<div class="vsm-vendor-thumbnail">
<?php if (has_post_thumbnail()): ?>
<a href="<?php the_permalink(); ?>">
<?php the_post_thumbnail('medium'); ?>
</a>
<?php endif; ?>
</div>
<div class="vsm-vendor-content">
<h3 class="vsm-vendor-title">
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
</h3>
<?php if ($atts['show_rating'] === 'yes' && $score): ?>
<div class="vsm-vendor-rating">
<div class="vsm-rating-stars" data-score="<?php echo esc_attr($score); ?>"></div>
<span class="vsm-rating-score"><?php echo esc_html($score); ?>分</span>
</div>
<?php endif; ?>
<div class="vsm-vendor-excerpt">
<?php the_excerpt(); ?>
</div>
<div class="vsm-vendor-meta">
<?php if ($contact_person): ?>
<div class="vsm-meta-item">
<span class="dashicons dashicons-businessperson"></span>
<?php echo esc_html($contact_person); ?>
</div>
<?php endif; ?>
<?php if ($phone): ?>
<div class="vsm-meta-item">
<span class="dashicons dashicons-phone"></span>
<?php echo esc_html($phone); ?>
</div>
<?php endif; ?>
</div>
<a href="<?php the_permalink(); ?>" class="vsm-view-details">
查看详情
</a>
</div>
</div>
<?php endwhile; wp_reset_postdata(); ?>
</div>
<?php if ($vendors->max_num_pages > 1): ?>
<div class="vsm-pagination">
<?php
echo paginate_links(array(
'total' => $vendors->max_num_pages,
'current' => max(1, get_query_var('paged')),
'prev_text' => '«',
'next_text' => '»'
));
?>
</div>
<?php endif;
return ob_get_clean();
}
/**
* 供应商详情短代码
*/
public function vendor_detail_shortcode($atts) {
$atts = shortcode_atts(array(
'id' => 0,
'show_products' => 'yes'
), $atts, 'vsm_vendor_detail');
$vendor_id = intval($atts['id']);
if (!$vendor_id || get_post_type($vendor_id) !== 'vsm_vendor') {
return '<p>供应商不存在</p>';
}
ob_start();
// 设置全局post变量
global $post;
$post = get_post($vendor_id);
setup_postdata($post);
?>
<div class="vsm-vendor-detail">
<div class="vsm-vendor-header">
<div class="vsm-vendor-header-left">


