feat(预约系统): 添加VIP客户搜索功能并优化用户体验

添加VIP客户搜索功能,支持姓名和手机号模糊搜索
增加手机号自动检测VIP功能并提供切换按钮
优化VIP客户选择界面样式和交互流程
This commit is contained in:
2025-11-19 01:57:46 +08:00
parent 471aed949c
commit 047438968b
+279 -28
View File
@@ -182,6 +182,112 @@ $packages_json = json_encode(array_map(function($package) {
<link rel="apple-touch-icon" href="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTkyIiBoZWlnaHQ9IjE5MiIgdmlld0JveD0iMCAwIDE5MiAxOTIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxOTIiIGhlaWdodD0iMTkyIiByeD0iMjQiIGZpbGw9IiMzMDk1RjQiLz4KPHN2ZyB4PSI0OCIgeT0iNDgiIHdpZHRoPSI5NiIgaGVpZ2h0PSI5NiIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJ3aGl0ZSI+CjxwYXRoIGQ9Ik0yMS4yIDQuNEMyMS42IDMuNiAyMi4xIDMuMSAyMi41IDIuN0MyMy40IDIuMSAyNC41IDIuMSAyNS4yIDIuN0MyNS44IDMuMSAyNi4zIDMuNiAyNi43IDQuNEMyNy4xIDUuMSAyNy4xIDYuMiAyNi43IDcuMUMyNi4zIDcuOCAyNS44IDguMyAyNS4yIDguN0MyNC43IDkuMSAyMy42IDkuMSAyMi45IDguN0MyMi4zIDguMyAyMS44IDcuOCAyMS40IDcuMUMyMS4wIDYuMiAyMS4wIDUuMSAyMS4yIDQuNFoiLz4KPHN2ZyB4PSIyMCIgeT0iMTIiIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJ3aGl0ZSI+CjxwYXRoIGQ9Ik0yMSAyMy41QzIwLjUgMjMuNSAyMCAyMyAyMCAyMi41VjEyQzIwIDExLjUgMjAuNSAxMSAyMSAxMUg5QzguNSAxMSAxMi41IDEwLjUgMTIgMTBIMjBWMTBCMjAgMTAuNSAyMC41IDExIDIxIDExVjIzLjVaIi8+CjxwYXRoIGQ9Ik0xOCAyMFYxN0gxNFY4SDVWMTNIMTlWMTVIMTlWMjBaIi8+CjxwYXRoIGQ9Ik04IDEwSDVWN0g4VjEwWiIvPgo8L3N2Zz4KPC9zdmc+">
<title>洗车预约系统</title>
<link rel="stylesheet" href="style.css">
<style>
/* VIP搜索结果样式 */
.vip-search-results {
position: absolute;
top: 100%;
left: 0;
right: 0;
background: white;
border: 1px solid #ddd;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
z-index: 1000;
max-height: 200px;
overflow-y: auto;
}
.vip-search-item {
padding: 12px 16px;
cursor: pointer;
border-bottom: 1px solid #f0f0f0;
transition: background-color 0.2s ease;
}
.vip-search-item:hover {
background-color: #f8f9fa;
}
.vip-search-item:last-child {
border-bottom: none;
}
.vip-search-item .customer-name {
font-weight: bold;
color: #333;
margin-bottom: 4px;
}
.vip-search-item .customer-phone {
color: #666;
font-size: 0.9em;
}
.vip-search-item .customer-car {
color: #888;
font-size: 0.85em;
margin-top: 4px;
}
.vip-search-item.selected {
background-color: #e3f2fd;
}
#vip_search {
position: relative;
}
.form-group {
position: relative;
}
.form-group #vip_search {
margin-bottom: 10px;
}
.search-tips {
font-size: 0.85em;
color: #666;
margin-top: 5px;
}
.no-results {
text-align: center;
color: #999;
padding: 20px;
font-style: italic;
}
.vip-search-results mark {
background-color: #ffeb3b;
color: #333;
padding: 1px 2px;
border-radius: 2px;
font-weight: bold;
}
.phone-vip-tip {
font-size: 0.85em;
margin-top: 5px;
padding: 8px 12px;
border-radius: 6px;
border: 1px solid #ddd;
}
.phone-vip-tip.vip-detected {
background-color: #e8f5e8;
border-color: #4caf50;
color: #2e7d32;
}
.phone-vip-tip.suggestion {
background-color: #fff3e0;
border-color: #ff9800;
color: #ef6c00;
}
</style>
</head>
<body>
<div class="container">
@@ -271,10 +377,17 @@ $packages_json = json_encode(array_map(function($package) {
</div>
<div class="form-group" id="vip_select_group" style="display: none;">
<label for="vip_id">选择VIP客户</label>
<label for="vip_search">搜索VIP客户</label>
<input type="text" id="vip_search" placeholder="输入姓名或手机号搜索"
oninput="searchVIPCustomers()" autocomplete="off"
onfocus="clearSearchResults()">
<div class="search-tips">💡 支持模糊搜索,输入姓名或手机号即可快速定位</div>
<label for="vip_id" style="margin-top: 10px;">选择VIP客户</label>
<select id="vip_id" name="vip_id" onchange="loadVIPInfo()">
<option value="">请选择VIP客户</option>
</select>
<div id="vip_search_results" class="vip-search-results" style="display: none;"></div>
</div>
</div>
@@ -286,7 +399,9 @@ $packages_json = json_encode(array_map(function($package) {
<div class="form-group">
<label for="phone">联系电话 *</label>
<input type="tel" id="phone" name="phone" placeholder="请输入联系电话">
<input type="tel" id="phone" name="phone" placeholder="请输入联系电话"
oninput="checkPhoneForVIP()">
<div id="phone_vip_tip" class="phone-vip-tip" style="display: none;"></div>
</div>
</div>
@@ -404,50 +519,186 @@ $packages_json = json_encode(array_map(function($package) {
slotDuration: 30 // 30分钟一个时段
};
// 初始化
// 页面加载完成时初始化
document.addEventListener('DOMContentLoaded', function() {
const today = new Date();
today.setDate(today.getDate());
const todayStr = today.toISOString().split('T')[0];
document.getElementById('appointment_date').value = todayStr;
selectedDate = todayStr;
// 初始化时间选择
generateTimeSlots();
// 默认选择今天的日期并显示时间
selectDate(todayStr);
// 处理当前时间
const now = new Date();
const todayStr = now.getFullYear() + '-' +
String(now.getMonth() + 1).padStart(2, '0') + '-' +
String(now.getDate()).padStart(2, '0');
document.getElementById('service_date').value = todayStr;
// 加载VIP客户列表
// 检查数据库连接
checkDatabaseConnection();
// 加载VIP客户(必须在页面加载时完成)
loadVIPCustomers();
// 移动端优化
if (/Mobi|Android|iPhone|iPad|iPod/i.test(navigator.userAgent)) {
document.body.classList.add('mobile-device');
// 自动聚焦到姓名输入框
setTimeout(() => {
document.getElementById('customer_name').focus();
}, 500);
}
});
let allVIPCustomers = []; // 全局变量存储所有VIP客户数据
// 加载VIP客户列表
function loadVIPCustomers() {
// 这里将从数据库获取VIP客户列表
// 在实际应用中,您可能需要通过AJAX获取
fetch('get_vip_customers.php')
.then(response => response.json())
.then(data => {
allVIPCustomers = data; // 存储所有VIP客户数据
updateVIPSelect(data); // 更新下拉列表
})
.catch(error => {
console.log('加载VIP客户列表失败:', error);
allVIPCustomers = [];
});
}
// 更新VIP客户下拉列表
function updateVIPSelect(customers) {
const vipSelect = document.getElementById('vip_id');
vipSelect.innerHTML = '<option value="">请选择VIP客户</option>';
data.forEach(vip => {
customers.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);
// 如果加载失败,显示空列表
});
}
// VIP客户搜索功能
function searchVIPCustomers() {
const searchTerm = document.getElementById('vip_search').value.trim();
const searchResultsDiv = document.getElementById('vip_search_results');
if (searchTerm === '') {
clearSearchResults();
updateVIPSelect(allVIPCustomers);
return;
}
// 模糊搜索:支持姓名和手机号搜索
const filteredCustomers = allVIPCustomers.filter(vip =>
vip.customer_name.includes(searchTerm) ||
vip.phone.includes(searchTerm)
);
// 显示搜索结果
displaySearchResults(filteredCustomers, searchTerm);
// 隐藏下拉列表
document.getElementById('vip_id').style.display = 'none';
}
// 显示搜索结果
function displaySearchResults(customers, searchTerm) {
const searchResultsDiv = document.getElementById('vip_search_results');
if (customers.length === 0) {
searchResultsDiv.innerHTML = '<div class="no-results">没有找到匹配的客户</div>';
} else {
searchResultsDiv.innerHTML = customers.map(vip => `
<div class="vip-search-item" onclick="selectVIPCustomer(${vip.id})"
data-customer-id="${vip.id}">
<div class="customer-name">${highlightSearchTerm(vip.customer_name, searchTerm)}</div>
<div class="customer-phone">${highlightSearchTerm(vip.phone, searchTerm)}</div>
<div class="customer-car">${vip.car_model || '未知车型'} - ${vip.car_number || '未知车牌'}</div>
</div>
`).join('');
}
searchResultsDiv.style.display = 'block';
}
// 高亮搜索关键词
function highlightSearchTerm(text, searchTerm) {
if (!searchTerm) return text;
const regex = new RegExp(`(${searchTerm})`, 'gi');
return text.replace(regex, '<mark>$1</mark>');
}
// 清除搜索结果
function clearSearchResults() {
document.getElementById('vip_search_results').style.display = 'none';
document.getElementById('vip_id').style.display = 'block';
// 清除搜索输入
const searchInput = document.getElementById('vip_search');
if (searchInput && searchInput.value !== '') {
searchInput.value = '';
updateVIPSelect(allVIPCustomers);
}
}
// 选择VIP客户
function selectVIPCustomer(customerId) {
// 设置下拉选择值
document.getElementById('vip_id').value = customerId;
// 清除搜索状态
clearSearchResults();
// 加载VIP客户信息
loadVIPInfo();
}
// 检查手机号是否为VIP客户
function checkPhoneForVIP() {
const phoneInput = document.getElementById('phone');
const tipDiv = document.getElementById('phone_vip_tip');
const phone = phoneInput.value.trim();
// 清除提示
tipDiv.style.display = 'none';
tipDiv.className = 'phone-vip-tip';
// 如果手机号为空或过短,不进行检查
if (phone.length < 3) {
return;
}
// 在VIP客户中搜索匹配的手机号
const matchedVIP = allVIPCustomers.find(vip => vip.phone.includes(phone));
if (matchedVIP) {
// 显示VIP客户提示
tipDiv.innerHTML = `
<strong>👑 检测到VIP客户!</strong><br>
该手机号属于 VIP客户:${matchedVIP.customer_name}<br>
<button type="button" onclick="switchToVIPMode(${matchedVIP.id})" class="switch-to-vip-btn">
切换到VIP客户模式
</button>
`;
tipDiv.className = 'phone-vip-tip vip-detected';
tipDiv.style.display = 'block';
} else if (phone.length >= 8) {
// 显示建议提示(当手机号长度足够时)
tipDiv.innerHTML = `
💡 <strong>提示:</strong>未找到该手机号的VIP客户<br>
如果此客户是VIP客户,请检查手机号是否正确
`;
tipDiv.className = 'phone-vip-tip suggestion';
tipDiv.style.display = 'block';
}
}
// 切换到VIP模式
function switchToVIPMode(vipId = null) {
// 切换到VIP客户模式
document.getElementById('customer_type').value = 'vip';
handleCustomerTypeChange();
// 如果提供了VIP ID,选择该VIP客户
if (vipId) {
// 先等待VIP客户列表加载完成
setTimeout(() => {
document.getElementById('vip_id').value = vipId;
loadVIPInfo();
}, 500);
}
// 隐藏提示
document.getElementById('phone_vip_tip').style.display = 'none';
}
// 处理客户类型变更