feat(预约系统): 添加VIP客户搜索功能并优化用户体验
添加VIP客户搜索功能,支持姓名和手机号模糊搜索 增加手机号自动检测VIP功能并提供切换按钮 优化VIP客户选择界面样式和交互流程
This commit is contained in:
@@ -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';
|
||||
}
|
||||
|
||||
// 处理客户类型变更
|
||||
|
||||
Reference in New Issue
Block a user