0) { $stmt = $pdo->prepare("SELECT * FROM vip_customers WHERE id = ? AND is_active = 1"); $stmt->execute([$vip_id]); $vip_customer = $stmt->fetch(); if (!$vip_customer) { throw new Exception('选择的VIP客户无效'); } // 使用VIP客户信息 $customer_name = $vip_customer['customer_name']; $phone = $vip_customer['phone']; // #region agent log $log_data = json_encode(['location' => 'index.php:28', 'message' => 'VIP customer data', 'data' => ['vip_id' => $vip_id, 'has_car_model' => isset($vip_customer['car_model']), 'has_car_number' => isset($vip_customer['car_number'])], 'timestamp' => time() * 1000, 'sessionId' => 'debug-session', 'runId' => 'run1', 'hypothesisId' => 'A']); file_put_contents('.cursor/debug.log', $log_data . "\n", FILE_APPEND); // #endregion // VIP客户信息优先,但允许通过POST覆盖(如果用户想修改) $car_model = isset($_POST['car_model']) && trim($_POST['car_model']) ? trim($_POST['car_model']) : (isset($vip_customer['car_model']) && $vip_customer['car_model'] ? $vip_customer['car_model'] : ''); $car_number = isset($_POST['car_number']) && trim($_POST['car_number']) ? trim($_POST['car_number']) : (isset($vip_customer['car_number']) && $vip_customer['car_number'] ? $vip_customer['car_number'] : ''); $member_type = 'VIP会员'; } else { // 新客户录入 $customer_name = trim($_POST['customer_name'] ?? ''); $phone = trim($_POST['phone'] ?? ''); $car_model = trim($_POST['car_model'] ?? ''); $car_number = trim($_POST['car_number'] ?? ''); } $package_id = (int)($_POST['package_id'] ?? 0); $custom_services = trim($_POST['custom_services'] ?? ''); $appointment_date = $_POST['appointment_date'] ?? ''; $appointment_time = $_POST['appointment_time'] ?? ''; $duration = (int)($_POST['duration'] ?? 60); $notes = trim($_POST['notes'] ?? ''); // 验证member_type和source $allowed_member_types = ['普通客户', 'VIP会员']; $member_type = isset($_POST['member_type']) && in_array($_POST['member_type'], $allowed_member_types) ? $_POST['member_type'] : '普通客户'; $allowed_sources = ['抖音', '微信', '快手', '朋友介绍', '其他']; $source = isset($_POST['source']) && in_array($_POST['source'], $allowed_sources) ? $_POST['source'] : '其他'; // 验证必填字段 if (empty($customer_name) || empty($phone) || empty($car_model) || empty($car_number) || empty($appointment_date) || empty($appointment_time)) { throw new Exception('请填写所有必填字段'); } // 验证VIP客户或新客户的必填字段 if ($customer_type === 'vip') { if (empty($vip_id)) { throw new Exception('请选择一个VIP客户'); } } else { if (empty($customer_name) || empty($phone)) { throw new Exception('请填写客户姓名和联系电话'); } } // 验证套餐 if ($package_id) { $stmt = $pdo->prepare("SELECT * FROM packages WHERE id = ? AND is_active = 1"); $stmt->execute([$package_id]); $package = $stmt->fetch(); if (!$package) { throw new Exception('选择的套餐无效'); } $total_price = $package['price']; } else { throw new Exception('请选择一个套餐'); } // 验证日期和时间格式 if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $appointment_date)) { throw new Exception('预约日期格式不正确'); } if (!preg_match('/^\d{2}:\d{2}$/', $appointment_time)) { throw new Exception('预约时间格式不正确'); } // 计算预约时间范围 $start_time = $appointment_date . ' ' . $appointment_time . ':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('计算结束时间失败'); } // 检查时间冲突 // 两个时间段重叠的条件:现有预约的开始时间 < 新预约的结束时间 AND 现有预约的结束时间 > 新预约的开始时间 // #region agent log $log_data = json_encode(['location' => 'index.php:98', 'message' => 'Checking time conflict', 'data' => ['start_time' => $start_time, 'end_time' => $end_time, 'duration' => $duration], 'timestamp' => time() * 1000, 'sessionId' => 'debug-session', 'runId' => 'run1', 'hypothesisId' => 'F']); 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 > ?"); $stmt->execute([$end_time, $start_time]); $conflict_count = $stmt->fetchColumn(); // #region agent log $log_data = json_encode(['location' => 'index.php:107', 'message' => 'Time conflict check result', 'data' => ['conflict_count' => $conflict_count], 'timestamp' => time() * 1000, 'sessionId' => 'debug-session', 'runId' => 'run1', 'hypothesisId' => 'F']); file_put_contents('.cursor/debug.log', $log_data . "\n", FILE_APPEND); // #endregion if ($conflict_count > 0) { throw new Exception('该时间段已被预约,请选择其他时间'); } // 检查客户是否有历史预约记录,如果有则自动转为普通客户 // #region agent log $log_data = json_encode(['location' => 'index.php:136', 'message' => 'Checking customer booking history', 'data' => ['phone' => $phone, 'car_number' => $car_number, 'current_member_type' => $member_type], 'timestamp' => time() * 1000, 'sessionId' => 'debug-session', 'runId' => 'run1', 'hypothesisId' => 'I']); file_put_contents('.cursor/debug.log', $log_data . "\n", FILE_APPEND); // #endregion // 检查该手机号和车牌号组合是否有历史预约记录 $stmt = $pdo->prepare("SELECT COUNT(*) FROM bookings WHERE phone = ? AND car_number = ?"); $stmt->execute([$phone, $car_number]); $has_booking_history = $stmt->fetchColumn() > 0; // 如果客户有历史预约记录,自动转为普通客户(除非是VIP客户模式) if ($has_booking_history && $member_type === 'VIP会员' && $customer_type !== 'vip') { $member_type = '普通客户'; // #region agent log $log_data = json_encode(['location' => 'index.php:144', 'message' => 'Auto converted to regular customer', 'data' => ['reason' => 'has_booking_history', 'phone' => $phone, 'car_number' => $car_number], 'timestamp' => time() * 1000, 'sessionId' => 'debug-session', 'runId' => 'run1', 'hypothesisId' => 'I']); file_put_contents('.cursor/debug.log', $log_data . "\n", FILE_APPEND); // #endregion } // 插入预约记录 // 对于0元订单,自动标记为已付款 $payment_status = ($total_price <= 0) ? '已付款' : '未付款'; $stmt = $pdo->prepare("INSERT INTO bookings (customer_name, phone, car_model, car_number, package_id, custom_services, start_time, end_time, duration, total_price, notes, member_type, source, payment_status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); $stmt->execute([$customer_name, $phone, $car_model, $car_number, $package_id, $custom_services, $start_time, $end_time, $duration, $total_price, $notes, $member_type, $source, $payment_status]); $success_message = "预约提交成功!"; } catch (Exception $e) { $message = $e->getMessage(); } } // 获取套餐列表 $stmt = $pdo->query("SELECT * FROM packages WHERE is_active = 1 ORDER BY price"); $packages = $stmt->fetchAll(); // 获取一周内的预约数据用于日历显示 $start_date = date('Y-m-d'); $end_date = date('Y-m-d', strtotime('+7 days')); $stmt = $pdo->prepare("SELECT DATE(start_time) as date, COUNT(*) as booking_count, GROUP_CONCAT( CONCAT( TIME_FORMAT(start_time, '%H:%i'), '-', TIME_FORMAT(end_time, '%H:%i'), '(', status, ')' ) ORDER BY start_time SEPARATOR '
' ) as bookings FROM bookings WHERE DATE(start_time) BETWEEN ? AND ? AND status NOT IN ('已完成', '已取消') GROUP BY DATE(start_time) ORDER BY date"); $stmt->execute([$start_date, $end_date]); $results = $stmt->fetchAll(PDO::FETCH_ASSOC); // 将结果转换为键值对格式(日期 => 预约数量) $booking_schedule = []; $booking_details = []; // 存储详细的预约信息 foreach ($results as $row) { $booking_schedule[$row['date']] = $row['booking_count']; $booking_details[$row['date']] = $row['bookings']; } // 获取具体的时间段预约信息供JavaScript使用 $stmt2 = $pdo->prepare("SELECT DATE(start_time) as date, TIME_FORMAT(start_time, '%H:%i') as start_time, TIME_FORMAT(end_time, '%H:%i') as end_time, status, customer_name, car_model, car_number FROM bookings WHERE DATE(start_time) BETWEEN ? AND ? AND status NOT IN ('已完成', '已取消') ORDER BY date, start_time"); $stmt2->execute([$start_date, $end_date]); $all_bookings = $stmt2->fetchAll(PDO::FETCH_ASSOC); // 按日期组织预约数据,处理跨天预约情况 $bookings_by_date = []; foreach ($all_bookings as $booking) { $booking_date = $booking['date']; // 使用不同的变量名避免覆盖外层$start_date $booking_start_time = $booking['start_time']; $booking_end_time = $booking['end_time']; // 将预约添加到开始日期 $bookings_by_date[$booking_date][] = $booking; // 检查是否是跨天预约(结束时间早于开始时间,表示跨天) // 注意:这里比较的是时间字符串(HH:MM格式),需要转换为可比较的格式 $start_timestamp = strtotime($booking_start_time); $end_timestamp = strtotime($booking_end_time); // #region agent log $log_data = json_encode(['location' => 'index.php:196', 'message' => 'Checking cross-day booking', 'data' => ['booking_date' => $booking_date, 'start_time' => $booking_start_time, 'end_time' => $booking_end_time, 'start_ts' => $start_timestamp, 'end_ts' => $end_timestamp], 'timestamp' => time() * 1000, 'sessionId' => 'debug-session', 'runId' => 'run1', 'hypothesisId' => 'G']); file_put_contents('.cursor/debug.log', $log_data . "\n", FILE_APPEND); // #endregion if ($start_timestamp !== false && $end_timestamp !== false && $end_timestamp < $start_timestamp) { // 计算第二天的日期 $next_date = date('Y-m-d', strtotime($booking_date . ' +1 day')); // 创建第二天的预约记录副本 $next_day_booking = $booking; $next_day_booking['is_cross_day'] = true; // 标记为跨天预约 // 将预约添加到第二天 $bookings_by_date[$next_date][] = $next_day_booking; } } // 获取套餐信息用于JavaScript $packages_json = json_encode(array_map(function($package) { $package['services'] = array_filter(array_map('trim', explode(',', $package['services']))); return $package; }, $packages)); ?> 张老师撸车(私家车库)工作室

🚗 张老师撸车工作室

📅 选择预约日期

第 1 页 / 共 4 页

📋 预约信息