This repository has been archived on 2026-06-20. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
carwash_order/pending_bookings.php
T
wsh5485 2c0e7cbb5f style: 将容器最大宽度从1200px调整为1400px
统一修改多个页面容器的最大宽度,以提供更宽敞的布局空间
2025-12-12 16:56:04 +08:00

1203 lines
52 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
date_default_timezone_set('Asia/Shanghai');
// pending_bookings.php - 待预约页面,处理WPS表单数据
session_start();
require_once 'db_connect.php';
// 处理表单提交
$success_message = '';
$error_message = '';
// 如果有预约转换请求
if (isset($_POST['action']) && $_POST['action'] == 'convert_to_booking' && isset($_POST['submission_id'])) {
$submission_id = $_POST['submission_id'];
$selected_date = $_POST['selected_date'];
$selected_time = $_POST['selected_time'];
$selected_package = $_POST['selected_package'];
$custom_notes = $_POST['custom_notes'];
$total_price = $_POST['total_price'];
$duration = $_POST['duration'];
try {
// 获取WPS表单提交数据
$stmt = $pdo->prepare("SELECT * FROM wps_form_submissions WHERE id = ?");
$stmt->execute([$submission_id]);
$submission = $stmt->fetch();
if (!$submission) {
throw new Exception("表单提交数据不存在");
}
// 获取套餐信息
$stmt = $pdo->prepare("SELECT * FROM packages WHERE id = ?");
$stmt->execute([$selected_package]);
$package = $stmt->fetch();
if (!$package) {
throw new Exception("选择的套餐不存在");
}
// 计算开始和结束时间
$start_time = $selected_date . ' ' . $selected_time;
$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, payment_status
) VALUES (
?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?,
?, ?, ?
)");
$stmt->execute([
$submission['name'],
$submission['mobile'],
$submission['car_type'],
$submission['license_plate'],
$selected_package,
$custom_notes,
$start_time,
$end_time,
$duration,
$total_price,
$submission['remarks'],
'已确认', // 默认设置为已确认
'普通客户', // 默认普通客户,可根据需要调整
'其他', // 默认来源,可根据需要调整
$payment_status // 根据总价自动设置付款状态
]);
$booking_id = $pdo->lastInsertId();
// 更新WPS表单提交状态为已处理
$stmt = $pdo->prepare("UPDATE wps_form_submissions SET status = 'processed' WHERE id = ?");
$stmt->execute([$submission_id]);
// 生成预约成功信息
$booking_success_msg = "预约成功!\n\n客户:{$submission['name']}\n手机号:{$submission['mobile']}\n车牌号:{$submission['license_plate']}\n车型:{$submission['car_type']}\n\n预约时间:{$start_time}\n服务项目:{$package['package_name']}\n服务时长:{$duration}分钟\n总价:{$total_price}\n\n感谢您的预约!";
$success_message = "预约转换成功!预约ID{$booking_id}";
// 存储预约成功信息到会话,以便在页面上显示
$_SESSION['booking_success_msg'] = $booking_success_msg;
} catch (Exception $e) {
$error_message = '预约转换失败:' . $e->getMessage();
}
}
// 获取待处理的WPS表单提交
try {
$stmt = $pdo->prepare("SELECT * FROM wps_form_submissions WHERE status = 'pending' ORDER BY create_time DESC");
$stmt->execute();
$pending_submissions = $stmt->fetchAll();
} catch (Exception $e) {
$error_message = '获取待处理表单失败:' . $e->getMessage();
$pending_submissions = [];
}
// 获取所有套餐
try {
$stmt = $pdo->prepare("SELECT * FROM packages WHERE is_active = true");
$stmt->execute();
$packages = $stmt->fetchAll();
} catch (Exception $e) {
$error_message = '获取套餐信息失败:' . $e->getMessage();
$packages = [];
}
// 获取当前日期及未来7天的日期
$current_date = date('Y-m-d');
$available_dates = [];
for ($i = 0; $i < 7; $i++) {
$available_dates[] = date('Y-m-d', strtotime($current_date . " +$i days"));
}
// 获取所有预约数据,用于显示空闲时间段
$booking_schedule = [];
$bookings_by_date = [];
try {
// 获取所有未来的预约(排除已取消的订单)
$stmt = $pdo->prepare("SELECT * FROM bookings WHERE end_time > NOW() AND status != '已取消' ORDER BY start_time ASC");
$stmt->execute();
$all_bookings = $stmt->fetchAll();
// 处理预约数据
foreach ($all_bookings as $booking) {
$start_date = date('Y-m-d', strtotime($booking['start_time']));
$end_date = date('Y-m-d', strtotime($booking['end_time']));
$start_time = date('H:i', strtotime($booking['start_time']));
$end_time = date('H:i', strtotime($booking['end_time']));
// 处理跨天预约
$is_cross_day = $start_date != $end_date;
// 添加到预约日程
if (!isset($booking_schedule[$start_date])) {
$booking_schedule[$start_date] = [];
}
if (!isset($bookings_by_date[$start_date])) {
$bookings_by_date[$start_date] = [];
}
// 主预约记录
$bookings_by_date[$start_date][] = [
'booking_id' => $booking['id'],
'customer_name' => $booking['customer_name'],
'car_model' => $booking['car_model'],
'car_number' => $booking['car_number'],
'status' => $booking['status'],
'start_time' => $start_time,
'end_time' => $end_time,
'is_cross_day' => $is_cross_day
];
// 如果是跨天预约,添加第二天的记录
if ($is_cross_day) {
if (!isset($bookings_by_date[$end_date])) {
$bookings_by_date[$end_date] = [];
}
$bookings_by_date[$end_date][] = [
'booking_id' => $booking['id'],
'customer_name' => $booking['customer_name'],
'car_model' => $booking['car_model'],
'car_number' => $booking['car_number'],
'status' => $booking['status'],
'start_time' => $start_time,
'end_time' => $end_time,
'is_cross_day' => $is_cross_day
];
}
}
} catch (Exception $e) {
$error_message = '获取预约数据失败:' . $e->getMessage();
}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="format-detection" content="telephone=no">
<meta name="description" content="待处理预约页面,处理WPS表单数据">
<meta name="keywords" content="待处理预约,预约管理,洗车预约">
<title>张老师撸车(私家车库)工作室</title>
<link rel="stylesheet" href="style.css">
<script src="mobile-nav.js" defer></script>
<!-- Favicon for mobile devices -->
<link rel="apple-touch-icon" sizes="180x180" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🚗</text></svg>">
<style>
/* 待预约页面特定样式 */
.pending-bookings-container {
max-width: 1400px;
margin: 0 auto;
padding: 20px;
}
.pending-card {
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
margin-bottom: 20px;
overflow: hidden;
}
.pending-card.selected-card {
background: #e3f2fd;
border: 2px solid #2196f3;
box-shadow: 0 4px 15px rgba(33, 150, 243, 0.3);
}
.pending-header {
background: #f5f5f5;
padding: 15px 20px;
border-bottom: 1px solid #ddd;
display: flex;
justify-content: space-between;
align-items: center;
}
.pending-details {
padding: 20px;
}
.detail-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 15px;
margin-bottom: 20px;
}
.detail-item {
margin-bottom: 10px;
}
.detail-label {
font-weight: bold;
color: #666;
}
.convert-form {
background: #f9f9f9;
padding: 20px;
border-top: 1px solid #ddd;
}
.form-row {
display: flex;
flex-wrap: wrap;
gap: 15px;
margin-bottom: 15px;
}
.form-group {
flex: 1;
min-width: 200px;
}
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
.form-group input, .form-group select, .form-group textarea {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
}
.btn {
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
font-weight: bold;
}
.btn-primary {
background: #007bff;
color: white;
}
.btn-primary:hover {
background: #0056b3;
}
.booking-success {
background: #d4edda;
border: 1px solid #c3e6cb;
color: #155724;
padding: 15px;
border-radius: 4px;
margin: 20px 0;
}
.status-badge {
padding: 5px 10px;
border-radius: 12px;
font-size: 12px;
font-weight: bold;
}
.status-pending {
background: #ffc107;
color: #212529;
}
/* 预约记录选择器样式 */
.submission-selector {
margin-bottom: 20px;
}
.submission-list {
display: flex;
flex-direction: column;
gap: 10px;
}
.submission-item {
background: #fff;
border: 1px solid #ddd;
border-radius: 8px;
padding: 15px;
cursor: pointer;
transition: all 0.3s ease;
}
.submission-item:hover {
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
border-color: #007bff;
}
.submission-item.selected-item {
background: #e3f2fd;
border-color: #2196f3;
box-shadow: 0 4px 15px rgba(33, 150, 243, 0.3);
}
.submission-info h4 {
margin: 0 0 10px 0;
color: #333;
}
.submission-meta {
display: flex;
flex-wrap: wrap;
gap: 15px;
color: #666;
font-size: 14px;
}
/* 日历和时间选择样式 */
.calendar-container {
margin-bottom: 20px;
}
.calendar-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.calendar-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
gap: 10px;
}
.calendar-day {
padding: 15px;
background: #f5f5f5;
border-radius: 4px;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
}
.calendar-day:hover {
background: #e9ecef;
}
.calendar-day.selected {
background: #007bff;
color: white;
}
.time-slots-container {
margin-bottom: 20px;
}
.time-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
gap: 10px;
}
.time-slot {
padding: 10px;
border-radius: 4px;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
}
.time-slot.available {
background: #d4edda;
color: #155724;
}
.time-slot.booked {
background: #f8d7da;
color: #721c24;
cursor: not-allowed;
}
.time-slot.past {
background: #e9ecef;
color: #6c757d;
cursor: not-allowed;
}
.time-slot.selected {
background: #007bff;
color: white;
}
.time-slot:hover.available {
background: #c3e6cb;
}
/* 预约时长提示样式 */
/* 套餐信息样式 */
.package-info {
background: #f8f9fa;
border: 1px solid #e9ecef;
border-radius: 8px;
padding: 20px;
margin-bottom: 20px;
display: none;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
transition: all 0.3s ease;
}
.package-info:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
}
.package-details {
margin-bottom: 15px;
}
.package-details h4 {
margin: 0 0 12px 0;
color: #2c3e50;
font-size: 18px;
font-weight: 600;
}
.package-meta {
display: flex;
gap: 16px;
margin: 15px 0;
flex-wrap: wrap;
align-items: center;
}
.package-meta span {
background: #e3f2fd;
color: #1976d2;
padding: 6px 12px;
border-radius: 20px;
font-size: 14px;
font-weight: 500;
}
#packageServices_<?php echo $submission['id']; ?> {
margin-top: 15px;
padding: 15px;
background: #ffffff;
border: 1px solid #e0e0e0;
border-radius: 6px;
}
#packageServices_<?php echo $submission['id']; ?> strong {
color: #2c3e50;
font-size: 16px;
display: block;
margin-bottom: 10px;
}
#packageServices_<?php echo $submission['id']; ?> br {
display: none;
}
#packageServices_<?php echo $submission['id']; ?>::before {
content: '';
}
#packageServices_<?php echo $submission['id']; ?>::after {
content: '';
}
.service-list {
margin: 10px 0 0 20px;
padding: 0;
}
.service-list li {
margin-bottom: 6px;
color: #424242;
line-height: 1.6;
font-size: 15px;
}
.service-list li::marker {
color: #1976d2;
font-weight: bold;
}
.booking-detail-item {
background: #fff;
border: 1px solid #e9ecef;
border-radius: 4px;
padding: 10px;
margin-bottom: 10px;
}
.booking-time {
font-weight: bold;
margin-bottom: 5px;
}
.status-已确认 {
color: #28a745;
}
.status-待服务 {
color: #ffc107;
}
.status-已完成 {
color: #6c757d;
}
</style>
</head>
<body>
<div class="pending-bookings-container">
<header class="header">
<button class="mobile-menu-toggle" onclick="toggleMobileMenu()" aria-label="菜单">
<span></span>
<span></span>
<span></span>
</button>
<h1>🚗 张老师撸车工作室 - 待处理预约</h1>
<nav class="nav">
<a href="index.php" class="nav-link">预约洗车</a>
<a href="bookings.php" class="nav-link">预约管理</a>
<a href="pending_bookings.php" class="nav-link active">待处理预约</a>
<a href="packages.php" class="nav-link">套餐管理</a>
<a href="vip.php" class="nav-link">VIP管理</a>
<a href="announcement.php" class="nav-link">今日待办</a>
</nav>
</header>
<!-- 移动端导航菜单 -->
<div class="mobile-nav-overlay" onclick="closeMobileMenu()"></div>
<nav class="mobile-nav">
<a href="index.php" class="nav-link">预约洗车</a>
<a href="bookings.php" class="nav-link">预约管理</a>
<a href="pending_bookings.php" class="nav-link active">待处理预约</a>
<a href="packages.php" class="nav-link">套餐管理</a>
<a href="vip.php" class="nav-link">VIP管理</a>
<a href="announcement.php" class="nav-link">今日待办</a>
</nav>
<?php if (isset($success_message)): ?>
<div class="success-message"><?php echo $success_message; ?></div>
<?php endif; ?>
<?php if (isset($error_message)): ?>
<div class="error-message">
<?php echo $error_message; ?>
</div>
<?php endif; ?>
<div class="card enhanced-card">
<h2>待处理预约 (共 <?php echo count($pending_submissions); ?> 条)</h2>
<?php if (empty($pending_submissions)): ?>
<div class="empty-message">暂无待处理的预约请求</div>
<?php else: ?>
<!-- 无论记录数量多少,都显示选择列表 -->
<?php if (true): ?>
<div class="submission-selector enhanced-card">
<h3>选择要处理的预约记录</h3>
<div class="submission-list">
<?php foreach ($pending_submissions as $submission): ?>
<div class="submission-item" onclick="selectSubmission(<?php echo $submission['id']; ?>)">
<div class="submission-info">
<h4><?php echo htmlspecialchars($submission['name']); ?></h4>
<div class="submission-meta">
<span>手机号:<?php echo htmlspecialchars($submission['mobile']); ?></span>
<span>车牌号:<?php echo htmlspecialchars($submission['license_plate']); ?></span>
<span>提交时间:<?php echo htmlspecialchars($submission['create_time']); ?></span>
</div>
</div>
<span class="status-badge status-pending">待处理</span>
</div>
<?php endforeach; ?>
</div>
</div>
<?php endif; ?>
<!-- 显示选中的预约记录的处理表单 -->
<?php foreach ($pending_submissions as $submission): ?>
<div class="pending-card enhanced-card" id="submission_<?php echo $submission['id']; ?>" style="display: none;">
<div class="pending-header">
<h3><?php echo htmlspecialchars($submission['name']); ?> 的预约请求</h3>
<span class="status-badge status-pending">待处理</span>
</div>
<div class="pending-details">
<div class="detail-grid">
<div class="detail-item">
<span class="detail-label">联系方式:</span>
<span class="detail-value"><?php echo htmlspecialchars($submission['mobile']); ?></span>
</div>
<div class="detail-item">
<span class="detail-label">车牌号:</span>
<span class="detail-value"><?php echo htmlspecialchars($submission['license_plate']); ?></span>
</div>
<div class="detail-item">
<span class="detail-label">车型:</span>
<span class="detail-value"><?php echo htmlspecialchars($submission['car_type']); ?></span>
</div>
<div class="detail-item">
<span class="detail-label">是否有车衣:</span>
<span class="detail-value"><?php echo htmlspecialchars($submission['has_car_coat']); ?></span>
</div>
<div class="detail-item">
<span class="detail-label">洗车习惯:</span>
<span class="detail-value"><?php echo htmlspecialchars($submission['car_wash_habit']); ?></span>
</div>
<div class="detail-item">
<span class="detail-label">撸车经验:</span>
<span class="detail-value"><?php echo htmlspecialchars($submission['car_wash_experience']); ?></span>
</div>
<div class="detail-item">
<span class="detail-label">洗车频率:</span>
<span class="detail-value"><?php echo htmlspecialchars($submission['wash_frequency']); ?></span>
</div>
<div class="detail-item">
<span class="detail-label">年龄段:</span>
<span class="detail-value"><?php echo htmlspecialchars($submission['age_group']); ?></span>
</div>
<div class="detail-item">
<span class="detail-label">自动编号:</span>
<span class="detail-value"><?php echo htmlspecialchars($submission['auto_number']); ?></span>
</div>
<div class="detail-item">
<span class="detail-label">提交时间:</span>
<span class="detail-value"><?php echo htmlspecialchars($submission['create_time']); ?></span>
</div>
</div>
<?php if (!empty($submission['remarks'])): ?>
<div class="detail-item">
<span class="detail-label">备注:</span>
<span class="detail-value"><?php echo htmlspecialchars($submission['remarks']); ?></span>
</div>
<?php endif; ?>
</div>
<div class="convert-form">
<h4>转换为正式预约</h4>
<form method="POST" action="pending_bookings.php">
<input type="hidden" name="action" value="convert_to_booking">
<input type="hidden" name="submission_id" value="<?php echo $submission['id']; ?>">
<div class="form-group">
<label for="selected_package_<?php echo $submission['id']; ?>">选择套餐:</label>
<select id="selected_package_<?php echo $submission['id']; ?>" name="selected_package" required onchange="updatePackageInfo(<?php echo $submission['id']; ?>)">
<option value="">请选择套餐</option>
<?php foreach ($packages as $package): ?>
<option value="<?php echo $package['id']; ?>"
data-duration="<?php echo $package['base_duration']; ?>"
data-price="<?php echo $package['price']; ?>"
data-services='<?php echo htmlspecialchars($package['services']); ?>'>
<?php echo htmlspecialchars($package['package_name']); ?> - ¥<?php echo number_format($package['price'], 2); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="package-info enhanced-card" id="packageInfo_<?php echo $submission['id']; ?>">
<div class="package-details">
<h4 id="packageName_<?php echo $submission['id']; ?>"></h4>
<div class="package-meta">
<span id="packageDuration_<?php echo $submission['id']; ?>"></span>
<span id="packagePrice_<?php echo $submission['id']; ?>"></span>
</div>
<div class="form-group" style="margin-top: 15px;">
<label for="total_price_<?php echo $submission['id']; ?>">最终价格 (¥)</label>
<input type="number" id="total_price_<?php echo $submission['id']; ?>" name="total_price" min="0" step="0.01" value="0" placeholder="输入最终价格" required>
<input type="hidden" id="package_price_<?php echo $submission['id']; ?>" value="0">
</div>
<div id="packageServices_<?php echo $submission['id']; ?>"></div>
</div>
</div>
<div class="calendar-container">
<div class="calendar-header">
<h5>选择预约日期</h5>
</div>
<div class="calendar-grid" id="calendarGrid_<?php echo $submission['id']; ?>">
<?php foreach ($available_dates as $date): ?>
<div class="calendar-day"
data-date="<?php echo $date; ?>"
onclick="selectDate(<?php echo $submission['id']; ?>, '<?php echo $date; ?>')">
<div><?php echo date('m月d日', strtotime($date)); ?></div>
<div><?php echo date('D', strtotime($date)); ?></div>
</div>
<?php endforeach; ?>
</div>
</div>
<div class="form-group">
<input type="hidden" id="selected_date_<?php echo $submission['id']; ?>" name="selected_date" value="<?php echo date('Y-m-d'); ?>">
<input type="hidden" id="selected_time_<?php echo $submission['id']; ?>" name="selected_time" value="" required>
</div>
<div class="time-slots-container">
<h5>选择预约时间</h5>
<div class="time-grid" id="timeGrid_<?php echo $submission['id']; ?>">
<!-- 时间格子将通过JavaScript生成 -->
</div>
</div>
<!-- 预约时长提示区域 -->
<!-- 提示信息将通过JavaScript动态生成 -->
</div>
<div class="form-row">
<div class="form-group">
<label for="customDuration_<?php echo $submission['id']; ?>">服务时长(分钟)</label>
<div class="quick-duration">
<button type="button" class="duration-btn" data-duration="60" onclick="selectDuration(<?php echo $submission['id']; ?>, 60)">1小时</button>
<button type="button" class="duration-btn" data-duration="90" onclick="selectDuration(<?php echo $submission['id']; ?>, 90)">1.5小时</button>
<button type="button" class="duration-btn" data-duration="120" onclick="selectDuration(<?php echo $submission['id']; ?>, 120)">2小时</button>
<button type="button" class="duration-btn" data-duration="240" onclick="selectDuration(<?php echo $submission['id']; ?>, 240)">4小时</button>
<button type="button" class="duration-btn" data-duration="360" onclick="selectDuration(<?php echo $submission['id']; ?>, 360)">6小时</button>
<button type="button" class="duration-btn" data-duration="480" onclick="selectDuration(<?php echo $submission['id']; ?>, 480)">8小时</button>
<button type="button" class="duration-btn" data-duration="600" onclick="selectDuration(<?php echo $submission['id']; ?>, 600)">10小时</button>
<button type="button" class="duration-btn" data-duration="720" onclick="selectDuration(<?php echo $submission['id']; ?>, 720)">12小时</button>
<input type="number" id="customDuration_<?php echo $submission['id']; ?>" name="duration" min="30" step="30" value="60" style="width: 80px; margin-left: 10px; margin-top: 10px;" required>
<span style="margin-left: 5px; margin-right: 5px;">分钟</span>
<!-- <button type="button" class="btn btn-sm" onclick="applyCustomDuration(<?php echo $submission['id']; ?>)">确定</button> -->
</div>
</div>
</div>
<div class="form-group">
<label for="custom_notes_<?php echo $submission['id']; ?>">自定义服务需求:</label>
<textarea id="custom_notes_<?php echo $submission['id']; ?>" name="custom_notes" rows="3"
placeholder="如有特殊需求,请在此说明..."></textarea>
</div>
<button type="submit" class="btn btn-primary">确认预约</button>
</form>
</div>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
</div>
<script>
// 选择预约记录函数(提前定义,确保在调用前可用)
function selectSubmission(submissionId) {
// 隐藏所有待处理预约卡片并移除高亮
document.querySelectorAll('.pending-card').forEach(card => {
card.style.display = 'none';
card.classList.remove('selected-card');
});
// 移除选择列表中所有项的高亮
document.querySelectorAll('.submission-item').forEach(item => {
item.classList.remove('selected-item');
});
// 显示选中的预约卡片并添加高亮
const selectedCard = document.getElementById(`submission_${submissionId}`);
if (selectedCard) {
selectedCard.style.display = 'block';
selectedCard.classList.add('selected-card');
}
// 为选择列表中对应的项添加高亮
const submissionItems = document.querySelectorAll('.submission-item');
submissionItems.forEach(item => {
// 查找包含当前submissionId的点击事件
if (item.onclick && item.onclick.toString().includes(`selectSubmission(${submissionId})`)) {
item.classList.add('selected-item');
}
});
}
// 工作时间设置
const workingHours = {
start: 0, // 00:00
end: 24, // 24:00
slotDuration: 30 // 30分钟一个时段
};
// 预约数据 - 为每个提交创建独立的预约数据对象
const allBookingsByDate = <?php echo json_encode($bookings_by_date); ?>;
// 页面加载时初始化所有预约的日期、时间和套餐信息
document.addEventListener('DOMContentLoaded', function() {
<?php $firstSubmissionId = null; ?>
<?php foreach ($pending_submissions as $submission): ?>
<?php if ($firstSubmissionId === null) $firstSubmissionId = $submission['id']; ?>
// 初始化日期
selectDate(<?php echo $submission['id']; ?>, '<?php echo date('Y-m-d'); ?>');
// 初始化默认套餐信息(如果有默认选择的话)
(function() {
let packageSelectElem = document.getElementById('selected_package_<?php echo $submission['id']; ?>');
if (packageSelectElem.value) {
updatePackageInfo(<?php echo $submission['id']; ?>);
} else if (packageSelectElem.options.length > 1) {
// 默认选择第一个套餐
packageSelectElem.selectedIndex = 1;
updatePackageInfo(<?php echo $submission['id']; ?>);
}
})();
<?php endforeach; ?>
// 默认显示并高亮第一条记录
<?php if ($firstSubmissionId !== null): ?>
selectSubmission(<?php echo $firstSubmissionId; ?>);
<?php endif; ?>
});
// 选择日期
function selectDate(submissionId, date) {
const calendarGrid = document.getElementById('calendarGrid_' + submissionId);
const timeGrid = document.getElementById('timeGrid_' + submissionId);
const selectedDateInput = document.getElementById('selected_date_' + submissionId);
// 更新日期输入
selectedDateInput.value = date;
// 更新日历选中状态
calendarGrid.querySelectorAll('.calendar-day').forEach(day => {
day.classList.remove('selected');
});
// 找到当前日历中的日期元素
const calendarDays = calendarGrid.querySelectorAll('.calendar-day');
calendarDays.forEach(day => {
if (day.dataset.date === date) {
day.classList.add('selected');
}
});
// 生成时间段
generateTimeSlots(submissionId, date);
}
// 生成时间段
function generateTimeSlots(submissionId, date) {
const timeGrid = document.getElementById('timeGrid_' + submissionId);
const selectedTimeInput = document.getElementById('selected_time_' + submissionId);
timeGrid.innerHTML = '';
// 获取当天已有预约
const dayBookings = allBookingsByDate[date] || [];
// 生成时间段
for (let hour = workingHours.start; hour < workingHours.end; hour++) {
for (let minute = 0; minute < 60; minute += workingHours.slotDuration) {
const timeString = `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;
const slotTime = new Date(`${date} ${timeString}:00`);
const now = new Date();
const isPast = slotTime <= now;
const isBooked = checkTimeSlotBooked(date, timeString);
const slotDiv = document.createElement('div');
slotDiv.className = `time-slot ${isPast ? 'past' : ''} ${isBooked ? 'booked' : 'available'}`;
slotDiv.textContent = timeString;
slotDiv.dataset.time = timeString;
// 只有可用的时间段才添加点击事件
if (!isPast && !isBooked) {
slotDiv.onclick = () => selectTimeSlot(submissionId, timeString);
} else {
// 禁用不可点击的时间段
slotDiv.style.cursor = 'not-allowed';
}
timeGrid.appendChild(slotDiv);
}
}
selectedTimeInput.value = '';
}
// 检查时间段是否已被预约
function checkTimeSlotBooked(date, time) {
const bookings = allBookingsByDate[date] || [];
for (let booking of bookings) {
const bookingStart = booking.start_time;
const bookingEnd = booking.end_time;
// 处理跨天预约的情况
if (booking.is_cross_day) {
// 如果是跨天预约的第二天记录,所有时间都应该是已被预约的(从00:00到结束时间)
if (time < bookingEnd) {
return true; // 该时间段已被预约
}
} else {
// 正常预约检查
if (time >= bookingStart && time < bookingEnd) {
return true; // 该时间段已被预约
}
}
}
return false; // 该时间段可用
}
// 选择时间
function selectTimeSlot(submissionId, time) {
const selectedTimeInput = document.getElementById('selected_time_' + submissionId);
// 更新时间输入
selectedTimeInput.value = time;
// 更新时间段选中状态
const timeGrid = document.getElementById('timeGrid_' + submissionId);
timeGrid.querySelectorAll('.time-slot').forEach(slot => {
slot.classList.remove('selected');
});
const slotElement = timeGrid.querySelector(`[data-time="${time}"]`);
if (slotElement) {
slotElement.classList.add('selected');
}
}
// 更新套餐信息
function updatePackageInfo(submissionId) {
console.log('=== updatePackageInfo called with submissionId:', submissionId, '===');
// 直接获取表单元素,确保在正确的表单上下文中操作
const packageSelect = document.getElementById('selected_package_' + submissionId);
if (!packageSelect) {
console.error('❌ Package select not found for submissionId:', submissionId);
return;
}
// 获取当前表单
const form = packageSelect.closest('form');
if (!form) {
console.error('❌ Form not found for submissionId:', submissionId);
return;
}
const selectedOption = packageSelect.options[packageSelect.selectedIndex];
const packageInfoDiv = document.getElementById('packageInfo_' + submissionId);
console.log('Selected option:', selectedOption, 'value:', selectedOption ? selectedOption.value : 'null');
if (selectedOption && selectedOption.value) {
// 使用getAttribute方法获取data属性,确保兼容所有浏览器
const duration = parseInt(selectedOption.getAttribute('data-duration'));
const price = parseFloat(selectedOption.getAttribute('data-price'));
const servicesJSON = selectedOption.getAttribute('data-services');
let services = [];
// 尝试解析servicesJSON,如果解析失败则将其视为逗号分隔字符串
if (servicesJSON) {
try {
// 尝试作为JSON解析
services = JSON.parse(servicesJSON);
console.log('✅ Parsed services as JSON:', services);
} catch (e) {
// 如果JSON解析失败,尝试作为逗号分隔字符串处理
console.log('⚠️ JSON parse failed, treating as comma-separated string:', servicesJSON);
services = servicesJSON.split(',').map(service => service.trim()).filter(service => service.length > 0);
console.log('✅ Converted to array:', services);
}
}
console.log('Package data:', {duration, price, services: services.length});
// 更新套餐信息显示
const packageNameElement = document.getElementById('packageName_' + submissionId);
const packageDurationElement = document.getElementById('packageDuration_' + submissionId);
const packagePriceElement = document.getElementById('packagePrice_' + submissionId);
if (packageNameElement) packageNameElement.textContent = selectedOption.textContent;
if (packageDurationElement) packageDurationElement.textContent = `基础时长: ${duration}分钟`;
if (packagePriceElement) packagePriceElement.textContent = `套餐价格: ¥${price.toFixed(2)}`;
// 更新服务项目显示
const servicesContainer = document.getElementById('packageServices_' + submissionId);
if (servicesContainer) {
if (services && services.length > 0) {
servicesContainer.innerHTML = '<strong>包含服务:</strong><ul class="service-list">' +
services.map(service => `<li>${service}</li>`).join('') + '</ul>';
} else {
servicesContainer.innerHTML = '';
}
}
// 使用两种方式获取时长输入框,确保万无一失
const durationInputById = document.getElementById('customDuration_' + submissionId);
const durationInputByName = form.querySelector('input[name="duration"]');
console.log('Duration inputs found - by ID:', durationInputById ? 'Yes' : 'No', 'by Name:', durationInputByName ? 'Yes' : 'No');
// 优先使用ID获取的元素,如果不存在则使用name获取的元素
const durationInput = durationInputById || durationInputByName;
if (durationInput) {
// 强制设置时长值
durationInput.value = duration;
// 触发change事件,确保所有依赖此输入的功能都能更新
durationInput.dispatchEvent(new Event('change'));
console.log('✅ Successfully updated duration input to:', duration);
} else {
console.error('❌ Cannot find duration input for submissionId:', submissionId);
}
// 同时更新自定义时长输入框
const customDurationInput = document.getElementById('customDuration_' + submissionId);
if (customDurationInput) {
customDurationInput.value = duration;
console.log('✅ Successfully updated custom duration input to:', duration);
} else {
console.error('❌ Cannot find custom duration input for submissionId:', submissionId);
}
// 更新价格输入框
const totalPriceInput = document.getElementById('total_price_' + submissionId);
if (totalPriceInput) {
totalPriceInput.value = price.toFixed(2);
console.log('✅ Updated total price to:', price.toFixed(2));
}
// 更新快捷选择按钮状态
console.log('Calling selectDuration with:', submissionId, duration);
selectDuration(submissionId, duration);
// 显示套餐信息
if (packageInfoDiv) {
packageInfoDiv.style.display = 'block';
}
} else {
if (packageInfoDiv) {
packageInfoDiv.style.display = 'none';
}
console.log('❌ No package selected');
}
}
// 快捷选择服务时长
function selectDuration(submissionId, minutes) {
console.log('=== selectDuration called with submissionId:', submissionId, 'minutes:', minutes, '===');
// 先检查minutes是否有效
if (isNaN(minutes) || minutes <= 0) {
console.error('❌ Invalid minutes value:', minutes);
return;
}
// 使用多种方式获取表单,确保找到正确的表单
let form = null;
// 方式1:通过套餐选择元素获取表单
const packageSelectForm = document.getElementById('selected_package_' + submissionId);
if (packageSelectForm) {
form = packageSelectForm.closest('form');
console.log('Form found via packageSelect:', form ? 'Yes' : 'No');
}
// 方式2:如果方式1失败,通过时长输入框获取表单
if (!form) {
const durationInput = document.getElementById('customDuration_' + submissionId);
if (durationInput) {
form = durationInput.closest('form');
console.log('Form found via durationInput:', form ? 'Yes' : 'No');
}
}
// 方式3:如果还是失败,尝试通过packageInfo找到表单
if (!form) {
const packageInfo = document.getElementById('packageInfo_' + submissionId);
if (packageInfo) {
form = packageInfo.closest('form');
console.log('Form found via packageInfo:', form ? 'Yes' : 'No');
}
}
if (!form) {
console.error('❌ Form not found for submissionId:', submissionId);
return;
}
// 获取唯一的时长输入框(现在同时用于显示和提交)
const durationInput = document.getElementById('customDuration_' + submissionId);
if (durationInput) {
// 强制设置时长值
durationInput.value = minutes;
// 触发change事件,确保所有依赖此输入的功能都能更新
durationInput.dispatchEvent(new Event('change'));
console.log('✅ Duration input updated to:', minutes);
} else {
console.error('❌ Duration input not found for submissionId:', submissionId);
}
// 获取当前表单的时长按钮
const durationButtons = form.querySelectorAll('.duration-btn');
console.log('Found duration buttons:', durationButtons.length);
if (durationButtons.length === 0) {
console.warn('⚠️ No duration buttons found in form');
return;
}
// 更新按钮选中状态
let buttonFound = false;
durationButtons.forEach(btn => {
// 使用getAttribute获取data属性,确保兼容所有浏览器
const btnDuration = parseInt(btn.getAttribute('data-duration'));
console.log('Checking button:', btn.textContent, 'data-duration:', btnDuration);
if (btnDuration === minutes) {
btn.classList.add('selected');
console.log('✅ Added selected class to button with duration:', btnDuration);
buttonFound = true;
} else {
btn.classList.remove('selected');
}
});
if (!buttonFound) {
console.warn('⚠️ No matching duration button found for:', minutes, 'minutes');
}
}
// 应用自定义时长
function applyCustomDuration(submissionId) {
const customDurationInput = document.getElementById('customDuration_' + submissionId);
const customDuration = parseInt(customDurationInput.value);
const maxDuration = 720; // 最大时长为12小时(720分钟)
if (customDuration < 30) {
alert('最小服务时长为30分钟');
customDurationInput.value = 30;
selectDuration(submissionId, 30);
} else if (customDuration > maxDuration) {
alert('最大服务时长为12小时(720分钟)');
customDurationInput.value = maxDuration;
selectDuration(submissionId, maxDuration);
} else {
// 确保时长是30的倍数
const roundedDuration = Math.round(customDuration / 30) * 30;
customDurationInput.value = roundedDuration;
selectDuration(submissionId, roundedDuration);
}
}
</script>
</body>
</html>