首页 / 应用软件 / 详细教程,为WordPress网站开发会议室预订与资源调度管理系统

详细教程,为WordPress网站开发会议室预订与资源调度管理系统

WordPress会议室预订与资源调度管理系统开发详细教程

引言:为什么需要会议室预订与资源调度系统

在现代办公环境中,会议室和各种共享资源(如投影仪、车辆、设备等)的高效管理是企业运营的重要环节。传统的人工预约方式不仅效率低下,还容易引发时间冲突和资源浪费。随着远程办公和混合工作模式的普及,一个数字化的资源调度系统变得尤为重要。

WordPress作为全球最流行的内容管理系统,不仅适用于博客和网站建设,通过代码二次开发,完全可以实现会议室预订与资源调度这样的专业功能。本教程将详细指导您如何从零开始,在WordPress平台上开发一个功能完善的会议室预订与资源调度管理系统。

第一部分:系统需求分析与规划

1.1 核心功能需求

在开始开发之前,我们需要明确系统应具备的核心功能:

  1. 会议室管理:添加、编辑、删除会议室,设置容量、设备配置等信息
  2. 资源管理:管理可预订资源(投影仪、白板、视频会议设备等)
  3. 预订功能:用户可查看可用时间段并进行预订
  4. 冲突检测:自动检测时间冲突,避免重复预订
  5. 日历视图:直观展示会议室和资源的占用情况
  6. 用户权限管理:不同用户角色拥有不同权限
  7. 通知系统:预订确认、提醒、变更通知
  8. 报表统计:使用频率统计、资源利用率分析

1.2 技术架构设计

我们将采用以下技术架构:

  • 前端:HTML5、CSS3、JavaScript(jQuery)、FullCalendar.js
  • 后端:PHP(WordPress核心)、MySQL数据库
  • 通信:AJAX实现无刷新操作
  • 安全性:WordPress非ces、数据验证、权限检查

1.3 数据库设计

我们需要创建以下自定义数据表:

  1. wp_meeting_rooms:存储会议室信息
  2. wp_resources:存储可预订资源信息
  3. wp_bookings:存储预订记录
  4. wp_booking_resources:预订与资源的关联表

第二部分:开发环境搭建与基础配置

2.1 开发环境准备

首先确保您具备以下环境:

  • WordPress 5.0+ 安装
  • PHP 7.4+ 版本
  • MySQL 5.6+ 数据库
  • 代码编辑器(VS Code、Sublime Text等)

2.2 创建自定义插件

我们将创建一个独立的插件来实现所有功能,确保与主题分离,便于维护和迁移。

在WordPress的wp-content/plugins/目录下创建新文件夹meeting-room-booking-system,并在其中创建主插件文件:

<?php
/**
 * Plugin Name: 会议室预订与资源调度管理系统
 * Plugin URI:  https://yourwebsite.com/
 * Description: 一个功能完整的会议室与资源预订管理系统
 * Version:     1.0.0
 * Author:      您的名称
 * License:     GPL v2 or later
 * Text Domain: mr-booking
 */

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

// 定义插件常量
define('MRB_PLUGIN_PATH', plugin_dir_path(__FILE__));
define('MRB_PLUGIN_URL', plugin_dir_url(__FILE__));
define('MRB_VERSION', '1.0.0');

// 初始化插件
require_once MRB_PLUGIN_PATH . 'includes/class-init.php';

2.3 创建数据库表

在插件初始化类中,添加创建数据库表的代码:

class MRB_Init {
    
    public function __construct() {
        // 激活插件时创建表
        register_activation_hook(__FILE__, array($this, 'create_tables'));
        
        // 加载其他组件
        $this->load_dependencies();
    }
    
    public function create_tables() {
        global $wpdb;
        
        $charset_collate = $wpdb->get_charset_collate();
        
        // 会议室表
        $rooms_table = $wpdb->prefix . 'meeting_rooms';
        $rooms_sql = "CREATE TABLE IF NOT EXISTS $rooms_table (
            id mediumint(9) NOT NULL AUTO_INCREMENT,
            name varchar(100) NOT NULL,
            description text,
            capacity smallint NOT NULL DEFAULT 10,
            location varchar(200),
            amenities text,
            status tinyint(1) DEFAULT 1,
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY (id)
        ) $charset_collate;";
        
        // 资源表
        $resources_table = $wpdb->prefix . 'resources';
        $resources_sql = "CREATE TABLE IF NOT EXISTS $resources_table (
            id mediumint(9) NOT NULL AUTO_INCREMENT,
            name varchar(100) NOT NULL,
            type varchar(50) NOT NULL,
            description text,
            quantity smallint NOT NULL DEFAULT 1,
            status tinyint(1) DEFAULT 1,
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY (id)
        ) $charset_collate;";
        
        // 预订表
        $bookings_table = $wpdb->prefix . 'bookings';
        $bookings_sql = "CREATE TABLE IF NOT EXISTS $bookings_table (
            id mediumint(9) NOT NULL AUTO_INCREMENT,
            room_id mediumint(9) NOT NULL,
            user_id bigint(20) NOT NULL,
            title varchar(200) NOT NULL,
            description text,
            start_time datetime NOT NULL,
            end_time datetime NOT NULL,
            attendees smallint DEFAULT 1,
            status varchar(20) DEFAULT 'confirmed',
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY (id),
            KEY room_id (room_id),
            KEY user_id (user_id),
            KEY start_time (start_time),
            KEY end_time (end_time)
        ) $charset_collate;";
        
        // 预订资源关联表
        $booking_resources_table = $wpdb->prefix . 'booking_resources';
        $booking_resources_sql = "CREATE TABLE IF NOT EXISTS $booking_resources_table (
            id mediumint(9) NOT NULL AUTO_INCREMENT,
            booking_id mediumint(9) NOT NULL,
            resource_id mediumint(9) NOT NULL,
            quantity smallint NOT NULL DEFAULT 1,
            PRIMARY KEY (id),
            KEY booking_id (booking_id),
            KEY resource_id (resource_id)
        ) $charset_collate;";
        
        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
        dbDelta($rooms_sql);
        dbDelta($resources_sql);
        dbDelta($bookings_sql);
        dbDelta($booking_resources_sql);
    }
    
    private function load_dependencies() {
        // 加载其他类文件
        require_once MRB_PLUGIN_PATH . 'includes/class-admin.php';
        require_once MRB_PLUGIN_PATH . 'includes/class-frontend.php';
        require_once MRB_PLUGIN_PATH . 'includes/class-ajax.php';
        require_once MRB_PLUGIN_PATH . 'includes/class-shortcodes.php';
    }
}

new MRB_Init();

第三部分:后台管理界面开发

3.1 创建管理菜单

class-admin.php中,添加管理菜单功能:

class MRB_Admin {
    
    public function __construct() {
        add_action('admin_menu', array($this, 'add_admin_menus'));
        add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'));
    }
    
    public function add_admin_menus() {
        // 主菜单
        add_menu_page(
            '会议室预订系统',
            '会议室预订',
            'manage_options',
            'mrb-dashboard',
            array($this, 'dashboard_page'),
            'dashicons-calendar-alt',
            30
        );
        
        // 子菜单
        add_submenu_page(
            'mrb-dashboard',
            '会议室管理',
            '会议室',
            'manage_options',
            'mrb-rooms',
            array($this, 'rooms_page')
        );
        
        add_submenu_page(
            'mrb-dashboard',
            '资源管理',
            '资源',
            'manage_options',
            'mrb-resources',
            array($this, 'resources_page')
        );
        
        add_submenu_page(
            'mrb-dashboard',
            '预订管理',
            '预订',
            'manage_options',
            'mrb-bookings',
            array($this, 'bookings_page')
        );
        
        add_submenu_page(
            'mrb-dashboard',
            '系统设置',
            '设置',
            'manage_options',
            'mrb-settings',
            array($this, 'settings_page')
        );
    }
    
    public function enqueue_admin_scripts($hook) {
        // 仅在我们的插件页面加载脚本
        if (strpos($hook, 'mrb-') !== false) {
            wp_enqueue_style('mrb-admin-style', MRB_PLUGIN_URL . 'assets/css/admin.css', array(), MRB_VERSION);
            wp_enqueue_script('mrb-admin-script', MRB_PLUGIN_URL . 'assets/js/admin.js', array('jquery'), MRB_VERSION, true);
            
            // 本地化脚本,传递数据到JS
            wp_localize_script('mrb-admin-script', 'mrb_admin', array(
                'ajax_url' => admin_url('admin-ajax.php'),
                'nonce' => wp_create_nonce('mrb_admin_nonce')
            ));
        }
    }
    
    public function dashboard_page() {
        include MRB_PLUGIN_PATH . 'templates/admin/dashboard.php';
    }
    
    public function rooms_page() {
        include MRB_PLUGIN_PATH . 'templates/admin/rooms.php';
    }
    
    public function resources_page() {
        include MRB_PLUGIN_PATH . 'templates/admin/resources.php';
    }
    
    public function bookings_page() {
        include MRB_PLUGIN_PATH . 'templates/admin/bookings.php';
    }
    
    public function settings_page() {
        include MRB_PLUGIN_PATH . 'templates/admin/settings.php';
    }
}

3.2 会议室管理界面

创建templates/admin/rooms.php文件:

<div class="wrap mrb-admin-wrap">
    <h1 class="wp-heading-inline">会议室管理</h1>
    <a href="#" class="page-title-action" id="mrb-add-room">添加新会议室</a>
    <hr class="wp-header-end">
    
    <!-- 添加/编辑会议室表单 (默认隐藏) -->
    <div id="mrb-room-form-container" style="display:none;">
        <h2 id="mrb-form-title">添加会议室</h2>
        <form id="mrb-room-form" method="post">
            <?php wp_nonce_field('mrb_save_room', 'mrb_room_nonce'); ?>
            <input type="hidden" id="room_id" name="room_id" value="0">
            
            <table class="form-table">
                <tr>
                    <th scope="row"><label for="room_name">会议室名称</label></th>
                    <td><input type="text" id="room_name" name="room_name" class="regular-text" required></td>
                </tr>
                <tr>
                    <th scope="row"><label for="room_capacity">容量</label></th>
                    <td><input type="number" id="room_capacity" name="room_capacity" min="1" max="500" value="10" required></td>
                </tr>
                <tr>
                    <th scope="row"><label for="room_location">位置</label></th>
                    <td><input type="text" id="room_location" name="room_location" class="regular-text"></td>
                </tr>
                <tr>
                    <th scope="row"><label for="room_description">描述</label></th>
                    <td><textarea id="room_description" name="room_description" rows="5" class="large-text"></textarea></td>
                </tr>
                <tr>
                    <th scope="row"><label for="room_amenities">设备配置</label></th>
                    <td>
                        <textarea id="room_amenities" name="room_amenities" rows="3" class="large-text" placeholder="例如:投影仪、白板、视频会议系统"></textarea>
                        <p class="description">每行一个设备,或使用逗号分隔</p>
                    </td>
                </tr>
                <tr>
                    <th scope="row"><label for="room_status">状态</label></th>
                    <td>
                        <select id="room_status" name="room_status">
                            <option value="1">可用</option>
                            <option value="0">不可用</option>
                        </select>
                    </td>
                </tr>
            </table>
            
            <p class="submit">
                <button type="submit" class="button button-primary">保存会议室</button>
                <button type="button" class="button" id="mrb-cancel-form">取消</button>
            </p>
        </form>
    </div>
    
    <!-- 会议室列表 -->
    <div id="mrb-rooms-list">
        <table class="wp-list-table widefat fixed striped">
            <thead>
                <tr>
                    <th scope="col" width="5%">ID</th>
                    <th scope="col" width="20%">名称</th>
                    <th scope="col" width="10%">容量</th>
                    <th scope="col" width="20%">位置</th>
                    <th scope="col" width="25%">设备配置</th>
                    <th scope="col" width="10%">状态</th>
                    <th scope="col" width="10%">操作</th>
                </tr>
            </thead>
            <tbody id="mrb-rooms-table-body">
                <!-- 通过AJAX加载数据 -->
                <tr>
                    <td colspan="7">加载中...</td>
                </tr>
            </tbody>
        </table>
    </div>
</div>

第四部分:前端预订界面开发

4.1 创建前端短代码

class-shortcodes.php中,创建用于前端显示的短代码:

class MRB_Shortcodes {
    
    public function __construct() {
        add_shortcode('meeting_room_booking', array($this, 'booking_calendar_shortcode'));
        add_shortcode('meeting_room_list', array($this, 'room_list_shortcode'));
        add_action('wp_enqueue_scripts', array($this, 'enqueue_frontend_scripts'));
    }
    
    public function enqueue_frontend_scripts() {
        global $post;
        
        // 仅在包含我们短代码的页面加载脚本
        if (is_a($post, 'WP_Post') && has_shortcode($post->post_content, 'meeting_room_booking')) {
            
            // FullCalendar库
            wp_enqueue_style('fullcalendar-css', 'https://cdn.jsdelivr.net/npm/fullcalendar@5.10.1/main.min.css', array(), '5.10.1');
            wp_enqueue_script('fullcalendar-js', 'https://cdn.jsdelivr.net/npm/fullcalendar@5.10.1/main.min.js', array('jquery'), '5.10.1', true);
            
            // 本地化日历
            wp_enqueue_script('fullcalendar-locale', 'https://cdn.jsdelivr.net/npm/fullcalendar@5.10.1/locales/zh-cn.js', array('fullcalendar-js'), '5.10.1', true);
            
            // 插件前端样式和脚本
            wp_enqueue_style('mrb-frontend-style', MRB_PLUGIN_URL . 'assets/css/frontend.css', array(), MRB_VERSION);
            wp_enqueue_script('mrb-frontend-script', MRB_PLUGIN_URL . 'assets/js/frontend.js', array('jquery', 'fullcalendar-js'), MRB_VERSION, true);
            
            // 传递数据到前端JS
            wp_localize_script('mrb-frontend-script', 'mrb_frontend', array(
                'ajax_url' => admin_url('admin-ajax.php'),
                'nonce' => wp_create_nonce('mrb_frontend_nonce'),
                'current_user_id' => get_current_user_id(),
                'calendar_locale' => get_locale(),
                'time_format' => get_option('time_format', 'H:i'),
                'date_format' => get_option('date_format', 'Y-m-d')
            ));
        }
    }
    
    public function booking_calendar_shortcode($atts) {
        // 检查用户是否登录
        if (!is_user_logged_in()) {
            return '<div class="mrb-login-required">请先登录系统以预订会议室。</div>';
        }
        
        ob_start();
        include MRB_PLUGIN_PATH . 'templates/frontend/booking-calendar.php';
        return ob_get_clean();
    }
    
    public function room_list_shortcode($atts) {
        ob_start();
        include MRB_PLUGIN_PATH . 'templates/frontend/room-list.php';
        return ob_get_clean();
    }
}

4.2 预订日历界面

创建templates/frontend/booking-calendar.php

<div class="mrb-booking-container">
    <div class="mrb-booking-header">
        <h2>会议室预订系统</h2>
        <div class="mrb-user-info">
            欢迎,<?php echo wp_get_current_user()->display_name; ?>!
        </div>
    </div>
    
    <div class="mrb-booking-main">
        <div class="mrb-sidebar">
            <div class="mrb-room-filter">
                <h3>筛选会议室</h3>
                <div class="mrb-filter-section">
                    <label for="mrb-filter-capacity">最小容量:</label>
                    <select id="mrb-filter-capacity">
                        <option value="0">不限</option>
                        <option value="5">5人以上</option>
                        <option value="10">10人以上</option>
                        <option value="20">20人以上</option>

<option value="30">30人以上</option>

                    <option value="50">50人以上</option>
                </select>
            </div>
            <div class="mrb-filter-section">
                <label for="mrb-filter-equipment">设备要求:</label>
                <div class="mrb-equipment-checkboxes">
                    <label><input type="checkbox" value="projector"> 投影仪</label>
                    <label><input type="checkbox" value="whiteboard"> 白板</label>
                    <label><input type="checkbox" value="videoconf"> 视频会议</label>
                    <label><input type="checkbox" value="phone"> 电话会议</label>
                </div>
            </div>
            <button id="mrb-apply-filter" class="button">应用筛选</button>
            <button id="mrb-reset-filter" class="button button-secondary">重置筛选</button>
        </div>
        
        <div class="mrb-room-list">
            <h3>可用会议室</h3>
            <div id="mrb-rooms-container">
                <!-- 通过AJAX加载会议室列表 -->
                <div class="mrb-loading">加载中...</div>
            </div>
        </div>
        
        <div class="mrb-resource-list">
            <h3>可预订资源</h3>
            <div id="mrb-resources-container">
                <!-- 通过AJAX加载资源列表 -->
                <div class="mrb-loading">加载中...</div>
            </div>
        </div>
    </div>
    
    <div class="mrb-calendar-section">
        <div class="mrb-calendar-controls">
            <button id="mrb-prev-week" class="button">< 上周</button>
            <button id="mrb-today" class="button">今天</button>
            <button id="mrb-next-week" class="button">下周 ></button>
            <span id="mrb-current-week" class="mrb-week-display"></span>
            
            <div class="mrb-view-toggle">
                <button class="button active" data-view="week">周视图</button>
                <button class="button" data-view="day">日视图</button>
                <button class="button" data-view="month">月视图</button>
            </div>
        </div>
        
        <div id="mrb-booking-calendar"></div>
        
        <div class="mrb-legend">
            <div class="mrb-legend-item">
                <span class="mrb-legend-color available"></span>
                <span>可预订</span>
            </div>
            <div class="mrb-legend-item">
                <span class="mrb-legend-color booked"></span>
                <span>已预订</span>
            </div>
            <div class="mrb-legend-item">
                <span class="mrb-legend-color your-booking"></span>
                <span>您的预订</span>
            </div>
            <div class="mrb-legend-item">
                <span class="mrb-legend-color unavailable"></span>
                <span>不可用</span>
            </div>
        </div>
    </div>
</div>

</div>

<!-- 预订模态框 -->
<div id="mrb-booking-modal" class="mrb-modal" style="display:none;">

<div class="mrb-modal-content">
    <div class="mrb-modal-header">
        <h3>新建预订</h3>
        <span class="mrb-modal-close">&times;</span>
    </div>
    <div class="mrb-modal-body">
        <form id="mrb-booking-form">
            <?php wp_nonce_field('mrb_create_booking', 'mrb_booking_nonce'); ?>
            <input type="hidden" id="booking_room_id" name="room_id">
            <input type="hidden" id="booking_start" name="start_time">
            <input type="hidden" id="booking_end" name="end_time">
            
            <div class="mrb-form-group">
                <label for="booking_title">会议主题 *</label>
                <input type="text" id="booking_title" name="title" required>
            </div>
            
            <div class="mrb-form-group">
                <label for="booking_description">会议描述</label>
                <textarea id="booking_description" name="description" rows="3"></textarea>
            </div>
            
            <div class="mrb-form-row">
                <div class="mrb-form-group">
                    <label for="booking_date">日期</label>
                    <input type="text" id="booking_date" name="date" readonly>
                </div>
                
                <div class="mrb-form-group">
                    <label for="booking_start_time">开始时间</label>
                    <select id="booking_start_time" name="start_time_select">
                        <!-- 通过JS动态生成时间选项 -->
                    </select>
                </div>
                
                <div class="mrb-form-group">
                    <label for="booking_end_time">结束时间</label>
                    <select id="booking_end_time" name="end_time_select">
                        <!-- 通过JS动态生成时间选项 -->
                    </select>
                </div>
            </div>
            
            <div class="mrb-form-group">
                <label for="booking_attendees">参会人数 *</label>
                <input type="number" id="booking_attendees" name="attendees" min="1" value="1" required>
                <span id="booking_capacity_info" class="mrb-hint"></span>
            </div>
            
            <div class="mrb-form-group">
                <label>预订资源</label>
                <div id="mrb-booking-resources">
                    <!-- 通过JS动态生成资源选项 -->
                </div>
            </div>
            
            <div class="mrb-form-group">
                <label for="booking_recurring">重复预订</label>
                <select id="booking_recurring" name="recurring">
                    <option value="none">不重复</option>
                    <option value="daily">每天</option>
                    <option value="weekly">每周</option>
                    <option value="monthly">每月</option>
                </select>
                <div id="mrb-recurring-options" style="display:none;">
                    <label for="booking_recurring_count">重复次数:</label>
                    <input type="number" id="booking_recurring_count" name="recurring_count" min="1" max="12" value="1">
                </div>
            </div>
            
            <div class="mrb-form-actions">
                <button type="submit" class="button button-primary">确认预订</button>
                <button type="button" class="button mrb-modal-cancel">取消</button>
            </div>
        </form>
    </div>
</div>

</div>


## 第五部分:AJAX处理与数据交互

### 5.1 AJAX处理类

在`class-ajax.php`中,处理所有前端和后端的AJAX请求:

class MRB_Ajax {


public function __construct() {
    // 前端AJAX动作
    add_action('wp_ajax_mrb_get_rooms', array($this, 'get_rooms'));
    add_action('wp_ajax_nopriv_mrb_get_rooms', array($this, 'get_rooms'));
    add_action('wp_ajax_mrb_get_resources', array($this, 'get_resources'));
    add_action('wp_ajax_nopriv_mrb_get_resources', array($this, 'get_resources'));
    add_action('wp_ajax_mrb_get_bookings', array($this, 'get_bookings'));
    add_action('wp_ajax_nopriv_mrb_get_bookings', array($this, 'get_bookings'));
    add_action('wp_ajax_mrb_create_booking', array($this, 'create_booking'));
    add_action('wp_ajax_mrb_cancel_booking', array($this, 'cancel_booking'));
    
    // 后台AJAX动作
    add_action('wp_ajax_mrb_admin_save_room', array($this, 'admin_save_room'));
    add_action('wp_ajax_mrb_admin_delete_room', array($this, 'admin_delete_room'));
    add_action('wp_ajax_mrb_admin_get_rooms', array($this, 'admin_get_rooms'));
}

/**
 * 获取会议室列表
 */
public function get_rooms() {
    // 验证nonce
    if (!check_ajax_referer('mrb_frontend_nonce', 'nonce', false)) {
        wp_die('安全验证失败', 403);
    }
    
    global $wpdb;
    $table_name = $wpdb->prefix . 'meeting_rooms';
    
    // 获取筛选参数
    $capacity = isset($_POST['capacity']) ? intval($_POST['capacity']) : 0;
    $equipment = isset($_POST['equipment']) ? $_POST['equipment'] : array();
    
    // 构建查询
    $where = array('status = 1');
    $params = array();
    
    if ($capacity > 0) {
        $where[] = 'capacity >= %d';
        $params[] = $capacity;
    }
    
    $where_sql = !empty($where) ? 'WHERE ' . implode(' AND ', $where) : '';
    
    // 如果有设备筛选,需要进一步处理
    if (!empty($equipment) && is_array($equipment)) {
        $query = "SELECT * FROM $table_name $where_sql";
        if (!empty($params)) {
            $query = $wpdb->prepare($query, $params);
        }
        
        $rooms = $wpdb->get_results($query);
        
        // 过滤设备
        $filtered_rooms = array();
        foreach ($rooms as $room) {
            $amenities = explode(',', $room->amenities);
            $amenities = array_map('trim', $amenities);
            
            $match = true;
            foreach ($equipment as $eq) {
                if (!in_array($eq, $amenities)) {
                    $match = false;
                    break;
                }
            }
            
            if ($match) {
                $filtered_rooms[] = $room;
            }
        }
        
        $rooms = $filtered_rooms;
    } else {
        $query = "SELECT * FROM $table_name $where_sql ORDER BY name ASC";
        if (!empty($params)) {
            $query = $wpdb->prepare($query, $params);
        }
        
        $rooms = $wpdb->get_results($query);
    }
    
    // 格式化返回数据
    $formatted_rooms = array();
    foreach ($rooms as $room) {
        $formatted_rooms[] = array(
            'id' => $room->id,
            'name' => $room->name,
            'capacity' => $room->capacity,
            'location' => $room->location,
            'amenities' => $room->amenities,
            'description' => $room->description
        );
    }
    
    wp_send_json_success($formatted_rooms);
}

/**
 * 获取资源列表
 */
public function get_resources() {
    if (!check_ajax_referer('mrb_frontend_nonce', 'nonce', false)) {
        wp_die('安全验证失败', 403);
    }
    
    global $wpdb;
    $table_name = $wpdb->prefix . 'resources';
    
    $resources = $wpdb->get_results(
        "SELECT * FROM $table_name WHERE status = 1 ORDER BY type, name ASC"
    );
    
    $formatted_resources = array();
    foreach ($resources as $resource) {
        $formatted_resources[] = array(
            'id' => $resource->id,
            'name' => $resource->name,
            'type' => $resource->type,
            'description' => $resource->description,
            'quantity' => $resource->quantity,
            'available' => $resource->quantity // 简化处理,实际需要计算已预订数量
        );
    }
    
    wp_send_json_success($formatted_resources);
}

/**
 * 获取预订数据
 */
public function get_bookings() {
    if (!check_ajax_referer('mrb_frontend_nonce', 'nonce', false)) {
        wp_die('安全验证失败', 403);
    }
    
    global $wpdb;
    
    $start = isset($_POST['start']) ? sanitize_text_field($_POST['start']) : date('Y-m-d');
    $end = isset($_POST['end']) ? sanitize_text_field($_POST['end']) : date('Y-m-d', strtotime('+1 month'));
    $room_id = isset($_POST['room_id']) ? intval($_POST['room_id']) : 0;
    
    $bookings_table = $wpdb->prefix . 'bookings';
    $rooms_table = $wpdb->prefix . 'meeting_rooms';
    
    // 构建查询
    $where = array("b.start_time >= %s", "b.end_time <= %s", "b.status != 'cancelled'");
    $params = array($start, $end);
    
    if ($room_id > 0) {
        $where[] = "b.room_id = %d";
        $params[] = $room_id;
    }
    
    $where_sql = implode(' AND ', $where);
    
    $query = $wpdb->prepare(
        "SELECT b.*, r.name as room_name, r.color as room_color 
         FROM $bookings_table b 
         LEFT JOIN $rooms_table r ON b.room_id = r.id 
         WHERE $where_sql 
         ORDER BY b.start_time ASC",
        $params
    );
    
    $bookings = $wpdb->get_results($query);
    
    // 格式化FullCalendar事件数据
    $events = array();
    $current_user_id = get_current_user_id();
    
    foreach ($bookings as $booking) {
        $color = '#3788d8'; // 默认蓝色
        
        if ($booking->user_id == $current_user_id) {
            $color = '#28a745'; // 用户自己的预订,绿色
        } elseif ($booking->status == 'pending') {
            $color = '#ffc107'; // 待审核,黄色
        }
        
        $events[] = array(
            'id' => $booking->id,
            'title' => $booking->title . ' (' . $booking->room_name . ')',
            'start' => $booking->start_time,
            'end' => $booking->end_time,
            'color' => $color,
            'extendedProps' => array(
                'room_id' => $booking->room_id,
                'room_name' => $booking->room_name,
                'description' => $booking->description,
                'attendees' => $booking->attendees,
                'status' => $booking->status,
                'user_id' => $booking->user_id
            )
        );
    }
    
    wp_send_json_success($events);
}

/**
 * 创建新预订
 */
public function create_booking() {
    if (!check_ajax_referer('mrb_frontend_nonce', 'nonce', false)) {
        wp_die('安全验证失败', 403);
    }
    
    // 验证用户登录
    if (!is_user_logged_in()) {
        wp_send_json_error('请先登录');
    }
    
    // 验证输入数据
    $required_fields = array('room_id', 'title', 'start_time', 'end_time', 'attendees');
    foreach ($required_fields as $field) {
        if (empty($_POST[$field])) {
            wp_send_json_error('缺少必要字段: ' . $field);
        }
    }
    
    global $wpdb;
    
    $room_id = intval($_POST['room_id']);
    $user_id = get_current_user_id();
    $title = sanitize_text_field($_POST['title']);
    $description = isset($_POST['description']) ? sanitize_textarea_field($_POST['description']) : '';
    $start_time = sanitize_text_field($_POST['start_time']);
    $end_time = sanitize_text_field($_POST['end_time']);
    $attendees = intval($_POST['attendees']);
    $resources = isset($_POST['resources']) ? $_POST['resources'] : array();
    
    // 检查会议室是否存在且可用
    $room = $wpdb->get_row($wpdb->prepare(
        "SELECT * FROM {$wpdb->prefix}meeting_rooms WHERE id = %d AND status = 1",
        $room_id
    ));
    
    if (!$room) {
        wp_send_json_error('会议室不存在或不可用');
    }
    
    // 检查容量
    if ($attendees > $room->capacity) {
        wp_send_json_error('参会人数超过会议室容量');
    }
    
    // 检查时间冲突
    $conflict = $wpdb->get_var($wpdb->prepare(
        "SELECT COUNT(*) FROM {$wpdb->prefix}bookings 
         WHERE room_id = %d 
         AND status != 'cancelled'
         AND (
             (start_time < %s AND end_time > %s) OR
             (start_time >= %s AND start_time < %s) OR
             (end_time > %s AND end_time <= %s)
         )",
        $room_id,
        $end_time, $start_time,
        $start_time, $end_time,
        $start_time, $end_time
    ));
    
    if ($conflict > 0) {
        wp_send_json_error('该时间段已被预订');
    }
    
    // 检查资源可用性
    $resource_errors = array();
    if (is_array($resources) && !empty($resources)) {
        foreach ($resources as $resource_id => $quantity) {
            $resource_id = intval($resource_id);
            $quantity = intval($quantity);
            
            if ($quantity > 0) {
                // 检查资源是否存在
                $resource = $wpdb->get_row($wpdb->prepare(
                    "SELECT * FROM {$wpdb->prefix}resources WHERE id = %d AND status = 1",
                    $resource_id
                ));
                
                if (!$resource) {
                    $resource_errors[] = "资源ID {$resource_id} 不存在";
                    continue
本文来自网络,不代表柔性供应链服务中心立场,转载请注明出处:https://mall.org.cn/5284.html

EXCHANGES®作者

上一篇
下一篇

为您推荐

发表回复

联系我们

联系我们

18559313275

在线咨询: QQ交谈

邮箱: vip@exchanges.center

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