首页 / 应用软件 / WordPress集成教程,连接酒店预订API实现房源查询与在线预订功能

WordPress集成教程,连接酒店预订API实现房源查询与在线预订功能

WordPress集成教程:连接酒店预订API实现房源查询与在线预订功能

引言:WordPress作为多功能开发平台的潜力

在当今数字化时代,酒店和住宿行业正经历着前所未有的转型。随着在线预订成为主流,拥有一个功能齐全、用户友好的网站对于酒店经营者至关重要。WordPress作为全球最受欢迎的内容管理系统,早已超越了简单的博客平台定位,通过其强大的可扩展性,可以转变为功能丰富的业务管理工具。

本教程将深入探讨如何通过WordPress代码二次开发,连接酒店预订API,实现专业的房源查询与在线预订功能。我们将从基础概念讲起,逐步深入到实际代码实现,最终打造一个完整的酒店预订系统。无论您是WordPress开发者、酒店经营者还是对网站集成感兴趣的技术爱好者,本教程都将为您提供实用的指导和解决方案。

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

1.1 理解酒店预订API的基本原理

酒店预订API(应用程序编程接口)是连接您的网站与酒店库存管理系统之间的桥梁。它允许您的WordPress网站实时访问房型信息、价格、可用性,并处理预订请求。常见的酒店API提供商包括Booking.com、Expedia、Hotelbeds等,也有许多专门为中小型酒店设计的API服务。

API通常通过RESTful架构或SOAP协议工作,使用JSON或XML格式传输数据。在开始集成前,您需要:

  • 注册并获取API密钥和访问令牌
  • 了解API的端点(Endpoints)、请求方法和参数
  • 熟悉API的响应数据结构和错误处理机制

1.2 WordPress开发环境配置

为了顺利进行二次开发,您需要搭建合适的开发环境:

  1. 本地开发环境:使用XAMPP、MAMP或Local by Flywheel搭建本地WordPress环境
  2. 代码编辑器:推荐使用VS Code、PHPStorm或Sublime Text
  3. 必备插件

    • Advanced Custom Fields(用于自定义字段管理)
    • Custom Post Type UI(创建自定义文章类型)
    • Query Monitor(调试数据库查询和API请求)
  4. 启用WordPress调试模式:在wp-config.php中添加以下代码:

    define('WP_DEBUG', true);
    define('WP_DEBUG_LOG', true);
    define('WP_DEBUG_DISPLAY', false);

1.3 创建自定义文章类型管理房源

在WordPress中,我们可以使用自定义文章类型(Custom Post Type)来管理酒店房源:

// 在主题的functions.php文件中添加以下代码
function register_hotel_room_post_type() {
    $labels = array(
        'name'               => '酒店房源',
        'singular_name'      => '房源',
        'menu_name'          => '酒店管理',
        'name_admin_bar'     => '房源',
        'add_new'            => '添加新房源',
        'add_new_item'       => '添加新房源',
        'new_item'           => '新房源',
        'edit_item'          => '编辑房源',
        'view_item'          => '查看房源',
        'all_items'          => '所有房源',
        'search_items'       => '搜索房源',
        'parent_item_colon'  => '父房源:',
        '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' => 'hotel-room'),
        'capability_type'    => 'post',
        'has_archive'        => true,
        'hierarchical'       => false,
        'menu_position'      => 5,
        'menu_icon'          => 'dashicons-building',
        'supports'           => array('title', 'editor', 'thumbnail', 'excerpt')
    );

    register_post_type('hotel_room', $args);
}
add_action('init', 'register_hotel_room_post_type');

第二部分:酒店预订API集成核心实现

2.1 API连接类设计与实现

创建一个专门的类来处理与酒店预订API的通信:

class Hotel_API_Connector {
    private $api_key;
    private $api_secret;
    private $base_url;
    private $access_token;
    private $token_expiry;
    
    public function __construct($api_key, $api_secret, $base_url) {
        $this->api_key = $api_key;
        $this->api_secret = $api_secret;
        $this->base_url = $base_url;
        $this->access_token = $this->get_stored_token();
    }
    
    // 获取访问令牌
    private function authenticate() {
        $response = wp_remote_post($this->base_url . '/auth', array(
            'body' => json_encode(array(
                'api_key' => $this->api_key,
                'api_secret' => $this->api_secret
            )),
            'headers' => array('Content-Type' => 'application/json'),
            'timeout' => 30
        ));
        
        if (is_wp_error($response)) {
            error_log('酒店API认证失败: ' . $response->get_error_message());
            return false;
        }
        
        $body = wp_remote_retrieve_body($response);
        $data = json_decode($body, true);
        
        if (isset($data['access_token'])) {
            $this->access_token = $data['access_token'];
            $this->token_expiry = time() + $data['expires_in'];
            
            // 存储令牌到数据库
            update_option('hotel_api_token', array(
                'token' => $this->access_token,
                'expiry' => $this->token_expiry
            ));
            
            return true;
        }
        
        return false;
    }
    
    // 获取存储的令牌
    private function get_stored_token() {
        $token_data = get_option('hotel_api_token', array());
        
        if (!empty($token_data) && isset($token_data['expiry']) && $token_data['expiry'] > time()) {
            return $token_data['token'];
        }
        
        return null;
    }
    
    // 发送API请求
    public function make_request($endpoint, $method = 'GET', $params = array()) {
        // 检查令牌有效性
        if (!$this->access_token || $this->token_expiry <= time()) {
            if (!$this->authenticate()) {
                return new WP_Error('auth_failed', 'API认证失败');
            }
        }
        
        $url = $this->base_url . $endpoint;
        
        $args = array(
            'method' => $method,
            'headers' => array(
                'Authorization' => 'Bearer ' . $this->access_token,
                'Content-Type' => 'application/json'
            ),
            'timeout' => 30
        );
        
        if (!empty($params)) {
            if ($method === 'GET') {
                $url = add_query_arg($params, $url);
            } else {
                $args['body'] = json_encode($params);
            }
        }
        
        $response = wp_remote_request($url, $args);
        
        if (is_wp_error($response)) {
            error_log('酒店API请求失败: ' . $response->get_error_message());
            return $response;
        }
        
        $response_code = wp_remote_retrieve_response_code($response);
        $response_body = wp_remote_retrieve_body($response);
        
        if ($response_code >= 400) {
            error_log('酒店API错误响应: ' . $response_body);
            return new WP_Error('api_error', 'API返回错误: ' . $response_code, $response_body);
        }
        
        return json_decode($response_body, true);
    }
    
    // 搜索可用房源
    public function search_rooms($check_in, $check_out, $guests = 2, $rooms = 1) {
        $endpoint = '/api/v1/rooms/search';
        
        $params = array(
            'check_in' => $check_in,
            'check_out' => $check_out,
            'guests' => $guests,
            'rooms' => $rooms
        );
        
        return $this->make_request($endpoint, 'GET', $params);
    }
    
    // 获取房源详情
    public function get_room_details($room_id) {
        $endpoint = '/api/v1/rooms/' . $room_id;
        return $this->make_request($endpoint);
    }
    
    // 创建预订
    public function create_booking($room_id, $check_in, $check_out, $guest_info, $payment_info) {
        $endpoint = '/api/v1/bookings';
        
        $params = array(
            'room_id' => $room_id,
            'check_in' => $check_in,
            'check_out' => $check_out,
            'guest_info' => $guest_info,
            'payment_info' => $payment_info
        );
        
        return $this->make_request($endpoint, 'POST', $params);
    }
    
    // 取消预订
    public function cancel_booking($booking_id) {
        $endpoint = '/api/v1/bookings/' . $booking_id . '/cancel';
        return $this->make_request($endpoint, 'POST');
    }
}

2.2 房源数据同步机制

为了确保WordPress中的房源信息与API数据同步,我们需要建立定期同步机制:

class Hotel_Room_Sync {
    private $api_connector;
    
    public function __construct($api_connector) {
        $this->api_connector = $api_connector;
        $this->init_hooks();
    }
    
    private function init_hooks() {
        // 每天凌晨同步房源数据
        if (!wp_next_scheduled('daily_hotel_room_sync')) {
            wp_schedule_event(strtotime('02:00:00'), 'daily', 'daily_hotel_room_sync');
        }
        
        add_action('daily_hotel_room_sync', array($this, 'sync_all_rooms'));
        
        // 手动同步触发器
        add_action('admin_post_sync_hotel_rooms', array($this, 'handle_manual_sync'));
    }
    
    // 同步所有房源
    public function sync_all_rooms() {
        // 获取API中的所有房源
        $api_rooms = $this->api_connector->make_request('/api/v1/rooms');
        
        if (is_wp_error($api_rooms)) {
            error_log('同步房源失败: ' . $api_rooms->get_error_message());
            return false;
        }
        
        $synced_count = 0;
        $updated_count = 0;
        
        foreach ($api_rooms as $api_room) {
            $room_id = $this->sync_single_room($api_room);
            
            if ($room_id) {
                if (get_post_meta($room_id, '_last_api_sync', true) == $api_room['updated_at']) {
                    $synced_count++;
                } else {
                    $updated_count++;
                }
            }
        }
        
        // 记录同步结果
        update_option('last_room_sync', array(
            'time' => current_time('mysql'),
            'synced' => $synced_count,
            'updated' => $updated_count,
            'total' => count($api_rooms)
        ));
        
        return true;
    }
    
    // 同步单个房源
    private function sync_single_room($api_room) {
        // 检查是否已存在
        $existing_posts = get_posts(array(
            'post_type' => 'hotel_room',
            'meta_key' => '_api_room_id',
            'meta_value' => $api_room['id'],
            'posts_per_page' => 1
        ));
        
        $post_data = array(
            'post_title' => $api_room['name'],
            'post_content' => $api_room['description'],
            'post_type' => 'hotel_room',
            'post_status' => 'publish'
        );
        
        if (!empty($existing_posts)) {
            $post_data['ID'] = $existing_posts[0]->ID;
            $post_id = wp_update_post($post_data);
        } else {
            $post_id = wp_insert_post($post_data);
        }
        
        if (is_wp_error($post_id) || $post_id == 0) {
            error_log('创建/更新房源失败: ' . print_r($post_id, true));
            return false;
        }
        
        // 更新自定义字段
        update_post_meta($post_id, '_api_room_id', $api_room['id']);
        update_post_meta($post_id, '_room_type', $api_room['type']);
        update_post_meta($post_id, '_max_guests', $api_room['max_guests']);
        update_post_meta($post_id, '_base_price', $api_room['base_price']);
        update_post_meta($post_id, '_amenities', $api_room['amenities']);
        update_post_meta($post_id, '_last_api_sync', $api_room['updated_at']);
        
        // 处理房源图片
        if (!empty($api_room['images'])) {
            $this->sync_room_images($post_id, $api_room['images']);
        }
        
        return $post_id;
    }
    
    // 同步房源图片
    private function sync_room_images($post_id, $images) {
        $attachment_ids = array();
        
        foreach ($images as $index => $image_url) {
            // 下载并设置特色图片
            $attachment_id = $this->upload_image_from_url($image_url, $post_id);
            
            if ($attachment_id && $index === 0) {
                set_post_thumbnail($post_id, $attachment_id);
            }
            
            if ($attachment_id) {
                $attachment_ids[] = $attachment_id;
            }
        }
        
        // 保存到图库
        if (!empty($attachment_ids)) {
            update_post_meta($post_id, '_room_gallery', $attachment_ids);
        }
    }
    
    // 从URL上传图片
    private function upload_image_from_url($image_url, $post_id) {
        require_once(ABSPATH . 'wp-admin/includes/media.php');
        require_once(ABSPATH . 'wp-admin/includes/file.php');
        require_once(ABSPATH . 'wp-admin/includes/image.php');
        
        // 检查是否已存在相同图片
        $existing_attachment = $this->get_attachment_by_url($image_url);
        
        if ($existing_attachment) {
            return $existing_attachment;
        }
        
        // 下载图片
        $tmp = download_url($image_url);
        
        if (is_wp_error($tmp)) {
            error_log('下载图片失败: ' . $tmp->get_error_message());
            return false;
        }
        
        // 准备文件数据
        $file_array = array(
            'name' => basename($image_url),
            'tmp_name' => $tmp
        );
        
        // 上传到媒体库
        $attachment_id = media_handle_sideload($file_array, $post_id);
        
        if (is_wp_error($attachment_id)) {
            @unlink($file_array['tmp_name']);
            error_log('上传图片失败: ' . $attachment_id->get_error_message());
            return false;
        }
        
        // 保存原始URL以便后续识别
        update_post_meta($attachment_id, '_original_image_url', $image_url);
        
        return $attachment_id;
    }
    
    // 根据URL获取已存在的附件
    private function get_attachment_by_url($url) {
        global $wpdb;
        
        $query = $wpdb->prepare(
            "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_original_image_url' AND meta_value = %s",
            $url
        );
        
        $attachment_id = $wpdb->get_var($query);
        
        return $attachment_id ? intval($attachment_id) : false;
    }
}

第三部分:前端功能实现与用户界面

3.1 房源搜索与筛选功能

创建一个短代码来显示房源搜索表单:

// 搜索表单短代码
function hotel_search_form_shortcode($atts) {
    ob_start();
    ?>
    <div class="hotel-search-form">
        <form id="hotel-search-form" method="GET" action="<?php echo esc_url(get_permalink(get_option('hotel_search_results_page'))); ?>">
            <div class="search-row">
                <div class="form-group">
                    <label for="check-in">入住日期</label>
                    <input type="date" id="check-in" name="check_in" 
                           value="<?php echo isset($_GET['check_in']) ? esc_attr($_GET['check_in']) : date('Y-m-d'); ?>" 
                           min="<?php echo date('Y-m-d'); ?>" required>
                </div>
                
                <div class="form-group">
                    <label for="check-out">退房日期</label>
                    <input type="date" id="check-out" name="check_out" 
                           value="<?php echo isset($_GET['check_out']) ? esc_attr($_GET['check_out']) : date('Y-m-d', strtotime('+1 day')); ?>" 
                           min="<?php echo date('Y-m-d', strtotime('+1 day')); ?>" required>
                </div>
                
                <div class="form-group">
                    <label for="guests">入住人数</label>
                    <select id="guests" name="guests">
                        <?php for ($i = 1; $i <= 10; $i++): ?>
                            <option value="<?php echo $i; ?>" <?php selected(isset($_GET['guests']) ? $_GET['guests'] : 2, $i); ?>>
                                <?php echo $i; ?> 人
                            </option>
                        <?php endfor; ?>
                    </select>
                </div>
                
                <div class="form-group">
                    <label for="rooms">房间数</label>
                    <select id="rooms" name="rooms">
                        <?php for ($i = 1; $i <= 5; $i++): ?>
                            <option value="<?php echo $i; ?>" <?php selected(isset($_GET['rooms']) ? $_GET['rooms'] : 1, $i); ?>>
                                <?php echo $i; ?> 间
                            </option>
                        <?php endfor; ?>
                    </select>
                </div>
            </div>
            
            <div class="search-row">
                <div class="form-group">
                    <label for="room-type">房型</label>
                    <select id="room-type" name="room_type">
                        <option value="">所有房型</option>
                        <option value="single" <?php selected(isset($_GET['room_type']) ? $_GET['room_type'] : '', 'single'); ?>>单人间</option>
                        <option value="double" <?php selected(isset($_GET['room_type']) ? $_GET['room_type'] : '', 'double'); ?>>双人间</option>
                        <option value="suite" <?php selected(isset($_GET['room_type']) ? $_GET['room_type'] : '', 'suite'); ?>>套房</option>
                        <option value="family" <?php selected(isset($_GET['room_type']) ? $_GET['room_type'] : '', 'family'); ?>>家庭房</option>
                    </select>
                </div>
                
                <div class="form-group">
                    <label for="price-min">价格范围</label>
                    <div class="price-range">
                        <input type="number" id="price-min" name="price_min" 
                               placeholder="最低价" value="<?php echo isset($_GET['price_min']) ? esc_attr($_GET['price_min']) : ''; ?>">
                        <span>至</span>
                        <input type="number" id="price-max" name="price_max" 
                               placeholder="最高价" value="<?php echo isset($_GET['price_max']) ? esc_attr($_GET['price_max']) : ''; ?>">
                    </div>
                </div>
                
                <div class="form-group">
                    <label for="amenities">设施</label>
                    <select id="amenities" name="amenities[]" multiple class="multi-select">
                        <option value="wifi" <?php selected(in_array('wifi', isset($_GET['amenities']) ? (array)$_GET['amenities'] : array()), true); ?>>WiFi</option>
                        <option value="breakfast" <?php selected(in_array('breakfast', isset($_GET['amenities']) ? (array)$_GET['amenities'] : array()), true); ?>>早餐</option>
                        <option value="parking" <?php selected(in_array('parking', isset($_GET['amenities']) ? (array)$_GET['amenities'] : array()), true); ?>>停车</option>
                        <option value="pool" <?php selected(in_array('pool', isset($_GET['amenities']) ? (array)$_GET['amenities'] : array()), true); ?>>泳池</option>
                        <option value="gym" <?php selected(in_array('gym', isset($_GET['amenities']) ? (array)$_GET['amenities'] : array()), true); ?>>健身房</option>
                    </select>
                </div>
            </div>
            
            <div class="form-submit">
                <button type="submit" class="search-button">搜索房源</button>
                <button type="button" class="reset-button" onclick="resetSearchForm()">重置条件</button>
            </div>
        </form>
    </div>
    
    <script>
    function resetSearchForm() {
        document.getElementById('hotel-search-form').reset();
        // 重置日期为默认值
        document.getElementById('check-in').value = '<?php echo date("Y-m-d"); ?>';
        document.getElementById('check-out').value = '<?php echo date("Y-m-d", strtotime("+1 day")); ?>';
    }
    
    // 日期验证
    document.getElementById('check-in').addEventListener('change', function() {
        var checkIn = new Date(this.value);
        var checkOut = new Date(document.getElementById('check-out').value);
        
        if (checkIn >= checkOut) {
            var nextDay = new Date(checkIn);
            nextDay.setDate(nextDay.getDate() + 1);
            document.getElementById('check-out').value = nextDay.toISOString().split('T')[0];
        }
        
        // 设置退房日期的最小值
        document.getElementById('check-out').min = this.value;
    });
    </script>
    
    <style>
    .hotel-search-form {
        background: #f8f9fa;
        padding: 25px;
        border-radius: 10px;
        box-shadow: 0 2px 15px rgba(0,0,0,0.1);
        margin: 20px 0;
    }
    
    .search-row {
        display: flex;
        flex-wrap: wrap;
        gap: 20px;
        margin-bottom: 20px;
    }
    
    .form-group {
        flex: 1;
        min-width: 200px;
    }
    
    .form-group label {
        display: block;
        margin-bottom: 8px;
        font-weight: 600;
        color: #333;
    }
    
    .form-group input,
    .form-group select {
        width: 100%;
        padding: 10px;
        border: 1px solid #ddd;
        border-radius: 5px;
        font-size: 14px;
    }
    
    .price-range {
        display: flex;
        align-items: center;
        gap: 10px;
    }
    
    .price-range input {
        flex: 1;
    }
    
    .multi-select {
        height: 100px;
    }
    
    .form-submit {
        text-align: center;
        margin-top: 20px;
    }
    
    .search-button,
    .reset-button {
        padding: 12px 30px;
        border: none;
        border-radius: 5px;
        font-size: 16px;
        cursor: pointer;
        transition: all 0.3s ease;
    }
    
    .search-button {
        background: #007cba;
        color: white;
        margin-right: 10px;
    }
    
    .search-button:hover {
        background: #005a87;
    }
    
    .reset-button {
        background: #6c757d;
        color: white;
    }
    
    .reset-button:hover {
        background: #545b62;
    }
    
    @media (max-width: 768px) {
        .search-row {
            flex-direction: column;
        }
        
        .form-group {
            min-width: 100%;
        }
    }
    </style>
    <?php
    return ob_get_clean();
}
add_shortcode('hotel_search', 'hotel_search_form_shortcode');

3.2 房源搜索结果展示

创建搜索结果页面模板:

// 搜索结果处理函数
function display_hotel_search_results() {
    if (!isset($_GET['check_in']) || !isset($_GET['check_out'])) {
        return '<div class="hotel-search-message">请先选择入住和退房日期</div>';
    }
    
    $check_in = sanitize_text_field($_GET['check_in']);
    $check_out = sanitize_text_field($_GET['check_out']);
    $guests = isset($_GET['guests']) ? intval($_GET['guests']) : 2;
    $rooms = isset($_GET['rooms']) ? intval($_GET['rooms']) : 1;
    
    // 获取API连接实例
    $api_connector = new Hotel_API_Connector(
        get_option('hotel_api_key'),
        get_option('hotel_api_secret'),
        get_option('hotel_api_base_url')
    );
    
    // 搜索可用房源
    $search_params = array(
        'check_in' => $check_in,
        'check_out' => $check_out,
        'guests' => $guests,
        'rooms' => $rooms
    );
    
    // 添加筛选条件
    if (!empty($_GET['room_type'])) {
        $search_params['room_type'] = sanitize_text_field($_GET['room_type']);
    }
    
    if (!empty($_GET['price_min'])) {
        $search_params['price_min'] = floatval($_GET['price_min']);
    }
    
    if (!empty($_GET['price_max'])) {
        $search_params['price_max'] = floatval($_GET['price_max']);
    }
    
    if (!empty($_GET['amenities'])) {
        $search_params['amenities'] = array_map('sanitize_text_field', (array)$_GET['amenities']);
    }
    
    $available_rooms = $api_connector->search_rooms($check_in, $check_out, $guests, $rooms);
    
    if (is_wp_error($available_rooms)) {
        return '<div class="hotel-search-error">搜索失败:' . esc_html($available_rooms->get_error_message()) . '</div>';
    }
    
    if (empty($available_rooms)) {
        return '<div class="hotel-search-empty">未找到符合条件的房源,请尝试调整搜索条件。</div>';
    }
    
    ob_start();
    ?>
    <div class="hotel-search-results">
        <div class="search-summary">
            <h3>搜索结果</h3>
            <p>入住:<?php echo date('Y年m月d日', strtotime($check_in)); ?> - 
               退房:<?php echo date('Y年m月d日', strtotime($check_out)); ?> | 
               共 <?php echo count($available_rooms); ?> 个房源可选</p>
        </div>
        
        <div class="results-controls">
            <div class="sort-options">
                <label>排序:</label>
                <select id="sort-results" onchange="sortRooms(this.value)">
                    <option value="price_asc">价格从低到高</option>
                    <option value="price_desc">价格从高到低</option>
                    <option value="rating_desc">评分从高到低</option>
                    <option value="name_asc">名称A-Z</option>
                </select>
            </div>
            
            <div class="view-options">
                <button class="view-btn active" onclick="changeView('grid')" title="网格视图">
                    <span class="dashicons dashicons-grid-view"></span>
                </button>
                <button class="view-btn" onclick="changeView('list')" title="列表视图">
                    <span class="dashicons dashicons-list-view"></span>
                </button>
            </div>
        </div>
        
        <div class="rooms-container grid-view">
            <?php foreach ($available_rooms as $room): ?>
                <div class="room-card" data-price="<?php echo $room['price_per_night']; ?>" 
                     data-rating="<?php echo $room['rating'] ?? 0; ?>" 
                     data-name="<?php echo esc_attr($room['name']); ?>">
                    
                    <div class="room-image">
                        <?php if (!empty($room['image'])): ?>
                            <img src="<?php echo esc_url($room['image']); ?>" alt="<?php echo esc_attr($room['name']); ?>">
                        <?php else: ?>
                            <div class="no-image">暂无图片</div>
                        <?php endif; ?>
                        
                        <?php if (isset($room['discount']) && $room['discount'] > 0): ?>
                            <span class="discount-badge">-<?php echo $room['discount']; ?>%</span>
                        <?php endif; ?>
                    </div>
                    
                    <div class="room-info">
                        <h3 class="room-title">
                            <a href="<?php echo get_permalink(); ?>?room_id=<?php echo $room['id']; ?>&check_in=<?php echo $check_in; ?>&check_out=<?php echo $check_out; ?>">
                                <?php echo esc_html($room['name']); ?>
                            </a>
                        </h3>
                        
                        <div class="room-meta">
                            <span class="room-type"><?php echo esc_html($room['type']); ?></span>
                            <span class="room-guests">最多 <?php echo $room['max_guests']; ?> 人</span>
                            <span class="room-size"><?php echo $room['size'] ?? '--'; ?> ㎡</span>
                        </div>
                        
                        <div class="room-amenities">
                            <?php if (!empty($room['amenities'])): ?>
                                <?php 
                                $amenities_display = array_slice($room['amenities'], 0, 3);
                                foreach ($amenities_display as $amenity): ?>
                                    <span class="amenity-tag"><?php echo esc_html($amenity); ?></span>
                                <?php endforeach; ?>
                                
                                <?php if (count($room['amenities']) > 3): ?>
                                    <span class="amenity-more">+<?php echo count($room['amenities']) - 3; ?> 更多</span>
                                <?php endif; ?>
                            <?php endif; ?>
                        </div>
                        
                        <div class="room-rating">
                            <?php if (isset($room['rating'])): ?>
                                <div class="stars">
                                    <?php 
                                    $full_stars = floor($room['rating']);
                                    $half_star = ($room['rating'] - $full_stars) >= 0.5;
                                    
                                    for ($i = 1; $i <= 5; $i++):
                                        if ($i <= $full_stars): ?>
                                            <span class="dashicons dashicons-star-filled"></span>
                                        <?php elseif ($half_star && $i == $full_stars + 1): ?>
                                            <span class="dashicons dashicons-star-half"></span>
                                        <?php else: ?>
                                            <span class="dashicons dashicons-star-empty"></span>
                                        <?php endif;
                                    endfor; ?>
                                </div>
                                <span class="rating-score"><?php echo number_format($room['rating'], 1); ?></span>
                            <?php endif; ?>
                        </div>
                        
                        <div class="room-price">
                            <div class="price-main">
                                <span class="currency">¥</span>
                                <span class="amount"><?php echo number_format($room['price_per_night'], 0); ?></span>
                                <span class="period">/晚</span>
                            </div>
                            
                            <?php if (isset($room['original_price']) && $room['original_price'] > $room['price_per_night']): ?>
                                <div class="price-original">
                                    ¥<?php echo number_format($room['original_price'], 0); ?>
                                </div>
                            <?php endif; ?>
                            
                            <div class="price-total">
                                总计:¥<?php echo number_format($room['total_price'], 0); ?>
                            </div>
                        </div>
                        
                        <div class="room-actions">
                            <a href="<?php echo get_permalink(); ?>?room_id=<?php echo $room['id']; ?>&check_in=<?php echo $check_in; ?>&check_out=<?php echo $check_out; ?>&action=book" 
                               class="book-button">
                                立即预订
                            </a>
                            <button class="view-details" 
                                    onclick="showRoomDetails('<?php echo $room['id']; ?>')">
                                查看详情
                            </button>
                        </div>
                    </div>
                </div>
            <?php endforeach; ?>
        </div>
        
        <!-- 分页 -->
        <?php if (count($available_rooms) > 12): ?>
            <div class="pagination">
                <button class="page-btn prev" disabled>上一页</button>
                <span class="page-numbers">1 / <?php echo ceil(count($available_rooms) / 12); ?></span>
                <button class="page-btn next">下一页</button>
            </div>
        <?php endif; ?>
    </div>
    
    <!-- 房源详情模态框 -->
    <div id="room-details-modal" class="modal">
        <div class="modal-content">
            <span class="close-modal">&times;</span>
            <div id="room-details-content"></div>
        </div>
    </div>
    
    <script>
    // 排序功能
    function sortRooms(sortBy) {
        const container = document.querySelector('.rooms-container');
        const rooms = Array.from(container.querySelectorAll('.room-card'));
        
        rooms.sort((a, b) => {
            let aValue, bValue;
            
            switch(sortBy) {
                case 'price_asc':
                    aValue = parseFloat(a.dataset.price);
                    bValue = parseFloat(b.dataset.price);
                    return aValue - bValue;
                    
                case 'price_desc':
                    aValue = parseFloat(a.dataset.price);
                    bValue = parseFloat(b.dataset.price);
                    return bValue - aValue;
                    
                case 'rating_desc':
                    aValue = parseFloat(a.dataset.rating);
                    bValue = parseFloat(b.dataset.rating);
                    return bValue - aValue;
                    
                case 'name_asc':
                    aValue = a.dataset.name.toLowerCase();
                    bValue = b.dataset.name.toLowerCase();
                    return aValue.localeCompare(bValue);
                    
                default:
                    return 0;
            }
        });
        
        // 重新排列DOM元素
        rooms.forEach(room => container.appendChild(room));
    }
    
    // 切换视图
    function changeView(viewType) {
        const container = document.querySelector('.rooms-container');
        const buttons = document.querySelectorAll('.view-btn');
        
        buttons.forEach(btn => btn.classList.remove('active'));
        event.target.classList.add('active');
        
        container.classList.remove('grid-view', 'list-view');
        container.classList.add(viewType + '-view');
    }
    
    // 显示房源详情
    function showRoomDetails(roomId) {
        // 使用AJAX获取房源详情
        fetch('<?php echo admin_url('admin-ajax.php'); ?>', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
            },
            body: 'action=get_room_details&room_id=' + roomId + 
                  '&check_in=<?php echo $check_in; ?>' + 
本文来自网络,不代表柔性供应链服务中心立场,转载请注明出处:https://mall.org.cn/5373.html

EXCHANGES®作者

上一篇
下一篇

为您推荐

发表回复

联系我们

联系我们

18559313275

在线咨询: QQ交谈

邮箱: vip@exchanges.center

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