feat: 添加调试日志并改进数据库处理逻辑
- 在多个文件中添加调试日志记录功能 - 将数据库连接统一迁移到db_connect.php - 改进预约时间冲突检测逻辑 - 优化VIP客户数据处理 - 增强套餐查询的健壮性 - 更新预约状态处理流程
This commit is contained in:
+71
-74
@@ -1,12 +1,9 @@
|
||||
<?php
|
||||
// 配置数据库连接参数
|
||||
$servername = "localhost";
|
||||
$username = "root";
|
||||
$password = "";
|
||||
$dbname = "car_wash_db";
|
||||
// 加载数据库配置
|
||||
require_once 'db_connect.php';
|
||||
|
||||
// 设置响应头为JSON
|
||||
header('Content-Type: application/json');
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
// 获取请求参数
|
||||
$phone = $_GET['phone'] ?? '';
|
||||
@@ -20,82 +17,82 @@ if (empty($phone)) {
|
||||
'pending' => 0,
|
||||
'completed' => 0,
|
||||
'bookings' => []
|
||||
]);
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
exit;
|
||||
}
|
||||
|
||||
// 创建数据库连接
|
||||
$conn = new mysqli($servername, $username, $password, $dbname);
|
||||
try {
|
||||
// 准备SQL查询 - 查询用户的预约记录(使用新的数据库结构)
|
||||
$sql = "SELECT b.*, p.package_name
|
||||
FROM bookings b
|
||||
LEFT JOIN packages p ON b.package_id = p.id
|
||||
WHERE b.phone = ?
|
||||
ORDER BY b.start_time DESC, b.id DESC";
|
||||
|
||||
// 检查连接
|
||||
if ($conn->connect_error) {
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$phone]);
|
||||
$results = $stmt->fetchAll();
|
||||
|
||||
$bookings = [];
|
||||
$pending = 0;
|
||||
$completed = 0;
|
||||
|
||||
// 处理查询结果
|
||||
foreach ($results as $row) {
|
||||
// 格式化日期和时间
|
||||
$booking_date = $row['start_time'] ? date('Y-m-d', strtotime($row['start_time'])) : '';
|
||||
$time_slot = '';
|
||||
if ($row['start_time'] && $row['end_time']) {
|
||||
$start_time = date('H:i', strtotime($row['start_time']));
|
||||
$end_time = date('H:i', strtotime($row['end_time']));
|
||||
$time_slot = $start_time . '-' . $end_time;
|
||||
}
|
||||
|
||||
$booking = [
|
||||
'id' => $row['id'],
|
||||
'booking_date' => $booking_date,
|
||||
'phone' => $row['phone'],
|
||||
'car_number' => $row['car_number'] ?? '',
|
||||
'car_model' => $row['car_model'] ?? '',
|
||||
'time_slot' => $time_slot,
|
||||
'status' => $row['status'] ?? '未知',
|
||||
'package_name' => $row['package_name'] ?? '',
|
||||
'notes' => $row['notes'] ?? ''
|
||||
];
|
||||
|
||||
// 统计不同状态的预约数量
|
||||
if ($booking['status'] === '待确认' || $booking['status'] === '已确认' || $booking['status'] === '进行中') {
|
||||
$pending++;
|
||||
} elseif ($booking['status'] === '已完成') {
|
||||
$completed++;
|
||||
}
|
||||
|
||||
$bookings[] = $booking;
|
||||
}
|
||||
|
||||
// 计算总预约数
|
||||
$total = count($bookings);
|
||||
|
||||
// 构建响应数据
|
||||
$response = [
|
||||
'success' => true,
|
||||
'total' => $total,
|
||||
'pending' => $pending,
|
||||
'completed' => $completed,
|
||||
'bookings' => $bookings
|
||||
];
|
||||
|
||||
// 返回JSON数据
|
||||
echo json_encode($response, JSON_UNESCAPED_UNICODE);
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => '数据库连接失败',
|
||||
'message' => '查询失败:' . $e->getMessage(),
|
||||
'total' => 0,
|
||||
'pending' => 0,
|
||||
'completed' => 0,
|
||||
'bookings' => []
|
||||
]);
|
||||
exit;
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
|
||||
// 准备SQL查询 - 查询用户的预约记录
|
||||
// 假设预约表名为bookings,套餐表名为packages
|
||||
$sql = "SELECT b.*, p.package_name
|
||||
FROM bookings b
|
||||
LEFT JOIN packages p ON b.package_id = p.id
|
||||
WHERE b.phone = ?
|
||||
ORDER BY b.booking_date DESC, b.id DESC";
|
||||
|
||||
$stmt = $conn->prepare($sql);
|
||||
$stmt->bind_param("s", $phone);
|
||||
$stmt->execute();
|
||||
$result = $stmt->get_result();
|
||||
|
||||
$bookings = [];
|
||||
$pending = 0;
|
||||
$completed = 0;
|
||||
|
||||
// 处理查询结果
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$booking = [
|
||||
'id' => $row['id'],
|
||||
'booking_date' => $row['booking_date'],
|
||||
'phone' => $row['phone'],
|
||||
'car_number' => $row['car_number'] ?? '',
|
||||
'car_model' => $row['car_model'] ?? '',
|
||||
'time_slot' => $row['time_slot'] ?? '',
|
||||
'status' => $row['status'] ?? '未知',
|
||||
'package_name' => $row['package_name'] ?? '',
|
||||
'notes' => $row['notes'] ?? ''
|
||||
];
|
||||
|
||||
// 统计不同状态的预约数量
|
||||
if ($booking['status'] === '待服务') {
|
||||
$pending++;
|
||||
} elseif ($booking['status'] === '已完成') {
|
||||
$completed++;
|
||||
}
|
||||
|
||||
$bookings[] = $booking;
|
||||
}
|
||||
|
||||
// 计算总预约数
|
||||
$total = count($bookings);
|
||||
|
||||
// 构建响应数据
|
||||
$response = [
|
||||
'success' => true,
|
||||
'total' => $total,
|
||||
'pending' => $pending,
|
||||
'completed' => $completed,
|
||||
'bookings' => $bookings
|
||||
];
|
||||
|
||||
// 返回JSON数据
|
||||
echo json_encode($response);
|
||||
|
||||
// 关闭数据库连接
|
||||
$stmt->close();
|
||||
$conn->close();
|
||||
?>
|
||||
|
||||
@@ -25,8 +25,12 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
// 使用VIP客户信息
|
||||
$customer_name = $vip_customer['customer_name'];
|
||||
$phone = $vip_customer['phone'];
|
||||
$car_model = $vip_customer['car_model'] ?: $car_model; // 允许覆盖
|
||||
$car_number = $vip_customer['car_number'] ?: $car_number; // 允许覆盖
|
||||
// #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
|
||||
$car_model = isset($vip_customer['car_model']) && $vip_customer['car_model'] ? $vip_customer['car_model'] : ''; // 允许覆盖
|
||||
$car_number = isset($vip_customer['car_number']) && $vip_customer['car_number'] ? $vip_customer['car_number'] : ''; // 允许覆盖
|
||||
$member_type = 'VIP会员';
|
||||
} else {
|
||||
// 新客户录入
|
||||
|
||||
+126
-94
@@ -1,111 +1,145 @@
|
||||
<?php
|
||||
// 配置数据库连接参数
|
||||
$servername = "localhost";
|
||||
$username = "root";
|
||||
$password = "";
|
||||
$dbname = "car_wash_db";
|
||||
// 加载数据库配置
|
||||
require_once 'db_connect.php';
|
||||
// #region agent log
|
||||
$log_data = json_encode(['location' => 'process_booking.php:3', 'message' => 'Database connection check', 'data' => ['has_pdo' => isset($pdo), 'using_db_connect' => true], 'timestamp' => time() * 1000, 'sessionId' => 'debug-session', 'runId' => 'run1', 'hypothesisId' => 'D']);
|
||||
file_put_contents('.cursor/debug.log', $log_data . "\n", FILE_APPEND);
|
||||
// #endregion
|
||||
|
||||
// 检查表单提交
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
// 获取表单数据
|
||||
$customer_name = $_POST['customer_name'] ?? '';
|
||||
$phone = $_POST['phone'] ?? '';
|
||||
$car_model = $_POST['car_model'] ?? '';
|
||||
$car_number = $_POST['car_number'] ?? '';
|
||||
$booking_date = $_POST['booking_date'] ?? '';
|
||||
$time_slot = $_POST['time_slot'] ?? '';
|
||||
$package_id = $_POST['package_id'] ?? '';
|
||||
$notes = $_POST['notes'] ?? '';
|
||||
$source = $_POST['source'] ?? ''; // 来源标识,用于确定返回页面
|
||||
try {
|
||||
// 获取表单数据
|
||||
$customer_name = $_POST['customer_name'] ?? '';
|
||||
$phone = $_POST['phone'] ?? '';
|
||||
$car_model = $_POST['car_model'] ?? '';
|
||||
$car_number = $_POST['car_number'] ?? '';
|
||||
$booking_date = $_POST['booking_date'] ?? '';
|
||||
$time_slot = $_POST['time_slot'] ?? '';
|
||||
$package_id = $_POST['package_id'] ?? '';
|
||||
$notes = $_POST['notes'] ?? '';
|
||||
$source = $_POST['source'] ?? '其他'; // 来源标识,用于确定返回页面
|
||||
$duration = isset($_POST['duration']) ? (int)$_POST['duration'] : 60; // 默认60分钟
|
||||
$total_price = isset($_POST['total_price']) ? (float)$_POST['total_price'] : 0;
|
||||
|
||||
// 验证必填字段
|
||||
$errors = [];
|
||||
// 验证必填字段
|
||||
if (empty($customer_name)) {
|
||||
throw new Exception('请输入客户姓名');
|
||||
}
|
||||
|
||||
if (empty($customer_name)) {
|
||||
$errors[] = '请输入客户姓名';
|
||||
}
|
||||
if (empty($phone)) {
|
||||
throw new Exception('请输入手机号码');
|
||||
} elseif (!preg_match('/^1[3-9]\d{9}$/', $phone)) {
|
||||
throw new Exception('请输入正确的手机号码');
|
||||
}
|
||||
|
||||
if (empty($phone)) {
|
||||
$errors[] = '请输入手机号码';
|
||||
} elseif (!preg_match('/^1[3-9]\d{9}$/', $phone)) {
|
||||
$errors[] = '请输入正确的手机号码';
|
||||
}
|
||||
if (empty($car_number)) {
|
||||
throw new Exception('请输入车牌号');
|
||||
}
|
||||
|
||||
if (empty($car_number)) {
|
||||
$errors[] = '请输入车牌号';
|
||||
}
|
||||
if (empty($booking_date)) {
|
||||
throw new Exception('请选择预约日期');
|
||||
}
|
||||
|
||||
if (empty($booking_date)) {
|
||||
$errors[] = '请选择预约日期';
|
||||
}
|
||||
if (empty($time_slot)) {
|
||||
throw new Exception('请选择预约时间');
|
||||
}
|
||||
|
||||
if (empty($time_slot)) {
|
||||
$errors[] = '请选择预约时间';
|
||||
}
|
||||
if (empty($package_id)) {
|
||||
throw new Exception('请选择洗车套餐');
|
||||
}
|
||||
|
||||
if (empty($package_id)) {
|
||||
$errors[] = '请选择洗车套餐';
|
||||
}
|
||||
// 验证日期是否为过去
|
||||
$current_date = date('Y-m-d');
|
||||
if ($booking_date < $current_date) {
|
||||
throw new Exception('不能选择过去的日期');
|
||||
}
|
||||
|
||||
// 验证日期是否为过去
|
||||
$current_date = date('Y-m-d');
|
||||
if ($booking_date < $current_date) {
|
||||
$errors[] = '不能选择过去的日期';
|
||||
}
|
||||
// 解析时间段,转换为start_time和end_time
|
||||
// time_slot格式可能是 "09:00-10:00" 或 "09:00"
|
||||
$start_time_str = '';
|
||||
$end_time_str = '';
|
||||
|
||||
// 如果有错误,返回错误信息
|
||||
if (!empty($errors)) {
|
||||
$error_message = implode('\n', $errors);
|
||||
echo "<script>
|
||||
alert('$error_message');
|
||||
window.history.back();
|
||||
</script>";
|
||||
exit;
|
||||
}
|
||||
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';
|
||||
} 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);
|
||||
}
|
||||
|
||||
// 创建数据库连接
|
||||
$conn = new mysqli($servername, $username, $password, $dbname);
|
||||
// #region agent log
|
||||
$log_data = json_encode(['location' => 'process_booking.php:70', 'message' => 'Time conversion', 'data' => ['booking_date' => $booking_date, 'time_slot' => $time_slot, 'start_time' => $start_time, 'end_time' => $end_time, 'duration' => $duration], 'timestamp' => time() * 1000, 'sessionId' => 'debug-session', 'runId' => 'run1', 'hypothesisId' => 'E']);
|
||||
file_put_contents('.cursor/debug.log', $log_data . "\n", FILE_APPEND);
|
||||
// #endregion
|
||||
|
||||
// 检查连接
|
||||
if ($conn->connect_error) {
|
||||
echo "<script>
|
||||
alert('数据库连接失败,请稍后重试');
|
||||
window.history.back();
|
||||
</script>";
|
||||
exit;
|
||||
}
|
||||
// 获取套餐信息以获取价格和默认时长
|
||||
$stmt = $pdo->prepare("SELECT * FROM packages WHERE id = ? AND is_active = 1");
|
||||
$stmt->execute([$package_id]);
|
||||
$package = $stmt->fetch();
|
||||
|
||||
// 检查是否已经存在相同的预约(同一天、同一时间段、同一车牌号)
|
||||
$check_sql = "SELECT * FROM bookings
|
||||
WHERE booking_date = ? AND time_slot = ? AND car_number = ? AND status != '已取消'";
|
||||
$check_stmt = $conn->prepare($check_sql);
|
||||
$check_stmt->bind_param("sss", $booking_date, $time_slot, $car_number);
|
||||
$check_stmt->execute();
|
||||
$check_result = $check_stmt->get_result();
|
||||
if (!$package) {
|
||||
throw new Exception('选择的套餐无效');
|
||||
}
|
||||
|
||||
if ($check_result->num_rows > 0) {
|
||||
echo "<script>
|
||||
alert('该时间段已存在相同车牌号的预约');
|
||||
window.history.back();
|
||||
</script>";
|
||||
$check_stmt->close();
|
||||
$conn->close();
|
||||
exit;
|
||||
}
|
||||
$check_stmt->close();
|
||||
// 如果未提供价格,使用套餐价格
|
||||
if ($total_price <= 0) {
|
||||
$total_price = $package['price'];
|
||||
}
|
||||
|
||||
// 插入预约记录
|
||||
$status = '待服务'; // 默认为待服务状态
|
||||
$create_time = date('Y-m-d H:i:s');
|
||||
// 如果未提供时长,使用套餐默认时长
|
||||
if ($duration <= 0) {
|
||||
$duration = $package['base_duration'];
|
||||
// 重新计算结束时间
|
||||
$end_time = date('Y-m-d H:i:s', strtotime($start_time) + $duration * 60);
|
||||
}
|
||||
|
||||
$insert_sql = "INSERT INTO bookings
|
||||
(customer_name, phone, car_model, car_number, booking_date, time_slot, package_id, notes, status, create_time)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
// 检查时间冲突
|
||||
$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]);
|
||||
|
||||
$stmt = $conn->prepare($insert_sql);
|
||||
$stmt->bind_param("ssssssssss", $customer_name, $phone, $car_model, $car_number, $booking_date, $time_slot, $package_id, $notes, $status, $create_time);
|
||||
if ($stmt->fetchColumn() > 0) {
|
||||
throw new Exception('该时间段已被预约,请选择其他时间');
|
||||
}
|
||||
|
||||
// 对于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, status)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
||||
|
||||
$member_type = '普通客户'; // 默认普通客户,VIP客户应该通过index.php添加
|
||||
|
||||
$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,
|
||||
'待确认' // status
|
||||
]);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
// 预约成功
|
||||
$success_message = '预约添加成功!';
|
||||
|
||||
@@ -116,19 +150,17 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
alert('$success_message');
|
||||
window.location.href = '$redirect_url';
|
||||
</script>";
|
||||
} else {
|
||||
// 预约失败
|
||||
|
||||
} catch (Exception $e) {
|
||||
$error_message = $e->getMessage();
|
||||
echo "<script>
|
||||
alert('预约添加失败,请稍后重试');
|
||||
alert('$error_message');
|
||||
window.history.back();
|
||||
</script>";
|
||||
}
|
||||
|
||||
// 关闭数据库连接
|
||||
$stmt->close();
|
||||
$conn->close();
|
||||
} else {
|
||||
// 不是POST请求,重定向到首页
|
||||
header('Location: index.php');
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
|
||||
+10
-1
@@ -62,7 +62,16 @@ try {
|
||||
}
|
||||
|
||||
// 计算新的持续时间(分钟)
|
||||
$duration = $start_dt->diff($end_dt)->i + ($start_dt->diff($end_dt)->h * 60);
|
||||
// #region agent log
|
||||
$log_data = json_encode(['location' => 'update_booking.php:65', 'message' => 'Calculating duration', 'data' => ['start_time' => $new_start_time, 'end_time' => $new_end_time], 'timestamp' => time() * 1000, 'sessionId' => 'debug-session', 'runId' => 'run1', 'hypothesisId' => 'C']);
|
||||
file_put_contents('.cursor/debug.log', $log_data . "\n", FILE_APPEND);
|
||||
// #endregion
|
||||
$interval = $start_dt->diff($end_dt);
|
||||
$duration = ($interval->days * 24 * 60) + ($interval->h * 60) + $interval->i;
|
||||
// #region agent log
|
||||
$log_data = json_encode(['location' => 'update_booking.php:67', 'message' => 'Duration calculated', 'data' => ['duration' => $duration, 'days' => $interval->days, 'hours' => $interval->h, 'minutes' => $interval->i], 'timestamp' => time() * 1000, 'sessionId' => 'debug-session', 'runId' => 'run1', 'hypothesisId' => 'C']);
|
||||
file_put_contents('.cursor/debug.log', $log_data . "\n", FILE_APPEND);
|
||||
// #endregion
|
||||
|
||||
// 更新预约时间和持续时间
|
||||
$stmt = $pdo->prepare("UPDATE bookings SET start_time = ?, end_time = ?, duration = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?");
|
||||
|
||||
@@ -414,13 +414,19 @@ try {
|
||||
<option value="">请选择套餐</option>
|
||||
<?php
|
||||
// 查询所有可用的洗车套餐
|
||||
$package_result = $conn->query("SELECT id, package_name, price FROM packages ORDER BY price ASC");
|
||||
if ($package_result && $package_result->num_rows > 0) {
|
||||
while ($package = $package_result->fetch_assoc()) {
|
||||
// #region agent log
|
||||
$log_data = json_encode(['location' => 'vip.php:417', 'message' => 'Loading packages', 'data' => ['using_pdo' => isset($pdo), 'using_conn' => isset($conn)], 'timestamp' => time() * 1000, 'sessionId' => 'debug-session', 'runId' => 'run1', 'hypothesisId' => 'B']);
|
||||
file_put_contents('.cursor/debug.log', $log_data . "\n", FILE_APPEND);
|
||||
// #endregion
|
||||
try {
|
||||
$stmt = $pdo->query("SELECT id, package_name, price FROM packages WHERE is_active = 1 ORDER BY price ASC");
|
||||
$packages = $stmt->fetchAll();
|
||||
foreach ($packages as $package) {
|
||||
echo "<option value='{$package['id']}'>{$package['package_name']} - ¥{$package['price']}</option>";
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
echo "<option value=''>加载套餐失败</option>";
|
||||
}
|
||||
$package_result->free_result();
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user