首页 / 应用软件 / 实战教程,为你的网站集成在线预约与日程管理

实战教程,为你的网站集成在线预约与日程管理

实战教程:为你的网站集成在线预约与日程管理

引言:为什么网站需要在线预约与日程管理功能

在数字化时代,用户体验已成为网站成功的关键因素之一。无论是服务型企业、医疗机构、教育机构还是自由职业者,能够提供便捷的在线预约功能,不仅能显著提升客户满意度,还能大幅提高工作效率。想象一下,一位潜在客户访问您的网站,对您的服务感兴趣,却需要打电话或发邮件才能预约,这种额外的步骤可能导致客户流失。

WordPress作为全球最流行的内容管理系统,拥有超过40%的网站市场份额。其强大的可扩展性使得我们可以通过代码二次开发,为网站添加各种实用功能。本教程将详细指导您如何为WordPress网站集成在线预约与日程管理功能,无需依赖昂贵的第三方插件,完全自主控制数据与用户体验。

第一部分:准备工作与环境搭建

1.1 开发环境要求

在开始之前,请确保您的开发环境满足以下要求:

  • WordPress 5.0或更高版本
  • PHP 7.4或更高版本(推荐PHP 8.0+)
  • MySQL 5.6或更高版本
  • 基本的HTML、CSS、JavaScript知识
  • 对WordPress主题开发有一定了解

1.2 创建开发用子主题

为了避免直接修改主题文件导致更新时丢失更改,我们首先创建一个子主题:

  1. 在WordPress的wp-content/themes/目录下创建新文件夹,命名为my-custom-booking-theme
  2. 在该文件夹中创建style.css文件,添加以下内容:
/*
Theme Name: 我的预约主题
Template: twentytwentythree
Version: 1.0
Description: 用于在线预约功能的子主题
*/

/* 在这里添加自定义样式 */
  1. 创建functions.php文件,用于添加自定义功能:
<?php
// 子主题的functions.php文件

// 添加父主题样式表
add_action('wp_enqueue_scripts', 'my_theme_enqueue_styles');
function my_theme_enqueue_styles() {
    wp_enqueue_style('parent-style', get_template_directory_uri() . '/style.css');
    wp_enqueue_style('child-style', get_stylesheet_directory_uri() . '/style.css', array('parent-style'));
}

// 在这里添加自定义功能
?>
  1. 在WordPress后台激活这个子主题。

1.3 安装必要的开发工具

为了高效开发,建议安装以下工具:

  • 代码编辑器(如VS Code、Sublime Text等)
  • 本地开发环境(如XAMPP、MAMP或Local by Flywheel)
  • 浏览器开发者工具
  • Git版本控制系统(可选但推荐)

第二部分:数据库设计与数据模型

2.1 设计预约数据表结构

我们需要创建自定义数据库表来存储预约信息。在WordPress中,我们可以使用dbDelta()函数来创建和更新表结构。

在子主题的functions.php文件中添加以下代码:

// 创建预约数据表
function create_booking_tables() {
    global $wpdb;
    
    $table_name = $wpdb->prefix . 'bookings';
    $charset_collate = $wpdb->get_charset_collate();
    
    $sql = "CREATE TABLE $table_name (
        id mediumint(9) NOT NULL AUTO_INCREMENT,
        customer_name varchar(100) NOT NULL,
        customer_email varchar(100) NOT NULL,
        customer_phone varchar(20),
        service_type varchar(100) NOT NULL,
        booking_date date NOT NULL,
        booking_time time NOT NULL,
        duration int NOT NULL DEFAULT 60,
        status varchar(20) DEFAULT 'pending',
        notes text,
        created_at datetime DEFAULT CURRENT_TIMESTAMP,
        updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        PRIMARY KEY (id),
        KEY booking_date (booking_date),
        KEY status (status)
    ) $charset_collate;";
    
    require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    dbDelta($sql);
    
    // 创建服务类型表
    $services_table = $wpdb->prefix . 'booking_services';
    $services_sql = "CREATE TABLE $services_table (
        id mediumint(9) NOT NULL AUTO_INCREMENT,
        service_name varchar(100) NOT NULL,
        description text,
        duration int NOT NULL DEFAULT 60,
        price decimal(10,2),
        is_active tinyint(1) DEFAULT 1,
        PRIMARY KEY (id)
    ) $charset_collate;";
    
    dbDelta($services_sql);
    
    // 创建员工/资源表
    $staff_table = $wpdb->prefix . 'booking_staff';
    $staff_sql = "CREATE TABLE $staff_table (
        id mediumint(9) NOT NULL AUTO_INCREMENT,
        staff_name varchar(100) NOT NULL,
        email varchar(100),
        services text, // 可提供的服务ID,用逗号分隔
        working_hours text, // JSON格式的工作时间
        is_active tinyint(1) DEFAULT 1,
        PRIMARY KEY (id)
    ) $charset_collate;";
    
    dbDelta($staff_sql);
}
add_action('after_setup_theme', 'create_booking_tables');

2.2 设计日程管理数据模型

除了预约信息,我们还需要管理日程可用性:

// 创建可用时间段表
function create_availability_tables() {
    global $wpdb;
    
    $table_name = $wpdb->prefix . 'booking_availability';
    $charset_collate = $wpdb->get_charset_collate();
    
    $sql = "CREATE TABLE $table_name (
        id mediumint(9) NOT NULL AUTO_INCREMENT,
        staff_id mediumint(9),
        date date NOT NULL,
        start_time time NOT NULL,
        end_time time NOT NULL,
        max_bookings int DEFAULT 1,
        booked_count int DEFAULT 0,
        is_available tinyint(1) DEFAULT 1,
        PRIMARY KEY (id),
        KEY date (date),
        KEY staff_id (staff_id)
    ) $charset_collate;";
    
    require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    dbDelta($sql);
}
add_action('after_setup_theme', 'create_availability_tables');

第三部分:创建预约前端界面

3.1 设计预约表单短代码

我们将创建一个短代码,可以在任何页面或文章中添加预约表单:

// 预约表单短代码
function booking_form_shortcode($atts) {
    ob_start();
    
    // 获取短代码属性
    $atts = shortcode_atts(array(
        'service_id' => '',
        'staff_id' => '',
    ), $atts);
    
    // 加载预约表单
    include(get_stylesheet_directory() . '/templates/booking-form.php');
    
    return ob_get_clean();
}
add_shortcode('booking_form', 'booking_form_shortcode');

3.2 创建预约表单HTML模板

在子主题目录下创建templates文件夹,然后创建booking-form.php文件:

<div class="booking-container">
    <div class="booking-progress">
        <div class="step active" data-step="1">选择服务</div>
        <div class="step" data-step="2">选择时间</div>
        <div class="step" data-step="3">填写信息</div>
        <div class="step" data-step="4">确认预约</div>
    </div>
    
    <form id="booking-form" method="post" action="<?php echo admin_url('admin-ajax.php'); ?>">
        <!-- 步骤1:选择服务 -->
        <div class="booking-step step-1 active">
            <h3>选择服务类型</h3>
            <div class="service-options">
                <?php
                global $wpdb;
                $services_table = $wpdb->prefix . 'booking_services';
                $services = $wpdb->get_results("SELECT * FROM $services_table WHERE is_active = 1");
                
                foreach($services as $service) {
                    echo '<div class="service-option" data-service-id="' . $service->id . '">';
                    echo '<h4>' . esc_html($service->service_name) . '</h4>';
                    echo '<p>' . esc_html($service->description) . '</p>';
                    echo '<div class="service-meta">';
                    echo '<span class="duration">' . $service->duration . '分钟</span>';
                    if($service->price) {
                        echo '<span class="price">¥' . number_format($service->price, 2) . '</span>';
                    }
                    echo '</div>';
                    echo '</div>';
                }
                ?>
            </div>
            <button type="button" class="btn-next" data-next-step="2">下一步</button>
        </div>
        
        <!-- 步骤2:选择日期和时间 -->
        <div class="booking-step step-2">
            <h3>选择预约时间</h3>
            <div class="date-selector">
                <div class="month-navigation">
                    <button type="button" class="prev-month">&lt;</button>
                    <h4 class="current-month"></h4>
                    <button type="button" class="next-month">&gt;</button>
                </div>
                <div class="calendar"></div>
            </div>
            <div class="time-slots">
                <h4>可用时间段</h4>
                <div class="slots-container"></div>
            </div>
            <div class="step-buttons">
                <button type="button" class="btn-prev" data-prev-step="1">上一步</button>
                <button type="button" class="btn-next" data-next-step="3">下一步</button>
            </div>
        </div>
        
        <!-- 步骤3:填写个人信息 -->
        <div class="booking-step step-3">
            <h3>填写个人信息</h3>
            <div class="form-group">
                <label for="customer_name">姓名 *</label>
                <input type="text" id="customer_name" name="customer_name" required>
            </div>
            <div class="form-group">
                <label for="customer_email">邮箱 *</label>
                <input type="email" id="customer_email" name="customer_email" required>
            </div>
            <div class="form-group">
                <label for="customer_phone">电话</label>
                <input type="tel" id="customer_phone" name="customer_phone">
            </div>
            <div class="form-group">
                <label for="notes">备注</label>
                <textarea id="notes" name="notes" rows="3"></textarea>
            </div>
            <div class="step-buttons">
                <button type="button" class="btn-prev" data-prev-step="2">上一步</button>
                <button type="button" class="btn-next" data-next-step="4">下一步</button>
            </div>
        </div>
        
        <!-- 步骤4:确认预约 -->
        <div class="booking-step step-4">
            <h3>确认预约信息</h3>
            <div class="booking-summary">
                <div class="summary-item">
                    <strong>服务:</strong>
                    <span id="summary-service"></span>
                </div>
                <div class="summary-item">
                    <strong>日期:</strong>
                    <span id="summary-date"></span>
                </div>
                <div class="summary-item">
                    <strong>时间:</strong>
                    <span id="summary-time"></span>
                </div>
                <div class="summary-item">
                    <strong>姓名:</strong>
                    <span id="summary-name"></span>
                </div>
                <div class="summary-item">
                    <strong>邮箱:</strong>
                    <span id="summary-email"></span>
                </div>
                <div class="summary-item">
                    <strong>电话:</strong>
                    <span id="summary-phone"></span>
                </div>
            </div>
            <div class="step-buttons">
                <button type="button" class="btn-prev" data-prev-step="3">上一步</button>
                <button type="submit" class="btn-submit">提交预约</button>
            </div>
        </div>
        
        <!-- 隐藏字段 -->
        <input type="hidden" name="action" value="submit_booking">
        <input type="hidden" name="service_id" id="service_id">
        <input type="hidden" name="booking_date" id="booking_date">
        <input type="hidden" name="booking_time" id="booking_time">
        <input type="hidden" name="nonce" value="<?php echo wp_create_nonce('booking_nonce'); ?>">
    </form>
    
    <!-- 成功/错误消息 -->
    <div id="booking-message" class="hidden"></div>
</div>

3.3 添加预约表单样式

在子主题的style.css文件中添加样式:

/* 预约系统样式 */
.booking-container {
    max-width: 800px;
    margin: 0 auto;
    padding: 20px;
    background: #f9f9f9;
    border-radius: 10px;
    box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}

.booking-progress {
    display: flex;
    justify-content: space-between;
    margin-bottom: 30px;
    position: relative;
}

.booking-progress:before {
    content: '';
    position: absolute;
    top: 15px;
    left: 0;
    right: 0;
    height: 2px;
    background: #ddd;
    z-index: 1;
}

.booking-progress .step {
    position: relative;
    z-index: 2;
    background: #fff;
    padding: 10px 20px;
    border-radius: 20px;
    border: 2px solid #ddd;
    text-align: center;
    min-width: 120px;
}

.booking-progress .step.active {
    border-color: #0073aa;
    background: #0073aa;
    color: white;
}

.booking-step {
    display: none;
}

.booking-step.active {
    display: block;
}

.service-options {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
    gap: 20px;
    margin-bottom: 30px;
}

.service-option {
    padding: 20px;
    border: 2px solid #ddd;
    border-radius: 8px;
    cursor: pointer;
    transition: all 0.3s ease;
}

.service-option:hover {
    border-color: #0073aa;
    transform: translateY(-2px);
}

.service-option.selected {
    border-color: #0073aa;
    background: #f0f8ff;
}

.service-meta {
    display: flex;
    justify-content: space-between;
    margin-top: 10px;
    color: #666;
}

.date-selector {
    margin-bottom: 30px;
}

.month-navigation {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 20px;
}

.calendar {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 5px;
}

.calendar-day {
    padding: 10px;
    text-align: center;
    border: 1px solid #ddd;
    cursor: pointer;
    border-radius: 4px;
}

.calendar-day:hover {
    background: #f0f0f0;
}

.calendar-day.available {
    background: #e8f5e9;
    border-color: #4caf50;
}

.calendar-day.selected {
    background: #4caf50;
    color: white;
}

.calendar-day.unavailable {
    background: #ffebee;
    color: #999;
    cursor: not-allowed;
}

.time-slots {
    margin-bottom: 30px;
}

.slots-container {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

.time-slot {
    padding: 10px 20px;
    border: 2px solid #ddd;
    border-radius: 4px;
    cursor: pointer;
}

.time-slot:hover {
    border-color: #0073aa;
}

.time-slot.selected {
    background: #0073aa;
    color: white;
    border-color: #0073aa;
}

.time-slot.unavailable {
    background: #f5f5f5;
    color: #999;
    cursor: not-allowed;
}

.form-group {
    margin-bottom: 20px;
}

.form-group label {
    display: block;
    margin-bottom: 5px;
    font-weight: bold;
}

.form-group input,
.form-group textarea {
    width: 100%;
    padding: 10px;
    border: 1px solid #ddd;
    border-radius: 4px;
    font-size: 16px;
}

.booking-summary {
    background: white;
    padding: 20px;
    border-radius: 8px;
    margin-bottom: 30px;
}

.summary-item {
    margin-bottom: 10px;
    padding-bottom: 10px;
    border-bottom: 1px solid #eee;
}

.step-buttons {
    display: flex;
    justify-content: space-between;
}

button {
    padding: 12px 24px;
    background: #0073aa;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-size: 16px;
}

button:hover {
    background: #005a87;
}

button.btn-prev {
    background: #6c757d;
}

button.btn-prev:hover {
    background: #545b62;
}

#booking-message {
    padding: 15px;
    margin-top: 20px;
    border-radius: 4px;
    display: none;
}

#booking-message.success {
    background: #d4edda;
    color: #155724;
    border: 1px solid #c3e6cb;
    display: block;
}

#booking-message.error {
    background: #f8d7da;
    color: #721c24;

实战教程:为你的网站集成在线预约与日程管理(续)

第四部分:实现预约功能后端逻辑

4.1 处理AJAX预约提交

functions.php中添加处理预约提交的代码:

// 处理预约提交
add_action('wp_ajax_submit_booking', 'handle_booking_submission');
add_action('wp_ajax_nopriv_submit_booking', 'handle_booking_submission');

function handle_booking_submission() {
    // 验证nonce
    if (!wp_verify_nonce($_POST['nonce'], 'booking_nonce')) {
        wp_send_json_error('安全验证失败,请刷新页面重试。');
    }
    
    // 验证必填字段
    $required_fields = ['customer_name', 'customer_email', 'service_id', 'booking_date', 'booking_time'];
    foreach ($required_fields as $field) {
        if (empty($_POST[$field])) {
            wp_send_json_error('请填写所有必填字段。');
        }
    }
    
    // 验证邮箱格式
    if (!is_email($_POST['customer_email'])) {
        wp_send_json_error('请输入有效的邮箱地址。');
    }
    
    // 验证日期格式
    $booking_date = DateTime::createFromFormat('Y-m-d', $_POST['booking_date']);
    if (!$booking_date) {
        wp_send_json_error('日期格式不正确。');
    }
    
    // 检查日期是否在未来
    $today = new DateTime();
    if ($booking_date < $today) {
        wp_send_json_error('不能预约过去的日期。');
    }
    
    global $wpdb;
    $bookings_table = $wpdb->prefix . 'bookings';
    
    // 检查该时间段是否已被预约
    $existing_booking = $wpdb->get_var($wpdb->prepare(
        "SELECT COUNT(*) FROM $bookings_table 
        WHERE booking_date = %s 
        AND booking_time = %s 
        AND status IN ('pending', 'confirmed')",
        $_POST['booking_date'],
        $_POST['booking_time']
    ));
    
    if ($existing_booking > 0) {
        wp_send_json_error('该时间段已被预约,请选择其他时间。');
    }
    
    // 插入预约数据
    $insert_data = array(
        'customer_name' => sanitize_text_field($_POST['customer_name']),
        'customer_email' => sanitize_email($_POST['customer_email']),
        'customer_phone' => sanitize_text_field($_POST['customer_phone'] ?? ''),
        'service_id' => intval($_POST['service_id']),
        'booking_date' => $_POST['booking_date'],
        'booking_time' => $_POST['booking_time'],
        'duration' => intval($_POST['duration'] ?? 60),
        'notes' => sanitize_textarea_field($_POST['notes'] ?? ''),
        'status' => 'pending'
    );
    
    $result = $wpdb->insert($bookings_table, $insert_data);
    
    if ($result) {
        $booking_id = $wpdb->insert_id;
        
        // 发送确认邮件
        send_booking_confirmation_email($booking_id, $insert_data);
        
        // 发送管理员通知
        send_admin_notification_email($booking_id, $insert_data);
        
        wp_send_json_success(array(
            'message' => '预约提交成功!我们已发送确认邮件到您的邮箱。',
            'booking_id' => $booking_id
        ));
    } else {
        wp_send_json_error('预约提交失败,请稍后重试。');
    }
}

// 发送确认邮件给客户
function send_booking_confirmation_email($booking_id, $booking_data) {
    $to = $booking_data['customer_email'];
    $subject = '您的预约确认 - ' . get_bloginfo('name');
    
    $message = '<html><body>';
    $message .= '<h2>预约确认</h2>';
    $message .= '<p>尊敬的 ' . $booking_data['customer_name'] . ',</p>';
    $message .= '<p>感谢您的预约,以下是您的预约详情:</p>';
    $message .= '<table border="0" cellpadding="10">';
    $message .= '<tr><td><strong>预约编号:</strong></td><td>' . $booking_id . '</td></tr>';
    $message .= '<tr><td><strong>服务类型:</strong></td><td>' . get_service_name($booking_data['service_id']) . '</td></tr>';
    $message .= '<tr><td><strong>预约日期:</strong></td><td>' . $booking_data['booking_date'] . '</td></tr>';
    $message .= '<tr><td><strong>预约时间:</strong></td><td>' . $booking_data['booking_time'] . '</td></tr>';
    $message .= '<tr><td><strong>预计时长:</strong></td><td>' . $booking_data['duration'] . '分钟</td></tr>';
    $message .= '</table>';
    $message .= '<p>如需修改或取消预约,请通过以下方式联系我们:</p>';
    $message .= '<p>电话:' . get_option('business_phone') . '</p>';
    $message .= '<p>邮箱:' . get_option('admin_email') . '</p>';
    $message .= '</body></html>';
    
    $headers = array(
        'Content-Type: text/html; charset=UTF-8',
        'From: ' . get_bloginfo('name') . ' <' . get_option('admin_email') . '>'
    );
    
    wp_mail($to, $subject, $message, $headers);
}

// 发送管理员通知
function send_admin_notification_email($booking_id, $booking_data) {
    $to = get_option('admin_email');
    $subject = '新预约通知 - 预约编号:' . $booking_id;
    
    $message = '<html><body>';
    $message .= '<h2>新预约通知</h2>';
    $message .= '<p>您收到一个新的预约请求:</p>';
    $message .= '<table border="0" cellpadding="10">';
    $message .= '<tr><td><strong>预约编号:</strong></td><td>' . $booking_id . '</td></tr>';
    $message .= '<tr><td><strong>客户姓名:</strong></td><td>' . $booking_data['customer_name'] . '</td></tr>';
    $message .= '<tr><td><strong>客户邮箱:</strong></td><td>' . $booking_data['customer_email'] . '</td></tr>';
    $message .= '<tr><td><strong>客户电话:</strong></td><td>' . $booking_data['customer_phone'] . '</td></tr>';
    $message .= '<tr><td><strong>服务类型:</strong></td><td>' . get_service_name($booking_data['service_id']) . '</td></tr>';
    $message .= '<tr><td><strong>预约日期:</strong></td><td>' . $booking_data['booking_date'] . '</td></tr>';
    $message .= '<tr><td><strong>预约时间:</strong></td><td>' . $booking_data['booking_time'] . '</td></tr>';
    $message .= '<tr><td><strong>备注:</strong></td><td>' . $booking_data['notes'] . '</td></tr>';
    $message .= '</table>';
    $message .= '<p><a href="' . admin_url('admin.php?page=booking-management') . '">点击这里管理预约</a></p>';
    $message .= '</body></html>';
    
    $headers = array(
        'Content-Type: text/html; charset=UTF-8',
        'From: ' . get_bloginfo('name') . ' <' . get_option('admin_email') . '>'
    );
    
    wp_mail($to, $subject, $message, $headers);
}

// 获取服务名称
function get_service_name($service_id) {
    global $wpdb;
    $services_table = $wpdb->prefix . 'booking_services';
    return $wpdb->get_var($wpdb->prepare(
        "SELECT service_name FROM $services_table WHERE id = %d",
        $service_id
    ));
}

4.2 实现可用时间段查询

// 获取可用时间段
add_action('wp_ajax_get_available_slots', 'get_available_time_slots');
add_action('wp_ajax_nopriv_get_available_slots', 'get_available_time_slots');

function get_available_time_slots() {
    // 验证nonce
    if (!wp_verify_nonce($_POST['nonce'], 'booking_nonce')) {
        wp_send_json_error('安全验证失败。');
    }
    
    $date = sanitize_text_field($_POST['date']);
    $service_id = intval($_POST['service_id']);
    
    // 验证日期格式
    $booking_date = DateTime::createFromFormat('Y-m-d', $date);
    if (!$booking_date) {
        wp_send_json_error('日期格式不正确。');
    }
    
    // 获取服务时长
    global $wpdb;
    $services_table = $wpdb->prefix . 'booking_services';
    $service = $wpdb->get_row($wpdb->prepare(
        "SELECT duration FROM $services_table WHERE id = %d",
        $service_id
    ));
    
    if (!$service) {
        wp_send_json_error('服务不存在。');
    }
    
    $service_duration = $service->duration;
    
    // 获取当天的预约情况
    $bookings_table = $wpdb->prefix . 'bookings';
    $bookings = $wpdb->get_results($wpdb->prepare(
        "SELECT booking_time, duration FROM $bookings_table 
        WHERE booking_date = %s 
        AND status IN ('pending', 'confirmed')",
        $date
    ));
    
    // 获取营业时间设置(这里可以扩展为从数据库读取)
    $business_hours = array(
        'start' => '09:00:00',
        'end' => '18:00:00',
        'lunch_start' => '12:00:00',
        'lunch_end' => '13:00:00'
    );
    
    // 生成时间段
    $time_slots = generate_time_slots($business_hours, $service_duration, $bookings);
    
    wp_send_json_success(array(
        'date' => $date,
        'slots' => $time_slots
    ));
}

// 生成时间段
function generate_time_slots($business_hours, $service_duration, $existing_bookings) {
    $slots = array();
    
    // 将时间转换为分钟数便于计算
    $start_minutes = time_to_minutes($business_hours['start']);
    $end_minutes = time_to_minutes($business_hours['end']);
    $lunch_start = time_to_minutes($business_hours['lunch_start']);
    $lunch_end = time_to_minutes($business_hours['lunch_end']);
    
    // 创建已预约时间段的映射
    $booked_slots = array();
    foreach ($existing_bookings as $booking) {
        $booking_start = time_to_minutes($booking->booking_time);
        $booking_end = $booking_start + $booking->duration;
        
        for ($time = $booking_start; $time < $booking_end; $time += 15) {
            $booked_slots[$time] = true;
        }
    }
    
    // 生成时间段
    $current_time = $start_minutes;
    while ($current_time + $service_duration <= $end_minutes) {
        // 跳过午休时间
        if ($current_time >= $lunch_start && $current_time < $lunch_end) {
            $current_time = $lunch_end;
            continue;
        }
        
        // 检查时间段是否可用
        $is_available = true;
        for ($check_time = $current_time; $check_time < $current_time + $service_duration; $check_time += 15) {
            if (isset($booked_slots[$check_time]) || 
                ($check_time >= $lunch_start && $check_time < $lunch_end)) {
                $is_available = false;
                break;
            }
        }
        
        if ($is_available) {
            $slot_time = minutes_to_time($current_time);
            $slots[] = array(
                'time' => $slot_time,
                'display' => format_time_display($slot_time),
                'available' => true
            );
        }
        
        $current_time += 15; // 15分钟间隔
    }
    
    return $slots;
}

// 时间转换辅助函数
function time_to_minutes($time) {
    list($hours, $minutes) = explode(':', $time);
    return intval($hours) * 60 + intval($minutes);
}

function minutes_to_time($minutes) {
    $hours = floor($minutes / 60);
    $mins = $minutes % 60;
    return sprintf('%02d:%02d:00', $hours, $mins);
}

function format_time_display($time) {
    return date('g:i A', strtotime($time));
}

第五部分:创建后台管理界面

5.1 添加管理菜单

// 添加预约管理菜单
add_action('admin_menu', 'register_booking_admin_menu');

function register_booking_admin_menu() {
    add_menu_page(
        '预约管理',
        '预约管理',
        'manage_options',
        'booking-management',
        'render_booking_management_page',
        'dashicons-calendar-alt',
        30
    );
    
    add_submenu_page(
        'booking-management',
        '所有预约',
        '所有预约',
        'manage_options',
        'booking-management',
        'render_booking_management_page'
    );
    
    add_submenu_page(
        'booking-management',
        '服务管理',
        '服务管理',
        'manage_options',
        'booking-services',
        'render_services_management_page'
    );
    
    add_submenu_page(
        'booking-management',
        '日程设置',
        '日程设置',
        'manage_options',
        'booking-settings',
        'render_booking_settings_page'
    );
    
    add_submenu_page(
        'booking-management',
        '预约统计',
        '预约统计',
        'manage_options',
        'booking-statistics',
        'render_booking_statistics_page'
    );
}

// 渲染预约管理页面
function render_booking_management_page() {
    global $wpdb;
    $bookings_table = $wpdb->prefix . 'bookings';
    $services_table = $wpdb->prefix . 'booking_services';
    
    // 处理批量操作
    if (isset($_POST['bulk_action']) && isset($_POST['booking_ids'])) {
        $action = sanitize_text_field($_POST['bulk_action']);
        $booking_ids = array_map('intval', $_POST['booking_ids']);
        
        if ($action === 'delete') {
            foreach ($booking_ids as $id) {
                $wpdb->delete($bookings_table, array('id' => $id));
            }
            echo '<div class="notice notice-success"><p>已删除选中的预约。</p></div>';
        } elseif (in_array($action, ['pending', 'confirmed', 'cancelled', 'completed'])) {
            $wpdb->query($wpdb->prepare(
                "UPDATE $bookings_table SET status = %s WHERE id IN (" . implode(',', $booking_ids) . ")",
                $action
            ));
            echo '<div class="notice notice-success"><p>已更新选中的预约状态。</p></div>';
        }
    }
    
    // 处理单个操作
    if (isset($_GET['action']) && isset($_GET['booking_id'])) {
        $action = sanitize_text_field($_GET['action']);
        $booking_id = intval($_GET['booking_id']);
        
        switch ($action) {
            case 'confirm':
                $wpdb->update($bookings_table, array('status' => 'confirmed'), array('id' => $booking_id));
                break;
            case 'cancel':
                $wpdb->update($bookings_table, array('status' => 'cancelled'), array('id' => $booking_id));
                break;
            case 'delete':
                $wpdb->delete($bookings_table, array('id' => $booking_id));
                break;
        }
        
        wp_redirect(admin_url('admin.php?page=booking-management'));
        exit;
    }
    
    // 获取预约数据
    $per_page = 20;
    $current_page = isset($_GET['paged']) ? max(1, intval($_GET['paged'])) : 1;
    $offset = ($current_page - 1) * $per_page;
    
    // 构建查询条件
    $where_conditions = array('1=1');
    $query_params = array();
    
    if (!empty($_GET['status'])) {
        $where_conditions[] = 'status = %s';
        $query_params[] = sanitize_text_field($_GET['status']);
    }
    
    if (!empty($_GET['date_from'])) {
        $where_conditions[] = 'booking_date >= %s';
        $query_params[] = sanitize_text_field($_GET['date_from']);
    }
    
    if (!empty($_GET['date_to'])) {
        $where_conditions[] = 'booking_date <= %s';
        $query_params[] = sanitize_text_field($_GET['date_to']);
    }
    
    if (!empty($_GET['search'])) {
        $search_term = '%' . $wpdb->esc_like(sanitize_text_field($_GET['search'])) . '%';
        $where_conditions[] = '(customer_name LIKE %s OR customer_email LIKE %s OR customer_phone LIKE %s)';
        $query_params[] = $search_term;
        $query_params[] = $search_term;
        $query_params[] = $search_term;
    }
    
    $where_clause = implode(' AND ', $where_conditions);
    
    // 获取总数
    $total_query = "SELECT COUNT(*) FROM $bookings_table WHERE $where_clause";
    if (!empty($query_params)) {
        $total_query = $wpdb->prepare($total_query, $query_params);
    }
    $total_bookings = $wpdb->get_var($total_query);
    
    // 获取数据
本文来自网络,不代表柔性供应链服务中心立场,转载请注明出处:https://mall.org.cn/5059.html

EXCHANGES®作者

上一篇
下一篇

为您推荐

发表回复

联系我们

联系我们

18559313275

在线咨询: QQ交谈

邮箱: vip@exchanges.center

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