feat(vip): 添加VIP客户管理功能

- 创建vip_customers表存储VIP客户信息
- 实现VIP客户添加、查看和删除功能
- 在预约页面增加VIP客户选择功能
- 添加VIP管理页面和API接口
This commit is contained in:
2025-11-19 01:51:04 +08:00
parent 00fc854a64
commit f605aa1c98
5 changed files with 489 additions and 8 deletions
+15
View File
@@ -2,6 +2,21 @@
CREATE DATABASE IF NOT EXISTS carwash_booking;
USE carwash_booking;
-- 创建VIP客户表
CREATE TABLE IF NOT EXISTS vip_customers (
id INT AUTO_INCREMENT PRIMARY KEY,
customer_name VARCHAR(100) NOT NULL COMMENT '客户姓名',
phone VARCHAR(20) NOT NULL UNIQUE COMMENT '联系电话(唯一)',
car_model VARCHAR(50) COMMENT '车型',
car_number VARCHAR(20) COMMENT '车牌号',
email VARCHAR(100) COMMENT '邮箱地址',
birthday DATE COMMENT '生日',
notes TEXT COMMENT '备注信息',
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NULL
);
-- 创建套餐表
CREATE TABLE IF NOT EXISTS packages (
id INT AUTO_INCREMENT PRIMARY KEY,
+48
View File
@@ -0,0 +1,48 @@
<?php
header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-cache, must-revalidate');
// 获取客户ID
$id = $_GET['id'] ?? null;
if (!$id) {
http_response_code(400);
echo json_encode(['error' => '缺少客户ID参数'], JSON_UNESCAPED_UNICODE);
exit;
}
// 数据库连接配置
$host = 'localhost';
$dbname = 'carwash_db';
$username = 'root';
$password = '';
try {
$pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8mb4", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 查询指定ID的VIP客户
$stmt = $pdo->prepare("
SELECT id, customer_name, phone, car_model, car_number, email, birthday, notes, is_active
FROM vip_customers
WHERE id = ? AND is_active = 1
");
$stmt->execute([$id]);
$vipCustomer = $stmt->fetch(PDO::FETCH_ASSOC);
if ($vipCustomer) {
echo json_encode($vipCustomer, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
} else {
http_response_code(404);
echo json_encode(['error' => 'VIP客户不存在'], JSON_UNESCAPED_UNICODE);
}
} catch(PDOException $e) {
http_response_code(500);
echo json_encode([
'error' => '数据库连接失败',
'message' => $e->getMessage()
], JSON_UNESCAPED_UNICODE);
}
?>
+34
View File
@@ -0,0 +1,34 @@
<?php
header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-cache, must-revalidate');
// 数据库连接配置
$host = 'localhost';
$dbname = 'carwash_db';
$username = 'root';
$password = '';
try {
$pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8mb4", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 查询所有VIP客户,按创建时间倒序排列
$stmt = $pdo->query("
SELECT id, customer_name, phone, car_model, car_number, email, birthday, is_active
FROM vip_customers
WHERE is_active = 1
ORDER BY created_at DESC
");
$vipCustomers = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode($vipCustomers, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
} catch(PDOException $e) {
http_response_code(500);
echo json_encode([
'error' => '数据库连接失败',
'message' => $e->getMessage()
], JSON_UNESCAPED_UNICODE);
}
?>
+126 -2
View File
@@ -8,8 +8,31 @@ $success_message = '';
// 处理表单提交
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
try {
$customer_type = $_POST['customer_type'];
$vip_id = isset($_POST['vip_id']) ? (int)$_POST['vip_id'] : 0;
// 如果选择VIP客户,从VIP表获取信息
if ($customer_type === 'vip' && $vip_id > 0) {
$stmt = $pdo->prepare("SELECT * FROM vip_customers WHERE id = ? AND is_active = 1");
$stmt->execute([$vip_id]);
$vip_customer = $stmt->fetch();
if (!$vip_customer) {
throw new Exception('选择的VIP客户无效');
}
// 使用VIP客户信息
$customer_name = $vip_customer['customer_name'];
$phone = $vip_customer['phone'];
$car_model = $vip_customer['car_model'] ?: $car_model; // 允许覆盖
$car_number = $vip_customer['car_number'] ?: $car_number; // 允许覆盖
$member_type = 'VIP会员';
} else {
// 新客户录入
$customer_name = trim($_POST['customer_name']);
$phone = trim($_POST['phone']);
}
$car_model = trim($_POST['car_model']);
$car_number = trim($_POST['car_number']);
$package_id = (int)$_POST['package_id'];
@@ -27,6 +50,17 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
throw new Exception('请填写所有必填字段');
}
// 验证VIP客户或新客户的必填字段
if ($customer_type === 'vip') {
if (empty($vip_id)) {
throw new Exception('请选择一个VIP客户');
}
} else {
if (empty($customer_name) || empty($phone)) {
throw new Exception('请填写客户姓名和联系电话');
}
}
// 验证套餐
if ($package_id) {
$stmt = $pdo->prepare("SELECT * FROM packages WHERE id = ? AND is_active = 1");
@@ -157,6 +191,7 @@ $packages_json = json_encode(array_map(function($package) {
<a href="index.php" class="nav-link active">预约洗车</a>
<a href="bookings.php" class="nav-link">预约管理</a>
<a href="packages.php" class="nav-link">套餐管理</a>
<a href="vip.php" class="nav-link">VIP管理</a>
</nav>
</header>
@@ -226,14 +261,33 @@ $packages_json = json_encode(array_map(function($package) {
<div class="booking-form-section">
<h2>📋 预约信息</h2>
<form method="POST" class="form" id="bookingForm">
<div class="form-row">
<div class="form-group">
<label for="customer_type">客户类型 *</label>
<select id="customer_type" name="customer_type" required onchange="handleCustomerTypeChange()">
<option value="new">新客户</option>
<option value="vip">VIP客户</option>
</select>
</div>
<div class="form-group" id="vip_select_group" style="display: none;">
<label for="vip_id">选择VIP客户</label>
<select id="vip_id" name="vip_id" onchange="loadVIPInfo()">
<option value="">请选择VIP客户</option>
</select>
</div>
</div>
<div class="form-row" id="new_customer_fields">
<div class="form-group">
<label for="customer_name">客户姓名 *</label>
<input type="text" id="customer_name" name="customer_name" required>
<input type="text" id="customer_name" name="customer_name" placeholder="请输入客户姓名">
</div>
<div class="form-group">
<label for="phone">联系电话 *</label>
<input type="tel" id="phone" name="phone" required>
<input type="tel" id="phone" name="phone" placeholder="请输入联系电话">
</div>
</div>
<div class="form-row">
@@ -361,6 +415,9 @@ $packages_json = json_encode(array_map(function($package) {
// 默认选择今天的日期并显示时间段
selectDate(todayStr);
// 加载VIP客户列表
loadVIPCustomers();
// 移动端优化
if (/Mobi|Android|iPhone|iPad|iPod/i.test(navigator.userAgent)) {
document.body.classList.add('mobile-device');
@@ -371,6 +428,73 @@ $packages_json = json_encode(array_map(function($package) {
}
});
// 加载VIP客户列表
function loadVIPCustomers() {
// 这里将从数据库获取VIP客户列表
// 在实际应用中,您可能需要通过AJAX获取
fetch('get_vip_customers.php')
.then(response => response.json())
.then(data => {
const vipSelect = document.getElementById('vip_id');
vipSelect.innerHTML = '<option value="">请选择VIP客户</option>';
data.forEach(vip => {
const option = document.createElement('option');
option.value = vip.id;
option.textContent = `${vip.customer_name} (${vip.phone})`;
vipSelect.appendChild(option);
});
})
.catch(error => {
console.log('加载VIP客户列表失败:', error);
// 如果加载失败,显示空列表
});
}
// 处理客户类型变更
function handleCustomerTypeChange() {
const customerType = document.getElementById('customer_type').value;
const vipSelectGroup = document.getElementById('vip_select_group');
const newCustomerFields = document.getElementById('new_customer_fields');
if (customerType === 'vip') {
vipSelectGroup.style.display = 'block';
newCustomerFields.style.display = 'none';
// 隐藏新客户字段的必填属性
document.getElementById('customer_name').required = false;
document.getElementById('phone').required = false;
} else {
vipSelectGroup.style.display = 'none';
newCustomerFields.style.display = 'flex';
// 显示新客户字段的必填属性
document.getElementById('customer_name').required = true;
document.getElementById('phone').required = true;
}
updateSubmitButton();
}
// 加载VIP客户信息
function loadVIPInfo() {
const vipId = document.getElementById('vip_id').value;
if (vipId) {
// 这里将从数据库获取VIP客户详细信息
fetch(`get_vip_customer.php?id=${vipId}`)
.then(response => response.json())
.then(vip => {
if (vip.car_model) {
document.getElementById('car_model').value = vip.car_model;
}
if (vip.car_number) {
document.getElementById('car_number').value = vip.car_number;
}
})
.catch(error => {
console.log('加载VIP信息失败:', error);
});
}
updateSubmitButton();
}
function showDateDetails(date) {
// 获取预约详情容器
const detailsDiv = document.getElementById('bookingDetails');
+260
View File
@@ -0,0 +1,260 @@
<?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 = ?");
$stmt->execute([$phone]);
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 (?, ?, ?, ?, ?, ?, ?)");
$stmt->execute([$customer_name, $phone, $car_model, $car_number, $email, $birthday, $notes]);
$success_message = "VIP客户录入成功!";
} elseif ($action === 'delete_vip') {
$id = (int)$_POST['vip_id'];
$stmt = $pdo->prepare("DELETE FROM vip_customers WHERE id = ?");
$stmt->execute([$id]);
$success_message = "VIP客户删除成功!";
}
}
} catch (Exception $e) {
$message = $e->getMessage();
}
}
// 获取所有VIP客户
try {
$stmt = $pdo->query("SELECT * FROM vip_customers ORDER BY created_at DESC");
$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>VIP管理 - 洗车预约系统</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<header class="header">
<h1>👑 VIP客户管理</h1>
<nav class="nav">
<a href="index.php" class="nav-link">预约洗车</a>
<a href="bookings.php" class="nav-link">预约管理</a>
<a href="packages.php" class="nav-link">套餐管理</a>
<a href="vip.php" class="nav-link active">VIP管理</a>
</nav>
</header>
<?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">
<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客户列表 (共 <?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>
<div class="vip-actions">
<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>
<script>
// 移动端优化脚本
document.addEventListener('DOMContentLoaded', function() {
// 为按钮添加触摸反馈
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>