首页 / 应用软件 / 详细教程,为WordPress网站开发线上研讨会预约与虚拟会议室管理

详细教程,为WordPress网站开发线上研讨会预约与虚拟会议室管理

详细教程:为WordPress网站开发线上研讨会预约与虚拟会议室管理系统

引言:线上活动管理的数字化需求

在数字化时代,线上研讨会已成为企业、教育机构和组织进行知识分享、产品发布和团队协作的重要方式。然而,许多WordPress网站所有者面临一个共同挑战:如何高效管理线上活动的预约流程和虚拟会议室?虽然市场上有一些插件可用,但它们往往功能有限、价格昂贵或不符合特定需求。

本教程将指导您通过WordPress代码二次开发,创建一个完整的线上研讨会预约与虚拟会议室管理系统。这个解决方案不仅成本效益高,而且完全可定制,能够满足您的特定需求。我们将从系统设计开始,逐步实现预约管理、虚拟会议室集成、自动通知和数据分析等功能。

第一部分:系统架构设计与环境准备

1.1 需求分析与功能规划

在开始编码之前,我们需要明确系统需求:

  1. 预约管理功能:用户可查看 upcoming 研讨会,选择并注册参加
  2. 虚拟会议室集成:自动生成或连接Zoom、Google Meet等平台会议室
  3. 自动化工作流:注册确认、提醒邮件、会议链接发送
  4. 管理后台:活动创建、参与者管理、数据分析
  5. 用户界面:直观的前端展示和响应式设计

1.2 开发环境配置

首先确保您的开发环境满足以下要求:

  • WordPress 5.0以上版本
  • PHP 7.4以上版本
  • MySQL 5.6以上或MariaDB 10.0以上
  • 代码编辑器(如VS Code、Sublime Text)
  • 本地开发环境(如XAMPP、MAMP或Local by Flywheel)

1.3 创建自定义插件

为了避免主题更新导致代码丢失,我们将创建一个独立插件:

  1. wp-content/plugins/目录下创建新文件夹virtual-seminar-manager
  2. 创建主插件文件virtual-seminar-manager.php
<?php
/**
 * Plugin Name: Virtual Seminar Manager
 * Plugin URI: https://yourwebsite.com/
 * Description: 完整的线上研讨会预约与虚拟会议室管理系统
 * Version: 1.0.0
 * Author: Your Name
 * License: GPL v2 or later
 * Text Domain: virtual-seminar
 */

// 防止直接访问
if (!defined('ABSPATH')) {
    exit;
}

// 定义插件常量
define('VSM_VERSION', '1.0.0');
define('VSM_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('VSM_PLUGIN_URL', plugin_dir_url(__FILE__));

// 初始化插件
require_once VSM_PLUGIN_DIR . 'includes/class-init.php';
VSM_Init::register_services();

第二部分:数据库设计与自定义帖子类型

2.1 创建数据库表

我们需要两个自定义表来存储研讨会和预约数据。在插件初始化类中添加以下代码:

// 在includes/class-init.php中
class VSM_Init {
    public static function register_services() {
        // 注册激活钩子
        register_activation_hook(__FILE__, [self::class, 'activate']);
        
        // 注册其他服务
        add_action('init', [self::class, 'register_post_types']);
        add_action('init', [self::class, 'register_taxonomies']);
    }
    
    public static function activate() {
        self::create_tables();
        flush_rewrite_rules();
    }
    
    private static function create_tables() {
        global $wpdb;
        $charset_collate = $wpdb->get_charset_collate();
        
        // 研讨会表
        $seminars_table = $wpdb->prefix . 'vsm_seminars';
        $sql1 = "CREATE TABLE IF NOT EXISTS $seminars_table (
            id mediumint(9) NOT NULL AUTO_INCREMENT,
            post_id bigint(20) NOT NULL,
            start_time datetime NOT NULL,
            end_time datetime NOT NULL,
            max_participants int(11) DEFAULT 100,
            current_participants int(11) DEFAULT 0,
            meeting_platform varchar(50) DEFAULT 'zoom',
            meeting_id varchar(255),
            meeting_password varchar(100),
            meeting_url text,
            status varchar(20) DEFAULT 'scheduled',
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY (id),
            KEY post_id (post_id),
            KEY start_time (start_time)
        ) $charset_collate;";
        
        // 预约表
        $bookings_table = $wpdb->prefix . 'vsm_bookings';
        $sql2 = "CREATE TABLE IF NOT EXISTS $bookings_table (
            id mediumint(9) NOT NULL AUTO_INCREMENT,
            seminar_id mediumint(9) NOT NULL,
            user_id bigint(20),
            user_email varchar(100) NOT NULL,
            user_name varchar(100) NOT NULL,
            booking_time datetime DEFAULT CURRENT_TIMESTAMP,
            confirmation_code varchar(32),
            attendance_status varchar(20) DEFAULT 'registered',
            join_time datetime,
            leave_time datetime,
            notes text,
            PRIMARY KEY (id),
            KEY seminar_id (seminar_id),
            KEY user_email (user_email),
            KEY confirmation_code (confirmation_code)
        ) $charset_collate;";
        
        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
        dbDelta($sql1);
        dbDelta($sql2);
    }
}

2.2 注册自定义帖子类型

创建研讨会自定义帖子类型,使其在WordPress后台可管理:

// 在includes/class-post-types.php中
class VSM_Post_Types {
    public static function register() {
        // 注册研讨会帖子类型
        $labels = array(
            'name' => __('研讨会', 'virtual-seminar'),
            'singular_name' => __('研讨会', 'virtual-seminar'),
            'menu_name' => __('研讨会管理', 'virtual-seminar'),
            'add_new' => __('添加新研讨会', 'virtual-seminar'),
            'add_new_item' => __('添加新研讨会', 'virtual-seminar'),
            'edit_item' => __('编辑研讨会', 'virtual-seminar'),
            'new_item' => __('新研讨会', 'virtual-seminar'),
            'view_item' => __('查看研讨会', 'virtual-seminar'),
            'search_items' => __('搜索研讨会', 'virtual-seminar'),
            'not_found' => __('未找到研讨会', 'virtual-seminar'),
            'not_found_in_trash' => __('回收站中未找到研讨会', 'virtual-seminar')
        );
        
        $args = array(
            'labels' => $labels,
            'public' => true,
            'publicly_queryable' => true,
            'show_ui' => true,
            'show_in_menu' => true,
            'query_var' => true,
            'rewrite' => array('slug' => 'seminar'),
            'capability_type' => 'post',
            'has_archive' => true,
            'hierarchical' => false,
            'menu_position' => 25,
            'menu_icon' => 'dashicons-video-alt3',
            'supports' => array('title', 'editor', 'thumbnail', 'excerpt'),
            'show_in_rest' => true
        );
        
        register_post_type('seminar', $args);
    }
}

第三部分:前端预约界面开发

3.1 创建预约短代码

为了让用户可以在任何页面添加预约界面,我们创建一个短代码:

// 在includes/class-shortcodes.php中
class VSM_Shortcodes {
    public static function init() {
        add_shortcode('seminar_booking', [self::class, 'seminar_booking_shortcode']);
        add_shortcode('seminar_list', [self::class, 'seminar_list_shortcode']);
    }
    
    public static function seminar_booking_shortcode($atts) {
        // 解析短代码属性
        $atts = shortcode_atts(array(
            'seminar_id' => 0,
            'show_title' => 'yes'
        ), $atts, 'seminar_booking');
        
        // 如果没有指定研讨会ID,尝试从当前页面获取
        $seminar_id = $atts['seminar_id'];
        if (!$seminar_id && get_post_type() === 'seminar') {
            $seminar_id = get_the_ID();
        }
        
        if (!$seminar_id) {
            return '<p class="vsm-error">' . __('未指定研讨会', 'virtual-seminar') . '</p>';
        }
        
        // 检查研讨会是否存在且可预约
        $seminar_data = self::get_seminar_data($seminar_id);
        if (!$seminar_data) {
            return '<p class="vsm-error">' . __('研讨会不存在或已结束', 'virtual-seminar') . '</p>';
        }
        
        // 输出预约表单
        ob_start();
        include VSM_PLUGIN_DIR . 'templates/booking-form.php';
        return ob_get_clean();
    }
    
    private static function get_seminar_data($post_id) {
        global $wpdb;
        $table_name = $wpdb->prefix . 'vsm_seminars';
        
        $seminar = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM $table_name WHERE post_id = %d AND status = 'scheduled'",
            $post_id
        ));
        
        if (!$seminar) {
            return false;
        }
        
        // 检查是否还有空位
        if ($seminar->current_participants >= $seminar->max_participants) {
            return false;
        }
        
        return $seminar;
    }
}

3.2 设计预约表单模板

创建templates/booking-form.php模板文件:

<?php
/**
 * 研讨会预约表单模板
 */
// 确保从短代码中调用
if (!isset($seminar_data)) {
    return;
}

// 获取帖子信息
$post = get_post($seminar_data->post_id);
$title = $post->post_title;
$excerpt = $post->post_excerpt;
$thumbnail = get_the_post_thumbnail($post->ID, 'medium');

// 格式化时间
$start_time = date_i18n('Y年m月d日 H:i', strtotime($seminar_data->start_time));
$end_time = date_i18n('H:i', strtotime($seminar_data->end_time));
$remaining = $seminar_data->max_participants - $seminar_data->current_participants;

// 处理表单提交
$submitted = false;
$error = '';
$success = '';

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['vsm_booking_nonce'])) {
    if (wp_verify_nonce($_POST['vsm_booking_nonce'], 'vsm_booking_action')) {
        $result = VSM_Booking_Handler::process_booking($_POST, $seminar_data);
        if ($result['success']) {
            $success = $result['message'];
            $submitted = true;
        } else {
            $error = $result['message'];
        }
    }
}
?>

<div class="vsm-booking-container">
    <?php if ($atts['show_title'] === 'yes') : ?>
    <div class="vsm-seminar-header">
        <?php if ($thumbnail) : ?>
        <div class="vsm-thumbnail">
            <?php echo $thumbnail; ?>
        </div>
        <?php endif; ?>
        
        <h2 class="vsm-title"><?php echo esc_html($title); ?></h2>
        
        <?php if ($excerpt) : ?>
        <div class="vsm-excerpt">
            <?php echo wpautop($excerpt); ?>
        </div>
        <?php endif; ?>
        
        <div class="vsm-meta">
            <div class="vsm-meta-item">
                <span class="dashicons dashicons-calendar-alt"></span>
                <span><?php echo $start_time . ' - ' . $end_time; ?></span>
            </div>
            <div class="vsm-meta-item">
                <span class="dashicons dashicons-groups"></span>
                <span><?php printf(__('剩余席位: %d/%d', 'virtual-seminar'), $remaining, $seminar_data->max_participants); ?></span>
            </div>
        </div>
    </div>
    <?php endif; ?>
    
    <?php if ($success) : ?>
    <div class="vsm-alert vsm-success">
        <?php echo $success; ?>
    </div>
    <?php elseif (!$submitted) : ?>
    
    <?php if ($error) : ?>
    <div class="vsm-alert vsm-error">
        <?php echo $error; ?>
    </div>
    <?php endif; ?>
    
    <form id="vsm-booking-form" method="post" class="vsm-booking-form">
        <?php wp_nonce_field('vsm_booking_action', 'vsm_booking_nonce'); ?>
        <input type="hidden" name="seminar_id" value="<?php echo $seminar_data->id; ?>">
        <input type="hidden" name="post_id" value="<?php echo $seminar_data->post_id; ?>">
        
        <div class="vsm-form-group">
            <label for="vsm_user_name"><?php _e('姓名', 'virtual-seminar'); ?> *</label>
            <input type="text" id="vsm_user_name" name="user_name" required 
                   placeholder="<?php _e('请输入您的姓名', 'virtual-seminar'); ?>">
        </div>
        
        <div class="vsm-form-group">
            <label for="vsm_user_email"><?php _e('电子邮箱', 'virtual-seminar'); ?> *</label>
            <input type="email" id="vsm_user_email" name="user_email" required 
                   placeholder="<?php _e('请输入您的邮箱地址', 'virtual-seminar'); ?>">
            <small class="vsm-help-text"><?php _e('会议链接将发送到此邮箱', 'virtual-seminar'); ?></small>
        </div>
        
        <div class="vsm-form-group">
            <label for="vsm_user_phone"><?php _e('手机号码', 'virtual-seminar'); ?></label>
            <input type="tel" id="vsm_user_phone" name="user_phone" 
                   placeholder="<?php _e('请输入您的手机号码', 'virtual-seminar'); ?>">
        </div>
        
        <div class="vsm-form-group">
            <label for="vsm_user_company"><?php _e('公司/机构', 'virtual-seminar'); ?></label>
            <input type="text" id="vsm_user_company" name="user_company" 
                   placeholder="<?php _e('请输入您的公司或机构名称', 'virtual-seminar'); ?>">
        </div>
        
        <div class="vsm-form-group">
            <label for="vsm_notes"><?php _e('备注或问题', 'virtual-seminar'); ?></label>
            <textarea id="vsm_notes" name="notes" rows="3" 
                      placeholder="<?php _e('如有特殊需求或问题,请在此说明', 'virtual-seminar'); ?>"></textarea>
        </div>
        
        <div class="vsm-form-group vsm-consent">
            <input type="checkbox" id="vsm_consent" name="consent" required>
            <label for="vsm_consent">
                <?php _e('我同意接收关于此研讨会的通知和后续信息', 'virtual-seminar'); ?>
            </label>
        </div>
        
        <div class="vsm-form-submit">
            <button type="submit" class="vsm-submit-btn">
                <?php _e('立即预约', 'virtual-seminar'); ?>
            </button>
        </div>
    </form>
    
    <?php endif; ?>
</div>

第四部分:虚拟会议室集成

4.1 Zoom API集成

我们将集成Zoom API来自动创建会议室。首先创建Zoom API处理类:

// 在includes/class-zoom-integration.php中
class VSM_Zoom_Integration {
    private $api_key;
    private $api_secret;
    private $account_id; // JWT应用需要
    private $client_id; // OAuth应用需要
    private $client_secret; // OAuth应用需要
    private $access_token;
    
    public function __construct() {
        $options = get_option('vsm_zoom_settings');
        $this->api_key = $options['api_key'] ?? '';
        $this->api_secret = $options['api_secret'] ?? '';
        $this->account_id = $options['account_id'] ?? '';
        $this->client_id = $options['client_id'] ?? '';
        $this->client_secret = $options['client_secret'] ?? '';
        
        // 获取或刷新访问令牌
        $this->access_token = $this->get_access_token();
    }
    
    /**
     * 获取OAuth访问令牌
     */
    private function get_access_token() {
        $token_data = get_transient('vsm_zoom_access_token');
        
        if (!$token_data) {
            // 使用OAuth 2.0获取新令牌
            $response = wp_remote_post('https://zoom.us/oauth/token', [
                'headers' => [
                    'Authorization' => 'Basic ' . base64_encode($this->client_id . ':' . $this->client_secret),
                    'Content-Type' => 'application/x-www-form-urlencoded'
                ],
                'body' => [
                    'grant_type' => 'account_credentials',
                    'account_id' => $this->account_id
                ]
            ]);
            
            if (!is_wp_error($response)) {
                $body = json_decode(wp_remote_retrieve_body($response));
                if (isset($body->access_token)) {
                    $token_data = $body->access_token;
                    // 令牌通常有效1小时,我们设置55分钟过期
                    set_transient('vsm_zoom_access_token', $token_data, 55 * MINUTE_IN_SECONDS);
                }
            }
        }
        
        return $token_data;
    }
    
    /**
     * 创建Zoom会议
     */
    public function create_meeting($seminar_data) {

/v2/users/me/meetings', [

        'headers' => [
            'Authorization' => 'Bearer ' . $this->access_token,
            'Content-Type' => 'application/json'
        ],
        'body' => json_encode([
            'topic' => $seminar_data['title'],
            'type' => 2, // 预定会议
            'start_time' => $seminar_data['start_time'],
            'duration' => $seminar_data['duration'],
            'timezone' => wp_timezone_string(),
            'password' => wp_generate_password(6, false), // 生成随机密码
            'settings' => [
                'host_video' => true,
                'participant_video' => true,
                'join_before_host' => false,
                'mute_upon_entry' => true,
                'waiting_room' => true,
                'auto_recording' => 'cloud' // 可选:none, local, cloud
            ]
        ])
    ]);
    
    if (is_wp_error($response)) {
        return [
            'success' => false,
            'error' => $response->get_error_message()
        ];
    }
    
    $body = json_decode(wp_remote_retrieve_body($response), true);
    
    if (isset($body['code'])) {
        return [
            'success' => false,
            'error' => $body['message']
        ];
    }
    
    return [
        'success' => true,
        'meeting_id' => $body['id'],
        'meeting_password' => $body['password'],
        'join_url' => $body['join_url'],
        'start_url' => $body['start_url'] // 主持人链接
    ];
}

/**
 * 更新Zoom会议
 */
public function update_meeting($meeting_id, $data) {
    $response = wp_remote_request("https://api.zoom.us/v2/meetings/{$meeting_id}", [
        'method' => 'PATCH',
        'headers' => [
            'Authorization' => 'Bearer ' . $this->access_token,
            'Content-Type' => 'application/json'
        ],
        'body' => json_encode($data)
    ]);
    
    return !is_wp_error($response);
}

/**
 * 删除Zoom会议
 */
public function delete_meeting($meeting_id) {
    $response = wp_remote_request("https://api.zoom.us/v2/meetings/{$meeting_id}", [
        'method' => 'DELETE',
        'headers' => [
            'Authorization' => 'Bearer ' . $this->access_token
        ]
    ]);
    
    return !is_wp_error($response);
}

}


### 4.2 Google Meet集成(替代方案)

// 在includes/class-google-meet-integration.php中
class VSM_Google_Meet_Integration {

private $client;
private $service;

public function __construct() {
    $this->init_client();
}

private function init_client() {
    require_once VSM_PLUGIN_DIR . 'vendor/autoload.php'; // 需要Google API客户端库
    
    $options = get_option('vsm_google_settings');
    $credentials = $options['credentials'] ?? '';
    
    if (!$credentials) {
        return false;
    }
    
    try {
        $this->client = new Google_Client();
        $this->client->setApplicationName('Virtual Seminar Manager');
        $this->client->setAuthConfig(json_decode($credentials, true));
        $this->client->addScope(Google_Service_Calendar::CALENDAR);
        
        // 检查是否有存储的令牌
        $token_path = VSM_PLUGIN_DIR . 'tokens/google-token.json';
        if (file_exists($token_path)) {
            $access_token = json_decode(file_get_contents($token_path), true);
            $this->client->setAccessToken($access_token);
        }
        
        // 如果令牌过期,刷新它
        if ($this->client->isAccessTokenExpired()) {
            if ($this->client->getRefreshToken()) {
                $this->client->fetchAccessTokenWithRefreshToken();
                file_put_contents($token_path, json_encode($this->client->getAccessToken()));
            }
        }
        
        $this->service = new Google_Service_Calendar($this->client);
        return true;
    } catch (Exception $e) {
        error_log('Google Meet初始化失败: ' . $e->getMessage());
        return false;
    }
}

/**
 * 创建Google Calendar事件并生成Meet链接
 */
public function create_meeting($seminar_data) {
    if (!$this->service) {
        return [
            'success' => false,
            'error' => 'Google服务未初始化'
        ];
    }
    
    try {
        // 创建日历事件
        $event = new Google_Service_Calendar_Event([
            'summary' => $seminar_data['title'],
            'description' => $seminar_data['description'],
            'start' => [
                'dateTime' => $seminar_data['start_time'],
                'timeZone' => wp_timezone_string(),
            ],
            'end' => [
                'dateTime' => $seminar_data['end_time'],
                'timeZone' => wp_timezone_string(),
            ],
            'conferenceData' => [
                'createRequest' => [
                    'requestId' => uniqid(),
                    'conferenceSolutionKey' => [
                        'type' => 'hangoutsMeet'
                    ]
                ]
            ],
            'attendees' => [
                ['email' => $seminar_data['organizer_email']]
            ],
            'reminders' => [
                'useDefault' => false,
                'overrides' => [
                    ['method' => 'email', 'minutes' => 24 * 60], // 提前1天
                    ['method' => 'popup', 'minutes' => 30] // 提前30分钟
                ]
            ]
        ]);
        
        $created_event = $this->service->events->insert('primary', $event, [
            'conferenceDataVersion' => 1
        ]);
        
        return [
            'success' => true,
            'meeting_id' => $created_event->getId(),
            'join_url' => $created_event->getHangoutLink(),
            'html_link' => $created_event->getHtmlLink()
        ];
        
    } catch (Exception $e) {
        return [
            'success' => false,
            'error' => $e->getMessage()
        ];
    }
}

}


## 第五部分:预约处理与数据库操作

### 5.1 预约处理类

// 在includes/class-booking-handler.php中
class VSM_Booking_Handler {


public static function process_booking($data, $seminar_data) {
    global $wpdb;
    
    // 验证数据
    $validation = self::validate_booking_data($data);
    if (!$validation['valid']) {
        return [
            'success' => false,
            'message' => $validation['message']
        ];
    }
    
    // 检查是否已预约
    $bookings_table = $wpdb->prefix . 'vsm_bookings';
    $existing_booking = $wpdb->get_var($wpdb->prepare(
        "SELECT COUNT(*) FROM $bookings_table 
         WHERE seminar_id = %d AND user_email = %s",
        $seminar_data->id,
        sanitize_email($data['user_email'])
    ));
    
    if ($existing_booking > 0) {
        return [
            'success' => false,
            'message' => __('您已经预约了此研讨会', 'virtual-seminar')
        ];
    }
    
    // 检查是否还有空位
    if ($seminar_data->current_participants >= $seminar_data->max_participants) {
        return [
            'success' => false,
            'message' => __('研讨会名额已满', 'virtual-seminar')
        ];
    }
    
    // 生成确认码
    $confirmation_code = wp_generate_password(12, false);
    
    // 插入预约记录
    $insert_result = $wpdb->insert(
        $bookings_table,
        [
            'seminar_id' => $seminar_data->id,
            'user_id' => is_user_logged_in() ? get_current_user_id() : 0,
            'user_email' => sanitize_email($data['user_email']),
            'user_name' => sanitize_text_field($data['user_name']),
            'confirmation_code' => $confirmation_code,
            'notes' => sanitize_textarea_field($data['notes'] ?? '')
        ],
        ['%d', '%d', '%s', '%s', '%s', '%s']
    );
    
    if (!$insert_result) {
        return [
            'success' => false,
            'message' => __('预约失败,请稍后重试', 'virtual-seminar')
        ];
    }
    
    $booking_id = $wpdb->insert_id;
    
    // 更新研讨会参与人数
    $seminars_table = $wpdb->prefix . 'vsm_seminars';
    $wpdb->update(
        $seminars_table,
        ['current_participants' => $seminar_data->current_participants + 1],
        ['id' => $seminar_data->id],
        ['%d'],
        ['%d']
    );
    
    // 发送确认邮件
    self::send_confirmation_email($booking_id, $confirmation_code, $seminar_data, $data);
    
    // 发送给管理员的通知
    self::send_admin_notification($booking_id, $seminar_data, $data);
    
    return [
        'success' => true,
        'message' => __('预约成功!确认邮件已发送到您的邮箱。', 'virtual-seminar'),
        'booking_id' => $booking_id,
        'confirmation_code' => $confirmation_code
    ];
}

private static function validate_booking_data($data) {
    // 验证必填字段
    $required_fields = ['user_name', 'user_email', 'seminar_id'];
    foreach ($required_fields as $field) {
        if (empty($data[$field])) {
            return [
                'valid' => false,
                'message' => __('请填写所有必填字段', 'virtual-seminar')
            ];
        }
    }
    
    // 验证邮箱格式
    if (!is_email($data['user_email'])) {
        return [
            'valid' => false,
            'message' => __('请输入有效的邮箱地址', 'virtual-seminar')
        ];
    }
    
    // 验证同意条款
    if (!isset($data['consent']) || $data['consent'] !== 'on') {
        return [
            'valid' => false,
            'message' => __('请同意接收研讨会相关信息', 'virtual-seminar')
        ];
    }
    
    return ['valid' => true];
}

private static function send_confirmation_email($booking_id, $confirmation_code, $seminar_data, $user_data) {
    $post = get_post($seminar_data->post_id);
    $start_time = date_i18n('Y年m月d日 H:i', strtotime($seminar_data->start_time));
    
    $to = $user_data['user_email'];
    $subject = sprintf(__('研讨会预约确认: %s', 'virtual-seminar'), $post->post_title);
    
    // 构建邮件内容
    $message = sprintf(__('尊敬的 %s,', 'virtual-seminar'), $user_data['user_name']) . "nn";
    $message .= sprintf(__('您已成功预约研讨会: %s', 'virtual-seminar'), $post->post_title) . "n";
    $message .= sprintf(__('时间: %s', 'virtual-seminar'), $start_time) . "nn";
    
    // 如果有会议链接,添加到邮件中
    if (!empty($seminar_data->meeting_url)) {
        $message .= __('会议链接: ', 'virtual-seminar') . $seminar_data->meeting_url . "n";
        if (!empty($seminar_data->meeting_password)) {
            $message .= __('会议密码: ', 'virtual-seminar') . $seminar_data->meeting_password . "n";
        }
    } else {
        $message .= __('会议链接将在研讨会开始前发送给您。', 'virtual-seminar') . "n";
    }
    
    $message .= "n" . __('您的预约确认码: ', 'virtual-seminar') . $confirmation_code . "n";
    $message .= __('如需取消预约,请访问: ', 'virtual-seminar') . home_url('/cancel-booking/?code=' . $confirmation_code) . "nn";
    $message .= __('感谢您的参与!', 'virtual-seminar') . "n";
    $message .= get_bloginfo('name');
    
    // 设置邮件头
    $headers = ['Content-Type: text/plain; charset=UTF-8'];
    
    // 发送邮件
    wp_mail($to, $subject, $message, $headers);
    
    // 记录邮件发送日志
    self::log_email_sent($booking_id, 'confirmation', $to);
}

private static function send_admin_notification($booking_id, $seminar_data, $user_data) {
    $admin_email = get_option('admin_email');
    $post = get_post($seminar_data->post_id);
    
    $subject = sprintf(__('新研讨会预约: %s', 'virtual-seminar'), $post->post_title);
    
    $message = sprintf(__('有新的研讨会预约:', 'virtual-seminar')) . "nn";
    $message .= sprintf(__('研讨会: %s', 'virtual-seminar'), $post->post_title) . "n";
    $message .= sprintf(__('预约人: %s', 'virtual-seminar'), $user_data['user_name']) . "n";
    $message .= sprintf(__('邮箱: %s', 'virtual-seminar'), $user_data['user_email']) . "n";
    $message .= sprintf(__('预约时间: %s', 'virtual-seminar'), current_time('mysql')) . "n";
    $message .= sprintf(__('预约ID: %d', 'virtual-seminar'), $booking_id) . "nn";
    
    if (!empty($user_data['user_phone'])) {
        $message .= sprintf(__('电话: %s', 'virtual-seminar'), $user_data['user_phone']) . "n";
    }
    
    if (!empty($user_data['user_company'])) {
        $message .= sprintf(__('公司: %s', 'virtual-seminar'), $user_data['user_company']) . "n";
    }
    
    if (!empty($user_data['notes'])) {
        $message .= sprintf(__('备注: %s', 'virtual-seminar'), $user_data['notes']) . "n";
    }
    
    $message .= "n" . __('查看所有预约: ', 'virtual-seminar') . admin_url('admin.php?page=vsm-bookings&seminar_id=' . $seminar_data->id);
    
    wp_mail($admin_email, $subject, $message);
}

private static function log_email_sent($booking_id, $type, $recipient) {
    global $wpdb;
    $table_name = $wpdb->prefix . 'vsm_email_logs';
    
    $wpdb->insert(
        $table_name,
        [
            'booking_id' => $booking_id,
            'email_type' => $type,
            'recipient' => $recipient,
            'sent_at' => current_time('mysql')
        ],
        ['%d', '%s', '%s', '%s']
    );
}

}


## 第六部分:后台管理界面

### 6.1 创建管理菜单

// 在includes/class-admin.php中
class VSM_Admin {


public static function init() {
    add_action('admin_menu', [self::class, 'add_admin_menu']);
    add_action('admin_enqueue_scripts', [self::class, 'enqueue_admin_scripts']);
    add_action('add_meta_boxes', [self::class, 'add_seminar_meta_boxes']);
    add_action('save_post_seminar', [self::class, 'save_seminar_meta'], 10, 2);
}

public static function add_admin_menu() {
    // 主菜单
    add_menu_page(
        __('研讨会管理', 'virtual-seminar'),
        __('研讨会管理', 'virtual-seminar'),
        'manage_options',
        'vsm-dashboard',
        [self::class, 'render_dashboard'],
        'dashicons-video-alt3',
        30
    );
    
    // 子菜单
    add_submenu_page(
        'vsm-dashboard',
        __('所有预约', 'virtual-seminar'),
        __('所有预约', 'virtual-seminar'),
        'manage_options',
        'vsm-bookings',
        [self::class, 'render_bookings_page']
    );
    
    add_submenu_page(
        'vsm-dashboard',
        __('设置', 'virtual-seminar'),
        __('设置', 'virtual-seminar'),
        'manage_options',
        'vsm-settings',
        [self::class, 'render_settings_page']
    );
    
    add_submenu_page(
        'vsm-dashboard',
        __('报告', 'virtual-seminar'),
        __('报告', 'virtual-seminar'),
        'manage_options',
        'vsm-reports',
        [self::class, 'render_reports_page']
    );
}

public static function render_dashboard() {
    global $wpdb;
    
    // 获取统计数据
    $seminars_table = $wpdb->prefix . 'vsm_seminars';
    $bookings_table = $wpdb->prefix . 'vsm_bookings';
    
    $total_seminars = $wpdb->get_var("SELECT COUNT(*) FROM $seminars_table");
    $upcoming_seminars = $wpdb->get_var($wpdb->prepare(
        "SELECT COUNT(*) FROM $seminars_table WHERE start_time > %s",
        current_time('mysql')
    ));
    $total_bookings = $wpdb->get_var("SELECT COUNT(*) FROM $bookings_table");
    $today_bookings = $wpdb->get_var($wpdb->prepare(
        "SELECT COUNT(*) FROM $bookings_table WHERE DATE(booking_time) = %s",
        current_time('Y-m-d')
    ));
    
   
本文来自网络,不代表柔性供应链服务中心立场,转载请注明出处:https://mall.org.cn/5371.html

EXCHANGES®作者

上一篇
下一篇

为您推荐

发表回复

联系我们

联系我们

18559313275

在线咨询: QQ交谈

邮箱: vip@exchanges.center

工作时间:周一至周五,9:00-17:30,节假日休息
返回顶部