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/vip.php
T
wsh5485 c64651d6c7 feat(移动端): 添加移动端导航菜单并优化响应式设计
refactor(预约统计): 修改查询逻辑只计算有效预约
2025-12-12 03:39:01 +08:00

1160 lines
53 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
session_start();
require_once 'db_connect.php';
$message = '';
$success_message = '';
// 处理表单提交
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
try {
if (isset($_POST['action'])) {
$action = $_POST['action'];
if ($action === 'add_vip') {
$customer_name = trim($_POST['customer_name']);
$phone = trim($_POST['phone']);
$car_model = trim($_POST['car_model']);
$car_number = trim($_POST['car_number']);
$email = trim($_POST['email'] ?? '');
$birthday = $_POST['birthday'] ?? '';
$notes = trim($_POST['notes'] ?? '');
if (empty($customer_name) || empty($phone)) {
throw new Exception('请填写客户姓名和联系电话');
}
// 检查VIP客户是否已存在(基于手机号和车牌号组合)
$stmt = $pdo->prepare("SELECT id FROM vip_customers WHERE phone = ? AND car_number = ?");
$stmt->execute([$phone, $car_number]);
if ($stmt->fetch()) {
throw new Exception('该手机号和车牌号组合已经是VIP客户');
}
// 插入VIP客户
$stmt = $pdo->prepare("INSERT INTO vip_customers
(customer_name, phone, car_model, car_number, email, birthday, notes)
VALUES (?, ?, ?, ?, ?, ?, ?)");
try {
$stmt->execute([$customer_name, $phone, $car_model, $car_number, $email, $birthday, $notes]);
$success_message = "VIP客户录入成功!";
} catch (PDOException $e) {
// 捕获唯一约束错误
if ($e->errorInfo[1] == 1062) { // MySQL唯一键约束错误码
throw new Exception('该手机号和车牌号组合已经是VIP客户');
}
throw $e; // 重新抛出其他类型的异常
}
} elseif ($action === 'update_vip') {
$id = (int)$_POST['vip_id'];
$customer_name = trim($_POST['customer_name']);
$phone = trim($_POST['phone']);
$car_model = trim($_POST['car_model']);
$car_number = trim($_POST['car_number']);
$email = trim($_POST['email'] ?? '');
$birthday = $_POST['birthday'] ?? '';
$notes = trim($_POST['notes'] ?? '');
if (empty($customer_name) || empty($phone)) {
throw new Exception('请填写客户姓名和联系电话');
}
// 检查手机号和车牌号组合是否与其他VIP客户冲突
$stmt = $pdo->prepare("SELECT id FROM vip_customers WHERE phone = ? AND car_number = ? AND id != ?");
$stmt->execute([$phone, $car_number, $id]);
if ($stmt->fetch()) {
throw new Exception('该手机号和车牌号组合已经被其他VIP客户使用');
}
// 更新VIP客户信息
$stmt = $pdo->prepare("UPDATE vip_customers SET
customer_name = ?,
phone = ?,
car_model = ?,
car_number = ?,
email = ?,
birthday = ?,
notes = ?,
updated_at = NOW()
WHERE id = ?");
try {
$stmt->execute([$customer_name, $phone, $car_model, $car_number, $email, $birthday, $notes, $id]);
$success_message = "VIP客户信息更新成功!";
} catch (PDOException $e) {
// 捕获唯一约束错误
if ($e->errorInfo[1] == 1062) { // MySQL唯一键约束错误码
throw new Exception('该手机号和车牌号组合已经被其他VIP客户使用');
}
throw $e; // 重新抛出其他类型的异常
}
} elseif ($action === 'delete_vip') {
$id = (int)$_POST['vip_id'];
$stmt = $pdo->prepare("DELETE FROM vip_customers WHERE id = ?");
$stmt->execute([$id]);
$success_message = "VIP客户删除成功!";
} elseif ($action === 'convert_from_booking') {
// 从预约记录转换为VIP客户
$booking_id = isset($_POST['booking_id']) ? (int)$_POST['booking_id'] : 0;
if ($booking_id <= 0) {
throw new Exception('无效的预约ID');
}
// 获取预约信息
$stmt = $pdo->prepare("SELECT customer_name, phone, car_model, car_number FROM bookings WHERE id = ?");
$stmt->execute([$booking_id]);
$booking = $stmt->fetch();
if (!$booking) {
throw new Exception('预约记录不存在');
}
// 检查是否已经是VIP客户
$stmt = $pdo->prepare("SELECT id FROM vip_customers WHERE phone = ? AND car_number = ?");
$stmt->execute([$booking['phone'], $booking['car_number']]);
if ($stmt->fetch()) {
throw new Exception('该客户已经是VIP客户');
}
// 插入VIP客户
$stmt = $pdo->prepare("INSERT INTO vip_customers
(customer_name, phone, car_model, car_number, notes)
VALUES (?, ?, ?, ?, ?)");
try {
$notes = '从预约记录 #' . $booking_id . ' 自动转换';
$stmt->execute([
$booking['customer_name'],
$booking['phone'],
$booking['car_model'] ?? '',
$booking['car_number'] ?? '',
$notes
]);
// 更新该客户的所有预约记录的member_type为VIP会员
$stmt = $pdo->prepare("UPDATE bookings SET member_type = 'VIP会员' WHERE phone = ? AND car_number = ?");
$stmt->execute([$booking['phone'], $booking['car_number']]);
$success_message = "客户已成功转换为VIP客户!";
} catch (PDOException $e) {
if ($e->errorInfo[1] == 1062) {
throw new Exception('该客户已经是VIP客户');
}
throw $e;
}
}
}
} catch (Exception $e) {
$message = $e->getMessage();
}
}
// 获取搜索参数
$search_phone = isset($_GET['search_phone']) ? trim($_GET['search_phone']) : '';
$search_car_number = isset($_GET['search_car_number']) ? trim($_GET['search_car_number']) : '';
// 获取所有VIP客户(支持搜索)
try {
// 构建查询语句
$query = "SELECT * FROM vip_customers WHERE 1=1";
$params = [];
if (!empty($search_phone)) {
$query .= " AND phone LIKE :phone";
$params[':phone'] = '%' . $search_phone . '%';
}
if (!empty($search_car_number)) {
$query .= " AND car_number LIKE :car_number";
$params[':car_number'] = '%' . $search_car_number . '%';
}
$query .= " ORDER BY created_at DESC";
$stmt = $pdo->prepare($query);
$stmt->execute($params);
$vip_customers = $stmt->fetchAll();
} catch (Exception $e) {
$error_message = '获取VIP客户列表失败:' . $e->getMessage();
$vip_customers = [];
}
?>
<!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="VIP客户管理,录入和管理VIP客户信息">
<meta name="keywords" content="VIP管理,客户管理,会员管理">
<title>张老师撸车(私家车库)工作室</title>
<link rel="stylesheet" href="style.css">
<script src="mobile-nav.js" defer></script>
</head>
<body>
<div class="container">
<header class="header">
<button class="mobile-menu-toggle" onclick="toggleMobileMenu()" aria-label="菜单">
<span></span>
<span></span>
<span></span>
</button>
<h1>🚗 张老师撸车工作室 - VIP管理</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">待处理预约</a>
<a href="packages.php" class="nav-link">套餐管理</a>
<a href="vip.php" class="nav-link active">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">待处理预约</a>
<a href="packages.php" class="nav-link">套餐管理</a>
<a href="vip.php" class="nav-link active">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; ?>
<?php if ($message): ?>
<div class="message error-message" style="background-color: #fee; color: #c33; border-color: #fcc;">
<?= htmlspecialchars($message) ?>
</div>
<?php endif; ?>
<div class="vip-management">
<!-- VIP搜索表单 -->
<div class="card search-container">
<h2>🔍 VIP客户搜索</h2>
<form method="GET" class="form search-form">
<div class="form-row">
<div class="form-group">
<label for="search_phone">手机号</label>
<input type="tel" id="search_phone" name="search_phone" placeholder="请输入手机号" value="<?php echo htmlspecialchars($search_phone); ?>">
</div>
<div class="form-group">
<label for="search_car_number">车牌号</label>
<input type="text" id="search_car_number" name="search_car_number" placeholder="请输入车牌号" value="<?php echo htmlspecialchars($search_car_number); ?>">
</div>
<div class="form-group" style="align-self: flex-end;">
<button type="submit" class="btn btn-primary">搜索</button>
<button type="button" class="btn" onclick="clearSearch()">清空</button>
</div>
</div>
</form>
</div>
<!-- VIP录入表单 -->
<div class="card">
<h2> 录入新VIP客户</h2>
<form method="POST" class="form">
<input type="hidden" name="action" value="add_vip">
<div class="form-row">
<div class="form-group">
<label for="customer_name">客户姓名 *</label>
<input type="text" id="customer_name" name="customer_name" required>
</div>
<div class="form-group">
<label for="phone">联系电话 *</label>
<input type="tel" id="phone" name="phone" required>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="car_model">车型</label>
<input type="text" id="car_model" name="car_model" placeholder="如:宝马X5">
</div>
<div class="form-group">
<label for="car_number">车牌号</label>
<input type="text" id="car_number" name="car_number" placeholder="如:京A88888">
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="email">邮箱</label>
<input type="email" id="email" name="email" placeholder="可选">
</div>
<div class="form-group">
<label for="birthday">生日</label>
<input type="date" id="birthday" name="birthday">
</div>
</div>
<div class="form-group">
<label for="notes">备注</label>
<textarea id="notes" name="notes" rows="3" placeholder="VIP客户特殊需求或备注信息..."></textarea>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">录入VIP客户</button>
<button type="reset" class="btn">重置</button>
</div>
</form>
</div>
<!-- 从预约转换为VIP -->
<div class="card">
<h2>📋 从预约记录转换为VIP客户</h2>
<p style="color: #666; margin-bottom: 15px;">选择预约记录,快速将普通客户转换为VIP客户</p>
<?php
// 获取可以转换为VIP的普通客户预约记录(最近30天,且不是VIP客户)
try {
$stmt = $pdo->prepare("SELECT DISTINCT b.id, b.customer_name, b.phone, b.car_model, b.car_number,
COUNT(*) as booking_count,
MAX(b.start_time) as last_booking_time
FROM bookings b
LEFT JOIN vip_customers v ON b.phone = v.phone AND b.car_number = v.car_number AND v.is_active = 1
WHERE b.member_type = '普通客户'
AND v.id IS NULL
AND b.start_time >= DATE_SUB(NOW(), INTERVAL 30 DAY)
GROUP BY b.phone, b.car_number, b.customer_name, b.car_model
ORDER BY last_booking_time DESC
LIMIT 20");
$stmt->execute();
$convertible_bookings = $stmt->fetchAll();
} catch (Exception $e) {
$convertible_bookings = [];
}
?>
<?php if (empty($convertible_bookings)): ?>
<div class="empty-message">暂无可转换的普通客户</div>
<?php else: ?>
<div style="max-height: 400px; overflow-y: auto;">
<?php foreach ($convertible_bookings as $booking): ?>
<div style="padding: 12px; border: 1px solid #e0e0e0; border-radius: 6px; margin-bottom: 10px; background: #f9f9f9;">
<div style="display: flex; justify-content: space-between; align-items: center;">
<div style="flex: 1;">
<strong><?php echo htmlspecialchars($booking['customer_name']); ?></strong><br>
<span style="color: #666; font-size: 0.9em;">
手机号:<?php echo htmlspecialchars($booking['phone']); ?> |
车牌号:<?php echo htmlspecialchars($booking['car_number']); ?><br>
<?php if ($booking['car_model']): ?>
车型:<?php echo htmlspecialchars($booking['car_model']); ?> |
<?php endif; ?>
预约次数:<?php echo $booking['booking_count']; ?>次
</span>
</div>
<form method="POST" style="margin-left: 15px;">
<input type="hidden" name="action" value="convert_from_booking">
<input type="hidden" name="booking_id" value="<?php echo $booking['id']; ?>">
<button type="submit" class="btn btn-sm" style="background-color: #ffd700; color: #333; font-weight: bold;"
onclick="return confirm('确定要将 <?php echo htmlspecialchars($booking['customer_name']); ?> 转换为VIP客户吗?')">
👑 转为VIP
</button>
</form>
</div>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
<!-- VIP客户列表 -->
<div class="card">
<h2>👑 VIP客户列表 (共 <?php echo count($vip_customers); ?> 位)</h2>
<?php if (empty($vip_customers)): ?>
<div class="empty-message">暂无VIP客户</div>
<?php else: ?>
<div class="vip-grid">
<?php foreach ($vip_customers as $vip): ?>
<div class="vip-card">
<div class="vip-header">
<h3><?php echo htmlspecialchars($vip['customer_name']); ?></h3>
<div class="vip-status">👑 VIP</div>
</div>
<div class="vip-details">
<div class="detail-item">
<span class="detail-label">联系电话:</span>
<span class="detail-value"><?php echo htmlspecialchars($vip['phone']); ?></span>
</div>
<?php if ($vip['car_model']): ?>
<div class="detail-item">
<span class="detail-label">车型:</span>
<span class="detail-value"><?php echo htmlspecialchars($vip['car_model']); ?></span>
</div>
<?php endif; ?>
<?php if ($vip['car_number']): ?>
<div class="detail-item">
<span class="detail-label">车牌号:</span>
<span class="detail-value"><?php echo htmlspecialchars($vip['car_number']); ?></span>
</div>
<?php endif; ?>
<?php if ($vip['email']): ?>
<div class="detail-item">
<span class="detail-label">邮箱:</span>
<span class="detail-value"><?php echo htmlspecialchars($vip['email']); ?></span>
</div>
<?php endif; ?>
<?php if ($vip['birthday']): ?>
<div class="detail-item">
<span class="detail-label">生日:</span>
<span class="detail-value"><?php echo date('Y-m-d', strtotime($vip['birthday'])); ?></span>
</div>
<?php endif; ?>
</div>
<?php if ($vip['notes']): ?>
<div class="vip-notes">
<span class="detail-label">备注:</span>
<span><?php echo htmlspecialchars($vip['notes']); ?></span>
</div>
<?php endif; ?>
<div class="vip-meta">
<span>录入时间:<?php echo $vip['created_at']; ?></span>
</div>
<script>
// 函数定义占位符,确保按钮点击时函数已定义
function editVip() {};
function viewBookings() {};
function addBookingForVip() {};
</script>
<div class="vip-actions">
<button type="button"
class="btn btn-sm btn-primary"
onclick="editVip(<?php echo $vip['id']; ?>, '<?php echo htmlspecialchars($vip['customer_name']); ?>',
'<?php echo htmlspecialchars($vip['phone']); ?>', '<?php echo htmlspecialchars($vip['car_model']); ?>',
'<?php echo htmlspecialchars($vip['car_number']); ?>', '<?php echo htmlspecialchars($vip['email']); ?>',
'<?php echo $vip['birthday'] ? date('Y-m-d', strtotime($vip['birthday'])) : ''; ?>',
'<?php echo htmlspecialchars($vip['notes']); ?>')">编辑</button>
<button type="button"
class="btn btn-sm btn-info"
onclick="viewBookings('<?php echo htmlspecialchars($vip['phone']); ?>', '<?php echo htmlspecialchars($vip['customer_name']); ?>')">查看预约</button>
<button type="button"
class="btn btn-sm btn-success"
onclick="addBookingForVip('<?php echo htmlspecialchars($vip['customer_name']); ?>',
'<?php echo htmlspecialchars($vip['phone']); ?>',
'<?php echo htmlspecialchars($vip['car_model']); ?>',
'<?php echo htmlspecialchars($vip['car_number']); ?>')">添加预约</button>
<form method="POST" style="display: inline;">
<input type="hidden" name="vip_id" value="<?php echo $vip['id']; ?>">
<button type="submit" name="action" value="delete_vip"
class="btn btn-sm btn-danger"
onclick="return confirm('确定要删除这个VIP客户吗?')">删除</button>
</form>
</div>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
</div>
<div style="text-align: center; margin-top: 2rem;">
<a href="index.php" class="btn">返回预约页面</a>
</div>
</div>
<!-- 添加预约模态框 -->
<div id="addBookingModal" class="modal" style="display: none;">
<div class="modal-content">
<div class="modal-header">
<h2>📝 为客户添加预约</h2>
<span class="close-modal" onclick="closeAddBookingModal()">&times;</span>
</div>
<div class="modal-body">
<form id="addBookingForm" method="POST" action="process_booking.php">
<!-- 预填充的VIP客户信息 -->
<input type="hidden" name="source" value="vip_page">
<div class="form-row">
<div class="form-group">
<label for="booking_customer_name">客户姓名</label>
<input type="text" class="form-control" id="booking_customer_name" name="customer_name" required readonly>
</div>
<div class="form-group">
<label for="booking_phone">手机号码</label>
<input type="tel" class="form-control" id="booking_phone" name="phone" required readonly>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="booking_car_model">车型</label>
<input type="text" class="form-control" id="booking_car_model" name="car_model">
</div>
<div class="form-group">
<label for="booking_car_number">车牌号</label>
<input type="text" class="form-control" id="booking_car_number" name="car_number" required>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="booking_date">预约日期</label>
<input type="date" class="form-control" id="booking_date" name="booking_date" required min="<?php echo date('Y-m-d'); ?>">
</div>
<div class="form-group">
<label for="booking_time_slot">预约时间</label>
<select class="form-control" id="booking_time_slot" name="time_slot" required>
<option value="">请选择时间</option>
<option value="09:00-10:00">09:00-10:00</option>
<option value="10:00-11:00">10:00-11:00</option>
<option value="11:00-12:00">11:00-12:00</option>
<option value="14:00-15:00">14:00-15:00</option>
<option value="15:00-16:00">15:00-16:00</option>
<option value="16:00-17:00">16:00-17:00</option>
<option value="17:00-18:00">17:00-18:00</option>
</select>
</div>
</div>
<div class="form-group">
<label for="booking_package_id">洗车套餐</label>
<select class="form-control" id="booking_package_id" name="package_id" required>
<option value="">请选择套餐</option>
<?php
// 查询所有可用的洗车套餐
// #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>";
}
?>
</select>
</div>
<div class="form-group">
<label for="booking_notes">备注</label>
<textarea class="form-control" id="booking_notes" name="notes" rows="3"></textarea>
</div>
<div class="form-actions">
<button type="button" class="btn btn-secondary" onclick="closeAddBookingModal()">取消</button>
<button type="submit" class="btn btn-primary">确认添加预约</button>
</div>
</form>
</div>
</div>
</div>
<!-- VIP客户预约记录模态框 -->
<div id="bookingsModal" class="modal" style="display: none;">
<div class="modal-content">
<div class="modal-header">
<h2>📋 <span id="customerName">客户</span> 的预约记录</h2>
<span class="close-modal" onclick="closeBookingsModal()">&times;</span>
</div>
<div class="modal-body">
<div id="bookingsLoading" style="text-align: center; padding: 20px;">
加载预约记录中...
</div>
<div id="bookingsContent" style="display: none;">
<div class="bookings-stats">
<div class="stat-item">
<span class="stat-label">总预约次数:</span>
<span id="totalBookings" class="stat-value">0</span>
</div>
<div class="stat-item">
<span class="stat-label">待服务:</span>
<span id="pendingBookings" class="stat-value pending">0</span>
</div>
<div class="stat-item">
<span class="stat-label">已完成:</span>
<span id="completedBookings" class="stat-value completed">0</span>
</div>
</div>
<div class="bookings-list" id="bookingsList">
<!-- 预约记录将通过JavaScript动态生成 -->
</div>
</div>
<div id="noBookings" style="display: none; text-align: center; padding: 40px; color: #666;">
暂无预约记录
</div>
</div>
</div>
</div>
<!-- VIP编辑模态框 -->
<div id="editVipModal" class="modal" style="display: none;">
<div class="modal-content">
<div class="modal-header">
<h2>编辑VIP客户信息</h2>
<span class="close-modal" onclick="closeModal()">&times;</span>
</div>
<div class="modal-body">
<form id="editVipForm" method="POST">
<input type="hidden" name="action" value="update_vip">
<input type="hidden" id="edit_vip_id" name="vip_id">
<div class="form-row">
<div class="form-group">
<label for="edit_customer_name">客户姓名 *</label>
<input type="text" id="edit_customer_name" name="customer_name" required>
</div>
<div class="form-group">
<label for="edit_phone">联系电话 *</label>
<input type="tel" id="edit_phone" name="phone" required>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="edit_car_model">车型</label>
<input type="text" id="edit_car_model" name="car_model" placeholder="如:宝马X5">
</div>
<div class="form-group">
<label for="edit_car_number">车牌号</label>
<input type="text" id="edit_car_number" name="car_number" placeholder="如:京A88888">
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="edit_email">邮箱</label>
<input type="email" id="edit_email" name="email" placeholder="可选">
</div>
<div class="form-group">
<label for="edit_birthday">生日</label>
<input type="date" id="edit_birthday" name="birthday">
</div>
</div>
<div class="form-group">
<label for="edit_notes">备注</label>
<textarea id="edit_notes" name="notes" rows="3" placeholder="VIP客户特殊需求或备注信息..."></textarea>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">保存修改</button>
<button type="button" class="btn" onclick="closeModal()">取消</button>
</div>
</form>
</div>
</div>
</div>
<!-- 模态框样式 -->
<style>
.modal {
display: none;
position: fixed;
z-index: 1000;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0,0,0,0.5);
padding-top: 60px;
}
.modal-content {
background-color: #fefefe;
margin: 5% auto;
padding: 20px;
border: 1px solid #888;
width: 90%;
max-width: 600px;
border-radius: 8px;
box-shadow: 0 4px 20px rgba(0,0,0,0.15);
}
.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 1px solid #eee;
}
.modal-header h2 {
margin: 0;
color: var(--el-text-primary);
}
.close-modal {
color: #aaa;
font-size: 28px;
font-weight: bold;
cursor: pointer;
transition: color 0.3s;
}
.close-modal:hover, .close-modal:focus {
color: #333;
text-decoration: none;
cursor: pointer;
}
.modal-body {
padding: 10px 0;
}
/* 搜索样式 */
.search-container {
background-color: #f8f9fa;
}
.search-form .form-row {
display: flex;
gap: 15px;
align-items: stretch;
}
.search-form .form-group {
flex: 1;
}
@media (max-width: 768px) {
.search-form .form-row {
flex-direction: column;
}
.search-form .form-group:last-child {
align-self: flex-start;
width: 100%;
display: flex;
gap: 10px;
margin-top: 10px;
}
.search-form .form-group:last-child button {
flex: 1;
}
}
/* 预约记录样式 */
.bookings-stats {
display: flex;
flex-wrap: wrap;
gap: 20px;
margin-bottom: 20px;
padding: 15px;
background-color: #f8f9fa;
border-radius: 8px;
}
.stat-item {
flex: 1;
min-width: 120px;
text-align: center;
}
.stat-label {
display: block;
font-size: 14px;
color: #666;
margin-bottom: 5px;
}
.stat-value {
display: block;
font-size: 24px;
font-weight: bold;
}
.stat-value.pending {
color: #ff9800;
}
.stat-value.completed {
color: #4caf50;
}
.bookings-list {
max-height: 400px;
overflow-y: auto;
}
.booking-item {
padding: 15px;
margin-bottom: 10px;
border: 1px solid #e0e0e0;
border-radius: 8px;
background-color: #fff;
}
.booking-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.booking-date {
font-weight: bold;
color: var(--el-text-primary);
}
.booking-status {
padding: 3px 10px;
border-radius: 12px;
font-size: 12px;
font-weight: bold;
}
.booking-status.pending {
background-color: #fff3cd;
color: #856404;
}
.booking-status.completed {
background-color: #d4edda;
color: #155724;
}
.booking-status.canceled {
background-color: #f8d7da;
color: #721c24;
}
.booking-details {
font-size: 14px;
color: #666;
}
.booking-detail-item {
margin-bottom: 5px;
}
/* 添加预约表单样式 */
#addBookingForm .form-row {
display: flex;
gap: 15px;
margin-bottom: 15px;
}
#addBookingForm .form-group {
flex: 1;
}
#addBookingForm label {
display: block;
margin-bottom: 5px;
font-weight: 500;
color: var(--el-text-primary);
}
#addBookingForm input, #addBookingForm select, #addBookingForm textarea {
width: 100%;
padding: 8px 12px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
}
#addBookingForm input:read-only {
background-color: #f8f9fa;
cursor: not-allowed;
}
.form-actions {
display: flex;
gap: 10px;
justify-content: flex-end;
margin-top: 20px;
}
@media (max-width: 768px) {
.bookings-stats {
flex-direction: column;
gap: 10px;
}
.stat-item {
min-width: auto;
}
.booking-header {
flex-direction: column;
align-items: flex-start;
gap: 5px;
}
#addBookingForm .form-row {
flex-direction: column;
}
}
</style>
<script>
// DOM加载完成后重新定义函数
document.addEventListener('DOMContentLoaded', function() {
// VIP编辑功能
window.editVip = function(id, name, phone, carModel, carNumber, email, birthday, notes) {
document.getElementById('edit_vip_id').value = id;
document.getElementById('edit_customer_name').value = name;
document.getElementById('edit_phone').value = phone;
document.getElementById('edit_car_model').value = carModel;
document.getElementById('edit_car_number').value = carNumber;
document.getElementById('edit_email').value = email || '';
document.getElementById('edit_birthday').value = birthday || '';
document.getElementById('edit_notes').value = notes || '';
// 显示模态框
document.getElementById('editVipModal').style.display = 'block';
};
window.closeModal = function() {
document.getElementById('editVipModal').style.display = 'none';
};
// 清空搜索
window.clearSearch = function() {
document.getElementById('search_phone').value = '';
document.getElementById('search_car_number').value = '';
// 提交空搜索表单以显示所有结果
document.querySelector('.search-form').submit();
};
// 查看VIP客户预约记录
window.viewBookings = function(phone, customerName) {
document.getElementById('customerName').textContent = customerName;
// 显示加载状态
document.getElementById('bookingsLoading').style.display = 'block';
document.getElementById('bookingsContent').style.display = 'none';
document.getElementById('noBookings').style.display = 'none';
// 显示模态框
document.getElementById('bookingsModal').style.display = 'block';
// 使用AJAX获取预约记录
const xhr = new XMLHttpRequest();
xhr.open('GET', 'get_bookings.php?phone=' + encodeURIComponent(phone), true);
xhr.onload = function() {
if (xhr.status === 200) {
try {
const data = JSON.parse(xhr.responseText);
// 更新统计信息
document.getElementById('totalBookings').textContent = data.total || 0;
document.getElementById('pendingBookings').textContent = data.pending || 0;
document.getElementById('completedBookings').textContent = data.completed || 0;
// 更新预约列表
const bookingsList = document.getElementById('bookingsList');
bookingsList.innerHTML = '';
if (data.bookings && data.bookings.length > 0) {
// 显示预约列表
document.getElementById('bookingsContent').style.display = 'block';
// 为每个预约创建HTML元素
data.bookings.forEach(function(booking) {
const bookingItem = document.createElement('div');
bookingItem.className = 'booking-item';
// 状态样式类
let statusClass = '';
switch(booking.status) {
case '待服务':
statusClass = 'pending';
break;
case '已完成':
statusClass = 'completed';
break;
default:
statusClass = 'canceled';
}
bookingItem.innerHTML = '<div class="booking-header">' +
'<div class="booking-date">预约日期:' + (booking.booking_date || '') + '</div>' +
'<span class="booking-status ' + statusClass + '">' + booking.status + '</span>' +
'</div>' +
'<div class="booking-details">' +
'<div class="booking-detail-item">车牌号:' + (booking.car_number || '未提供') + '</div>' +
'<div class="booking-detail-item">车型:' + (booking.car_model || '未提供') + '</div>' +
'<div class="booking-detail-item">洗车套餐:' + (booking.package_name || '未选择') + '</div>' +
'<div class="booking-detail-item">预约时间:' + (booking.time_slot || '未选择') + '</div>' +
(booking.notes ? '<div class="booking-detail-item">备注:' + booking.notes + '</div>' : '') +
'</div>';
bookingsList.appendChild(bookingItem);
});
} else {
// 显示无预约记录提示
document.getElementById('noBookings').style.display = 'block';
}
} catch (e) {
console.error('解析预约数据失败:', e);
document.getElementById('noBookings').style.display = 'block';
} finally {
// 隐藏加载状态
document.getElementById('bookingsLoading').style.display = 'none';
}
} else {
console.error('获取预约记录失败:', xhr.status);
document.getElementById('noBookings').style.display = 'block';
// 隐藏加载状态
document.getElementById('bookingsLoading').style.display = 'none';
}
};
xhr.onerror = function() {
console.error('网络错误');
document.getElementById('bookingsLoading').style.display = 'none';
document.getElementById('noBookings').style.display = 'block';
};
xhr.send();
};
window.closeBookingsModal = function() {
document.getElementById('bookingsModal').style.display = 'none';
};
// 为VIP客户添加预约
window.addBookingForVip = function(customerName, phone, carModel, carNumber) {
// 预填充表单数据
document.getElementById('booking_customer_name').value = customerName;
document.getElementById('booking_phone').value = phone;
document.getElementById('booking_car_model').value = carModel || '';
document.getElementById('booking_car_number').value = carNumber || '';
// 设置默认预约日期为今天
const today = new Date();
const year = today.getFullYear();
const month = String(today.getMonth() + 1).padStart(2, '0');
const day = String(today.getDate()).padStart(2, '0');
document.getElementById('booking_date').value = `${year}-${month}-${day}`;
// 清空其他字段
document.getElementById('booking_time_slot').value = '';
document.getElementById('booking_package_id').value = '';
document.getElementById('booking_notes').value = '';
// 显示模态框
document.getElementById('addBookingModal').style.display = 'block';
};
window.closeAddBookingModal = function() {
document.getElementById('addBookingModal').style.display = 'none';
};
// 点击模态框外部关闭
window.onclick = function(event) {
const editModal = document.getElementById('editVipModal');
const bookingsModal = document.getElementById('bookingsModal');
const addBookingModal = document.getElementById('addBookingModal');
if (event.target === editModal) {
closeModal();
} else if (event.target === bookingsModal) {
closeBookingsModal();
} else if (event.target === addBookingModal) {
closeAddBookingModal();
}
};
// 添加预约表单提交事件
if (document.getElementById('addBookingForm')) {
document.getElementById('addBookingForm').addEventListener('submit', function(e) {
// 可以在这里添加额外的表单验证逻辑
// 例如验证日期时间是否合理,套餐是否已选择等
// 验证车牌号
const carNumber = document.getElementById('booking_car_number').value.trim();
if (!carNumber) {
alert('请输入车牌号');
e.preventDefault();
return false;
}
// 验证预约日期和时间
const bookingDate = new Date(document.getElementById('booking_date').value);
const timeSlot = document.getElementById('booking_time_slot').value;
const today = new Date();
today.setHours(0, 0, 0, 0);
if (bookingDate < today) {
alert('不能选择过去的日期');
e.preventDefault();
return false;
}
if (!timeSlot) {
alert('请选择预约时间');
e.preventDefault();
return false;
}
// 验证套餐选择
const packageId = document.getElementById('booking_package_id').value;
if (!packageId) {
alert('请选择洗车套餐');
e.preventDefault();
return false;
}
// 提交表单前可以添加确认提示
if (!confirm('确认要添加这个预约吗?')) {
e.preventDefault();
return false;
}
return true;
});
}
// 移动端优化脚本
// 为按钮添加触摸反馈
const buttons = document.querySelectorAll('.btn');
buttons.forEach(btn => {
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);
if (isMobile) {
document.body.classList.add('mobile-device');
}
});
</script>
</body>
</html>