<?php ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL); session_start(); include('db.php'); // 检查用户是否已登录 if (!isset($_SESSION['username'])) { header('Location: index.php'); exit; } // 获取设备信息 $equipment_id = isset($_GET['id']) ? intval($_GET['id']) : 0; $equipment_query = "SELECT * FROM equipment WHERE id = ?"; $stmt = $conn->prepare($equipment_query); $stmt->bind_param("i", $equipment_id); $stmt->execute(); $equipment_result = $stmt->get_result(); $equipment = $equipment_result->fetch_assoc(); if (!$equipment) { echo "设备不存在。"; exit; } // 获取设备特定的问题 $questions_query = "SELECT * FROM equipment_questions WHERE equipment_id = ?"; $stmt = $conn->prepare($questions_query); $stmt->bind_param("i", $equipment_id); $stmt->execute(); $questions_result = $stmt->get_result(); $questions = []; while ($row = $questions_result->fetch_assoc()) { $questions[] = $row; } ?> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>预约设备</title> <!-- 引入Bootstrap CSS 和 FullCalendar --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"> <script src="https://cdn.jsdelivr.net/npm/fullcalendar@6.1.15/index.global.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.min.js"></script> <style> .time-slot { display: inline-block; width: 80px; height: 40px; text-align: center; line-height: 40px; margin: 1px; border: 1px solid #ddd; cursor: pointer; } .booked { background-color: #ff6666; color: white; cursor: not-allowed; } .available { background-color: #66ff66; color: black; } .selected { background-color: #0066ff; color: white; } #calendar { max-width: 500px; margin: 0 auto; background-color: #f8f9fa; padding: 10px; border-radius: 10px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); } .calendar-title { text-align: center; font-size: 24px; font-weight: bold; margin-bottom: 20px; color: #343a40; } .divider { border-top: 2px solid #dee2e6; margin: 40px 0; } .equipment-photo { display: block; width: auto; max-height: 300px; margin: 20px 0; } .equipment-description { margin-left: 20px; max-width: 300px; } .photo-description-container { display: flex; justify-content: center; align-items: center; } #booking-info { margin-top: 20px; } #timeSlots { margin-top: 20px; } </style> </head> <body> <!-- 导航栏 --> <nav class="navbar navbar-expand-lg navbar-light bg-light"> <!-- 省略,内容与index.php相同 --> </nav> <div class="container mt-3"> <a href="index.php" class="btn btn-secondary">返回主页</a> <button onclick="history.back()" class="btn btn-secondary">返回上一级</button> </div> <div class="container mt-4"> <!-- 添加链接到“我的预约”页面 --> <div class="mb-3"> <a href="equipment_status.php" class="btn btn-secondary">返回设备详细列表</a> <a href="equipment_list.php" class="btn btn-secondary">返回设备简表</a> <a href="my_bookings.php" class="btn btn-info">查看我的预约</a> </div> <h2>预约 <?php echo htmlspecialchars($equipment['name'], ENT_QUOTES, 'UTF-8'); ?></h2> <form action="submit_booking.php" method="POST"> <input type="hidden" name="equipment_id" value="<?php echo $equipment['id']; ?>"> <input type="hidden" id="selectedStartTime" name="start_time"> <input type="hidden" id="selectedEndTime" name="end_time"> <input type="hidden" id="selectedDate" name="date"> <!-- 显示设备照片和描述 --> <div class="row mb-4"> <div class="col-md-6"> <?php if (!empty($equipment['photo'])) { ?> <img src="<?php echo htmlspecialchars($equipment['photo'], ENT_QUOTES, 'UTF-8'); ?>" alt="设备照片" class="img-fluid equipment-photo"> <?php } ?> </div> <div class="col-md-6"> <?php if (!empty($equipment['description'])) { ?> <p><?php echo nl2br(htmlspecialchars($equipment['description'], ENT_QUOTES, 'UTF-8')); ?></p> <?php } ?> </div> </div> <!-- FullCalendar --> <div class="form-group row"> <div class="col-md-6"> <div class="divider"></div> <div class="calendar-title">请选择日期:</div> <div id="calendar"></div> </div> <div class="col-md-6"> <div class="divider"></div> <div id="booking-info"> <h5> >> 先从左侧日历选择日期,再选择时间段<br /> >> 请在时间表上选择起始时间,结束时间必须在开始时间之后,否则会取消所选时间。<br /> >> 预约的时长=结束时间-起始时间,最短预约时间为半小时。<br /> >> 例如:如果起始时间为10:00,结束时间是11:00,虽然显示占据了3个格子,但实际预约的时长仅为1小时! </h5> </div> <div id="timeSlots" class="mt-4"></div> </div> </div> <div class="form-group"> <div class="divider"></div> <label for="title" style="font-size: 20px">实验目的(一句话概括本次预约的实验目的。例如:AliCPT微波复用读出电路刻蚀工艺研究)</label> <textarea class="form-control" id="title" name="title" rows="1" required></textarea> </div> <!-- 设备特定的问题 --> <?php foreach ($questions as $question) { ?> <div class="form-group mt-3"> <label for="question_<?php echo $question['id']; ?>" style="font-size: 20px"> <?php echo htmlspecialchars($question['question'], ENT_QUOTES, 'UTF-8'); ?> </label> <input type="text" class="form-control" id="question_<?php echo $question['id']; ?>" name="answers[<?php echo $question['id']; ?>]" required> </div> <?php } ?> <!-- 提交预约 --> <button type="submit" class="btn btn-success mt-4" id="submitBookingForm" disabled>提交预约</button> </form> </div> <script> $(document).ready(function () { let submitButton = document.getElementById("submitBookingForm"); submitButton.disabled = true; // 初始化 FullCalendar var calendar = new FullCalendar.Calendar(document.getElementById('calendar'), { initialView: 'dayGridMonth', locale: 'zh-cn', selectable: true, // 允许选择日期 headerToolbar: { left: 'prev,next today', center: 'title', right: 'dayGridMonth' }, aspectRatio: 1.5, // 调整日历的宽高比 windowResize: function(view) { // 动态调整日历大小 if (window.innerWidth < 600) { calendar.setOption('aspectRatio', 1); // 小屏幕设备 } else { calendar.setOption('aspectRatio', 1.5); // 普通设备 } }, dateClick: function (info) { // 禁止选择今天之前的日期 var today = new Date(); today.setHours(0, 0, 0, 0); var selectedDate = new Date(info.dateStr); if (selectedDate < today) { alert('不能选择过去的日期,请选择今天或之后的日期。'); return; } // 用户选择了日期,自动触发检查预约情况 var equipmentId = <?php echo $equipment['id']; ?>; // 清空之前的时间段 $('#timeSlots').html(''); // 发送 AJAX 请求,获取当天的预约情况 $.ajax({ url: 'fetch_bookings.php', type: 'POST', data: { equipment_id: equipmentId, date: info.dateStr }, success: function (data) { var bookings = JSON.parse(data); var startTime = new Date(info.dateStr + 'T08:00:00'); var endTime = new Date(info.dateStr + 'T21:00:00'); // 以 30 分钟间隔生成时间段 for (var time = startTime; time < endTime; time.setMinutes(time.getMinutes() + 30)) { var timeString = time.toTimeString().substring(0, 5); var isBooked = false; // 检查该时间段是否已被预约 for (var i = 0; i < bookings.length; i++) { var bookingStart = new Date(bookings[i].start_time); var bookingEnd = new Date(bookings[i].end_time); if (time >= bookingStart && time < bookingEnd) { isBooked = true; break; } } // 显示时间段 if (isBooked) { $('#timeSlots').append('<div class="time-slot booked">' + timeString + '</div>'); } else { $('#timeSlots').append('<div class="time-slot available" data-time="' + timeString + '">' + timeString + '</div>'); } } // 允许用户选择多个连续的时间段 var selectedSlots = []; $('.available').click(function () { var time = $(this).data('time'); var index = selectedSlots.indexOf(time); if (selectedSlots.length === 0) { // 第一次选择,添加时间段 selectedSlots.push(time); $(this).addClass('selected'); } else { // 获取第一个选择的时间段和当前点击的时间段的索引 var firstIndex = $('.available').index($('.available[data-time="' + selectedSlots[0] + '"]')); var currentIndex = $('.available').index($(this)); // 清除之前的选择 $('.available').removeClass('selected'); selectedSlots = []; // 选择第一个和当前点击的之间的所有时间段 if (currentIndex > firstIndex) { for (var i = firstIndex; i <= currentIndex; i++) { var slotTime = $('.available').eq(i).data('time'); selectedSlots.push(slotTime); $('.available').eq(i).addClass('selected'); } } } if (selectedSlots.length > 1){ var firstSlot = selectedSlots[0]; var lastSlot = selectedSlots[selectedSlots.length - 1]; var start = new Date(info.dateStr + ' ' + firstSlot + ':00'); var end = new Date(info.dateStr + ' ' + lastSlot + ':00'); var duration = (end - start) / (1000 * 60 * 60); // 时长,以分钟为单位 if (duration > 5) { alert('每次预约的时长不能超过5小时。'); submitButton.disabled = true; } else { // 更新隐藏的表单值 $('#selectedStartTime').val(info.dateStr + ' ' + firstSlot + ':00'); $('#selectedEndTime').val(info.dateStr + ' ' + lastSlot + ':00'); $('#selectedDate').val(info.dateStr); submitButton.disabled = false; } }else{ submitButton.disabled = true; } }); }, error: function () { $('#booking-info').html('<p class="text-danger">无法获取预约信息,请稍后重试。</p>'); } }); } }); calendar.render(); }); </script> </body> </html>