diff --git a/announcement.php b/announcement.php index d8500ab..742abbb 100644 --- a/announcement.php +++ b/announcement.php @@ -430,18 +430,19 @@ try { // 移动端优化脚本 document.addEventListener('DOMContentLoaded', function() { // 为按钮添加触摸反馈 - const buttons = document.querySelectorAll('.btn'); - buttons.forEach(btn => { + var buttons = document.querySelectorAll('.btn'); + for (var i = 0; i < buttons.length; i++) { + var btn = buttons[i]; btn.addEventListener('touchstart', function() { this.style.transform = 'translateY(1px)'; }); btn.addEventListener('touchend', function() { this.style.transform = 'translateY(-2px)'; }); - }); + } // 检测设备类型 - const isMobile = /Mobi|Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); + var isMobile = /Mobi|Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); if (isMobile) { document.body.classList.add('mobile-device'); } @@ -452,8 +453,8 @@ try { }, 5 * 60 * 1000); // 将倒计时添加到页面标题旁边 - const pageHeader = document.querySelector('.page-header'); - const refreshInfo = document.createElement('div'); + var pageHeader = document.querySelector('.page-header'); + var refreshInfo = document.createElement('div'); refreshInfo.style.cssText = 'font-size:0.9rem;color:#666;margin-top:5px;'; if (pageHeader) { @@ -466,28 +467,29 @@ try { // 显示北京时间及距离下次刷新倒计时 function updateBeijingTime() { - const now = new Date(); - const beijingTime = new Date(now.getTime() + 8 * 60 * 60 * 1000); // 转为北京时间 - const hours = String(beijingTime.getUTCHours()).padStart(2, '0'); - const minutes = String(beijingTime.getUTCMinutes()).padStart(2, '0'); - const seconds = String(beijingTime.getUTCSeconds()).padStart(2, '0'); + var now = new Date(); + var beijingTime = new Date(now.getTime() + 8 * 60 * 60 * 1000); // 转为北京时间 + var hours = String(beijingTime.getUTCHours()).padStart(2, '0'); + var minutes = String(beijingTime.getUTCMinutes()).padStart(2, '0'); + var seconds = String(beijingTime.getUTCSeconds()).padStart(2, '0'); // 计算距离下次刷新的剩余时间 - const refreshInterval = 5 * 60 * 1000; // 5分钟 - const elapsed = now.getTime() % refreshInterval; - const remaining = refreshInterval - elapsed; - const remMinutes = Math.floor(remaining / 60000); - const remSeconds = Math.floor((remaining % 60000) / 1000); + var refreshInterval = 5 * 60 * 1000; // 5分钟 + var elapsed = now.getTime() % refreshInterval; + var remaining = refreshInterval - elapsed; + var remMinutes = Math.floor(remaining / 60000); + var remSeconds = Math.floor((remaining % 60000) / 1000); // 更新显示 if (refreshInfo) { - refreshInfo.textContent = `北京时间 ${hours}:${minutes}:${seconds} | 下次刷新 ${remMinutes}分${remSeconds}秒`; + refreshInfo.textContent = '北京时间 ' + hours + ':' + minutes + ':' + seconds + ' | 下次刷新 ' + remMinutes + '分' + remSeconds + '秒'; } } // 每秒更新一次 setInterval(updateBeijingTime, 1000); updateBeijingTime(); // 初始化显示 + }); diff --git a/booking_template.php b/booking_template.php new file mode 100644 index 0000000..cbd53f5 --- /dev/null +++ b/booking_template.php @@ -0,0 +1,161 @@ + [ + 'title' => '预约成功!', + 'message' => "预约成功!\n\n" . + "客户:{customer_name}\n" . + "手机号:{phone}\n" . + "车牌号:{car_number}\n" . + "车型:{car_model}\n" . + "\n" . + "预约时间:{start_time}\n" . + "服务项目:{package_name}\n" . + "服务时长:{duration}分钟\n" . + "总价:{total_price}元\n" . + "\n" . + "感谢您的预约!" + ], + // 详细模板 + 'detailed' => [ + 'title' => '【张老师撸车工作室】预约确认', + 'message' => "尊敬的 {customer_name} 先生/女士:\n\n" . + "恭喜您,您的洗车预约已成功确认!\n\n" . + "🔹 客户信息:\n" . + " - 姓名:{customer_name}\n" . + " - 手机号:{phone}\n" . + " - 车牌号:{car_number}\n" . + " - 车型:{car_model}\n" . + " - 会员类型:{member_type}\n" . + "\n" . + "🔹 预约详情:\n" . + " - 预约时间:{date} {time_range}\n" . + " - 服务项目:{package_name}\n" . + " - 自定义服务:{custom_services}\n" . + " - 服务时长:{duration}分钟\n" . + " - 总价:¥{total_price}\n" . + " - 支付状态:{payment_status}\n" . + "\n" . + "🔹 备注信息:\n" . + " {notes}\n" . + "\n" . + "🔹 温馨提示:\n" . + " 1. 请提前10分钟到达洗车地点\n" . + " 2. 如需改期或取消,请至少提前2小时联系我们\n" . + " 3. 联系电话:138-0013-8000\n" . + "\n" . + "感谢您选择张老师撸车工作室!\n" . + "祝您用车愉快!🚗✨" + ], + // 简洁模板 + 'simple' => [ + 'title' => '预约确认', + 'message' => "{customer_name},您的洗车预约已确认:\n" . + "时间:{start_time}\n" . + "项目:{package_name}\n" . + "总价:{total_price}元\n" . + "如需调整请联系我们。" + ] +]; + +/** + * 生成预约信息 + * @param array $booking_data 预约数据数组 + * @param string $template_name 使用的模板名称 + * @return string 生成的预约信息 + */ +function generateBookingMessage($booking_data, $template_name = 'basic') { + global $booking_templates; + + // 检查模板是否存在 + if (!isset($booking_templates[$template_name])) { + $template_name = 'basic'; // 默认使用基本模板 + } + + $template = $booking_templates[$template_name]['message']; + + // 定义替换字段 + $replacements = [ + '{customer_name}' => $booking_data['customer_name'] ?? '未知客户', + '{phone}' => $booking_data['phone'] ?? '未提供', + '{car_model}' => $booking_data['car_model'] ?? '未提供', + '{car_number}' => $booking_data['car_number'] ?? '未提供', + '{member_type}' => $booking_data['member_type'] ?? '普通客户', + '{package_name}' => $booking_data['package_name'] ?? '未选择套餐', + '{custom_services}' => $booking_data['custom_services'] ?? '无', + '{start_time}' => $booking_data['start_time'] ?? '未设置', + '{end_time}' => $booking_data['end_time'] ?? '未设置', + '{date}' => $booking_data['date'] ?? (isset($booking_data['start_time']) ? date('Y年m月d日', strtotime($booking_data['start_time'])) : '未设置'), + '{time_range}' => $booking_data['time_range'] ?? (isset($booking_data['start_time'], $booking_data['end_time']) ? date('H:i', strtotime($booking_data['start_time'])) . ' - ' . date('H:i', strtotime($booking_data['end_time'])) : '未设置'), + '{duration}' => $booking_data['duration'] ?? '未设置', + '{total_price}' => $booking_data['total_price'] ?? '0.00', + '{notes}' => $booking_data['notes'] ?? '无', + '{status}' => $booking_data['status'] ?? '未确认', + '{payment_status}' => $booking_data['payment_status'] ?? '未支付', + '{source}' => $booking_data['source'] ?? '未知', + '{created_at}' => $booking_data['created_at'] ?? date('Y-m-d H:i:s') + ]; + + // 替换模板中的占位符 + $message = str_replace(array_keys($replacements), array_values($replacements), $template); + + return $message; +} + +/** + * 获取指定模板的标题 + * @param string $template_name 模板名称 + * @return string 模板标题 + */ +function getTemplateTitle($template_name = 'basic') { + global $booking_templates; + + if (isset($booking_templates[$template_name])) { + return $booking_templates[$template_name]['title']; + } + + return $booking_templates['basic']['title']; +} + +/** + * 获取所有可用的模板名称 + * @return array 模板名称数组 + */ +function getAvailableTemplates() { + global $booking_templates; + return array_keys($booking_templates); +} + +/** + * 示例用法: + * 1. 包含此文件:require_once 'booking_template.php'; + * 2. 准备预约数据: + * $booking_data = [ + * 'customer_name' => '张三', + * 'phone' => '138-0013-8000', + * 'car_model' => '特斯拉 Model 3', + * 'car_number' => '京A12345', + * 'member_type' => 'VIP会员', + * 'package_name' => '精致洗车套餐', + * 'start_time' => '2023-10-01 10:00:00', + * 'end_time' => '2023-10-01 11:00:00', + * 'duration' => 60, + * 'total_price' => '128.00', + * 'notes' => '车顶上有行李架,请小心清洗', + * 'status' => '已确认', + * 'payment_status' => '已付款', + * 'source' => '微信' + * ]; + * 3. 生成预约信息: + * $message = generateBookingMessage($booking_data, 'detailed'); + * 4. 输出或使用生成的信息: + * echo $message; + */ +?> \ No newline at end of file diff --git a/bookings.php b/bookings.php index ad04e66..73a7de6 100644 --- a/bookings.php +++ b/bookings.php @@ -243,7 +243,15 @@ try {
- + + @@ -605,9 +613,31 @@ try { } // 复制预约信息到剪贴板 - function copyMessage(id, customer_name, phone, car_model, car_number, package_name, date, time) { + function copyMessage(id, customer_name, phone, car_model, car_number, package_name, date, time, duration, notes) { // 构建预约信息字符串 - const message = `预约信息\n\n客户姓名:${customer_name}\n联系方式:${phone}\n车型:${car_model}\n车牌号:${car_number}\n服务套餐:${package_name}\n预约日期:${date}\n预约时间:${time}`; + const message = `【张老师撸车工作室】预约确认\n + 客户姓名:${customer_name} + 联系方式:${phone} + 车型:${car_model} + 车牌号:${car_number} + 预约日期:${date} + 套餐:${package_name} + 预约时间:${time} + 预计服务时长:${duration}分钟 + 车友备注:${notes} + \n温馨提示: + 1. 请提前20分钟到达工作室 + 2. 如需改期或取消,请至少提前2小时联系我们 + 3. 联系电话:186-0345-3500 + + \n工作室地点: + 山西省太原市晋源区义井街道西中环充电站内 + 也可高德/百度/腾讯地图软件内搜索‘张老师撸车’ + + 感谢您选择张老师撸车工作室! + 祝您用车愉快! + + `; // 复制到剪贴板 const textArea = document.createElement('textarea'); diff --git a/example_template_usage.php b/example_template_usage.php new file mode 100644 index 0000000..4833e85 --- /dev/null +++ b/example_template_usage.php @@ -0,0 +1,213 @@ + '张三', + 'phone' => '138-0013-8000', + 'car_number' => '京A12345', + 'car_model' => '特斯拉 Model 3', + 'start_time' => '2023-10-01 10:00:00', + 'package_name' => '精致洗车套餐', + 'duration' => 60, + 'total_price' => '128.00' + ]; + + // 生成预约信息 + $message = generateBookingMessage($booking_data, 'basic'); + + // 输出结果 + echo "模板标题:" . getTemplateTitle('basic') . "\n"; + echo "模板内容:\n" . $message . "\n\n"; +} + +// 示例2:使用详细模板 +function example_detailed_template() { + echo "=== 示例2:使用详细模板 ===\n\n"; + + // 准备完整的预约数据 + $booking_data = [ + 'customer_name' => '李四', + 'phone' => '139-0013-9000', + 'car_model' => '宝马 5系', + 'car_number' => '沪B67890', + 'member_type' => 'VIP会员', + 'package_name' => '深度清洁套餐', + 'custom_services' => '内饰消毒 + 轮胎养护', + 'start_time' => '2023-10-02 14:30:00', + 'end_time' => '2023-10-02 16:00:00', + 'duration' => 90, + 'total_price' => '298.00', + 'notes' => '车辆右前门有轻微划痕,清洗时请注意', + 'status' => '已确认', + 'payment_status' => '已付款', + 'source' => '抖音' + ]; + + // 生成预约信息 + $message = generateBookingMessage($booking_data, 'detailed'); + + // 输出结果 + echo "模板标题:" . getTemplateTitle('detailed') . "\n"; + echo "模板内容:\n" . $message . "\n\n"; +} + +// 示例3:使用简洁模板 +function example_simple_template() { + echo "=== 示例3:使用简洁模板 ===\n\n"; + + // 准备简约的预约数据 + $booking_data = [ + 'customer_name' => '王五', + 'phone' => '137-0013-7000', + 'car_number' => '粤C54321', + 'car_model' => '本田 CR-V', + 'start_time' => '2023-10-03 09:30:00', + 'package_name' => '快速洗车', + 'duration' => 30, + 'total_price' => '38.00' + ]; + + // 生成预约信息 + $message = generateBookingMessage($booking_data, 'simple'); + + // 输出结果 + echo "模板标题:" . getTemplateTitle('simple') . "\n"; + echo "模板内容:\n" . $message . "\n\n"; +} + +// 示例4:自定义模板数据 +function example_custom_data() { + echo "=== 示例4:自定义模板数据 ===\n\n"; + + // 从数据库获取的示例预约数据 + $db_booking_data = [ + 'id' => 123, + 'customer_name' => '赵六', + 'phone' => '136-0013-6000', + 'car_model' => '丰田 凯美瑞', + 'car_number' => '苏D98765', + 'member_type' => '普通会员', + 'package_id' => 2, + 'package_name' => '打蜡套餐', + 'custom_services' => '', + 'start_time' => '2023-10-04 16:00:00', + 'end_time' => '2023-10-04 17:30:00', + 'duration' => 90, + 'total_price' => '198.00', + 'notes' => '', + 'status' => '已确认', + 'payment_status' => '未付款', + 'source' => '朋友介绍', + 'created_at' => '2023-09-25 14:20:00', + 'updated_at' => '2023-09-25 14:20:00' + ]; + + // 生成预约信息 + $message = generateBookingMessage($db_booking_data, 'detailed'); + + // 输出结果 + echo "模板标题:" . getTemplateTitle('detailed') . "\n"; + echo "模板内容:\n" . $message . "\n\n"; +} + +// 示例5:将模板集成到现有系统中 +function example_integration() { + echo "=== 示例5:将模板集成到现有系统中 ===\n\n"; + + // 模拟从数据库获取预约数据 + function getBookingFromDatabase($booking_id) { + // 这里应该是实际的数据库查询 + return [ + 'id' => $booking_id, + 'customer_name' => '孙七', + 'phone' => '135-0013-5000', + 'car_model' => '大众 帕萨特', + 'car_number' => '浙E34567', + 'member_type' => '普通客户', + 'package_name' => '普通洗车', + 'start_time' => '2023-10-05 11:00:00', + 'end_time' => '2023-10-05 11:30:00', + 'duration' => 30, + 'total_price' => '58.00', + 'notes' => '', + 'status' => '已确认', + 'payment_status' => '已付款', + 'source' => '其他' + ]; + } + + // 模拟发送预约确认信息 + function sendBookingConfirmation($booking_id) { + // 获取预约数据 + $booking = getBookingFromDatabase($booking_id); + + // 生成预约信息 + $template_name = $booking['member_type'] == 'VIP会员' ? 'detailed' : 'basic'; + $message = generateBookingMessage($booking, $template_name); + $title = getTemplateTitle($template_name); + + // 这里应该是实际的发送逻辑(短信、微信等) + echo "向 {$booking['phone']} 发送信息:\n"; + echo "标题:{$title}\n"; + echo "内容:\n{$message}\n"; + + return true; + } + + // 使用示例 + $booking_id = 456; + sendBookingConfirmation($booking_id); +} + +// 运行所有示例 +example_basic_template(); +example_detailed_template(); +example_simple_template(); +example_custom_data(); +example_integration(); + +// 显示可用模板 +echo "\n=== 可用模板列表 ===\n"; +echo "当前系统中可用的预约信息模板:\n"; +$templates = getAvailableTemplates(); +foreach ($templates as $template) { + echo "- {$template} (标题:" . getTemplateTitle($template) . ")\n"; +} + +// 如何自定义模板的说明 +echo "\n=== 如何自定义模板 ===\n"; +echo "1. 打开 booking_template.php 文件\n"; +echo "2. 在 \$booking_templates 数组中添加新的模板或修改现有模板\n"; +echo "3. 每个模板包含 title 和 message 两个字段\n"; +echo "4. 使用 {字段名} 作为占位符,系统会自动替换为实际数据\n"; +echo "5. 可使用的占位符包括:\n"; +echo " - {customer_name}:客户姓名\n"; +echo " - {phone}:手机号\n"; +echo " - {car_model}:车型\n"; +echo " - {car_number}:车牌号\n"; +echo " - {member_type}:会员类型\n"; +echo " - {package_name}:服务项目\n"; +echo " - {custom_services}:自定义服务\n"; +echo " - {start_time}:预约开始时间\n"; +echo " - {end_time}:预约结束时间\n"; +echo " - {date}:预约日期\n"; +echo " - {time_range}:时间范围\n"; +echo " - {duration}:服务时长\n"; +echo " - {total_price}:总价\n"; +echo " - {notes}:备注\n"; +echo " - {status}:预约状态\n"; +echo " - {payment_status}:支付状态\n"; +echo " - {source}:来源渠道\n"; +echo " - {created_at}:创建时间\n"; +?> \ No newline at end of file diff --git a/get_daily_booking_duration.php b/get_daily_booking_duration.php new file mode 100644 index 0000000..b4b8d52 --- /dev/null +++ b/get_daily_booking_duration.php @@ -0,0 +1,28 @@ + 'Invalid date format']); + exit; +} + +try { + // 查询指定日期的总预约时长 + $sql = "SELECT SUM(duration) as total_duration FROM bookings WHERE DATE(start_time) = ?"; + $stmt = $pdo->prepare($sql); + $stmt->execute([$date]); + $row = $stmt->fetch(); + + // 获取总时长,如果没有预约则返回0 + $total_duration = $row['total_duration'] ? $row['total_duration'] : 0; + + // 返回结果 + echo json_encode(['total_duration' => $total_duration]); +} catch (PDOException $e) { + echo json_encode(['error' => 'Database query failed: ' . $e->getMessage()]); +} diff --git a/index.php b/index.php index 63524bf..1ef8494 100644 --- a/index.php +++ b/index.php @@ -96,13 +96,16 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { } // 插入预约记录 + // 对于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) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); + 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]); + $start_time, $end_time, $duration, $total_price, $notes, $member_type, $source, $payment_status]); $success_message = "预约提交成功!"; diff --git a/pending_bookings.php b/pending_bookings.php index caa3d33..bd825f5 100644 --- a/pending_bookings.php +++ b/pending_bookings.php @@ -42,14 +42,17 @@ if (isset($_POST['action']) && $_POST['action'] == 'convert_to_booking' && isset $end_time = date('Y-m-d H:i:s', strtotime($start_time) + $duration * 60); // 将数据插入到正式预约表 + // 对于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, status, - member_type, source + member_type, source, payment_status ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, - ?, ? + ?, ?, ? )"); $stmt->execute([ @@ -66,7 +69,8 @@ if (isset($_POST['action']) && $_POST['action'] == 'convert_to_booking' && isset $submission['remarks'], '已确认', // 默认设置为已确认 '普通客户', // 默认普通客户,可根据需要调整 - '其他' // 默认来源,可根据需要调整 + '其他', // 默认来源,可根据需要调整 + $payment_status // 根据总价自动设置付款状态 ]); $booking_id = $pdo->lastInsertId(); @@ -430,6 +434,32 @@ try { background: #c3e6cb; } + /* 预约时长提示样式 */ + .duration-alert { + margin: 15px 0; + padding: 15px; + border-radius: 4px; + font-weight: bold; + } + + .duration-alert .alert { + padding: 12px; + border-radius: 4px; + margin-bottom: 0; + } + + .duration-alert .alert-warning { + background-color: #fff3cd; + border-color: #ffeaa7; + color: #856404; + } + + .duration-alert .alert-info { + background-color: #d1ecf1; + border-color: #bee5eb; + color: #0c5460; + } + /* 套餐信息样式 */ .package-info { background: #f8f9fa; @@ -723,6 +753,11 @@ try { + +
+ +
+
@@ -852,6 +887,9 @@ try { // 生成时间段 generateTimeSlots(submissionId, date); + + // 显示时长提示 + showDurationAlert(submissionId); } // 生成时间段 @@ -934,6 +972,9 @@ try { if (slotElement) { slotElement.classList.add('selected'); } + + // 显示时长提示 + showDurationAlert(submissionId); } // 更新套餐信息 @@ -1137,6 +1178,9 @@ try { if (!buttonFound) { console.warn('⚠️ No matching duration button found for:', minutes, 'minutes'); } + + // 显示时长提示 + showDurationAlert(submissionId); } // 应用自定义时长 @@ -1159,6 +1203,57 @@ try { customDurationInput.value = roundedDuration; selectDuration(submissionId, roundedDuration); } + + // 显示时长提示 + showDurationAlert(submissionId); + } + + // 计算当天总预约时长(异步函数) + async function calculateDailyTotalDuration(submissionId) { + const selectedDate = document.getElementById('selected_date_' + submissionId).value; + const currentDuration = parseInt(document.getElementById('customDuration_' + submissionId).value); + + try { + // 通过AJAX请求获取当天已有的预约时长 + const response = await fetch(`get_daily_booking_duration.php?date=${selectedDate}`); + const data = await response.json(); + + if (data.error) { + console.error('获取当天预约时长失败:', data.error); + return currentDuration; // 如果获取失败,只返回当前预约时长 + } + + const existingDuration = data.total_duration || 0; + return existingDuration + currentDuration; + } catch (error) { + console.error('获取当天预约时长出错:', error); + return currentDuration; // 如果出错,只返回当前预约时长 + } + } + + // 显示时长提示 + async function showDurationAlert(submissionId) { + const alertContainer = document.getElementById('durationAlert_' + submissionId); + + // 清空现有提示 + alertContainer.innerHTML = '
加载中...
'; + + try { + const totalDuration = await calculateDailyTotalDuration(submissionId); + + // 清空现有提示 + alertContainer.innerHTML = ''; + + // 根据总时长显示不同的提示 + if (totalDuration >= 720) { // 大于等于12小时 + alertContainer.innerHTML = '
⚠️ 当天总预约时长已达到12小时,你要当超人啊,别约了!
'; + } else if (totalDuration >= 360) { // 大于等于6小时 + alertContainer.innerHTML = '
💡 当天总预约时长已达到6小时,注意休息!
'; + } + } catch (error) { + console.error('计算总预约时长出错:', error); + alertContainer.innerHTML = ''; + } }