fix(预约系统): 增强日期时间验证并修复跨天预约处理
- 添加日期和时间格式的正则验证 - 改进时间有效性检查逻辑,防止无效时间输入 - 修复跨天预约处理中的变量命名冲突问题 - 优化时间冲突检测SQL查询条件 - 增加XSS防护措施,对VIP客户搜索结果显示进行转义
This commit is contained in:
+53
-11
@@ -60,15 +60,50 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$start_time_str = '';
|
||||
$end_time_str = '';
|
||||
|
||||
// 验证日期格式
|
||||
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $booking_date)) {
|
||||
throw new Exception('预约日期格式不正确');
|
||||
}
|
||||
|
||||
if (strpos($time_slot, '-') !== false) {
|
||||
// 格式:09:00-10:00
|
||||
list($start_time_str, $end_time_str) = explode('-', $time_slot);
|
||||
$start_time = $booking_date . ' ' . trim($start_time_str) . ':00';
|
||||
$end_time = $booking_date . ' ' . trim($end_time_str) . ':00';
|
||||
$start_time_str = trim($start_time_str);
|
||||
$end_time_str = trim($end_time_str);
|
||||
|
||||
// 验证时间格式
|
||||
if (!preg_match('/^\d{2}:\d{2}$/', $start_time_str) || !preg_match('/^\d{2}:\d{2}$/', $end_time_str)) {
|
||||
throw new Exception('时间段格式不正确');
|
||||
}
|
||||
|
||||
$start_time = $booking_date . ' ' . $start_time_str . ':00';
|
||||
$end_time = $booking_date . ' ' . $end_time_str . ':00';
|
||||
|
||||
// 验证时间有效性
|
||||
$start_timestamp = strtotime($start_time);
|
||||
$end_timestamp = strtotime($end_time);
|
||||
if ($start_timestamp === false || $end_timestamp === false) {
|
||||
throw new Exception('时间段无效');
|
||||
}
|
||||
if ($end_timestamp <= $start_timestamp) {
|
||||
throw new Exception('结束时间必须晚于开始时间');
|
||||
}
|
||||
} else {
|
||||
// 格式:09:00,使用默认时长
|
||||
$start_time = $booking_date . ' ' . trim($time_slot) . ':00';
|
||||
$end_time = date('Y-m-d H:i:s', strtotime($start_time) + $duration * 60);
|
||||
$time_slot = trim($time_slot);
|
||||
if (!preg_match('/^\d{2}:\d{2}$/', $time_slot)) {
|
||||
throw new Exception('时间格式不正确');
|
||||
}
|
||||
|
||||
$start_time = $booking_date . ' ' . $time_slot . ':00';
|
||||
$start_timestamp = strtotime($start_time);
|
||||
if ($start_timestamp === false) {
|
||||
throw new Exception('开始时间无效');
|
||||
}
|
||||
$end_time = date('Y-m-d H:i:s', $start_timestamp + $duration * 60);
|
||||
if ($end_time === false) {
|
||||
throw new Exception('计算结束时间失败');
|
||||
}
|
||||
}
|
||||
|
||||
// #region agent log
|
||||
@@ -98,16 +133,23 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
}
|
||||
|
||||
// 检查时间冲突
|
||||
// 两个时间段重叠的条件:现有预约的开始时间 < 新预约的结束时间 AND 现有预约的结束时间 > 新预约的开始时间
|
||||
// #region agent log
|
||||
$log_data = json_encode(['location' => 'process_booking.php:100', 'message' => 'Checking time conflict', 'data' => ['start_time' => $start_time, 'end_time' => $end_time], 'timestamp' => time() * 1000, 'sessionId' => 'debug-session', 'runId' => 'run1', 'hypothesisId' => 'H']);
|
||||
file_put_contents('.cursor/debug.log', $log_data . "\n", FILE_APPEND);
|
||||
// #endregion
|
||||
$stmt = $pdo->prepare("SELECT COUNT(*) FROM bookings
|
||||
WHERE status != '已取消'
|
||||
AND (
|
||||
(start_time <= ? AND end_time > ?)
|
||||
OR (start_time < ? AND end_time >= ?)
|
||||
OR (start_time >= ? AND end_time <= ?)
|
||||
)");
|
||||
$stmt->execute([$start_time, $start_time, $end_time, $end_time, $start_time, $end_time]);
|
||||
AND start_time < ?
|
||||
AND end_time > ?");
|
||||
$stmt->execute([$end_time, $start_time]);
|
||||
$conflict_count = $stmt->fetchColumn();
|
||||
// #region agent log
|
||||
$log_data = json_encode(['location' => 'process_booking.php:110', 'message' => 'Time conflict check result', 'data' => ['conflict_count' => $conflict_count], 'timestamp' => time() * 1000, 'sessionId' => 'debug-session', 'runId' => 'run1', 'hypothesisId' => 'H']);
|
||||
file_put_contents('.cursor/debug.log', $log_data . "\n", FILE_APPEND);
|
||||
// #endregion
|
||||
|
||||
if ($stmt->fetchColumn() > 0) {
|
||||
if ($conflict_count > 0) {
|
||||
throw new Exception('该时间段已被预约,请选择其他时间');
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user